1 ; -*- coding: utf-8 -*-
3 ; to see kernel options, download FastForthSpecs.f
4 ; FastForth kernel options: MSP430ASSEMBLER, CONDCOMP, DOUBLE_INPUT
6 ; TARGET SELECTION ( = the name of ;INC;target.pat file without the extension)
7 ; MSP_EXP430FR5739 MSP_EXP430FR5969 MSP_EXP430FR5994 MSP_EXP430FR6989
8 ; MSP_EXP430FR4133 MSP_EXP430FR2433 CHIPSTICK_FR2433 MSP_EXP430FR2355
11 ; from scite editor : copy your target selection in (shift+F8) parameter 1:
15 ; drag and drop this file onto SendSourceFileToTarget.bat
16 ; then select your TARGET when asked.
20 ; rDODOES to rEXIT must be saved before use and restored after
21 ; scratch registers Y to S are free for use
22 ; under interrupt, IP is free for use
24 ; FORTH conditionnals: unary{ 0= 0< 0> }, binary{ = < > U< }
26 ; ASSEMBLER conditionnal usage with IF UNTIL WHILE S< S>= U< U>= 0= 0<> 0>=
28 ; ASSEMBLER conditionnal usage with ?GOTO S< S>= U< U>= 0= 0<> 0<
31 ; -----------------------------------------------------
33 ; -----------------------------------------------------
39 ; https://forth-standard.org/standard/core/toR
40 ; >R x -- R: -- x push to return stack
48 ; https://forth-standard.org/standard/core/Rfrom
49 ; R> -- x R: x -- pop from return stack
59 ; https://forth-standard.org/standard/core/Zeroless
60 ; 0< n -- flag true if TOS negative
61 ZEROLESS ADD TOS,TOS ;1 set carry if TOS negative
62 SUBC TOS,TOS ;1 TOS=-1 if carry was clear
63 EQUALTRUE XOR #-1,TOS ;1 TOS=-1 if carry was set
68 ; https://forth-standard.org/standard/core/StoD
69 ; S>D n -- d single -> double prec.
77 ; https://forth-standard.org/standard/core/DROP
78 ; DROP x -- drop top of stack
80 DROP1 MOV @PSP+,TOS ; 2
85 ; https://forth-standard.org/standard/core/DUP
86 ; DUP x -- x x duplicate top of stack
88 QDUPNEXT SUB #2,PSP ; 2 push old TOS..
89 MOV TOS,0(PSP) ; 3 ..onto stack
90 QDUPEND MOV @IP+,PC ; 4
92 ; https://forth-standard.org/standard/core/qDUP
93 ; ?DUP x -- 0 | x x DUP if nonzero
101 ; https://forth-standard.org/standard/core/SWAP
102 ; SWAP x1 x2 -- x2 x1 swap top two items
111 ;https://forth-standard.org/standard/core/OVER
112 ;C OVER x1 x2 -- x1 x2 x1
114 OVER MOV TOS,-2(PSP) ; 3 -- x1 (x2) x2
115 MOV @PSP,TOS ; 2 -- x1 (x2) x1
116 SUB #2,PSP ; 1 -- x1 x2 x1
122 ; https://forth-standard.org/standard/core/NIP
123 ; NIP x1 x2 -- x2 Drop the first item below the top of stack
129 ;https://forth-standard.org/standard/core/ROT
130 ;C ROT x1 x2 x3 -- x2 x3 x1
132 ROT MOV @PSP,W ; 2 fetch x2
133 MOV TOS,0(PSP) ; 3 store x3
134 MOV 2(PSP),TOS ; 3 fetch x1
135 MOV W,2(PSP) ; 3 store x2
140 ;https://forth-standard.org/standard/core/UMDivMOD
141 ; UM/MOD udlo|udhi u1 -- r q unsigned 32/16->r16 q16
143 UMSLASHMOD PUSH #DROP ;3 as return address for MU/MOD
147 .IFNDEF FLOORED_DIVISION
149 ;https://forth-standard.org/standard/core/SMDivREM
150 ;C SM/REM d1lo d1hi n2 -- n3 n4 symmetric signed div
152 SMSLASHREM MOV TOS,S ;1 S=divisor
153 MOV @PSP,T ;2 T=rem_sign
154 CMP #0,TOS ;1 n2 >= 0 ?
155 JGE d1u2SMSLASHREM ;2 yes
158 d1u2SMSLASHREM ; -- d1 u2
159 CMP #0,0(PSP) ;3 d1hi >= 0 ?
160 JGE ud1u2SMSLASHREM ;2 yes
161 XOR #-1,2(PSP) ;4 d1lo
162 XOR #-1,0(PSP) ;4 d1hi
163 ADD #1,2(PSP) ;4 d1lo+1
164 ADDC #0,0(PSP) ;4 d1hi+C
165 ud1u2SMSLASHREM ; -- ud1 u2
166 PUSHM #2,S ;4 PUSHM S,T
169 POPM #2,S ;4 POPM T,S
170 CMP #0,T ;1 -- ur uq T=rem_sign>=0?
171 JGE SMSLASHREMnruq ;2 yes
175 XOR S,T ;1 S=divisor T=quot_sign
176 CMP #0,T ;1 -- nr uq T=quot_sign>=0?
177 JGE SMSLASHREMnrnq ;2 yes
180 SMSLASHREMnrnq ; -- nr nq S=divisor
181 MOV @IP+,PC ;4 34 words
184 .ELSE ; FLOORED_DIVISION
186 ;https://forth-standard.org/standard/core/FMDivMOD
187 ;C FM/MOD d1 n1 -- r q floored signed div'n
189 FMSLASHMOD MOV TOS,S ;1 S=divisor
190 MOV @PSP,T ;2 T=rem_sign
191 CMP #0,TOS ;1 n2 >= 0 ?
192 JGE d1u2FMSLASHMOD ;2 yes
195 d1u2FMSLASHMOD ; -- d1 u2
196 CMP #0,0(PSP) ;3 d1hi >= 0 ?
197 JGE ud1u2FMSLASHMOD ;2 yes
198 XOR #-1,2(PSP) ;4 d1lo
199 XOR #-1,0(PSP) ;4 d1hi
200 ADD #1,2(PSP) ;4 d1lo+1
201 ADDC #0,0(PSP) ;4 d1hi+C
202 ud1u2FMSLASHMOD ; -- ud1 u2
203 PUSHM #2,S ;4 PUSHM S,T
206 POPM #2,S ;4 POPM T,S
207 CMP #0,T ;1 -- ur uq T=rem_sign>=0?
208 JGE FMSLASHMODnruq ;2 yes
212 XOR S,T ;1 S=divisor T=quot_sign
213 CMP #0,T ;1 -- nr uq T=quot_sign>=0?
214 JGE FMSLASHMODnrnq ;2 yes
217 FMSLASHMODnrnq ; -- nr nq S=divisor
221 CMP #1,TOS ; quotient < 1 ?
223 QUOTLESSONE ADD S,0(PSP) ; add divisor to remainder
224 SUB #1,TOS ; decrement quotient
232 ;https://forth-standard.org/standard/core/Div
233 ;C / n1 n2 -- n3 signed divide
237 .IFNDEF FLOORED_DIVISION
246 ;https://forth-standard.org/standard/core/CFetch
247 ; C@ c-addr -- char fetch char from memory
249 CFETCH MOV.B @TOS,TOS ;2
254 ; https://forth-standard.org/standard/core/OneMinus
255 ; 1- n1/u1 -- n2/u2 subtract 1 from TOS
262 ;https://forth-standard.org/standard/core/less
263 ;C < n1 n2 -- flag test n1<n2, signed
265 LESS SUB @PSP+,TOS ;1 TOS=n2-n1
266 JZ LESSEND ;2 flag Z = 1
267 JL TOSFALSE ;2 signed jump
268 TOSTRUE MOV #-1,TOS ;1 flag Z = 0
269 LESSEND MOV @IP+,PC ;4
271 ;https://forth-standard.org/standard/core/more
272 ;C > n1 n2 -- flag test n1>n2, signed
274 MORE SUB @PSP+,TOS ;2 TOS=n2-n1
276 TOSFALSE AND #0,TOS ;1 flag Z = 1
282 ;; https://forth-standard.org/standard/core/IF
283 ;; IF -- IFadr initialize conditional forward branch
284 ; FORTHWORDIMM "IF" ; immediate
287 ; MOV &DP,TOS ; -- HERE
288 ; ADD #4,&DP ; compile one word, reserve one word
289 ; MOV #QFBRAN,0(TOS) ; -- HERE compile QFBRAN
290 ; ADD #2,TOS ; -- HERE+2=IFadr
293 ; FORTHWORDIMM "ELSE" ; immediate
294 ;; https://forth-standard.org/standard/core/ELSE
295 ;; ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
296 ;ELSS ADD #4,&DP ; make room to compile two words
297 ; MOV &DP,W ; W=HERE+4
299 ; MOV W,0(TOS) ; HERE+4 ==> [IFadr]
301 ; MOV W,TOS ; -- ELSEadr
304 ; FORTHWORDIMM "THEN" ; immediate
305 ;; https://forth-standard.org/standard/core/THEN
306 ;; THEN IFadr -- resolve forward branch
307 ;THEN MOV &DP,0(TOS) ; -- IFadr
313 ; https://forth-standard.org/standard/core/TO
320 ;https://forth-standard.org/standard/core/SPACE
321 ;C SPACE -- output a space
326 MOV #EMIT,PC ;17~ 23~
330 ;https://forth-standard.org/standard/core/SPACES
331 ;C SPACES n -- output n spaces
341 JNZ SPACE ;25~ ==> 27~ by space ==> 2.963 MBds @ 8 MHz
343 SPACESNEXT2 MOV @PSP+,TOS ; -- drop n
348 ; https://forth-standard.org/standard/core/TwoFetch
349 ; 2@ a-addr -- x1 x2 fetch 2 cells ; the lower address will appear on top of stack
358 ; https://forth-standard.org/standard/core/TwoStore
359 ; 2! x1 x2 a-addr -- store 2 cells ; the top of stack is stored at the lower adr
361 TWOSTORE MOV @PSP+,0(TOS)
368 ; https://forth-standard.org/standard/core/TwoDUP
369 ; 2DUP x1 x2 -- x1 x2 x1 x2 dup top 2 cells
371 TWODUP MOV TOS,-2(PSP) ; 3
378 ; https://forth-standard.org/standard/core/TwoDROP
379 ; 2DROP x1 x2 -- drop 2 cells
387 ; https://forth-standard.org/standard/core/TwoSWAP
388 ; 2SWAP x1 x2 x3 x4 -- x3 x4 x1 x2
390 TWOSWAP MOV @PSP,W ; -- x1 x2 x3 x4 W=x3
391 MOV 4(PSP),0(PSP) ; -- x1 x2 x1 x4
392 MOV W,4(PSP) ; -- x3 x2 x1 x4
393 MOV TOS,W ; -- x3 x2 x1 x4 W=x4
394 MOV 2(PSP),TOS ; -- x3 x2 x1 x2 W=x4
395 MOV W,2(PSP) ; -- x3 x4 x1 x2
400 ; https://forth-standard.org/standard/core/TwoOVER
401 ; 2OVER x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2
403 TwoOVER SUB #4,PSP ; -- x1 x2 x3 x x x4
404 MOV TOS,2(PSP) ; -- x1 x2 x3 x4 x x4
405 MOV 8(PSP),0(PSP) ; -- x1 x2 x3 x4 x1 x4
406 MOV 6(PSP),TOS ; -- x1 x2 x3 x4 x1 x2
411 ; https://forth-standard.org/standard/core/TwotoR
412 ; ( x1 x2 -- ) ( R: -- x1 x2 ) Transfer cell pair x1 x2 to the return stack.
421 ; https://forth-standard.org/standard/core/TwoRFetch
422 ; ( -- x1 x2 ) ( R: x1 x2 -- x1 x2 ) Copy cell pair x1 x2 from the return stack.
432 ; https://forth-standard.org/standard/core/TwoRfrom
433 ; ( -- x1 x2 ) ( R: x1 x2 -- ) Transfer cell pair x1 x2 from the return stack
442 ; ===============================================
444 ; ===============================================
446 ; https://forth-standard.org/standard/double/Dd
447 ; D. dlo dhi -- display d (signed)
449 MOV TOS,S ; S will be pushed as sign
450 MOV #UDOT+10,PC ; U. + 10 = D.
454 ; https://forth-standard.org/standard/double/TwoROT
455 ; Rotate the top three cell pairs on the stack bringing cell pair x1 x2 to the top of the stack.
457 TWOROT MOV 8(PSP),X ; 3
459 MOV 4(PSP),8(PSP) ; 5
460 MOV 2(PSP),6(PSP) ; 5
469 ; https://forth-standard.org/standard/double/DtoS
470 ; D>S d -- n double prec -> single.
477 ; https://forth-standard.org/standard/double/DZeroEqual
479 DZEROEQUAL ADD #2,PSP
486 DSETFLAG AND #-1,TOS ; to set N, Z flags
489 ; https://forth-standard.org/standard/double/DZeroless
497 ; https://forth-standard.org/standard/double/DEqual
499 DEQUAL ADD #6,PSP ; 2
500 CMP TOS,-4(PSP) ; 3 ud1H - ud2H
503 CMP -6(PSP),-2(PSP) ; 4 ud1L - ud2L
507 ; https://forth-standard.org/standard/double/Dless
508 ; flag is true if and only if d1 is less than d2
511 CMP TOS,-4(PSP) ; 3 d1H - d2H
515 DLESS2 JNZ DSETFLAG ; 2
516 CMP -6(PSP),-2(PSP) ; 4 d1L - d2L
520 ; https://forth-standard.org/standard/double/DUless
521 ; flag is true if and only if ud1 is less than ud2
523 DULESS ADD #6,PSP ; 2
524 CMP TOS,-4(PSP) ; 3 ud1H - ud2H
531 ; https://forth-standard.org/standard/double/DPlus
533 DPLUS ADD @PSP+,2(PSP)
539 ; https://forth-standard.org/standard/double/MPlus
551 ; https://forth-standard.org/standard/double/DMinus
553 DMINUS SUB @PSP+,2(PSP)
560 ; https://forth-standard.org/standard/double/DNEGATE
562 DNEGATE XOR #-1,0(PSP)
568 ; https://forth-standard.org/standard/double/DABS
569 ; DABS d1 -- |d1| absolute value
577 ; https://forth-standard.org/standard/double/DTwoDiv
585 ; https://forth-standard.org/standard/double/DTwoTimes
586 DTWOTIMES FORTHWORD "D2*"
593 ; https://forth-standard.org/standard/double/DMAX
594 FORTHWORD "DMAX" ; -- d1 d2
596 .word TWOOVER,TWOOVER ; -- d1 d2 d1 d2
597 .word DLESS,QFBRAN,DMAX1 ; -- d1 d2
598 .word TWOTOR,TWODROP,TWORFROM ; -- d2
599 .word BRAN,DMAX2 ; -- d1 d2
600 DMAX1 .word TWODROP ; -- d1
605 ; https://forth-standard.org/standard/double/DMIN
606 FORTHWORD "DMIN" ; -- d1 d2
608 .word TWOOVER,TWOOVER ; -- d1 d2 d1 d2
609 .word DLESS,QFBRAN,DMIN1 ; -- d1 d2
610 .word TWODROP ; -- d1
611 .word BRAN,DMIN2 ; -- d1 d2
612 DMIN1 .word TWOTOR,TWODROP,TWORFROM ; -- d2
617 ; https://forth-standard.org/standard/double/MTimesDiv
618 FORTHWORD "M*/" ; d1 * n1 / +n2 -- d2
621 MOV 4(PSP),&MPYS32L ; 5 Load 1st operand d1lo
622 MOV 2(PSP),&MPYS32H ; 5 d1hi
623 MOV @PSP+,&OP2 ; 4 -- d1 n2 load 2nd operand n1
626 MOV &RES0,S ; 3 S = RESlo
627 MOV &RES1,TOS ; 3 TOS = RESmi
628 MOV &RES2,W ; 3 W = REShi
629 MOV #0,rDOCON ; clear sign flag
630 CMP #0,W ; negative product ?
632 XOR #-1,S ; compute ABS value if yes
638 MOV #-1,rDOCON ; set sign flag
641 MOV #0,rDOCON ; rDOCON = sign
642 CMP #0,2(PSP) ; d1 < 0 ?
644 XOR #-1,4(PSP) ; compute ABS value if yes
650 CMP #0,0(PSP) ; n1 < 0 ?
655 ; let's process UM* -- ud1lo ud1hi u1 +n2
656 MTIMESDIV3 MOV 4(PSP),Y ; 3 uMDlo
657 MOV 2(PSP),T ; 3 uMDhi
658 MOV @PSP+,S ; 2 uMRlo -- ud1lo ud1hi +n2
659 MOV #0,rDODOES ; 1 uMDlo=0
660 MOV #0,2(PSP) ; 3 uRESlo=0
661 MOV #0,0(PSP) ; 3 uRESmi=0 -- uRESlo uRESmi +n2
662 MOV #0,W ; 1 uREShi=0
663 MOV #1,X ; 1 BIT TEST REGlo
664 MTIMESDIV4 BIT X,S ; 1 test actual bit in uMRlo
666 ADD Y,2(PSP) ; 3 IF 1: ADD uMDlo TO uRESlo
667 ADDC T,0(PSP) ; 3 ADDC uMDmi TO uRESmi
668 ADDC rDODOES,W ; 1 ADDC uMRlo TO uREShi
669 MTIMESDIV5 ADD Y,Y ; 1 (RLA LSBs) uMDlo *2
670 ADDC T,T ; 1 (RLC MSBs) uMDhi *2
671 ADDC rDODOES,rDODOES ; 1 (RLA LSBs) uMDlo *2
672 ADD X,X ; 1 (RLA) NEXT BIT TO TEST
673 JNC MTIMESDIV4 ; 1 IF BIT IN CARRY: FINISHED W=uREShi
681 .ENDIF ; endcase of software/hardware_MPY
684 ; ------------------------------
689 ; X = Don't care QUOTlo
690 ; Y = Don't care QUOThi
696 MOV #32,rDODOES ; 2 init loop count
697 CMP #0,W ; DVDhi = 0 ?
698 JNZ MTIMESDIV6 ; if no
699 MOV TOS,W ; DVDmi --> DVDhi
700 CALL #MDIV1DIV2 ; with loop count / 2
702 MTIMESDIV6 CALL #MDIV1 ; -- urem ud2lo ud2hi
703 MTIMESDIV7 MOV @PSP+,0(PSP) ; -- d2lo d2hi
704 CMP #0,rDOCON ; RES sign is set ?
706 XOR #-1,0(PSP) ; DNEGATE quot
710 CMP #0,&FORTHADDON ; floored/symetric division flag test
711 JGE MTIMESDIV8 ; if not(floored division and quot<0)
712 CMP #0,W ; remainder <> 0 ?
713 JZ MTIMESDIV8 ; if not(floored division, quot<0 and remainder <>0)
714 SUB #1,0(PSP) ; decrement quotient
716 MTIMESDIV8 MOV #XDODOES,rDODOES
718 MOV @IP+,PC ; 52 words
722 ; https://forth-standard.org/standard/double/TwoVARIABLE
723 FORTHWORD "2VARIABLE" ; --
733 ; https://forth-standard.org/standard/double/TwoCONSTANT
734 FORTHWORD "2CONSTANT" ; udlo/dlo/Flo udhi/dhi/Shi -- to create double or s15q16 CONSTANT
737 .word COMMA,COMMA ; compile Shi then Flo
739 .word TWOFETCH ; execution part
744 ; https://forth-standard.org/standard/double/TwoVALUE
745 FORTHWORD "2VALUE" ; x1 x2 "<spaces>name" --
747 .word CREATE ; compile Shi then Flo
748 .word COMMA,COMMA ; compile Shi then Flo
752 BIT #UF9,SR ; flag set by TO
754 MOV #TwoFetch,PC ; execute TwoFetch
755 TwoVALUESTO BIC #UF9,SR ; clear flag
756 MOV #TwoStore,PC ; execute TwoStore
760 ; https://forth-standard.org/standard/double/TwoLITERAL
761 FORTHWORDIMM "2LITERAL"
762 TwoLITERAL BIS #UF9,SR ; see LITERAL
767 ; https://forth-standard.org/standard/double/DDotR
771 .word TOR,SWAP,OVER,DABS,LESSNUM,NUMS,ROT,SIGN,NUMGREATER
772 .word RFROM,OVER,MINUS,SPACES,TYPE