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/>.
21 FORTHWORD "{CORE_COMP}"
24 ;https://forth-standard.org/standard/core/SPACE
25 ;C SPACE -- output a space
32 ;https://forth-standard.org/standard/core/SPACES
33 ;C SPACES n -- output n spaces
43 JNZ SPACE ;25~ ==> 27~ by space ==> 2.963 MBds @ 8 MHz
45 SPACESNEXT2 MOV @PSP+,TOS ; -- drop n
50 ;https://forth-standard.org/standard/core/UMTimes
51 ;C UM* u1 u2 -- ud unsigned 16x16->32 mult.
53 UMSTAR MOV @PSP,&MPY ; Load 1st operand
54 MOV TOS,&OP2 ; Load 2nd operand
55 MOV &RES0,0(PSP) ; low result on stack
56 MOV &RES1,TOS ; high result in TOS
59 ;https://forth-standard.org/standard/core/MTimes
60 ;C M* n1 n2 -- dlo dhi signed 16*16->32 multiply
70 ;https://forth-standard.org/standard/core/MTimes
71 ;C M* n1 n2 -- dlo dhi signed 16*16->32 multiply
73 MSTAR MOV TOS,S ; TOS= n2
74 XOR @PSP,S ; S contains sign of result
75 CMP #0,0(PSP) ; n1 > -1 ?
77 XOR #-1,0(PSP) ; no : n1 --> u1
79 u1n2MSTAR CMP #0,TOS ; n2 <= -1 ?
81 XOR #-1,TOS ; y: n2 --> u2
83 u1u2MSTAR PUSHM #2,IP ; PUSHM IP,S
85 .word UMSTAR ; UMSTAR use S,T,W,X,Y
87 POPM #2,IP ; POPM S,IP
88 CMP #0,S ; result > -1 ?
90 XOR #-1,0(PSP) ; no : ud --> d
98 ;https://forth-standard.org/standard/core/UMDivMOD
99 ; UM/MOD udlo|udhi u1 -- r q unsigned 32/16->r16 q16
101 UMSLASHMOD PUSH #DROP ;3 as return address for MU/MOD
104 ;https://forth-standard.org/standard/core/SMDivREM
105 ;C SM/REM d1lo d1hi n2 -- n3 n4 symmetric signed div
107 SMSLASHREM MOV TOS,S ;1 S=divisor
108 MOV @PSP,T ;2 T=rem_sign
109 CMP #0,TOS ;1 n2 >= 0 ?
110 JGE d1u2SMSLASHREM ;2 yes
113 d1u2SMSLASHREM ; -- d1 u2
114 CMP #0,0(PSP) ;3 d1hi >= 0 ?
115 JGE ud1u2SMSLASHREM ;2 yes
116 XOR #-1,2(PSP) ;4 d1lo
117 XOR #-1,0(PSP) ;4 d1hi
118 ADD #1,2(PSP) ;4 d1lo+1
119 ADDC #0,0(PSP) ;4 d1hi+C
120 ud1u2SMSLASHREM ; -- ud1 u2
121 PUSHM #2,S ;4 PUSHM S,T
124 POPM #2,S ;4 POPM T,S
125 CMP #0,T ;1 -- ur uq T=rem_sign>=0?
126 JGE SMSLASHREMnruq ;2 yes
130 XOR S,T ;1 S=divisor T=quot_sign
131 CMP #0,T ;1 -- nr uq T=quot_sign>=0?
132 JGE SMSLASHREMnrnq ;2 yes
135 SMSLASHREMnrnq ; -- nr nq S=divisor
136 MOV @IP+,PC ;4 34 words
138 ;https://forth-standard.org/standard/core/FMDivMOD
139 ;C FM/MOD d1 n1 -- r q floored signed div'n
144 FMSLASHMOD1 .word $+2 ; -- remainder quotient S=divisor
147 CMP #1,TOS ; quotient < 1 ?
149 QUOTLESSONE ADD S,0(PSP) ; add divisor to remainder
150 SUB #1,TOS ; decrement quotient
155 ;https://forth-standard.org/standard/core/NEGATE
156 ;C NEGATE x1 -- x2 two's complement
160 ;https://forth-standard.org/standard/core/ABS
161 ;C ABS n1 -- +n2 absolute value
167 ;https://forth-standard.org/standard/core/Times
168 ;C * n1 n2 -- n3 signed multiply
171 .word MSTAR,DROP,EXIT
173 ;https://forth-standard.org/standard/core/DivMOD
174 ;C /MOD n1 n2 -- n3 n4 signed divide/rem'dr
177 .word TOR,STOD,RFROM,FMSLASHMOD,EXIT
179 ;https://forth-standard.org/standard/core/Div
180 ;C / n1 n2 -- n3 signed divide
183 .word TOR,STOD,RFROM,FMSLASHMOD,NIP,EXIT
185 ;https://forth-standard.org/standard/core/MOD
186 ;C MOD n1 n2 -- n3 signed remainder
189 .word TOR,STOD,RFROM,FMSLASHMOD,DROP,EXIT
191 ;https://forth-standard.org/standard/core/TimesDivMOD
192 ;C */MOD n1 n2 n3 -- n4 n5 n1*n2/n3, rem"
195 .word TOR,MSTAR,RFROM,FMSLASHMOD,EXIT
197 ;https://forth-standard.org/standard/core/TimesDiv
198 ;C */ n1 n2 n3 -- n4 n1*n2/n3
201 .word TOR,MSTAR,RFROM,FMSLASHMOD,NIP,EXIT
205 ;https://forth-standard.org/standard/core/ALIGNED
206 ;C ALIGNED addr -- a-addr align given addr
212 ;https://forth-standard.org/standard/core/ALIGN
213 ;C ALIGN -- align HERE
215 ALIGNN BIT #1,&DDP ; 3
219 ;https://forth-standard.org/standard/core/CHARS
220 ;C CHARS n1 -- n2 chars->adrs units
224 ;https://forth-standard.org/standard/core/CHARPlus
225 ;C CHAR+ c-addr1 -- c-addr2 add char size
230 ;https://forth-standard.org/standard/core/CELLS
231 ;C CELLS n1 -- n2 cells->adrs units
236 ;https://forth-standard.org/standard/core/CELLPlus
237 ;C CELL+ a-addr1 -- a-addr2 add cell size
242 ;----------------------------------------------------------------------
244 ;----------------------------------------------------------------------
246 ; https://forth-standard.org/standard/core/StoD
247 ; S>D n -- d single -> double prec.
253 ; https://forth-standard.org/standard/core/TwoFetch
254 ; 2@ a-addr -- x1 x2 fetch 2 cells ; the lower address will appear on top of stack
261 ; https://forth-standard.org/standard/core/TwoStore
262 ; 2! x1 x2 a-addr -- store 2 cells ; the top of stack is stored at the lower adr
264 TWOSTORE MOV @PSP+,0(TOS)
269 ;; https://forth-standard.org/standard/double/TwoVALUE
273 ; .word COMMA,COMMA ; compile hi then lo
282 ; https://forth-standard.org/standard/core/TwoDROP
283 ; 2DROP x1 x2 -- drop 2 cells
289 ; https://forth-standard.org/standard/core/TwoSWAP
290 ; 2SWAP x1 x2 x3 x4 -- x3 x4 x1 x2
292 MOV @PSP,W ; -- x1 x2 x3 x4 W=x3
293 MOV 4(PSP),0(PSP) ; -- x1 x2 x1 x4
294 MOV W,4(PSP) ; -- x3 x2 x1 x4
295 MOV TOS,W ; -- x3 x2 x1 x4 W=x4
296 MOV 2(PSP),TOS ; -- x3 x2 x1 x2 W=x4
297 MOV W,2(PSP) ; -- x3 x4 x1 x2
300 ; https://forth-standard.org/standard/core/TwoOVER
301 ; 2OVER x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2
303 SUB #4,PSP ; -- x1 x2 x3 x x x4
304 MOV TOS,2(PSP) ; -- x1 x2 x3 x4 x x4
305 MOV 8(PSP),0(PSP) ; -- x1 x2 x3 x4 x1 x4
306 MOV 6(PSP),TOS ; -- x1 x2 x3 x4 x1 x2
309 ;https://forth-standard.org/standard/core/CFetch
310 ; C@ c-addr -- char fetch char from memory
312 CFETCH MOV.B @TOS,TOS ;2
315 ;https://forth-standard.org/standard/core/CStore
316 ; C! char c-addr -- store char in memory
318 CSTORE MOV.B @PSP+,0(TOS) ;4
323 ;https://forth-standard.org/standard/core/CComma
324 ; C, char -- append char
332 ;https://forth-standard.org/standard/core/AND
333 ;C AND x1 x2 -- x3 logical AND
338 ;https://forth-standard.org/standard/core/OR
339 ;C OR x1 x2 -- x3 logical OR
344 ;https://forth-standard.org/standard/core/XOR
345 ;C XOR x1 x2 -- x3 logical XOR
350 ;https://forth-standard.org/standard/core/INVERT
351 ;C INVERT x1 -- x2 bitwise inversion
356 ;https://forth-standard.org/standard/core/LSHIFT
357 ;C LSHIFT x1 u -- x2 logical L shift u places
360 AND #1Fh,TOS ; no need to shift more than 16
368 ;https://forth-standard.org/standard/core/RSHIFT
369 ;C RSHIFT x1 u -- x2 logical R shift u places
372 AND #1Fh,TOS ; no need to shift more than 16
374 RSH_1 BIC #1,SR ; CLRC
381 ;https://forth-standard.org/standard/core/TwoTimes
382 ;C 2* x1 -- x2 arithmetic left shift
387 ;https://forth-standard.org/standard/core/TwoDiv
388 ;C 2/ x1 -- x2 arithmetic right shift
393 ;https://forth-standard.org/standard/core/MAX
394 ;C MAX n1 n2 -- n3 signed maximum
396 MAX CMP @PSP,TOS ; n2-n1
401 ;https://forth-standard.org/standard/core/MIN
402 ;C MIN n1 n2 -- n3 signed minimum
404 MIN CMP @PSP,TOS ; n2-n1
409 ;https://forth-standard.org/standard/core/PlusStore
410 ;C +! n/u a-addr -- add to memory
412 PLUSSTORE ADD @PSP+,0(TOS)
416 ;https://forth-standard.org/standard/core/CHAR
417 ;C CHAR -- char parse ASCII character
420 .word FBLANK,WORDD,ONEPLUS,CFETCH,EXIT
422 ;https://forth-standard.org/standard/core/BracketCHAR
423 ;C [CHAR] -- compile character literal
424 FORTHWORDIMM "[CHAR]" ; immediate
430 ;https://forth-standard.org/standard/core/FILL
431 ;C FILL c-addr u char -- fill memory with char
433 FILL MOV @PSP+,X ; count
434 MOV @PSP+,W ; address
437 FILL_1 MOV.B TOS,0(W) ; store char in memory
441 FILL_X MOV @PSP+,TOS ; pop new TOS
444 ;https://forth-standard.org/standard/core/HEX
449 ;https://forth-standard.org/standard/core/DECIMAL
451 DECIMAL MOV #10,&BASE
454 ; https://forth-standard.org/standard/core/HERE
455 ; HERE -- addr returns memory ptr
459 ;https://forth-standard.org/standard/core/p
460 ;C ( \ -- paren ; skip input until )
461 FORTHWORDIMM "\40" ; immediate
463 .word lit,')',WORDD,DROP,EXIT
465 ;https://forth-standard.org/standard/core/Dotp
466 ; .( \ -- dotparen ; type comment immediatly.
467 FORTHWORDIMM ".\40" ; immediate
468 DOTPAREN MOV #0,&CAPS
472 .word FBLANK,LIT,CAPS,STORE
475 ;https://forth-standard.org/standard/core/J
476 ;C J -- n R: 4*sys -- 4*sys
477 ;C get the second loop index
479 JJ SUB #2,PSP ; make room in TOS
481 MOV 4(RSP),TOS ; index = loopctr - fudge
485 ;https://forth-standard.org/standard/core/UNLOOP
486 ;UNLOOP -- R: sys1 sys2 -- drop loop parms
491 ;https://forth-standard.org/standard/core/LEAVE
492 ;C LEAVE -- L: -- adrs
493 FORTHWORDIMM "LEAVE" ; immediate
494 LEAV MOV &DDP,W ; compile three words
495 MOV #UNLOOP,0(W) ; [HERE] = UNLOOP
496 MOV #BRAN,2(W) ; [HERE+2] = BRAN
497 ADD #6,&DDP ; [HERE+4] = After LOOP adr
501 MOV W,0(X) ; leave HERE+4 on LEAVEPTR stack
504 ;https://forth-standard.org/standard/core/RECURSE
505 ;C RECURSE -- recurse to current definition (compile current definition)
506 FORTHWORDIMM "RECURSE" ; immediate
512 ; https://forth-standard.org/standard/core/toBODY
513 ; >BODY -- addr leave BODY of a CREATEd word; also leave default ACTION-OF primary DEFERred word
518 ;https://forth-standard.org/standard/core/SOURCE
519 ;C SOURCE -- adr u of current input buffer
524 MOV &SOURCE_ORG,0(PSP)
527 ;https://forth-standard.org/standard/core/BASE
528 ;C BASE -- a-addr holds conversion radix
531 .word BASE ; VARIABLE address in RAM space
533 ;https://forth-standard.org/standard/core/toIN
534 ;C >IN -- a-addr holds offset in input stream
537 .word TOIN ; VARIABLE address in RAM space
539 ;https://forth-standard.org/standard/core/PAD
545 ; https://forth-standard.org/standard/core/MARKER
547 ;( "<spaces>name" -- )
548 ;Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
549 ;with the execution semantics defined below.
551 ;name Execution: ( -- )
552 ;Restore all dictionary allocation and search order pointers to the state they had just prior to the
553 ;definition of name. Remove the definition of name and all subsequent definitions. Restoration
554 ;of any structures still existing that could refer to deleted definitions or deallocated data space is
555 ;not necessarily provided. No other contextual information such as numeric base is affected
557 MARKER_DOES .word $+2 ; execution part
558 MOV @RSP+,IP ; -- PFA
559 MOV @TOS+,&INIVOC ; set VOC_LINK value for RST_STATE
560 MOV @TOS,&INIDP ; set DP value for RST_STATE
562 MOV #RST_STATE,PC ; execute RST_STATE, PWR_STATE then STATE_DOES
564 FORTHWORD "MARKER" ; definition part
565 CALL #HEADER ;4 W = DP+4
566 MOV #DODOES,-4(W) ;4 CFA = DODOES
567 MOV #MARKER_DOES,-2(W) ;4 PFA = MARKER_DOES
568 MOV &LASTVOC,0(W) ;5 [BODY] = VOCLINK to be restored
570 MOV Y,2(W) ;3 [BODY+2] = LFA = DP to be restored