1 ; -*- coding: utf-8 -*-
3 ; ----------------------------------------------------------------------
4 ;forthMSP430FR_asm.asm 1584 bytes
5 ; ----------------------------------------------------------------------
7 ; ----------------------------------------------------------------------
8 ; MOV(.B) SR,dst is coded as follow : MOV(.B) R2,dst ; 1 cycle, one word AS=00 (register mode)
9 ; MOV(.B) #0,dst is coded as follow : MOV(.B) R3,dst ; 1 cycle, one word AS=00 (register mode)
10 ; MOV(.B) #1,dst is coded as follow : MOV(.B) (R3),dst ; 1 cycle, one word AS=01 ( x(reg) mode)
11 ; MOV(.B) #4,dst is coded as follow : MOV(.B) @R2,dst ; 1 cycle, one word AS=10 ( @reg mode)
12 ; MOV(.B) #2,dst is coded as follow : MOV(.B) @R3,dst ; 1 cycle, one word AS=10 ( @reg mode)
13 ; MOV(.B) #8,dst is coded as follow : MOV(.B) @R2+,dst ; 1 cycle, one word AS=11 ( @reg+ mode)
14 ; MOV(.B) #-1,dst is coded as follow : MOV(.B) @R3+,dst ; 1 cycle, one word AS=11 ( @reg+ mode)
15 ; ----------------------------------------------------------------------
16 ; MOV(.B) &EDE,dst is coded as follow : MOV(.B) EDE(R2),dst ; 3 cycles, two words AS=01 ( x(reg) mode)
17 ; MOV(.B) #xxxx,dst is coded as follow: MOV(.B) @PC+,dst ; 2 cycles, two words AS=11 ( @reg+ mode)
18 ; ----------------------------------------------------------------------
20 ; PUSHM order : PSP,TOS, IP, S, T, W, X, Y, rDOVAR,rDOCON,rDODOES, rDOCOL, R3, SR,RSP, PC
21 ; PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8, R7 , R6 , R5 , R4 , R3, R2, R1, R0
23 ; example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
25 ; POPM order : PC,RSP, SR, R3, rDOCOL,rDODOES,rDOCON,rDOVAR, Y, X, W, T, S, IP,TOS,PSP
26 ; POPM order : R0, R1, R2, R3, R4 , R5 , R6 , R7 , R8, R9,R10,R11,R12,R13,R14,R15
28 ; example : POPM #6,IP pop Y,X,W,T,S,IP registers from return stack
30 ; ----------------------------------------------------------------------
31 ; DTCforthMSP430FR5xxx ASSEMBLER : search argument "xxxx"
32 ; ----------------------------------------------------------------------
34 ; common code for 3 successive Searches: ARG, ARG+Offset, ARG-offset
35 ; part I: search symbolic ARG,
36 ; leave PFA of VARIABLE, [PFA] of CONSTANT, User_Parameter_Field_Address of MARKER_DOES, CFA for all others.
37 SearchARGn PUSH &TOIN ;4 push TOIN for iterative SearchARGn
38 mASM2FORTH ; -- sep sep = ','|'('|' '
39 .word WORDD,FIND ; -- addr search definition
40 .word QFBRAN,SRCHARGNUM ; -- addr if not found
41 mNEXTADR ; -- CFA of this definition
42 MOV @TOS+,S ; -- PFA S=DOxxx
43 SUB #1287h,S ; if CFA is DOVAR ?
44 JZ ARGFOUND ; -- addr yes, PFA = adr of VARIABLE
45 ADD #1,S ; is CFA is DOCON ?
47 MOV @TOS,TOS ; -- cte yes, TOS = constant
49 QMARKER CMP #MARKER_DOES,0(TOS) ; -- PFA search if PFA = [MARKER_DOES]
51 .IFDEF VOCABULARY_SET ; -- PFA
52 ADD #30,TOS ; -- UPFA+2 skip room for DP, CURRENT, CONTEXT(8), null_word, LASTVOC, RET_ADR 2+(2+2+16+2+2+2) bytes +2 !
54 ADD #8,TOS ; -- UPFA+2 skip room for DP, RET_ADR 2+(2+2) bytes +2 !
56 ISOTHER SUB #2,TOS ; -- ARG for all other cases
57 ARGFOUND ADD #2,RSP ; remove TOIN
58 MOV @RSP+,PC ;24 SR(Z)=0 if ARG found
59 ; Part II: search numeric ARG if symbolic ARG not found
60 SRCHARGNUM .word QNUMBER ;
61 .word QFBRAN,ARGNOTFOUND; -- addr
62 .word ARGFOUND ; -- ARG
63 ARGNOTFOUND mNEXTADR ; -- addr
64 MOV @RSP+,&TOIN ; restore TOIN
65 MOV @RSP+,PC ;32 return to caller with SR(Z)=1 if ARG not found
66 ; ----------------------------------;
68 ; ----------------------------------;
70 ; Search index of "xxxx(REG)," ; <== CompIdxSrchRn <== PARAM1IDX
71 ; Search index of ",xxxx(REG)" ; <== CompIdxSrchRn <== PARAM2IDX
72 ; Search index of "xxxx(REG)," ; <== CALLA, MOVA
73 ; Search index of ",xxxx(REG)" ; <== MOVA
74 SUB #1,&TOIN ; move >IN back one (unskip first_char)
75 MOV #'(',TOS ; addr -- "(" as WORD separator to find xxxx of "xxxx(REG),"
76 SearchARG ; sep -- n|d or abort" not found"
77 ; Search ARG of "#xxxx," ; <== PARAM1SHARP sep = ','
78 ; Search ARG of "&xxxx," ; <== PARAMXAMP sep = ','
79 ; Search ARG of ",&xxxx" ; <== PARAMXAMP <== PARAM2AMP sep = ' '
81 PUSHM #4,IP ; -- sep PUSHM IP,S,T,W as IP_RET,OPCODE,OPCODEADR,sep
82 CALL #SearchARGn ; first: search ARG without offset
83 JNZ SrchEnd ; -- ARG if ARG found
85 CALL #SearchARGn ; 2th: search ARG + offset
86 JNZ ArgPlusOfst ; -- ARG if ARG of ARG+offset found
88 CALL #SearchARGn ; 3th: search ARG - offset
89 SUB #1,&TOIN ; to handle offset with its minus sign
90 ArgPlusOfst PUSH TOS ; -- ARG R-- IP_RET,OPCODE,OPCODEADR,sep,ARG
91 MOV 2(RSP),TOS ; -- sep reload offset sep
92 mASM2FORTH ; search offset
93 .word WORDD,QNUMBER ; -- Ofst|c-addr flag
94 .word QFBRAN,FNOTFOUND ; -- c-addr no return, see TICK
96 ADD @RSP+,TOS ; -- Arg+Ofst
97 SrchEnd POPM #4,IP ; POPM W,T,S,IP common return for SearchARG and SearchRn
100 ; ----------------------------------------------------------------------
101 ; DTCforthMSP430FR5xxx ASSEMBLER : search REG
102 ; ----------------------------------------------------------------------
103 ; compute index of "xxxx(REG)," ; <== PARAM1IDX, sep=','
104 ; compute index of ",xxxx(REG)" ; <== PARAM2IDX, sep=' '
105 CompIdxSrchRn ; addr -- Rn|addr
106 CALL #SearchIndex ; -- xxxx aborted if not found
108 MOV TOS,0(X) ; -- xxxx compile ARG xxxx
110 MOV #')',TOS ; -- ")" prepare separator to search REG of "xxxx(REG)"
111 ; search REG of "xxxx(REG),"
112 ; search REG of ",xxxx(REG)"
113 ; search REG of "@REG," sep = ',' ; <== PARAM1AT
114 SkipRSrchRn ADD #1,&TOIN ; skip 'R' in input buffer
115 ; search REG of "@REG+," sep = '+' ; <== PARAM1ATPL
116 ; search REG of "REG," sep = ',' ; <== PARAM1REG
117 ; search REG of ",REG" sep = ' ' ; <== PARAM2REG
118 SearchRn MOV &TOIN,W ;3
119 PUSHM #4,IP ; PUSHM IP,S,T,W as IP_RET,OPCODE,OPCODEADR,TOIN
120 mASM2FORTH ; search xx of Rxx
121 .word WORDD,QNUMBER ;
122 .word QFBRAN,REGNOTFOUND; -- xxxx SR(Z)=1 if Not a Number
123 mNEXTADR ; -- Rn number is found
125 JNC SrchEnd ; -- Rn SR(Z)=0, Rn found,
126 JC REGNUM_ERR ; abort if Rn out of bounds
128 REGNOTFOUND mNEXTADR ; -- addr SR(Z)=1, (used in case of @REG not found),
129 MOV @RSP,&TOIN ; -- addr restore TOIN, ready for next SearchRn
130 JMP SrchEnd ; -- addr SR(Z)=1 ==> not a register
132 ; ----------------------------------------------------------------------
133 ; DTCforthMSP430FR5xxx ASSEMBLER : INTERPRET FIRST OPERAND
134 ; ----------------------------------------------------------------------
135 ; PARAM1 separator -- ; parse input buffer until separator and compute first operand of opcode
136 ; sep is "," for src TYPE II and " " for dst (TYPE II).
137 PARAM1 JNZ QPARAM1SHARP ; -- sep if prefix <> 'R'
139 CALL #SearchRn ; case of "REG,"
140 JNZ SWAPREG ; -- 000R REG of "REG," found, S=OPCODE=0
141 ; ----------------------------------;
142 QPARAM1SHARP CMP.B #'#',W ; -- sep W=first char
145 CALL #SearchARG ; -- xxxx abort if not found
146 MOV #0300h,S ; OPCODE = 0300h : MOV #0,dst is coded MOV R3,dst
147 CMP #0,TOS ; -- xxxx #0 ?
149 MOV #0310h,S ; OPCODE = 0310h : MOV #1,dst is coded MOV 0(R3),dst
150 CMP #1,TOS ; -- xxxx #1 ?
152 MOV #0320h,S ; OPCODE = 0320h : MOV #2,dst is coded MOV @R3,dst
153 CMP #2,TOS ; -- xxxx #2 ?
155 MOV #0330h,S ; OPCODE = 0330h : MOV #-1,dst is coded MOV @R3+,dst
156 CMP #-1,TOS ; -- xxxx #-1 ?
158 MOV #0220h,S ; OPCODE = 0220h : MOV #4,dst is coded MOV @R2,dst
159 CMP #4,TOS ; -- xxxx #4 ?
161 MOV #0230h,S ; OPCODE = 0230h : MOV #8,dst is coded MOV @R2+,dst
162 CMP #8,TOS ; -- xxxx #8 ?
164 MOV #0030h,S ; -- xxxx for all other cases : MOV @PC+,dst
165 ; endcase of "&xxxx," ; <== PARAM1AMP
166 ; endcase of ",&xxxx" ; <== PARAMXAMP <== PARAM2AMP
168 ADD #2,&DP ; cell allot for arg
169 MOV TOS,0(X) ; compile arg
171 ; ----------------------------------;
172 QPARAM1AMP CMP.B #'&',W ; -- sep
174 ; case of "&xxxx," ; search for "&xxxx,"
175 PARAM1AMP MOV #0210h,S ; set code type : xxxx(R2) with AS=0b01 ==> x210h
176 ; case of "&xxxx,"|",&xxxx" ; <== PARAM2AMP
177 PARAMXAMP CALL #SearchARG ;
178 JMP StoreArg ; -- then ret
179 ; ----------------------------------;
180 QPARAM1AT CMP.B #'@',W ; -- sep
182 ; case of "@REG,"|"@REG+,"
183 PARAM1AT MOV #0020h,S ; -- sep init OPCODE with indirect code type : AS=0b10
184 CALL #SkipRSrchRn ; Z = not found
185 JNZ SWAPREG ; -- Rn REG of "@REG," found
186 ; case of "@REG+," ; -- addr search REG of "@REG+"
187 PARAM1ATPL MOV #'+',TOS ; -- sep
189 JNZ PARAM1ATPLX ; -- Rn REG found
190 ; ----------------------------------; REG not found
191 ; case of "xxxx(REG)," ; -- sep OPCODE I
192 ; case of "xxxx(REG)" ; -- sep OPCODE II
193 PARAM1IDX CALL #CompIdxSrchRn ; -- 000R compile index xxxx and search REG of "(REG)", abort if xxxx not found
194 ; case of "@REG+,"|"xxxx(REG)," ; <== PARAM1ATPL OPCODE I
195 ; case of "@REG+"|"xxxx(REG)" ; <== PARAM1ATPL OPCODE II
196 PARAM1ATPLX BIS #0010h,S ; AS=0b01 for indexing address, AS=0b11 for @REG+
197 MOV #3FFFh,W ;2 4000h = first OPCODE type I
198 CMP S,W ;1 with OPCODE II @REG or xxxx(REG) don't skip CR !
199 ADDC #0,&TOIN ;1 with OPCODE I, @REG+, or xxxx(REG), skip "," ready for the second operand search
200 ; endcase of "@REG," ; -- 000R <== PARAM1AT
201 ; endcase of "REG," ; -- 000R <== PARAM1REG
202 SWAPREG SWPB TOS ; -- 0R00 swap bytes because it's not a dst REG typeI (not a 2 ops inst.)
203 ; endcase of ",REG" ; -- 0R0D <== PARAM2REG (dst REG typeI)
204 ; endcase of ",xxxx(REG)" ; -- 0R0D <== PARAM2IDX (dst REG typeI)
205 OPCODEPLREG ADD TOS,S ; -- 0R00|0R0D
206 ; endcase of all ; <== PARAM1SHARP PARAM1AMP PARAM2AMP
207 PARAMENDOF MOV @PSP+,TOS ; --
208 MOV @IP+,PC ; -- S=OPCODE,T=OPCODEADR
209 ; ----------------------------------;
211 ; ----------------------------------------------------------------------
212 ; DTCforthMSP430FR5xxx ASSEMBLER : INTERPRET 2th OPERAND
213 ; ----------------------------------------------------------------------
214 PARAM2 JNZ QPARAM2AMP ; -- sep if prefix <> 'R'
215 PARAM2REG CALL #SearchRn ; -- sep case of ",REG"
216 JNZ OPCODEPLREG ; -- 000D REG of ",REG" found
217 ; ----------------------------------;
218 QPARAM2AMP CMP.B #'&',W ;
219 JNZ PARAM2IDX ; '&' not found
221 PARAM2AMP BIS #0082h,S ; change OPCODE : AD=1, dst = R2
222 JMP PARAMXAMP ; -- ' '
223 ; ----------------------------------;
224 ; case of ",xxxx(REG) ; -- sep
225 PARAM2IDX BIS #0080h,S ; set AD=1
226 CALL #CompIdxSrchRn ; compile index xxxx and search REG of ",xxxx(REG)", abort if xxxx not found
227 JNZ OPCODEPLREG ; -- 000D if REG found
228 MOV #NOTFOUND,PC ; does ABORT" ?"
229 ; ----------------------------------;
231 ; ----------------------------------------------------------------------------------------
232 ; DTCforthMSP430FR5xxx ASSEMBLER: reset OPCODE in S reg, set OPCODE addr in T reg,
233 ; move Prefix in W reg, skip prefix in input buffer. Flag SR(Z)=1 if prefix = 'R'.
234 ; ----------------------------------------------------------------------------------------
236 MOV #0,S ; reset OPCODE
237 MOV &DP,T ; HERE --> OPCODEADR
238 ADD #2,&DP ; cell allot for opcode
239 ; SkipPrfx ; -- skip all occurring char 'BL', plus one prefix
240 SkipPrfx MOV #20h,W ; -- W=BL
243 SKIPLOOP CMP.B @X+,W ; -- W=BL does character match?
245 MOV.B -1(X),W ; W=prefix
246 SUB &SOURCE_ORG,X ; --
247 MOV X,&TOIN ; -- >IN points after prefix
248 CMP.B #'R',W ; preset SR(Z)=1 if prefix = 'R'
251 ; ----------------------------------------------------------------------
252 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODE TYPE 0 : zero operand :-)
253 ; ----------------------------------------------------------------------
256 .word lit,1300h,COMMA,EXIT
258 ; ----------------------------------------------------------------------
259 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODES TYPE I : double operand
260 ; ----------------------------------------------------------------------
262 ; OPCODE(code) = 0bxxxx opcode
264 ; = 0bxxxx src_register,
265 ; OPCODE(7) AD (dst addr type)
269 ; OPCODE(B) = 0b0 word
271 ; OPCODE(54) AS (src addr type)
272 ; OPCODE(AS) = 0b00 register,
277 ; OPCODE(dst) = 0bxxxx ,dst_register
278 ; ----------------------------------------------------------------------
280 ; TYPE1DOES -- BODYDOES search and compute PARAM1 & PARAM2 as src and dst operands then compile instruction
281 TYPE1DOES .word lit,',' ; -- sep
282 .word InitAndSkipPrfx ; init S=0, T=DP, DP=DP+2 then skip prefix, SR(Z)=1 if prefix = 'R'
283 .word PARAM1 ; -- BODYDOES S=OPCODE,T=OPCODEADR
284 .word BL,SkipPrfx ; -- sep SR(Z)=1 if prefix = 'R'
285 .word PARAM2 ; -- BODYDOES S=OPCODE,T=OPCODEADR
287 MAKEOPCODE MOV @RSP+,IP
288 BIS @TOS,S ; -- opcode generic opcode + customized S
289 MOV S,0(T) ; -- opcode store complete opcode
290 JMP PARAMENDOF ; -- then EXIT
294 .word TYPE1DOES,4000h
297 .word TYPE1DOES,4040h
300 .word TYPE1DOES,5000h
303 .word TYPE1DOES,5040h
306 .word TYPE1DOES,6000h
309 .word TYPE1DOES,6040h
312 .word TYPE1DOES,7000h
315 .word TYPE1DOES,7040h
318 .word TYPE1DOES,8000h
321 .word TYPE1DOES,8040h
324 .word TYPE1DOES,9000h
327 .word TYPE1DOES,9040h
330 .word TYPE1DOES,0A000h
333 .word TYPE1DOES,0A040h
336 .word TYPE1DOES,0B000h
339 .word TYPE1DOES,0B040h
342 .word TYPE1DOES,0C000h
345 .word TYPE1DOES,0C040h
348 .word TYPE1DOES,0D000h
351 .word TYPE1DOES,0D040h
354 .word TYPE1DOES,0E000h
357 .word TYPE1DOES,0E040h
360 .word TYPE1DOES,0F000h
363 .word TYPE1DOES,0F040h
365 ; ----------------------------------------------------------------------
366 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES TYPE II : single operand
367 ; ----------------------------------------------------------------------
369 ; OPCODE(code) = 0bxxxxxxxxx
371 ; OPCODE(B) = 0b0 word
373 ; OPCODE(54) (dst addr type)
374 ; OPCODE(AS) = 0b00 register
379 ; OPCODE(dst) = 0bxxxx dst register
380 ; ----------------------------------------------------------------------
382 TYPE2DOES ; -- BODYDOES
383 .word BL ; -- BODYDOES ' '
384 .word InitAndSkipPrfx ;
385 .word PARAM1 ; -- BODYDOES S=OPCODE,T=OPCODEADR
388 AND #0070h,S ; keep B/W & AS infos in OPCODE
389 SWPB W ; (REG org --> REG dst)
390 AND #000Fh,W ; keep REG
391 BIS_ASMTYPE BIS W,S ; -- BODYDOES add it in OPCODE
392 JMP MAKEOPCODE ; -- then end
394 asmword "RRC" ; Rotate Right through Carry ( word)
396 .word TYPE2DOES,1000h
397 asmword "RRC.B" ; Rotate Right through Carry ( byte)
399 .word TYPE2DOES,1040h
400 asmword "SWPB" ; Swap bytes
402 .word TYPE2DOES,1080h
405 .word TYPE2DOES,1100h
408 .word TYPE2DOES,1140h
411 .word TYPE2DOES,1180h
414 .word TYPE2DOES,1200h
417 .word TYPE2DOES,1240h
420 .word TYPE2DOES,1280h
422 ; ----------------------------------------------------------------------
424 ; ----------------------------------------------------------------------
426 MUL_REG_ERR ADD #1,W ; <== PUSHM|POPM|RRAM|RRUM|RRCM|RLAM error
427 BRANCH_ERR MOV W,TOS ; <== ASM_branch error
428 REGNUM_ERR ; <== REG number error
429 mASM2FORTH ; -- n n = value out of bounds
431 .byte 13,"out of bounds"
434 ; ----------------------------------------------------------------------
435 ; DTCforthMSP430FR5xxx ASSEMBLER, CONDITIONAL BRANCHS
436 ; ----------------------------------------------------------------------
437 ; ASSEMBLER FORTH OPCODE(FEDC)
438 ; OPCODE(code) for TYPE JNE,JNZ 0<>, <> = 0x20xx + (offset AND 3FF) ; branch if Z = 0
439 ; OPCODE(code) for TYPE JEQ,JZ 0=, = = 0x24xx + (offset AND 3FF) ; branch if Z = 1
440 ; OPCODE(code) for TYPE JNC,JLO U< = 0x28xx + (offset AND 3FF) ; branch if C = 0
441 ; OPCODE(code) for TYPE JC,JHS U>= = 0x2Cxx + (offset AND 3FF) ; branch if C = 1
442 ; OPCODE(code) for TYPE JN 0< = 0x30xx + (offset AND 3FF) ; branch if N = 1
443 ; OPCODE(code) for TYPE JGE >= = 0x34xx + (offset AND 3FF) ; branch if (N xor V) = 0
444 ; OPCODE(code) for TYPE JL < = 0x38xx + (offset AND 3FF) ; branch if (N xor V) = 1
445 ; OPCODE(code) for TYPE JMP = 0x3Cxx + (offset AND 3FF)
447 asmword "S>=" ; if >= assertion (opposite of jump if < )
451 asmword "S<" ; if < assertion
455 asmword "0>=" ; if 0>= assertion ; use only with IF UNTIL WHILE !
459 asmword "0<" ; jump if 0< ; use only with ?GOTO !
463 asmword "U<" ; if U< assertion
467 asmword "U>=" ; if U>= assertion
471 asmword "0<>" ; if <>0 assertion
475 asmword "0=" ; if =0 assertion
479 ;ASM IF OPCODE -- @OPCODE1
482 MOV TOS,0(W) ; compile incomplete opcode
487 ;ASM THEN @OPCODE -- resolve forward branch
489 ASM_THEN MOV &DP,W ; -- @OPCODE W=dst
490 MOV TOS,Y ; Y=@OPCODE
491 ASM_THEN1 MOV @PSP+,TOS ; --
493 ADD #2,X ; -- Y=@OPCODE W=dst X=src+2
494 SUB X,W ; -- Y=@OPCODE W=dst-src+2=displacement (bytes)
496 JC BRANCH_ERR ; (JHS) unsigned branch if displ. > 1022 bytes
497 RRA W ; -- Y=@OPCODE W=displacement (words)
498 BIS W,0(Y) ; -- [@OPCODE]=OPCODE completed
501 ; ELSE @OPCODE1 -- @OPCODE2 branch for IF..ELSE
503 MOV &DP,W ; -- W=HERE
504 MOV #3C00h,0(W) ; compile unconditionnal branch
507 MOV W,0(PSP) ; -- @OPCODE2 @OPCODE1
508 JMP ASM_THEN ; -- @OPCODE2
510 ; BEGIN -- BEGINadr initialize backward branch
517 ; UNTIL @BEGIN OPCODE -- resolve conditional backward branch
519 MOV @PSP+,W ; -- OPCODE W=@BEGIN
520 ASM_UNTIL1 MOV TOS,Y ; Y=OPCODE W=@BEGIN
521 ASM_UNTIL2 MOV @PSP+,TOS ; --
522 MOV &DP,X ; -- Y=OPCODE X=HERE W=dst
523 SUB #2,W ; -- Y=OPCODE X=HERE W=dst-2
524 SUB X,W ; -- Y=OPCODE X=src W=src-dst-2=displacement (bytes)
526 JL BRANCH_ERR ; signed branch if displ. < -1024 bytes
527 RRA W ; -- Y=OPCODE X=HERE W=displacement (words)
528 AND #3FFh,W ; -- Y=OPCODE X=HERE W=troncated negative displacement (words)
529 BIS W,Y ; -- Y=OPCODE (completed)
534 ; AGAIN @BEGIN -- uncond'l backward branch
535 ; unconditional backward branch
537 ASM_AGAIN MOV TOS,W ; W=@BEGIN
538 MOV #3C00h,Y ; Y = asmcode JMP
541 ; WHILE @BEGIN OPCODE -- @WHILE @BEGIN
543 mDOCOL ; -- @BEGIN OPCODE
544 .word ASM_IF,SWAP,EXIT
546 ; REPEAT @WHILE @BEGIN -- resolve WHILE loop
548 mDOCOL ; -- @WHILE @BEGIN
549 .word ASM_AGAIN,ASM_THEN,EXIT
551 ; ------------------------------------------------------------------------------------------
552 ; DTCforthMSP430FR5xxx ASSEMBLER : branch up to 3 backward labels and up to 3 forward labels
553 ; ------------------------------------------------------------------------------------------
554 ; used for non canonical branchs, as BASIC language: "goto line x"
555 ; labels BWx and FWx must be set at the beginning of line (>IN < 8).
556 ; FWx can resolve only one previous GOTO|?GOTO FWx.
557 ; BWx can resolve any subsequent GOTO|?GOTO BWx.
562 MOV TOS,Y ; -- BODY Y = BWx addr
565 CMP #8,&TOIN ; are we colon 8 or more ?
566 JC ASM_UNTIL1 ; yes, use this label
567 MOV &DP,0(Y) ; no, set LABEL = DP
573 .word BACKWDOES ; PFA
574 .word ASMBW1 ; in RAM
579 .word ASMBW2 ; in RAM
584 .word ASMBW3 ; in RAM
590 MOV @TOS,Y ; -- BODY Y=@OPCODE of FWx
591 MOV #0,0(TOS) ; V3.9: clear @OPCODE of FWx to avoid jmp resolution without label
592 CMP #8,&TOIN ; are we colon 8 or more ?
593 FORWUSE JNC ASM_THEN1 ; no: resolve FWx with W=DP, Y=@OPCODE
594 FORWSET MOV @PSP+,0(W) ; yes compile opcode (without displacement)
595 ADD #2,&DP ; increment DP
596 MOV W,0(TOS) ; store @OPCODE into BODY of FWx
604 .word ASMFW1 ; in RAM
609 .word ASMFW3 ; in RAM
614 .word ASMFW3 ; in RAM
616 ;ASM GOTO <label> -- unconditionnal branch to label
620 MOV #3C00h,TOS ; -- JMP_OPCODE
622 .word TICK ; -- OPCODE CFA<label>
625 ;ASM <cond> ?GOTO <label> OPCODE -- conditionnal branch to label
627 INVJMP CMP #3000h,TOS ; invert code jump process
628 JZ GOTONEXT ; case of JN, do nothing
629 XOR #0400h,TOS ; case of: JNZ<-->JZ JNC<-->JC JL<-->JGE
630 BIT #1000h,TOS ; 3xxxh case ?
632 XOR #0800h,TOS ; complementary action for JL<-->JGE
635 ; --------------------------------------------------------------------------------
636 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES TYPE III : PUSHM|POPM|RLAM|RRAM|RRUM|RRCM
637 ; --------------------------------------------------------------------------------
638 ; PUSHM, syntax: PUSHM #n,REG with 0 < n < 17
639 ; POPM syntax: POPM #n,REG with 0 < n < 17
642 ; PUSHM order : PSP,TOS, IP, S, T, W, X, Y, rEXIT,rDOVAR,rDOCON, rDODOES, R3, SR,RSP, PC
643 ; PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8, R7 , R6 , R5 , R4 , R3, R2, R1, R0
645 ; example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
647 ; POPM order : PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT, Y, X, W, T, S, IP,TOS,PSP
648 ; POPM order : R0, R1, R2, R3, R4 , R5 , R6 , R7 , R8, R9,R10,R11,R12,R13,R14,R15
650 ; example : POPM #6,IP pulls Y,X,W,T,S,IP registers from return stack
652 ; RxxM syntax: RxxM #n,REG with 0 < n < 5
654 TYPE3DOES ; -- BODYDOES
655 .word LIT,',' ; -- BODYDOES ','
657 .word WORDD,QNUMBER ;
658 .word QFBRAN,FNOTFOUND; see INTERPRET
659 .word BL ; -- BODYDOES n ' '
660 .word InitAndSkipPrfx ; -- BODYDOES n ' '
661 .word PARAM2 ; -- BODYDOES n S=OPCODE = 0x000R
663 MOV TOS,W ; -- BODYDOES n W = n
664 MOV @PSP+,TOS ; -- BODYDOES
665 SUB #1,W ; W = n floored to 0
667 MOV @TOS,X ; X=OPCODE
668 RLAM #4,X ; OPCODE bit 1000h --> C
669 JNC RxxMINSTRU ; if bit 1000h = 0
670 PxxxINSTRU MOV S,Y ; S=REG, Y=REG to test
671 RLAM #3,X ; OPCODE bit 0200h --> C
672 JNC PUSHMINSTRU ; W=n-1 Y=REG
673 POPMINSTRU SUB W,S ; to make POPM opcode, compute first REG to POP; TI is complicated....
674 PUSHMINSTRU SUB W,Y ; Y=REG-(n-1)
676 JC MUL_REG_ERR ; JC=JHS (U>=)
677 RLAM #4,W ; W = n << 4
678 JMP BIS_ASMTYPE ; BODYDOES --
679 RxxMINSTRU CMP #4,W ;
680 JC MUL_REG_ERR ; JC=JHS (U>=)
682 RLAM #2,W ; W = N << 10
683 JMP BIS_ASMTYPE ; BODYDOES --
687 .word TYPE3DOES,0050h
690 .word TYPE3DOES,0150h
693 .word TYPE3DOES,0250h
696 .word TYPE3DOES,0350h
699 .word TYPE3DOES,1500h
702 .word TYPE3DOES,1700h
707 .word TYPE3DOES,0040h
710 .word TYPE3DOES,0140h
713 .word TYPE3DOES,0240h
716 .word TYPE3DOES,0340h
719 .word TYPE3DOES,1400h
722 .word TYPE3DOES,1600h
724 ; --------------------------------------------------------------------------------
725 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODE TYPE III bis: CALLA (without extended word)
726 ; --------------------------------------------------------------------------------
727 ; absolute and immediate instructions must be written as $x.xxxx (DOUBLE numbers with dot)
728 ; indexed instructions must be written as $xxxx(REG)
729 ; --------------------------------------------------------------------------------
733 .word InitAndSkipPrfx ; -- sep SR(Z)=1 if prefix = 'R'
736 CALLA0 MOV #134h,S ; 134h<<4 = 1340h = opcode for CALLA Rn
737 JNZ CALLA1 ; -- sep if prefix <> 'R'
738 CALLA01 CALL #SearchRn ; -- Rn
739 CALLA02 RLAM #4,S ; (opcode>>4)<<4 = opcode
740 BIS TOS,S ; update opcode with Rn|$x
741 MOV S,0(T) ; store opcode
744 ;-----------------------------------;
745 CALLA1 ADD #2,S ; -- sep 136h<<4 = opcode for CALLA @REG
746 CMP.B #'@',W ; Search @REG
748 CALLA11 CALL #SkipRSrchRn ;
749 JNZ CALLA02 ; if REG found, update opcode
750 ;-----------------------------------;
751 ADD #1,S ; 137h<<4 = opcode for CALLA @REG+
752 MOV #'+',TOS ; -- sep
754 ;-----------------------------------;
755 CALLA2 ADD #2,&DP ; -- sep make room for xxxx of #$x.xxxx|&$x.xxxx|$xxxx(REG)
758 MOV #13Bh,S ; 13Bh<<4 = opcode for CALLA #$x.xxxx
759 CALLA21 CALL #SearchARG ; -- Lo Hi
760 MOV @PSP+,2(T) ; -- Hi store $xxxx of #$x.xxxx|&$x.xxxx
761 JMP CALLA02 ; update opcode with $x. and store opcode
762 ;-----------------------------------;
763 CALLA3 CMP.B #'&',W ; -- sep
765 ADD #2,S ; 138h<<4 = opcode for CALLA &$x.xxxx
767 ;-----------------------------------;
768 CALLA4 SUB #1,S ; 135h<<4 = opcode for CALLA $xxxx(REG)
769 CALLA41 CALL #SearchIndex ; -- n
770 MOV TOS,2(T) ; -- n store $xxxx of $xxxx(REG)
771 MOV #')',TOS ; -- sep
772 JMP CALLA11 ; search Rn and update opcode
774 ; ===============================================================
775 ; to allow data access beyond $FFFF
776 ; ===============================================================
778 ; MOVA #$x.xxxx|&$x.xxxx|$xxxx(Rs)|Rs|@Rs|@Rs+ , &$x.xxxx|$xxxx(Rd)|Rd
779 ; ADDA (#$x.xxxx|Rs , Rd)
780 ; CMPA (#$x.xxxx|Rs , Rd)
781 ; SUBA (#$x.xxxx|Rs , Rd)
783 ; first argument process ACMS1
784 ;-----------------------------------;
785 ACMS1 MOV @PSP+,S ; -- sep S=BODYDOES
787 ;-----------------------------------;
788 ACMS10 JNZ ACMS11 ; -- sep if prefix <> 'R'
789 ACMS101 CALL #SearchRn ; -- Rn
790 ACMS102 RLAM #4,TOS ; 8<<src
792 ACMS103 BIS S,TOS ; update opcode with src|dst
793 MOV TOS,0(T) ; save opcode
794 MOV T,TOS ; -- OPCODE_addr
796 ;-----------------------------------;
797 ACMS11 CMP.B #'#',W ; -- sep X=addr
799 BIC #40h,S ; set #opcode
800 ACMS111 ADD #2,&DP ; make room for low #$xxxx|&$xxxx|$xxxx(REG)
801 CALL #SearchARG ; -- Lo Hi
802 MOV @PSP+,2(T) ; -- Hi store $xxxx of #$x.xxxx|&$x.xxxx|$xxxx(REG)
803 AND #0Fh,TOS ; -- Hi sel Hi src
805 ;-----------------------------------;
806 MOVA12 CMP.B #'&',W ; -- sep case of MOVA &$x.xxxx
808 XOR #00E0h,S ; set MOVA &$x.xxxx, opcode
810 ;-----------------------------------;
811 MOVA13 BIC #00F0h,S ; set MOVA @REG, opcode
812 CMP.B #'@',W ; -- sep
814 CALL #SkipRSrchRn ; -- Rn
815 JNZ ACMS102 ; if @REG found
816 BIS #0010h,S ; set @REG+ opcode
817 MOV #'+',TOS ; -- '+'
818 MOVA131 CALL #SearchRn ; -- Rn case of MOVA @REG+,|MOVA $x.xxxx(REG),
819 MOVA132 ADD #1,&TOIN ; skip "," ready for the second operand search
821 ;-----------------------------------;
822 MOVA14 BIS #0030h,S ; -- sep set xxxx(REG), opcode
823 ADD #2,&DP ; make room for first $xxxx of $xxxx(REG),
824 CALL #SearchIndex ; -- n
825 MOV TOS,2(T) ; -- n store $xxxx as 2th word
826 MOV #')',TOS ; -- ')'
827 CALL #SkipRSrchRn ; -- Rn
830 ; 2th argument process ACMS2
831 ;-----------------------------------; -- OPCODE_addr sep
832 ACMS2 MOV @PSP+,T ; -- sep T=OPCODE_addr
834 ;-----------------------------------;
835 ACMS21 JNZ MOVA22 ; -- sep if prefix <> 'R'
836 ACMS211 CALL #SearchRn ; -- Rn
838 ;-----------------------------------;
839 MOVA22 BIC #0F0h,S ; -- sep
840 ADD #2,&DP ; make room for $xxxx
843 BIS #060h,S ; set ,&$x.xxxx opcode
844 CALL #SearchARG ; -- Lo Hi
845 MOV @PSP+,2(T) ; -- Hi store $xxxx as 2th word
846 JMP ACMS103 ; update opcode with dst $x and write opcode
847 ;-----------------------------------;
848 MOVA23 BIS #070h,S ; set ,xxxx(REG) opcode
849 CALL #SearchIndex ; -- n
850 MOV TOS,2(T) ; -- n write $xxxx of ,$xxxx(REG) as 2th word
851 MOV #')',TOS ; -- ")" as WORD separator to find REG of "xxxx(REG),"
852 CALL #SkipRSrchRn ; -- Rn
855 ; --------------------------------------------------------------------------------
856 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES IV 2 operands: Adda|Cmpa|Mova|Suba (without extended word)
857 ; --------------------------------------------------------------------------------
858 ; absolute and immediate instructions must be written as $x.xxxx (DOUBLE numbers)
859 ; indexed instructions must be written as $.xxxx(REG) (DOUBLE numbers)
860 ; --------------------------------------------------------------------------------
861 TYPE4DOES .word lit,',' ; -- BODYDOES "," char separator for PARAM1
862 .word InitAndSkipPRFX ; SR(Z)=1 if prefix = 'R'
863 .word ACMS1 ; -- OPCODE_addr
864 .word BL,SkipPRFX ; SR(Z)=1 if prefix = 'R'
865 .word ACMS2 ; -- OPCODE_addr
870 .word TYPE4DOES,00C0h
873 .word TYPE4DOES,00D0h
876 .word TYPE4DOES,00E0h
879 .word TYPE4DOES,00F0h