
macro Print1 Str:s,Reg:r
{
   STMFD    R13!,{R0,R14}
   SWI      OS_WriteS
   DCB      Str,0
   ALIGN
   MOV      R0,Reg
   BL       Print_Number
   LDMFD    R13!,{R0,R14}
}

macro Print2 Str:s,Reg1:r,Reg2:r
{
   STMFD    R13!,{R0,R14}
   SWI      OS_WriteS
   DCB      Str,0
   ALIGN
   MOV      R0,Reg1
   BL       Print_Number
   LDMFD    R13,{R0,R14}
   MOV      R0,Reg2
   BL       Print_Number
   LDMFD    R13!,{R0,R14}
}

macro Print3 Str:s,Reg1:r,Reg2:r,Reg3:r
{
   STMFD    R13!,{R0,R14}
   SWI      OS_WriteS
   DCB      Str,0
   ALIGN
   MOV      R0,Reg1
   BL       Print_Number
   LDMFD    R13,{R0,R14}
   MOV      R0,Reg2
   BL       Print_Number
   LDMFD    R13,{R0,R14}
   MOV      R0,Reg3
   BL       Print_Number
   LDMFD    R13!,{R0,R14}
}

macro PrintFP FPReg:f
{
   STMFD    R13!,{R14}
   SFMFD    F0,1,[R13]!
   MVFS     F0,FPReg
   BL       Print_FP_Number
   LFMFD    F0,1,[R13]!
   LDMFD    R13!,{R14}
}

macro Print Str:s
{
   STMFD    R13!,{R14}
   SWI      OS_WriteS
   DCB      Str,0
   ALIGN
   LDMFD    R13!,{R14}
}

macro PrintCC$cc Str:s
{
#set ncc=cc EOR 1
   B$ncc    _Not_CC
   STMFD    R13!,{R14}
   MOV      R14,R15
   SWI      OS_WriteS
   DCB      Str,0
   ALIGN
   TEQP     R14,#0
   LDMFD    R13!,{R14}
   ._Not_CC
}

macro PrintStr Str:s,Reg:r
{
   STMFD    R13!,{R0,R14}
   SWI      OS_WriteS
   DCB      Str,0
   ALIGN
   MOV      R0,Reg
   SWI      OS_Write0
   LDMFD    R13!,{R0,R14}
}

macro PrintChar Str:s,Reg:r
{
   STMFD    R13!,{R0,R14}
   SWI      OS_WriteS
   DCB      Str,0
   ALIGN
   MOV      R0,Reg
   CMP      R0,#' '
   MOVLT    R0,#'.'
   SWI      OS_WriteC
   SWI      OS_WriteI+' '
   SWI      OS_WriteI+'('
   LDMFD    R13,{R0,R14}
   MOV      R0,Reg
   BL       Print_Number
   SWI      OS_WriteI+')'
   LDMFD    R13!,{R0,R14}
}

macro PrintHex Str:s,Reg:r
{
   STMFD    R13!,{R0,R14}
   SWI      OS_WriteS
   DCB      Str,0
   ALIGN
   MOV      R0,Reg
   BL       Print_HexNumber
   LDMFD    R13!,{R0,R14}
}

macro PrintHex2 Str:s,Reg1:r,Reg2:r
{
   STMFD    R13!,{R0,R14}
   SWI      OS_WriteS
   DCB      Str,0
   ALIGN
   MOV      R0,Reg1
   BL       Print_HexNumber
   LDMFD    R13,{R0,R14}
   MOV      R0,Reg2
   BL       Print_HexNumber
   LDMFD    R13!,{R0,R14}
}

macro PrintHex3 Str:s,Reg1:r,Reg2:r,Reg3:r
{
   STMFD    R13!,{R0,R14}
   SWI      OS_WriteS
   DCB      Str,0
   ALIGN
   LDMFD    R13,{R0,R14}
   MOV      R0,Reg1
   BL       Print_HexNumber
   LDMFD    R13,{R0,R14}
   MOV      R0,Reg2
   BL       Print_HexNumber
   LDMFD    R13,{R0,R14}
   MOV      R0,Reg3
   BL       Print_HexNumber
   LDMFD    R13!,{R0,R14}
}

macro Home
{
   SWI      OS_WriteS
   DCB      4,30,10,0
}

macro NL
{
   SWI      OS_NewLine
}

macro Get
{
   STMFD    R13!,{R0-R3}
   MOV      R0,#15
   MOV      R1,#1
   SWI      OS_Byte
   SWI      OS_ReadC
   LDMFD    R13!,{R0-R3}
}

