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<
36 0<> IF MOV #0,TOS THEN \ if TOS <> 0 (DOUBLE input), set TOS = 0
39 SUB #307,TOS \ FastForth V3.7
41 $0D EMIT \ return to column 1 without CR
42 ABORT" FastForth version = 3.7 please!"
43 ABORT" build FastForth with DOUBLE_INPUT addon !"
44 PWR_STATE \ if no abort remove this word
49 ; -----------------------------------------------------
51 ; -----------------------------------------------------
53 [DEFINED] {DOUBLE} [IF] {DOUBLE} [THEN]
58 \ https://forth-standard.org/standard/core/toR
59 \ >R x -- R: -- x push to return stack
68 \ https://forth-standard.org/standard/core/Rfrom
69 \ R> -- x R: x -- pop from return stack ; CALL #RFROM performs DOVAR
79 \ https://forth-standard.org/standard/core/Fetch
80 \ @ c-addr -- char fetch char from memory
88 \ https://forth-standard.org/standard/core/Store
89 \ ! x a-addr -- store cell in memory
98 \ https://forth-standard.org/standard/core/CFetch
99 \ C@ c-addr -- char fetch char from memory
106 [UNDEFINED] SWAP [IF]
107 \ https://forth-standard.org/standard/core/SWAP
108 \ SWAP x1 x2 -- x2 x1 swap top two items
117 [UNDEFINED] OVER [IF]
118 \ https://forth-standard.org/standard/core/OVER
119 \ OVER x1 x2 -- x1 x2 x1
121 MOV TOS,-2(PSP) \ 3 -- x1 (x2) x2
122 MOV @PSP,TOS \ 2 -- x1 (x2) x1
123 SUB #2,PSP \ 1 -- x1 x2 x1
129 \ https://forth-standard.org/standard/core/ROT
130 \ ROT x1 x2 x3 -- x2 x3 x1
132 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
141 \ https://forth-standard.org/standard/core/Minus
142 \ - n1/u1 n2/u2 -- n3/u3 n3 = n1-n2
144 SUB @PSP+,TOS \ 2 -- n2-n1 ( = -n3)
146 ADD #1,TOS \ 1 -- n3 = -(n2-n1) = n1-n2
151 [UNDEFINED] < [IF] \ define < and >
152 \ https://forth-standard.org/standard/core/less
153 \ < n1 n2 -- flag test n1<n2, signed
155 SUB @PSP+,TOS \ 1 TOS=n2-n1
156 S< ?GOTO FW1 \ 2 signed
158 BW1 MOV #-1,TOS \ 1 flag Z = 0
163 \ https://forth-standard.org/standard/core/more
164 \ > n1 n2 -- flag test n1>n2, signed
166 SUB @PSP+,TOS \ 2 TOS=n2-n1
167 S< ?GOTO BW1 \ 2 --> +5
168 FW1 AND #0,TOS \ 1 flag Z = 1
173 [UNDEFINED] IF [IF] \ define IF THEN
174 \ https://forth-standard.org/standard/core/IF
175 \ IF -- IFadr initialize conditional forward branch
179 MOV &DP,TOS \ -- HERE
180 ADD #4,&DP \ compile one word, reserve one word
181 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
182 ADD #2,TOS \ -- HERE+2=IFadr
186 \ https://forth-standard.org/standard/core/THEN
187 \ THEN IFadr -- resolve forward branch
188 CODE THEN \ immediate
189 MOV &DP,0(TOS) \ -- IFadr
195 [UNDEFINED] ELSE [IF]
196 \ https://forth-standard.org/standard/core/ELSE
197 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
198 CODE ELSE \ immediate
199 ADD #4,&DP \ make room to compile two words
202 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
204 MOV W,TOS \ -- ELSEadr
210 \ https://forth-standard.org/standard/core/TO
217 [UNDEFINED] DOES> [IF]
218 \ https://forth-standard.org/standard/core/DOES
219 \ DOES> -- set action for the latest CREATEd definition
221 MOV &LAST_CFA,W \ W = CFA of CREATEd word
222 MOV #DODOES,0(W) \ replace CFA (DOCON) by new CFA (DODOES)
223 MOV IP,2(W) \ replace PFA by the address after DOES> as execution address
229 [UNDEFINED] SPACES [IF]
230 \ https://forth-standard.org/standard/core/SPACES
231 \ SPACES n -- output n spaces
245 MOV @PSP+,TOS \ -- drop n
251 \ https://forth-standard.org/standard/core/TwoFetch
252 \ 2@ a-addr -- x1 x2 fetch 2 cells ; the lower address will appear on top of stack
262 \ https://forth-standard.org/standard/core/TwoStore
263 \ 2! x1 x2 a-addr -- store 2 cells ; the top of stack is stored at the lower adr
272 [UNDEFINED] 2DUP [IF]
273 \ https://forth-standard.org/standard/core/TwoDUP
274 \ 2DUP x1 x2 -- x1 x2 x1 x2 dup top 2 cells
276 SUB #4,PSP \ -- x1 x x x2
277 MOV TOS,2(PSP) \ -- x1 x2 x x2
278 MOV 4(PSP),0(PSP) \ -- x1 x2 x1 x2
283 [UNDEFINED] 2DROP [IF]
284 \ https://forth-standard.org/standard/core/TwoDROP
285 \ 2DROP x1 x2 -- drop 2 cells
293 [UNDEFINED] 2SWAP [IF]
294 \ https://forth-standard.org/standard/core/TwoSWAP
295 \ 2SWAP x1 x2 x3 x4 -- x3 x4 x1 x2
297 MOV @PSP,W \ -- x1 x2 x3 x4 W=x3
298 MOV 4(PSP),0(PSP) \ -- x1 x2 x1 x4
299 MOV W,4(PSP) \ -- x3 x2 x1 x4
300 MOV TOS,W \ -- x3 x2 x1 x4 W=x4
301 MOV 2(PSP),TOS \ -- x3 x2 x1 x2 W=x4
302 MOV W,2(PSP) \ -- x3 x4 x1 x2
307 [UNDEFINED] 2OVER [IF]
308 \ https://forth-standard.org/standard/core/TwoOVER
309 \ 2OVER x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2
311 SUB #4,PSP \ -- x1 x2 x3 x x x4
312 MOV TOS,2(PSP) \ -- x1 x2 x3 x4 x x4
313 MOV 8(PSP),0(PSP) \ -- x1 x2 x3 x4 x1 x4
314 MOV 6(PSP),TOS \ -- x1 x2 x3 x4 x1 x2
320 \ https://forth-standard.org/standard/core/TwotoR
321 \ ( x1 x2 -- ) ( R: -- x1 x2 ) Transfer cell pair x1 x2 to the return stack.
331 \ https://forth-standard.org/standard/core/TwoRFetch
332 \ ( -- x1 x2 ) ( R: x1 x2 -- x1 x2 ) Copy cell pair x1 x2 from the return stack.
343 \ https://forth-standard.org/standard/core/TwoRfrom
344 \ ( -- x1 x2 ) ( R: x1 x2 -- ) Transfer cell pair x1 x2 from the return stack
354 \ ===============================================
356 \ ===============================================
359 \ https://forth-standard.org/standard/double/Dd
360 \ D. dlo dhi -- display d (signed)
362 MOV #U.,W \ U. + 10 = D.
368 [UNDEFINED] 2ROT [IF]
369 \ https://forth-standard.org/standard/double/TwoROT
370 \ Rotate the top three cell pairs on the stack bringing cell pair x1 x2 to the top of the stack.
374 MOV 4(PSP),8(PSP) \ 5
375 MOV 2(PSP),6(PSP) \ 5
385 \ https://forth-standard.org/standard/double/DtoS
386 \ D>S d -- n double prec -> single.
394 \ https://forth-standard.org/standard/double/DZeroEqual
410 \ https://forth-standard.org/standard/double/DZeroless
423 \ https://forth-standard.org/standard/double/DEqual
425 CMP TOS,2(PSP) \ 3 ud1H - ud2H
428 CMP @PSP,4(PSP) \ 4 ud1L - ud2L
439 \ https://forth-standard.org/standard/double/Dless
440 \ flag is true if and only if d1 is less than d2
442 CMP TOS,2(PSP) \ 3 d1H - d2H
448 CMP @PSP,4(PSP) \ 4 d1L - d2L
459 \ https://forth-standard.org/standard/double/DUless
460 \ flag is true if and only if ud1 is less than ud2
462 CMP TOS,2(PSP) \ 3 ud1H - ud2H
468 CMP @PSP,4(PSP) \ 4 ud1L - ud2L
479 \ https://forth-standard.org/standard/double/DPlus
488 \ https://forth-standard.org/standard/double/MPlus
502 \ https://forth-standard.org/standard/double/DMinus
511 [UNDEFINED] DNEGATE [IF]
512 \ https://forth-standard.org/standard/double/DNEGATE
522 [UNDEFINED] DABS [IF]
523 \ https://forth-standard.org/standard/double/DABS
524 \ DABS d1 -- |d1| absolute value
535 \ https://forth-standard.org/standard/double/DTwoDiv
544 \ https://forth-standard.org/standard/double/DTwoTimes
552 [UNDEFINED] DMAX [IF]
553 \ https://forth-standard.org/standard/double/DMAX
555 2OVER 2OVER \ -- d1 d2 d1 d2
557 2>R 2DROP 2R> \ -- d2
564 [UNDEFINED] DMIN [IF]
565 \ https://forth-standard.org/standard/double/DMIN
567 2OVER 2OVER \ -- d1 d2 d1 d2
570 ELSE 2>R 2DROP 2R> \ -- d1 d2
574 DEVICEID C@ $EF > [IF] ; test for MSP430FR413x devices without hardware_MPY
577 \ https://forth-standard.org/standard/double/MTimesDiv
578 CODE M*/ \ d1lo d1hi n1 +n2 -- d2lo d2hi
579 BIC #UF9,SR \ clear RES sign flag
580 CMP #0,2(PSP) \ d1 < 0 ?
586 BIS #UF9,SR \ set RES sign flag
588 CMP #0,0(PSP) \ n1 < 0 ?
598 THEN \ let's process UM* -- ud1lo ud1hi u1 +n2
599 MOV 4(PSP),Y \ 3 uMDlo
600 MOV 2(PSP),T \ 3 uMDhi
601 MOV @PSP+,S \ 2 uMRlo -- ud1lo ud1hi +n2
602 MOV #0,rDODOES \ 1 uMDlo=0
603 MOV #0,2(PSP) \ 3 uRESlo=0
604 MOV #0,0(PSP) \ 3 uRESmi=0 -- uRESlo uRESmi +n2
605 MOV #0,W \ 1 uREShi=0
606 MOV #1,X \ 1 BIT TEST REGlo
607 BEGIN BIT X,S \ 1 test actual bit in uMRlo
608 0<> IF ADD Y,2(PSP) \ 3 IF 1: ADD uMDlo TO uRESlo
609 ADDC T,0(PSP) \ 3 ADDC uMDmi TO uRESmi
610 ADDC rDODOES,W \ 1 ADDC uMRlo TO uREShi
611 THEN ADD Y,Y \ 1 (RLA LSBs) uMDlo *2
612 ADDC T,T \ 1 (RLC MSBs) uMDhi *2
613 ADDC rDODOES,rDODOES \ 1 (RLA LSBs) uMDlo *2
614 ADD X,X \ 1 (RLA) NEXT BIT TO TEST
615 U>= UNTIL \ 1 IF BIT IN CARRY: FINISHED W=uREShi
623 \ reg division output
624 \ --------------------------
628 \ W = 0|DVD(47-32) REM
635 MOV #32,rDODOES \ 2 init loop count
636 CMP #0,W \ DVDhi = 0 ?
638 MOV TOS,W \ DVDmi --> DVDhi
639 CALL #MDIV1DIV2 \ with loop count / 2
641 CALL #MDIV1 \ -- urem ud2lo ud2hi
643 MOV @PSP+,0(PSP) \ -- ud2lo ud2hi
644 BIT #UF9,SR \ sign is set ?
650 BIC #UF9,SR \ clear sign flag
651 \ now, make floored division, only used if rem<>0 and quot<0 :
652 CMP #0,W \ remainder <> 0 ?
654 SUB #1,0(PSP) \ decrement quotient
662 [ELSE] \ hardware multiplier
665 \ https://forth-standard.org/standard/double/MTimesDiv
666 CODE M*/ \ d1 * n1 / +n2 -- d2
667 MOV 4(PSP),&MPYS32L \ 5 Load 1st operand d1lo
668 MOV 2(PSP),&MPYS32H \ 5 d1hi
669 MOV @PSP+,&OP2 \ 4 -- d1 n2 load 2nd operand n1
672 MOV &RES0,S \ 3 S = RESlo
673 MOV &RES1,TOS \ 3 TOS = RESmi
674 MOV &RES2,W \ 3 W = REShi
675 BIC #UF9,SR \ clear sign flag
676 CMP #0,W \ negative product ?
684 BIS #UF9,SR \ set sign flag
686 \ reg division output
687 \ --------------------------
691 \ W = 0|DVD(47-32) REM
698 MOV #32,rDODOES \ 2 init loop count
699 CMP #0,W \ DVDhi = 0 ?
701 MOV TOS,W \ DVDmi --> DVDhi
702 CALL #MDIV1DIV2 \ with loop count / 2
704 CALL #MDIV1 \ -- urem ud2lo ud2hi
706 MOV @PSP+,0(PSP) \ -- d2lo d2hi
707 BIT #UF9,SR \ RES sign is set ?
713 BIC #UF9,SR \ clear sign flag
714 \ now, make floored division, only used if rem<>0 and quot<0 :
715 CMP #0,W \ remainder <> 0 ?
717 SUB #1,0(PSP) \ decrement quotient
721 MOV @IP+,PC \ 52 words
725 [THEN] ; end of software/hardware_MPY
727 [UNDEFINED] 2VARIABLE [IF]
728 \ https://forth-standard.org/standard/double/TwoVARIABLE
738 [UNDEFINED] 2CONSTANT [IF]
739 \ https://forth-standard.org/standard/double/TwoCONSTANT
740 : 2CONSTANT \ udlo/dlo/Flo udhi/dhi/Shi -- to create double or s15q16 CONSTANT
742 , , \ compile Shi then Flo
748 [UNDEFINED] 2VALUE [IF]
749 \ https://forth-standard.org/standard/double/TwoVALUE
750 : 2VALUE \ x1 x2 "<spaces>name" --
751 CREATE , , \ compile Shi then Flo
755 BIT #UF9,SR \ flag set by TO
757 MOV #2@,PC \ execute TwoFetch
759 BIC #UF9,SR \ clear flag
760 MOV #2!,PC \ execute TwoStore
764 [UNDEFINED] 2LITERAL [IF]
765 \ https://forth-standard.org/standard/double/TwoLITERAL
767 BIS #UF9,SR \ see LITERAL
773 \ https://forth-standard.org/standard/double/DDotR
776 >R SWAP OVER DABS <# #S ROT SIGN #>
777 R> OVER - SPACES TYPE
781 [THEN] \ end of {DOUBLE}
785 \ ------------------------------------------------------------------------------
786 \ ------------------------------------------------------------------------------
787 \ Complement to test DOUBLE
788 \ ------------------------------------------------------------------------------
789 \ ------------------------------------------------------------------------------
791 [UNDEFINED] VARIABLE [IF]
792 \ https://forth-standard.org/standard/core/VARIABLE
802 [UNDEFINED] CONSTANT [IF]
803 \ https://forth-standard.org/standard/core/CONSTANT
804 \ CONSTANT <name> n -- define a Forth CONSTANT
808 MOV TOS,-2(W) \ PFA = n
815 [UNDEFINED] CELLS [IF]
816 \ https://forth-standard.org/standard/core/CELLS
817 \ CELLS n1 -- n2 cells->adrs units
824 [UNDEFINED] ALLOT [IF]
825 \ https://forth-standard.org/standard/core/ALLOT
826 \ ALLOT n -- allocate n bytes
834 [UNDEFINED] DEPTH [IF]
835 \ https://forth-standard.org/standard/core/DEPTH
836 \ DEPTH -- +n number of items on stack, must leave 0 if stack empty
840 SUB PSP,TOS \ PSP-S0--> TOS
841 RRA TOS \ TOS/2 --> TOS
842 SUB #2,PSP \ post decrement stack...
848 \ https://forth-standard.org/standard/core/DUP
849 \ DUP x -- x x duplicate top of stack
851 BW1 SUB #2,PSP \ 2 push old TOS..
852 MOV TOS,0(PSP) \ 3 ..onto stack
856 \ https://forth-standard.org/standard/core/qDUP
857 \ ?DUP x -- 0 | x x DUP if nonzero
859 CMP #0,TOS \ 2 test for TOS nonzero
865 [UNDEFINED] DO [IF] \ define DO LOOP +LOOP
866 \ https://forth-standard.org/standard/core/DO
867 \ DO -- DOadr L: -- 0
871 ADD #2,&DP \ make room to compile xdo
872 MOV &DP,TOS \ -- HERE+2
873 MOV #XDO,-2(TOS) \ compile xdo
874 ADD #2,&LEAVEPTR \ -- HERE+2 LEAVEPTR+2
876 MOV #0,0(W) \ -- HERE+2 L-- 0
880 \ https://forth-standard.org/standard/core/LOOP
881 \ LOOP DOadr -- L-- an an-1 .. a1 0
882 CODE LOOP \ immediate
884 BW1 ADD #4,&DP \ make room to compile two words
886 MOV X,-4(W) \ xloop --> HERE
887 MOV TOS,-2(W) \ DOadr --> HERE+2
888 BEGIN \ resolve all "leave" adr
889 MOV &LEAVEPTR,TOS \ -- Adr of top LeaveStack cell
890 SUB #2,&LEAVEPTR \ --
891 MOV @TOS,TOS \ -- first LeaveStack value
892 CMP #0,TOS \ -- = value left by DO ?
894 MOV W,0(TOS) \ move adr after loop as UNLOOP adr
900 \ https://forth-standard.org/standard/core/PlusLOOP
901 \ +LOOP adrs -- L-- an an-1 .. a1 0
902 CODE +LOOP \ immediate
909 \ https://forth-standard.org/standard/core/I
910 \ I -- n R: sys1 sys2 -- sys1 sys2
911 \ get the innermost loop index
913 SUB #2,PSP \ 1 make room in TOS
915 MOV @RSP,TOS \ 2 index = loopctr - fudge
922 \ https://forth-standard.org/standard/core/Plus
923 \ + n1/u1 n2/u2 -- n3/u3 add n1+n2
931 \ https://forth-standard.org/standard/core/Equal
932 \ = x1 x2 -- flag test x1=x2
939 XOR #-1,TOS \ 1 flag Z = 1
945 \ https://forth-standard.org/standard/core/ZeroEqual
946 \ 0= n/u -- flag return true if TOS=0
948 SUB #1,TOS \ borrow (clear cy) if TOS was 0
949 SUBC TOS,TOS \ TOS=-1 if borrow was set
954 [UNDEFINED] SOURCE [IF]
955 \ https://forth-standard.org/standard/core/SOURCE
956 \ SOURCE -- adr u of current input buffer
961 MOV &SOURCE_ORG,0(PSP)
967 \ https://forth-standard.org/standard/core/toIN
968 \ C >IN -- a-addr holds offset in input stream
972 [UNDEFINED] SWAP [IF]
973 \ https://forth-standard.org/standard/core/SWAP
974 \ SWAP x1 x2 -- x2 x1 swap top two items
983 [UNDEFINED] DROP [IF]
984 \ https://forth-standard.org/standard/core/DROP
985 \ DROP x -- drop top of stack
993 \ https://forth-standard.org/standard/core/OnePlus
994 \ 1+ n1/u1 -- n2/u2 add 1 to TOS
1001 [UNDEFINED] CHAR [IF]
1002 \ https://forth-standard.org/standard/core/CHAR
1003 \ CHAR -- char parse ASCII character
1009 [UNDEFINED] [CHAR] [IF]
1010 \ https://forth-standard.org/standard/core/BracketCHAR
1011 \ [CHAR] -- compile character literal
1013 CHAR POSTPONE LITERAL
1018 \ https://forth-standard.org/standard/core/TwoDiv
1019 \ 2/ x1 -- x2 arithmetic right shift
1026 [UNDEFINED] INVERT [IF]
1027 \ https://forth-standard.org/standard/core/INVERT
1028 \ INVERT x1 -- x2 bitwise inversion
1035 [UNDEFINED] RSHIFT [IF]
1036 \ https://forth-standard.org/standard/core/RSHIFT
1037 \ RSHIFT x1 u -- x2 logical R7 shift u places
1040 AND #$1F,TOS \ no need to shift more than 16
1042 BEGIN BIC #C,SR \ Clr Carry
1052 \ https://forth-standard.org/standard/core/Zeroless
1053 \ 0< n -- flag true if TOS negative
1055 ADD TOS,TOS \ 1 set carry if TOS negative
1056 SUBC TOS,TOS \ 1 TOS=-1 if carry was clear
1057 XOR #-1,TOS \ 1 TOS=-1 if carry was set
1062 [UNDEFINED] S>D [IF]
1063 \ https://forth-standard.org/standard/core/StoD
1064 \ S>D n -- d single -> double prec.
1071 \ https://forth-standard.org/standard/core/OneMinus
1072 \ 1- n1/u1 -- n2/u2 subtract 1 from TOS
1079 [UNDEFINED] UM/MOD [IF]
1080 \ https://forth-standard.org/standard/core/UMDivMOD
1081 \ UM/MOD udlo|udhi u1 -- r q unsigned 32/16->r16 q16
1084 MOV #MUSMOD,PC \ execute MUSMOD then return to DROP
1088 [UNDEFINED] SM/REM [IF]
1089 \ https://forth-standard.org/standard/core/SMDivREM
1090 \ SM/REM DVDlo DVDhi DIVlo -- r3 q4 symmetric signed div
1093 MOV @PSP,T \ T=DVD_sign==>rem_sign
1094 CMP #0,TOS \ n2 >= 0 ?
1097 ADD #1,TOS \ -- d1 u2
1099 CMP #0,0(PSP) \ d1hi >= 0 ?
1101 XOR #-1,2(PSP) \ d1lo
1102 XOR #-1,0(PSP) \ d1hi
1103 ADD #1,2(PSP) \ d1lo+1
1104 ADDC #0,0(PSP) \ d1hi+C
1105 THEN \ -- uDVDlo uDVDhi uDIVlo
1106 PUSHM #3,IP \ save IP,S,T
1108 UM/MOD \ -- uREMlo uQUOTlo
1110 POPM #3,IP \ restore T,S,IP
1111 CMP #0,T \ T=rem_sign
1116 XOR S,T \ S=divisor T=quot_sign
1117 CMP #0,T \ -- n3 u4 T=quot_sign
1121 THEN \ -- n3 n4 S=divisor
1126 [UNDEFINED] FM/MOD [IF]
1127 \ https://forth-standard.org/standard/core/FMDivMOD
1128 \ FM/MOD d1 n1 -- r q floored signed div'n
1131 HI2LO \ -- remainder quotient S=divisor
1132 CMP #0,0(PSP) \ remainder <> 0 ?
1134 CMP #1,TOS \ quotient < 1 ?
1136 ADD S,0(PSP) \ add divisor to remainder
1137 SUB #1,TOS \ decrement quotient
1145 [UNDEFINED] NIP [IF]
1146 \ https://forth-standard.org/standard/core/NIP
1147 \ NIP x1 x2 -- x2 Drop the first item below the top of stack
1155 \ https://forth-standard.org/standard/core/Div
1156 \ / n1 n2 -- n3 signed quotient
1158 >R DUP 0< R> FM/MOD NIP
1162 [UNDEFINED] NEGATE [IF]
1163 \ https://forth-standard.org/standard/core/NEGATE
1164 \ C NEGATE x1 -- x2 two's complement
1172 [UNDEFINED] HERE [IF]
1178 [UNDEFINED] CHARS [IF]
1179 \ https://forth-standard.org/standard/core/CHARS
1180 \ CHARS n1 -- n2 chars->adrs units
1186 [UNDEFINED] MOVE [IF]
1187 \ https://forth-standard.org/standard/core/MOVE
1188 \ MOVE addr1 addr2 u -- smart move
1189 \ VERSION FOR 1 ADDRESS UNIT = 1 CHAR
1192 MOV @PSP+,Y \ Y = addr2 = dst
1193 MOV @PSP+,X \ X = addr1 = src
1194 MOV @PSP+,TOS \ pop new TOS
1195 CMP #0,W \ count = 0 ?
1196 0<> IF \ if 0, already done !
1197 CMP X,Y \ Y-X \ dst - src
1198 0<> IF \ else already done !
1199 U< IF \ U< if src > dst
1200 BEGIN \ copy W bytes
1205 MOV @IP+,PC \ out 1 of MOVE ====>
1206 THEN \ U>= if dst > src
1207 ADD W,Y \ copy W bytes beginning with the end
1217 MOV @IP+,PC \ out 2 of MOVE ====>
1224 \ SET THE FOLLOWING FLAG TO TRUE FOR MORE VERBOSE OUTPUT; THIS MAY
1225 \ ALLOW YOU TO TELL WHICH TEST CAUSED YOUR SYSTEM TO HANG.
1230 \ : EMPTY-STACK ( ... -- ) \ EMPTY STACK: HANDLES UNDERFLOWED STACK TOO.
1232 \ IF DUP 0< IF NEGATE 0
1234 \ ELSE 0 DO DROP LOOP THEN
1237 \ : ERROR \ ( C-ADDR U -- ) DISPLAY AN ERROR MESSAGE FOLLOWED BY
1238 \ \ THE LINE THAT HAD THE ERROR.
1239 \ TYPE SOURCE TYPE CR \ DISPLAY LINE CORRESPONDING TO ERROR
1240 \ EMPTY-STACK \ THROW AWAY EVERY THING ELSE
1241 \ QUIT \ *** Uncomment this line to QUIT on an error
1244 VARIABLE ACTUAL-DEPTH \ STACK RECORD
1245 CREATE ACTUAL-RESULTS 20 CELLS ALLOT
1247 : T{ \ ( -- ) SYNTACTIC SUGAR.
1250 : -> \ ( ... -- ) RECORD DEPTH AND CONTENT OF STACK.
1251 DEPTH DUP ACTUAL-DEPTH ! \ RECORD DEPTH
1252 ?DUP IF \ IF THERE IS SOMETHING ON STACK
1253 0 DO ACTUAL-RESULTS I CELLS + ! LOOP \ SAVE THEM
1256 : }T \ ( ... -- ) COMPARE STACK (EXPECTED) CONTENTS WITH SAVED
1257 \ (ACTUAL) CONTENTS.
1258 DEPTH ACTUAL-DEPTH @ = IF \ IF DEPTHS MATCH
1259 DEPTH ?DUP IF \ IF THERE IS SOMETHING ON THE STACK
1260 0 DO \ FOR EACH STACK ITEM
1261 ACTUAL-RESULTS I CELLS + @ \ COMPARE ACTUAL WITH EXPECTED
1262 \ = 0= IF S" INCORRECT RESULT: " ERROR LEAVE THEN \ jmt
1263 = 0= IF TRUE ABORT" INCORRECT RESULT" THEN \ jmt : abort with colorised message
1266 ELSE \ DEPTH MISMATCH
1267 \ S" WRONG NUMBER OF RESULTS: " ERROR \ jmt
1268 TRUE ABORT" WRONG NUMBER OF RESULTS" \ jmt : abort with colorised message
1271 : TESTING \ ( -- ) TALKING COMMENT.
1273 IF DUP >R TYPE CR R> >IN !
1274 ELSE >IN ! DROP [CHAR] * EMIT
1280 0 INVERT 1 RSHIFT CONSTANT MAX-INT ; %011...1
1281 0 INVERT 1 RSHIFT INVERT CONSTANT MIN-INT ; %100...0
1282 MAX-INT 2/ CONSTANT HI-INT ; %001...1
1283 MIN-INT 2/ CONSTANT LO-INT ; %110...0
1284 -1 MAX-INT 2CONSTANT MAX-2INT ; %.011...1
1285 0 MIN-INT 2CONSTANT MIN-2INT ; %.100...0
1286 MAX-2INT 2/ 2CONSTANT HI-2INT ; %.001...1
1287 MIN-2INT 2/ 2CONSTANT LO-2INT ; %.110...0
1291 ; -----------------------------------------------------------------------------
1293 ; -----------------------------------------------------------------------------
1305 T{ 1 2 2CONSTANT 2c1 -> }T
1307 T{ : cd1 2c1 ; -> }T
1310 T{ : cd2 2CONSTANT ; -> }T
1311 T{ -1 -2 cd2 2c2 -> }T
1314 T{ 4 5 2CONSTANT 2c3 IMMEDIATE 2c3 -> 4 5 }T
1315 T{ : cd6 2c3 2LITERAL ; cd6 -> 4 5 }T
1318 T{ 2VARIABLE 2v1 -> }T
1321 T{ -1 -2 2v1 2! -> }T
1322 T{ 2v1 2@ -> -1 -2 }T
1323 T{ : cd2 2VARIABLE ; -> }T
1325 T{ : cd3 2v2 2! ; -> }T
1327 T{ 2v2 2@ -> -2 -1 }T
1329 T{ 2VARIABLE 2v3 IMMEDIATE 5 6 2v3 2! -> }T
1333 T{ : cd1 [ MAX-2INT ] 2LITERAL ; -> }T
1334 T{ cd1 -> MAX-2INT }T
1335 T{ 2VARIABLE 2v4 IMMEDIATE 5 6 2v4 2! -> }T
1336 T{ : cd7 2v4 [ 2@ ] 2LITERAL ; cd7 -> 5 6 }T
1337 T{ : cd8 [ 6 7 ] 2v4 [ 2! ] ; 2v4 2@ -> 6 7 }T
1340 T{ 1 2 2VALUE t2val -> }T
1342 T{ 3 4 TO t2val -> }T
1344 : sett2val t2val 2SWAP TO t2val ;
1345 T{ 5 6 sett2val t2val -> 3 4 5 6 }T
1348 T{ 0. 5. D+ -> 5. }T \ small integers
1349 T{ -5. 0. D+ -> -5. }T
1350 T{ 1. 2. D+ -> 3. }T
1351 T{ 1. -2. D+ -> -1. }T
1352 T{ -1. 2. D+ -> 1. }T
1353 T{ -1. -2. D+ -> -3. }T
1354 T{ -1. 1. D+ -> 0. }T
1355 T{ 0 0 0 5 D+ -> 0 5 }T \ mid range integers
1356 T{ -1 5 0 0 D+ -> -1 5 }T
1357 T{ 0 0 0 -5 D+ -> 0 -5 }T
1358 T{ 0 -5 -1 0 D+ -> -1 -5 }T
1359 T{ 0 1 0 2 D+ -> 0 3 }T
1360 T{ -1 1 0 -2 D+ -> -1 -1 }T
1361 T{ 0 -1 0 2 D+ -> 0 1 }T
1362 T{ 0 -1 -1 -2 D+ -> -1 -3 }T
1363 T{ -1 -1 0 1 D+ -> -1 0 }T
1365 T{ MIN-INT 0 2DUP D+ -> 0 1 }T
1366 T{ MIN-INT S>D MIN-INT 0 D+ -> 0 0 }T
1368 T{ HI-2INT 1. D+ -> 0 HI-INT 1+ }T \ large double integers
1369 T{ HI-2INT 2DUP D+ -> 1S 1- MAX-INT }T
1370 T{ MAX-2INT MIN-2INT D+ -> -1. }T
1371 T{ MAX-2INT LO-2INT D+ -> HI-2INT }T
1372 T{ LO-2INT 2DUP D+ -> MIN-2INT }T
1373 T{ HI-2INT MIN-2INT D+ 1. D+ -> LO-2INT }T
1376 T{ 0. 5. D- -> -5. }T \ small integers
1377 T{ 5. 0. D- -> 5. }T
1378 T{ 0. -5. D- -> 5. }T
1379 T{ 1. 2. D- -> -1. }T
1380 T{ 1. -2. D- -> 3. }T
1381 T{ -1. 2. D- -> -3. }T
1382 T{ -1. -2. D- -> 1. }T
1383 T{ -1. -1. D- -> 0. }T
1384 T{ 0 0 0 5 D- -> 0 -5 }T \ mid-range integers
1385 T{ -1 5 0 0 D- -> -1 5 }T
1386 T{ 0 0 -1 -5 D- -> 1 4 }T
1387 T{ 0 -5 0 0 D- -> 0 -5 }T
1388 T{ -1 1 0 2 D- -> -1 -1 }T
1389 T{ 0 1 -1 -2 D- -> 1 2 }T
1390 T{ 0 -1 0 2 D- -> 0 -3 }T
1391 T{ 0 -1 0 -2 D- -> 0 1 }T
1392 T{ 0 0 0 1 D- -> 0 -1 }T
1393 T{ MIN-INT 0 2DUP D- -> 0. }T
1394 T{ MIN-INT S>D MAX-INT 0 D- -> 1 1S }T
1395 T{ MAX-2INT max-2INT D- -> 0. }T \ large integers
1396 T{ MIN-2INT min-2INT D- -> 0. }T
1397 T{ MAX-2INT hi-2INT D- -> lo-2INT DNEGATE }T
1398 T{ HI-2INT lo-2INT D- -> max-2INT }T
1399 T{ LO-2INT hi-2INT D- -> min-2INT 1. D+ }T
1400 T{ MIN-2INT min-2INT D- -> 0. }T
1401 T{ MIN-2INT lo-2INT D- -> lo-2INT }T
1404 T{ 0. D0< -> <FALSE> }T
1405 T{ 1. D0< -> <FALSE> }T
1406 T{ MIN-INT 0 D0< -> <FALSE> }T
1407 T{ 0 MAX-INT D0< -> <FALSE> }T
1408 T{ MAX-2INT D0< -> <FALSE> }T
1409 T{ -1. D0< -> <TRUE> }T
1410 T{ MIN-2INT D0< -> <TRUE> }T
1413 T{ 1. D0= -> <FALSE> }T
1414 T{ MIN-INT 0 D0= -> <FALSE> }T
1415 T{ MAX-2INT D0= -> <FALSE> }T
1416 T{ -1 MAX-INT D0= -> <FALSE> }T
1417 T{ 0. D0= -> <TRUE> }T
1418 T{ -1. D0= -> <FALSE> }T
1419 T{ 0 MIN-INT D0= -> <FALSE> }T
1422 T{ 0. D2* -> 0. D2* }T
1423 T{ MIN-INT 0 D2* -> 0 1 }T
1424 T{ HI-2INT D2* -> MAX-2INT 1. D- }T
1425 T{ LO-2INT D2* -> MIN-2INT }T
1430 T{ 0 1 D2/ -> MIN-INT 0 }T
1431 T{ MAX-2INT D2/ -> HI-2INT }T
1432 T{ -1. D2/ -> -1. }T
1433 T{ MIN-2INT D2/ -> LO-2INT }T
1436 T{ 0. 1. D< -> <TRUE> }T
1437 T{ 0. 0. D< -> <FALSE> }T
1438 T{ 1. 0. D< -> <FALSE> }T
1439 T{ -1. 1. D< -> <TRUE> }T
1440 T{ -1. 0. D< -> <TRUE> }T
1441 T{ -2. -1. D< -> <TRUE> }T
1442 T{ -1. -2. D< -> <FALSE> }T
1443 T{ -1. MAX-2INT D< -> <TRUE> }T
1444 T{ MIN-2INT MAX-2INT D< -> <TRUE> }T
1445 T{ MAX-2INT -1. D< -> <FALSE> }T
1446 T{ MAX-2INT MIN-2INT D< -> <FALSE> }T
1447 T{ MAX-2INT 2DUP -1. D+ D< -> <FALSE> }T
1448 T{ MIN-2INT 2DUP 1. D+ D< -> <TRUE> }T
1451 T{ -1. -1. D= -> <TRUE> }T
1452 T{ -1. 0. D= -> <FALSE> }T
1453 T{ -1. 1. D= -> <FALSE> }T
1454 T{ 0. -1. D= -> <FALSE> }T
1455 T{ 0. 0. D= -> <TRUE> }T
1456 T{ 0. 1. D= -> <FALSE> }T
1457 T{ 1. -1. D= -> <FALSE> }T
1458 T{ 1. 0. D= -> <FALSE> }T
1459 T{ 1. 1. D= -> <TRUE> }T
1460 T{ 0 -1 0 -1 D= -> <TRUE> }T
1461 T{ 0 -1 0 0 D= -> <FALSE> }T
1462 T{ 0 -1 0 1 D= -> <FALSE> }T
1463 T{ 0 0 0 -1 D= -> <FALSE> }T
1464 T{ 0 0 0 0 D= -> <TRUE> }T
1465 T{ 0 0 0 1 D= -> <FALSE> }T
1466 T{ 0 1 0 -1 D= -> <FALSE> }T
1467 T{ 0 1 0 0 D= -> <FALSE> }T
1468 T{ 0 1 0 1 D= -> <TRUE> }T
1470 T{ MAX-2INT MIN-2INT D= -> <FALSE> }T
1471 T{ MAX-2INT 0. D= -> <FALSE> }T
1472 T{ MAX-2INT MAX-2INT D= -> <TRUE> }T
1473 T{ MAX-2INT HI-2INT D= -> <FALSE> }T
1474 T{ MAX-2INT MIN-2INT D= -> <FALSE> }T
1475 T{ MIN-2INT MIN-2INT D= -> <TRUE> }T
1476 T{ MIN-2INT LO-2INT D= -> <FALSE> }T
1477 T{ MIN-2INT MAX-2INT D= -> <FALSE> }T
1480 T{ 1234 0 D>S -> 1234 }T
1481 T{ -1234 -1 D>S -> -1234 }T
1482 T{ MAX-INT 0 D>S -> MAX-INT }T
1483 T{ MIN-INT -1 D>S -> MIN-INT }T
1488 T{ -1. DABS -> 1. }T
1489 T{ MAX-2INT DABS -> MAX-2INT }T
1490 T{ MIN-2INT 1. D+ DABS -> MAX-2INT }T
1493 T{ 1. 2. DMAX -> 2. }T
1494 T{ 1. 0. DMAX -> 1. }T
1495 T{ 1. -1. DMAX -> 1. }T
1496 T{ 1. 1. DMAX -> 1. }T
1497 T{ 0. 1. DMAX -> 1. }T
1498 T{ 0. -1. DMAX -> 0. }T
1499 T{ -1. 1. DMAX -> 1. }T
1500 T{ -1. -2. DMAX -> -1. }T
1501 T{ MAX-2INT HI-2INT DMAX -> MAX-2INT }T
1502 T{ MAX-2INT MIN-2INT DMAX -> MAX-2INT }T
1503 T{ MIN-2INT MAX-2INT DMAX -> MAX-2INT }T
1504 T{ MIN-2INT LO-2INT DMAX -> LO-2INT }T
1506 T{ MAX-2INT 1. DMAX -> MAX-2INT }T
1507 T{ MAX-2INT -1. DMAX -> MAX-2INT }T
1508 T{ MIN-2INT 1. DMAX -> 1. }T
1509 T{ MIN-2INT -1. DMAX -> -1. }T
1512 T{ 1. 2. DMIN -> 1. }T
1513 T{ 1. 0. DMIN -> 0. }T
1514 T{ 1. -1. DMIN -> -1. }T
1515 T{ 1. 1. DMIN -> 1. }T
1516 T{ 0. 1. DMIN -> 0. }T
1517 T{ 0. -1. DMIN -> -1. }T
1518 T{ -1. 1. DMIN -> -1. }T
1519 T{ -1. -2. DMIN -> -2. }T
1520 T{ MAX-2INT HI-2INT DMIN -> HI-2INT }T
1521 T{ MAX-2INT MIN-2INT DMIN -> MIN-2INT }T
1522 T{ MIN-2INT MAX-2INT DMIN -> MIN-2INT }T
1523 T{ MIN-2INT LO-2INT DMIN -> MIN-2INT }T
1525 T{ MAX-2INT 1. DMIN -> 1. }T
1526 T{ MAX-2INT -1. DMIN -> -1. }T
1527 T{ MIN-2INT 1. DMIN -> MIN-2INT }T
1528 T{ MIN-2INT -1. DMIN -> MIN-2INT }T
1531 T{ 0. DNEGATE -> 0. }T
1532 T{ 1. DNEGATE -> -1. }T
1533 T{ -1. DNEGATE -> 1. }T
1534 T{ max-2int DNEGATE -> min-2int SWAP 1+ SWAP }T
1535 T{ min-2int SWAP 1+ SWAP DNEGATE -> max-2int }T
1538 T{ 1. 2. 3. 2ROT -> 2. 3. 1. }T
1539 T{ MAX-2INT MIN-2INT 1. 2ROT -> MIN-2INT 1. MAX-2INT }T
1542 T{ 1. 1. DU< -> <FALSE> }T
1543 T{ 1. -1. DU< -> <TRUE> }T
1544 T{ -1. 1. DU< -> <FALSE> }T
1545 T{ -1. -2. DU< -> <FALSE> }T
1546 T{ MAX-2INT HI-2INT DU< -> <FALSE> }T
1547 T{ HI-2INT MAX-2INT DU< -> <TRUE> }T
1548 T{ MAX-2INT MIN-2INT DU< -> <TRUE> }T
1549 T{ MIN-2INT MAX-2INT DU< -> <FALSE> }T
1550 T{ MIN-2INT LO-2INT DU< -> <TRUE> }T
1553 T{ HI-2INT 1 M+ -> HI-2INT 1. D+ }T
1554 T{ MAX-2INT -1 M+ -> MAX-2INT -1. D+ }T
1555 T{ MIN-2INT 1 M+ -> MIN-2INT 1. D+ }T
1556 T{ LO-2INT -1 M+ -> LO-2INT -1. D+ }T
1559 : ?floored [ -3 2 / -2 = ] LITERAL IF 1. D- THEN ;
1561 T{ 5. 7 11 M*/ -> 3. }T
1562 T{ 5. -7 11 M*/ -> -3. ?floored }T
1563 T{ -5. 7 11 M*/ -> -3. ?floored }T
1564 T{ -5. -7 11 M*/ -> 3. }T
1566 T{ MAX-2INT 8 16 M*/ -> HI-2INT }T
1567 T{ MAX-2INT -8 16 M*/ -> HI-2INT DNEGATE ?floored }T
1568 T{ MIN-2INT 8 16 M*/ -> LO-2INT }T
1569 T{ MIN-2INT -8 16 M*/ -> LO-2INT DNEGATE }T
1571 T{ MAX-2INT MAX-INT MAX-INT M*/ -> MAX-2INT }T
1572 T{ MAX-2INT MAX-INT 2/ MAX-INT M*/ -> MAX-INT 1- HI-2INT NIP }T
1573 T{ MIN-2INT LO-2INT NIP DUP NEGATE M*/ -> MIN-2INT }T
1574 T{ MIN-2INT LO-2INT NIP 1- MAX-INT M*/ -> MIN-INT 3 + HI-2INT NIP 2 + }T
1575 T{ MAX-2INT LO-2INT NIP DUP NEGATE M*/ -> MAX-2INT DNEGATE }T
1576 T{ MIN-2INT MAX-INT DUP M*/ -> MIN-2INT }T
1579 MAX-2INT 71 73 M*/ 2CONSTANT dbl1
1580 MIN-2INT 73 79 M*/ 2CONSTANT dbl2
1581 : d>ascii \ ( d -- caddr u )
1582 DUP >R <# DABS #S R> SIGN #> \ ( -- caddr1 u )
1583 HERE SWAP 2DUP 2>R CHARS DUP ALLOT MOVE 2R>
1586 dbl1 d>ascii 2CONSTANT "dbl1"
1587 dbl2 d>ascii 2CONSTANT "dbl2"
1590 CR ." You should see lines duplicated:" CR
1591 5 SPACES "dbl1" TYPE CR
1593 8 SPACES "dbl1" DUP >R TYPE CR
1594 5 SPACES dbl1 R> 3 + D.R CR
1595 5 SPACES "dbl2" TYPE CR
1597 10 SPACES "dbl2" DUP >R TYPE CR
1598 5 SPACES dbl2 R> 5 + D.R CR
1601 T{ DoubleOutput -> }T