OSDN Git Service

Ver 301
[fast-forth/master.git] / forthMSP430FR_EXTD_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_EXTD_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 ; ----------------------------------------------------------------------
48 ; DTCforthMSP430FR5xxx ASSEMBLER : search argument "xxxx", IP is free
49 ; ----------------------------------------------------------------------
50
51 ;SearchARG                           ; separator -- n|d or abort" not found"
52 ;; Search ARG of "#xxxx,"            ; <== PARAM10
53 ;; Search ARG of "&xxxx,"            ; <== PARAM111
54 ;; Search ARG of "xxxx(REG),"        ; <== PARAM130
55 ;; Search ARG of ",&xxxx"            ; <== PARAM111 <== PARAM20
56 ;; Search ARG of ",xxxx(REG)"        ; <== PARAM210
57 ;            PUSHM #2,S              ;                   PUSHM S,T as OPCODE, OPCODEADR
58 ;            ASMtoFORTH              ; -- separator      search word first
59 ;            .word   WORDD,FIND      ; -- addr
60 ;            .word QTBRAN,SearchARGW ; -- addr           if word found
61 ;            .word   QNUMBER         ;
62 ;            .word   QFBRAN,NotFound ; -- addr           ABORT if not found
63 ;FSearchEnd  .word   SearchEnd       ; -- value          goto SearchEnd if number found
64 ;SearchARGW  FORTHtoASM              ; -- xt             xt = CFA
65 ;            MOV     @TOS+,X         ; -- PFA
66 ;QDODOES     SUB     #DODOES,X       ;                   DODOES = 1284h
67 ;            JNZ     QDOCON          ;
68 ;            ADD     #2,TOS          ; -- BODY           leave BODY address for DOES words
69 ;            JMP     SearchEnd       ;
70 ;QDOCON      CMP     #1,X            ; -- PFA            DOCON = 1285h
71 ;            JNZ     QDOVAR          ;
72 ;            MOV     @TOS,TOS        ; -- cte            replace PFA by [PFA] for CONSTANT and CREATE words
73 ;            JMP     SearchEnd       ;
74 ;QDOVAR      CMP     #2,X            ; -- PFA            DOVAR = 1286h
75 ;            JZ      SearchEnd       ;                   if DOVAR nothing to do
76 ;            SUB     #2,TOS          ; -- CFA            replace PFA by CFA for all other words
77 ;SearchEnd   POPM    #2,S            ;                   POPM T,S
78 ;            RET                     ;
79
80 SearchARG                           ; separator -- n|d or abort" not found"
81 ; Search ARG of "#xxxx,"            ; <== PARAM10
82 ; Search ARG of "&xxxx,"            ; <== PARAM111
83 ; Search ARG of "xxxx(REG),"        ; <== PARAM130
84 ; Search ARG of ",&xxxx"            ; <== PARAM111 <== PARAM20
85 ; Search ARG of ",xxxx(REG)"        ; <== PARAM210
86             PUSHM #2,S              ;                   PUSHM S,T as OPCODE, OPCODEADR
87             ASMtoFORTH              ; -- separator      search word first
88             .word   WORDD,FIND      ; -- addr
89             .word QTBRAN,SearchARGW ; -- addr           if word found
90             .word   QNUMBER         ;
91             .word   QFBRAN,NotFound ; -- addr           ABORT if not found
92 FSearchEnd  .word   SearchEnd       ; -- value          goto SearchEnd if number found
93 SearchARGW  FORTHtoASM              ; -- xt             xt = CFA
94             MOV     @TOS+,X         ; -- PFA
95 QDOVAR      SUB     #DOVAR,X        ;                   DOVAR = 1286h
96             JZ      SearchEnd       ;
97             ADD     #1,X            ; -- PFA            DOCON = 1285h
98             JNZ     QDODOES         ;
99             MOV     @TOS,TOS        ; -- cte
100             JMP     SearchEnd       ;
101 QDODOES     ADD     #2,TOS          ; -- BODY           leave BODY address for DOES words
102             ADD     #1,X            ;                   DODOES = 1284h
103             JZ      SearchEnd       ;        
104             SUB     #4,TOS          ; -- CFA
105 SearchEnd   POPM    #2,S            ;                   POPM T,S
106             RET                     ;
107
108 ; Arg_Double_to_single conversion needed only for OPCODE type V|VI, 2th pass.
109 ARGD2S      BIT #UF9,SR             ; -- Lo Hi
110             JZ ARGD2SEND
111             MOV @PSP+,TOS           ; -- Lo         skip hi
112 ARGD2SEND   RET
113
114 ; ----------------------------------------------------------------------
115 ; DTCforthMSP430FR5xxx ASSEMBLER : search REG
116 ; ----------------------------------------------------------------------
117
118 ; compute arg of "xxxx(REG),"       ;               <== PARAM130, sep=','
119 ; compute arg of ",xxxx(REG)"       ;               <== PARAM210, sep=' '
120 ComputeARGParenREG                  ; sep -- Rn
121             MOV #'(',TOS            ; -- "("        as WORD separator to find xxxx of "xxxx(REG),"
122             CALL #SearchARG         ; -- xxxx       aborted if not found
123             CALL #ARGD2S            ;               skip arg_hi if DOUBLE
124             MOV &DDP,X
125             ADD #2,&DDP
126             MOV TOS,0(X)            ; -- xxxx       compile xxxx
127             MOV #')',TOS            ; -- ")"        prepare separator to search REG of "xxxx(REG)"
128
129 ; search REG of "xxxx(REG),"    separator = ')' 
130 ; search REG of ",xxxx(REG)"    separator = ')' 
131 ; search REG of "@REG,"         separator = ',' <== PARAM120
132 ; search REG of "@REG+,"        separator = '+' <== PARAM121
133 ; search REG of "REG,"          separator = ',' <== PARAM13
134 ; search REG of ",REG"          separator = BL  <== PARAM21
135
136 SearchREG   PUSHM #2,S              ;                   PUSHM S,T as OPCODE, OPCODEADR
137             PUSH &TOIN              ; -- sep        save >IN
138             ADD #1,&TOIN            ;               skip "R"
139             ASMtoFORTH              ;               search xx of Rxx
140             .word WORDD,QNUMBER     ;
141             .word QFBRAN,NOTaREG    ; -- xxxx       if Not a Number
142             FORTHtoASM              ; -- Rn         number is found
143             ADD #2,RSP              ;               remove >IN
144             CMP #16,TOS             ; -- Rn       
145             JHS BOUNDERROR          ;               abort if Rn out of bounds
146             JLO SearchEnd           ; -- Rn         Z=0 ==> found
147
148 NOTaREG     FORTHtoASM              ; -- addr       Z=1
149             MOV @RSP+,&TOIN         ; -- addr       restore >IN
150             JMP SearchEnd           ; -- addr       Z=1 ==> not a register 
151
152
153 ; ----------------------------------------------------------------------
154 ; DTCforthMSP430FR5xxx ASSEMBLER : INTERPRET FIRST OPERAND
155 ; ----------------------------------------------------------------------
156
157 ; PARAM1 is used for OPCODES type I (double operand) and OPCODES type II (single operand) instructions
158 ; PARAM1 is used for OPCODES type V (double operand) and OPCODES type VI (single operand) extended instructions
159
160 ; PARAM1     separator --           ; parse input buffer until separator and compute first operand of opcode
161                                     ; sep is comma for src and space for dst .
162 PARAM1      mDOCOL                  ; -- sep        OPCODES types I|V sep = ','  OPCODES types II|VI sep = ' '
163             .word   FBLANK,SKIP     ; -- sep addr
164             FORTHtoASM              ; -- sep addr
165             MOV     #0,S            ; -- sep addr   reset OPCODE
166             MOV     &DDP,T          ; -- sep addr   HERE --> OPCODEADR (opcode is preset to its address !)
167             ADD     #2,&DDP         ; -- sep addr   cell allot for opcode
168             MOV.B   @TOS,W          ; -- sep addr   W=first char of instruction code
169             MOV     @PSP+,TOS       ; -- sep        W=c-addr
170             CMP.B   #'#',W          ; -- sep        W=first char
171             JNE     PARAM11
172 ; "#" found : case of "#xxxx,"
173 PARAM10     ADD #1,&TOIN            ; -- sep        skip # prefix
174             CALL #SearchARG         ; -- xxxx       abort if not found
175             CALL #ARGD2S            ;               skip arg_hi of OPCODE type V
176             MOV #0300h,S            ;               OPCODE = 0300h : MOV #0,dst is coded MOV R3,dst
177             CMP #0,TOS              ; -- xxxx       #0 ?
178             JZ PARAMENDOF
179             MOV #0310h,S            ;               OPCODE = 0310h : MOV #1,dst is coded MOV 0(R3),dst
180             CMP #1,TOS              ; -- xxxx       #1 ?
181             JZ PARAMENDOF
182             MOV #0320h,S            ;               OPCODE = 0320h : MOV #2,dst is coded MOV @R3,dst
183             CMP #2,TOS              ; -- xxxx       #2 ?
184             JZ PARAMENDOF
185             MOV #0220h,S            ;               OPCODE = 0220h : MOV #4,dst is coded MOV @R2,dst
186             CMP #4,TOS              ; -- xxxx       #4 ?
187             JZ PARAMENDOF
188             MOV #0230h,S            ;               OPCODE = 0230h : MOV #8,dst is coded MOV @R2+,dst 
189             CMP #8,TOS              ; -- xxxx       #8 ?
190             JZ PARAMENDOF
191             MOV #0330h,S            ; -- -1         OPCODE = 0330h : MOV #-1,dst is coded MOV @R3+,dst
192             CMP #-1,TOS             ; -- xxxx       #-1 ?
193             JZ PARAMENDOF
194             MOV #0030h,S            ; -- xxxx       for all other cases : MOV @PC+,dst
195 ; case of "&xxxx,"                  ;               <== PARAM110
196 ; case of ",&xxxx"                  ;               <== PARAM20
197 StoreArg    MOV &DDP,X              ;
198             ADD #2,&DDP             ;               cell allot for arg
199 StoreTOS                            ;               <== TYPE1DOES
200             MOV TOS,0(X)            ;               compile arg
201 ; endcase of all "&xxxx"            ;
202 ; endcase of all "#xxxx"            ;               <== PARAM101,102,104,108,10M1
203 ; endcase of all "REG"|"@REG"|"@REG+"               <== PARAM124
204 PARAMENDOF  MOV @PSP+,TOS           ; --
205             MOV @RSP+,IP            ;
206             mNEXT                   ; --            S=OPCODE,T=OPCODEADR
207 ; ----------------------------------;
208 PARAM11     CMP.B   #'&',W          ; -- sep
209             JNE     PARAM12
210 ; case of "&xxxx,"                  ; -- sep        search for "&xxxx,"
211 PARAM110    MOV     #0210h,S        ; -- sep        set code type : xxxx(SR) with AS=0b01 ==> x210h (and SR=0 !)
212 ; case of "&xxxx,"
213 ; case of ",&xxxx"                  ;               <== PARAM20
214 PARAM111    ADD     #1,&TOIN        ; -- sep        skip "&" prefix
215             CALL    #SearchARG      ; -- arg        abort if not found
216             CALL    #ARGD2S         ;               skip arg_hi of opcode type V
217             JMP     StoreArg        ; --            then ret
218 ; ----------------------------------;
219 PARAM12     CMP.B   #'@',W          ; -- sep
220             JNE     PARAM13
221 ; case of "@REG,"|"@REG+,"
222 PARAM120    MOV     #0020h,S        ; -- sep        init OPCODE with indirect code type : AS=0b10
223             ADD     #1,&TOIN        ; -- sep        skip "@" prefix
224             CALL    #SearchREG      ;               Z = not found
225             JNZ     PARAM123        ; -- value      REG of "@REG," found
226 ; case of "@REG+,"                  ; -- addr       REG of "@REG" not found, search REG of "@REG+"
227 PARAM121    ADD     #0010h,S        ;               change OPCODE from @REG to @REG+ type
228             MOV     #'+',TOS        ; -- "+"        as WORD separator to find REG of "@REG+,"
229             CALL    #SearchREG      ; -- value|addr X = flag
230 ; case of "@REG+,"                  ;
231 ; case of "xxxx(REG),"              ;               <== PARAM130
232                                     ;               case of double separator:   +, and ),
233 PARAM122    CMP &SOURCE_LEN,&TOIN   ;               test OPCODE II parameter ending by REG+ or (REG) without comma,
234             JZ      PARAM123        ;               i.e. >IN = SOURCE_LEN : don't skip char CR !
235             ADD     #1,&TOIN        ; -- 000R       skip "," ready for the second operand search
236 ; case of "@REG+,"
237 ; case of "xxxx(REG),"
238 ; case of "@REG,"                   ; -- 000R       <== PARAM120
239 ; case of "REG,"                    ; -- 000R       <== PARAM13
240 PARAM123    SWPB    TOS             ; -- 0R00       swap bytes because it's not a dst REG typeI (not a 2 ops inst.)
241 ; case of "@REG+,"                  ; -- 0R00                   (src REG typeI)
242 ; case of "xxxx(REG),"              ; -- 0R00                   (src REG typeI or dst REG typeII)
243 ; case of "@REG,"                   ; -- 0R00                   (src REG typeI)
244 ; case of "REG,"                    ; -- 0R00                   (src REG typeI or dst REG typeII)
245 ; case of ",REG"                    ; -- 000R       <== PARAM21     (dst REG typeI)
246 ; case of ",xxxx(REG)"              ; -- 000R       <== PARAM210    (dst REG typeI)
247 PARAM124    ADD     TOS,S           ; -- 0R00|000R
248             JMP     PARAMENDOF
249 ; ----------------------------------;
250 ; case of "REG,"|"xxxx(REG),"       ;               first, searg REG of "REG,"
251 PARAM13     CALL    #SearchREG      ; -- sep        save >IN for second parsing (case of "xxxx(REG),")
252             JNZ     PARAM123        ; -- 000R       REG of "REG," found, S=OPCODE=0
253 ; case of "xxxx(REG),"              ; -- c-addr     "REG," not found
254 PARAM130    ADD     #0010h,S        ;               AS=0b01 for indexing address
255             CALL #ComputeARGparenREG;               compile xxxx and search REG of "(REG)"
256             JMP     PARAM122        ; 
257
258 ; ----------------------------------------------------------------------
259 ; DTCforthMSP430FR5xxx ASSEMBLER : INTERPRET 2th OPERAND
260 ; ----------------------------------------------------------------------
261
262 PARAM3                              ; for OPCODES TYPE III
263             MOV     #0,S            ;                       init OPCODE=0
264             MOV     &DDP,T          ;                       T=OPCODEADR
265             ADD     #2,&DDP         ;                       make room for opcode
266 ; ----------------------------------;
267 PARAM2      mDOCOL                  ;               parse input buffer until BL and compute this 2th operand
268             .word   FBLANK,SKIP     ;               skip space(s) between "arg1," and "arg2" if any; use not S,T.
269             FORTHtoASM              ; -- c-addr     search for '&' of "&xxxx
270             CMP.B   #'&',0(TOS)     ;
271             MOV     #20h,TOS        ; -- ' '        as WORD separator to find xxxx of ",&xxxx"
272             JNE     PARAM21         ;               '&' not found
273 ; case of ",&xxxx"                  ;
274 PARAM20     ADD     #0082h,S        ;               change OPCODE : AD=1, dst = R2
275             JMP     PARAM111        ; -- ' '
276 ; ----------------------------------;
277 ; case of ",REG"|",xxxx(REG)        ; -- ' '        first, search REG of ",REG"
278 PARAM21     CALL    #SearchREG      ;
279             JNZ     PARAM124        ; -- 000R       REG of ",REG" found
280 ; case of ",xxxx(REG)               ; -- addr       REG not found
281 PARAM210    ADD     #0080h,S        ;               set AD=1
282             CALL #ComputeARGparenREG;               compile argument xxxx and search REG of "(REG)"
283             JMP     PARAM124        ; -- 000R       REG of "(REG) found
284
285 ; ----------------------------------------------------------------------
286 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODE TYPE 0 : zero operand     f:-)
287 ; ----------------------------------------------------------------------
288             asmword "RETI"
289             mDOCOL
290             .word   lit,1300h,COMMA,EXIT
291
292 ; ----------------------------------------------------------------------
293 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODES TYPE I : double operand
294 ; ----------------------------------------------------------------------
295 ;                                               OPCODE(FEDC)
296 ; OPCODE(code) for TYPE I                          = 0bxxxx             opcode I
297 ;                                                   OPCODE(BA98)
298 ;                                                      = 0bxxxx         src register
299 ;                                                       OPCODE(7)       AD (dst addr type)
300 ;                                                          = 0b0        register
301 ;                                                          = 0b1        x(Rn),&adr
302 ;                                                        OPCODE(6)      size
303 ; OPCODE(B)  for TYPE I or TYPE II                          = 0b0       word
304 ;                                                           = 0b1       byte
305 ;                                                         OPCODE(54)    AS (src addr type)
306 ; OPCODE(AS) for TYPE I or OPCODE(AD) for TYPE II            = 0b00     register
307 ;                                                            = 0b01     x(Rn),&adr
308 ;                                                            = 0b10     @Rn
309 ;                                                            = 0b11     @Rn+
310 ;                                                           OPCODE(3210)
311 ; OPCODE(dst) for TYPE I or TYPE II                            = 0bxxxx dst register
312 ; ----------------------------------------------------------------------
313
314 ; TYPE1DOES     -- BODYDOES      search and compute PARAM1 & PARAM2 as src and dst operands then compile instruction
315 TYPE1DOES   .word   lit,',',PARAM1  ; -- BODYDOES
316             .word   PARAM2          ; -- BODYDOES           char separator (BL) included in PARAM2
317             FORTHtoASM              ;
318 MAKEOPCODE  MOV     T,X             ; -- opcode             X= OPCODEADR to compile opcode
319             MOV     @TOS,TOS        ; -- opcode             part of instruction
320             BIS     S,TOS           ; -- opcode             opcode is complete
321             JMP     StoreTOS        ; --                    then EXIT
322
323             asmword "MOV"
324             mDODOES
325             .word   TYPE1DOES,4000h
326             asmword "MOV.B"
327             mDODOES
328             .word   TYPE1DOES,4040h
329             asmword "ADD"
330             mDODOES
331             .word   TYPE1DOES,5000h
332             asmword "ADD.B"
333             mDODOES
334             .word   TYPE1DOES,5040h
335             asmword "ADDC"
336             mDODOES
337             .word   TYPE1DOES,6000h
338             asmword "ADDC.B"
339             mDODOES
340             .word   TYPE1DOES,6040h
341             asmword "SUBC"
342             mDODOES
343             .word   TYPE1DOES,7000h
344             asmword "SUBC.B"
345             mDODOES
346             .word   TYPE1DOES,7040h
347             asmword "SUB"
348             mDODOES
349             .word   TYPE1DOES,8000h
350             asmword "SUB.B"
351             mDODOES
352             .word   TYPE1DOES,8040h
353             asmword "CMP"
354             mDODOES
355             .word   TYPE1DOES,9000h
356             asmword "CMP.B"
357             mDODOES
358             .word   TYPE1DOES,9040h
359             asmword "DADD"
360             mDODOES
361             .word   TYPE1DOES,0A000h
362             asmword "DADD.B"
363             mDODOES
364             .word   TYPE1DOES,0A040h
365             asmword "BIT"
366             mDODOES
367             .word   TYPE1DOES,0B000h
368             asmword "BIT.B"
369             mDODOES
370             .word   TYPE1DOES,0B040h
371             asmword "BIC"
372             mDODOES
373             .word   TYPE1DOES,0C000h
374             asmword "BIC.B"
375             mDODOES
376             .word   TYPE1DOES,0C040h
377             asmword "BIS"
378             mDODOES
379             .word   TYPE1DOES,0D000h
380             asmword "BIS.B"
381             mDODOES
382             .word   TYPE1DOES,0D040h
383             asmword "XOR"
384             mDODOES
385             .word   TYPE1DOES,0E000h
386             asmword "XOR.B"
387             mDODOES
388             .word   TYPE1DOES,0E040h
389             asmword "AND"
390             mDODOES
391             .word   TYPE1DOES,0F000h
392             asmword "AND.B"
393             mDODOES
394             .word   TYPE1DOES,0F040h
395
396 ; ----------------------------------------------------------------------
397 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES TYPE II : single operand
398 ; ----------------------------------------------------------------------
399 ;                                               OPCODE(FEDCBA987)       opcodeII
400 ; OPCODE(code) for TYPE II                         = 0bxxxxxxxxx
401 ;                                                        OPCODE(6)      size
402 ; OPCODE(B)  for TYPE I or TYPE II                          = 0b0       word
403 ;                                                           = 0b1       byte
404 ;                                                         OPCODE(54)    (dst addr type)
405 ; OPCODE(AS) for TYPE I or OPCODE(AD) for TYPE II            = 0b00     register
406 ;                                                            = 0b01     x(Rn),&adr
407 ;                                                            = 0b10     @Rn
408 ;                                                            = 0b11     @Rn+
409 ;                                                           OPCODE(3210)
410 ; OPCODE(dst) for TYPE I or TYPE II                            = 0bxxxx dst register
411 ; ----------------------------------------------------------------------
412
413 TYPE2DOES   .word   FBLANK,PARAM1   ; -- BODYDOES
414             FORTHtoASM              ;
415             MOV     S,W             ;
416             AND     #0070h,S        ;                   keep B/W & AS infos in OPCODE
417             SWPB    W               ;                   (REG org --> REG dst)
418             AND     #000Fh,W        ;                   keep REG
419 BIS_ASMTYPE BIS     W,S             ; -- BODYDOES       add it in OPCODE
420             JMP     MAKEOPCODE      ; -- then end
421
422             asmword "RRC"           ; Rotate Right through Carry ( word)
423             mDODOES
424             .word   TYPE2DOES,1000h
425             asmword "RRC.B"         ; Rotate Right through Carry ( byte)
426             mDODOES
427             .word   TYPE2DOES,1040h
428             asmword "SWPB"          ; Swap bytes
429             mDODOES
430             .word   TYPE2DOES,1080h
431             asmword "RRA"
432             mDODOES
433             .word   TYPE2DOES,1100h
434             asmword "RRA.B"
435             mDODOES
436             .word   TYPE2DOES,1140h
437             asmword "SXT"
438             mDODOES
439             .word   TYPE2DOES,1180h
440             asmword "PUSH"
441             mDODOES
442             .word   TYPE2DOES,1200h
443             asmword "PUSH.B"
444             mDODOES
445             .word   TYPE2DOES,1240h
446             asmword "CALL"
447             mDODOES
448             .word   TYPE2DOES,1280h
449
450 BOUNDERRWM1 ADD     #1,W            ; <== RRAM|RRUM|RRCM|RLAM error
451 BOUNDERRORW MOV     W,TOS           ; <== PUSHM|POPM|ASM_branch error
452 BOUNDERROR                          ; <== REG number error
453             mDOCOL                  ; -- n      n = value out of bounds
454             .word   DOT,XSQUOTE
455             .byte 13,"out of bounds"
456             .word   QABORTYES
457
458 ; --------------------------------------------------------------------------------
459 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES TYPE III : PUSHM|POPM|RLAM|RRAM|RRUM|RRCM
460 ; --------------------------------------------------------------------------------
461 ; PUSHM, syntax:    PUSHM #n,REG  with 0 < n < 17 
462 ; POPM syntax:       POPM #n,REG  with 0 < n < 17 
463
464
465 ; PUSHM order : PSP,TOS, IP,  S,  T,  W,  X,  Y, rEXIT,rDOVAR,rDOCON, rDODOES, R3, SR,RSP, PC
466 ; PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8,  R7  ,  R6  ,  R5  ,   R4   , R3, R2, R1, R0
467
468 ; example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
469 ;
470 ; POPM  order :  PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT,  Y,  X,  W,  T,  S, IP,TOS,PSP
471 ; POPM  order :  R0, R1, R2, R3,   R4   ,  R5  ,  R6  ,  R7 , R8, R9,R10,R11,R12,R13,R14,R15
472
473 ; example : POPM #6,IP   pulls Y,X,W,T,S,IP registers from return stack
474
475 ; RxxM syntax: RxxM #n,REG  with 0 < n < 5 
476
477 TYPE3DOES   .word   FBLANK,SKIP     ;                       skip spaces if any
478             FORTHtoASM              ; -- BODYDOES c-addr
479             ADD     #1,&TOIN        ;                       skip "#"
480             MOV     #',',TOS        ; -- BODYDOES ","
481             ASMtoFORTH
482             .word   WORDD,QNUMBER
483             .word   QFBRAN,NotFound ;                       ABORT
484             .word   PARAM3          ; -- BODYDOES 0x000N    S=OPCODE = 0x000R
485             FORTHtoASM
486             MOV     TOS,W           ; -- BODYDOES n         W = n
487             MOV     @PSP+,TOS       ; -- BODYDOES
488             SUB     #1,W            ;                       W = n floored to 0
489             JN      BOUNDERRWM1
490             MOV     @TOS,X          ;                       X=OPCODE
491             RLAM    #4,X            ;                       OPCODE bit 1000h --> C
492             JNC     RxxMINSTRU      ;                       if bit 1000h = 0
493 PxxxINSTRU  MOV     S,Y             ;                       S=REG, Y=REG to test
494             RLAM    #3,X            ;                       OPCODE bit 0200h --> C                  
495             JNC     PUSHMINSTRU     ;                       W=n-1 Y=REG
496 POPMINSTRU  SUB     W,S             ;                       to make POPM opcode, compute first REG to POP; TI is complicated....
497 PUSHMINSTRU SUB     W,Y             ;                       Y=REG-(n-1)
498             CMP     #16,Y
499             JHS     BOUNDERRWM1     ;                       JC=JHS    (U>=)
500             RLAM    #4,W            ;                       W = n << 4      
501             JMP     BIS_ASMTYPE     ; BODYDOES --            
502 RxxMINSTRU  CMP     #4,W            ;
503             JHS     BOUNDERRWM1     ;                       JC=JHS    (U>=)
504             SWPB    W               ; -- BODYDOES           W = n << 8
505             RLAM    #2,W            ;                       W = N << 10
506             JMP     BIS_ASMTYPE     ; BODYDOES --
507
508             asmword "RRCM.A"
509             mDODOES
510             .word   TYPE3DOES,0040h
511             asmword "RRCM"
512             mDODOES
513             .word   TYPE3DOES,0050h
514             asmword "RRAM.A"
515             mDODOES
516             .word   TYPE3DOES,0140h
517             asmword "RRAM"
518             mDODOES
519             .word   TYPE3DOES,0150h
520             asmword "RLAM.A"
521             mDODOES
522             .word   TYPE3DOES,0240h
523             asmword "RLAM"
524             mDODOES
525             .word   TYPE3DOES,0250h
526             asmword "RRUM.A"
527             mDODOES
528             .word   TYPE3DOES,0340h
529             asmword "RRUM"
530             mDODOES
531             .word   TYPE3DOES,0350h
532             asmword "PUSHM.A"
533             mDODOES
534             .word   TYPE3DOES,1400h
535             asmword "PUSHM"
536             mDODOES
537             .word   TYPE3DOES,1500h
538             asmword "POPM.A"
539             mDODOES
540             .word   TYPE3DOES,1600h
541             asmword "POPM"
542             mDODOES
543             .word   TYPE3DOES,1700h
544
545 ; ----------------------------------------------------------------------
546 ; DTCforthMSP430FR5xxx ASSEMBLER, CONDITIONAL BRANCHS
547 ; ----------------------------------------------------------------------
548 ;                       ASSEMBLER       FORTH         OPCODE(FEDC)
549 ; OPCODE(code) for TYPE JNE,JNZ         0<>, <>     = 0x20xx + (offset AND 3FF) ; branch if Z = 0
550 ; OPCODE(code) for TYPE JEQ,JZ          0=, =       = 0x24xx + (offset AND 3FF) ; branch if Z = 1
551 ; OPCODE(code) for TYPE JNC,JLO         U<          = 0x28xx + (offset AND 3FF) ; branch if C = 0
552 ; OPCODE(code) for TYPE JC,JHS          U>=         = 0x2Cxx + (offset AND 3FF) ; branch if C = 1
553 ; OPCODE(code) for TYPE JN              0<          = 0x30xx + (offset AND 3FF) ; branch if N = 1
554 ; OPCODE(code) for TYPE JGE             >=          = 0x34xx + (offset AND 3FF) ; branch if (N xor V) = 0
555 ; OPCODE(code) for TYPE JL              <           = 0x38xx + (offset AND 3FF) ; branch if (N xor V) = 1
556 ; OPCODE(code) for TYPE JMP                         = 0x3Cxx + (offset AND 3FF)
557
558             asmword "S>="           ; if >= assertion (opposite of jump if < )
559             mDOCON
560             .word   3800h
561
562             asmword "S<"            ; if < assertion
563             mDOCON
564             .word   3400h
565
566             asmword "0>="           ; if 0>= assertion  ; use only with IF UNTIL WHILE !
567             mDOCON
568             .word   3000h
569
570             asmword "0<"            ; jump if 0<        ; use only with ?JMP ?GOTO !
571             mDOCON
572             .word   3000h
573
574             asmword "U<"            ; if U< assertion
575             mDOCON
576             .word   2C00h
577
578             asmword "U>="           ; if U>= assertion
579             mDOCON
580             .word   2800h
581
582             asmword "0<>"           ; if <>0 assertion
583             mDOCON
584             .word   2400h
585
586             asmword "0="            ; if =0 assertion
587             mDOCON
588             .word   2000h
589
590 ;ASM IF      OPCODE -- @OPCODE1
591             asmword "IF"
592 ASM_IF      MOV     &DDP,W
593             MOV     TOS,0(W)        ; compile incomplete opcode
594             ADD     #2,&DDP
595             MOV     W,TOS
596             mNEXT
597
598 ;ASM THEN     @OPCODE --        resolve forward branch
599             asmword "THEN"
600 ASM_THEN    MOV     &DDP,W          ; -- @OPCODE    W=dst
601             MOV     TOS,Y           ;               Y=@OPCODE
602 ASM_THEN1   MOV     @PSP+,TOS       ; --
603             MOV     Y,X             ;
604             ADD     #2,X            ; --        Y=@OPCODE   W=dst   X=src+2
605             SUB     X,W             ; --        Y=@OPCODE   W=dst-src+2=displacement*2 (bytes)
606             RRA     W               ; --        Y=@OPCODE   W=displacement (words)
607             CMP     #512,W
608             JC      BOUNDERRORW     ; (JHS) unsigned branch if u> 511
609             BIS     W,0(Y)          ; --       [@OPCODE]=OPCODE completed
610             mNEXT
611
612 ;C ELSE     @OPCODE1 -- @OPCODE2    branch for IF..ELSE
613             asmword "ELSE"
614 ASM_ELSE    MOV     &DDP,W          ; --        W=HERE
615             MOV     #3C00h,0(W)     ;           compile unconditionnal branch
616             ADD     #2,&DDP         ; --        DP+2
617             SUB     #2,PSP
618             MOV     W,0(PSP)        ; -- @OPCODE2 @OPCODE1
619             JMP     ASM_THEN        ; -- @OPCODE2
620
621 ;C BEGIN    -- @BEGIN               same as FORTH counterpart
622
623 ;C UNTIL    @BEGIN OPCODE --   resolve conditional backward branch
624             asmword "UNTIL"
625 ASM_UNTIL   MOV     @PSP+,W         ;  -- OPCODE                        W=@BEGIN
626 ASM_UNTIL1  MOV     TOS,Y           ;               Y=OPCODE            W=@BEGIN
627 ASM_UNTIL2  MOV     @PSP+,TOS       ;  --
628             MOV     &DDP,X          ;  --           Y=OPCODE    X=HERE  W=dst
629             SUB     #2,W            ;  --           Y=OPCODE    X=HERE  W=dst-2
630             SUB     X,W             ;  --           Y=OPCODE    X=src   W=src-dst-2=displacement (bytes)
631             RRA     W               ;  --           Y=OPCODE    X=HERE  W=displacement (words)
632             CMP     #-512,W
633             JL      BOUNDERRORW     ; signed branch if < -512
634             AND     #3FFh,W         ;  --           Y=OPCODE   X=HERE  W=troncated negative displacement (words)
635             BIS     W,Y             ;  --           Y=OPCODE (completed)
636             MOV     Y,0(X)
637             ADD     #2,&DDP
638             mNEXT
639
640 ;X AGAIN    @BEGIN --      uncond'l backward branch
641 ;   unconditional backward branch
642             asmword "AGAIN"
643 ASM_AGAIN   MOV TOS,W               ;               W=@BEGIN
644             MOV #3C00h,Y            ;               Y = asmcode JMP
645             JMP ASM_UNTIL2          ;
646
647 ;C WHILE    @BEGIN OPCODE -- @WHILE @BEGIN
648             asmword "WHILE"
649 ASM_WHILE   mDOCOL                  ; -- @BEGIN OPCODE
650             .word   ASM_IF,SWAP,EXIT
651
652 ;C REPEAT   @WHILE @BEGIN --     resolve WHILE loop
653             asmword "REPEAT"
654 ASM_REPEAT  mDOCOL                  ; -- @WHILE @BEGIN
655             .word   ASM_AGAIN,ASM_THEN,EXIT
656
657 ; ------------------------------------------------------------------------------------------
658 ; DTCforthMSP430FR5xxx ASSEMBLER : branch up to 3 backward labels and up to 3 forward labels
659 ; ------------------------------------------------------------------------------------------
660 ; used for non canonical branchs, as BASIC language: "goto line x"
661 ; labels BWx and FWx must be set at the beginning of line (>IN < 8).
662 ; FWx at the beginning of a line can resolve only one previous GOTO|?GOTO  FWx.
663 ; BWx at the beginning of a line can be resolved by any subsequent GOTO|?GOTO BWx.
664
665 BACKWDOES   FORTHtoASM
666             MOV @RSP+,IP            ;
667             MOV TOS,Y               ; -- PFA        Y = ASMBWx addr
668             MOV @PSP+,TOS           ; --
669             MOV @Y,W                ;               W = LABEL
670             CMP #8,&TOIN            ;               are we colon 8 or more ?
671 BACKWUSE    JHS ASM_UNTIL1          ;               yes, use this label  
672 BACKWSET    MOV &DDP,0(Y)           ;               no, set LABEL = DP
673             mNEXT
674
675 ; backward label 1
676             asmword "BW1"
677             mdodoes
678             .word BACKWDOES
679             .word 0
680 ; backward label 2
681             asmword "BW2"
682             mdodoes
683             .word BACKWDOES
684             .word 0
685 ; backward label 3
686             asmword "BW3"
687             mdodoes
688             .word BACKWDOES
689             .word 0
690
691 FORWDOES    FORTHtoASM
692             MOV @RSP+,IP
693             MOV &DDP,W              ;
694             MOV @TOS,Y              ; -- PFA        Y=[ASMFWx]
695             CMP #8,&TOIN            ;               are we colon 8 or more ?
696 FORWUSE     JLO ASM_THEN1           ;               no: resolve FWx with W=DDP, Y=ASMFWx
697 FORWSET     MOV @PSP+,0(W)          ;               yes compile incomplete opcode
698             ADD #2,&DDP             ;                   increment DDP
699             MOV W,0(TOS)            ;                   store @OPCODE into ASMFWx
700             MOV @PSP+,TOS           ;   --
701             mNEXT
702
703 ; forward label 1
704             asmword "FW1"
705             mdodoes
706             .word FORWDOES
707             .word 0
708 ; forward label 2
709             asmword "FW2"
710             mdodoes
711             .word FORWDOES
712             .word 0
713 ; forward label 3
714             asmword "FW3"
715             mdodoes
716             .word FORWDOES
717             .word 0
718
719 ;ASM    <cond> ?GOTO <label>    OPCODE --       conditionnal branch to label
720             asmword "?GOTO"
721 INVJMP      CMP #3000h,TOS          ; invert code jump process
722             JZ GOTONEXT             ; case of JN, do nothing
723             XOR #0400h,TOS          ; case of: JNZ<-->JZ  JNC<-->JC  JL<-->JGE
724             BIT #1000h,TOS          ; 3xxxh case ?
725             JZ  GOTONEXT            ; no
726             XOR #0800h,TOS          ; complementary action for JL<-->JGE
727 GOTONEXT    mDOCOL
728             .word   TICK            ;  -- OPCODE CFA<label>
729             .word   EXECUTE,EXIT
730
731 ;ASM    GOTO <label>                   --       unconditionnal branch to label
732             asmword "GOTO"
733             SUB #2,PSP
734             MOV TOS,0(PSP)
735             MOV #3C00h,TOS          ; asmcode JMP
736             JMP GOTONEXT
737
738 ; ===============================================================
739 ; Extended assembler
740 ; ===============================================================
741
742 ; ===============================================================
743 ; to allow data access beyond $FFFF
744 ; ===============================================================
745
746 ; MOVA (#$x.xxxx|&$x.xxxx|$.xxxx(Rs)|Rs|@Rs|@Rs+ , &|Rd|$.xxxx(Rd)) 
747 ; ADDA (#$x.xxxx|Rs , Rd) 
748 ; CMPA (#$x.xxxx|Rs , Rd) 
749 ; SUBA (#$x.xxxx|Rs , Rd) 
750
751 ; first argument process ACMS1
752 ;-----------------------------------;
753 ACMS1       mDOCOL                  ; -- BODYDOES ','   
754             .word   FBLANK,SKIP     ; -- BODYDOES ',' addr
755             FORTHtoASM              ;
756             MOV.B @TOS,X            ;                   X=first char of opcode string
757             MOV @PSP+,TOS           ; -- BODYDOES ','
758             MOV @PSP+,S             ; -- ','            S=BODYDOES
759             MOV @S,S                ;                   S=opcode
760             MOV &DDP,T              ;                   T=DDP
761             ADD #2,&DDP             ;                   make room for opcode
762 ;-----------------------------------;
763 ACMS10      CMP.B #'R',X            ; -- ','    
764             JNZ ACMS11              ;
765 ACMS101     CALL #SearchREG         ; -- Rn         src
766 ACMS102     RLAM #4,TOS             ;               8<<src
767             RLAM #4,TOS             ;
768 ACMS103     BIS S,TOS               ;               update opcode with src|dst
769             MOV TOS,0(T)            ;               save opcode
770             MOV T,TOS               ; -- OPCODE_addr
771             mSEMI                   ;
772 ;-----------------------------------;
773 ACMS11      CMP.B #'#',X            ; -- ','        X=addr
774             JNE MOVA12              ;
775             BIC #40h,S              ;               set #opcode
776 ACMS111     ADD #1,&TOIN            ;               skip '#'|'&'
777             ADD #2,&DDP             ;               make room for low #$xxxx|&$xxxx|$xxxx(REG)
778             CALL #SearchARG         ; -- Lo Hi
779             MOV @PSP+,2(T)          ; -- Hi         store $xxxx of #$x.xxxx|&$x.xxxx|$x.xxxx(REG)
780             AND #0Fh,TOS            ; -- Hi         sel Hi src
781             JMP ACMS102             ;
782 ;-----------------------------------;
783 MOVA12      CMP.B #'&',X            ; -- ','        case of MOVA &$x.xxxx
784             JNZ MOVA13              ;
785             XOR #00E0h,S            ;               set MOVA &$x.xxxx, opcode                 
786             JMP ACMS111             ;
787 ;-----------------------------------;
788 MOVA13      BIC #00F0h,S            ;               set MOVA @REG, opcode
789             CMP.B #'@',X            ; -- ','
790             JNZ MOVA14              ;
791             ADD #1,&TOIN            ;               skip '@'
792             CALL #SearchREG         ; -- Rn 
793             JNZ ACMS102             ;               if @REG found
794 ;-----------------------------------;
795             BIS #0010h,S            ;               set @REG+ opcode
796             MOV #'+',TOS            ; -- '+'
797 MOVA131     CALL #SearchREG         ; -- Rn         case of MOVA @REG+,|MOVA $x.xxxx(REG),
798             CMP &SOURCE_LEN,&TOIN   ;               test TYPE II first parameter ending by @REG+ (REG) without comma,
799             JZ ACMS102              ;               i.e. may be >IN = SOURCE_LEN: don't skip char CR !
800             ADD #1,&TOIN            ;               skip "," ready for the second operand search
801             JMP ACMS102             ;
802 ;-----------------------------------;
803 MOVA14      BIS #0030h,S            ;               set xxxx(REG), opcode
804             ADD #2,&DDP             ; -- ','        make room for first $xxxx of $0.xxxx(REG),
805             MOV #'(',TOS            ; -- "("        as WORD separator to find xxxx of "xxxx(REG),"
806             CALL #SearchARG         ; -- Lo Hi
807             MOV @PSP+,2(T)          ; -- Hi         store $xxxx as 2th word
808             MOV #')',TOS            ; -- ')'
809             JMP MOVA131             ;
810
811 ; 2th argument process ACMS2
812 ;-----------------------------------;
813 ACMS2       mDOCOL                  ; -- OPCODE_addr 
814             .word FBLANK,SKIP       ; -- OPCODE_addr addr
815             FORTHtoASM              ;
816             MOV @PSP+,T             ; -- addr       T=OPCODE_addr
817             MOV @T,S                ;               S=opcode
818             MOV.B @TOS,X            ; -- addr       X=first char of string instruction         
819             MOV.B #' ',TOS          ; -- ' '
820 ;-----------------------------------;
821 ACMS21      CMP.B #'R',X            ; -- ' '
822             JNZ MOVA22              ;
823 ACMS211     CALL #SearchREG         ; -- Rn
824             JMP ACMS103             ;
825 ;-----------------------------------;
826 MOVA22      BIC #0F0h,S             ;
827             ADD #2,&DDP             ; -- ' '        make room for $xxxx
828             CMP.B #'&',X            ;
829             JNZ MOVA23              ;
830             BIS #060h,S             ;               set ,&$x.xxxx opcode
831             ADD #1,&TOIN            ;               skip '&'
832             CALL #SearchARG         ; -- Lo Hi
833             MOV @PSP+,2(T)          ; -- Hi         store $xxxx as 2th word
834             JMP ACMS103             ;               update opcode with dst $x and write opcode
835 ;-----------------------------------;
836 MOVA23      BIS #070h,S             ;               set ,xxxx(REG) opcode
837             MOV #'(',TOS            ; -- "("        as WORD separator to find xxxx of "xxxx(REG),"
838             CALL #SearchARG         ; -- Lo Hi
839             MOV @PSP+,2(T)          ; -- Hi         write $xxxx of ,$0.xxxx(REG) as 2th word
840             MOV #')',TOS            ; -- ")"        as WORD separator to find REG of "xxxx(REG),"
841             JMP ACMS211
842
843 ; --------------------------------------------------------------------------------
844 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES IV 2 operands: Adda|Cmpa|Mova|Suba (without extended word)
845 ; --------------------------------------------------------------------------------
846 ; absolute and immediate instructions must be written as $x.xxxx  (DOUBLE numbers)
847 ; indexed instructions must be written as $.xxxx(REG) (DOUBLE numbers)
848 ; --------------------------------------------------------------------------------
849
850 TYPE4DOES   .word   lit,','         ; -- BODYDOES ","        char separator for PARAM1
851             .word   ACMS1           ; -- OPCODE_addr
852             .word   ACMS2           ; -- OPCODE_addr
853             .word   DROP,EXIT
854
855             asmword "MOVA"
856             mDODOES
857             .word   TYPE4DOES,00C0h
858             asmword "CMPA"
859             mDODOES
860             .word   TYPE4DOES,00D0h
861             asmword "ADDA"
862             mDODOES
863             .word   TYPE4DOES,00E0h
864             asmword "SUBA"
865             mDODOES
866             .word   TYPE4DOES,00F0h
867
868 ; --------------------------------------------------------------------------------
869 ; DTCforthMSP430FR5xxx ASSEMBLER:  OPCODE TYPE III bis: CALLA (without extended word)
870 ; --------------------------------------------------------------------------------
871 ; absolute and immediate instructions must be written as $x.xxxx  (DOUBLE numbers)
872 ; indexed instructions must be written as $.xxxx(REG) (DOUBLE numbers)
873 ; --------------------------------------------------------------------------------
874
875             asmword "CALLA"
876             mDOCOL
877             .word FBLANK,SKIP       ; -- addr
878             FORTHtoASM
879             MOV &DDP,T              ;           T = DDP
880             ADD #2,&DDP             ;           make room for opcode
881             MOV.B @TOS,TOS          ; -- char   First char of opcode
882 CALLA0      MOV #134h,S             ;           134h<<4 = 1340h = opcode for CALLA Rn
883             CMP.B #'R',TOS   
884             JNZ CALLA1
885 CALLA01     MOV.B #' ',TOS          ;        
886 CALLA02     CALL #SearchREG         ; -- Rn
887 CALLA03     RLAM #4,S               ;           (opcode>>4)<<4 = opcode
888             BIS TOS,S               ;           update opcode
889             MOV S,0(T)              ;           store opcode
890             MOV @PSP+,TOS
891             mSEMI
892 ;-----------------------------------;
893 CALLA1      ADD #2,S                ;           136h<<4 = opcode for CALLA @REG
894             CMP.B #'@',TOS          ; -- char   Search @REG
895             JNZ CALLA2              ;
896             ADD #1,&TOIN            ;           skip '@'
897             MOV.B #' ',TOS          ; -- ' '
898             CALL #SearchREG         ;
899             JNZ  CALLA03            ;           if REG found, update opcode
900 ;-----------------------------------;
901             ADD #1,S                ;           137h<<4 = opcode for CALLA @REG+
902             MOV #'+',TOS            ; -- '+'
903             JMP CALLA02             ;
904 ;-----------------------------------;
905 CALLA2      ADD #2,&DDP             ;           make room for xxxx of #$x.xxxx|&$x.xxxx|$0.xxxx(REG)
906             CMP.B #'#',TOS          ;
907             JNZ CALLA3
908             MOV #13Bh,S             ;           13Bh<<4 = opcode for CALLA #$x.xxxx
909 CALLA21     ADD #1,&TOIN            ;           skip '#'|'&'
910 CALLA22     CALL #SearchARG         ; -- Lo Hi
911             MOV @PSP+,2(T)          ; -- Hi     store #$xxxx|&$xxxx
912             JMP CALLA03             ;           update opcode with $x. and store opcode
913 ;-----------------------------------;
914 CALLA3      CMP.B #'&',TOS   
915             JNZ CALLA4              ;
916             ADD #2,S                ;           138h<<4 = opcode for CALLA &$x.xxxx
917             JMP CALLA21
918 ;-----------------------------------;
919 CALLA4      MOV.B #'(',TOS          ; -- "("
920             SUB #1,S                ;           135h<<4 = opcode for CALLA $0.xxxx(REG)
921 CALLA41     CALL #SearchARG         ; -- Lo Hi
922             MOV @PSP+,2(T)          ; -- Hi     store $xxxx 
923             MOV #')',TOS            ; -- ')'
924             JMP CALLA02             ;           search Rn and update opcode
925     
926
927 ; PRMX1 is used for OPCODES type V (double operand) and OPCODES type VI (single operand) extended instructions
928
929 PRMX1       mDOCOL                  ; -- sep            OPCODES type V|VI separator = ','|' '
930             .word FBLANK,SKIP       ; -- sep addr
931             FORTHtoASM              ;
932             MOV.B @TOS,X            ; -- sep addr       X= first char of opcode string
933             MOV @PSP+,TOS           ; -- sep
934             MOV #1800h,S            ;                   init S=Extended word
935 ;-----------------------------------;
936 PRMX10      CMP.B #'R',X            ; -- sep
937             JNZ PRMX11              ;
938 PRMX101     CALL #SearchREG         ; -- Rn             Rn of REG; call SearchREG only to update >IN
939 PRMX102     MOV S,TOS               ; -- EW             update Extended word
940 PRMX103     mSEMI                   ; -- Ext_Word
941 ;-----------------------------------;
942 PRMX11      MOV #0,&RPT_WORD        ;                   clear RPT
943             CMP.B #'#',X            ; -- sep
944             JNZ PRMX12
945 PRMX111     ADD #1,&TOIN            ; -- sep            skip '#'
946 PRMX112     CALL #SearchARG         ; -- Lo Hi          search $x.xxxx of #x.xxxx,
947             ADD #2,PSP              ; -- Hi             pop unused low word
948 PRMX113     AND #0Fh,TOS            ;                   
949 PRMX114     RLAM #3,TOS
950             RLAM #4,TOS             ; -- 7<<Hi
951 PRMX115     BIS TOS,S               ;                   update extended word with srcHi
952             JMP PRMX102
953 ;-----------------------------------;
954 PRMX12      CMP.B #'&',X            ; -- sep
955             JZ PRMX111
956 ;-----------------------------------;
957 PRMX13      CMP.B #'@',X            ; -- sep
958             JNZ PRMX14
959 PRMX131     ADD #1,&TOIN            ; -- sep            skip '@'
960 PRMX132     CALL #SearchREG         ; -- Rn             Rn of @REG,
961             JNZ PRMX102             ;                   if Rn found
962 ;-----------------------------------;
963             MOV #'+',TOS            ; -- '+'
964 PRMX133     ADD #1,&TOIN            ;                   skip '@'
965             CALL #SearchREG         ; -- Rn             Rn of @REG+,
966 PRMX134     CMP &SOURCE_LEN,&TOIN   ;                   test case of TYPE VI first parameter without ','
967             JZ PRMX102              ;                   don't take the risk of skipping CR !
968             ADD #1,&TOIN            ;                   skip ',' ready to search 2th operand
969             JMP PRMX102             ;
970 ;-----------------------------------;
971 PRMX14      MOV #'(',TOS            ; -- '('            to find $x.xxxx of "x.xxxx(REG),"
972             CALL #SearchARG         ; -- Lo Hi                  
973             MOV TOS,0(PSP)          ; -- Hi Hi
974 PRMX141     MOV #')',TOS            ; -- Hi ')'
975             CALL #SearchREG         ; -- Hi Rn
976             MOV @PSP+,TOS           ; -- Hi
977             AND #0Fh,TOS
978             BIS TOS,S
979             JMP PRMX134
980 ;-----------------------------------;
981
982 ; PRMX2 is used for OPCODES type V (double operand) extended instructions
983         
984 ;-----------------------------------;
985 PRMX2       mDOCOL                  ; -- Extended_Word 
986             .word   FBLANK,SKIP     ; -- Extended_Word addr
987             FORTHtoASM              ;
988             MOV @PSP+,S             ; -- addr     S=Extended_Word
989             MOV.B @TOS,X            ; -- addr     X=first char of code instruction
990             MOV #' ',TOS            ; -- ' '
991 ;-----------------------------------;
992 PRMX20      CMP.B #'R',X            ; -- ' '
993             JZ  PRMX102             ;               extended word not to be updated  
994 ;-----------------------------------;
995 PRMX21      MOV #0,&RPT_WORD        ;
996             CMP.B #'&',X            ;
997             JNZ PRMX22              ;
998 PRMX211     ADD #1,&TOIN            ; -- ' '      skip '&'
999 PRMX212     CALL #SearchARG         ; -- Lo Hi
1000 PRMX213     ADD #2,PSP              ; -- hi       pop low word
1001             AND #0Fh,TOS            ; -- Hi
1002             JMP PRMX115             ;               update Extended word with dst_Hi
1003 ;-----------------------------------;
1004 PRMX22      MOV #'(',TOS            ; -- '('      as WORD separator to find xxxx of "xxxx(REG)"
1005             CALL #SearchARG         ; -- Lo Hi    search x.xxxx of x.xxxx(REG)
1006             JMP PRMX213
1007     
1008 ; UPDATE_eXtendedWord
1009 ;-----------------------------------;
1010 UPDATE_XW                           ;   BODYDOES Extended_Word -- BODYDOES+2    >IN R--
1011             MOV &DDP,T              ;
1012             ADD #2,&DDP             ;                   make room for extended word
1013             MOV TOS,S               ;                   S = Extended_Word
1014             MOV @PSP+,TOS           ; -- BODYDOES
1015             BIS &RPT_WORD,S         ;                   update Extended_word with RPT_WORD
1016             MOV #0,&RPT_WORD        ;                   clear RPT before next instruction
1017             BIS @TOS+,S             ; -- BODYDOES+2     update Extended_word with [BODYDOES] = A/L bit
1018             MOV S,0(T)              ;                   store extended word
1019             MOV @RSP+,&TOIN         ;                   >IN R--     restore >IN at the start of instruction string
1020             mNEXT                   ;
1021 ;-----------------------------------;
1022
1023 ; --------------------------------------------------------------------------------
1024 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES V extended double operand
1025 ; --------------------------------------------------------------------------------
1026 ; absolute and immediate instructions must be written as $x.xxxx  (DOUBLE numbers)
1027 ; indexed instructions must be written as $.xxxx(REG) (DOUBLE numbers)
1028 ; --------------------------------------------------------------------------------
1029
1030
1031 ; these instructions below are processed in two pass:
1032 ; pass 1: extended word process by TYPE5DOES with [BODYDOES] value
1033 ; pass 2: instruction process by TYPE1DOES with [BODYDOES+2] value
1034 ; all numeric arguments must be written as DOUBLE numbers (including a point) : $x.xxxx
1035
1036 TYPE5DOES                               ; -- BODYDOES
1037             .word   LIT,TOIN,FETCH,TOR  ; R-- >IN                    save >IN for 2th pass
1038             .word   lit,','             ; -- BODYDOES ','            char separator for PRMX1
1039             .word   PRMX1,PRMX2         ; -- BODYDOES Extended_Word
1040             .word   UPDATE_XW           ; -- BODYDOES+2              >IN is restored ready for 2th pass
1041             .word   BRAN,TYPE1DOES      ; -- BODYDOES+2              2th pass: completes instruction with opcode = [BODYDOES+2]
1042
1043             asmword "MOVX"
1044             mDODOES
1045             .word   TYPE5DOES,40h,4000h ; [PFADOES]=TYPE5DOES, [BODYDOES]=A/L bit, [BODYDOES+2]=OPCODE,
1046             asmword "MOVX.A"
1047             mDODOES
1048             .word   TYPE5DOES,0,4040h
1049             asmword "MOVX.B"
1050             mDODOES
1051             .word   TYPE5DOES,40h,4040h
1052             asmword "ADDX"
1053             mDODOES          
1054             .word   TYPE5DOES,40h,5000h
1055             asmword "ADDX.A"
1056             mDODOES          
1057             .word   TYPE5DOES,0,5040h
1058             asmword "ADDX.B"
1059             mDODOES          
1060             .word   TYPE5DOES,40h,5040h
1061             asmword "ADDCX"  
1062             mDODOES          
1063             .word   TYPE5DOES,40h,6000h
1064             asmword "ADDCX.A"
1065             mDODOES          
1066             .word   TYPE5DOES,0,6040h
1067             asmword "ADDCX.B"
1068             mDODOES          
1069             .word   TYPE5DOES,40h,6040h
1070             asmword "SUBCX"  
1071             mDODOES          
1072             .word   TYPE5DOES,40h,7000h
1073             asmword "SUBCX.A"
1074             mDODOES
1075             .word   TYPE5DOES,0,7040h
1076             asmword "SUBCX.B"
1077             mDODOES          
1078             .word   TYPE5DOES,40h,7040h
1079             asmword "SUBX"   
1080             mDODOES          
1081             .word   TYPE5DOES,40h,8000h
1082             asmword "SUBX.A" 
1083             mDODOES          
1084             .word   TYPE5DOES,0,8040h
1085             asmword "SUBX.B" 
1086             mDODOES          
1087             .word   TYPE5DOES,40h,8040h
1088             asmword "CMPX"   
1089             mDODOES          
1090             .word   TYPE5DOES,40h,9000h
1091             asmword "CMPX.A" 
1092             mDODOES          
1093             .word   TYPE5DOES,0,9040h
1094             asmword "CMPX.B" 
1095             mDODOES          
1096             .word   TYPE5DOES,40h,9040h
1097             asmword "DADDX"
1098             mDODOES
1099             .word   TYPE5DOES,40h,0A000h
1100             asmword "DADDX.A"
1101             mDODOES          
1102             .word   TYPE5DOES,0,0A040h
1103             asmword "DADDX.B"
1104             mDODOES          
1105             .word   TYPE5DOES,40h,0A040h
1106             asmword "BITX"   
1107             mDODOES          
1108             .word   TYPE5DOES,40h,0B000h
1109             asmword "BITX.A" 
1110             mDODOES          
1111             .word   TYPE5DOES,0,0B040h
1112             asmword "BITX.B" 
1113             mDODOES          
1114             .word   TYPE5DOES,40h,0B040h
1115             asmword "BICX"   
1116             mDODOES          
1117             .word   TYPE5DOES,40h,0C000h
1118             asmword "BICX.A" 
1119             mDODOES          
1120             .word   TYPE5DOES,0,0C040h
1121             asmword "BICX.B" 
1122             mDODOES          
1123             .word   TYPE5DOES,40h,0C040h
1124             asmword "BISX"
1125             mDODOES
1126             .word   TYPE5DOES,40h,0D000h
1127             asmword "BISX.A" 
1128             mDODOES          
1129             .word   TYPE5DOES,0,0D040h
1130             asmword "BISX.B" 
1131             mDODOES          
1132             .word   TYPE5DOES,40h,0D040h
1133             asmword "XORX"   
1134             mDODOES          
1135             .word   TYPE5DOES,40h,0E000h
1136             asmword "XORX.A" 
1137             mDODOES          
1138             .word   TYPE5DOES,0,0E040h
1139             asmword "XORX.B" 
1140             mDODOES          
1141             .word   TYPE5DOES,40h,0E040h
1142             asmword "ANDX"   
1143             mDODOES          
1144             .word   TYPE5DOES,40h,0F000h
1145             asmword "ANDX.A" 
1146             mDODOES          
1147             .word   TYPE5DOES,0,0F040h
1148             asmword "ANDX.B" 
1149             mDODOES          
1150             .word   TYPE5DOES,40h,0F040h
1151
1152 ; --------------------------------------------------------------------------------
1153 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES VI extended single operand (take count of RPT)
1154 ; --------------------------------------------------------------------------------
1155 ; absolute and immediate instructions must be written as $x.xxxx  (DOUBLE numbers)
1156 ; indexed instructions must be written as $.xxxx(REG) (DOUBLE numbers)
1157 ; --------------------------------------------------------------------------------
1158
1159 ; these instructions below are processed in two pass:
1160 ; pass 1: extended word process by TYPE6DOES with [BODYDOES] value
1161 ; pass 2: instruction process by TYPE2DOES with [BODYDOES+2] value
1162 ; all numeric arguments must be written as DOUBLE numbers (including a point) : $x.xxxx
1163
1164 TYPE6DOES                               ; -- BODYDOES
1165             .word   LIT,TOIN,FETCH,TOR  ;                       save >IN for 2th pass
1166             .word   FBLANK              ; -- BODYDOES ' '
1167             .word   PRMX1               ; -- BODYDOES Extended_Word  
1168             .word   UPDATE_XW           ; -- BODYDOES+2
1169             .word   BRAN,TYPE2DOES      ; -- BODYDOES+2         pass 2: completes instruction with opcode = [BODYDOES+2]
1170
1171             asmword "RRCX"              ; ZC=0; RRCX Rx,Rx may be repeated by prefix RPT #n|Rn
1172             mDODOES
1173             .word   TYPE6DOES,40h,1000h
1174             asmword "RRCX.A"            ; ZC=0; RRCX.A Rx may be repeated by prefix RPT #n|Rn 
1175             mDODOES          
1176             .word   TYPE6DOES,0,1040h
1177             asmword "RRCX.B"            ; ZC=0; RRCX.B Rx may be repeated by prefix RPT #n|Rn
1178             mDODOES          
1179             .word   TYPE6DOES,40h,1040h
1180             asmword "RRUX"              ; ZC=1; RRUX Rx may be repeated by prefix RPT #n|Rn
1181             mDODOES          
1182             .word   TYPE6DOES,140h,1000h
1183             asmword "RRUX.A"            ; ZC=1; RRUX.A Rx may be repeated by prefix RPT #n|Rn 
1184             mDODOES          
1185             .word   TYPE6DOES,100h,1040h
1186             asmword "RRUX.B"            ; ZC=1; RRUX.B Rx may be repeated by prefix RPT #n|Rn 
1187             mDODOES          
1188             .word   TYPE6DOES,140h,1040h
1189             asmword "SWPBX"
1190             mDODOES          
1191             .word   TYPE6DOES,40h,1080h
1192             asmword "SWPBX.A"
1193             mDODOES          
1194             .word   TYPE6DOES,0,1080h
1195             asmword "RRAX"
1196             mDODOES          
1197             .word   TYPE6DOES,40h,1100h
1198             asmword "RRAX.A"
1199             mDODOES          
1200             .word   TYPE6DOES,0,1140h
1201             asmword "RRAX.B"
1202             mDODOES          
1203             .word   TYPE6DOES,40h,1140h
1204             asmword "SXTX"
1205             mDODOES
1206             .word   TYPE6DOES,40h,1180h
1207             asmword "SXTX.A" 
1208             mDODOES          
1209             .word   TYPE6DOES,0,1180h
1210             asmword "PUSHX"  
1211             mDODOES          
1212             .word   TYPE6DOES,40h,1200h
1213             asmword "PUSHX.A"
1214             mDODOES          
1215             .word   TYPE6DOES,0,1240h
1216             asmword "PUSHX.B"
1217             mDODOES          
1218             .word   TYPE6DOES,40h,1240h
1219
1220 ; ----------------------------------------------------------------------
1221 ; DTCforthMSP430FR5xxx ASSEMBLER, RPT instruction before REG|REG,REG eXtended instructions
1222 ; ----------------------------------------------------------------------
1223 ; RPT #1 is coded 0 in repetition count field (count n-1)
1224 ; please note that "RPT Rn" with [Rn]=0 has same effect as "RPT #1"
1225
1226 RPT_WORD    .word 0
1227
1228             asmword "RPT"           ; RPT #n | RPT Rn     repeat n | [Rn]+1 times modulo 16
1229             mdocol
1230             .word FBLANK,SKIP
1231             FORTHtoASM              ; -- addr
1232             MOV @TOS,X              ;           X=char
1233             MOV.B #' ',TOS          ; -- ' '    as separator
1234             CMP.B #'R',X
1235             JNZ RPT1
1236             CALL #SearchREG         ; -- Rn
1237             JZ RPT1                 ;           if not found
1238             BIS #80h,TOS            ; -- $008R  R=Rn
1239             JMP RPT2
1240 RPT1        CALL #SearchARG         ; -- $xxxx
1241             SUB #1,TOS              ; -- n-1
1242             AND #0Fh,TOS            ; -- $000x
1243 RPT2        MOV TOS,&RPT_WORD
1244             MOV @PSP+,TOS
1245             mSEMI