; >-------------------------------------------------------------<

.Print_Number
   STMFD    R13!,{R0-R2,R14}
   ADR      R1,Number_Buffer
   MOV      R2,#20
   SWI      OS_ConvertInteger4         ; Convert number to text
   MOV      R2,R0
   ADR      R0,Space
   SUB      R1,R1,R2
   RSBS     R1,R1,#Field               ; Number of space=field-number of digits
   MOVMI    R1,#0
   SWI      OS_WriteN                  ; Right justify the number
   MOV      R0,R2
   SWI      OS_Write0                  ; Print the number
   LDMFD    R13!,{R0-R2,R15}

; >-------------------------------------------------------------<

.Print_HexNumber
   STMFD    R13!,{R0-R2,R14}
   ADR      R1,Number_Buffer
   MOV      R2,#20
   SWI      OS_ConvertHex8             ; Convert the number to text
   MOV      R2,R0
   ADR      R0,Space
   SUB      R1,R1,R2
   RSBS     R1,R1,#Field               ; Number of space=field-number of digits
   MOVMI    R1,#0
   SWI      OS_WriteN                  ; Right justify the number
   MOV      R0,R2
   SWI      OS_Write0                  ; Print the number
   LDMFD    R13!,{R0-R2,R15}

.Number_Buffer   DBB   16
.Space           DBB   16,32

; >-------------------------------------------------------------<

   ; R0 -      last non-zero digit pointer
   ; R1 -      data
   ; R2 -      string pointer
   ; R3 -      data
   ; R4 -      BCD number to be printed
   ; R5 -      start bit
   ; R6 -      end bit
   ; R7 - R9 - number to print
   ;
.Print_FP_Number                      ;_F0 = FP number
   STMFD    R13!,{R0-R9,R14}
   ADR      R2,FP_Number_Buffer
   ADR      R1,FP_Number
   STFP     F0,[R1]                    ; Store the number in BCD format (3 words)
   LDMIA    R1,{R7-R9}                 ; Read words
   TST      R7,#1 << 31                ; Is the number negative?
   MOVNE    R1,#'-'
   STRNEB   R1,[R2],#1
   MOV      R3,#&F
   ANDS     R1,R3,R7,LSR #8            ; digit=&F AND number >> counter
   ADD      R1,R1,#'0'                 ; Make digit an ASCII digit
   STRB     R1,[R2],#1
   MOV      R0,R2
   MOV      R1,#'.'
   STRB     R1,[R2],#1
   MOV      R4,R7
   MOV      R5,#4
   MOV      R6,#0
   BL       WriteBCD                   ; Write the number digits in word 1 (d18-d16)
   MOV      R4,R8
   MOV      R5,#28
   BL       WriteBCD                   ; Write the number digits in word 2 (d15-d8)
   MOV      R4,R9
   MOV      R5,#28
   BL       WriteBCD                   ; Write the number digits in word 3 (d7-d0)
   MOV      R2,R0
   ANDS     R6,R7,#&FFFF000            ; Is the exponent zero?
   MOV      R1,#0
   STRB     R1,[R2]
   BNE      PFPN_Not_Zero
   ADR      R0,FP_Number_Buffer
   SWI      OS_Write0
   LDMFD    R13!,{R0-R9,R15}           ; Return

.PFPN_Not_Zero
   MOV      R1,#'E'
   STRB     R1,[R2],#1
   TST      R7,#1 << 30                ; Is the exponent negative?
   MOVNE    R1,#'-'
   STRNEB   R1,[R2],#1
   MOV      R4,R7
   MOV      R5,#24
   MOV      R6,#12
   BL       WriteBCD                   ; Write the exponent digits in word 1 (e0-e3)
   MOV      R1,#0
   STRB     R1,[R2]
   ADR      R0,FP_Number_Buffer
   SWI      OS_Write0
   LDMFD    R13!,{R0-R9,R15}

.WriteBCD
   MOV      R3,#&F

.Digit_Loop
   ANDS     R1,R3,R4,LSR R5            ; digit=&F AND number >> counter
   ADD      R1,R1,#'0'                 ; Make digit an ASCII digit
   STRB     R1,[R2],#1
   MOVNE    R0,R2
   SUB      R5,R5,#4                   ; counter=counter-4 (go to next digit)
   CMP      R5,R6                      ; counter<=end bit?
   BGE      Digit_Loop
   MOV      R15,R14

.FP_Number        DBD 3
.FP_Number_Buffer DBB 24
