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'
48 ; FORTHWORD "SKIP" ; used by assembler to parse input stream
49 SKIP MOV #SOURCE_LEN,Y ;2
50 MOV TOS,W ; -- char W=char
51 MOV @Y+,X ;2 -- char W=char X=buf_length
52 MOV @Y,TOS ;2 -- Start_buf_adr W=char X=buf_length
53 ADD TOS,X ; -- Start_buf_adr W=char X=Start_buf_adr+buf_length=End_buf_addr
54 ADD &TOIN,TOS ; -- Parse_Adr W=char X=End_buf_addr
55 SKIPLOOP CMP TOS,X ; -- Parse_Adr W=char X=End_buf_addr
56 JZ SKIPEND ; -- Parse_Adr if end of buffer
57 CMP.B @TOS+,W ; -- Parse_Adr does character match?
58 JZ SKIPLOOP ; -- Parse_Adr+1
59 SKIPNEXT SUB #1,TOS ; -- addr
61 SUB @Y,W ; -- addr W=Parse_Addr-Start_buf_adr=Toin
65 ; ----------------------------------------------------------------------
66 ; DTCforthMSP430FR5xxx ASSEMBLER : search argument "xxxx", IP is free
67 ; ----------------------------------------------------------------------
69 SearchARG ; separator -- n|d or abort" not found"
70 ; Search ARG of "#xxxx," ; <== PARAM10
71 ; Search ARG of "&xxxx," ; <== PARAM111
72 ; Search ARG of "xxxx(REG)," ; <== PARAM130
73 ; Search ARG of ",&xxxx" ; <== PARAM111 <== PARAM20
74 ; Search ARG of ",xxxx(REG)" ; <== PARAM210
75 PUSHM #2,S ; PUSHM S,T as OPCODE, OPCODEADR
76 ASMtoFORTH ; -- separator search word first
77 .word WORDD,FIND ; -- addr
78 .word QTBRAN,ARGWORD ; -- addr if Word found
80 .word QFBRAN,NotFound ; -- addr ABORT if not found
81 FSearchEnd .word SearchEnd ; -- value goto SearchEnd if number found
82 ARGWORD .word $+2 ; -- xt xt = CFA
84 QDOVAR SUB #DOVAR,X ; DOVAR = 1286h
85 ISDOVAR JZ SearchEnd ;
86 QDOCON ADD #1,X ; -- PFA DOCON = 1285h
87 ISNOTDOCON JNZ QDODOES ;
88 ISDOCON MOV @TOS,TOS ; -- cte
90 QDODOES ADD #2,TOS ; -- BODY leave BODY address for DOES words
91 ADD #1,X ; DODOES = 1284h
92 ISDODOES JZ SearchEnd ;
93 ISOTHER SUB #4,TOS ; -- CFA
94 SearchEnd POPM #2,S ; POPM T,S
97 ; Arg_Double_to_single conversion needed only for OPCODE type V|VI, 2th pass.
98 ARGD2S BIT #UF9,SR ; -- Lo Hi
100 MOV @PSP+,TOS ; -- Lo skip hi
101 ARGD2SEND MOV @RSP+,PC ;
103 ; ----------------------------------------------------------------------
104 ; DTCforthMSP430FR5xxx ASSEMBLER : search REG
105 ; ----------------------------------------------------------------------
107 ; compute arg of "xxxx(REG)," ; <== PARAM130, sep=','
108 ; compute arg of ",xxxx(REG)" ; <== PARAM210, sep=' '
109 ComputeARGParenREG ; sep -- Rn
110 MOV #'(',TOS ; -- "(" as WORD separator to find xxxx of "xxxx(REG),"
111 CALL #SearchARG ; -- xxxx aborted if not found
112 CALL #ARGD2S ; skip arg_hi if DOUBLE
115 MOV TOS,0(X) ; -- xxxx compile xxxx
116 MOV #')',TOS ; -- ")" prepare separator to search REG of "xxxx(REG)"
118 ; search REG of "xxxx(REG)," separator = ')'
119 ; search REG of ",xxxx(REG)" separator = ')'
120 ; search REG of "@REG," separator = ',' <== PARAM120
121 ; search REG of "@REG+," separator = '+' <== PARAM121
122 ; search REG of "REG," separator = ',' <== PARAM13
123 ; search REG of ",REG" separator = BL <== PARAM21
125 SearchREG PUSHM #2,S ; PUSHM S,T as OPCODE, OPCODEADR
126 PUSH &TOIN ; -- sep save >IN
127 ADD #1,&TOIN ; skip "R"
128 ASMtoFORTH ; search xx of Rxx
129 .word WORDD,QNUMBER ;
130 .word QFBRAN,NOTaREG ; -- xxxx if Not a Number
131 .word $+2 ; -- Rn number is found
132 ADD #2,RSP ; remove >IN
134 JC BOUNDERROR ; abort if Rn out of bounds
135 JNC SearchEnd ; -- Rn Z=0 ==> found
137 NOTaREG .word $+2 ; -- addr Z=1
138 MOV @RSP+,&TOIN ; -- addr restore >IN
139 JMP SearchEnd ; -- addr Z=1 ==> not a register
142 ; ----------------------------------------------------------------------
143 ; DTCforthMSP430FR5xxx ASSEMBLER : INTERPRET FIRST OPERAND
144 ; ----------------------------------------------------------------------
146 ; PARAM1 is used for OPCODES type I (double operand) and OPCODES type II (single operand) instructions
147 ; PARAM1 is used for OPCODES type V (double operand) and OPCODES type VI (single operand) extended instructions
149 ; PARAM1 separator -- ; parse input buffer until separator and compute first operand of opcode
150 ; sep is comma for src and space for dst .
151 PARAM1 mDOCOL ; -- sep OPCODES types I|V sep = ',' OPCODES types II|VI sep = ' '
152 .word FBLANK,SKIP ; -- sep addr
153 .word $+2 ; -- sep addr
154 MOV #0,S ; -- sep addr reset OPCODE
155 MOV &DDP,T ; -- sep addr HERE --> OPCODEADR (opcode is preset to its address !)
156 ADD #2,&DDP ; -- sep addr cell allot for opcode
157 MOV.B @TOS,W ; -- sep addr W=first char of instruction code
158 MOV @PSP+,TOS ; -- sep W=c-addr
159 CMP.B #'#',W ; -- sep W=first char
161 ; "#" found : case of "#xxxx,"
162 PARAM10 ADD #1,&TOIN ; -- sep skip # prefix
163 CALL #SearchARG ; -- xxxx abort if not found
164 CALL #ARGD2S ; skip arg_hi of OPCODE type V
165 MOV #0300h,S ; OPCODE = 0300h : MOV #0,dst is coded MOV R3,dst
166 CMP #0,TOS ; -- xxxx #0 ?
168 MOV #0310h,S ; OPCODE = 0310h : MOV #1,dst is coded MOV 0(R3),dst
169 CMP #1,TOS ; -- xxxx #1 ?
171 MOV #0320h,S ; OPCODE = 0320h : MOV #2,dst is coded MOV @R3,dst
172 CMP #2,TOS ; -- xxxx #2 ?
174 MOV #0220h,S ; OPCODE = 0220h : MOV #4,dst is coded MOV @R2,dst
175 CMP #4,TOS ; -- xxxx #4 ?
177 MOV #0230h,S ; OPCODE = 0230h : MOV #8,dst is coded MOV @R2+,dst
178 CMP #8,TOS ; -- xxxx #8 ?
180 MOV #0330h,S ; -- -1 OPCODE = 0330h : MOV #-1,dst is coded MOV @R3+,dst
181 CMP #-1,TOS ; -- xxxx #-1 ?
183 MOV #0030h,S ; -- xxxx for all other cases : MOV @PC+,dst
184 ; case of "&xxxx," ; <== PARAM110
185 ; case of ",&xxxx" ; <== PARAM20
186 StoreArg MOV &DDP,X ;
187 ADD #2,&DDP ; cell allot for arg
188 StoreTOS ; <== TYPE1DOES
189 MOV TOS,0(X) ; compile arg
190 ; endcase of all "&xxxx" ;
191 ; endcase of all "#xxxx" ; <== PARAM101,102,104,108,10M1
192 ; endcase of all "REG"|"@REG"|"@REG+" <== PARAM124
193 PARAMENDOF MOV @PSP+,TOS ; --
195 MOV @IP+,PC ; -- S=OPCODE,T=OPCODEADR
196 ; ----------------------------------;
197 PARAM11 CMP.B #'&',W ; -- sep
199 ; case of "&xxxx," ; -- sep search for "&xxxx,"
200 PARAM110 MOV #0210h,S ; -- sep set code type : xxxx(SR) with AS=0b01 ==> x210h (and SR=0 !)
202 ; case of ",&xxxx" ; <== PARAM20
203 PARAM111 ADD #1,&TOIN ; -- sep skip "&" prefix
204 CALL #SearchARG ; -- arg abort if not found
205 CALL #ARGD2S ; skip arg_hi of opcode type V
206 JMP StoreArg ; -- then ret
207 ; ----------------------------------;
208 PARAM12 CMP.B #'@',W ; -- sep
210 ; case of "@REG,"|"@REG+,"
211 PARAM120 MOV #0020h,S ; -- sep init OPCODE with indirect code type : AS=0b10
212 ADD #1,&TOIN ; -- sep skip "@" prefix
213 CALL #SearchREG ; Z = not found
214 JNZ PARAM123 ; -- value REG of "@REG," found
215 ; case of "@REG+," ; -- addr REG of "@REG" not found, search REG of "@REG+"
216 PARAM121 ADD #0010h,S ; change OPCODE from @REG to @REG+ type
217 MOV #'+',TOS ; -- "+" as WORD separator to find REG of "@REG+,"
218 CALL #SearchREG ; -- value|addr X = flag
220 ; case of "xxxx(REG)," ; <== PARAM130
221 ; case of double separator: +, and ),
222 PARAM122 CMP &SOURCE_LEN,&TOIN ; test OPCODE II parameter ending by REG+ or (REG) without comma,
223 JZ PARAM123 ; i.e. >IN = SOURCE_LEN : don't skip char CR !
224 ADD #1,&TOIN ; -- 000R skip "," ready for the second operand search
226 ; case of "xxxx(REG),"
227 ; case of "@REG," ; -- 000R <== PARAM120
228 ; case of "REG," ; -- 000R <== PARAM13
229 PARAM123 SWPB TOS ; -- 0R00 swap bytes because it's not a dst REG typeI (not a 2 ops inst.)
230 ; case of "@REG+," ; -- 0R00 (src REG typeI)
231 ; case of "xxxx(REG)," ; -- 0R00 (src REG typeI or dst REG typeII)
232 ; case of "@REG," ; -- 0R00 (src REG typeI)
233 ; case of "REG," ; -- 0R00 (src REG typeI or dst REG typeII)
234 ; case of ",REG" ; -- 000R <== PARAM21 (dst REG typeI)
235 ; case of ",xxxx(REG)" ; -- 000R <== PARAM210 (dst REG typeI)
236 PARAM124 ADD TOS,S ; -- 0R00|000R
238 ; ----------------------------------;
239 ; case of "REG,"|"xxxx(REG)," ; first, searg REG of "REG,"
240 PARAM13 CALL #SearchREG ; -- sep save >IN for second parsing (case of "xxxx(REG),")
241 JNZ PARAM123 ; -- 000R REG of "REG," found, S=OPCODE=0
242 ; case of "xxxx(REG)," ; -- c-addr "REG," not found
243 PARAM130 ADD #0010h,S ; AS=0b01 for indexing address
244 CALL #ComputeARGparenREG; compile xxxx and search REG of "(REG)"
247 ; ----------------------------------------------------------------------
248 ; DTCforthMSP430FR5xxx ASSEMBLER : INTERPRET 2th OPERAND
249 ; ----------------------------------------------------------------------
251 PARAM3 ; for OPCODES TYPE III
252 MOV #0,S ; init OPCODE=0
253 MOV &DDP,T ; T=OPCODEADR
254 ADD #2,&DDP ; make room for opcode
255 ; ----------------------------------;
256 PARAM2 mDOCOL ; parse input buffer until BL and compute this 2th operand
257 .word FBLANK,SKIP ; skip space(s) between "arg1," and "arg2" if any; use not S,T.
258 .word $+2 ; -- c-addr search for '&' of "&xxxx
260 MOV #20h,TOS ; -- ' ' as WORD separator to find xxxx of ",&xxxx"
261 JNE PARAM21 ; '&' not found
263 PARAM20 ADD #0082h,S ; change OPCODE : AD=1, dst = R2
264 JMP PARAM111 ; -- ' '
265 ; ----------------------------------;
266 ; case of ",REG"|",xxxx(REG) ; -- ' ' first, search REG of ",REG"
267 PARAM21 CALL #SearchREG ;
268 JNZ PARAM124 ; -- 000R REG of ",REG" found
269 ; case of ",xxxx(REG) ; -- addr REG not found
270 PARAM210 ADD #0080h,S ; set AD=1
271 CALL #ComputeARGparenREG; compile argument xxxx and search REG of "(REG)"
272 JMP PARAM124 ; -- 000R REG of "(REG) found
274 ; ----------------------------------------------------------------------
275 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODE TYPE 0 : zero operand f:-)
276 ; ----------------------------------------------------------------------
279 .word lit,1300h,COMMA,EXIT
281 ; ----------------------------------------------------------------------
282 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODES TYPE I : double operand
283 ; ----------------------------------------------------------------------
285 ; OPCODE(code) for TYPE I = 0bxxxx opcode I
287 ; = 0bxxxx src register
288 ; OPCODE(7) AD (dst addr type)
292 ; OPCODE(B) for TYPE I or TYPE II = 0b0 word
294 ; OPCODE(54) AS (src addr type)
295 ; OPCODE(AS) for TYPE I or OPCODE(AD) for TYPE II = 0b00 register
300 ; OPCODE(dst) for TYPE I or TYPE II = 0bxxxx dst register
301 ; ----------------------------------------------------------------------
303 ; TYPE1DOES -- BODYDOES search and compute PARAM1 & PARAM2 as src and dst operands then compile instruction
304 TYPE1DOES .word lit,',',PARAM1 ; -- BODYDOES
305 .word PARAM2 ; -- BODYDOES char separator (BL) included in PARAM2
307 MAKEOPCODE MOV T,X ; -- opcode X= OPCODEADR to compile opcode
308 MOV @TOS,TOS ; -- opcode part of instruction
309 BIS S,TOS ; -- opcode opcode is complete
310 JMP StoreTOS ; -- then EXIT
314 .word TYPE1DOES,4000h
317 .word TYPE1DOES,4040h
320 .word TYPE1DOES,5000h
323 .word TYPE1DOES,5040h
326 .word TYPE1DOES,6000h
329 .word TYPE1DOES,6040h
332 .word TYPE1DOES,7000h
335 .word TYPE1DOES,7040h
338 .word TYPE1DOES,8000h
341 .word TYPE1DOES,8040h
344 .word TYPE1DOES,9000h
347 .word TYPE1DOES,9040h
350 .word TYPE1DOES,0A000h
353 .word TYPE1DOES,0A040h
356 .word TYPE1DOES,0B000h
359 .word TYPE1DOES,0B040h
362 .word TYPE1DOES,0C000h
365 .word TYPE1DOES,0C040h
368 .word TYPE1DOES,0D000h
371 .word TYPE1DOES,0D040h
374 .word TYPE1DOES,0E000h
377 .word TYPE1DOES,0E040h
380 .word TYPE1DOES,0F000h
383 .word TYPE1DOES,0F040h
385 ; ----------------------------------------------------------------------
386 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES TYPE II : single operand
387 ; ----------------------------------------------------------------------
388 ; OPCODE(FEDCBA987) opcodeII
389 ; OPCODE(code) for TYPE II = 0bxxxxxxxxx
391 ; OPCODE(B) for TYPE I or TYPE II = 0b0 word
393 ; OPCODE(54) (dst addr type)
394 ; OPCODE(AS) for TYPE I or OPCODE(AD) for TYPE II = 0b00 register
399 ; OPCODE(dst) for TYPE I or TYPE II = 0bxxxx dst register
400 ; ----------------------------------------------------------------------
402 TYPE2DOES .word FBLANK,PARAM1 ; -- BODYDOES
405 AND #0070h,S ; keep B/W & AS infos in OPCODE
406 SWPB W ; (REG org --> REG dst)
407 AND #000Fh,W ; keep REG
408 BIS_ASMTYPE BIS W,S ; -- BODYDOES add it in OPCODE
409 JMP MAKEOPCODE ; -- then end
411 asmword "RRC" ; Rotate Right through Carry ( word)
413 .word TYPE2DOES,1000h
414 asmword "RRC.B" ; Rotate Right through Carry ( byte)
416 .word TYPE2DOES,1040h
417 asmword "SWPB" ; Swap bytes
419 .word TYPE2DOES,1080h
422 .word TYPE2DOES,1100h
425 .word TYPE2DOES,1140h
428 .word TYPE2DOES,1180h
431 .word TYPE2DOES,1200h
434 .word TYPE2DOES,1240h
437 .word TYPE2DOES,1280h
439 BOUNDERRWM1 ADD #1,W ; <== RRAM|RRUM|RRCM|RLAM error
440 BOUNDERRORW MOV W,TOS ; <== PUSHM|POPM|ASM_branch error
441 BOUNDERROR ; <== REG number error
442 mDOCOL ; -- n n = value out of bounds
444 .byte 13,"out of bounds"
447 ; --------------------------------------------------------------------------------
448 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES TYPE III : PUSHM|POPM|RLAM|RRAM|RRUM|RRCM
449 ; --------------------------------------------------------------------------------
450 ; PUSHM, syntax: PUSHM #n,REG with 0 < n < 17
451 ; POPM syntax: POPM #n,REG with 0 < n < 17
454 ; PUSHM order : PSP,TOS, IP, S, T, W, X, Y, rEXIT,rDOVAR,rDOCON, rDODOES, R3, SR,RSP, PC
455 ; PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8, R7 , R6 , R5 , R4 , R3, R2, R1, R0
457 ; example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
459 ; POPM order : PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT, Y, X, W, T, S, IP,TOS,PSP
460 ; POPM order : R0, R1, R2, R3, R4 , R5 , R6 , R7 , R8, R9,R10,R11,R12,R13,R14,R15
462 ; example : POPM #6,IP pulls Y,X,W,T,S,IP registers from return stack
464 ; RxxM syntax: RxxM #n,REG with 0 < n < 5
466 TYPE3DOES .word FBLANK,SKIP ; skip spaces if any
467 .word $+2 ; -- BODYDOES c-addr
468 ADD #1,&TOIN ; skip "#"
469 MOV #',',TOS ; -- BODYDOES ","
472 .word QFBRAN,NotFound ; ABORT
473 .word PARAM3 ; -- BODYDOES 0x000N S=OPCODE = 0x000R
475 MOV TOS,W ; -- BODYDOES n W = n
476 MOV @PSP+,TOS ; -- BODYDOES
477 SUB #1,W ; W = n floored to 0
479 MOV @TOS,X ; X=OPCODE
480 RLAM #4,X ; OPCODE bit 1000h --> C
481 JNC RxxMINSTRU ; if bit 1000h = 0
482 PxxxINSTRU MOV S,Y ; S=REG, Y=REG to test
483 RLAM #3,X ; OPCODE bit 0200h --> C
484 JNC PUSHMINSTRU ; W=n-1 Y=REG
485 POPMINSTRU SUB W,S ; to make POPM opcode, compute first REG to POP; TI is complicated....
486 PUSHMINSTRU SUB W,Y ; Y=REG-(n-1)
488 JC BOUNDERRWM1 ; JC=JHS (U>=)
489 RLAM #4,W ; W = n << 4
490 JMP BIS_ASMTYPE ; BODYDOES --
491 RxxMINSTRU CMP #4,W ;
492 JC BOUNDERRWM1 ; JC=JHS (U>=)
493 SWPB W ; -- BODYDOES W = n << 8
494 RLAM #2,W ; W = N << 10
495 JMP BIS_ASMTYPE ; BODYDOES --
499 .word TYPE3DOES,0040h
502 .word TYPE3DOES,0050h
505 .word TYPE3DOES,0140h
508 .word TYPE3DOES,0150h
511 .word TYPE3DOES,0240h
514 .word TYPE3DOES,0250h
517 .word TYPE3DOES,0340h
520 .word TYPE3DOES,0350h
523 .word TYPE3DOES,1400h
526 .word TYPE3DOES,1500h
529 .word TYPE3DOES,1600h
532 .word TYPE3DOES,1700h
534 ; ----------------------------------------------------------------------
535 ; DTCforthMSP430FR5xxx ASSEMBLER, CONDITIONAL BRANCHS
536 ; ----------------------------------------------------------------------
537 ; ASSEMBLER FORTH OPCODE(FEDC)
538 ; OPCODE(code) for TYPE JNE,JNZ 0<>, <> = 0x20xx + (offset AND 3FF) ; branch if Z = 0
539 ; OPCODE(code) for TYPE JEQ,JZ 0=, = = 0x24xx + (offset AND 3FF) ; branch if Z = 1
540 ; OPCODE(code) for TYPE JNC,JLO U< = 0x28xx + (offset AND 3FF) ; branch if C = 0
541 ; OPCODE(code) for TYPE JC,JHS U>= = 0x2Cxx + (offset AND 3FF) ; branch if C = 1
542 ; OPCODE(code) for TYPE JN 0< = 0x30xx + (offset AND 3FF) ; branch if N = 1
543 ; OPCODE(code) for TYPE JGE >= = 0x34xx + (offset AND 3FF) ; branch if (N xor V) = 0
544 ; OPCODE(code) for TYPE JL < = 0x38xx + (offset AND 3FF) ; branch if (N xor V) = 1
545 ; OPCODE(code) for TYPE JMP = 0x3Cxx + (offset AND 3FF)
547 asmword "S>=" ; if >= assertion (opposite of jump if < )
551 asmword "S<" ; if < assertion
555 asmword "0>=" ; if 0>= assertion ; use only with IF UNTIL WHILE !
559 asmword "0<" ; jump if 0< ; use only with ?JMP ?GOTO !
563 asmword "U<" ; if U< assertion
567 asmword "U>=" ; if U>= assertion
571 asmword "0<>" ; if <>0 assertion
575 asmword "0=" ; if =0 assertion
579 ;ASM IF OPCODE -- @OPCODE1
582 MOV TOS,0(W) ; compile incomplete opcode
587 ;ASM THEN @OPCODE -- resolve forward branch
589 ASM_THEN MOV &DDP,W ; -- @OPCODE W=dst
590 MOV TOS,Y ; Y=@OPCODE
591 ASM_THEN1 MOV @PSP+,TOS ; --
593 ADD #2,X ; -- Y=@OPCODE W=dst X=src+2
594 SUB X,W ; -- Y=@OPCODE W=dst-src+2=displacement*2 (bytes)
595 RRA W ; -- Y=@OPCODE W=displacement (words)
597 JC BOUNDERRORW ; (JHS) unsigned branch if u> 511
598 BIS W,0(Y) ; -- [@OPCODE]=OPCODE completed
601 ;C ELSE @OPCODE1 -- @OPCODE2 branch for IF..ELSE
603 ASM_ELSE MOV &DDP,W ; -- W=HERE
604 MOV #3C00h,0(W) ; compile unconditionnal branch
605 ADD #2,&DDP ; -- DP+2
607 MOV W,0(PSP) ; -- @OPCODE2 @OPCODE1
608 JMP ASM_THEN ; -- @OPCODE2
610 ;C UNTIL @BEGIN OPCODE -- resolve conditional backward branch
612 ASM_UNTIL MOV @PSP+,W ; -- OPCODE W=@BEGIN
613 ASM_UNTIL1 MOV TOS,Y ; Y=OPCODE W=@BEGIN
614 ASM_UNTIL2 MOV @PSP+,TOS ; --
615 MOV &DDP,X ; -- Y=OPCODE X=HERE W=dst
616 SUB #2,W ; -- Y=OPCODE X=HERE W=dst-2
617 SUB X,W ; -- Y=OPCODE X=src W=src-dst-2=displacement (bytes)
618 RRA W ; -- Y=OPCODE X=HERE W=displacement (words)
620 JL BOUNDERRORW ; signed branch if < -512
621 AND #3FFh,W ; -- Y=OPCODE X=HERE W=troncated negative displacement (words)
622 BIS W,Y ; -- Y=OPCODE (completed)
627 ;X AGAIN @BEGIN -- uncond'l backward branch
628 ; unconditional backward branch
630 ASM_AGAIN MOV TOS,W ; W=@BEGIN
631 MOV #3C00h,Y ; Y = asmcode JMP
634 ;C WHILE @BEGIN OPCODE -- @WHILE @BEGIN
636 ASM_WHILE mDOCOL ; -- @BEGIN OPCODE
637 .word ASM_IF,SWAP,EXIT
639 ;C REPEAT @WHILE @BEGIN -- resolve WHILE loop
641 ASM_REPEAT mDOCOL ; -- @WHILE @BEGIN
642 .word ASM_AGAIN,ASM_THEN,EXIT
644 ; ------------------------------------------------------------------------------------------
645 ; DTCforthMSP430FR5xxx ASSEMBLER : branch up to 3 backward labels and up to 3 forward labels
646 ; ------------------------------------------------------------------------------------------
647 ; used for non canonical branchs, as BASIC language: "goto line x"
648 ; labels BWx and FWx must be set at the beginning of line (>IN < 8).
649 ; FWx at the beginning of a line can resolve only one previous GOTO|?GOTO FWx.
650 ; BWx at the beginning of a line can be resolved by any subsequent GOTO|?GOTO BWx.
654 MOV TOS,Y ; -- PFA Y = ASMBWx addr
657 CMP #8,&TOIN ; are we colon 8 or more ?
658 BACKWUSE JC ASM_UNTIL1 ; yes, use this label
659 BACKWSET MOV &DDP,0(Y) ; no, set LABEL = DP
681 MOV @TOS,Y ; -- PFA Y=[ASMFWx]
682 CMP #8,&TOIN ; are we colon 8 or more ?
683 FORWUSE JNC ASM_THEN1 ; no: resolve FWx with W=DDP, Y=ASMFWx
684 FORWSET MOV @PSP+,0(W) ; yes compile incomplete opcode
685 ADD #2,&DDP ; increment DDP
686 MOV W,0(TOS) ; store @OPCODE into ASMFWx
706 ;ASM <cond> ?GOTO <label> OPCODE -- conditionnal branch to label
708 INVJMP CMP #3000h,TOS ; invert code jump process
709 JZ GOTONEXT ; case of JN, do nothing
710 XOR #0400h,TOS ; case of: JNZ<-->JZ JNC<-->JC JL<-->JGE
711 BIT #1000h,TOS ; 3xxxh case ?
713 XOR #0800h,TOS ; complementary action for JL<-->JGE
715 .word TICK ; -- OPCODE CFA<label>
718 ;ASM GOTO <label> -- unconditionnal branch to label
722 MOV #3C00h,TOS ; asmcode JMP
725 ; ===============================================================
727 ; ===============================================================
729 ; ===============================================================
730 ; to allow data access beyond $FFFF
731 ; ===============================================================
733 ; MOVA (#$x.xxxx|&$x.xxxx|$.xxxx(Rs)|Rs|@Rs|@Rs+ , &|Rd|$.xxxx(Rd))
734 ; ADDA (#$x.xxxx|Rs , Rd)
735 ; CMPA (#$x.xxxx|Rs , Rd)
736 ; SUBA (#$x.xxxx|Rs , Rd)
738 ; first argument process ACMS1
739 ;-----------------------------------;
740 ACMS1 mDOCOL ; -- BODYDOES ','
741 .word FBLANK,SKIP ; -- BODYDOES ',' addr
743 MOV.B @TOS,X ; X=first char of opcode string
744 MOV @PSP+,TOS ; -- BODYDOES ','
745 MOV @PSP+,S ; -- ',' S=BODYDOES
748 ADD #2,&DDP ; make room for opcode
749 ;-----------------------------------;
750 ACMS10 CMP.B #'R',X ; -- ','
752 ACMS101 CALL #SearchREG ; -- Rn src
753 ACMS102 RLAM #4,TOS ; 8<<src
755 ACMS103 BIS S,TOS ; update opcode with src|dst
756 MOV TOS,0(T) ; save opcode
757 MOV T,TOS ; -- OPCODE_addr
760 ;-----------------------------------;
761 ACMS11 CMP.B #'#',X ; -- ',' X=addr
763 BIC #40h,S ; set #opcode
764 ACMS111 ADD #1,&TOIN ; skip '#'|'&'
765 ADD #2,&DDP ; make room for low #$xxxx|&$xxxx|$xxxx(REG)
766 CALL #SearchARG ; -- Lo Hi
767 MOV @PSP+,2(T) ; -- Hi store $xxxx of #$x.xxxx|&$x.xxxx|$x.xxxx(REG)
768 AND #0Fh,TOS ; -- Hi sel Hi src
770 ;-----------------------------------;
771 MOVA12 CMP.B #'&',X ; -- ',' case of MOVA &$x.xxxx
773 XOR #00E0h,S ; set MOVA &$x.xxxx, opcode
775 ;-----------------------------------;
776 MOVA13 BIC #00F0h,S ; set MOVA @REG, opcode
777 CMP.B #'@',X ; -- ','
779 ADD #1,&TOIN ; skip '@'
780 CALL #SearchREG ; -- Rn
781 JNZ ACMS102 ; if @REG found
782 ;-----------------------------------;
783 BIS #0010h,S ; set @REG+ opcode
784 MOV #'+',TOS ; -- '+'
785 MOVA131 CALL #SearchREG ; -- Rn case of MOVA @REG+,|MOVA $x.xxxx(REG),
786 CMP &SOURCE_LEN,&TOIN ; test TYPE II first parameter ending by @REG+ (REG) without comma,
787 JZ ACMS102 ; i.e. may be >IN = SOURCE_LEN: don't skip char CR !
788 ADD #1,&TOIN ; skip "," ready for the second operand search
790 ;-----------------------------------;
791 MOVA14 BIS #0030h,S ; set xxxx(REG), opcode
792 ADD #2,&DDP ; -- ',' make room for first $xxxx of $0.xxxx(REG),
793 MOV #'(',TOS ; -- "(" as WORD separator to find xxxx of "xxxx(REG),"
794 CALL #SearchARG ; -- Lo Hi
795 MOV @PSP+,2(T) ; -- Hi store $xxxx as 2th word
796 MOV #')',TOS ; -- ')'
799 ; 2th argument process ACMS2
800 ;-----------------------------------;
801 ACMS2 mDOCOL ; -- OPCODE_addr
802 .word FBLANK,SKIP ; -- OPCODE_addr addr
804 MOV @PSP+,T ; -- addr T=OPCODE_addr
806 MOV.B @TOS,X ; -- addr X=first char of string instruction
807 MOV.B #' ',TOS ; -- ' '
808 ;-----------------------------------;
809 ACMS21 CMP.B #'R',X ; -- ' '
811 ACMS211 CALL #SearchREG ; -- Rn
813 ;-----------------------------------;
815 ADD #2,&DDP ; -- ' ' make room for $xxxx
818 BIS #060h,S ; set ,&$x.xxxx opcode
819 ADD #1,&TOIN ; skip '&'
820 CALL #SearchARG ; -- Lo Hi
821 MOV @PSP+,2(T) ; -- Hi store $xxxx as 2th word
822 JMP ACMS103 ; update opcode with dst $x and write opcode
823 ;-----------------------------------;
824 MOVA23 BIS #070h,S ; set ,xxxx(REG) opcode
825 MOV #'(',TOS ; -- "(" as WORD separator to find xxxx of "xxxx(REG),"
826 CALL #SearchARG ; -- Lo Hi
827 MOV @PSP+,2(T) ; -- Hi write $xxxx of ,$0.xxxx(REG) as 2th word
828 MOV #')',TOS ; -- ")" as WORD separator to find REG of "xxxx(REG),"
831 ; --------------------------------------------------------------------------------
832 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES IV 2 operands: Adda|Cmpa|Mova|Suba (without extended word)
833 ; --------------------------------------------------------------------------------
834 ; absolute and immediate instructions must be written as $x.xxxx (DOUBLE numbers)
835 ; indexed instructions must be written as $.xxxx(REG) (DOUBLE numbers)
836 ; --------------------------------------------------------------------------------
838 TYPE4DOES .word lit,',' ; -- BODYDOES "," char separator for PARAM1
839 .word ACMS1 ; -- OPCODE_addr
840 .word ACMS2 ; -- OPCODE_addr
845 .word TYPE4DOES,00C0h
848 .word TYPE4DOES,00D0h
851 .word TYPE4DOES,00E0h
854 .word TYPE4DOES,00F0h
856 ; --------------------------------------------------------------------------------
857 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODE TYPE III bis: CALLA (without extended word)
858 ; --------------------------------------------------------------------------------
859 ; absolute and immediate instructions must be written as $x.xxxx (DOUBLE numbers)
860 ; indexed instructions must be written as $.xxxx(REG) (DOUBLE numbers)
861 ; --------------------------------------------------------------------------------
865 .word FBLANK,SKIP ; -- addr
868 ADD #2,&DDP ; make room for opcode
869 MOV.B @TOS,TOS ; -- char First char of opcode
870 CALLA0 MOV #134h,S ; 134h<<4 = 1340h = opcode for CALLA Rn
873 CALLA01 MOV.B #' ',TOS ;
874 CALLA02 CALL #SearchREG ; -- Rn
875 CALLA03 RLAM #4,S ; (opcode>>4)<<4 = opcode
876 BIS TOS,S ; update opcode
877 MOV S,0(T) ; store opcode
881 ;-----------------------------------;
882 CALLA1 ADD #2,S ; 136h<<4 = opcode for CALLA @REG
883 CMP.B #'@',TOS ; -- char Search @REG
885 ADD #1,&TOIN ; skip '@'
886 MOV.B #' ',TOS ; -- ' '
888 JNZ CALLA03 ; if REG found, update opcode
889 ;-----------------------------------;
890 ADD #1,S ; 137h<<4 = opcode for CALLA @REG+
891 MOV #'+',TOS ; -- '+'
893 ;-----------------------------------;
894 CALLA2 ADD #2,&DDP ; make room for xxxx of #$x.xxxx|&$x.xxxx|$0.xxxx(REG)
897 MOV #13Bh,S ; 13Bh<<4 = opcode for CALLA #$x.xxxx
898 CALLA21 ADD #1,&TOIN ; skip '#'|'&'
899 CALLA22 CALL #SearchARG ; -- Lo Hi
900 MOV @PSP+,2(T) ; -- Hi store #$xxxx|&$xxxx
901 JMP CALLA03 ; update opcode with $x. and store opcode
902 ;-----------------------------------;
903 CALLA3 CMP.B #'&',TOS
905 ADD #2,S ; 138h<<4 = opcode for CALLA &$x.xxxx
907 ;-----------------------------------;
908 CALLA4 MOV.B #'(',TOS ; -- "("
909 SUB #1,S ; 135h<<4 = opcode for CALLA $0.xxxx(REG)
910 CALLA41 CALL #SearchARG ; -- Lo Hi
911 MOV @PSP+,2(T) ; -- Hi store $xxxx
912 MOV #')',TOS ; -- ')'
913 JMP CALLA02 ; search Rn and update opcode
916 ; PRMX1 is used for OPCODES type V (double operand) and OPCODES type VI (single operand) extended instructions
918 PRMX1 mDOCOL ; -- sep OPCODES type V|VI separator = ','|' '
919 .word FBLANK,SKIP ; -- sep addr
921 MOV.B @TOS,X ; -- sep addr X= first char of opcode string
922 MOV @PSP+,TOS ; -- sep
923 MOV #1800h,S ; init S=Extended word
924 ;-----------------------------------;
925 PRMX10 CMP.B #'R',X ; -- sep
927 PRMX101 CALL #SearchREG ; -- Rn Rn of REG; call SearchREG only to update >IN
928 PRMX102 MOV S,TOS ; -- EW update Extended word
930 MOV @IP+,PC ; -- Ext_Word
931 ;-----------------------------------;
932 PRMX11 MOV #0,&RPT_WORD ; clear RPT
933 CMP.B #'#',X ; -- sep
935 PRMX111 ADD #1,&TOIN ; -- sep skip '#'
936 PRMX112 CALL #SearchARG ; -- Lo Hi search $x.xxxx of #x.xxxx,
937 ADD #2,PSP ; -- Hi pop unused low word
938 PRMX113 AND #0Fh,TOS ;
940 RLAM #4,TOS ; -- 7<<Hi
941 PRMX115 BIS TOS,S ; update extended word with srcHi
943 ;-----------------------------------;
944 PRMX12 CMP.B #'&',X ; -- sep
946 ;-----------------------------------;
947 PRMX13 CMP.B #'@',X ; -- sep
949 PRMX131 ADD #1,&TOIN ; -- sep skip '@'
950 PRMX132 CALL #SearchREG ; -- Rn Rn of @REG,
951 JNZ PRMX102 ; if Rn found
952 ;-----------------------------------;
953 MOV #'+',TOS ; -- '+'
954 PRMX133 ADD #1,&TOIN ; skip '@'
955 CALL #SearchREG ; -- Rn Rn of @REG+,
956 PRMX134 CMP &SOURCE_LEN,&TOIN ; test case of TYPE VI first parameter without ','
957 JZ PRMX102 ; don't take the risk of skipping CR !
958 ADD #1,&TOIN ; skip ',' ready to search 2th operand
960 ;-----------------------------------;
961 PRMX14 MOV #'(',TOS ; -- '(' to find $x.xxxx of "x.xxxx(REG),"
962 CALL #SearchARG ; -- Lo Hi
963 MOV TOS,0(PSP) ; -- Hi Hi
964 PRMX141 MOV #')',TOS ; -- Hi ')'
965 CALL #SearchREG ; -- Hi Rn
966 MOV @PSP+,TOS ; -- Hi
970 ;-----------------------------------;
972 ; PRMX2 is used for OPCODES type V (double operand) extended instructions
974 ;-----------------------------------;
975 PRMX2 mDOCOL ; -- Extended_Word
976 .word FBLANK,SKIP ; -- Extended_Word addr
978 MOV @PSP+,S ; -- addr S=Extended_Word
979 MOV.B @TOS,X ; -- addr X=first char of code instruction
980 MOV #' ',TOS ; -- ' '
981 ;-----------------------------------;
982 PRMX20 CMP.B #'R',X ; -- ' '
983 JZ PRMX102 ; extended word not to be updated
984 ;-----------------------------------;
985 PRMX21 MOV #0,&RPT_WORD ;
988 PRMX211 ADD #1,&TOIN ; -- ' ' skip '&'
989 PRMX212 CALL #SearchARG ; -- Lo Hi
990 PRMX213 ADD #2,PSP ; -- hi pop low word
992 JMP PRMX115 ; update Extended word with dst_Hi
993 ;-----------------------------------;
994 PRMX22 MOV #'(',TOS ; -- '(' as WORD separator to find xxxx of "xxxx(REG)"
995 CALL #SearchARG ; -- Lo Hi search x.xxxx of x.xxxx(REG)
998 ;; UPDATE_eXtendedWord
999 ;;-----------------------------------;
1000 ;UPDATE_XW ; BODYDOES Extended_Word -- BODYDOES+2 >IN R--
1002 ; ADD #2,&DDP ; make room for extended word
1003 ; MOV TOS,S ; S = Extended_Word
1004 ; MOV @PSP+,TOS ; -- BODYDOES
1005 ; BIS &RPT_WORD,S ; update Extended_word with RPT_WORD
1006 ; MOV #0,&RPT_WORD ; clear RPT before next instruction
1007 ; BIS @TOS+,S ; -- BODYDOES+2 update Extended_word with [BODYDOES] = A/L bit
1008 ; MOV S,0(T) ; store extended word
1009 ; MOV @RSP+,&TOIN ; >IN R-- restore >IN at the start of instruction string
1011 ;;-----------------------------------;
1013 ;-----------------------------------;
1014 ; UPDATE_eXtendedWord
1015 ;-----------------------------------;
1016 UPDATE_XW ; BODYDOES >IN Extended_Word -- BODYDOES+2
1017 MOV @PSP+,&TOIN ; -- BODYDOES EW restore >IN at the start of instruction string
1019 ADD #2,&DDP ; make room for extended word
1020 MOV TOS,S ; S = Extended_Word
1022 BIS &RPT_WORD,S ; update Extended_word with RPT_WORD
1023 MOV #0,&RPT_WORD ; clear RPT before next instruction
1024 BIS @TOS+,S ; -- BODYDOES+2 update Extended_word with [BODYDOES] = A/L bit
1025 MOV S,0(T) ; store extended word
1027 ;-----------------------------------;
1029 ; --------------------------------------------------------------------------------
1030 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES V extended double operand
1031 ; --------------------------------------------------------------------------------
1032 ; absolute and immediate instructions must be written as $x.xxxx (DOUBLE numbers)
1033 ; indexed instructions must be written as $.xxxx(REG) (DOUBLE numbers)
1034 ; --------------------------------------------------------------------------------
1037 ; these instructions below are processed in two pass:
1038 ; pass 1: extended word process by TYPE5DOES with [BODYDOES] value
1039 ; pass 2: instruction process by TYPE1DOES with [BODYDOES+2] value
1040 ; all numeric arguments must be written as DOUBLE numbers (including a point) : $x.xxxx
1042 TYPE5DOES ; -- BODYDOES
1043 ; .word LIT,TOIN,FETCH,TOR ; R-- >IN save >IN for 2th pass
1044 ; .word lit,',' ; -- BODYDOES ',' char separator for PRMX1
1045 ; .word PRMX1,PRMX2 ; -- BODYDOES Extended_Word
1046 ; .word UPDATE_XW ; -- BODYDOES+2 >IN is restored ready for 2th pass
1047 ; .word BRAN,TYPE1DOES ; -- BODYDOES+2 2th pass: completes instruction with opcode = [BODYDOES+2]
1048 .word LIT,TOIN,FETCH ; -- BODYDOES >IN
1049 .word lit,',' ; -- BODYDOES >IN ',' char separator for PRMX1
1050 .word PRMX1,PRMX2 ; -- BODYDOES >IN Extended_Word
1051 .word UPDATE_XW ; -- BODYDOES+2 >IN is restored ready for 2th pass
1052 .word BRAN,TYPE1DOES ; -- BODYDOES+2 2th pass: completes instruction with opcode = [BODYDOES+2]
1056 .word TYPE5DOES ; [PFADOES] = TYPE5DOES
1057 .word 40h ; [BODYDOES] = A/L bit
1058 .word 4000h ; [BODYDOES+2] = OPCODE
1061 .word TYPE5DOES,0,4040h
1064 .word TYPE5DOES,40h,4040h
1067 .word TYPE5DOES,40h,5000h
1070 .word TYPE5DOES,0,5040h
1073 .word TYPE5DOES,40h,5040h
1076 .word TYPE5DOES,40h,6000h
1079 .word TYPE5DOES,0,6040h
1082 .word TYPE5DOES,40h,6040h
1085 .word TYPE5DOES,40h,7000h
1088 .word TYPE5DOES,0,7040h
1091 .word TYPE5DOES,40h,7040h
1094 .word TYPE5DOES,40h,8000h
1097 .word TYPE5DOES,0,8040h
1100 .word TYPE5DOES,40h,8040h
1103 .word TYPE5DOES,40h,9000h
1106 .word TYPE5DOES,0,9040h
1109 .word TYPE5DOES,40h,9040h
1112 .word TYPE5DOES,40h,0A000h
1115 .word TYPE5DOES,0,0A040h
1118 .word TYPE5DOES,40h,0A040h
1121 .word TYPE5DOES,40h,0B000h
1124 .word TYPE5DOES,0,0B040h
1127 .word TYPE5DOES,40h,0B040h
1130 .word TYPE5DOES,40h,0C000h
1133 .word TYPE5DOES,0,0C040h
1136 .word TYPE5DOES,40h,0C040h
1139 .word TYPE5DOES,40h,0D000h
1142 .word TYPE5DOES,0,0D040h
1145 .word TYPE5DOES,40h,0D040h
1148 .word TYPE5DOES,40h,0E000h
1151 .word TYPE5DOES,0,0E040h
1154 .word TYPE5DOES,40h,0E040h
1157 .word TYPE5DOES,40h,0F000h
1160 .word TYPE5DOES,0,0F040h
1163 .word TYPE5DOES,40h,0F040h
1165 ; --------------------------------------------------------------------------------
1166 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES VI extended single operand (take count of RPT)
1167 ; --------------------------------------------------------------------------------
1168 ; absolute and immediate instructions must be written as $x.xxxx (DOUBLE numbers)
1169 ; indexed instructions must be written as $.xxxx(REG) (DOUBLE numbers)
1170 ; --------------------------------------------------------------------------------
1172 ; these instructions below are processed in two pass:
1173 ; pass 1: extended word process by TYPE6DOES with [BODYDOES] value
1174 ; pass 2: instruction process by TYPE2DOES with [BODYDOES+2] value
1175 ; all numeric arguments must be written as DOUBLE numbers (including a point) : $x.xxxx
1177 TYPE6DOES ; -- BODYDOES
1178 ; .word LIT,TOIN,FETCH,TOR ; R-- >IN save >IN for 2th pass
1179 ; .word FBLANK ; -- BODYDOES ' '
1180 ; .word PRMX1 ; -- BODYDOES Extended_Word
1181 ; .word UPDATE_XW ; -- BODYDOES+2
1182 ; .word BRAN,TYPE2DOES ; -- BODYDOES+2 pass 2: completes instruction with opcode = [BODYDOES+2]
1183 .word LIT,TOIN,FETCH ; -- BODYDOES >IN
1184 .word FBLANK ; -- BODYDOES >IN ' '
1185 .word PRMX1 ; -- BODYDOES >IN Extended_Word
1186 .word UPDATE_XW ; -- BODYDOES+2
1187 .word BRAN,TYPE2DOES ; -- BODYDOES+2 pass 2: completes instruction with opcode = [BODYDOES+2]
1189 asmword "RRCX" ; ZC=0; RRCX Rx,Rx may be repeated by prefix RPT #n|Rn
1191 .word TYPE6DOES,40h,1000h
1192 asmword "RRCX.A" ; ZC=0; RRCX.A Rx may be repeated by prefix RPT #n|Rn
1194 .word TYPE6DOES,0,1040h
1195 asmword "RRCX.B" ; ZC=0; RRCX.B Rx may be repeated by prefix RPT #n|Rn
1197 .word TYPE6DOES,40h,1040h
1198 asmword "RRUX" ; ZC=1; RRUX Rx may be repeated by prefix RPT #n|Rn
1200 .word TYPE6DOES,140h,1000h
1201 asmword "RRUX.A" ; ZC=1; RRUX.A Rx may be repeated by prefix RPT #n|Rn
1203 .word TYPE6DOES,100h,1040h
1204 asmword "RRUX.B" ; ZC=1; RRUX.B Rx may be repeated by prefix RPT #n|Rn
1206 .word TYPE6DOES,140h,1040h
1209 .word TYPE6DOES,40h,1080h
1212 .word TYPE6DOES,0,1080h
1215 .word TYPE6DOES,40h,1100h
1218 .word TYPE6DOES,0,1140h
1221 .word TYPE6DOES,40h,1140h
1224 .word TYPE6DOES,40h,1180h
1227 .word TYPE6DOES,0,1180h
1230 .word TYPE6DOES,40h,1200h
1233 .word TYPE6DOES,0,1240h
1236 .word TYPE6DOES,40h,1240h
1238 ; ----------------------------------------------------------------------
1239 ; DTCforthMSP430FR5xxx ASSEMBLER, RPT instruction before REG|REG,REG eXtended instructions
1240 ; ----------------------------------------------------------------------
1241 ; RPT #1 is coded 0 in repetition count field (count n-1)
1242 ; please note that "RPT Rn" with [Rn]=0 has same effect as "RPT #1"
1246 asmword "RPT" ; RPT #n | RPT Rn repeat n | [Rn]+1 times modulo 16
1251 MOV.B #' ',TOS ; -- ' ' as separator
1254 CALL #SearchREG ; -- Rn
1255 JZ RPT1 ; if not found
1256 BIS #80h,TOS ; -- $008R R=Rn
1258 RPT1 CALL #SearchARG ; -- $xxxx
1260 AND #0Fh,TOS ; -- $000x
1261 RPT2 MOV TOS,&RPT_WORD