6 ; https://forth-standard.org/standard/core/HOLDS
7 ; Adds the string represented by addr u to the pictured numeric output string
8 ; compilation use: <# S" string" HOLDS #>
9 ; free chars area in the 32+2 bytes HOLD buffer = {26,23,2} chars with a 32 bits sized {hexa,decimal,binary} number.
10 ; (2 supplementary bytes are room for sign - and decimal point)
11 ; perfect to display all a line on LCD 2x20 chars...
15 HOLDS1 ADD TOS,X ; 1 src
17 HOLDSLOOP SUB #1,X ; 1 src-1
23 HOLDSNEXT MOV Y,&HP ; 3
27 FORTHWORD "F+" ; -- d1lo d1hi d2lo d2hi
28 ADD @PSP+,2(PSP) ; -- sumlo d1hi d2hi
29 ADDC @PSP+,TOS ; -- sumlo sumhi
32 FORTHWORD "F-" ; -- d1lo d1hi d2lo d2hi
33 SUB @PSP+,2(PSP) ; -- diflo d1hi d2hi
34 SUBC TOS,0(PSP) ; -- diflo difhi d2hi
39 FORTHWORD "F/" ; s15.16 / s15.16 --> s15.16 result
41 XOR TOS,S ; MDhi XOR MRhi --> S keep sign of result
43 MOV 4(PSP),Y ; DVDlo --> DVDhi
44 MOV 2(PSP),X ; DVDhi --> REMlo
45 BIT #8000,X ; MD < 0 ?
58 ; unsigned 32-BIT DIVIDEND : 32-BIT DIVISOR --> 32-BIT QUOTIENT, 32-BIT REMAINDER
59 ; DVDhi|DVDlo : DVRhi|DVRlo --> QUOThi|QUOTlo, REMAINDER
61 ; MOV 4(PSP),T ; DVDlo
62 ; MOV 2(PSP),Y ; DVDhi
63 ; MOV #0,X ; REMlo = 0
64 Q6432 .word 1537h ; PUSHM R7,R4
67 MOV #32,R5 ; init loop count
68 Q321 CMP TOS,W ;1 REMhi <> DIVhi ?
70 CMP R6,X ;1 REMlo U< DIVlo ?
71 Q322 JLO Q323 ;2 yes: REM U< DIV
72 SUB R6,X ;1 no: REMlo - DIVlo (carry is set)
73 SUBC TOS,W ;1 REMhi - DIVhi
74 Q323 ADDC R7,R7 ;1 RLC quotLO
75 ADDC R4,R4 ;1 RLC quotHI
76 SUB #1,R5 ;1 Decrement loop counter
77 JN Q6432END ;2 loop back if count>=0
83 SUB R6,X ;1 REMlo - DIVlo
84 SUBC TOS,W ;1 REMhi - DIVhi
88 ; MOV X,4(PSP) ; REMlo
89 ; MOV W,2(PSP) ; REMhi
90 ADD #4,PSP ; skip REMlo REMhi
92 MOV R7,0(PSP) ; QUOTlo
94 .word 1734h ; POPM R4,R7
95 ; MOV @IP+,PC ; 33 words
97 FDIVSGN AND #-1,S ; clear V, set N
98 JGE FDIVEND ; if positive
105 .IFDEF MPY ; hardware multiplier
107 ; F#S Qlo Qhi -- Qhi 0 convert fractionnal part of Q15.16 fixed point number
109 FNUMS MOV @PSP,X ; -- Qlo Qhi X = Qlo
110 MOV TOS,0(PSP) ; -- Qhi Qhi
111 SUB #2,PSP ; -- Qhi x Qhi
112 MOV X,0(PSP) ; -- Qhi Qlo Qhi
113 MOV #4,T ; -- Qhi Qlo x T = limit for base 16
116 ADD #1,T ; T = limit for base 10
117 FNUMS2 MOV #0,S ; S = count
118 FNUMSLOOP MOV @PSP,&MPY ; Load 1st operand
119 MOV &BASE,&OP2 ; Load 2nd operand
120 MOV &RES0,0(PSP) ; -- Qhi Qlo' x low result on stack
121 MOV &RES1,TOS ; -- Qhi Qlo' digit high result in TOS
122 CMP #10,TOS ; digit to char
125 FNUMS2CHAR ADD #30h,TOS
126 MOV.B TOS,HOLDS_ORG(S) ; -- Qhi Qlo' char char to string
128 CMP T,S ;2 count=limit ?
129 JLO FNUMSLOOP ; loop back if U<
130 MOV T,TOS ; -- Qhi Qlo' limit
131 MOV #0,0(PSP) ; -- Qhi 0 limit
132 MOV #HOLDS_ORG,X ; -- Qhi 0 len X= org
135 FORTHWORD "F*" ; signed s15.16 multiplication --> s15.16 result
136 MOV 4(PSP),&MPYS32L ; 5 Load 1st operand
137 MOV 2(PSP),&MPYS32H ; 5
138 MOV @PSP,&OP2L ; 4 load 2nd operand
140 ADD #4,PSP ; 1 remove 2 cells
142 NOP2 ; 2 wait 8 cycles after write OP2L before reading RES1
147 .ELSE ; no hardware multiplier
149 ; F#S Qlo Qhi -- Qhi 0 convert fractionnal part of Q15.16 fixed point number
151 ; create a counted string at PAD+CPL+2
152 ; with digit high result of Qdlo * base
153 ; UMstar use S,T,W,X,Y
154 ; mov &BASE,S , jmp UMSTAR1 without hardware MPY
155 ; result: digit in tos (high) to convert in digit
157 FNUMS MOV @PSP,X ; -- Qlo Qhi X = Qlo
158 MOV TOS,0(PSP) ; -- Qhi Qhi
159 SUB #2,PSP ; -- Qhi x Qhi
160 MOV X,0(PSP) ; -- Qhi Qlo Qhi
161 MOV #4,TOS ; -- Qhi Qlo limit TOS = count for base 16
164 ADD #1,TOS ; TOS = limit for base 10
165 FNUMS2 .word 151Eh ; PUSHM TOS,IP TOS=limit IP count
166 MOV #FNUMSNEXT,IP ; -- Qhi Qlo limit
168 FNUMSLOOP PUSH S ; R-- limit IP count
169 MOV &BASE,TOS ; -- Qhi Qlo base
171 FNUMSNEXT FORTHtoASM ; -- Qhi QloRem digit
173 CMP #10,TOS ; digit to char
176 FNUMS2CHAR ADD #30h,TOS
177 MOV @RSP+,S ; R-- limit IP
178 MOV.B TOS,HOLDS_ORG(S) ; -- Qhi Qlorem char char to stringto string
180 CMP 2(RSP),S ;3 count=limit ?
182 .word 171Dh ; -- Qhi Qlorem limit POPM IP,TOS ;
183 MOV #0,0(PSP) ; -- Qhi 0 limit
184 MOV #HOLDS_ORG,X ; -- Qhi 0 len X= org
187 ; unsigned multiply 32*32 = 64
188 ; don't use S reg (keep sign)
191 .word 1537h ; 6 PUSHM R7,R4 save R7 ~ R4 regs
192 MOV 4(PSP),IP ; 3 MDlo
193 MOV 2(PSP),T ; 3 MDhi
197 MOV #0,4(PSP) ; 3 RESlo=0
198 MOV #0,2(PSP) ; 3 REShi=0
199 MOV #0,R6 ; 1 RESLO=0
200 MOV #0,R7 ; 1 RESHI=0
201 MOV #1,X ; 1 BIT TEST REGlo
202 MOV #0,Y ; 1 BIT TEST2 REGhi
205 BIT Y,TOS ; 1 TEST ACTUAL BIT MRhi
207 UDMT2 BIT X,W ; 1 TEST ACTUAL BIT MRlo
209 ADD IP,4(PSP) ; 3 IF 1: ADD MDlo TO RESlo
210 ADDC T,2(PSP) ; 3 ADDC MDhi TO REShi
211 ADDC R4,R6 ; 1 ADDC MDLO TO RESLO
212 ADDC R5,R7 ; 1 ADDC MDHI TO RESHI
213 UDMT4 ADD IP,IP ; 1 (RLA LSBs) MDlo *2
214 ADDC T,T ; 1 (RLC MSBs) MDhi *2
215 ADDC R4,R4 ; 1 (RLA LSBs) MDLO *2
216 ADDC R5,R5 ; 1 (RLC MSBs) MDHI *2
217 ADD X,X ; 1 (RLA) NEXT BIT TO TEST
218 ADDC Y,Y ; 1 (RLA) NEXT BIT TO TEST
219 JLO UDMT1 ; 2 IF BIT IN CARRY: FINISHED 32 * 16~ (average loop)
221 MOV R7,TOS ; 1 high result in TOS
222 .word 1734h ; 6 POPM R4,R7 restore R4 ~ R7 regs
227 FORTHWORD "F*" ; s15.16 * s15.16 --> s15.16 result
229 XOR TOS,S ; MDhi XOR MRhi --> S keep sign of result
230 BIT #8000,2(PSP) ; MD < 0 ?
238 FORTHtoASM ; -- RES0 RES1 RES2 RES3
240 MOV @PSP+,TOS ; -- RES0 RES1 RES2
241 MOV @PSP+,0(PSP) ; -- RES1 RES2
242 JMP FDIVSGN ; goto end of F/ to process sign of result
247 FORTHWORD "F." ; display a Q15.16 number
249 .word LESSNUM,DUP,TOR,DABBS
250 .word FNUMS,lit,',',HOLD,NUMS
251 .word RFROM,SIGN,NUMGREATER,TYPE,SPACE,EXIT
253 FORTHWORD "S>F" ; convert a signed number to a Q15.16 (signed) number
258 ; https://forth-standard.org/standard/core/TwoFetch
259 ; 2@ a-addr -- x1 x2 fetch 2 cells ; the lower address will appear on top of stack
268 ; https://forth-standard.org/standard/double/TwoCONSTANT
269 ; udlo/dlo/Flo udhi/dhi/Qhi -- create a double or a Q15.16 CONSTANT
270 FORTHWORD "2CONSTANT"
273 .word COMMA,COMMA ; compile udhi/dhi/Qhi then udlo/dlo/Qlo