OSDN Git Service

fixed ASSEMBLER crash
[fast-forth/master.git] / forthMSP430FR_ASM.asm
1 ; -*- coding: utf-8 -*-
2 ; http://patorjk.com/software/taag/#p=display&f=Banner&t=Fast Forth
3
4 ; Fast Forth For Texas Instrument MSP430FRxxxx FRAM devices
5 ; Copyright (C) <2017>  <J.M. THOORENS>
6 ;
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.
11 ;
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.
16 ;
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/>.
19
20
21 ; ----------------------------------------------------------------------
22 ;forthMSP430FR_asm.asm
23 ; ----------------------------------------------------------------------
24
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 ; ----------------------------------------------------------------------
35
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
38
39 ; example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
40 ;
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
43
44 ; example : POPM #6,IP   pop Y,X,W,T,S,IP registers from return stack
45
46
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
60 SKIPEND     MOV TOS,W               ;
61             SUB @Y,W                ; -- addr           W=Parse_Addr-Start_buf_adr=Toin
62             MOV W,&TOIN             ;
63             MOV @IP+,PC             ; 4
64
65 ; ----------------------------------------------------------------------
66 ; DTCforthMSP430FR5xxx ASSEMBLER : search argument "xxxx", IP is free
67 ; ----------------------------------------------------------------------
68
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
79             .word   QNUMBER         ;
80             .word   QFBRAN,NotFound ; -- addr           ABORT if not found
81             .word   SearchEnd       ; -- value          goto SearchEnd if number found
82 ARGWORD     .word   $+2             ; -- CFA
83             MOV     @TOS+,S         ; -- PFA            S=DOxxx
84 QDOVAR      SUB     #DOVAR,S        ;                   DOVAR = 1287h
85 ISDOVAR     JZ      SearchEnd       ; -- adr
86 QDOCON      ADD     #1,S            ;                   DOCON = 1286h
87 ISNOTDOCON  JNZ     QDODOES         ;
88 ISDOCON     MOV     @TOS,TOS        ; -- cte
89             JMP     SearchEnd       ;
90 QDODOES     ADD     #2,TOS          ;
91             ADD     #1,S            ;                   DODOES = 1285h
92 ISDODOES    JZ      SearchEnd       ; -- BODY           leave BODY address for DOES words        
93 ISOTHER     SUB     #4,TOS          ; -- CFA            leave execute adr
94 SearchEnd   POPM    #2,S            ;                   POPM T,S
95             MOV     @RSP+,PC        ; RET
96
97 ; ----------------------------------------------------------------------
98 ; DTCforthMSP430FR5xxx ASSEMBLER : search REG
99 ; ----------------------------------------------------------------------
100
101 ; compute arg of "xxxx(REG),"       ;               <== PARAM130, sep=','
102 ; compute arg of ",xxxx(REG)"       ;               <== PARAM210, sep=' '
103 ComputeARGpREG                      ; sep -- Rn
104             MOV #'(',TOS            ; -- "("        as WORD separator to find xxxx of "xxxx(REG),"
105             CALL #SearchARG         ; -- xxxx       aborted if not found
106             MOV &DDP,X
107             ADD #2,&DDP
108             MOV TOS,0(X)            ; -- xxxx       compile xxxx
109             MOV #')',TOS            ; -- ")"        prepare separator to search REG of "xxxx(REG)"
110
111 ; search REG of "xxxx(REG),"    separator = ')' 
112 ; search REG of ",xxxx(REG)"    separator = ')' 
113 ; search REG of "@REG,"         separator = ',' <== PARAM120
114 ; search REG of "@REG+,"        separator = '+' <== PARAM121
115 ; search REG of "REG,"          separator = ',' <== PARAM13
116 ; search REG of ",REG"          separator = BL  <== PARAM21
117
118 SearchREG   PUSHM #2,S              ;               PUSHM S,T as OPCODE, OPCODEADR
119             CMP &SOURCE_LEN,&TOIN   ;               bad case of ,xxxx without prefix &
120             JNZ SearchREG1          ;
121             MOV #BAD_CSP,PC         ;               génère une erreur bidon
122 SearchREG1  PUSH &TOIN              ; -- sep        save >IN
123             ADD #1,&TOIN            ;               skip "R"
124             ASMtoFORTH              ;               search xx of Rxx
125             .word WORDD,QNUMBER     ;
126             .word QFBRAN,NOTaREG    ; -- xxxx       if Not a Number
127             .word   $+2             ; -- Rn         number is found
128             ADD #2,RSP              ;               remove >IN
129             CMP #16,TOS             ; -- Rn       
130             JC  BOUNDERROR          ;               abort if Rn out of bounds
131             JNC SearchEnd           ; -- Rn
132
133 NOTaREG     .word   $+2             ; -- addr       Z=1
134             MOV @RSP+,&TOIN         ; -- addr       restore >IN
135             JMP SearchEnd           ; -- addr       Z=1 ==> not a register 
136
137 ; ----------------------------------------------------------------------
138 ; DTCforthMSP430FR5xxx ASSEMBLER : INTERPRET FIRST OPERAND
139 ; ----------------------------------------------------------------------
140
141 ; PARAM1     separator --                   ; parse input buffer until separator and compute first operand of opcode
142                                             ; sep is comma for src and space for dst .
143 PARAM1      mDOCOL                  ; -- sep        OPCODES types I|V sep = ','  OPCODES types II|VI sep = ' '
144             .word   FBLANK,SKIP     ; -- sep addr
145             .word   $+2             ; -- sep addr
146             MOV     #0,S            ; -- sep addr   reset OPCODE
147             MOV     &DDP,T          ; -- sep addr   HERE --> OPCODEADR (opcode is preset to its address !)
148             ADD     #2,&DDP         ; -- sep addr   cell allot for opcode
149             MOV.B   @TOS,W          ; -- sep addr   W=first char of instruction code
150             MOV     @PSP+,TOS       ; -- sep        W=c-addr
151             CMP.B   #'#',W          ; -- sep        W=first char
152             JNE     PARAM11
153 ; "#" found : case of "#xxxx,"
154 PARAM10     ADD #1,&TOIN            ; -- sep        skip # prefix
155             CALL #SearchARG         ; -- xxxx       abort if not found
156             MOV #0300h,S            ;               OPCODE = 0300h : MOV #0,dst is coded MOV R3,dst
157             CMP #0,TOS              ; -- xxxx       #0 ?
158             JZ PARAMENDOF
159             MOV #0310h,S            ;               OPCODE = 0310h : MOV #1,dst is coded MOV 0(R3),dst
160             CMP #1,TOS              ; -- xxxx       #1 ?
161             JZ PARAMENDOF
162             MOV #0320h,S            ;               OPCODE = 0320h : MOV #2,dst is coded MOV @R3,dst
163             CMP #2,TOS              ; -- xxxx       #2 ?
164             JZ PARAMENDOF
165             MOV #0220h,S            ;               OPCODE = 0220h : MOV #4,dst is coded MOV @R2,dst
166             CMP #4,TOS              ; -- xxxx       #4 ?
167             JZ PARAMENDOF
168             MOV #0230h,S            ;               OPCODE = 0230h : MOV #8,dst is coded MOV @R2+,dst 
169             CMP #8,TOS              ; -- xxxx       #8 ?
170             JZ PARAMENDOF
171             MOV #0330h,S            ; -- -1         OPCODE = 0330h : MOV #-1,dst is coded MOV @R3+,dst
172             CMP #-1,TOS             ; -- xxxx       #-1 ?
173             JZ PARAMENDOF
174             MOV #0030h,S            ; -- xxxx       for all other cases : MOV @PC+,dst
175 ; case of "&xxxx,"                  ;               <== PARAM110
176 ; case of ",&xxxx"                  ;               <== PARAM20
177 StoreArg    MOV &DDP,X              ;
178             ADD #2,&DDP             ;               cell allot for arg
179 StoreTOS                            ;               <== TYPE1DOES
180             MOV TOS,0(X)            ;               compile arg
181 ; endcase of all "&xxxx"            ;
182 ; endcase of all "#xxxx"            ;               <== PARAM101,102,104,108,10M1
183 ; endcase of all "REG"|"@REG"|"@REG+"               <== PARAM124
184 PARAMENDOF  MOV @PSP+,TOS           ; --
185             MOV @RSP+,IP            ;
186             MOV @IP+,PC             ; --            S=OPCODE,T=OPCODEADR
187 ; ----------------------------------;
188 PARAM11     CMP.B   #'&',W          ; -- sep
189             JNE     PARAM12
190 ; case of "&xxxx,"                  ; -- sep        search for "&xxxx,"
191 PARAM110    MOV     #0210h,S        ; -- sep        set code type : xxxx(SR) with AS=0b01 ==> x210h (and SR=0 !)
192 ; case of "&xxxx,"
193 ; case of ",&xxxx"                  ;               <== PARAM20
194 PARAM111    ADD     #1,&TOIN        ; -- sep        skip "&" prefix
195             CALL    #SearchARG      ; -- arg        abort if not found
196             JMP     StoreArg        ; --            then ret
197 ; ----------------------------------;
198 PARAM12     CMP.B   #'@',W          ; -- sep
199             JNE     PARAM13
200 ; case of "@REG,"|"@REG+,"
201 PARAM120    MOV     #0020h,S        ; -- sep        init OPCODE with indirect code type : AS=0b10
202             ADD     #1,&TOIN        ; -- sep        skip "@" prefix
203             CALL    #SearchREG      ;               Z = not found
204             JNZ     PARAM123        ; -- value      REG of "@REG," found
205 ; case of "@REG+,"                  ; -- addr       REG of "@REG" not found, search REG of "@REG+"
206 PARAM121    ADD     #0010h,S        ;               change OPCODE from @REG to @REG+ type
207             MOV     #'+',TOS        ; -- "+"        as WORD separator to find REG of "@REG+,"
208             CALL    #SearchREG      ; -- value|addr X = flag
209 ; case of "@REG+,"                  ;
210 ; case of "xxxx(REG),"              ;               <== PARAM130
211                                     ;               case of double separator:   +, and ),
212 PARAM122    CMP &SOURCE_LEN,&TOIN   ;               test OPCODE II parameter ending by REG+ or (REG) without comma,
213             JZ      PARAM123        ;               i.e. >IN = SOURCE_LEN : don't skip char CR !
214             ADD     #1,&TOIN        ; -- 000R       skip "," ready for the second operand search
215 ; case of "@REG+,"
216 ; case of "xxxx(REG),"
217 ; case of "@REG,"                   ; -- 000R       <== PARAM120
218 ; case of "REG,"                    ; -- 000R       <== PARAM13
219 PARAM123    SWPB    TOS             ; -- 0R00       swap bytes because it's not a dst REG typeI (not a 2 ops inst.)
220 ; case of "@REG+,"                  ; -- 0R00                   (src REG typeI)
221 ; case of "xxxx(REG),"              ; -- 0R00                   (src REG typeI or dst REG typeII)
222 ; case of "@REG,"                   ; -- 0R00                   (src REG typeI)
223 ; case of "REG,"                    ; -- 0R00                   (src REG typeI or dst REG typeII)
224 ; case of ",REG"                    ; -- 000R       <== PARAM21     (dst REG typeI)
225 ; case of ",xxxx(REG)"              ; -- 000R       <== PARAM210    (dst REG typeI)
226 PARAM124    ADD     TOS,S           ; -- 0R00|000R
227             JMP     PARAMENDOF
228 ; ----------------------------------;
229 ; case of "REG,"|"xxxx(REG),"       ;               first, searg REG of "REG,"
230 PARAM13     CALL    #SearchREG      ; -- sep        save >IN for second parsing (case of "xxxx(REG),")
231             JNZ     PARAM123        ; -- 000R       REG of "REG," found, S=OPCODE=0
232 ; case of "xxxx(REG),"              ; -- c-addr     "REG," not found
233 PARAM130    ADD     #0010h,S        ;               AS=0b01 for indexing address
234             CALL    #ComputeARGpREG ;               compile xxxx and search REG of "(REG)"
235             JMP     PARAM122        ; 
236
237 ; ----------------------------------------------------------------------
238 ; DTCforthMSP430FR5xxx ASSEMBLER : INTERPRET 2th OPERAND
239 ; ----------------------------------------------------------------------
240
241 PARAM3                              ; for OPCODES TYPE III
242             MOV     #0,S            ;                       init OPCODE=0
243             MOV     &DDP,T          ;                       T=OPCODEADR
244             ADD     #2,&DDP         ;                       make room for opcode
245 ; ----------------------------------;
246 PARAM2      mDOCOL                  ;               parse input buffer until BL and compute this 2th operand
247             .word   FBLANK,SKIP     ;               skip space(s) between "arg1," and "arg2" if any; use not S,T.
248             .word   $+2             ; -- c-addr     search for '&' of "&xxxx
249             CMP.B   #'&',0(TOS)     ;
250             MOV     #20h,TOS        ; -- ' '        as WORD separator to find xxxx of ",&xxxx"
251             JNE     PARAM21         ;               '&' not found
252 ; case of ",&xxxx"                  ;
253 PARAM20     ADD     #0082h,S        ;               change OPCODE : AD=1, dst = R2
254             JMP     PARAM111        ; -- ' '
255 ; ----------------------------------;
256 ; case of ",REG"|",xxxx(REG)        ; -- ' '        first, search REG of ",REG"
257 PARAM21     CALL    #SearchREG      ;
258             JNZ     PARAM124        ; -- 000R       REG of ",REG" found
259 ; case of ",xxxx(REG)               ; -- addr       REG not found
260 PARAM210    ADD     #0080h,S        ;               set AD=1
261             CALL    #ComputeARGpREG ;               compile argument xxxx and search REG of "(REG)"
262             JMP     PARAM124        ; -- 000R       REG of "(REG) found
263
264 ; ----------------------------------------------------------------------
265 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODES TYPE 0 : zero operand     f:-)
266 ; ----------------------------------------------------------------------
267             asmword "RETI"
268             mDOCOL
269             .word   lit,1300h,COMMA,EXIT
270
271 ; ----------------------------------------------------------------------
272 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODES TYPE I : double operand
273 ; ----------------------------------------------------------------------
274 ;                                               OPCODE(FEDC)
275 ; OPCODE(code) for TYPE I                          = 0bxxxx             opcode I
276 ;                                                   OPCODE(BA98)
277 ;                                                      = 0bxxxx         src register
278 ;                                                       OPCODE(7)       AD (dst addr type)
279 ;                                                          = 0b0        register
280 ;                                                          = 0b1        x(Rn),&adr
281 ;                                                        OPCODE(6)      size
282 ; OPCODE(B)  for TYPE I or TYPE II                          = 0b0       word
283 ;                                                           = 0b1       byte
284 ;                                                         OPCODE(54)    AS (src addr type)
285 ; OPCODE(AS) for TYPE I or OPCODE(AD) for TYPE II            = 0b00     register
286 ;                                                            = 0b01     x(Rn),&adr
287 ;                                                            = 0b10     @Rn
288 ;                                                            = 0b11     @Rn+
289 ;                                                           OPCODE(3210)
290 ; OPCODE(dst) for TYPE I or TYPE II                            = 0bxxxx dst register
291 ; ----------------------------------------------------------------------
292
293 TYPE1DOES   .word   lit,',',PARAM1  ; -- BODYDOES
294             .word   PARAM2          ; -- BODYDOES           char separator (BL) included in PARAM2
295             .word   $+2             ;
296 MAKEOPCODE  MOV     T,X             ; -- opcode             X= OPCODEADR to compile opcode
297             MOV     @TOS,TOS        ; -- opcode             part of instruction
298             BIS     S,TOS           ; -- opcode             opcode is complete
299             JMP     StoreTOS        ; --                    then EXIT
300
301             asmword "MOV"
302             CALL rDODOES
303             .word   TYPE1DOES,4000h
304             asmword "MOV.B"
305             CALL rDODOES
306             .word   TYPE1DOES,4040h
307             asmword "ADD"
308             CALL rDODOES
309             .word   TYPE1DOES,5000h
310             asmword "ADD.B"
311             CALL rDODOES
312             .word   TYPE1DOES,5040h
313             asmword "ADDC"
314             CALL rDODOES
315             .word   TYPE1DOES,6000h
316             asmword "ADDC.B"
317             CALL rDODOES
318             .word   TYPE1DOES,6040h
319             asmword "SUBC"
320             CALL rDODOES
321             .word   TYPE1DOES,7000h
322             asmword "SUBC.B"
323             CALL rDODOES
324             .word   TYPE1DOES,7040h
325             asmword "SUB"
326             CALL rDODOES
327             .word   TYPE1DOES,8000h
328             asmword "SUB.B"
329             CALL rDODOES
330             .word   TYPE1DOES,8040h
331             asmword "CMP"
332             CALL rDODOES
333             .word   TYPE1DOES,9000h
334             asmword "CMP.B"
335             CALL rDODOES
336             .word   TYPE1DOES,9040h
337             asmword "DADD"
338             CALL rDODOES
339             .word   TYPE1DOES,0A000h
340             asmword "DADD.B"
341             CALL rDODOES
342             .word   TYPE1DOES,0A040h
343             asmword "BIT"
344             CALL rDODOES
345             .word   TYPE1DOES,0B000h
346             asmword "BIT.B"
347             CALL rDODOES
348             .word   TYPE1DOES,0B040h
349             asmword "BIC"
350             CALL rDODOES
351             .word   TYPE1DOES,0C000h
352             asmword "BIC.B"
353             CALL rDODOES
354             .word   TYPE1DOES,0C040h
355             asmword "BIS"
356             CALL rDODOES
357             .word   TYPE1DOES,0D000h
358             asmword "BIS.B"
359             CALL rDODOES
360             .word   TYPE1DOES,0D040h
361             asmword "XOR"
362             CALL rDODOES
363             .word   TYPE1DOES,0E000h
364             asmword "XOR.B"
365             CALL rDODOES
366             .word   TYPE1DOES,0E040h
367             asmword "AND"
368             CALL rDODOES
369             .word   TYPE1DOES,0F000h
370             asmword "AND.B"
371             CALL rDODOES
372             .word   TYPE1DOES,0F040h
373
374 ; ----------------------------------------------------------------------
375 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES TYPE II : single operand
376 ; ----------------------------------------------------------------------
377 ;                                               OPCODE(FEDCBA987)       opcodeII
378 ; OPCODE(code) for TYPE II                         = 0bxxxxxxxxx
379 ;                                                        OPCODE(6)      size
380 ; OPCODE(B)  for TYPE I or TYPE II                          = 0b0       word
381 ;                                                           = 0b1       byte
382 ;                                                         OPCODE(54)    (dst addr type)
383 ; OPCODE(AS) for TYPE I or OPCODE(AD) for TYPE II            = 0b00     register
384 ;                                                            = 0b01     x(Rn),&adr
385 ;                                                            = 0b10     @Rn
386 ;                                                            = 0b11     @Rn+
387 ;                                                           OPCODE(3210)
388 ; OPCODE(dst) for TYPE I or TYPE II                            = 0bxxxx dst register
389 ; ----------------------------------------------------------------------
390
391 TYPE2DOES   .word   FBLANK,PARAM1   ; -- BODYDOES
392             .word   $+2             ;
393             MOV     S,W             ;
394             AND     #0070h,S        ;                   keep B/W & AS infos in OPCODE
395             SWPB    W               ;                   (REG org --> REG dst)
396             AND     #000Fh,W        ;                   keep REG
397 BIS_ASMTYPE BIS     W,S             ; -- BODYDOES       add it in OPCODE
398             JMP     MAKEOPCODE      ; -- then end
399
400             asmword "RRC"           ; Rotate Right through Carry ( word)
401             CALL rDODOES
402             .word   TYPE2DOES,1000h
403             asmword "RRC.B"         ; Rotate Right through Carry ( byte)
404             CALL rDODOES
405             .word   TYPE2DOES,1040h
406             asmword "SWPB"          ; Swap bytes
407             CALL rDODOES
408             .word   TYPE2DOES,1080h
409             asmword "RRA"
410             CALL rDODOES
411             .word   TYPE2DOES,1100h
412             asmword "RRA.B"
413             CALL rDODOES
414             .word   TYPE2DOES,1140h
415             asmword "SXT"
416             CALL rDODOES
417             .word   TYPE2DOES,1180h
418             asmword "PUSH"
419             CALL rDODOES
420             .word   TYPE2DOES,1200h
421             asmword "PUSH.B"
422             CALL rDODOES
423             .word   TYPE2DOES,1240h
424             asmword "CALL"
425             CALL rDODOES
426             .word   TYPE2DOES,1280h
427
428 BOUNDERRWM1 ADD     #1,W            ; <== RRAM|RRUM|RRCM|RLAM error
429 BOUNDERRORW MOV     W,TOS           ; <== PUSHM|POPM|ASM_branch error
430 BOUNDERROR                          ; <== REG number error
431             mDOCOL                  ; -- n      n = value out of bounds
432             .word   DOT,XSQUOTE
433             .byte 13,"out of bounds"
434             .word   QABORTYES
435
436 ; ----------------------------------------------------------------------
437 ; DTCforthMSP430FR5xxx ASSEMBLER, CONDITIONAL BRANCHS
438 ; ----------------------------------------------------------------------
439 ;                       ASSEMBLER       FORTH         OPCODE(FEDC)
440 ; OPCODE(code) for TYPE JNE,JNZ         0<>, <>     = 0x20xx + (offset AND 3FF) ; branch if Z = 0
441 ; OPCODE(code) for TYPE JEQ,JZ          0=, =       = 0x24xx + (offset AND 3FF) ; branch if Z = 1
442 ; OPCODE(code) for TYPE JNC,JLO         U<          = 0x28xx + (offset AND 3FF) ; branch if C = 0
443 ; OPCODE(code) for TYPE JC,JHS          U>=         = 0x2Cxx + (offset AND 3FF) ; branch if C = 1
444 ; OPCODE(code) for TYPE JN              0<          = 0x30xx + (offset AND 3FF) ; branch if N = 1
445 ; OPCODE(code) for TYPE JGE             >=          = 0x34xx + (offset AND 3FF) ; branch if (N xor V) = 0
446 ; OPCODE(code) for TYPE JL              <           = 0x38xx + (offset AND 3FF) ; branch if (N xor V) = 1
447 ; OPCODE(code) for TYPE JMP                         = 0x3Cxx + (offset AND 3FF)
448
449             asmword "S>="           ; if >= assertion (opposite of jump if < )
450             CALL rDOCON
451             .word   3800h
452
453             asmword "S<"            ; if < assertion
454             CALL rDOCON
455             .word   3400h
456
457             asmword "0>="           ; if 0>= assertion  ; use only with IF UNTIL WHILE !
458             CALL rDOCON
459             .word   3000h
460
461             asmword "0<"            ; jump if 0<        ; use only with ?GOTO !
462             CALL rDOCON
463             .word   3000h
464
465             asmword "U<"            ; if U< assertion
466             CALL rDOCON
467             .word   2C00h
468
469             asmword "U>="           ; if U>= assertion
470             CALL rDOCON
471             .word   2800h
472
473             asmword "0<>"           ; if <>0 assertion
474             CALL rDOCON
475             .word   2400h
476
477             asmword "0="            ; if =0 assertion
478             CALL rDOCON
479             .word   2000h
480
481 ;ASM IF      OPCODE -- @OPCODE1
482             asmword "IF"
483 ASM_IF      MOV     &DDP,W
484             MOV     TOS,0(W)        ; compile incomplete opcode
485             ADD     #2,&DDP
486             MOV     W,TOS
487             MOV     @IP+,PC
488
489 ;ASM THEN     @OPCODE --        resolve forward branch
490             asmword "THEN"
491 ASM_THEN    MOV     &DDP,W          ; -- @OPCODE    W=dst
492             MOV     TOS,Y           ;               Y=@OPCODE
493 ASM_THEN1   MOV     @PSP+,TOS       ; --
494             MOV     Y,X             ;
495             ADD     #2,X            ; --        Y=@OPCODE   W=dst   X=src+2
496             SUB     X,W             ; --        Y=@OPCODE   W=dst-src+2=displacement*2 (bytes)
497             RRA     W               ; --        Y=@OPCODE   W=displacement (words)
498             CMP     #512,W
499             JC      BOUNDERRORW     ; (JHS) unsigned branch if u> 511
500             BIS     W,0(Y)          ; --       [@OPCODE]=OPCODE completed
501             MOV     @IP+,PC
502
503 ; ELSE      @OPCODE1 -- @OPCODE2    branch for IF..ELSE
504             asmword "ELSE"
505 ASM_ELSE    MOV     &DDP,W          ; --        W=HERE
506             MOV     #3C00h,0(W)     ;           compile unconditionnal branch
507             ADD     #2,&DDP         ; --        DP+2
508             SUB     #2,PSP
509             MOV     W,0(PSP)        ; -- @OPCODE2 @OPCODE1
510             JMP     ASM_THEN        ; -- @OPCODE2
511
512 ; BEGIN     -- BEGINadr             initialize backward branch
513             asmword "BEGIN"
514             MOV #HERE,PC
515
516 ; UNTIL     @BEGIN OPCODE --   resolve conditional backward branch
517             asmword "UNTIL"
518 ASM_UNTIL   MOV     @PSP+,W         ;  -- OPCODE                        W=@BEGIN
519 ASM_UNTIL1  MOV     TOS,Y           ;               Y=OPCODE            W=@BEGIN
520 ASM_UNTIL2  MOV     @PSP+,TOS       ;  --
521             MOV     &DDP,X          ;  --           Y=OPCODE    X=HERE  W=dst
522             SUB     #2,W            ;  --           Y=OPCODE    X=HERE  W=dst-2
523             SUB     X,W             ;  --           Y=OPCODE    X=src   W=src-dst-2=displacement (bytes)
524             RRA     W               ;  --           Y=OPCODE    X=HERE  W=displacement (words)
525             CMP     #-512,W
526             JL      BOUNDERRORW     ; signed branch if < -512
527             AND     #3FFh,W         ;  --           Y=OPCODE   X=HERE  W=troncated negative displacement (words)
528             BIS     W,Y             ;  --           Y=OPCODE (completed)
529             MOV     Y,0(X)
530             ADD     #2,&DDP
531             MOV     @IP+,PC
532
533 ;  AGAIN    @BEGIN --      uncond'l backward branch
534 ;   unconditional backward branch
535             asmword "AGAIN"
536 ASM_AGAIN   MOV TOS,W               ;               W=@BEGIN
537             MOV #3C00h,Y            ;               Y = asmcode JMP
538             JMP ASM_UNTIL2          ;
539
540 ; WHILE     @BEGIN OPCODE -- @WHILE @BEGIN
541             asmword "WHILE"
542 ASM_WHILE   mDOCOL                  ; -- @BEGIN OPCODE
543             .word   ASM_IF,SWAP,EXIT
544
545 ; REPEAT    @WHILE @BEGIN --     resolve WHILE loop
546             asmword "REPEAT"
547 ASM_REPEAT  mDOCOL                  ; -- @WHILE @BEGIN
548             .word   ASM_AGAIN,ASM_THEN,EXIT
549
550 ; ------------------------------------------------------------------------------------------
551 ; DTCforthMSP430FR5xxx ASSEMBLER : branch up to 3 backward labels and up to 3 forward labels
552 ; ------------------------------------------------------------------------------------------
553 ; used for non canonical branchs, as BASIC language: "goto line x"
554 ; labels BWx and FWx must be respectively set and used at the beginning of line (>IN < 8).
555 ; FWx at the beginning of a line can resolve only one previous GOTO|?GOTO FWx.
556 ; BWx at the beginning of a line can be resolved by any subsequent GOTO|?GOTO BWx.
557
558 ;BACKWDOES   FORTHtoASM
559 ;            MOV @RSP+,IP
560 ;            MOV @TOS,TOS
561 ;            MOV TOS,Y               ; Y = ASMBWx
562 ;            MOV @PSP+,TOS           ; 
563 ;            MOV @Y,W                ;               W = [ASMBWx]
564 ;            CMP #8,&TOIN            ;               are we colon 8 or more ?
565 ;BACKWUSE    JHS ASM_UNTIL1          ;               yes, use this label  
566 ;BACKWSET    MOV &DDP,0(Y)           ;               no, set LABEL = DP
567 ;            mNEXT
568
569 ;; backward label 1
570 ;            asmword "BW1"
571 ;            mdodoes
572 ;            .word BACKWDOES
573 ;            .word ASMBW1            ; in RAM
574
575 BACKWDOES   .word   $+2
576             MOV @RSP+,IP            ;
577             MOV TOS,Y               ; -- PFA        Y = ASMBWx addr
578             MOV @PSP+,TOS           ; --
579             MOV @Y,W                ;               W = LABEL
580             CMP #8,&TOIN            ;               are we colon 8 or more ?
581 BACKWUSE    JC ASM_UNTIL1           ;               yes, use this label  
582 BACKWSET    MOV &DDP,0(Y)           ;               no, set LABEL = DP
583             MOV @IP+,PC
584
585 ; backward label 1
586             asmword "BW1"
587             CALL rDODOES
588             .word BACKWDOES
589             .word 0
590 ; backward label 2
591             asmword "BW2"
592             CALL rDODOES
593             .word BACKWDOES
594             .word 0
595 ; backward label 3
596             asmword "BW3"
597             CALL rDODOES
598             .word BACKWDOES
599             .word 0
600
601 ;FORWDOES    .word   $+2
602 ;            MOV @RSP+,IP
603 ;            MOV &DDP,W              ;
604 ;            MOV @TOS,TOS
605 ;            MOV @TOS,Y              ; -- PFA        Y= ASMFWx
606 ;            CMP #8,&TOIN            ;               are we colon 8 or more ?
607 ;FORWUSE     JNC ASM_THEN1           ;               no: resolve FWx with W=DDP, Y=ASMFWx
608 ;FORWSET     MOV @PSP+,0(W)          ;               yes compile incomplete opcode
609 ;            ADD #2,&DDP             ;                   increment DDP
610 ;            MOV W,0(TOS)            ;                   store @OPCODE into ASMFWx
611 ;            MOV @PSP+,TOS           ;   --
612 ;            MOV @IP+,PC
613 ;
614 ;; forward label 1
615 ;            asmword "FW1"
616 ;            CALL rDODOES            ; CFA
617 ;            .word FORWDOES          ; 
618 ;            .word ASMFW1            ; in RAM 
619
620 FORWDOES    .word   $+2
621             MOV @RSP+,IP
622             MOV &DDP,W              ;
623             MOV @TOS,Y              ; -- PFA        Y=[BODY]=ASMFWx
624             CMP #8,&TOIN            ;               are we colon 8 or more ?
625 FORWUSE     JNC ASM_THEN1           ;               no: resolve FWx with W=DDP, Y=ASMFWx
626 FORWSET     MOV @PSP+,0(W)          ;               yes compile incomplete opcode
627             ADD #2,&DDP             ;                   increment DDP
628             MOV W,0(TOS)            ;                   store @OPCODE into ASMFWx
629             MOV @PSP+,TOS           ;   --
630             MOV @IP+,PC
631
632 ; forward label 1
633             asmword "FW1"
634             CALL rDODOES            ; CFA
635             .word FORWDOES          ; 
636             .word 0                 ; BODY 
637 ; forward label 2
638             asmword "FW2"
639             CALL rDODOES
640             .word FORWDOES
641             .word 0
642 ; forward label 3
643             asmword "FW3"
644             CALL rDODOES
645             .word FORWDOES
646             .word 0
647
648 ;ASM    GOTO <label>                   --       unconditionnal branch to label
649             asmword "GOTO"
650             SUB #2,PSP
651             MOV TOS,0(PSP)
652             MOV #3C00h,TOS          ;  -- JMP_OPCODE
653 GOTONEXT    mDOCOL
654             .word   TICK            ;  -- OPCODE CFA<label>
655             .word   EXECUTE,EXIT
656
657 ;ASM    <cond> ?GOTO <label>    OPCODE --       conditionnal branch to label
658             asmword "?GOTO"
659 INVJMP      CMP #3000h,TOS          ; invert code jump process
660             JZ GOTONEXT             ; case of JN, do nothing
661             XOR #0400h,TOS          ; case of: JNZ<-->JZ  JNC<-->JC  JL<-->JGE
662             BIT #1000h,TOS          ; 3xxxh case ?
663             JZ  GOTONEXT            ; no
664             XOR #0800h,TOS          ; complementary action for JL<-->JGE
665             JMP GOTONEXT
666
667 ; --------------------------------------------------------------------------------
668 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES TYPE III : PUSHM|POPM|RLAM|RRAM|RRUM|RRCM
669 ; --------------------------------------------------------------------------------
670 ; PUSHM, syntax:    PUSHM #n,REG  with 0 < n < 17 
671 ; POPM syntax:       POPM #n,REG  with 0 < n < 17 
672
673
674 ; PUSHM order : PSP,TOS, IP,  S,  T,  W,  X,  Y, rEXIT,rDOVAR,rDOCON, rDODOES, R3, SR,RSP, PC
675 ; PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8,  R7  ,  R6  ,  R5  ,   R4   , R3, R2, R1, R0
676
677 ; example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
678 ;
679 ; POPM  order :  PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT,  Y,  X,  W,  T,  S, IP,TOS,PSP
680 ; POPM  order :  R0, R1, R2, R3,   R4   ,  R5  ,  R6  ,  R7 , R8, R9,R10,R11,R12,R13,R14,R15
681
682 ; example : POPM #6,IP   pulls Y,X,W,T,S,IP registers from return stack
683
684 ; RxxM syntax: RxxM #n,REG  with 0 < n < 5 
685
686 TYPE3DOES   .word   FBLANK,SKIP     ;                       skip spaces if any
687             .word   $+2             ; -- BODYDOES c-addr
688             ADD     #1,&TOIN        ;                       skip "#"
689             MOV     #',',TOS        ; -- BODYDOES ","
690             ASMtoFORTH
691             .word   WORDD,QNUMBER
692             .word   QFBRAN,NotFound ;                       ABORT
693             .word   PARAM3          ; -- BODYDOES 0x000N    S=OPCODE = 0x000R
694             .word   $+2
695             MOV     TOS,W           ; -- BODYDOES n         W = n
696             MOV     @PSP+,TOS       ; -- BODYDOES
697             SUB     #1,W            ;                       W = n floored to 0
698             JN      BOUNDERRWM1
699             MOV     @TOS,X          ;                       X=OPCODE
700             RLAM    #4,X            ;                       OPCODE bit 1000h --> C
701             JNC     RxxMINSTRU      ;                       if bit 1000h = 0
702 PxxxINSTRU  MOV     S,Y             ;                       S=REG, Y=REG to test
703             RLAM    #3,X            ;                       OPCODE bit 0200h --> C                  
704             JNC     PUSHMINSTRU     ;                       W=n-1 Y=REG
705 POPMINSTRU  SUB     W,S             ;                       to make POPM opcode, compute first REG to POP; TI is complicated....
706 PUSHMINSTRU SUB     W,Y             ;                       Y=REG-(n-1)
707             CMP     #16,Y
708             JC      BOUNDERRWM1     ;                       JC=JHS    (U>=)
709             RLAM    #4,W            ;                       W = n << 4      
710             JMP     BIS_ASMTYPE     ; BODYDOES --            
711 RxxMINSTRU  CMP     #4,W            ;
712             JC      BOUNDERRWM1     ;                       JC=JHS    (U>=)
713             SWPB    W               ; -- BODYDOES           W = n << 8
714             RLAM    #2,W            ;                       W = N << 10
715             JMP     BIS_ASMTYPE     ; BODYDOES --
716
717             asmword "RRCM"
718             CALL rDODOES
719             .word   TYPE3DOES,0050h
720             asmword "RRAM"
721             CALL rDODOES
722             .word   TYPE3DOES,0150h
723             asmword "RLAM"
724             CALL rDODOES
725             .word   TYPE3DOES,0250h
726             asmword "RRUM"
727             CALL rDODOES
728             .word   TYPE3DOES,0350h
729             asmword "PUSHM"
730             CALL rDODOES
731             .word   TYPE3DOES,1500h
732             asmword "POPM"
733             CALL rDODOES
734             .word   TYPE3DOES,1700h
735
736     .IFDEF EXTENDED_MEM
737
738             asmword "RRCM.A"
739             CALL rDODOES
740             .word   TYPE3DOES,0040h
741             asmword "RRAM.A"
742             CALL rDODOES
743             .word   TYPE3DOES,0140h
744             asmword "RLAM.A"
745             CALL rDODOES
746             .word   TYPE3DOES,0240h
747             asmword "RRUM.A"
748             CALL rDODOES
749             .word   TYPE3DOES,0340h
750             asmword "PUSHM.A"
751             CALL rDODOES
752             .word   TYPE3DOES,1400h
753             asmword "POPM.A"
754             CALL rDODOES
755             .word   TYPE3DOES,1600h
756
757 ; --------------------------------------------------------------------------------
758 ; DTCforthMSP430FR5xxx ASSEMBLER:  OPCODE TYPE III bis: CALLA (without extended word)
759 ; --------------------------------------------------------------------------------
760 ; absolute and immediate instructions must be written as $x.xxxx  (DOUBLE numbers with dot)
761 ; indexed instructions must be written as $.xxxx(REG) (DOUBLE numbers with dot)
762 ; --------------------------------------------------------------------------------
763 ; may be usefull to access ROM libraries beyond $FFFF
764 ; --------------------------------------------------------------------------------
765
766             asmword "CALLA"
767             mDOCOL
768             .word FBLANK,SKIP       ; -- addr
769             .word   $+2
770             MOV &DDP,T              ;           T = DDP
771             ADD #2,&DDP             ;           make room for opcode
772             MOV.B @TOS,TOS          ; -- char   First char of opcode
773 CALLA0      MOV #134h,S             ;           134h<<4 = 1340h = opcode for CALLA Rn
774             CMP.B #'R',TOS   
775             JNZ CALLA1
776 CALLA01     MOV.B #' ',TOS          ;        
777 CALLA02     CALL #SearchREG         ; -- Rn
778 CALLA03     RLAM #4,S               ;           (opcode>>4)<<4 = opcode
779             BIS TOS,S               ;           update opcode
780             MOV S,0(T)              ;           store opcode
781             MOV @PSP+,TOS
782             MOV @RSP+,IP 
783             MOV @IP+,PC
784 ;-----------------------------------;
785 CALLA1      ADD #2,S                ;           136h<<4 = opcode for CALLA @REG
786             CMP.B #'@',TOS          ; -- char   Search @REG
787             JNZ CALLA2              ;
788             ADD #1,&TOIN            ;           skip '@'
789             MOV.B #' ',TOS          ; -- ' '
790             CALL #SearchREG         ;
791             JNZ  CALLA03            ;           if REG found, update opcode
792 ;-----------------------------------;
793             ADD #1,S                ;           137h<<4 = opcode for CALLA @REG+
794             MOV #'+',TOS            ; -- '+'
795             JMP CALLA02             ;
796 ;-----------------------------------;
797 CALLA2      ADD #2,&DDP             ;           make room for xxxx of #$x.xxxx|&$x.xxxx|$0.xxxx(REG)
798             CMP.B #'#',TOS          ;
799             JNZ CALLA3
800             MOV #13Bh,S             ;           13Bh<<4 = opcode for CALLA #$x.xxxx
801 CALLA21     ADD #1,&TOIN            ;           skip '#'|'&'
802 CALLA22     CALL #SearchARG         ; -- Lo Hi
803             MOV @PSP+,2(T)          ; -- Hi     store #$xxxx|&$xxxx
804             JMP CALLA03             ;           update opcode with $x. and store opcode
805 ;-----------------------------------;
806 CALLA3      CMP.B #'&',TOS   
807             JNZ CALLA4              ;
808             ADD #2,S                ;           138h<<4 = opcode for CALLA &$x.xxxx
809             JMP CALLA21
810 ;-----------------------------------;
811 CALLA4      MOV.B #'(',TOS          ; -- "("
812             SUB #1,S                ;           135h<<4 = opcode for CALLA $0.xxxx(REG)
813 CALLA41     CALL #SearchARG         ; -- Lo Hi
814             MOV @PSP+,2(T)          ; -- Hi     store $xxxx 
815             MOV #')',TOS            ; -- ')'
816             JMP CALLA02             ;           search Rn and update opcode
817     
818 ; ===============================================================
819 ; to allow data access beyond $FFFF
820 ; ===============================================================
821
822 ; MOVA (#$x.xxxx|&$x.xxxx|$.xxxx(Rs)|Rs|@Rs|@Rs+ , &|Rd|$.xxxx(Rd)) 
823 ; ADDA (#$x.xxxx|Rs , Rd) 
824 ; CMPA (#$x.xxxx|Rs , Rd) 
825 ; SUBA (#$x.xxxx|Rs , Rd) 
826
827 ; first argument process ACMS1
828 ;-----------------------------------;
829 ACMS1       mDOCOL                  ; -- BODYDOES ','   
830             .word   FBLANK,SKIP     ; -- BODYDOES ',' addr
831             .word   $+2             ;
832             MOV.B @TOS,X            ;                   X=first char of opcode string
833             MOV @PSP+,TOS           ; -- BODYDOES ','
834             MOV @PSP+,S             ; -- ','            S=BODYDOES
835             MOV @S,S                ;                   S=opcode
836             MOV &DDP,T              ;                   T=DDP
837             ADD #2,&DDP             ;                   make room for opcode
838 ;-----------------------------------;
839 ACMS10      CMP.B #'R',X            ; -- ','    
840             JNZ ACMS11              ;
841 ACMS101     CALL #SearchREG         ; -- Rn         src
842 ACMS102     RLAM #4,TOS             ;               8<<src
843             RLAM #4,TOS             ;
844 ACMS103     BIS S,TOS               ;               update opcode with src|dst
845             MOV TOS,0(T)            ;               save opcode
846             MOV T,TOS               ; -- OPCODE_addr
847             mSEMI                   ;
848 ;-----------------------------------;
849 ACMS11      CMP.B #'#',X            ; -- ','        X=addr
850             JNE MOVA12              ;
851             BIC #40h,S              ;               set #opcode
852 ACMS111     ADD #1,&TOIN            ;               skip '#'|'&'
853             ADD #2,&DDP             ;               make room for low #$xxxx|&$xxxx|$xxxx(REG)
854             CALL #SearchARG         ; -- Lo Hi
855             MOV @PSP+,2(T)          ; -- Hi         store $xxxx of #$x.xxxx|&$x.xxxx|$x.xxxx(REG)
856             AND #0Fh,TOS            ; -- Hi         sel Hi src
857             JMP ACMS102             ;
858 ;-----------------------------------;
859 MOVA12      CMP.B #'&',X            ; -- ','        case of MOVA &$x.xxxx
860             JNZ MOVA13              ;
861             XOR #00E0h,S            ;               set MOVA &$x.xxxx, opcode                 
862             JMP ACMS111             ;
863 ;-----------------------------------;
864 MOVA13      BIC #00F0h,S            ;               set MOVA @REG, opcode
865             CMP.B #'@',X            ; -- ','
866             JNZ MOVA14              ;
867             ADD #1,&TOIN            ;               skip '@'
868             CALL #SearchREG         ; -- Rn 
869             JNZ ACMS102             ;               if @REG found
870 ;-----------------------------------;
871             BIS #0010h,S            ;               set @REG+ opcode
872             MOV #'+',TOS            ; -- '+'
873 MOVA131     CALL #SearchREG         ; -- Rn         case of MOVA @REG+,|MOVA $x.xxxx(REG),
874             CMP &SOURCE_LEN,&TOIN   ;               test TYPE II first parameter ending by @REG+ (REG) without comma,
875             JZ ACMS102              ;               i.e. may be >IN = SOURCE_LEN: don't skip char CR !
876             ADD #1,&TOIN            ;               skip "," ready for the second operand search
877             JMP ACMS102             ;
878 ;-----------------------------------;
879 MOVA14      BIS #0030h,S            ;               set xxxx(REG), opcode
880             ADD #2,&DDP             ; -- ','        make room for first $xxxx of $0.xxxx(REG),
881             MOV #'(',TOS            ; -- "("        as WORD separator to find xxxx of "xxxx(REG),"
882             CALL #SearchARG         ; -- Lo Hi
883             MOV @PSP+,2(T)          ; -- Hi         store $xxxx as 2th word
884             MOV #')',TOS            ; -- ')'
885             JMP MOVA131             ;
886
887 ; 2th argument process ACMS2
888 ;-----------------------------------;
889 ACMS2       mDOCOL                  ; -- OPCODE_addr 
890             .word FBLANK,SKIP       ; -- OPCODE_addr addr
891             .word   $+2             ;
892             MOV @PSP+,T             ; -- addr       T=OPCODE_addr
893             MOV @T,S                ;               S=opcode
894             MOV.B @TOS,X            ; -- addr       X=first char of string instruction         
895             MOV.B #' ',TOS          ; -- ' '
896 ;-----------------------------------;
897 ACMS21      CMP.B #'R',X            ; -- ' '
898             JNZ MOVA22              ;
899 ACMS211     CALL #SearchREG         ; -- Rn
900             JMP ACMS103             ;
901 ;-----------------------------------;
902 MOVA22      BIC #0F0h,S             ;
903             ADD #2,&DDP             ; -- ' '        make room for $xxxx
904             CMP.B #'&',X            ;
905             JNZ MOVA23              ;
906             BIS #060h,S             ;               set ,&$x.xxxx opcode
907             ADD #1,&TOIN            ;               skip '&'
908             CALL #SearchARG         ; -- Lo Hi
909             MOV @PSP+,2(T)          ; -- Hi         store $xxxx as 2th word
910             JMP ACMS103             ;               update opcode with dst $x and write opcode
911 ;-----------------------------------;
912 MOVA23      BIS #070h,S             ;               set ,xxxx(REG) opcode
913             MOV #'(',TOS            ; -- "("        as WORD separator to find xxxx of "xxxx(REG),"
914             CALL #SearchARG         ; -- Lo Hi
915             MOV @PSP+,2(T)          ; -- Hi         write $xxxx of ,$0.xxxx(REG) as 2th word
916             MOV #')',TOS            ; -- ")"        as WORD separator to find REG of "xxxx(REG),"
917             JMP ACMS211
918
919 ; --------------------------------------------------------------------------------
920 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES IV 2 operands: Adda|Cmpa|Mova|Suba (without extended word)
921 ; --------------------------------------------------------------------------------
922 ; absolute and immediate instructions must be written as $x.xxxx  (DOUBLE numbers)
923 ; indexed instructions must be written as $.xxxx(REG) (DOUBLE numbers)
924 ; --------------------------------------------------------------------------------
925
926 TYPE4DOES   .word   lit,','         ; -- BODYDOES ","        char separator for PARAM1
927             .word   ACMS1           ; -- OPCODE_addr
928             .word   ACMS2           ; -- OPCODE_addr
929             .word   DROP,EXIT
930
931             asmword "MOVA"
932             CALL rDODOES
933             .word   TYPE4DOES,00C0h
934             asmword "CMPA"
935             CALL rDODOES
936             .word   TYPE4DOES,00D0h
937             asmword "ADDA"
938             CALL rDODOES
939             .word   TYPE4DOES,00E0h
940             asmword "SUBA"
941             CALL rDODOES
942             .word   TYPE4DOES,00F0h
943
944     .ENDIF ; EXTENDED_MEM