2 ; -----------------------------------------------------
4 ; -----------------------------------------------------
6 \ to see kernel options, download FastForthSpecs.f
7 \ FastForth kernel options: MSP430ASSEMBLER, CONDCOMP, FIXPOINT_INPUT
10 \ MSP_EXP430FR5739 MSP_EXP430FR5969 MSP_EXP430FR5994 MSP_EXP430FR6989
11 \ MSP_EXP430FR2433 MSP_EXP430FR4133 MSP_EXP430FR2355 CHIPSTICK_FR2433
14 \ rDODOES to rEXIT must be saved before use and restored after
15 \ scratch registers Y to S are free for use
16 \ under interrupt, IP is free for use
18 \ PUSHM order : PSP,TOS, IP, S, T, W, X, Y, rEXIT,rDOVAR,rDOCON, rDODOES, R3, SR,RSP, PC
19 \ PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8, R7 , R6 , R5 , R4 , R3, R2, R1, R0
21 \ example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
23 \ POPM order : PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT, Y, X, W, T, S, IP,TOS,PSP
24 \ POPM order : R0, R1, R2, R3, R4 , R5 , R6 , R7 , R8, R9,R10,R11,R12,R13,R14,R15
26 \ example : POPM #6,IP pop Y,X,W,T,S,IP registers from return stack
28 \ FORTH conditionnals: unary{ 0= 0< 0> }, binary{ = < > U< }
30 \ ASSEMBLER conditionnal usage with IF UNTIL WHILE S< S>= U< U>= 0= 0<> 0>=
31 \ ASSEMBLER conditionnal usage with ?JMP ?GOTO S< S>= U< U>= 0= 0<> 0<
36 [DEFINED] {FIXPOINT} [IF] {FIXPOINT} [THEN] \ remove {FIXPOINT} if outside core
38 [UNDEFINED] {FIXPOINT} [IF] \ don't replicate {FIXPOINT} inside core
42 \ https://forth-standard.org/standard/core/HOLDS
43 \ Adds the string represented by addr u to the pictured numeric output string
44 \ compilation use: <# S" string" HOLDS #>
45 \ free chars area in the 32+2 bytes HOLD buffer = {26,23,2} chars with a 32 bits sized {hexa,decimal,binary} number.
46 \ (2 supplementary bytes are room for sign - and decimal point)
52 BEGIN SUB #1,X \ 1 src-1
54 U>= WHILE SUB #1,Y \ 1 dst-1
58 MOV @IP+,PC \ 4 15 words
61 CODE F+ \ add Q15.16 numbers
62 ADD @PSP+,2(PSP) \ -- sumlo d1hi d2hi
63 ADDC @PSP+,TOS \ -- sumlo sumhi
67 CODE F- \ substract Q15.16 numbers
68 SUB @PSP+,2(PSP) \ -- diflo d1hi d2hi
69 SUBC TOS,0(PSP) \ -- diflo difhi d2hi
74 $1A04 C@ $EF > [IF] ; test tag value MSP430FR413x subfamily without hardware_MPY
76 CODE F/ \ Q15.16 / Q15.16 --> Q15.16 result
79 MOV @PSP+,X \ DVDhi --> REMlo
81 MOV @PSP,Y \ DVDlo --> DVDhi
84 XOR TOS,S \ DVDhi XOR DVRhi --> S keep sign of result
86 S< IF XOR #-1,Y \ INV(DVDlo)
87 XOR #-1,X \ INV(DVDhi)
88 ADD #1,Y \ INV(DVDlo)+1
89 ADDC #0,X \ INV(DVDhi)+C
90 THEN AND #-1,TOS \ DVR < 0 ?
91 S< IF XOR #-1,R6 \ INV(DVRlo)
92 XOR #-1,TOS \ INV(DVRhi)
93 ADD #1,R6 \ INV(DVRlo)+1
94 ADDC #0,TOS \ INV(DVRhi)+C
96 \ don't uncomment lines below !
97 \ ------------------------------------------------------------------------
98 \ UD/MOD DVDlo DVDhi DVRlo DVRhi -- REMlo REMhi QUOTlo QUOThi
99 \ ------------------------------------------------------------------------
100 \ MOV 4(PSP),T \ DVDlo
101 \ MOV 2(PSP),Y \ DVDhi
102 \ MOV #0,X \ REMlo = 0
103 \ MOV #0,W \ REMhi = 0
104 MOV #32,R5 \ init loop count
105 BW1 CMP TOS,W \ 1 REMhi = DVRhi ?
106 0= IF CMP R6,X \ 1 REMlo U< DVRlo ?
108 U>= IF SUB R6,X \ 1 no: REMlo - DVRlo (carry is set)
109 SUBC TOS,W \ 1 REMhi - DVRhi
111 BW2 ADDC R7,R7 \ 1 RLC quotLO
112 ADDC R4,R4 \ 1 RLC quotHI
113 SUB #1,R5 \ 1 Decrement loop counter
114 0< ?GOTO FW1 \ 2 out of loop if count<0
115 ADD T,T \ 1 RLA DVDlo
116 ADDC Y,Y \ 1 RLC DVDhi
117 ADDC X,X \ 1 RLC REMlo
118 ADDC W,W \ 1 RLC REMhi
119 U< ?GOTO BW1 \ 2 15~ loop
120 SUB R6,X \ 1 REMlo - DVRlo
121 SUBC TOS,W \ 1 REMhi - DVRhi
123 GOTO BW2 \ 2 16~ loop
125 \ MOV X,4(PSP) \ REMlo
126 \ MOV W,2(PSP) \ REMhi
127 \ ADD #4,PSP \ skip REMlo REMhi
128 MOV R7,0(PSP) \ QUOTlo
130 POPM #4,R7 \ restore R4 to R7
131 \ MOV @IP+,PC \ end of UD/MOD
132 \ ------------------------------------------------------------------------
133 BW1 AND #-1,S \ clear V, set N; QUOT < 0 ?
134 S< IF XOR #-1,0(PSP) \ INV(QUOTlo)
135 XOR #-1,TOS \ INV(QUOThi)
136 ADD #1,0(PSP) \ INV(QUOTlo)+1
137 ADDC #0,TOS \ INV(QUOThi)+C
141 \ F#S Qlo Qhi u -- Qhi 0 convert fractional part Qlo of Q15.16 fixed point number
144 MOV 2(PSP),X \ -- Qlo Qhi u X = Qlo
145 MOV @PSP,2(PSP) \ -- Qhi Qhi u
146 MOV X,0(PSP) \ -- Qhi Qlo u
147 PUSHM #2,TOS \ save TOS,IP
148 MOV #0,S \ -- Qhi Qlo x
149 BEGIN PUSH S \ R-- limit IP count
150 MOV &BASE,TOS \ -- Qhi Qlo base
152 UM* \ u1 u2 -- RESlo REShi
153 HI2LO \ -- Qhi RESlo digit
155 CMP #10,TOS \ digit to char
158 MOV @RSP+,S \ R-- limit IP
159 MOV.B TOS,HOLDS_ORG(S) \ -- Qhi RESlo char char to string
161 CMP 2(RSP),S \ count=limit ?
163 POPM #2,TOS \ restore IP,TOS
164 MOV #0,0(PSP) \ -- Qhi 0 len
165 SUB #2,PSP \ -- Qhi 0 x len
166 MOV #HOLDS_ORG,0(PSP) \ -- Qhi 0 addr len
170 \ unsigned multiply 32*32 = 64
171 \ don't use S reg (keep sign)
174 PUSHM #4,R7 \ 6 save R7 ~ R4 regs
175 MOV 4(PSP),IP \ 3 MDlo
176 MOV 2(PSP),T \ 3 MDhi
180 MOV #0,4(PSP) \ 3 RESlo=0
181 MOV #0,2(PSP) \ 3 REShi=0
182 MOV #0,R6 \ 1 RESLO=0
183 MOV #0,R7 \ 1 RESHI=0
184 MOV #1,X \ 1 BIT TEST REGlo
185 MOV #0,Y \ 1 BIT TEST2 REGhi
187 0<> IF BIT X,W \ 2+1 TEST ACTUAL BIT MRlo
188 ELSE BIT Y,TOS \ 2+1 TEST ACTUAL BIT MRhi
190 0<> IF ADD IP,4(PSP) \ 2+3 IF 1: ADD MDlo TO RESlo
191 ADDC T,2(PSP) \ 3 ADDC MDhi TO REShi
192 ADDC R4,R6 \ 1 ADDC MDLO TO RESLO
193 ADDC R5,R7 \ 1 ADDC MDHI TO RESHI
194 THEN ADD IP,IP \ 1 (RLA LSBs) MDlo *2
195 ADDC T,T \ 1 (RLC MSBs) MDhi *2
196 ADDC R4,R4 \ 1 (RLA LSBs) MDLO *2
197 ADDC R5,R5 \ 1 (RLC MSBs) MDHI *2
198 ADD X,X \ 1 (RLA) NEXT BIT TO TEST
199 ADDC Y,Y \ 1 (RLA) NEXT BIT TO TEST
200 U>= UNTIL MOV R6,0(PSP) \ 2+2 IF BIT IN CARRY: FINISHED 32 * 16~ (average loop)
201 MOV R7,TOS \ 1 high result in TOS
202 POPM #4,R7 \ 6 restore R4 to R7
207 CODE F* \ s15.16 * s15.16 --> s15.16 result
209 XOR TOS,S \ 1s15 XOR 2s15 --> S keep sign of result
210 BIT #$8000,2(PSP) \ MD < 0 ?
211 0<> IF XOR #-1,2(PSP)
217 DABS UDM* \ -- RES0 RES1 RES2 RES3
220 MOV @PSP+,TOS \ -- RES0 RES1 RES2
221 MOV @PSP+,0(PSP) \ -- RES1 RES2
222 GOTO BW1 \ goto end of F/ to process sign of result
225 [ELSE] \ hardware multiplier
227 CODE F/ \ Q15.16 / Q15.16 --> Q15.16 result
232 PUSHM #4,R7 \ 6 PUSHM R7 to R4
233 MOV @PSP+,R6 \ 2 DVRlo
234 MOV @PSP+,X \ 2 DVDhi --> REMlo
235 MOV #0,W \ 1 REMhi = 0
236 MOV @PSP,Y \ 2 DVDlo --> DVDhi
237 MOV #0,T \ 1 DVDlo = 0
239 XOR TOS,S \ 1 DVDhi XOR DVRhi --> S keep sign of result
240 AND #-1,X \ 1 DVD < 0 ?
241 S< IF XOR #-1,Y \ 1 INV(DVDlo)
242 XOR #-1,X \ 1 INV(DVDhi)
243 ADD #1,Y \ 1 INV(DVDlo)+1
244 ADDC #0,X \ 1 INV(DVDhi)+C
245 THEN AND #-1,TOS \ 1 DVR < 0 ?
246 S< IF XOR #-1,R6 \ 1 INV(DVRlo)
247 XOR #-1,TOS \ 1 INV(DVRhi)
248 ADD #1,R6 \ 1 INV(DVRlo)+1
249 ADDC #0,TOS \ 1 INV(DVRhi)+C
250 THEN MOV #32,R5 \ 2 init loop count
251 BW1 CMP TOS,W \ 1 REMhi = DVRhi ?
253 CMP R6,X \ 1 REMlo U< DVRlo ?
256 SUB R6,X \ 1 no: REMlo - DVRlo (carry is set)
257 SUBC TOS,W \ 1 REMhi - DVRhi
259 BW2 ADDC R7,R7 \ 1 RLC quotLO
260 ADDC R4,R4 \ 1 RLC quotHI
261 SUB #1,R5 \ 1 Decrement loop counter
262 0< ?GOTO FW1 \ 2 out of loop if count<0
263 ADD T,T \ 1 RLA DVDlo
264 ADDC Y,Y \ 1 RLC DVDhi
265 ADDC X,X \ 1 RLC REMlo
266 ADDC W,W \ 1 RLC REMhi
267 U< ?GOTO BW1 \ 2 19~ loop
268 SUB R6,X \ 1 REMlo - DVRlo
269 SUBC TOS,W \ 1 REMhi - DVRhi
271 GOTO BW2 \ 2 16~ loop
272 FW1 AND #-1,S \ 1 clear V, set N; QUOT < 0 ?
273 S< IF XOR #-1,R7 \ 1 INV(QUOTlo)
274 XOR #-1,R4 \ 1 INV(QUOThi)
275 ADD #1,R7 \ 1 INV(QUOTlo)+1
276 ADDC #0,R4 \ 1 INV(QUOThi)+C
277 THEN MOV R7,0(PSP) \ 3 QUOTlo
278 MOV R4,TOS \ 1 QUOThi
279 POPM #4,R7 \ 6 restore R4 to R7
283 \ F#S Qlo Qhi u -- Qhi 0 convert fractionnal part of Q15.16 fixed point number
286 MOV 2(PSP),X \ -- Qlo Qhi u X = Qlo
287 MOV @PSP,2(PSP) \ -- Qhi Qhi u
288 MOV X,0(PSP) \ -- Qhi Qlo u
289 MOV TOS,T \ T = limit
291 BEGIN MOV @PSP,&MPY \ Load 1st operand
292 MOV &BASE,&OP2 \ Load 2nd operand
293 MOV &RES0,0(PSP) \ -- Qhi RESlo x low result on stack
294 MOV &RES1,TOS \ -- Qhi RESlo REShi high result in TOS
295 CMP #10,TOS \ digit to char
298 MOV.B TOS,HOLDS_ORG(S) \ -- Qhi RESlo char char to string
300 CMP T,S \ count=limit ?
301 0= UNTIL MOV #0,0(PSP) \ -- Qhi 0 REShi
302 MOV T,TOS \ -- Qhi 0 limit
303 SUB #2,PSP \ -- Qhi 0 x len
304 MOV #HOLDS_ORG,0(PSP) \ -- Qhi 0 addr len
308 CODE F* \ signed s15.16 multiplication --> s15.16 result
309 MOV 4(PSP),&MPYS32L \ 5 Load 1st operand
310 MOV 2(PSP),&MPYS32H \ 5
311 MOV @PSP,&OP2L \ 4 load 2nd operand
313 ADD #4,PSP \ 1 remove 2 cells
315 \ NOP2 \ 2 wait 8 cycles after write OP2L before reading RES1
321 [THEN] \ hardware multiplier
323 CODE F. \ display a Q15.16 number with 4/5/16 digits after comma
325 MOV #4,T \ T = 4 preset 4 digits for base 16 and by default
329 ADD #1,T \ T = 5 set 5 digits
333 MOV #16,T \ T = 16 set 16 digits
336 PUSHM #3,IP \ R-- IP sign #digit
338 <# DABS \ -- uQlo uQhi R-- IP sign #digit
339 R> F#S \ -- uQhi 0 R-- IP sign
340 $2C HOLD \ $2C = char ','
342 R> SIGN #> \ -- addr len R-- IP
346 CODE S>F \ convert a signed number to a Q15.16 (signed) number
354 \ https://forth-standard.org/standard/core/TwoFetch
355 \ 2@ a-addr -- x1 x2 fetch 2 cells ; the lower address will appear on top of stack
362 [THEN] \ of [UNDEFINED] 2@
364 [UNDEFINED] 2CONSTANT [IF]
366 \ https://forth-standard.org/standard/double/TwoCONSTANT
367 : 2CONSTANT \ udlo/dlo/Qlo udhi/dhi/Qhi -- to create double or Q15.16 CONSTANT
368 CREATE , , \ compile Qhi then Qlo
369 DOES> 2@ \ execution part addr -- Qhi Qlo
372 [THEN] \ of [UNDEFINED] 2CONSTANT
375 [THEN] \ of [UNDEFINED] {FIXPOINT}
379 ; -----------------------
381 ; -----------------------
385 PI -1,0 F* 2CONSTANT -PI
404 32767,99999 1,0 f* F.
405 32767,99999 1,0 f/ F.
406 32767,99999 2,0 f/ F.
407 32767,99999 4,0 f/ F.
408 32767,99999 8,0 f/ F.
409 32767,99999 16,0 f/ F.
420 ; sqrt(32768)^2 = 32768
421 181,01933598375 181,01933598375 f* f.
422 181,01933598375 -181,01933598375 f* f.
423 -181,01933598375 181,01933598375 f* f.
424 -181,01933598375 -181,01933598375 f* f.