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_EXTD_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
47 ;;Z SKIP char -- addr ; skip all occurring character 'char' in input stream
48 ; FORTHWORD "SKIP" ; used by assembler to parse input stream
49 SKIP: MOV #SOURCE_LEN,Y ;
50 MOV @Y+,X ; -- char X=length
51 MOV @Y,W ; -- char X=length W=org
52 ADD W,X ; -- char X=End W=org
53 ADD &TOIN,W ; -- char X=End W=ptr
54 SKIPLOOP: CMP W,X ; -- char ptr=End ?
55 JZ SKIPEND ; -- char yes
56 CMP.B @W+,TOS ; -- char does character match?
57 JZ SKIPLOOP ; -- char yes
58 SKIPNEXT: SUB #1,W ; -- char
59 SKIPEND: MOV W,TOS ; -- addr
60 SUB @Y,W ; -- addr W=Ptr-Org=Toin
64 ; https://forth-standard.org/standard/double/TwoCONSTANT
65 ; udlo/dlo/Flo udhi/dhi/Qhi -- create a double or a Q15.16 CONSTANT
70 .word COMMA,COMMA ; compile udhi/dhi/Qhi then udlo/dlo/Qlo
72 PFA2CTE FORTHtoASM ; equ 2@
78 ; https://forth-standard.org/standard/double/TwoVARIABLE
86 ; ----------------------------------------------------------------------
87 ; DTCforthMSP430FR5xxx ASSEMBLER : search argument "xxxx", IP is free
88 ; ----------------------------------------------------------------------
90 SearchARG ; separator -- n|d or abort" not found"
91 ; ----------------------------------------------------------------------
92 ; Search ARG of "#xxxx," ; <== PARAM10
93 ; Search ARG of "&xxxx," ; <== PARAM111
94 ; Search ARG of "xxxx(REG)," ; <== PARAM130
95 ; Search ARG of ",&xxxx" ; <== PARAM111 <== PARAM20
96 ; Search ARG of ",xxxx(REG)" ; <== PARAM210
97 PUSHM #2,S ; PUSHM S,T
98 ASMtoFORTH ; -- separator search word first
99 .word WORDD,FIND ; -- addr
100 .word QTBRAN,SearchARGW ; -- addr if word found
102 .word QFBRAN,NotFound ; -- addr ABORT if not found
103 FSearchEnd .word SearchEnd ; -- value goto SearchEnd if number found
104 SearchARGW FORTHtoASM ; -- xt xt = CFA
108 ADD #2,TOS ; -- PFA remplace CFA by PFA for VARIABLE words
112 MOV 2(TOS),TOS ; -- cte remplace CFA by [PFA] for CONSTANT (and CREATEd) words
114 QDODOES CMP #DODOES,X
116 ADD #4,TOS ; -- BODY leave BODY address for DOES words
117 CMP #PFA2CTE,2(X) ; PFA = 2CONSTANT DOES ?
119 CMP #PFA2VAR,2(X) ; PFA = 2VARIABLE DOES ?
121 DOESDOUBLE CALL #PFA2CTE+2 ; -- Lo Hi 2@
123 SearchEnd POPM #2,S ; POPM T,S
126 ; Arg_Double_to_single conversion needed only for OPCODE type V|VI, 2th pass.
127 ARGD2S BIT #UF9,SR ; -- Lo Hi
129 MOV @PSP+,TOS ; -- Lo skip hi
132 ; ----------------------------------------------------------------------
133 ; DTCforthMSP430FR5xxx ASSEMBLER : search REG
134 ; ----------------------------------------------------------------------
136 ; compile $xxxx of $xxxx(REG) then SearchREG
137 ; ----------------------------------------------------------------------
138 ComputeARGParenREG ; sep -- Rn
139 ; compute REG of "xxxx(REG)," ; <== PARAM130, sep=','
140 ; compute REG of ",xxxx(REG)" ; <== PARAM210, sep=' '
141 MOV #'(',TOS ; -- "(" as WORD separator to find xxxx of "xxxx(REG),"
142 CALL #SearchARG ; -- xxxx aborted if not found
143 CALL #ARGD2S ; skip arg_hi if DOUBLE
146 MOV TOS,0(X) ; -- xxxx compile xxxx
147 MOV #')',TOS ; -- ")" prepare separator to search REG of "xxxx(REG)"
149 ; search REG of "xxxx(REG)," separator = ')'
150 ; search REG of ",xxxx(REG)" separator = ')'
151 ; search REG of "@REG," separator = ',' <== PARAM120
152 ; search REG of "@REG+," separator = '+' <== PARAM121
153 ; search REG of "REG," separator = ',' <== PARAM13
154 ; search REG of ",REG" separator = BL <== PARAM21
155 SearchREG ; sep -- Rn
156 PUSHM #2,S ; PUSHM S,T
157 PUSH &TOIN ; -- sep save >IN
158 ADD #1,&TOIN ; skip "R"
159 ASMtoFORTH ; search xx of Rxx
160 .word WORDD,QNUMBER ;
161 .word QFBRAN,NOTaREG ; -- xxxx if Not a Number
162 FORTHtoASM ; -- Rn number is found
163 ADD #2,RSP ; remove >IN
165 JHS BOUNDERROR ; abort if Rn out of bounds
166 JLO SearchEnd ; -- Rn Z=0 ==> found
168 NOTaREG FORTHtoASM ; -- addr Z=1
169 MOV @RSP+,&TOIN ; -- addr restore >IN
170 JMP SearchEnd ; -- addr Z=1 ==> not a register
173 ; ----------------------------------------------------------------------
174 ; DTCforthMSP430FR5xxx ASSEMBLER : INTERPRET FIRST OPERAND
175 ; ----------------------------------------------------------------------
177 ; PARAM1 is used for OPCODES type I (double operand) and OPCODES type II (single operand) instructions
178 ; PARAM1 is used for OPCODES type V (double operand) and OPCODES type VI (single operand) extended instructions
180 ; PARAM1 separator -- ; parse input buffer until separator and compute first operand of opcode
181 ; sep is comma for src and space for dst .
183 PARAM1 mDOCOL ; -- sep OPCODES types I|V sep = ',' OPCODES types II|VI sep = ' '
184 .word FBLANK,SKIP ; -- sep addr
185 FORTHtoASM ; -- sep addr
186 MOV #0,S ; -- sep addr reset ASMTYPE
187 MOV &DDP,T ; -- sep addr HERE --> OPCODEADR (opcode is preset to its address !)
188 ADD #2,&DDP ; -- sep addr cell allot for opcode
189 MOV.B @TOS,W ; -- sep addr W=first char of instruction code
190 MOV @PSP+,TOS ; -- sep W=c-addr
191 CMP.B #'#',W ; -- sep W=first char
194 ; "#" found : case of "#xxxx,"
195 PARAM10 ADD #1,&TOIN ; -- sep skip # prefix
196 CALL #SearchARG ; -- xxxx abort if not found
197 CALL #ARGD2S ; skip arg_hi
199 PARAM100 CMP #0,TOS ; -- xxxx = 0 ?
202 MOV #0300h,S ; -- 0 example : MOV #0,dst <=> MOV R3,dst
205 PARAM101 CMP #1,TOS ; -- xxxx = 1 ?
208 MOV #0310h,S ; -- 1 example : MOV #1,dst <=> MOV 0(R3),dst
211 PARAM102 CMP #2,TOS ; -- xxxx = 2 ?
214 MOV #0320h,S ; -- 2 ASMTYPE = 0320h example : MOV #2, <=> MOV @R3,
217 PARAM104 CMP #4,TOS ; -- xxxx = 4 ?
220 MOV #0220h,S ; -- 4 ASMTYPE = 0220h example : MOV #4, <=> MOV @R2,
223 PARAM108 CMP #8,TOS ; -- xxxx = 8 ?
226 MOV #0230h,S ; -- 8 ASMTYPE = 0230h example : MOV #8, <=> MOV @R2+,
229 PARAM10M1 CMP #-1,TOS ; -- xxxx = -1 ?
232 MOV #0330h,S ; -- -1 ASMTYPE = 0330h example : MOV #-1 <=> MOV @R3+,
235 ; case of all others "#xxxx," ; -- xxxx
236 PARAM1000 MOV #0030h,S ; -- xxxx add immediate code type : @PC+,
238 ; case of "&xxxx," ; <== PARAM110
239 ; case of ",&xxxx" ; <== PARAM20
240 StoreArg MOV &DDP,X ; -- xxxx
241 ADD #2,&DDP ; cell allot for arg
243 StoreTOS ; <== TYPE1DOES
244 MOV TOS,0(X) ; compile arg
245 ; endcase of all "&xxxx" ;
246 ; endcase of all "#xxxx" ; <== PARAM101,102,104,108,10M1
247 ; endcase of all "REG"|"@REG"|"@REG+" ; <== PARAM124
248 PARAMENDOF MOV @PSP+,TOS ; --
251 ; ------------------------------------------
253 PARAM11 CMP.B #'&',W ; -- sep
256 ; case of "&xxxx," ; -- sep search for "&xxxx,"
257 PARAM110 MOV #0210h,S ; -- sep set code type : xxxx(SR) with AS=0b01 ==> x210h (and SR=0 !)
260 ; case of ",&xxxx" ; <== PARAM20
261 PARAM111 ADD #1,&TOIN ; -- sep skip "&" prefix
262 CALL #SearchARG ; -- arg abort if not found
263 CALL #ARGD2S ; skip arg_hi
264 JMP StoreArg ; -- then ret
265 ; ------------------------------------------
267 PARAM12 CMP.B #'@',W ; -- sep
270 ; case of "@REG,"|"@REG+,"
271 PARAM120 MOV #0020h,S ; -- sep init ASMTYPE with indirect code type : AS=0b10
272 ADD #1,&TOIN ; -- sep skip "@" prefix
273 CALL #SearchREG ; Z = not found
274 JNZ PARAM123 ; -- value REG of "@REG," found
276 ; case of "@REG+," ; -- addr REG of "@REG" not found, search REG of "@REG+"
277 PARAM121 ADD #0010h,S ; change ASMTYPE from @REG to @REG+ type
278 MOV #'+',TOS ; -- "+" as WORD separator to find REG of "@REG+,"
279 CALL #SearchREG ; -- value|addr X = flag
282 ; case of "xxxx(REG)," ; <== PARAM130
283 ; case of double separator: +, and ),
284 PARAM122 CMP &SOURCE_LEN,&TOIN ; test OPCODE II parameter ending by REG+ or (REG) without comma,
285 JZ PARAM123 ; i.e. >IN = SOURCE_LEN : don't skip char CR !
286 ADD #1,&TOIN ; -- 000R skip "," ready for the second operand search
288 ; case of "@REG," ; -- 000R <== PARAM120
289 ; case of "REG," ; -- 000R <== PARAM13
290 PARAM123 SWPB TOS ; -- 0R00 swap bytes because it's not a dst REG typeI (not a 2 ops inst.)
292 ; case of ",REG" ; -- 000R <== PARAM21 (dst REG typeI)
293 ; case of ",xxxx(REG)" ; -- 000R <== PARAM210 (dst REG typeI)
294 PARAM124 ADD TOS,S ; -- 0R00|000R
296 ; ------------------------------------------
298 ; case of "REG,"|"xxxx(REG)," ; first, searg REG of "REG,"
299 PARAM13 CALL #SearchREG ; -- sep save >IN for second parsing (case of "xxxx(REG),")
300 JNZ PARAM123 ; -- 000R REG of "REG," found, S=ASMTYPE=0
302 ; case of "xxxx(REG)," ; -- c-addr "REG," not found
303 PARAM130 ADD #0010h,S ; AS=0b01 for indexing address
304 CALL #ComputeARGparenREG ; compile xxxx and search REG of "(REG)"
307 ; ----------------------------------------------------------------------
308 ; DTCforthMSP430FR5xxx ASSEMBLER : INTERPRET 2th OPERAND
309 ; ----------------------------------------------------------------------
311 ; PARAM2 is used for OPCODES type I (double operand) instructions
312 ; PARAM2 is used for OPCODES type V (double operand) extended instructions
314 ; PARAM2 -- ; parse input buffer until BL and compute this 2th operand
316 .word FBLANK,SKIP ; skip space(s) between "arg1," and "arg2" if any; use not S,T.
317 FORTHtoASM ; -- c-addr search for '&' of "&xxxx
319 MOV #20h,TOS ; -- ' ' as WORD separator to find xxxx of ",&xxxx"
320 JNE PARAM21 ; '&' not found
323 PARAM20 ADD #0082h,S ; change ASMTYPE : AD=1, dst = R2
324 JMP PARAM111 ; -- ' '
325 ; ------------------------------------------
327 ; case of ",REG"|",xxxx(REG) ; -- ' ' first, search REG of ",REG"
328 PARAM21 CALL #SearchREG ;
329 JNZ PARAM124 ; -- 000R REG of ",REG" found
331 ; case of ",xxxx(REG) ; -- addr REG not found
332 PARAM210 ADD #0080h,S ; set AD=1
333 CALL #ComputeARGparenREG ; compile argument xxxx and search REG of "(REG)"
334 JMP PARAM124 ; -- 000R REG of "(REG) found
337 ; ----------------------------------------------------------------------
338 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODE TYPE 0 : zero operand f:-)
339 ; ----------------------------------------------------------------------
342 .word lit,1300h,COMMA,EXIT
344 ; ----------------------------------------------------------------------
345 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODES TYPE I : double operand
346 ; ----------------------------------------------------------------------
348 ; OPCODE(code) for TYPE I = 0bxxxx opcode I
350 ; = 0bxxxx src register
351 ; OPCODE(7) AD (dst addr type)
355 ; OPCODE(B) for TYPE I or TYPE II = 0b0 word
357 ; OPCODE(54) AS (src addr type)
358 ; OPCODE(AS) for TYPE I or OPCODE(AD) for TYPE II = 0b00 register
363 ; OPCODE(dst) for TYPE I or TYPE II = 0bxxxx dst register
364 ; ----------------------------------------------------------------------
366 ; TYPE1DOES -- BODYDOES search and compute PARAM1 & PARAM2 as src and dst operands then compile instruction
367 TYPE1DOES ; -- BODYDOES
368 .word lit,',' ; -- BODYDOES ',' char separator for PARAM1
369 .word PARAM1 ; -- BODYDOES
370 .word PARAM2 ; -- BODYDOES char separator (BL) included in PARAM2
372 MAKEOPCODE MOV @TOS,TOS ; -- opcode part of instruction
373 BIS S,TOS ; -- opcode opcode is complete
374 MOV T,X ; -- opcode X= OPCODEADR to compile opcode
375 JMP StoreTOS ; -- then EXIT
379 .word TYPE1DOES,4000h
383 .word TYPE1DOES,4040h
387 .word TYPE1DOES,5000h
391 .word TYPE1DOES,5040h
395 .word TYPE1DOES,6000h
399 .word TYPE1DOES,6040h
403 .word TYPE1DOES,7000h
407 .word TYPE1DOES,7040h
411 .word TYPE1DOES,8000h
415 .word TYPE1DOES,8040h
419 .word TYPE1DOES,9000h
423 .word TYPE1DOES,9040h
427 .word TYPE1DOES,0A000h
431 .word TYPE1DOES,0A040h
435 .word TYPE1DOES,0B000h
439 .word TYPE1DOES,0B040h
443 .word TYPE1DOES,0C000h
447 .word TYPE1DOES,0C040h
451 .word TYPE1DOES,0D000h
455 .word TYPE1DOES,0D040h
459 .word TYPE1DOES,0E000h
463 .word TYPE1DOES,0E040h
467 .word TYPE1DOES,0F000h
471 .word TYPE1DOES,0F040h
473 ; ----------------------------------------------------------------------
474 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES TYPE II : single operand
475 ; ----------------------------------------------------------------------
476 ; OPCODE(FEDCBA987) opcodeII
477 ; OPCODE(code) for TYPE II = 0bxxxxxxxxx
479 ; OPCODE(B) for TYPE I or TYPE II = 0b0 word
481 ; OPCODE(54) (dst addr type)
482 ; OPCODE(AS) for TYPE I or OPCODE(AD) for TYPE II = 0b00 register
487 ; OPCODE(dst) for TYPE I or TYPE II = 0bxxxx dst register
488 ; ----------------------------------------------------------------------
490 TYPE2DOES ; -- BODYDOES
491 .word FBLANK ; -- BODYDOES ' ' char separator for PARAM1
492 .word PARAM1 ; -- BODYDOES
495 AND #0070h,S ; keep B/W & AS infos in ASMTYPE
496 SWPB W ; (REG org --> REG dst)
497 AND #000Fh,W ; keep REG
498 BIS_ASMTYPE BIS W,S ; -- BODYDOES add it in ASMTYPE
499 JMP MAKEOPCODE ; -- then end
501 asmword "RRC" ; Rotate Right through Carry ( word)
503 .word TYPE2DOES,1000h
505 asmword "RRC.B" ; Rotate Right through Carry ( byte)
507 .word TYPE2DOES,1040h
509 asmword "SWPB" ; Swap bytes
511 .word TYPE2DOES,1080h
515 .word TYPE2DOES,1100h
519 .word TYPE2DOES,1140h
523 .word TYPE2DOES,1180h
527 .word TYPE2DOES,1200h
531 .word TYPE2DOES,1240h
535 .word TYPE2DOES,1280h
538 BOUNDERRWM1 ADD #1,W ; <== RRAM|RRUM|RRCM|RLAM error
539 BOUNDERRORW MOV W,TOS ; <== PUSHM|POPM|ASM_branch error
540 BOUNDERROR ; <== REG number error
541 mDOCOL ; -- n n = value out of bounds
543 .byte 13,"out of bounds"
548 ; ----------------------------------------------------------------
550 TYPE3DOES ; -- BODYDOES
551 .word FBLANK,SKIP ; -- BODYDOES addr skip spaces if any
553 MOV #0,S ; init ASMTYPE=0
554 MOV &DDP,T ; init OPCODEADR=DP
555 ADD #2,&DDP ; make room for opcode
556 ADD #1,&TOIN ; skip "#"
557 MOV #',',TOS ; -- BODYDOES ","
558 PUSHM #2,S ; PUSHM S,T
561 .word QFBRAN,NotFound ; ABORT
565 .word PARAM2 ; -- BODYDOES 0x000N S=ASMTYPE = 0x000R
567 MOV TOS,W ; -- BODYDOES n W = n
568 MOV @PSP+,TOS ; -- BODYDOES
569 SUB #1,W ; W = n floored to 0
571 MOV @TOS,X ; X=OPCODE
572 RLAM #4,X ; OPCODE bit 1000h --> C
573 JNC RxxMINSTRU ; if bit 1000h = 0
574 PxxxINSTRU MOV S,Y ; S=REG, Y=REG to test
575 RLAM #3,X ; OPCODE bit 0200h --> C
576 JNC PUSHMINSTRU ; W=n-1 Y=REG
577 POPMINSTRU SUB W,S ; to make POPM opcode, compute first REG to POP; TI is complicated....
578 PUSHMINSTRU SUB W,Y ; Y=REG-(n-1)
580 JHS BOUNDERRWM1 ; JC=JHS (U>=)
581 RLAM #4,W ; W = n << 4
582 JMP BIS_ASMTYPE ; BODYDOES --
583 RxxMINSTRU CMP #4,W ;
584 JHS BOUNDERRWM1 ; JC=JHS (U>=)
585 SWPB W ; -- BODYDOES W = n << 8
586 RLAM #2,W ; W = N << 10
587 JMP BIS_ASMTYPE ; BODYDOES --
589 ; --------------------------------------------------------------------------------
590 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES TYPE III : PUSHM|POPM|RLAM|RRAM|RRUM|RRCM
591 ; --------------------------------------------------------------------------------
595 .word TYPE3DOES,0040h
599 .word TYPE3DOES,0050h
603 .word TYPE3DOES,0140h
607 .word TYPE3DOES,0150h
611 .word TYPE3DOES,0240h
615 .word TYPE3DOES,0250h
619 .word TYPE3DOES,0340h
623 .word TYPE3DOES,0350h
627 .word TYPE3DOES,1400h
631 .word TYPE3DOES,1500h
635 .word TYPE3DOES,1600h
639 .word TYPE3DOES,1700h
641 ; ----------------------------------------------------------------------
642 ; DTCforthMSP430FR5xxx ASSEMBLER, CONDITIONAL BRANCHS
643 ; ----------------------------------------------------------------------
644 ; ASSEMBLER FORTH OPCODE(FEDC)
645 ; OPCODE(code) for TYPE JNE,JNZ 0<>, <> = 0x20xx + (offset AND 3FF) ; branch if Z = 0
646 ; OPCODE(code) for TYPE JEQ,JZ 0=, = = 0x24xx + (offset AND 3FF) ; branch if Z = 1
647 ; OPCODE(code) for TYPE JNC,JLO U< = 0x28xx + (offset AND 3FF) ; branch if C = 0
648 ; OPCODE(code) for TYPE JC,JHS U>= = 0x2Cxx + (offset AND 3FF) ; branch if C = 1
649 ; OPCODE(code) for TYPE JN 0< = 0x30xx + (offset AND 3FF) ; branch if N = 1
650 ; OPCODE(code) for TYPE JGE >= = 0x34xx + (offset AND 3FF) ; branch if (N xor V) = 0
651 ; OPCODE(code) for TYPE JL < = 0x38xx + (offset AND 3FF) ; branch if (N xor V) = 1
652 ; OPCODE(code) for TYPE JMP = 0x3Cxx + (offset AND 3FF)
654 CODE_JMP mDOCON ; branch always
657 asmword "S>=" ; if >= assertion (opposite of jump if < )
661 asmword "S<" ; if < assertion
665 asmword "0>=" ; if 0>= assertion ; use only with IF UNTIL WHILE !
669 asmword "0<" ; jump if 0< ; use only with ?JMP ?GOTO !
673 asmword "U<" ; if U< assertion
677 asmword "U>=" ; if U>= assertion
681 asmword "0<>" ; if <>0 assertion
685 asmword "0=" ; if =0 assertion
689 ;ASM IF OPCODE -- @OPCODE1
692 MOV TOS,0(W) ; compile incomplete opcode
697 ;ASM THEN @OPCODE -- resolve forward branch
699 ASM_THEN MOV &DDP,W ; -- @OPCODE W=dst
700 MOV TOS,Y ; Y=@OPCODE
701 ASM_THEN1 MOV @PSP+,TOS ; --
703 ADD #2,X ; -- Y=@OPCODE W=dst X=src+2
704 SUB X,W ; -- Y=@OPCODE W=dst-src+2=displacement*2 (bytes)
705 RRA W ; -- Y=@OPCODE W=displacement (words)
707 JC BOUNDERRORW ; (JHS) unsigned branch if u> 511
708 BIS W,0(Y) ; -- [@OPCODE]=OPCODE completed
711 ;C ELSE @OPCODE1 -- @OPCODE2 branch for IF..ELSE
713 ASM_ELSE MOV &DDP,W ; -- W=HERE
714 MOV #3C00h,0(W) ; compile unconditionnal branch
715 ADD #2,&DDP ; -- DP+2
717 MOV W,0(PSP) ; -- @OPCODE2 @OPCODE1
718 JMP ASM_THEN ; -- @OPCODE2
720 ;C BEGIN -- @BEGIN same as FORTH counterpart
722 ;C UNTIL @BEGIN OPCODE -- resolve conditional backward branch
724 ASM_UNTIL MOV @PSP+,W ; -- OPCODE W=dst
727 MOV &DDP,X ; -- Y=OPCODE X=HERE W=dst
728 SUB #2,W ; -- Y=OPCODE X=HERE W=dst-2
729 SUB X,W ; -- Y=OPCODE X=src W=src-dst-2=displacement (bytes)
730 RRA W ; -- Y=OPCODE X=HERE W=displacement (words)
732 JL BOUNDERRORW ; signed branch if < -512
733 AND #3FFh,W ; -- Y=OPCODE X=HERE W=troncated negative displacement (words)
734 BIS W,Y ; -- Y=OPCODE (completed)
739 ;X AGAIN @BEGIN -- uncond'l backward branch
740 ; unconditional backward branch
742 ASM_AGAIN mDOCOL ; -- @BEGIN
743 .word CODE_JMP ; -- @BEGIN opcode
747 ;C WHILE @BEGIN OPCODE -- @WHILE @BEGIN
749 ASM_WHILE mDOCOL ; -- @BEGIN OPCODE
750 .word ASM_IF ; -- @BEGIN @WHILE
751 .word SWAP ; -- @WHILE @BEGIN
754 ;C REPEAT @WHILE @BEGIN -- resolve WHILE loop
756 ASM_REPEAT mDOCOL ; -- @WHILE @BEGIN
757 .word CODE_JMP ; -- @WHILE @BEGIN opcode
758 .word ASM_UNTIL ; -- @WHILE
762 ; ------------------------------------------------------------------------------------------
763 ; DTCforthMSP430FR5xxx ASSEMBLER : branch up to 3 backward labels and up to 3 forward labels
764 ; ------------------------------------------------------------------------------------------
765 ; used for non canonical branchs, as BASIC language: "goto line x"
766 ; when a branch to label is resolved, it's ready for new use
772 MOV TOS,Y ; Y = ASMBWx
774 MOV @Y,W ; W = [ASMBWx]
776 MOV #0,0(Y) ; preset [ASMBWx] = 0 for next use
780 MOV &DDP,0(Y) ; [ASMBWx] = DDP
787 .word ASMBW1 ; in RAM
793 .word ASMBW2 ; in RAM
799 .word ASMBW3 ; in RAM
806 MOV @TOS,Y ; Y=[ASMFWx]
807 CMP #0,Y ; ASMFWx = 0 ? (FWx is free?)
808 MOV #0,0(TOS) ; preset [ASMFWx] for next use
809 FORWUSE ; PFA -- @OPCODE
811 FORWSET ; OPCODE PFA --
812 MOV @PSP+,0(W) ; -- PFA compile incomplete opcode
813 ADD #2,&DDP ; increment DDP
814 MOV W,0(TOS) ; store @OPCODE into ASMFWx
823 .word ASMFW1 ; in RAM
829 .word ASMFW2 ; in RAM
835 .word ASMFW3 ; in RAM
838 ; invert FORTH conditionnal branch FORTH_JMP_OPCODE -- LABEL_JMP_OPCODE
839 INVJMP CMP #3000h,TOS
840 JZ INVJMPEND ; case of JN, do nothing
841 XOR #0400h,TOS ; case of: JNZ<-->JZ JNC<-->JC JL<-->JGE
842 BIT #1000h,TOS ; 3xxxh case ?
844 XOR #0800h,TOS ; complementary action for JL<-->JGE
847 ;ASM GOTO <label> -- unconditionnal branch to label
850 .word CODE_JMP,TICK ; -- OPCODE CFA<label>
853 ;ASM <cond> ?GOTO <label> OPCODE -- conditionnal branch to label
856 .word INVJMP,TICK ; -- OPCODE CFA<label>
859 ; ----------------------------------------------------------------
860 ; DTCforthMSP430FR5xxx ASSEMBLER : branch to a previous definition
861 ; ----------------------------------------------------------------
863 ;ASM JMP <word> ; -- unconditionnal branch to a previous definition
866 .word TICK ; -- @BACKWARD
870 ;ASM <cond> ?JMP <word> ; OPCODE -- conditionnal branch to a previous definition
873 .word INVJMP,TICK,SWAP ;
876 ; ===============================================================
878 ; ===============================================================
880 ; Adda|Cmpa|Mova|Suba first argument process ACMS1
882 ACMS1 mDOCOL ; -- BODYDOES ','
883 .word FBLANK,SKIP ; -- BODYDOES ',' addr
885 MOV.B @TOS,X ; X=first char of opcode string
886 MOV @PSP+,TOS ; -- BODYDOES ','
887 MOV @PSP+,S ; -- ',' S=BODYDOES
890 ADD #2,&DDP ; make room for opcode
891 ;-------------------------------;
892 ACMS10 CMP.B #'R',X ; -- ','
894 ACMS101 CALL #SearchREG ; -- Rn src
895 ACMS102 RLAM #4,TOS ; 8<<src
897 ACMS103 BIS S,TOS ; update opcode with src|dst
898 MOV TOS,0(T) ; save opcode
899 MOV T,TOS ; -- OPCODE_addr
901 ;-------------------------------;
902 ACMS11 CMP.B #'#',X ; -- ',' X=addr
904 BIC #40h,S ; set #opcode
905 ACMS111 ADD #1,&TOIN ; skip '#'|'&'
906 ADD #2,&DDP ; make room for low #$xxxx|&$xxxx|$xxxx(REG)
907 CALL #SearchARG ; -- Lo Hi
908 MOV @PSP+,2(T) ; -- Hi store $xxxx of #$x.xxxx|&$x.xxxx|$x.xxxx(REG)
909 AND #0Fh,TOS ; -- Hi sel Hi src
911 ;-------------------------------;
912 MOVA12 CMP.B #'&',X ; -- ',' case of MOVA &$x.xxxx
914 XOR #00E0h,S ; set MOVA &$x.xxxx, opcode
916 ;-------------------------------;
917 MOVA13 BIC #00F0h,S ; set MOVA @REG, opcode
918 CMP.B #'@',X ; -- ','
920 ADD #1,&TOIN ; skip '@'
921 CALL #SearchREG ; -- Rn
922 JNZ ACMS102 ; if @REG found
923 ;-------------------------------;
924 BIS #0010h,S ; set @REG+ opcode
925 MOV #'+',TOS ; -- '+'
926 MOVA131 CALL #SearchREG ; -- Rn case of MOVA @REG+,|MOVA $x.xxxx(REG),
927 CMP &SOURCE_LEN,&TOIN ; test TYPE II first parameter ending by @REG+ (REG) without comma,
928 JZ ACMS102 ; i.e. may be >IN = SOURCE_LEN: don't skip char CR !
929 ADD #1,&TOIN ; skip "," ready for the second operand search
931 ;-------------------------------;
932 MOVA14 BIS #0030h,S ; set xxxx(REG), opcode
933 ADD #2,&DDP ; -- ',' make room for first $xxxx of $0.xxxx(REG),
934 MOV #'(',TOS ; -- "(" as WORD separator to find xxxx of "xxxx(REG),"
935 CALL #SearchARG ; -- Lo Hi
936 MOV @PSP+,2(T) ; -- Hi store $xxxx as 2th word
937 MOV #')',TOS ; -- ')'
940 ; Adda|Cmpa|Mova|Suba 2th argument process ACMS2
942 ;-------------------------------;
943 ACMS2 mDOCOL ; -- OPCODE_addr
944 .word FBLANK,SKIP ; -- OPCODE_addr addr
946 MOV @PSP+,T ; -- addr T=OPCODE_addr
948 MOV.B @TOS,X ; -- addr X=first char of string instruction
949 MOV.B #' ',TOS ; -- ' '
950 ;-------------------------------;
951 ACMS21 CMP.B #'R',X ; -- ' '
953 ACMS211 CALL #SearchREG ; -- Rn
955 ;-------------------------------;
957 ADD #2,&DDP ; -- ' ' make room for $xxxx
960 BIS #060h,S ; set ,&$x.xxxx opcode
961 ADD #1,&TOIN ; skip '&'
962 CALL #SearchARG ; -- Lo Hi
963 MOV @PSP+,2(T) ; -- Hi store $xxxx as 2th word
964 JMP ACMS103 ; update opcode with dst $x and write opcode
965 ;-------------------------------;
966 MOVA23 BIS #070h,S ; set ,xxxx(REG) opcode
967 MOV #'(',TOS ; -- "(" as WORD separator to find xxxx of "xxxx(REG),"
968 CALL #SearchARG ; -- Lo Hi
969 MOV @PSP+,2(T) ; -- Hi write $xxxx of ,$0.xxxx(REG) as 2th word
970 MOV #')',TOS ; -- ")" as WORD separator to find REG of "xxxx(REG),"
974 ; --------------------------------------------------------------------------------
975 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES IV 2 operands: Adda|Cmpa|Mova|Suba (without extended word)
976 ; --------------------------------------------------------------------------------
977 ; absolute and immediate instructions must be written as $x.xxxx (DOUBLE numbers)
978 ; indexed instructions must be written as $.xxxx(REG) (DOUBLE numbers)
979 ; --------------------------------------------------------------------------------
981 TYPE4DOES .word lit,',' ; -- BODYDOES "," char separator for PARAM1
982 .word ACMS1 ; -- OPCODE_addr
986 .word ACMS2 ; -- OPCODE_addr
991 .word TYPE4DOES,00C0h
995 .word TYPE4DOES,00D0h
999 .word TYPE4DOES,00E0h
1003 .word TYPE4DOES,00F0h
1006 ; --------------------------------------------------------------------------------
1007 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODE TYPE III bis: CALLA (without extended word)
1008 ; --------------------------------------------------------------------------------
1009 ; absolute and immediate instructions must be written as $x.xxxx (DOUBLE numbers)
1010 ; indexed instructions must be written as $.xxxx(REG) (DOUBLE numbers)
1011 ; --------------------------------------------------------------------------------
1015 .word FBLANK,SKIP ; -- addr
1017 MOV &DDP,T ; T = DDP
1018 ADD #2,&DDP ; make room for opcode
1019 MOV.B @TOS,TOS ; -- char First char of opcode
1020 CALLA0 MOV #134h,S ; 134h<<4 = 1340h = opcode for CALLA Rn
1023 CALLA01 MOV.B #' ',TOS ;
1024 CALLA02 CALL #SearchREG ; -- Rn
1025 CALLA03 RLAM #4,S ; (opcode>>4)<<4 = opcode
1026 BIS TOS,S ; update opcode
1027 MOV S,0(T) ; store opcode
1030 ;---------------------------;
1031 CALLA1 ADD #2,S ; 136h<<4 = opcode for CALLA @REG
1032 CMP.B #'@',TOS ; -- char Search @REG
1034 ADD #1,&TOIN ; skip '@'
1035 MOV.B #' ',TOS ; -- ' '
1037 JNZ CALLA03 ; if REG found, update opcode
1038 ;---------------------------;
1039 ADD #1,S ; 137h<<4 = opcode for CALLA @REG+
1040 MOV #'+',TOS ; -- '+'
1042 ;---------------------------;
1043 CALLA2 ADD #2,&DDP ; make room for xxxx of #$x.xxxx|&$x.xxxx|$0.xxxx(REG)
1046 MOV #13Bh,S ; 13Bh<<4 = opcode for CALLA #$x.xxxx
1047 CALLA21 ADD #1,&TOIN ; skip '#'|'&'
1048 CALLA22 CALL #SearchARG ; -- Lo Hi
1049 MOV @PSP+,2(T) ; -- Hi store #$xxxx|&$xxxx
1050 JMP CALLA03 ; update opcode with $x. and store opcode
1051 ;---------------------------;
1052 CALLA3 CMP.B #'&',TOS
1054 ADD #2,S ; 138h<<4 = opcode for CALLA &$x.xxxx
1056 ;---------------------------;
1057 CALLA4 MOV.B #'(',TOS ; -- "("
1058 SUB #1,S ; 135h<<4 = opcode for CALLA $0.xxxx(REG)
1059 CALLA41 CALL #SearchARG ; -- Lo Hi
1060 MOV @PSP+,2(T) ; -- Hi store $xxxx
1061 MOV #')',TOS ; -- ')'
1062 JMP CALLA02 ; search Rn and update opcode
1066 ; PRMX1 is used for OPCODES type V (double operand) and OPCODES type VI (single operand) extended instructions
1068 PRMX1 mDOCOL ; -- sep OPCODES type V|VI separator = ','|' '
1069 .word FBLANK,SKIP ; -- sep addr
1071 MOV.B @TOS,X ; -- sep addr X= first char of opcode string
1072 MOV @PSP+,TOS ; -- sep
1073 MOV #1800h,S ; init S=Extended word
1074 ;-------------------------------;
1075 PRMX10 CMP.B #'R',X ; -- sep
1077 PRMX101 CALL #SearchREG ; -- Rn Rn of REG; call SearchREG only to update >IN
1078 PRMX102 MOV S,TOS ; -- EW update Extended word
1079 PRMX103 mSEMI ; -- Ext_Word
1080 ;-------------------------------;
1081 PRMX11 MOV #0,&RPT_WORD ; clear RPT
1082 CMP.B #'#',X ; -- sep
1084 PRMX111 ADD #1,&TOIN ; -- sep skip '#'
1085 PRMX112 CALL #SearchARG ; -- Lo Hi search $x.xxxx of #x.xxxx,
1086 ADD #2,PSP ; -- Hi pop unused low word
1087 PRMX113 AND #0Fh,TOS ;
1089 RLAM #4,TOS ; -- 7<<Hi
1090 PRMX115 BIS TOS,S ; update extended word with srcHi
1092 ;-------------------------------;
1093 PRMX12 CMP.B #'&',X ; -- sep
1095 ;-------------------------------; search REG of @REG,|@REG+,
1096 PRMX13 CMP.B #'@',X ; -- sep
1098 PRMX131 ADD #1,&TOIN ; -- sep skip '@'
1099 PRMX132 CALL #SearchREG ; -- Rn Rn of @REG,
1100 JNZ PRMX102 ; if Rn found
1101 ;-------------------------------;
1102 MOV #'+',TOS ; -- '+'
1103 PRMX133 ADD #1,&TOIN ; skip '@'
1104 CALL #SearchREG ; -- Rn Rn of @REG+,
1105 PRMX134 CMP &SOURCE_LEN,&TOIN ; test case of TYPE VI first parameter without ','
1106 JZ PRMX102 ; don't take the risk of skipping CR !
1107 ADD #1,&TOIN ; skip ',' ready to search 2th operand
1109 ;-------------------------------;
1110 PRMX14 MOV #'(',TOS ; -- '(' to find $x.xxxx of "x.xxxx(REG),"
1111 CALL #SearchARG ; -- Lo Hi
1112 MOV TOS,0(PSP) ; -- Hi Hi
1113 PRMX141 MOV #')',TOS ; -- Hi ')'
1114 CALL #SearchREG ; -- Hi Rn
1115 MOV @PSP+,TOS ; -- Hi
1119 ;-------------------------------;
1121 ; PRMX2 is used for OPCODES type V (double operand) extended instructions
1123 ;-------------------------------;
1124 PRMX2 mDOCOL ; -- Extended_Word
1125 .word FBLANK,SKIP ; -- Extended_Word addr
1127 MOV @PSP+,S ; -- addr S=Extended_Word
1128 MOV.B @TOS,X ; -- addr X=first char of code instruction
1129 MOV #' ',TOS ; -- ' '
1130 ;-------------------------------;
1131 PRMX20 CMP.B #'R',X ; -- ' '
1132 JZ PRMX102 ; extended word not to be updated
1133 ;-------------------------------;
1134 PRMX21 MOV #0,&RPT_WORD ;
1137 PRMX211 ADD #1,&TOIN ; -- ' ' skip '&'
1138 PRMX212 CALL #SearchARG ; -- Lo Hi
1139 PRMX213 ADD #2,PSP ; -- hi pop low word
1140 AND #0Fh,TOS ; -- Hi
1141 JMP PRMX115 ; update Extended word with dst_Hi
1142 ;-------------------------------;
1143 PRMX22 MOV #'(',TOS ; -- '(' as WORD separator to find xxxx of "xxxx(REG)"
1144 CALL #SearchARG ; -- Lo Hi search x.xxxx of x.xxxx(REG)
1147 ; UPDATE_eXtendedWord
1148 ;-------------------------------;
1149 UPDATE_XW ; BODYDOES Extended_Word -- BODYDOES+2 >IN R--
1151 ADD #2,&DDP ; make room for extended word
1152 MOV TOS,S ; S = Extended_Word
1153 MOV @PSP+,TOS ; -- BODYDOES
1154 BIS &RPT_WORD,S ; update Extended_word with RPT_WORD
1155 MOV #0,&RPT_WORD ; clear RPT before next instruction
1156 BIS @TOS+,S ; -- BODYDOES+2 update Extended_word with [BODYDOES] = A/L bit
1157 MOV S,0(T) ; store extended word
1158 MOV @RSP+,&TOIN ; >IN R-- restore >IN at the start of instruction string
1160 ;-------------------------------;
1162 ; --------------------------------------------------------------------------------
1163 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES V extended double operand
1164 ; --------------------------------------------------------------------------------
1165 ; absolute and immediate instructions must be written as $x.xxxx (DOUBLE numbers)
1166 ; indexed instructions must be written as $.xxxx(REG) (DOUBLE numbers)
1167 ; --------------------------------------------------------------------------------
1170 ; these instructions below are processed in two pass:
1171 ; pass 1: extended word process by TYPE5DOES with [BODYDOES] value
1172 ; pass 2: instruction process by TYPE1DOES with [BODYDOES+2] value
1173 ; all numeric arguments must be written as DOUBLE numbers (including a point) : $x.xxxx
1175 TYPE5DOES ; -- BODYDOES
1176 .word LIT,TOIN,FETCH,TOR ; R-- >IN save >IN for 2th pass
1177 .word lit,',' ; -- BODYDOES ',' char separator for PRMX1
1178 .word PRMX1 ; -- BODYDOES Extended_Word
1179 .word PRMX2 ; -- BODYDOES Extended_Word
1180 .word UPDATE_XW ; -- BODYDOES+2 >IN is restored ready for 2th pass
1181 .word BRAN,TYPE1DOES ; -- BODYDOES+2 2th pass: completes instruction with opcode = [BODYDOES+2]
1185 .word TYPE5DOES,40h,4000h ; [PFADOES]=TYPE5DOES, [BODYDOES]=A/L bit, [BODYDOES+2]=OPCODE,
1189 .word TYPE5DOES,0,4040h
1193 .word TYPE5DOES,40h,4040h
1197 .word TYPE5DOES,40h,5000h
1201 .word TYPE5DOES,0,5040h
1205 .word TYPE5DOES,40h,5040h
1209 .word TYPE5DOES,40h,6000h
1213 .word TYPE5DOES,0,6040h
1217 .word TYPE5DOES,40h,6040h
1221 .word TYPE5DOES,40h,7000h
1225 .word TYPE5DOES,0,7040h
1229 .word TYPE5DOES,40h,7040h
1233 .word TYPE5DOES,40h,8000h
1237 .word TYPE5DOES,0,8040h
1241 .word TYPE5DOES,40h,8040h
1245 .word TYPE5DOES,40h,9000h
1249 .word TYPE5DOES,0,9040h
1253 .word TYPE5DOES,40h,9040h
1257 .word TYPE5DOES,40h,0A000h
1261 .word TYPE5DOES,0,0A040h
1265 .word TYPE5DOES,40h,0A040h
1269 .word TYPE5DOES,40h,0B000h
1273 .word TYPE5DOES,0,0B040h
1277 .word TYPE5DOES,40h,0B040h
1281 .word TYPE5DOES,40h,0C000h
1285 .word TYPE5DOES,0,0C040h
1289 .word TYPE5DOES,40h,0C040h
1293 .word TYPE5DOES,40h,0D000h
1297 .word TYPE5DOES,0,0D040h
1301 .word TYPE5DOES,40h,0D040h
1305 .word TYPE5DOES,40h,0E000h
1309 .word TYPE5DOES,0,0E040h
1313 .word TYPE5DOES,40h,0E040h
1317 .word TYPE5DOES,40h,0F000h
1321 .word TYPE5DOES,0,0F040h
1325 .word TYPE5DOES,40h,0F040h
1327 ; --------------------------------------------------------------------------------
1328 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES VI extended single operand (take count of RPT)
1329 ; --------------------------------------------------------------------------------
1330 ; absolute and immediate instructions must be written as $x.xxxx (DOUBLE numbers)
1331 ; indexed instructions must be written as $.xxxx(REG) (DOUBLE numbers)
1332 ; --------------------------------------------------------------------------------
1334 ; these instructions below are processed in two pass:
1335 ; pass 1: extended word process by TYPE6DOES with [BODYDOES] value
1336 ; pass 2: instruction process by TYPE2DOES with [BODYDOES+2] value
1337 ; all numeric arguments must be written as DOUBLE numbers (including a point) : $x.xxxx
1339 TYPE6DOES ; -- BODYDOES
1340 .word LIT,TOIN,FETCH,TOR ; save >IN for 2th pass
1341 .word FBLANK ; -- BODYDOES ' '
1342 .word PRMX1 ; -- BODYDOES Extended_Word
1343 .word UPDATE_XW ; -- BODYDOES+2
1344 .word BRAN,TYPE2DOES ; -- BODYDOES+2 pass 2: completes instruction with opcode = [BODYDOES+2]
1346 asmword "RRCX" ; ZC=0; RRCX Rx,Rx may be repeated by prefix RPT #n|Rn
1348 .word TYPE6DOES,40h,1000h
1350 asmword "RRCX.A" ; ZC=0; RRCX.A Rx may be repeated by prefix RPT #n|Rn
1352 .word TYPE6DOES,0,1040h
1354 asmword "RRCX.B" ; ZC=0; RRCX.B Rx may be repeated by prefix RPT #n|Rn
1356 .word TYPE6DOES,40h,1040h
1358 asmword "RRUX" ; ZC=1; RRUX Rx may be repeated by prefix RPT #n|Rn
1360 .word TYPE6DOES,140h,1000h
1362 asmword "RRUX.A" ; ZC=1; RRUX.A Rx may be repeated by prefix RPT #n|Rn
1364 .word TYPE6DOES,100h,1040h
1366 asmword "RRUX.B" ; ZC=1; RRUX.B Rx may be repeated by prefix RPT #n|Rn
1368 .word TYPE6DOES,140h,1040h
1372 .word TYPE6DOES,40h,1080h
1376 .word TYPE6DOES,0,1080h
1380 .word TYPE6DOES,40h,1100h
1384 .word TYPE6DOES,0,1140h
1388 .word TYPE6DOES,40h,1140h
1392 .word TYPE6DOES,40h,1180h
1396 .word TYPE6DOES,0,1180h
1400 .word TYPE6DOES,40h,1200h
1404 .word TYPE6DOES,0,1240h
1408 .word TYPE6DOES,40h,1240h
1410 ; ----------------------------------------------------------------------
1411 ; DTCforthMSP430FR5xxx ASSEMBLER, RPT instruction before REG|REG,REG eXtended instructions
1412 ; ----------------------------------------------------------------------
1414 asmword "RPT" ; RPT #n | RPT [Rn] repeat n | [Rn] times modulo 16
1417 FORTHtoASM ; -- addr
1419 MOV.B #' ',TOS ; -- ' ' as separator
1422 CALL #SearchREG ; -- Rn
1423 JZ RPT1 ; if not found
1424 BIS #80h,TOS ; -- $008R R=Rn
1426 RPT1 CALL #SearchARG ; -- $xxxx
1427 AND #0Fh,TOS ; -- $000x
1428 RPT2 MOV TOS,&RPT_WORD