OSDN Git Service

v 162, added Conditionnal Compilation and bootloader
[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 : R15,R14,R13,R12,R11,R10, R9, R8, R7, R6, R5, R4 (TI's reg)
37 ; or          : PSP,TOS, IP,  S,  T,  W,  X,  Y, R7, R6, R5, R4 (FastForth reg)
38 ; example : PUSHM IP,Y or PUSHM R13,R8
39
40 ; POPM  order :  R4, R5, R6, R7, R8, R9,R10,R11,R12,R13,R14,R15 (TI's reg)
41 ; or          :  R4, R5, R6, R7,  Y,  X,  W,  T,  S, IP,TOS,PSP (FastForth reg)
42 ; example : POPM Y,IP or POPM R8,R13
43
44 ; ----------------------------------------------------------------------
45 ; DTCforthMSP430FR5xxx ASSEMBLER : STRUCTURE
46 ; ----------------------------------------------------------------------
47
48 ;X  ASSEMBLER       --              ; set ASSEMBLER the first context vocabulary
49     .IFDEF VOCABULARY_SET
50             FORTHWORD "ASSEMBLER"
51     .ENDIF ; VOCABULARY_SET
52 ASSEMBLER       mDODOES             ; leave ASSEMBLER_BODY on the stack and run VOCDOES
53                 .word   VOCDOES
54 ASSEMBLER_BODY  .word   lastasmword ; here is the structure created by VOCABULARY
55     .SWITCH THREADS
56     .CASE   2
57                 .word   lastasmword1
58     .CASE   4
59                 .word   lastasmword1
60                 .word   lastasmword2
61                 .word   lastasmword3
62     .CASE   8
63                 .word   lastasmword1
64                 .word   lastasmword2
65                 .word   lastasmword3
66                 .word   lastasmword4
67                 .word   lastasmword5
68                 .word   lastasmword6
69                 .word   lastasmword7
70     .CASE   16
71                 .word   lastasmword1
72                 .word   lastasmword2
73                 .word   lastasmword3
74                 .word   lastasmword4
75                 .word   lastasmword5
76                 .word   lastasmword6
77                 .word   lastasmword7
78                 .word   lastasmword8
79                 .word   lastasmword9
80                 .word   lastasmword10
81                 .word   lastasmword11
82                 .word   lastasmword12
83                 .word   lastasmword13
84                 .word   lastasmword14
85                 .word   lastasmword15
86     .CASE   32
87                 .word   lastasmword1
88                 .word   lastasmword2
89                 .word   lastasmword3
90                 .word   lastasmword4
91                 .word   lastasmword5
92                 .word   lastasmword6
93                 .word   lastasmword7
94                 .word   lastasmword8
95                 .word   lastasmword9
96                 .word   lastasmword10
97                 .word   lastasmword11
98                 .word   lastasmword12
99                 .word   lastasmword13
100                 .word   lastasmword14
101                 .word   lastasmword15
102                 .word   lastasmword16
103                 .word   lastasmword17
104                 .word   lastasmword18
105                 .word   lastasmword19
106                 .word   lastasmword20
107                 .word   lastasmword21
108                 .word   lastasmword22
109                 .word   lastasmword23
110                 .word   lastasmword24
111                 .word   lastasmword25
112                 .word   lastasmword26
113                 .word   lastasmword27
114                 .word   lastasmword28
115                 .word   lastasmword29
116                 .word   lastasmword30
117                 .word   lastasmword31
118     .ELSECASE
119     .ENDCASE
120                 .word   voclink
121 voclink         .set    $-2
122
123              FORTHWORDIMM "HI2LO"   ; immediate, switch to low level, add ASSEMBLER context, set interpretation state
124             mDOCOL
125 HI2LO       .word   HERE,CELLPLUS,COMMA
126             .word   LEFTBRACKET
127 HI2LONEXT   .word   ALSO,ASSEMBLER
128             .word   EXIT
129
130 ;             FORTHWORDIMM "SEMIC"   ; same as HI2LO, plus restore IP; counterpart of COLON
131 ;            mDOCOL
132 ;            .word   HI2LO
133 ;            .word   LIT,413Dh,COMMA ; compile MOV @RSP+,IP
134 ;            .word   EXIT
135
136            FORTHWORD "CODE"     ; a CODE word must be finished with ENDCODE
137 ASMCODE     CALL #HEADER        ;
138             SUB #4,&DDP         ;
139             mDOCOL
140             .word   SAVE_PSP
141             .word   BRAN,HI2LONEXT
142
143
144             asmword "ENDCODE"   ; restore previous context and test PSP balancing
145 ENDCODE     mDOCOL
146             .word   PREVIOUS,QREVEAL
147             .word   EXIT
148
149             FORTHWORD "ASM"     ; used to define an assembler word which is not executable by FORTH interpreter
150                                 ; i.e. typically an assembler word called by CALL and ended by RET
151                                 ; ASM words are only usable in another ASSEMBLER words
152                                 ; an ASM word must be finished with ENDASM
153             MOV     &CURRENT,&ASM_CURRENT
154             MOV     #ASSEMBLER_BODY,&CURRENT
155             JMP     ASMCODE
156
157             asmword "ENDASM"    ; end of an ASM word
158             MOV     &ASM_CURRENT,&CURRENT
159             JMP     ENDCODE
160
161
162             asmword "COLON"     ; compile DOCOL, remove ASSEMBLER from CONTEXT, switch to compilation state
163             MOV &DDP,W
164
165     .SWITCH DTC
166     .CASE 1
167             MOV #DOCOL1,0(W)    ; compile CALL xDOCOL
168             ADD #2,&DDP
169
170     .CASE 2
171             MOV #DOCOL1,0(W)    ; compile PUSH IP
172 COLON1      MOV #DOCOL2,2(W)    ; compile CALL rEXIT
173             ADD #4,&DDP
174
175     .CASE 3 ; inlined DOCOL
176             MOV #DOCOL1,0(W)    ; compile PUSH IP
177 COLON1      MOV #DOCOL2,2(W)    ; compile MOV PC,IP
178             MOV #DOCOL3,4(W)    ; compile ADD #4,IP
179             MOV #NEXT,6(W)      ; compile MOV @IP+,PC
180             ADD #8,&DDP         ;
181     .ENDCASE ; DTC
182
183 COLON2      MOV #-1,&STATE      ; enter in compile state
184             MOV #PREVIOUS,PC    ; restore previous state of CONTEXT
185
186
187             asmword "LO2HI"     ; same as COLON but without saving IP
188     .SWITCH DTC
189     .CASE 1                     ; compile 2 words
190             MOV &DDP,W
191             MOV #12B0h,0(W)     ; compile CALL #EXIT, 2 words  4+6=10~
192             MOV #EXIT,2(W)
193             ADD #4,&DDP
194             JMP COLON2
195     .ELSECASE                   ; CASE 2 : compile 1 word, CASE 3 : compile 3 words
196             SUB #2,&DDP         ; to skip PUSH IP
197             MOV &DDP,W
198             JMP COLON1
199     .ENDCASE
200
201 ;;Z SKIP      char -- addr               ; skip all occurring character 'char' in input stream
202 ;            FORTHWORD "SKIP"            ; used by assembler to parse input stream
203 SKIP:       MOV     #SOURCE_LEN,Y       ;
204             MOV     @Y+,X               ; -- char       X=length
205             MOV     @Y,W                ; -- char       X=length    W=org
206             ADD     W,X                 ; -- char       X=End       W=org
207             ADD     &TOIN,W             ; -- char       X=End       W=ptr
208 SKIPLOOP:   CMP     W,X                 ; -- char       ptr=End ?
209             JZ      SKIPEND             ; -- char       yes
210             CMP.B   @W+,TOS             ; -- char       does character match?
211             JZ      SKIPLOOP            ; -- char       yes
212 SKIPNEXT:   SUB     #1,W                ; -- char
213 SKIPEND:    MOV     W,TOS               ; -- addr
214             SUB     @Y,W                ; -- addr       W=Ptr-Org=Toin
215             MOV     W,&TOIN             ;
216             mNEXT
217
218 ; ----------------------------------------------------------------------
219 ; DTCforthMSP430FR5xxx ASSEMBLER : search argument "xxxx", IP is free
220 ; ----------------------------------------------------------------------
221
222 ; Search ARG of "#xxxx"<sep>                ; <== PARAM10
223 ; Search ARG of "&xxxx"<sep>                ; <== PARAM111
224 ; Search ARG of "xxxx(REG)"<sep>            ; <== PARAM130
225 ; Search ARG of <sep>"xxxx(REG)"            ; <== PARAM210
226 SearchARG   ASMtoFORTH                      ; -- separator      search word first
227             .word   WORDD,FIND              ; -- c-addr
228 ;            .word   ZEROEQUAL
229 ;            .word   QBRAN,SearchARGW        ; -- c-addr         if found
230             .word   QZBRAN,SearchARGW        ; -- c-addr         if found
231             .word   QNUMBER                 ;
232             .word   QBRAN,NotFound          ; -- c-addr
233             .word   AsmSrchEnd              ; -- value          end if number found
234 SearchARGW  FORTHtoASM                      ; -- xt
235             MOV     @TOS,X
236 QDOVAR      CMP     #DOVAR,X
237             JNZ     QDOCON
238             ADD     #2,TOS                  ; remplace CFA by PFA for VARIABLE words
239             MOV     @RSP+,PC                ; ret
240 QDOCON      CMP     #DOCON,X
241             JNZ     QDODOES
242             MOV     2(TOS),TOS              ; remplace CFA by [PFA] for CONSTANT (and CREATEd) words
243             MOV     @RSP+,PC                ; ret
244 QDODOES     CMP     #DODOES,X
245             JNZ     AsmSrchEnd
246             ADD     #4,TOS                  ; leave BODY for DOES words (but don't execute !)
247 AsmSrchEnd  RET                             ;
248
249 ; ----------------------------------------------------------------------
250 ; DTCforthMSP430FR5xxx ASSEMBLER : search REG
251 ; ----------------------------------------------------------------------
252
253 ; STOre ARGument xxxx of "xxxx(REG)"<sep>   ; <== PARAM130
254 ; STOre ARGument xxxx of <sep>"xxxx(REG)"   ; <== PARAM210
255 StoARGsearchREG
256             MOV &DDP,X
257             ADD #2,&DDP
258             MOV TOS,0(X)                    ; -- xxxx       compile xxxx
259             MOV #')',TOS                    ; -- ")"        prepare separator to search REG of "xxxx(REG)"
260
261 ; search REG of "xxxx(REG)"<sep> separator = ')'  ;
262 ; search REG of <sep>"xxxx(REG)" separator = ')'  ;
263 ; search REG of "@REG"<sep>      separator = <sep>; <== PARAM120
264 ; search REG of "@REG+"<sep>     separator = '+'  ; <== PARAM121
265 ; search REG of "REG"<sep>       separator = <sep>; <== PARAM13
266 ; search REG of <sep>"REG"       separator = ' '  ; <== PARAM21
267
268 SearchREG   PUSH    &TOIN                   ; -- separator  save >IN
269             ADD     #1,&TOIN                ;               skip "R"
270             ASMtoFORTH                      ;               search xx of Rxx
271             .word   WORDD,QNUMBER           ;
272             .word   QBRAN,notREG            ; -- xxxx       if number found
273             FORTHtoASM                      ; -- c-addr     if number not found
274             ADD     #2,RSP                  ;           remove >IN
275             CMP     #16,TOS                 ; -- 000R   register > 15 ?
276             JHS     BOUNDERROR              ;           yes : abort
277             MOV     @RSP+,PC                ; -- 000R   Z=0 ==> found
278
279 notREG      FORTHtoASM                      ; -- c-addr
280             MOV     @RSP+,&TOIN             ; -- c-addr          restore >IN
281             BIS     #Z,SR                   ;           Z=1 ==> not found
282             MOV     @RSP+,PC                ; -- c_addr
283
284 ; ----------------------------------------------------------------------
285 ; DTCforthMSP430FR5xxx ASSEMBLER : INTERPRET FIRST OPERAND
286 ; ----------------------------------------------------------------------
287
288 ; PARAM1     separator --                   ; parse input buffer until separator and compute first operand of opcode
289                                             ; sep is comma or space.
290
291 PARAM1      mDOCOL                          ; -- sep
292             .word   FBLANK,SKIP             ; -- sep c-addr
293             FORTHtoASM                      ; -- sep c-addr
294             MOV     #0,&ASMTYPE             ; -- sep c-addr        reset ASMTYPE
295             MOV     &DDP,&OPCODE            ; -- sep c-addr        HERE --> OPCODE (opcode is preset to its address !)
296             ADD     #2,&DDP                 ; -- sep c-addr        cell allot for opcode
297             MOV     TOS,W                   ; -- sep c-addr        W=c-addr
298             MOV     @PSP+,TOS               ; -- sep               W=c-addr
299             CMP.B   #'#',0(W)               ; -- sep               W=c-addr
300             JNE     PARAM11
301
302 ; "#" found : case of "#xxxx"<sep>
303 PARAM10     ADD     #1,&TOIN                ; -- sep        skip # prefix
304             CALL    #SearchARG              ; -- xxxx       abort if not found
305
306 PARAM100    CMP #0,TOS                      ; -- xxxx       = 0 ?
307             JNE PARAM101
308 ; case of "#0"<sep>
309             MOV #0300h,&ASMTYPE             ; -- 0          example : MOV #0,dst <=> MOV R3,dst
310             JMP PARAMENDOF
311
312 PARAM101    CMP #1,TOS                      ; -- xxxx       = 1 ?
313             JNE PARAM102
314 ; case of "#1"<sep>
315             MOV #0310h,&ASMTYPE             ; -- 1          example : MOV #1,dst <=> MOV 0(R3),dst
316             JMP PARAMENDOF
317
318 PARAM102    CMP #2,TOS                      ; -- xxxx       = 2 ?
319             JNE PARAM104
320 ; case of "#2"<sep>
321             MOV #0320h,&ASMTYPE             ; -- 2          ASMTYPE = 0320h  example : MOV #2, <=> MOV @R3,
322             JMP PARAMENDOF
323
324 PARAM104    CMP #4,TOS                      ; -- xxxx       = 4 ?
325             JNE PARAM108
326 ; case of "#4"<sep>
327             MOV #0220h,&ASMTYPE             ; -- 4          ASMTYPE = 0220h  example : MOV #4, <=> MOV @SR,
328             JMP PARAMENDOF
329
330 PARAM108    CMP #8,TOS                      ; -- xxxx       = 8 ?
331             JNE PARAM10M1
332 ; case of "#8"<sep>
333             MOV #0230h,&ASMTYPE             ; -- 8          ASMTYPE = 0230h  example : MOV #8, <=> MOV @SR+,
334             JMP PARAMENDOF
335
336 PARAM10M1   CMP #-1,TOS                     ; -- xxxx       = -1 ?
337             JNE PARAM1000
338 ; case of "#-1"<sep>
339             MOV #0330h,&ASMTYPE             ; -- -1         ASMTYPE = 0330h  example : XOR #-1 <=> XOR @R3+,
340             JMP PARAMENDOF
341
342 ; case of all others "#xxxx"<sep>           ; -- xxxx
343 PARAM1000   MOV #0030h,&ASMTYPE             ; -- xxxx       add immediate code type : @PC+,
344
345 ; case of "&xxxx"<sep>                      ; <== PARAM110
346 ; case of <sep>"&xxxx"                      ; <== PARAM20
347 StoreArg    MOV &DDP,X                      ; -- xxxx
348             ADD #2,&DDP                     ;               cell allot for arg
349 StoreTOS    MOV TOS,0(X)                    ;               compile arg
350
351 ; endcase of all "&xxxx"                    ;
352 ; endcase of all "#xxxx"                    ; <== PARAM101,102,104,108,10M1
353 ; endcase of all "REG"|"@REG"|"@REG+"       ; <== PARAM124
354 PARAMENDOF  MOV @PSP+,TOS                   ; --
355             MOV @RSP+,IP
356             mNEXT                           ; --
357 ; ------------------------------------------
358
359 PARAM11     CMP.B   #'&',0(W)               ; -- sep
360             JNE     PARAM12
361
362 ; case of "&xxxx"<sep>                      ; -- sep        search for "&xxxx,"
363 PARAM110    MOV     #0210h,&ASMTYPE         ; -- sep        set code type : xxxx(SR) with AS=0b01 ==> x210h (and SR=0 !)
364
365 ; case of "&xxxx"<sep>
366 ; case of <sep>"&xxxx"                      ; <== PARAM20
367 PARAM111    ADD     #1,&TOIN                ; -- sep        skip "&" prefix
368             PUSH    #StoreArg               ;               prepare next ret : compile xxxx then ret
369             JMP     SearchARG               ; -- sep        abort if not found
370 ; ------------------------------------------
371
372 PARAM12     CMP.B   #'@',0(W)               ; -- sep
373             JNE     PARAM13
374
375 ; case of "@REG"<sep>|"@REG+"<sep>
376 PARAM120    MOV     #0020h,&ASMTYPE         ; -- sep        init ASMTYPE with indirect code type : AS=0b10
377             ADD     #1,&TOIN                ; -- sep        skip "@" prefix
378             CALL    #SearchREG              ;               Z = not found
379             JNZ     PARAM123                ; -- value      REG of "@REG," found
380
381 ; case of "@REG+"<sep>                      ; -- c-addr     "@REG"<sep> not found, search REG of "@REG+"
382 PARAM121    ADD     #0010h,&ASMTYPE         ;               change ASMTYPE from @REG to @REG+ type
383             MOV     #'+',TOS                ; -- "+"        as WORD separator to find REG of "@REG+,"
384             CALL    #SearchREG              ; -- value|c-addr   X = flag
385
386 ; case of "REG" of "@REG+"<sep>
387 ; case of "REG" of "xxxx(REG)"<sep>         ; <== PARAM130
388 PARAM122    JZ      REGnotFound             ; -- c-addr
389             CMP     &SOURCE_LEN,&TOIN       ;               test OPCODE II parameter ending by REG+ or (REG) without comma,
390             JZ      PARAM123                ;               i.e. >IN = SOURCE_LEN : don't skip char CR !
391             ADD     #1,&TOIN                ; -- 000R       skip "," ready for the second operand search
392
393 ; case of "REG" of "@REG+"<sep>
394 ; case of "REG" of "xxxx(REG)"<sep>
395 ; case of "REG" of "@REG"<sep>              ; <== PARAM120
396 ; case of "REG" of "REG"<sep>               ; <== PARAM13
397 PARAM123    SWPB    TOS                     ; 000R -- 0R00  swap bytes because it's not a dst REG typeI (not a 2 ops inst.)
398
399 ; case of "REG" of "@REG+"<sep>             ; -- 0R00                   (src REG typeI)
400 ; case of "REG" of "xxxx(REG)"<sep>         ; -- 0R00                   (src REG typeI or dst REG typeII)
401 ; case of "REG" of "@REG"<sep>              ; -- 0R00                   (src REG typeI)
402 ; case of "REG" of "REG"<sep>               ; -- 0R00                   (src REG typeI or dst REG typeII)
403 ; case of "REG" of <sep>"REG"               ; -- 000R   <== PARAM21     (dst REG typeI)
404 ; case of "REG" of <sep>"xxxx(REG)"         ; -- 000R   <== PARAM210    (dst REG typeI)
405 PARAM124    ADD     TOS,&ASMTYPE            ; -- 0R00|000R
406             JMP     PARAMENDOF
407 ; ------------------------------------------
408
409 ; case of "REG"<sep>|"xxxx(REG)"<sep>       ;               first, searg REG of "REG,"
410 PARAM13     CALL    #SearchREG              ; -- sep        save >IN for second parsing (case of "xxxx(REG),")
411             JNZ     PARAM123                ; -- 000R       REG of "REG," found, ASMTYPE=0
412
413 ; case of "xxxx(REG)"<sep>                  ; -- c-addr     "REG," not found
414 PARAM130    ADD     #0010h,&ASMTYPE         ;               AS=0b01 for indexing address
415             MOV     #'(',TOS                ; -- "("        as WORD separator to find xxxx of "xxxx(REG),"
416             CALL    #SearchARG              ; -- xxxx       aborted if not found
417             PUSH    #PARAM122               ;               prepare next ret : REG found or not found
418             JMP     StoARGsearchREG         ;               compile xxxx and search REG of "(REG)"
419
420 ; ----------------------------------------------------------------------
421 ; DTCforthMSP430FR5xxx ASSEMBLER : INTERPRET 2th OPERAND
422 ; ----------------------------------------------------------------------
423
424 ; PARAM2     --                             ; parse input buffer until BL and compute this 2th operand
425
426 PARAM2      mDOCOL                          ;
427             .word   FBLANK,SKIP             ;               skip space(s) between "arg1," and "arg2" if any
428             FORTHtoASM                      ; -- c-addr     search for '&' of "&xxxx
429             CMP.B   #'&',0(TOS)             ;
430             MOV     #20h,TOS                ; -- " "        as WORD separator to find xxxx of ",&xxxx"
431             JNE     PARAM21                 ;               '&' not found
432
433 ; case of <sep>"&xxxx"                      ;
434 PARAM20     ADD     #0082h,&ASMTYPE         ;               change ASMTYPE : AD=1, dst = R2
435             JMP     PARAM111                ; -- " "
436 ; ------------------------------------------
437
438 ; case of <sep>"REG"|<sep>"xxxx(REG)        ; -- " "        first, search REG of ",REG"
439 PARAM21     CALL    #SearchREG              ;
440             JNZ     PARAM124                ; -- 000R       REG of ",REG" found
441
442 ; case of <sep>"xxxx(REG)                   ; -- c-addr     REG not found
443 PARAM210    ADD     #0080h,&ASMTYPE         ;               set AD=1
444             MOV     #'(',TOS                ; -- "("        as WORD separator to find xxxx of ",xxxx(REG)"
445             CALL    #SearchARG              ; -- xxxx       aborted if not found
446             CALL    #StoARGsearchREG        ;               compile argument xxxx and search REG of "(REG)"
447             JNZ     PARAM124                ; -- 000R       REG of "(REG) found
448 REGnotFound MOV     #NotFound,IP            ; -- c-addr     abort
449             mNEXT
450
451
452 ; ----------------------------------------------------------------------
453 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODES TYPE 0 : zero operand     f:-)
454 ; ----------------------------------------------------------------------
455             asmword "RETI"
456             mDOCOL
457             .word   lit,1300h,COMMA,EXIT
458
459 ; ----------------------------------------------------------------------
460 ; DTCforthMSP430FR5xxx ASSEMBLER: OPCODES TYPE I : double operand
461 ; ----------------------------------------------------------------------
462 ;                                               OPCODE(FEDC)
463 ; OPCODE(code) for TYPE I                          = 0bxxxx             opcode I
464 ;                                                   OPCODE(BA98)
465 ;                                                      = 0bxxxx         src register
466 ;                                                       OPCODE(7)       AD (dst addr type)
467 ;                                                          = 0b0        register
468 ;                                                          = 0b1        x(Rn),&adr
469 ;                                                        OPCODE(6)      size
470 ; OPCODE(B)  for TYPE I or TYPE II                          = 0b0       word
471 ;                                                           = 0b1       byte
472 ;                                                         OPCODE(54)    AS (src addr type)
473 ; OPCODE(AS) for TYPE I or OPCODE(AD) for TYPE II            = 0b00     register
474 ;                                                            = 0b01     x(Rn),&adr
475 ;                                                            = 0b10     @Rn
476 ;                                                            = 0b11     @Rn+
477 ;                                                           OPCODE(3210)
478 ; OPCODE(dst) for TYPE I or TYPE II                            = 0bxxxx dst register
479 ; ----------------------------------------------------------------------
480
481 ; TYPE1DOES     -- PFADOES      search and compute PARAM1 & PARAM2 as src and dst operands then compile instruction
482 TYPE1DOES                                   ; -- PFADOES
483             .word   lit,','                 ; -- PFADOES ","        char separator for PARAM1
484             .word   PARAM1                  ; -- PFADOES
485             .word   PARAM2                  ; -- PFADOES            char separator (BL) included in PARAM2
486             FORTHtoASM                      ; -- PFADOES
487 MAKEOPCODE  MOV     @TOS,TOS                ; -- opcode             part of instruction
488             BIS     &ASMTYPE,TOS            ; -- opcode             opcode is complete
489             MOV     &OPCODE,X               ; -- opcode             X= addr to compile opcode
490             JMP     StoreTOS                ;                       then EXIT
491
492             asmword "MOV"
493             mDODOES
494             .word   TYPE1DOES,4000h
495
496             asmword "MOV.B"
497             mDODOES
498             .word   TYPE1DOES,4040h
499
500             asmword "ADD"
501             mDODOES
502             .word   TYPE1DOES,5000h
503
504             asmword "ADD.B"
505             mDODOES
506             .word   TYPE1DOES,5040h
507
508             asmword "ADDC"
509             mDODOES
510             .word   TYPE1DOES,6000h
511
512             asmword "ADDC.B"
513             mDODOES
514             .word   TYPE1DOES,6040h
515
516             asmword "SUBC"
517             mDODOES
518             .word   TYPE1DOES,7000h
519
520             asmword "SUBC.B"
521             mDODOES
522             .word   TYPE1DOES,7040h
523
524             asmword "SUB"
525             mDODOES
526             .word   TYPE1DOES,8000h
527
528             asmword "SUB.B"
529             mDODOES
530             .word   TYPE1DOES,8040h
531
532             asmword "CMP"
533             mDODOES
534             .word   TYPE1DOES,9000h
535
536             asmword "CMP.B"
537             mDODOES
538             .word   TYPE1DOES,9040h
539
540             asmword "DADD"
541             mDODOES
542             .word   TYPE1DOES,0A000h
543
544             asmword "DADD.B"
545             mDODOES
546             .word   TYPE1DOES,0A040h
547
548             asmword "BIT"
549             mDODOES
550             .word   TYPE1DOES,0B000h
551
552             asmword "BIT.B"
553             mDODOES
554             .word   TYPE1DOES,0B040h
555
556             asmword "BIC"
557             mDODOES
558             .word   TYPE1DOES,0C000h
559
560             asmword "BIC.B"
561             mDODOES
562             .word   TYPE1DOES,0C040h
563
564             asmword "BIS"
565             mDODOES
566             .word   TYPE1DOES,0D000h
567
568             asmword "BIS.B"
569             mDODOES
570             .word   TYPE1DOES,0D040h
571
572             asmword "XOR"
573             mDODOES
574             .word   TYPE1DOES,0E000h
575
576             asmword "XOR.B"
577             mDODOES
578             .word   TYPE1DOES,0E040h
579
580             asmword "AND"
581             mDODOES
582             .word   TYPE1DOES,0F000h
583
584             asmword "AND.B"
585             mDODOES
586             .word   TYPE1DOES,0F040h
587
588 ; ----------------------------------------------------------------------
589 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES TYPE II : single operand
590 ; ----------------------------------------------------------------------
591 ;                                               OPCODE(FEDCBA987)       opcodeII
592 ; OPCODE(code) for TYPE II                         = 0bxxxxxxxxx
593 ;                                                        OPCODE(6)      size
594 ; OPCODE(B)  for TYPE I or TYPE II                          = 0b0       word
595 ;                                                           = 0b1       byte
596 ;                                                         OPCODE(54)    (dst addr type)
597 ; OPCODE(AS) for TYPE I or OPCODE(AD) for TYPE II            = 0b00     register
598 ;                                                            = 0b01     x(Rn),&adr
599 ;                                                            = 0b10     @Rn
600 ;                                                            = 0b11     @Rn+
601 ;                                                           OPCODE(3210)
602 ; OPCODE(dst) for TYPE I or TYPE II                            = 0bxxxx dst register
603 ; ----------------------------------------------------------------------
604
605 ; TYPE2DOES     -- PFADOES          search and compute PARAM1 as dst operand then compile instruction
606 TYPE2DOES                                   ; -- PFADOES
607             .word   FBLANK                  ;               char separator for PARAM1
608             .word   PARAM1
609             FORTHtoASM                      ; -- PFADOES
610             MOV     &ASMTYPE,W              ;
611             AND     #0070h,&ASMTYPE         ;             keep B/W & AS infos in ASMTYPE
612             SWPB    W                       ;             (REG org --> REG dst)
613             AND     #000Fh,W                ;             keep REG
614 BIS_ASMTYPE BIS     W,&ASMTYPE              ; -- PFADOES  add it in ASMTYPE
615             JMP     MAKEOPCODE              ; -- then end
616
617             asmword "RRC"          ; Rotate Right through Carry ( word)
618             mDODOES
619             .word   TYPE2DOES,1000h
620
621             asmword "RRC.B"         ; Rotate Right through Carry ( byte)
622             mDODOES
623             .word   TYPE2DOES,1040h
624
625             asmword "SWPB"          ; Swap bytes
626             mDODOES
627             .word   TYPE2DOES,1080h
628
629             asmword "RRA"
630             mDODOES
631             .word   TYPE2DOES,1100h
632
633             asmword "RRA.B"
634             mDODOES
635             .word   TYPE2DOES,1140h
636
637             asmword "SXT"
638             mDODOES
639             .word   TYPE2DOES,1180h
640
641             asmword "PUSH"
642             mDODOES
643             .word   TYPE2DOES,1200h
644
645             asmword "PUSH.B"
646             mDODOES
647             .word   TYPE2DOES,1240h
648
649             asmword "CALL"
650             mDODOES
651             .word   TYPE2DOES,1280h
652
653 ; ----------------------------------------------------------------------
654 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES TYPE III : PUSHM POPM
655 ; ----------------------------------------------------------------------
656 ; syntax :  PUSHM R13,R9    ; R-- R13 R12 R11 R10 R9    (first >= last)
657 ;           POPM  R9,R13    ; R--                       (last >= first)
658 ; this syntax is more explicit than TI's one and can reuse typeI template
659
660 ; PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8, R7, R6, R5, R4 (TI's reg)
661 ; or          : PSP,TOS, IP,  S,  T,  W,  X,  Y, R7, R6, R5, R4 (FastForth reg)
662 ; example : PUSHM IP,Y or PUSHM R13,R8
663
664 ; POPM  order :  R4, R5, R6, R7, R8, R9,R10,R11,R12,R13,R14,R15 (TI's reg)
665 ; or          :  R4, R5, R6, R7,  Y,  X,  W,  T,  S, IP,TOS,PSP (FastForth reg)
666 ; example : POPM Y,IP or POPM R8,R13
667
668 ; TYPE3DOES     -- PFADOES       parse input stream to search :"   REG, REG " as operands of PUSHM|POPM then compile instruction
669 TYPE3DOES                                   ; -- PFADOES
670             .word   lit,','                 ; -- PFADOES ","        char separator for PARAM1
671             .word   PARAM1                  ; -- PFADOES            ASMTYPE contains : 0x0S00    S=REGsrc
672             .word   PARAM2                  ; -- PFADOES            ASMTYPE contains : 0x0S0D    D=REGdst
673             FORTHtoASM                      ; -- PFADOES
674             MOV.B   &ASMTYPE,X              ;                       X=REGdst
675             MOV.B   &ASMTYPE+1,W            ;                       W=REGsrc
676             MOV     W,&ASMTYPE              ;                       ASMTYPE = 0x000S
677             CMP     #1500h,0(TOS)           ; -- PFADOES            PUSHM ?
678             JNZ     POPMCASEOF
679 PUSHMCASEOF SUB     X,W                     ; -- PFADOES            PUSHM : REGsrc - REGdst = n-1
680             JMP     TYPE3QERR
681 POPMCASEOF  SUB     W,X                     ; -- PFADOES            POPM  : REGdst - REGsrc = n-1
682             MOV     X,W
683 TYPE3QERR   CMP     #16,W
684             JHS     BOUNDERRORW             ; -- PFADOES            (u>=)
685             .word   0E5Ah                   ;                       RLAM #4,R10 --> RLAM #4,W
686             JMP     BIS_ASMTYPE             ; --            then end
687
688 BOUNDERRWM1 ADD     #1,W                    ; <== RRAM|RRUM|RRCM|RLAM error
689 BOUNDERRORW MOV     W,TOS                   ; <== PUSHM|POPM|ASM_branch error
690 BOUNDERROR                                  ; <== REG number error
691             mDOCOL                          ; -- n      n = value out of bounds
692             .word   DOT,XSQUOTE
693             .byte   13,"out of bounds"
694             .word   QABORTYES
695
696             asmword "PUSHM"
697 ASM_PUSHM   mDODOES
698             .word   TYPE3DOES,01500h
699
700             asmword "POPM"
701 ASM_POPM    mDODOES
702             .word   TYPE3DOES,01700h
703
704 ; ----------------------------------------------------------------------
705 ; DTCforthMSP430FR5xxx ASSEMBLER, OPCODES TYPE IV : RLAM|RRAM|RRUM|RRCM
706 ; ----------------------------------------------------------------------
707
708 ; TYPE4DOES      -- PFADOES        parse input stream to search : "   #N, REG " as operands of RLAM|RRAM|RRUM|RRCM
709 TYPE4DOES                                   ; -- PFADOES
710             .word   FBLANK,SKIP             ;                       skip spaces if any
711             FORTHtoASM                      ; -- PFADOES c-addr
712             MOV     #0,&ASMTYPE             ;                       init ASMTYPE=0
713             MOV     &DDP,&OPCODE            ;                       init OPCODE=DP
714             ADD     #2,&DDP                 ;                       make room for opcode
715             ADD     #1,&TOIN                ;                       skip "#"
716             MOV     #',',TOS                ; -- PFADOES ","
717             ASMtoFORTH
718             .word   WORDD,QNUMBER
719             .word   QBRAN,NotFound
720             .word   PARAM2                  ; -- PFADOES 0x000N     ASMTYPE = 0x000R
721             FORTHtoASM
722             MOV     TOS,W                   ; -- PFADOES 0x000N     W = 0x000N
723             MOV     @PSP+,TOS               ; -- PFADOES
724             SUB     #1,W                    ;                       W = N floored to 0
725             CMP     #4,W                    ;
726             JHS     BOUNDERRWM1             ;                       JC=JHS    (U>=)
727             SWPB    W                       ; -- PFADOES            W = N << 8
728             .word   065Ah                   ; RLAM #2,R10           W = N << 10
729             JMP     BIS_ASMTYPE             ; --
730
731             asmword "RRCM"
732             mDODOES
733             .word   TYPE4DOES,0050h
734
735             asmword "RRAM"
736             mDODOES
737             .word   TYPE4DOES,0150h
738
739             asmword "RLAM"
740             mDODOES
741             .word   TYPE4DOES,0250h
742
743             asmword "RRUM"
744             mDODOES
745             .word   TYPE4DOES,0350h
746
747 ; ----------------------------------------------------------------------
748 ; DTCforthMSP430FR5xxx ASSEMBLER, CONDITIONAL BRANCHS
749 ; ----------------------------------------------------------------------
750 ;                       ASSEMBLER       FORTH         OPCODE(FEDC)
751 ; OPCODE(code) for TYPE JNE,JNZ         0<>, <>     = 0x20xx + (offset AND 3FF) ; branch if Z = 0
752 ; OPCODE(code) for TYPE JEQ,JZ          0=, =       = 0x24xx + (offset AND 3FF) ; branch if Z = 1
753 ; OPCODE(code) for TYPE JNC,JLO         U<          = 0x28xx + (offset AND 3FF) ; branch if C = 0
754 ; OPCODE(code) for TYPE JC,JHS          U>=         = 0x2Cxx + (offset AND 3FF) ; branch if C = 1
755 ; OPCODE(code) for TYPE JN              0<          = 0x30xx + (offset AND 3FF) ; branch if N = 1
756 ; OPCODE(code) for TYPE JGE             >=          = 0x34xx + (offset AND 3FF) ; branch if (N xor V) = 0
757 ; OPCODE(code) for TYPE JL              <           = 0x38xx + (offset AND 3FF) ; branch if (N xor V) = 1
758 ; OPCODE(code) for TYPE JMP                         = 0x3Cxx + (offset AND 3FF)
759
760 CODE_JMP    mDOCON                      ; branch always
761             .word   3C00h
762
763             asmword "S>="               ; if >= assertion
764             mDOCON
765             .word   3800h
766
767             asmword "S<"                ; if < assertion
768             mDOCON
769             .word   3400h
770
771             asmword "0>="               ; if 0>= assertion  ; use only with IF UNTIL WHILE !
772             mDOCON
773             .word   3000h
774
775             asmword "0<"                ; jump if 0<        ; use only with ?JMP ?GOTO !
776             mDOCON
777             .word   3000h
778
779             asmword "U<"                ; if U< assertion
780             mDOCON
781             .word   2C00h
782
783             asmword "U>="               ; if U>= assertion
784             mDOCON
785             .word   2800h
786
787             asmword "0<>"               ; if <>0 assertion
788             mDOCON
789             .word   2400h
790
791             asmword "0="                ; if =0 assertion
792             mDOCON
793             .word   2000h
794
795 ;ASM IF      OPCODE -- @OPCODE1
796             asmword "IF"
797 ASM_IF      MOV     &DDP,W
798             MOV     TOS,0(W)
799             ADD     #2,&DDP
800             MOV     W,TOS
801             mNEXT
802
803 ;ASM THEN     @OPCODE --        resolve forward branch
804             asmword "THEN"
805 ASM_THEN    MOV     &DDP,W              ; -- @OPCODE   W=dst
806             MOV     TOS,Y               ;               Y=@OPCODE
807 ASM_THEN1   MOV     @PSP+,TOS           ; --
808             MOV     Y,X                 ;
809             ADD     #2,X                ; --        Y=@OPCODE   W=dst   X=src+2
810             SUB     X,W                 ; --        Y=@OPCODE   W=dst-src+2=displacement*2 (bytes)
811             RRA     W                   ; --        Y=@OPCODE   W=displacement (words)
812             CMP     #512,W
813             JC      BOUNDERRORW         ; (JHS) unsigned branch if u> 511
814             BIS     W,0(Y)              ; --       [@OPCODE]=OPCODE completed
815             mNEXT
816
817 ;C ELSE     @OPCODE1 -- @OPCODE2    branch for IF..ELSE
818             asmword "ELSE"
819 ASM_ELSE    MOV     &DDP,W              ; --        W=HERE
820             MOV     #3C00h,0(W)         ;           compile unconditionnal branch
821             ADD     #2,&DDP             ; --        DP+2
822             SUB     #2,PSP
823             MOV     W,0(PSP)            ; -- dst
824             JMP     ASM_THEN
825
826 ;C BEGIN    -- @BEGIN                   same as FORTH counterpart
827
828 ;C UNTIL    @BEGIN OPCODE --   resolve conditional backward branch
829             asmword "UNTIL"
830 ASM_UNTIL   MOV     @PSP+,W             ;  -- OPCODE           W=dst
831 ASM_UNTIL1  MOV     TOS,Y
832             MOV     @PSP+,TOS           ;  --
833             MOV     &DDP,X              ;  --       Y=OPCODE   X=HERE  W=dst
834             SUB     #2,W                ;  --       Y=OPCODE   X=HERE  W=dst-2
835             SUB     X,W                 ;  --       Y=OPCODE   X=src   W=src-dst-2=displacement (bytes)
836             RRA     W                   ;  --       Y=OPCODE   X=HERE  W=displacement (words)
837             CMP     #-512,W
838             JL      BOUNDERRORW         ; signed branch if < -512
839             AND     #3FFh,W             ;  --       Y=OPCODE   X=HERE  W=troncated negative displacement (words)
840             BIS     W,Y                 ;  --       Y=OPCODE (completed)
841             MOV     Y,0(X)
842             ADD     #2,&DDP
843             mNEXT
844
845 ;X AGAIN    @BEGIN --      uncond'l backward branch
846 ;   unconditional backward branch
847             asmword "AGAIN"
848 ASM_AGAIN   mDOCOL                      ; -- @BEGIN
849             .word   CODE_JMP            ; -- @BEGIN opcode
850             .word   ASM_UNTIL           ; --
851             .word   EXIT                ; --
852
853 ;C WHILE    @BEGIN OPCODE -- @WHILE @BEGIN
854             asmword "WHILE"
855 ASM_WHILE   mDOCOL                      ; -- @BEGIN OPCODE
856             .word   ASM_IF              ; -- @BEGIN @WHILE
857             .word   SWAP                ; -- @WHILE @BEGIN
858             .word   EXIT
859
860 ;C REPEAT   @WHILE @BEGIN --     resolve WHILE loop
861             asmword "REPEAT"
862 ASM_REPEAT  mDOCOL                      ; -- @WHILE @BEGIN
863             .word   CODE_JMP            ; -- @WHILE @BEGIN opcode
864             .word   ASM_UNTIL           ; -- @WHILE
865             .word   ASM_THEN            ; --
866             .word   EXIT
867
868 ; ----------------------------------------------------------------
869 ; DTCforthMSP430FR5xxx ASSEMBLER : branch to a previous definition
870 ; ----------------------------------------------------------------
871
872 ;ASM    JMP <word>          ;        --       unconditionnal branch to a previous definition
873             asmword "JMP"
874 JUMP        mDOCOL
875             .word   TICK,CODE_JMP
876             .word   ASM_UNTIL,EXIT
877
878
879 ; invert FORTH conditionnal branch      FORTH_JMP_OPCODE -- LABEL_JMP_OPCODE
880 INVJMP      BIT #1000h,TOS  ; 3xxxh case ?
881             JNZ INVJMP3xxxh ; yes
882 INVJMP2xxxh XOR #0400h,TOS  ; no: case of JNE/JNZ JEQ/JZ JNC/JLO JC/JHS
883             mNEXT
884 INVJMP3xxxh CMP #3400h,TOS
885             JLO INVJMPEND   ; case of 3000h, do nothing
886             JZ INVJMP3400h
887 INVJMP3800h MOV #3400h,TOS  ; not jump if >= --> jump if <
888             mNEXT
889 INVJMP3400h MOV #3800h,TOS  ; not jump if <  --> jump if >=
890 INVJMPEND   mNEXT
891
892
893 ;ASM    <cond> ?JMP <word>  ;  OPCODE --       conditionnal branch to a previous definition
894             asmword "?JMP"
895             mDOCOL
896             .word   INVJMP,TICK,SWAP
897             .word   ASM_UNTIL,EXIT
898
899 ; ------------------------------------------------------------------------------------------
900 ; DTCforthMSP430FR5xxx ASSEMBLER : branch up to 3 backward labels and up to 3 forward labels
901 ; ------------------------------------------------------------------------------------------
902 ; used for non canonical branchs, as BASIC language: "goto line x"
903 ; when a branch to label is resolved, it's ready for new use
904
905 BACKWARDDOES        ;
906     FORTHtoASM
907     MOV @RSP+,IP
908     MOV TOS,Y
909     MOV @PSP+,TOS
910     MOV @Y,W        ;               W = [PFA]
911     CMP #0,W        ;               W = 0 ?
912     JNZ BACKWUSE
913 BACKWSET            ; --
914     MOV &DDP,0(Y)   ;               [PFA] = @LABEL
915     mNEXT
916 BACKWUSE            ; -- OPCODE
917     MOV #0,0(Y)     ;               reset [PFA] for next use
918     JMP ASM_UNTIL1  ;               resolve backward branch
919
920 ; backward label 1
921             asmword "BW1"
922             mdodoes
923             .word BACKWARDDOES
924 CLRBW1      .word 0
925
926 ; backward label 2
927             asmword "BW2"
928             mdodoes
929             .word BACKWARDDOES
930 CLRBW2      .word 0
931
932 ; backward label 3
933             asmword "BW3"
934             mdodoes
935             .word BACKWARDDOES
936 CLRBW3      .word 0
937
938 FORWARDDOES
939     FORTHtoASM
940     MOV @RSP+,IP
941     MOV &DDP,W      ;
942     MOV @TOS,Y      ;           Y=@OPCODE
943     CMP #0,Y
944     JNZ FORWUSE
945 FORWSET             ; OPCODE PFA --
946     MOV @PSP+,0(W)  ; -- PFA        compile incomplete opcode
947     ADD #2,&DDP     ;
948     MOV W,0(TOS)    ;               store @OPCODE into PFA
949     MOV @PSP+,TOS   ;   --
950     mNEXT
951 FORWUSE             ; PFA -- @OPCODE
952     MOV #0,0(TOS)   ;               reset PFA for next use
953     JMP ASM_THEN1   ;               resolve forward branch
954
955
956 ; forward label 1
957             asmword "FW1"
958             mdodoes
959             .word FORWARDDOES
960 CLRFW1      .word 0
961
962 ; forward label 2
963             asmword "FW2"
964             mdodoes
965             .word FORWARDDOES
966 CLRFW2      .word 0
967
968 ; forward label 3
969             asmword "FW3"
970             mdodoes
971             .word FORWARDDOES
972 CLRFW3      .word 0
973
974
975 ;ASM    GOTO <label>                   --       unconditionnal branch to label
976             asmword "GOTO"
977             mDOCOL
978             .word   CODE_JMP,TICK   ;  -- OPCODE PFA<label>
979             .word   EXECUTE,EXIT
980
981 ;ASM    <cond> ?GOTO <label>    OPCODE --       conditionnal branch to label
982             asmword "?GOTO"
983             mDOCOL
984             .word   INVJMP,TICK     ;  -- OPCODE PFA<label>
985             .word   EXECUTE,EXIT
986
987
988