OSDN Git Service

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