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) <2017> <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 ; ----------------------------------------------------------------------
22 ;forthMSP430FR_asm.asm
23 ; ----------------------------------------------------------------------
25 ; ----------------------------------------------------------------------
26 ; MOV(.B) #0, dst is coded as follow : MOV(.B) R3, dst ; 1 cycle, one word As=00 register mode
27 ; MOV(.B) #1, dst is coded as follow : MOV(.B) 0(R3), dst ; 2 cycles, one word AS=01 x(reg) mode
28 ; MOV(.B) #2, dst is coded as follow : MOV(.B) @R3, dst ; 2 cycles, one word AS=10 @reg mode
29 ; MOV(.B) #4, dst is coded as follow : MOV(.B) @R2, dst ; 2 cycles, one word AS=10 @reg mode
30 ; MOV(.B) #8, dst is coded as follow : MOV(.B) @R2+, dst ; 2 cycles, one word AS=11 @reg+ mode
31 ; MOV(.B) #-1,dst is coded as follow : MOV(.B) @R3+, dst ; 2 cycles, one word AS=11
32 ; MOV(.B) #xxxx,dst is coded a follow : MOV(.B) @PC+, dst ; 2 cycles, two words AS=11 @reg+ mode
33 ; MOV(.B) &EDE,&TON is coded as follow: MOV(.B) EDE(R2),TON(R2) ; (R2=0), three words AS=01, AD=1 x(reg) mode
34 ; ----------------------------------------------------------------------
36 ; PUSHM order : PSP,TOS, IP, S, T, W, X, Y, rEXIT,rDOVAR,rDOCON, rDODOES, R3, SR,RSP, PC
37 ; PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8, R7 , R6 , R5 , R4 , R3, R2, R1, R0
39 ; example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
41 ; POPM order : PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT, Y, X, W, T, S, IP,TOS,PSP
42 ; POPM order : R0, R1, R2, R3, R4 , R5 , R6 , R7 , R8, R9,R10,R11,R12,R13,R14,R15
44 ; example : POPM #6,IP pop Y,X,W,T,S,IP registers from return stack
46 ;;Z SKIP char -- addr ; skip all occurring character 'char' in input stream
47 ; FORTHWORD "SKIP" ; used by assembler to parse input stream
48 SKIP: MOV #SOURCE_LEN,Y ;
49 MOV @Y+,X ; -- char X=length
50 MOV @Y,W ; -- char X=length W=org
51 ADD W,X ; -- char X=End W=org
52 ADD &TOIN,W ; -- char X=End W=ptr
53 SKIPLOOP: CMP W,X ; -- char ptr=End ?
54 JZ SKIPEND ; -- char yes
55 CMP.B @W+,TOS ; -- char does character match?
56 JZ SKIPLOOP ; -- char yes
57 SKIPNEXT: SUB #1,W ; -- char
58 SKIPEND: MOV W,TOS ; -- addr
59 SUB @Y,W ; -- addr W=Ptr-Org=Toin
63 ; ----------------------------------------------------------------------
64 ; DTCforthMSP430FR5xxx ASSEMBLER : search argument "xxxx", IP is free
65 ; ----------------------------------------------------------------------
67 SearchARG ; separator -- n|d or abort" not found"
68 ; ----------------------------------------------------------------------
69 ; Search ARG of "#xxxx," ; <== PARAM10
70 ; Search ARG of "&xxxx," ; <== PARAM111
71 ; Search ARG of "xxxx(REG)," ; <== PARAM130
72 ; Search ARG of ",&xxxx" ; <== PARAM111 <== PARAM20
73 ; Search ARG of ",xxxx(REG)" ; <== PARAM210
74 PUSHM #2,S ; PUSHM S,T
75 ASMtoFORTH ; -- separator search word first
76 .word WORDD,FIND ; -- c-addr
77 .word QTBRAN,SearchARGW ; -- c-addr if found
79 .word QFBRAN,NotFound ; -- c-addr ABORT if not found
80 FsearchEnd .word SearchEnd ; -- value goto end if number found
81 SearchARGW FORTHtoASM ; -- xt xt = CFA
85 ADD #2,TOS ; remplace CFA by PFA for VARIABLE words
89 MOV 2(TOS),TOS ; remplace CFA by [PFA] for CONSTANT (and CREATEd) words
93 ADD #4,TOS ; leave BODY address for DOES words
94 SearchEnd POPM #2,S ; POPM T,S
97 ; ----------------------------------------------------------------------
98 ; DTCforthMSP430FR5xxx ASSEMBLER : search REG
99 ; ----------------------------------------------------------------------
101 ; compute "xxxx(REG)," ; <== PARAM130
102 ; compute ",xxxx(REG)" ; <== PARAM210
104 MOV #'(',TOS ; -- "(" as WORD separator to find xxxx of "xxxx(REG),"
105 CALL #SearchARG ; -- xxxx aborted if not found
108 MOV TOS,0(X) ; -- xxxx compile xxxx
109 MOV #')',TOS ; -- ")" prepare separator to search REG of "xxxx(REG)"
111 ; search REG of "xxxx(REG)," separator = ')' ;
112 ; search REG of ",xxxx(REG)" separator = ')' ;
113 ; search REG of "@REG," separator = ',' ; <== PARAM120
114 ; search REG of "@REG+," separator = '+' ; <== PARAM121
115 ; search REG of "REG," separator = ',' ; <== PARAM13
116 ; search REG of ",REG" separator = ' ' ; <== PARAM21
118 SearchREG PUSHM #2,S ; PUSHM S,T
119 PUSH &TOIN ; -- separator save >IN
120 ADD #1,&TOIN ; skip "R"
121 ASMtoFORTH ; search xx of Rxx
122 .word WORDD,QNUMBER ;
123 .word QFBRAN,NOTaREG; -- xxxx if Not a Number
124 FORTHtoASM ; -- c-addr number is found
125 ADD #2,RSP ; remove >IN
126 CMP #16,TOS ; -- 000R register > 15 ?
127 JHS BOUNDERROR ; yes : abort
128 JLO SearchEnd ; -- 000R Z=0 ==> found
130 NOTaREG FORTHtoASM ; -- c-addr Z=1
131 MOV @RSP+,&TOIN ; -- c-addr restore >IN
132 JMP SearchEnd ; -- c_addr Z=1 ==> not a register
135 ; ----------------------------------------------------------------------
136 ; DTCforthMSP430FR5xxx ASSEMBLER : INTERPRET FIRST OPERAND
137 ; ----------------------------------------------------------------------
139 ; PARAM1 separator -- ; parse input buffer until separator and compute first operand of opcode
140 ; sep is comma for src and space for dst .
142 PARAM1 mDOCOL ; -- sep
143 .word FBLANK,SKIP ; -- sep c-addr
144 FORTHtoASM ; -- sep c-addr
145 MOV #0,S ; -- sep c-addr reset ASMTYPE
146 MOV &DDP,T ; -- sep c-addr HERE --> OPCODEADR (opcode is preset to its address !)
147 ADD #2,&DDP ; -- sep c-addr cell allot for opcode
148 MOV.B @TOS,W ; -- sep c-addr W=first char of instruction code
149 MOV @PSP+,TOS ; -- sep W=c-addr
150 CMP.B #'#',W ; -- sep W=first char
153 ; "#" found : case of "#xxxx,"
154 PARAM10 ADD #1,&TOIN ; -- sep skip # prefix
155 CALL #SearchARG ; -- xxxx abort if not found
157 PARAM100 CMP #0,TOS ; -- xxxx = 0 ?
160 MOV #0300h,S ; -- 0 example : MOV #0,dst <=> MOV R3,dst
163 PARAM101 CMP #1,TOS ; -- xxxx = 1 ?
166 MOV #0310h,S ; -- 1 example : MOV #1,dst <=> MOV 0(R3),dst
169 PARAM102 CMP #2,TOS ; -- xxxx = 2 ?
172 MOV #0320h,S ; -- 2 ASMTYPE = 0320h example : MOV #2, <=> MOV @R3,
175 PARAM104 CMP #4,TOS ; -- xxxx = 4 ?
178 MOV #0220h,S ; -- 4 ASMTYPE = 0220h example : MOV #4, <=> MOV @SR,
181 PARAM108 CMP #8,TOS ; -- xxxx = 8 ?
184 MOV #0230h,S ; -- 8 ASMTYPE = 0230h example : MOV #8, <=> MOV @SR+,
187 PARAM10M1 CMP #-1,TOS ; -- xxxx = -1 ?
190 MOV #0330h,S ; -- -1 ASMTYPE = 0330h example : XOR #-1 <=> XOR @R3+,
193 ; case of all others "#xxxx," ; -- xxxx
194 PARAM1000 MOV #0030h,S ; -- xxxx add immediate code type : @PC+,
196 ; case of "&xxxx," ; <== PARAM110
197 ; case of ",&xxxx" ; <== PARAM20
198 StoreArg MOV &DDP,X ; -- xxxx
199 ADD #2,&DDP ; cell allot for arg
201 StoreTOS ; <== TYPE1DOES
202 MOV TOS,0(X) ; compile arg
203 ; endcase of all "&xxxx" ;
204 ; endcase of all "#xxxx" ; <== PARAM101,102,104,108,10M1
205 ; endcase of all "REG"|"@REG"|"@REG+" ; <== PARAM124
206 PARAMENDOF MOV @PSP+,TOS ; --
209 ; ------------------------------------------
211 PARAM11 CMP.B #'&',W ; -- sep
214 ; case of "&xxxx," ; -- sep search for "&xxxx,"
215 PARAM110 MOV #0210h,S ; -- sep set code type : xxxx(SR) with AS=0b01 ==> x210h (and SR=0 !)
218 ; case of ",&xxxx" ; <== PARAM20
219 PARAM111 ADD #1,&TOIN ; -- sep skip "&" prefix
220 CALL #SearchARG ; -- arg abort if not found
221 JMP StoreArg ; -- then ret
222 ; ------------------------------------------
224 PARAM12 CMP.B #'@',W ; -- sep
227 ; case of "@REG,"|"@REG+,"
228 PARAM120 MOV #0020h,S ; -- sep init ASMTYPE with indirect code type : AS=0b10
229 ADD #1,&TOIN ; -- sep skip "@" prefix
230 CALL #SearchREG ; Z = not found
231 JNZ PARAM123 ; -- value REG of "@REG," found
233 ; case of "@REG+," ; -- c-addr REG of "@REG" not found, search REG of "@REG+"
234 PARAM121 ADD #0010h,S ; change ASMTYPE from @REG to @REG+ type
235 MOV #'+',TOS ; -- "+" as WORD separator to find REG of "@REG+,"
236 CALL #SearchREG ; -- value|c-addr X = flag
239 ; case of "xxxx(REG)," ; <== PARAM130
240 ; cases of double separator: +, and ),
241 PARAM122 CMP &SOURCE_LEN,&TOIN ; test OPCODE II parameter ending by REG+ or (REG) without comma,
242 JZ PARAM123 ; i.e. >IN = SOURCE_LEN : don't skip char CR !
243 ADD #1,&TOIN ; -- 000R skip "," ready for the second operand search
246 ; case of "xxxx(REG),"
247 ; case of "@REG," ; <== PARAM120
248 ; case of "REG," ; <== PARAM13
249 PARAM123 SWPB TOS ; 000R -- 0R00 swap bytes because it's not a dst REG typeI (not a 2 ops inst.)
251 ; case of "@REG+," ; -- 0R00 (src REG typeI)
252 ; case of "xxxx(REG)," ; -- 0R00 (src REG typeI or dst REG typeII)
253 ; case of "@REG," ; -- 0R00 (src REG typeI)
254 ; case of "REG," ; -- 0R00 (src REG typeI or dst REG typeII)
258 ; case of ",REG" ; -- 000R <== PARAM21 (dst REG typeI)
259 ; case of ",xxxx(REG)" ; -- 000R <== PARAM210 (dst REG typeI)
260 PARAM124 ADD TOS,S ; -- 0R00|000R
262 ; ------------------------------------------
264 ; case of "REG,"|"xxxx(REG)," ; first, searg REG of "REG,"
265 PARAM13 CALL #SearchREG ; -- sep save >IN for second parsing (case of "xxxx(REG),")
266 JNZ PARAM123 ; -- 000R REG of "REG," found, S=ASMTYPE=0
268 ; case of "xxxx(REG)," ; -- c-addr "REG," not found
269 PARAM130 ADD #0010h,S ; AS=0b01 for indexing address
270 CALL #ComputeARGparenREG ; compile xxxx and search REG of "(REG)"
273 ; ----------------------------------------------------------------------
274 ; DTCforthMSP430FR5xxx ASSEMBLER : INTERPRET 2th OPERAND
275 ; ----------------------------------------------------------------------
277 ; PARAM2 -- ; parse input buffer until BL and compute this 2th operand
279 .word FBLANK,SKIP ; skip space(s) between "arg1," and "arg2" if any; use not S,T.
280 FORTHtoASM ; -- c-addr search for '&' of "&xxxx
282 MOV #20h,TOS ; -- " " as WORD separator to find xxxx of ",&xxxx"
283 JNE PARAM21 ; '&' not found
286 PARAM20 ADD #0082h,S ; change ASMTYPE : AD=1, dst = R2
287 JMP PARAM111 ; -- " "
288 ; ------------------------------------------
290 ; case of ",REG"|",xxxx(REG) ; -- " " first, search REG of ",REG"
291 PARAM21 CALL #SearchREG ;
292 JNZ PARAM124 ; -- 000R REG of ",REG" found
294 ; case of ",xxxx(REG) ; -- c-addr REG not found
295 PARAM210 ADD #0080h,S ; set AD=1
296 CALL #ComputeARGparenREG ; compile argument xxxx and search REG of "(REG)"
297 JMP PARAM124 ; -- 000R REG of "(REG) found
300 ; ----------------------------------------------------------------------
301 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODES TYPE 0 : zero operand f:-)
302 ; ----------------------------------------------------------------------
305 .word lit,1300h,COMMA,EXIT
307 ; ----------------------------------------------------------------------
308 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODES TYPE I : double operand
309 ; ----------------------------------------------------------------------
311 ; OPCODE(code) for TYPE I = 0bxxxx opcode I
313 ; = 0bxxxx src register
314 ; OPCODE(7) AD (dst addr type)
318 ; OPCODE(B) for TYPE I or TYPE II = 0b0 word
320 ; OPCODE(54) AS (src addr type)
321 ; OPCODE(AS) for TYPE I or OPCODE(AD) for TYPE II = 0b00 register
326 ; OPCODE(dst) for TYPE I or TYPE II = 0bxxxx dst register
327 ; ----------------------------------------------------------------------
329 ; TYPE1DOES -- PFADOES search and compute PARAM1 & PARAM2 as src and dst operands then compile instruction
330 TYPE1DOES ; -- PFADOES
331 .word lit,',' ; -- PFADOES "," char separator for PARAM1
332 .word PARAM1 ; -- PFADOES
333 .word PARAM2 ; -- PFADOES char separator (BL) included in PARAM2
334 FORTHtoASM ; -- PFADOES
335 MAKEOPCODE MOV @TOS,TOS ; -- opcode part of instruction
336 BIS S,TOS ; -- opcode opcode is complete
337 MOV T,X ; -- opcode X= OPCODEADR to compile opcode
338 JMP StoreTOS ; then EXIT
342 .word TYPE1DOES,4000h
346 .word TYPE1DOES,4040h
350 .word TYPE1DOES,5000h
354 .word TYPE1DOES,5040h
358 .word TYPE1DOES,6000h
362 .word TYPE1DOES,6040h
366 .word TYPE1DOES,7000h
370 .word TYPE1DOES,7040h
374 .word TYPE1DOES,8000h
378 .word TYPE1DOES,8040h
382 .word TYPE1DOES,9000h
386 .word TYPE1DOES,9040h
390 .word TYPE1DOES,0A000h
394 .word TYPE1DOES,0A040h
398 .word TYPE1DOES,0B000h
402 .word TYPE1DOES,0B040h
406 .word TYPE1DOES,0C000h
410 .word TYPE1DOES,0C040h
414 .word TYPE1DOES,0D000h
418 .word TYPE1DOES,0D040h
422 .word TYPE1DOES,0E000h
426 .word TYPE1DOES,0E040h
430 .word TYPE1DOES,0F000h
434 .word TYPE1DOES,0F040h
436 ; ----------------------------------------------------------------------
437 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES TYPE II : single operand
438 ; ----------------------------------------------------------------------
439 ; OPCODE(FEDCBA987) opcodeII
440 ; OPCODE(code) for TYPE II = 0bxxxxxxxxx
442 ; OPCODE(B) for TYPE I or TYPE II = 0b0 word
444 ; OPCODE(54) (dst addr type)
445 ; OPCODE(AS) for TYPE I or OPCODE(AD) for TYPE II = 0b00 register
450 ; OPCODE(dst) for TYPE I or TYPE II = 0bxxxx dst register
451 ; ----------------------------------------------------------------------
453 ; TYPE2DOES -- PFADOES search and compute PARAM1 as dst operand then compile instruction
454 TYPE2DOES ; -- PFADOES
455 .word FBLANK ; char separator for PARAM1
457 FORTHtoASM ; -- PFADOES
459 AND #0070h,S ; keep B/W & AS infos in ASMTYPE
460 SWPB W ; (REG org --> REG dst)
461 AND #000Fh,W ; keep REG
462 BIS_ASMTYPE BIS W,S ; -- PFADOES add it in ASMTYPE
463 JMP MAKEOPCODE ; -- then end
465 asmword "RRC" ; Rotate Right through Carry ( word)
467 .word TYPE2DOES,1000h
469 asmword "RRC.B" ; Rotate Right through Carry ( byte)
471 .word TYPE2DOES,1040h
473 asmword "SWPB" ; Swap bytes
475 .word TYPE2DOES,1080h
479 .word TYPE2DOES,1100h
483 .word TYPE2DOES,1140h
487 .word TYPE2DOES,1180h
491 .word TYPE2DOES,1200h
495 .word TYPE2DOES,1240h
499 .word TYPE2DOES,1280h
502 BOUNDERRWM1 ADD #1,W ; <== RRAM|RRUM|RRCM|RLAM error
503 BOUNDERRORW MOV W,TOS ; <== PUSHM|POPM|ASM_branch error
504 BOUNDERROR ; <== REG number error
505 mDOCOL ; -- n n = value out of bounds
507 .byte 13,"out of bounds"
510 ; --------------------------------------------------------------------------------
511 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES TYPE III : PUSHM|POPM|RLAM|RRAM|RRUM|RRCM
512 ; --------------------------------------------------------------------------------
513 ; PUSHM, syntax: PUSHM #n,REG with 0 < n < 17
514 ; POPM syntax: POPM #n,REG with 0 < n < 17
517 ; PUSHM order : PSP,TOS, IP, S, T, W, X, Y, rEXIT,rDOVAR,rDOCON, rDODOES, R3, SR,RSP, PC
518 ; PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8, R7 , R6 , R5 , R4 , R3, R2, R1, R0
520 ; example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
522 ; POPM order : PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT, Y, X, W, T, S, IP,TOS,PSP
523 ; POPM order : R0, R1, R2, R3, R4 , R5 , R6 , R7 , R8, R9,R10,R11,R12,R13,R14,R15
525 ; example : POPM #6,IP pulls Y,X,W,T,S,IP registers from return stack
527 ; RxxM syntax: RxxM #n,REG with 0 < n < 5
529 ; TYPE3DOES -- PFADOES parse input stream to search : " #N, REG " as operands of RLAM|RRAM|RRUM|RRCM
530 TYPE3DOES ; -- PFADOES
531 .word FBLANK,SKIP ; skip spaces if any
532 FORTHtoASM ; -- PFADOES c-addr
533 MOV #0,S ; init ASMTYPE=0
534 MOV &DDP,T ; init OPCODEADR=DP
535 ADD #2,&DDP ; make room for opcode
536 ADD #1,&TOIN ; skip "#"
537 MOV #',',TOS ; -- PFADOES ","
538 PUSHM #2,S ; PUSHM S,T
541 .word QFBRAN,NotFound ; ABORT
545 .word PARAM2 ; -- PFADOES 0x000N S=ASMTYPE = 0x000R
547 MOV TOS,W ; -- PFADOES n W = n
548 MOV @PSP+,TOS ; -- PFADOES
549 SUB #1,W ; W = n floored to 0
551 MOV @TOS,X ; X=OPCODE
552 RLAM #4,X ; OPCODE bit 1000h --> C
554 PxxxINSTRU MOV S,Y ; S=REG, Y=REG to test
555 RLAM #3,X ; OPCODE bit 0200h --> C
556 JNC PUSHMINSTRU ; W=n-1 Y=REG
557 POPMINSTRU SUB W,S ; to make POPM opcode, compute first REG to POP; TI is complicated....
558 PUSHMINSTRU SUB W,Y ; Y=REG-(n-1)
560 JHS BOUNDERRWM1 ; JC=JHS (U>=)
561 RLAM #4,W ; W = n << 4
562 JMP BIS_ASMTYPE ; PFADOES --
563 RxxMINSTRU CMP #4,W ;
564 JHS BOUNDERRWM1 ; JC=JHS (U>=)
565 SWPB W ; -- PFADOES W = n << 8
566 RLAM #2,W ; W = N << 10
567 JMP BIS_ASMTYPE ; PFADOES --
571 .word TYPE3DOES,0050h
575 .word TYPE3DOES,0150h
579 .word TYPE3DOES,0250h
583 .word TYPE3DOES,0350h
587 .word TYPE3DOES,1500h
591 .word TYPE3DOES,1700h
593 ; ----------------------------------------------------------------------
594 ; DTCforthMSP430FR5xxx ASSEMBLER, CONDITIONAL BRANCHS
595 ; ----------------------------------------------------------------------
596 ; ASSEMBLER FORTH OPCODE(FEDC)
597 ; OPCODE(code) for TYPE JNE,JNZ 0<>, <> = 0x20xx + (offset AND 3FF) ; branch if Z = 0
598 ; OPCODE(code) for TYPE JEQ,JZ 0=, = = 0x24xx + (offset AND 3FF) ; branch if Z = 1
599 ; OPCODE(code) for TYPE JNC,JLO U< = 0x28xx + (offset AND 3FF) ; branch if C = 0
600 ; OPCODE(code) for TYPE JC,JHS U>= = 0x2Cxx + (offset AND 3FF) ; branch if C = 1
601 ; OPCODE(code) for TYPE JN 0< = 0x30xx + (offset AND 3FF) ; branch if N = 1
602 ; OPCODE(code) for TYPE JGE >= = 0x34xx + (offset AND 3FF) ; branch if (N xor V) = 0
603 ; OPCODE(code) for TYPE JL < = 0x38xx + (offset AND 3FF) ; branch if (N xor V) = 1
604 ; OPCODE(code) for TYPE JMP = 0x3Cxx + (offset AND 3FF)
606 CODE_JMP mDOCON ; branch always
609 asmword "S>=" ; if >= assertion (opposite of jump if < )
613 asmword "S<" ; if < assertion
617 asmword "0>=" ; if 0>= assertion ; use only with IF UNTIL WHILE !
621 asmword "0<" ; jump if 0< ; use only with ?JMP ?GOTO !
625 asmword "U<" ; if U< assertion
629 asmword "U>=" ; if U>= assertion
633 asmword "0<>" ; if <>0 assertion
637 asmword "0=" ; if =0 assertion
641 ;ASM IF OPCODE -- @OPCODE1
644 MOV TOS,0(W) ; compile incomplete opcode
649 ;ASM THEN @OPCODE -- resolve forward branch
651 ASM_THEN MOV &DDP,W ; -- @OPCODE W=dst
652 MOV TOS,Y ; Y=@OPCODE
653 ASM_THEN1 MOV @PSP+,TOS ; --
655 ADD #2,X ; -- Y=@OPCODE W=dst X=src+2
656 SUB X,W ; -- Y=@OPCODE W=dst-src+2=displacement*2 (bytes)
657 RRA W ; -- Y=@OPCODE W=displacement (words)
659 JC BOUNDERRORW ; (JHS) unsigned branch if u> 511
660 BIS W,0(Y) ; -- [@OPCODE]=OPCODE completed
663 ;C ELSE @OPCODE1 -- @OPCODE2 branch for IF..ELSE
665 ASM_ELSE MOV &DDP,W ; -- W=HERE
666 MOV #3C00h,0(W) ; compile unconditionnal branch
667 ADD #2,&DDP ; -- DP+2
669 MOV W,0(PSP) ; -- @OPCODE2 @OPCODE1
670 JMP ASM_THEN ; -- @OPCODE2
672 ;C BEGIN -- @BEGIN same as FORTH counterpart
674 ;C UNTIL @BEGIN OPCODE -- resolve conditional backward branch
676 ASM_UNTIL MOV @PSP+,W ; -- OPCODE W=dst
679 MOV &DDP,X ; -- Y=OPCODE X=HERE W=dst
680 SUB #2,W ; -- Y=OPCODE X=HERE W=dst-2
681 SUB X,W ; -- Y=OPCODE X=src W=src-dst-2=displacement (bytes)
682 RRA W ; -- Y=OPCODE X=HERE W=displacement (words)
684 JL BOUNDERRORW ; signed branch if < -512
685 AND #3FFh,W ; -- Y=OPCODE X=HERE W=troncated negative displacement (words)
686 BIS W,Y ; -- Y=OPCODE (completed)
691 ;X AGAIN @BEGIN -- uncond'l backward branch
692 ; unconditional backward branch
694 ASM_AGAIN mDOCOL ; -- @BEGIN
695 .word CODE_JMP ; -- @BEGIN opcode
699 ;C WHILE @BEGIN OPCODE -- @WHILE @BEGIN
701 ASM_WHILE mDOCOL ; -- @BEGIN OPCODE
702 .word ASM_IF ; -- @BEGIN @WHILE
703 .word SWAP ; -- @WHILE @BEGIN
706 ;C REPEAT @WHILE @BEGIN -- resolve WHILE loop
708 ASM_REPEAT mDOCOL ; -- @WHILE @BEGIN
709 .word CODE_JMP ; -- @WHILE @BEGIN opcode
710 .word ASM_UNTIL ; -- @WHILE
714 ; ------------------------------------------------------------------------------------------
715 ; DTCforthMSP430FR5xxx ASSEMBLER : branch up to 3 backward labels and up to 3 forward labels
716 ; ------------------------------------------------------------------------------------------
717 ; used for non canonical branchs, as BASIC language: "goto line x"
718 ; when a branch to label is resolved, it's ready for new use
724 MOV TOS,Y ; Y = ASMBWx
726 MOV @Y,W ; W = [ASMBWx]
728 MOV #0,0(Y) ; clear [ASMBWx] for next use
732 MOV &DDP,0(Y) ; [ASMBWx] = DDP
739 .word ASMBW1 ; in RAM
745 .word ASMBW2 ; in RAM
751 .word ASMBW3 ; in RAM
758 MOV @TOS,Y ; Y=[ASMFWx]
759 CMP #0,Y ; ASMFWx = 0 ? (FWx is free?)
760 MOV #0,0(TOS) ; clear [ASMFWx] for next use
761 FORWUSE ; PFA -- @OPCODE
763 FORWSET ; OPCODE PFA --
764 MOV @PSP+,0(W) ; -- PFA compile incomplete opcode
765 ADD #2,&DDP ; increment DDP
766 MOV W,0(TOS) ; store @OPCODE into ASMFWx
775 .word ASMFW1 ; in RAM
781 .word ASMFW2 ; in RAM
787 .word ASMFW3 ; in RAM
790 ; invert FORTH conditionnal branch FORTH_JMP_OPCODE -- LABEL_JMP_OPCODE
791 INVJMP CMP #3000h,TOS
792 JZ INVJMPEND ; case of JN, do nothing
793 XOR #0400h,TOS ; case of: JNZ<-->JZ JNC<-->JC JL<-->JGE
794 BIT #1000h,TOS ; 3xxxh case ?
796 XOR #0800h,TOS ; complementary action for JL<-->JGE
799 ;ASM GOTO <label> -- unconditionnal branch to label
802 .word CODE_JMP,TICK ; -- OPCODE CFA<label>
805 ;ASM <cond> ?GOTO <label> OPCODE -- conditionnal branch to label
808 .word INVJMP,TICK ; -- OPCODE CFA<label>
811 ; ----------------------------------------------------------------
812 ; DTCforthMSP430FR5xxx ASSEMBLER : branch to a previous definition
813 ; ----------------------------------------------------------------
815 ;ASM JMP <word> ; -- unconditionnal branch to a previous definition
818 .word TICK ; -- @BACKWARD
822 ;ASM <cond> ?JMP <word> ; OPCODE -- conditionnal branch to a previous definition
825 .word INVJMP,TICK,SWAP ;