1 \ -*- coding: utf-8 -*-
3 ; -----------------------------------------------------
5 ; -----------------------------------------------------
7 \ to see kernel options, download FastForthSpecs.f
8 \ FastForth kernel options: MSP430ASSEMBLER, CONDCOMP, FIXPOINT_INPUT
11 \ MSP_EXP430FR5739 MSP_EXP430FR5969 MSP_EXP430FR5994 MSP_EXP430FR6989
12 \ MSP_EXP430FR2433 MSP_EXP430FR4133 MSP_EXP430FR2355 CHIPSTICK_FR2433
15 \ rDODOES to rEXIT must be saved before use and restored after
16 \ scratch registers Y to S are free for use
17 \ under interrupt, IP is free for use
19 \ PUSHM order : PSP,TOS, IP, S, T, W, X, Y, rEXIT,rDOVAR,rDOCON, rDODOES, R3, SR,RSP, PC
20 \ PUSHM order : PSP,TOS,IP,S,T,W, X, Y, rDOCOL , rDOVAR , rDOCON , rDODOES , R3, SR, RSP, PC
22 \ example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
24 \ POPM order : PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT, Y, X, W, T, S, IP,TOS,PSP
25 \ POPM order : PC, RSP, SR, R3, rDODOES , rDOCON , rDOVAR , rDOCOL , Y, X,W,T,S,IP,TOS,PSP
27 \ example : POPM #6,IP pop Y,X,W,T,S,IP registers from return stack
29 \ FORTH conditionnals: unary{ 0= 0< 0> }, binary{ = < > U< }
31 \ ASSEMBLER conditionnal usage with IF UNTIL WHILE S< S>= U< U>= 0= 0<> 0>=
32 \ ASSEMBLER conditionnal usage with ?JMP ?GOTO S< S>= U< U>= 0= 0<> 0<
35 : DEFINED! ECHO 1 ABORT" already loaded!" ;
37 [DEFINED] {FIXPOINT} [IF] DEFINED!
47 [UNDEFINED] HOLDS [IF]
48 \ https://forth-standard.org/standard/core/HOLDS
49 \ Adds the string represented by addr u to the pictured numeric output string
50 \ compilation use: <# S" string" HOLDS #>
51 \ free chars area in the 32+2 bytes HOLD buffer = {26,23,2} chars with a 32 bits sized {hexa,decimal,binary} number.
52 \ (2 supplementary bytes are room for sign - and decimal point)
58 BEGIN SUB #1,X \ 1 src-1
60 U>= WHILE SUB #1,Y \ 1 dst-1
64 MOV @IP+,PC \ 4 15 words
68 CODE F+ \ add Q15.16 numbers
69 ADD @PSP+,2(PSP) \ -- sumlo d1hi d2hi
70 ADDC @PSP+,TOS \ -- sumlo sumhi
74 CODE F- \ substract Q15.16 numbers
75 SUB @PSP+,2(PSP) \ -- diflo d1hi d2hi
76 SUBC TOS,0(PSP) \ -- diflo difhi d2hi
81 $1A04 C@ $EF > [IF] ; test tag value MSP430FR413x subfamily without hardware_MPY
83 CODE F/ \ Q15.16 / Q15.16 --> Q15.16 result
85 MOV @PSP+,rDOVAR \ DVRlo
86 MOV @PSP+,X \ DVDhi --> REMlo
88 MOV @PSP,Y \ DVDlo --> DVDhi
91 XOR TOS,S \ DVDhi XOR DVRhi --> S keep sign of result
93 S< IF XOR #-1,Y \ INV(DVDlo)
94 XOR #-1,X \ INV(DVDhi)
95 ADD #1,Y \ INV(DVDlo)+1
96 ADDC #0,X \ INV(DVDhi)+C
97 THEN AND #-1,TOS \ DVR < 0 ?
98 S< IF XOR #-1,rDOVAR \ INV(DVRlo)
99 XOR #-1,TOS \ INV(DVRhi)
100 ADD #1,rDOVAR \ INV(DVRlo)+1
101 ADDC #0,TOS \ INV(DVRhi)+C
103 \ don't uncomment lines below !
104 \ ------------------------------------------------------------------------
105 \ UD/MOD DVDlo DVDhi DVRlo DVRhi -- REMlo REMhi QUOTlo QUOThi
106 \ ------------------------------------------------------------------------
107 \ MOV 4(PSP),T \ DVDlo
108 \ MOV 2(PSP),Y \ DVDhi
109 \ MOV #0,X \ REMlo = 0
110 \ MOV #0,W \ REMhi = 0
111 MOV #32,rDOCON \ init loop count
112 BW1 CMP TOS,W \ 1 REMhi = DVRhi ?
113 0= IF CMP rDOVAR,X \ 1 REMlo U< DVRlo ?
115 U>= IF SUB rDOVAR,X \ 1 no: REMlo - DVRlo (carry is set)
116 SUBC TOS,W \ 1 REMhi - DVRhi
118 BW2 ADDC rDOCOL,rDOCOL \ 1 RLC quotLO
119 ADDC rDODOES,rDODOES \ 1 RLC quotHI
120 SUB #1,rDOCON \ 1 Decrement loop counter
121 0< ?GOTO FW1 \ 2 out of loop if count<0
122 ADD T,T \ 1 RLA DVDlo
123 ADDC Y,Y \ 1 RLC DVDhi
124 ADDC X,X \ 1 RLC REMlo
125 ADDC W,W \ 1 RLC REMhi
126 U< ?GOTO BW1 \ 2 15~ loop
127 SUB rDOVAR,X \ 1 REMlo - DVRlo
128 SUBC TOS,W \ 1 REMhi - DVRhi
130 GOTO BW2 \ 2 16~ loop
132 \ MOV X,4(PSP) \ REMlo
133 \ MOV W,2(PSP) \ REMhi
134 \ ADD #4,PSP \ skip REMlo REMhi
135 MOV rDOCOL,0(PSP) \ QUOTlo
136 MOV rDODOES,TOS \ QUOThi
137 POPM #4,rDOCOL \ restore rDODOES to rDOCOL
138 \ MOV @IP+,PC \ end of UD/MOD
139 \ ------------------------------------------------------------------------
140 BW1 AND #-1,S \ clear V, set N; QUOT < 0 ?
141 S< IF XOR #-1,0(PSP) \ INV(QUOTlo)
142 XOR #-1,TOS \ INV(QUOThi)
143 ADD #1,0(PSP) \ INV(QUOTlo)+1
144 ADDC #0,TOS \ INV(QUOThi)+C
149 \ F#S Qlo Qhi u -- Qhi 0 convert fractional part Qlo of Q15.16 fixed point number
152 MOV 2(PSP),X \ -- Qlo Qhi u X = Qlo
153 MOV @PSP,2(PSP) \ -- Qhi Qhi u
154 MOV X,0(PSP) \ -- Qhi Qlo u
155 PUSHM #2,TOS \ save TOS,IP
156 MOV #0,S \ -- Qhi Qlo x
157 BEGIN PUSH S \ R-- limit IP count
158 MOV &BASE,TOS \ -- Qhi Qlo base
160 UM* \ u1 u2 -- RESlo REShi
161 HI2LO \ -- Qhi RESlo digit
163 CMP #10,TOS \ digit to char
166 MOV @RSP+,S \ R-- limit IP
167 MOV.B TOS,HOLDS_ORG(S) \ -- Qhi RESlo char char to string
169 CMP 2(RSP),S \ count=limit ?
171 POPM #2,TOS \ restore IP,TOS
172 MOV #0,0(PSP) \ -- Qhi 0 len
173 SUB #2,PSP \ -- Qhi 0 x len
174 MOV #HOLDS_ORG,0(PSP) \ -- Qhi 0 addr len
179 \ unsigned multiply 32*32 = 64
180 \ don't use S reg (keep sign)
183 PUSHM #4,rDOCOL \ 6 save rDOCOL ~ rDODOES regs
184 MOV 4(PSP),IP \ 3 MDlo
185 MOV 2(PSP),T \ 3 MDhi
187 MOV #0,rDODOES \ 1 MDLO=0
188 MOV #0,rDOCON \ 1 MDHI=0
189 MOV #0,4(PSP) \ 3 RESlo=0
190 MOV #0,2(PSP) \ 3 REShi=0
191 MOV #0,rDOVAR \ 1 RESLO=0
192 MOV #0,rDOCOL \ 1 RESHI=0
193 MOV #1,X \ 1 BIT TEST REGlo
194 MOV #0,Y \ 1 BIT TEST2 REGhi
196 0<> IF BIT X,W \ 2+1 TEST ACTUAL BIT MRlo
197 ELSE BIT Y,TOS \ 2+1 TEST ACTUAL BIT MRhi
199 0<> IF ADD IP,4(PSP) \ 2+3 IF 1: ADD MDlo TO RESlo
200 ADDC T,2(PSP) \ 3 ADDC MDhi TO REShi
201 ADDC rDODOES,rDOVAR \ 1 ADDC MDLO TO RESLO
202 ADDC rDOCON,rDOCOL \ 1 ADDC MDHI TO RESHI
203 THEN ADD IP,IP \ 1 (RLA LSBs) MDlo *2
204 ADDC T,T \ 1 (RLC MSBs) MDhi *2
205 ADDC rDODOES,rDODOES \ 1 (RLA LSBs) MDLO *2
206 ADDC rDOCON,rDOCON \ 1 (RLC MSBs) MDHI *2
207 ADD X,X \ 1 (RLA) NEXT BIT TO TEST
208 ADDC Y,Y \ 1 (RLA) NEXT BIT TO TEST
209 U>= UNTIL MOV rDOVAR,0(PSP) \ 2+2 IF BIT IN CARRY: FINISHED 32 * 16~ (average loop)
210 MOV rDOCOL,TOS \ 1 high result in TOS
211 POPM #4,rDOCOL \ 6 restore rDODOES to rDOCOL
216 CODE F* \ s15.16 * s15.16 --> s15.16 result
218 XOR TOS,S \ 1s15 XOR 2s15 --> S keep sign of result
219 BIT #$8000,2(PSP) \ MD < 0 ?
220 0<> IF XOR #-1,2(PSP)
226 DABS UDM* \ -- RES0 RES1 RES2 RES3
229 MOV @PSP+,TOS \ -- RES0 RES1 RES2
230 MOV @PSP+,0(PSP) \ -- RES1 RES2
231 GOTO BW1 \ goto end of F/ to process sign of result
234 [ELSE] \ hardware multiplier
236 CODE F/ \ Q15.16 / Q15.16 --> Q15.16 result
241 PUSHM #4,rDOCOL \ 6 PUSHM rDOCOL to rDODOES
242 MOV @PSP+,rDOVAR \ 2 DVRlo
243 MOV @PSP+,X \ 2 DVDhi --> REMlo
244 MOV #0,W \ 1 REMhi = 0
245 MOV @PSP,Y \ 2 DVDlo --> DVDhi
246 MOV #0,T \ 1 DVDlo = 0
248 XOR TOS,S \ 1 DVDhi XOR DVRhi --> S keep sign of result
249 AND #-1,X \ 1 DVD < 0 ?
250 S< IF XOR #-1,Y \ 1 INV(DVDlo)
251 XOR #-1,X \ 1 INV(DVDhi)
252 ADD #1,Y \ 1 INV(DVDlo)+1
253 ADDC #0,X \ 1 INV(DVDhi)+C
254 THEN AND #-1,TOS \ 1 DVRhi < 0 ?
255 S< IF XOR #-1,rDOVAR \ 1 INV(DVRlo)
256 XOR #-1,TOS \ 1 INV(DVRhi)
257 ADD #1,rDOVAR \ 1 INV(DVRlo)+1
258 ADDC #0,TOS \ 1 INV(DVRhi)+C
260 \ don't uncomment lines below !
261 \ ------------------------------------------------------------------------
262 \ UD/MOD DVDlo DVDhi DVRlo DVRhi -- REMlo REMhi QUOTlo QUOThi
263 \ ------------------------------------------------------------------------
264 \ MOV 4(PSP),T \ DVDlo
265 \ MOV 2(PSP),Y \ DVDhi
266 \ MOV #0,X \ REMlo = 0
267 \ MOV #0,W \ REMhi = 0
268 MOV #32,rDOCON \ 2 init loop count
269 BW1 CMP TOS,W \ 1 REMhi = DVRhi ?
270 0= IF CMP rDOVAR,X \ 1 REMlo U< DVRlo ?
272 U>= IF SUB rDOVAR,X \ 1 no: REMlo - DVRlo (carry is set)
273 SUBC TOS,W \ 1 REMhi - DVRhi
275 BW2 ADDC rDOCOL,rDOCOL \ 1 RLC quotLO
276 ADDC rDODOES,rDODOES \ 1 RLC quotHI
277 SUB #1,rDOCON \ 1 Decrement loop counter
278 0< ?GOTO FW1 \ 2 out of loop if count<0
279 ADD T,T \ 1 RLA DVDlo
280 ADDC Y,Y \ 1 RLC DVDhi
281 ADDC X,X \ 1 RLC REMlo
282 ADDC W,W \ 1 RLC REMhi
283 U< ?GOTO BW1 \ 2 19~ loop
284 SUB rDOVAR,X \ 1 REMlo - DVRlo
285 SUBC TOS,W \ 1 REMhi - DVRhi
287 GOTO BW2 \ 2 16~ loop
288 FW1 AND #-1,S \ 1 clear V, set N; QUOT < 0 ?
289 S< IF XOR #-1,rDOCOL \ 1 INV(QUOTlo)
290 XOR #-1,rDODOES \ 1 INV(QUOThi)
291 ADD #1,rDOCOL \ 1 INV(QUOTlo)+1
292 ADDC #0,rDODOES \ 1 INV(QUOThi)+C
293 THEN MOV rDOCOL,0(PSP) \ 3 QUOTlo
294 MOV rDODOES,TOS \ 1 QUOThi
295 POPM #4,rDOCOL \ 6 restore rDODOES to rDOCOL
300 \ F#S Qlo Qhi u -- Qhi 0 convert fractionnal part of Q15.16 fixed point number
303 MOV 2(PSP),X \ -- Qlo Qhi u X = Qlo
304 MOV @PSP,2(PSP) \ -- Qhi Qhi u
305 MOV X,0(PSP) \ -- Qhi Qlo u
306 MOV TOS,T \ T = limit
308 BEGIN MOV @PSP,&MPY \ Load 1st operand
309 MOV &BASE,&OP2 \ Load 2nd operand
310 MOV &RES0,0(PSP) \ -- Qhi RESlo x low result on stack
311 MOV &RES1,TOS \ -- Qhi RESlo REShi high result in TOS
312 CMP #10,TOS \ digit to char
315 MOV.B TOS,HOLDS_ORG(S) \ -- Qhi RESlo char char to string
317 CMP T,S \ count=limit ?
318 0= UNTIL MOV #0,0(PSP) \ -- Qhi 0 REShi
319 MOV T,TOS \ -- Qhi 0 limit
320 SUB #2,PSP \ -- Qhi 0 x len
321 MOV #HOLDS_ORG,0(PSP) \ -- Qhi 0 addr len
326 CODE F* \ signed s15.16 multiplication --> s15.16 result
327 MOV 4(PSP),&MPYS32L \ 5 Load 1st operand
328 MOV 2(PSP),&MPYS32H \ 5
329 MOV @PSP,&OP2L \ 4 load 2nd operand
331 ADD #4,PSP \ 1 remove 2 cells
333 \ NOP2 \ 2 wait 8 cycles after write OP2L before reading RES1
339 [THEN] \ hardware multiplier
342 CODE F. \ display a Q15.16 number with 4/5/16 digits after comma
344 MOV #4,T \ T = 4 preset 4 digits for base 16 and by default
348 ADD #1,T \ T = 5 set 5 digits
352 MOV #16,T \ T = 16 set 16 digits
355 PUSHM #3,IP \ R-- IP sign #digit
357 <# DABS \ -- uQlo uQhi R-- IP sign #digit
358 R> F#S \ -- uQhi 0 R-- IP sign
359 $2C HOLD \ $2C = char ','
361 R> SIGN #> \ -- addr len R-- IP
365 CODE S>F \ convert a signed number to a Q15.16 (signed) number
374 \ https://forth-standard.org/standard/core/TwoFetch
375 \ 2@ a-addr -- x1 x2 fetch 2 cells ; the lower address will appear on top of stack
382 [THEN] \ of [UNDEFINED] 2@
384 [UNDEFINED] 2CONSTANT [IF]
385 \ https://forth-standard.org/standard/double/TwoCONSTANT
386 : 2CONSTANT \ udlo/dlo/Qlo udhi/dhi/Qhi -- to create double or Q15.16 CONSTANT
387 CREATE , , \ compile Qhi then Qlo
388 DOES> 2@ \ execution part addr -- Qhi Qlo
390 [THEN] \ of [UNDEFINED] 2CONSTANT
394 [THEN] \ of [UNDEFINED] {FIXPOINT}
398 ; -----------------------
400 ; -----------------------
404 PI -1,0 F* 2CONSTANT -PI
423 32767,99999 1,0 f* F.
424 32767,99999 1,0 f/ F.
425 32767,99999 2,0 f/ F.
426 32767,99999 4,0 f/ F.
427 32767,99999 8,0 f/ F.
428 32767,99999 16,0 f/ F.
439 ; sqrt(32768)^2 = 32768
440 181,01933598375 181,01933598375 f* f.
441 181,01933598375 -181,01933598375 f* f.
442 -181,01933598375 181,01933598375 f* f.
443 -181,01933598375 -181,01933598375 f* f.