1 ; -*- coding: utf-8 -*-
2 ; http://patorjk.com/software/taag/#p=display&f=Banner&t=Fast Forth
4 ; Fast Forth For Texas Instrument MSP430FRxxxx FRAM devices
5 ; Copyright (C) <2015> <J.M. THOORENS>
7 ; This program is free software: you can redistribute it and/or modify
8 ; it under the terms of the GNU General Public License as published by
9 ; the Free Software Foundation, either version 3 of the License, or
10 ; (at your option) any later version.
12 ; This program is distributed in the hope that it will be useful,
13 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ; GNU General Public License for more details.
17 ; You should have received a copy of the GNU General Public License
18 ; along with this program. If not, see <http://www.gnu.org/licenses/>.
22 FORTHWORD "{FIXPOINT}"
25 ; https://forth-standard.org/standard/core/HOLDS
26 ; Adds the string represented by addr u to the pictured numeric output string
27 ; compilation use: <# S" string" HOLDS #>
28 ; free chars area in the 32+2 bytes HOLD buffer = {26,23,2} chars with a 32 bits sized {hexa,decimal,binary} number.
29 ; (2 supplementary bytes are room for sign - and decimal point)
30 ; perfect to display all a line on LCD 2x20 chars...
34 HOLDS1 ADD TOS,X ; 1 src
36 HOLDSLOOP SUB #1,X ; 1 src-1
42 HOLDSNEXT MOV Y,&HP ; 3
46 FORTHWORD "F+" ; -- d1lo d1hi d2lo d2hi
47 ADD @PSP+,2(PSP) ; -- sumlo d1hi d2hi
48 ADDC @PSP+,TOS ; -- sumlo sumhi
51 FORTHWORD "F-" ; -- d1lo d1hi d2lo d2hi
52 SUB @PSP+,2(PSP) ; -- diflo d1hi d2hi
53 SUBC TOS,0(PSP) ; -- diflo difhi d2hi
57 .IFDEF MPY ; hardware multiplier
59 FORTHWORD "F/" ; s15.16 / s15.16 --> s15.16 result
61 PUSHM #4,R7 ; PUSHM R7,R4
63 MOV @PSP+,X ; DVDhi --> REMlo
65 MOV @PSP,Y ; DVDlo --> DVDhi
68 XOR TOS,S ; MDhi XOR MRhi --> S keep sign of result
82 ; unsigned 32-BIT DIVIDEND : 32-BIT DIVISOR --> 32-BIT QUOTIENT, 32-BIT REMAINDER
83 ; DVDhi|DVDlo : DVRhi|DVRlo --> QUOThi|QUOTlo, REMAINDER
85 ; MOV 4(PSP),T ; DVDlo
86 ; MOV 2(PSP),Y ; DVDhi
87 ; MOV #0,X ; REMlo = 0
88 Q6432 MOV #32,R5 ; init loop count
89 Q321 CMP TOS,W ;1 REMhi <> DIVhi ?
91 CMP R6,X ;1 REMlo U< DIVlo ?
92 Q322 JLO Q323 ;2 yes: REM U< DIV
93 SUB R6,X ;1 no: REMlo - DIVlo (carry is set)
94 SUBC TOS,W ;1 REMhi - DIVhi
95 Q323 ADDC R7,R7 ;1 RLC quotLO
96 ADDC R4,R4 ;1 RLC quotHI
97 SUB #1,R5 ;1 Decrement loop counter
98 JN Q6432END ;2 loop back if count>=0
100 ADDC Y,Y ;1 RLC DVDhi
101 ADDC X,X ;1 RLC REMlo
102 ADDC W,W ;1 RLC REMhi
104 SUB R6,X ;1 REMlo - DIVlo
105 SUBC TOS,W ;1 REMhi - DIVhi
109 ; MOV X,4(PSP) ; REMlo
110 ; MOV W,2(PSP) ; REMhi
111 ; MOV @IP+,PC ; 33 words
112 AND #-1,S ; clear V, set N
113 JGE FDIVEND ; if positive
118 FDIVEND MOV R7,0(PSP) ; QUOTlo
120 POPM #4,R7 ; POPM R4 R5 R6 R7
123 ; F#S Qlo Qhi u -- Qhi 0 convert fractionnal part of Q15.16 fixed point number
127 MOV 2(PSP),X ; -- Qlo Qhi u X = Qlo
128 MOV @PSP,2(PSP) ; -- Qhi Qhi u
129 MOV X,0(PSP) ; -- Qhi Qlo u
130 MOV TOS,T ; T = limit
132 FNUMSLOOP MOV @PSP,&MPY ; Load 1st operand
133 MOV &BASE,&OP2 ; Load 2nd operand
134 MOV &RES0,0(PSP) ; -- Qhi Qlo' x low result on stack
135 MOV &RES1,TOS ; -- Qhi Qlo' digit high result in TOS
136 CMP #10,TOS ; digit to char
139 FNUMS2CHAR ADD #30h,TOS
140 MOV.B TOS,HOLDS_ORG(S) ; -- Qhi Qlo' char char to string
142 CMP T,S ;2 count=limit ?
143 JLO FNUMSLOOP ; loop back if U<
144 MOV T,TOS ; -- Qhi Qlo' limit
145 MOV #0,0(PSP) ; -- Qhi 0 limit
146 MOV #HOLDS_ORG,X ; -- Qhi 0 len X= org
149 FORTHWORD "F*" ; signed s15.16 multiplication --> s15.16 result
150 MOV 4(PSP),&MPYS32L ; 5 Load 1st operand
151 MOV 2(PSP),&MPYS32H ; 5
152 MOV @PSP,&OP2L ; 4 load 2nd operand
154 ADD #4,PSP ; 1 remove 2 cells
156 NOP2 ; 2 wait 8 cycles after write OP2L before reading RES1
161 .ELSE ; no hardware multiplier
163 FORTHWORD "F/" ; s15.16 / s15.16 --> s15.16 result
165 PUSHM #4,R7 ; PUSHM R7,R4
167 MOV @PSP+,X ; DVDhi --> REMlo
169 MOV @PSP,Y ; DVDlo --> DVDhi
172 XOR TOS,S ; MDhi XOR MRhi --> S keep sign of result
186 ; unsigned 32-BIT DIVIDEND : 32-BIT DIVISOR --> 32-BIT QUOTIENT, 32-BIT REMAINDER
187 ; DVDhi|DVDlo : DVRhi|DVRlo --> QUOThi|QUOTlo, REMAINDER
189 ; MOV 4(PSP),T ; DVDlo
190 ; MOV 2(PSP),Y ; DVDhi
191 ; MOV #0,X ; REMlo = 0
192 Q6432 MOV #32,R5 ; init loop count
193 Q321 CMP TOS,W ;1 REMhi <> DIVhi ?
195 CMP R6,X ;1 REMlo U< DIVlo ?
196 Q322 JLO Q323 ;2 yes: REM U< DIV
197 SUB R6,X ;1 no: REMlo - DIVlo (carry is set)
198 SUBC TOS,W ;1 REMhi - DIVhi
199 Q323 ADDC R7,R7 ;1 RLC quotLO
200 ADDC R4,R4 ;1 RLC quotHI
201 SUB #1,R5 ;1 Decrement loop counter
202 JN Q6432END ;2 loop back if count>=0
204 ADDC Y,Y ;1 RLC DVDhi
205 ADDC X,X ;1 RLC REMlo
206 ADDC W,W ;1 RLC REMhi
208 SUB R6,X ;1 REMlo - DIVlo
209 SUBC TOS,W ;1 REMhi - DIVhi
213 ; MOV X,4(PSP) ; REMlo
214 ; MOV W,2(PSP) ; REMhi
215 ; ADD #4,PSP ; skip REMlo REMhi
217 MOV R7,0(PSP) ; QUOTlo
219 POPM #4,R7 ; POPM R4 R5 R6 R7
220 ; MOV @IP+,PC ; 33 words
222 FDIVSGN AND #-1,S ; clear V, set N
223 JGE FDIVEND ; if positive
230 ; F#S Qlo Qhi u -- Qhi 0 convert fractionnal part of Q15.16 fixed point number
233 ; create a counted string at PAD+CPL+2
234 ; with digit high result of Qdlo * base
235 ; UMstar use S,T,W,X,Y
236 ; mov &BASE,S , jmp UMSTAR1 without hardware MPY
237 ; result: digit in tos (high) to convert in digit
240 MOV 2(PSP),X ; -- Qlo Qhi u X = Qlo
241 MOV @PSP,2(PSP) ; -- Qhi Qhi u
242 MOV X,0(PSP) ; -- Qhi Qlo u
243 PUSHM #2,TOS ; PUSHM TOS,IP TOS=limit IP
245 MOV #FNUMSNEXT,IP ; -- Qhi Qlo limit
246 FNUMSLOOP PUSH S ; R-- limit IP count
247 MOV &BASE,TOS ; -- Qhi Qlo base
249 FNUMSNEXT FORTHtoASM ; -- Qhi QloRem digit
251 CMP #10,TOS ; digit to char
254 FNUMS2CHAR ADD #30h,TOS
255 MOV @RSP+,S ; R-- limit IP
256 MOV.B TOS,HOLDS_ORG(S) ; -- Qhi Qlorem char char to stringto string
258 CMP 2(RSP),S ;3 count=limit ?
260 POPM #2,TOS ; -- Qhi Qlorem limit POPM IP,TOS
261 MOV #0,0(PSP) ; -- Qhi 0 limit
262 MOV #HOLDS_ORG,X ; -- Qhi 0 len X= org
265 ; unsigned multiply 32*32 = 64
266 ; don't use S reg (keep sign)
269 PUSHM #4,R7 ; 6 PUSHM R7,R4 save R7 ~ R4 regs
270 MOV 4(PSP),IP ; 3 MDlo
271 MOV 2(PSP),T ; 3 MDhi
275 MOV #0,4(PSP) ; 3 RESlo=0
276 MOV #0,2(PSP) ; 3 REShi=0
277 MOV #0,R6 ; 1 RESLO=0
278 MOV #0,R7 ; 1 RESHI=0
279 MOV #1,X ; 1 BIT TEST REGlo
280 MOV #0,Y ; 1 BIT TEST2 REGhi
283 BIT Y,TOS ; 1 TEST ACTUAL BIT MRhi
285 UDMT2 BIT X,W ; 1 TEST ACTUAL BIT MRlo
287 ADD IP,4(PSP) ; 3 IF 1: ADD MDlo TO RESlo
288 ADDC T,2(PSP) ; 3 ADDC MDhi TO REShi
289 ADDC R4,R6 ; 1 ADDC MDLO TO RESLO
290 ADDC R5,R7 ; 1 ADDC MDHI TO RESHI
291 UDMT4 ADD IP,IP ; 1 (RLA LSBs) MDlo *2
292 ADDC T,T ; 1 (RLC MSBs) MDhi *2
293 ADDC R4,R4 ; 1 (RLA LSBs) MDLO *2
294 ADDC R5,R5 ; 1 (RLC MSBs) MDHI *2
295 ADD X,X ; 1 (RLA) NEXT BIT TO TEST
296 ADDC Y,Y ; 1 (RLA) NEXT BIT TO TEST
297 JLO UDMT1 ; 2 IF BIT IN CARRY: FINISHED 32 * 16~ (average loop)
299 MOV R7,TOS ; 1 high result in TOS
300 POPM #4,R7 ; 6 POPM R4 R5 R6 R7
305 FORTHWORD "F*" ; s15.16 * s15.16 --> s15.16 result
307 XOR TOS,S ; MDhi XOR MRhi --> S keep sign of result
308 BIT #8000,2(PSP) ; MD < 0 ?
316 FORTHtoASM ; -- RES0 RES1 RES2 RES3
318 MOV @PSP+,TOS ; -- RES0 RES1 RES2
319 MOV @PSP+,0(PSP) ; -- RES1 RES2
320 JMP FDIVSGN ; goto end of F/ to process sign of result
325 FORTHWORD "F." ; display a Q15.16 number with 4 digits after comma
327 .word LESSNUM,DUP,TOR,DABBS
328 .word lit,4,FNUMS,lit,',',HOLD,NUMS
329 .word RFROM,SIGN,NUMGREATER,TYPE,SPACE,EXIT
331 FORTHWORD "S>F" ; convert a signed number to a Q15.16 (signed) number
336 ; https://forth-standard.org/standard/core/TwoFetch
337 ; 2@ a-addr -- x1 x2 fetch 2 cells ; the lower address will appear on top of stack
346 ; https://forth-standard.org/standard/double/TwoCONSTANT
347 ; udlo/dlo/Flo udhi/dhi/Qhi -- create a double or a Q15.16 CONSTANT
348 FORTHWORD "2CONSTANT"
351 .word COMMA,COMMA ; compile udhi/dhi/Qhi then udlo/dlo/Qlo