\ Syntax Layer



\ ****** Make a smarter Notation for register adressing modes
\
\   MSP430x2xx Family User' s Guide, Page 50, 3.3 Addressing Modes
\   The syntax description is given in Table 3-3, "Source/Destination Operand Addressing Modes"
\
\   The modes are:
\     Register mode           Rn      Register contents are operand
\     Indexed mode            X(Rn)   (Rn + X) points to the operand. X is stored in the next word.
\     Symbolic mode           ADDR    (PC + X) points to the operand. X is stored in the next word.
\                                     Indexed mode X(PC) is used.
\     Absolute mode           &ADDR   The word following the instruction contains the absolute address.
\                                     Indexed mode X(SR) is used.
\     Indirect register mode  @Rn     Rn is used as a pointer to the operand.
\     Indirect autoincrement  @Rn+    Rn is used as a pointer to the operand.
\                                     Rn is incremented afterwards by 1 for .B instructions and by 2 for .W instructions.
\     Immediate mode          #N      The word following the instruction contains the immediate constant N.
\                                     Indirect autoincrement mode @PC+ is used.
\
\
\   Now lets turn this into a notation.
\
\     ASSEMBLER  FORTH
\ 1.  Rn         rn         ( rn -- )   \ register# is on stack, mode# is set to 1
\ 2.  x(Rn)      x (rn)     ( x rn -- ) \ x and register# are on stack, mode# is set to 2
\ 3.  ADDR       a          ( a -- )    \ adr is on stack; default mode# = 3
\ 4.  &ADDR      a &a       ( a -- )    \ adr is on stack, mode# is set to 4
\ 5.  @Rn        @rn        ( rn -- )   \ register# is on stack, mode# is set to 5
\ 6.  @Rn+       @rn+       ( rn -- )   \ register# is on stack, mode# is set to 6
\ 7.  #n         n #n       ( n -- )    \ constant is on stack, mode# is set to 7
\ All seven are aplicable to source, 1..4 to destination only.



\ *** Here we go:  Definig 7 modes.


\ shift in modes: upper nible=src, lower nibble= dest
: accumulate-mode  ( n -- ) mode# 4 lshift +  to mode# ;
: ds-swap \ swap stack and accumulated mode too.
  swap  ( dRn sRn -- sRn dRn )
  mode# $F and   mode# 4 rshift $F and  ( -- dm sm )
  swap reset-mode# accumulate-mode accumulate-mode ;


\ Seven addressing modes.
: m1 ( -- )       1 accumulate-mode ; \ Rn
: m2 ( -- )       2 accumulate-mode ; \ x(Rn)
: m3 ( -- )       3 accumulate-mode ; \ ADDR
: m4 ( -- )       4 accumulate-mode ; \ &ADDR
: m5 ( -- )       5 accumulate-mode ; \ @Rn
: m6 ( -- )       6 accumulate-mode ; \ @Rn+
: m7 ( -- )       7 accumulate-mode ; \ #N
\ All seven are aplicable to source, 1..4 to destination only.

: m8 ( -- )       8 accumulate-mode ; \ handle constant generator



\ *** Now we do register names, knowing their mode.

\ The CPU incorporates sixteen 16-bit registers R0 ... R15
\ R0, R1, R2, and R3 have dedicated functions.
\ R4 to R15 are general pupose registers.
\ Rn ( -- n ) ( set mode value too)



\ 1.   Register mode           Rn       Make a name for each register.
\ Function: Put register# on stack, set mode# to 1.

: R0 0 m1 ;     ' R0 alias PC  \ program counter
: R1 1 m1 ;     ' R1 alias SP  \ stack pointer
: R2 2 m1 ;     ' R2 alias SR  \ status register
                ' R2 alias CG1 \ Constant Generator Registers CG1
: R3 3 m1 ;     ' R3 alias CG2 \ Constant Generator Registers CG2

: R4 4 m1 ;
: R5 5 m1 ;
: R6 6 m1 ;
: R7 7 m1 ;
: R8 8 m1 ;
: R9 9 m1 ;
: R10 10 m1 ;
: R11 11 m1 ;
: R12 12 m1 ;
: R13 13 m1 ;
: R14 14 m1 ;
: R15 15 m1 ;

  \ alias for MSP430
' R1 alias RSP \ retur stack pointer
' R4 alias PSP \ parameter stack pointer
' R5 alias IP  \ instruction pointer
' R6 alias W   \ working register
' R7 alias TOS \ top of (parameter) stack



\ 2.   Indexed mode        x (Rn)     Make a name for each register.
\ Function: x is on stack, put register# on stack, set mode# to 2.

: (R0) 0 m2 ;     ' (R0) alias (PC)  \ program counter
: (R1) 1 m2 ;     ' (R1) alias (SP)  \ stack ponter
: (R2) 2 m2 ;     ' (R2) alias (SR)  \ status register
: (R3) 3 m2 ;
: (R4) 4 m2 ;
: (R5) 5 m2 ;
: (R6) 6 m2 ;
: (R7) 7 m2 ;
: (R8) 8 m2 ;
: (R9) 9 m2 ;
: (R10) 10 m2 ;
: (R11) 11 m2 ;
: (R12) 12 m2 ;
: (R13) 13 m2 ;
: (R14) 14 m2 ;
: (R15) 15 m2 ;

  \ alias for MSP430
' (R1) alias (RSP) \ retur stack pointer
' (R4) alias (PSP) \ parameter stack pointer
' (R5) alias (IP)  \ instruction pointer
' (R6) alias (W)   \ working register
' (R7) alias (TOS) \ top of (parameter) stack



\ 3.   Symbolic mode            a         This mode is default, no modifier.
\ Function: Address a is on stack, mode# is 3.



\ 4.   Absolute mode            a &a      Make a mode modifier.
\ Function: Address a is on stack and stays unchanged. &a sets mode# to 4.
  ' m4 alias &A ( addr -- addr )



\ 5.   Indirect register mode   @rn       Make a name for each register.
\ Function: Put register# on stack, set mode# to 5.

: @R0 0 m5 ;     ' @R0 alias @PC  \ program counter
: @R1 1 m5 ;     ' @R1 alias @SP  \ stack ponter
: @R2 2 m5 ;     ' @R2 alias @SR  \ status register
: @R3 3 m5 ;
: @R4 4 m5 ;
: @R5 5 m5 ;
: @R6 6 m5 ;
: @R7 7 m5 ;
: @R8 8 m5 ;
: @R9 9 m5 ;
: @R10 10 m5 ;
: @R11 11 m5 ;
: @R12 12 m5 ;
: @R13 13 m5 ;
: @R14 14 m5 ;
: @R15 15 m5 ;

  \ alias for MSP430
' @R1 alias @RSP \ retur stack pointer
' @R4 alias @PSP \ parameter stack pointer
' @R5 alias @IP  \ instruction pointer
' @R6 alias @W   \ working register
' @R7 alias @TOS \ top of (parameter) stack



\ 6.   Indirect autoincrement  @rn+       Make a name for each register.
\ Function: Put register# on stack, set mode# to 6.

: @R0+ 0 m6 ;     ' @R0+ alias @PC+  \ program counter
: @R1+ 1 m6 ;     ' @R1+ alias @SP+  \ stack ponter
: @R2+ 2 m6 ;     ' @R2+ alias @SR+  \ status register
: @R3+ 3 m6 ;
: @R4+ 4 m6 ;
: @R5+ 5 m6 ;
: @R6+ 6 m6 ;
: @R7+ 7 m6 ;
: @R8+ 8 m6 ;
: @R9+ 9 m6 ;
: @R10+ 10 m6 ;
: @R11+ 11 m6 ;
: @R12+ 12 m6 ;
: @R13+ 13 m6 ;
: @R14+ 14 m6 ;
: @R15+ 15 m6 ;

  \ alias for MSP430
' @R1+ alias @RSP+ \ retur stack pointer
' @R4+ alias @PSP+ \ parameter stack pointer
' @R5+ alias @IP+  \ instruction pointer
' @R6+ alias @W+   \ working register
' @R7+ alias @TOS+ \ top of (parameter) stack



\ 7.   Immediate mode          n n#    Make mode modifier.
\ Function: Constant n is on stack, mode# is set to 7.

  ' m7 alias #N ( n -- n )



\ 8.     Lets make constant words to use constant gererators CG1 or CG2.
\ Function: Executin token on stack, set register# and As bits in mode.

: 0#     ( -- xt ) ['] s#0    m8 ;
: 1#     ( -- xt ) ['] s#1    m8 ;
: 2#     ( -- xt ) ['] s#2    m8 ;
: 4#     ( -- xt ) ['] s#4    m8 ;
: 8#     ( -- xt ) ['] s#8    m8 ;
: FFFF#  ( -- xt ) ['] s#FFFF m8 ;



\ ****** Here are the mnemonics, that use the smarter adressing mode notation.

\ *** Double-Operand Instructions (Format I)

: smode# ( -- n )  mode# 4 rshift $F and ;

: smodeI ( src | x src -- )
    smode#
    dup 1 = if drop sRn     exit then
    dup 2 = if drop sx(Rn)  exit then
    dup 3 = if drop sADDR   exit then
    dup 4 = if drop s&ADDR  exit then
    dup 5 = if drop s@Rn    exit then
    dup 6 = if drop s@Rn+   exit then
    dup 7 = if drop s#K     exit then
    dup 8 = if drop execute exit then
    1 throw ;

: dmode# ( -- n )  mode# $F and ;
: dmodeI ( dst | x dst -- )
    dmode#
    dup 1 = if drop dRn     exit then
    dup 2 = if drop dx(Rn)  exit then
    dup 3 = if drop dADDR   exit then
    dup 4 = if drop d&ADDR  exit then
    1 throw ;   \ error(1) address mode in destination > 4

\ expression ex may be single or doubble item. res
 : MOV.W  ( ex1 ex2  -- ) dmodeI smodeI     mov.w,  reset-mode# ;
 : ADD.W  ( ex1 ex2  -- ) dmodeI smodeI     add.w,  reset-mode# ;
 : ADDC.W ( ex1 ex2  -- ) dmodeI smodeI     addc.w, reset-mode# ;
 : SUBC.W ( ex1 ex2  -- ) dmodeI smodeI     subc.w, reset-mode# ;
 : SUB.W  ( ex1 ex2  -- ) dmodeI smodeI     sub.w,  reset-mode# ;
 : CMP.W  ( ex1 ex2  -- ) dmodeI smodeI     cmp.w,  reset-mode# ;
 : DADD.W ( ex1 ex2  -- ) dmodeI smodeI     dadd.w, reset-mode# ;
 : BIT.W  ( ex1 ex2  -- ) dmodeI smodeI     bit.w,  reset-mode# ;
 : BIC.W  ( ex1 ex2  -- ) dmodeI smodeI     bic.w,  reset-mode# ;
 : BIS.W  ( ex1 ex2  -- ) dmodeI smodeI     bis.w,  reset-mode# ;
 : XOR.W  ( ex1 ex2  -- ) dmodeI smodeI     xor.w,  reset-mode# ;
 : AND.W  ( ex1 ex2  -- ) dmodeI smodeI     and.w,  reset-mode# ;

 : MOV.B  ( ex1 ex2  -- ) dmodeI smodeI     mov.B,  reset-mode# ;
 : ADD.B  ( ex1 ex2  -- ) dmodeI smodeI     add.B,  reset-mode# ;
 : ADDC.B ( ex1 ex2  -- ) dmodeI smodeI     addc.B, reset-mode# ;
 : SUBC.B ( ex1 ex2  -- ) dmodeI smodeI     subc.B, reset-mode# ;
 : SUB.B  ( ex1 ex2  -- ) dmodeI smodeI     sub.B,  reset-mode# ;
 : CMP.B  ( ex1 ex2  -- ) dmodeI smodeI     cmp.B,  reset-mode# ;
 : DADD.B ( ex1 ex2  -- ) dmodeI smodeI     dadd.B, reset-mode# ;
 : BIT.B  ( ex1 ex2  -- ) dmodeI smodeI     bit.B,  reset-mode# ;
 : BIC.B  ( ex1 ex2  -- ) dmodeI smodeI     bic.B,  reset-mode# ;
 : BIS.B  ( ex1 ex2  -- ) dmodeI smodeI     bis.B,  reset-mode# ;
 : XOR.B  ( ex1 ex2  -- ) dmodeI smodeI     xor.B,  reset-mode# ;
 : AND.B  ( ex1 ex2  -- ) dmodeI smodeI     and.B,  reset-mode# ;

 ' MOV.W     alias MOV
 ' ADD.W     alias ADD
 ' ADDC.W    alias ADDC
 ' SUBC.W    alias SUBC
 ' SUB.W     alias SUB
 ' CMP.W     alias CMP
 ' DADD.W    alias DADD
 ' BIT.W     alias BIT
 ' BIC.W     alias BIC
 ' BIS.W     alias BIS
\ ' XOR.W     alias XOR
\ ' AND.W     alias AND



\ *** Single-Operand Instructions ( Format II )

: modeII ( src | x src -- )
    mode# $F and
    dup 1 = if drop Rn     exit then
    dup 2 = if drop x(Rn)  exit then
    dup 3 = if drop ADDR   exit then
    dup 4 = if drop &ADDR  exit then
    dup 5 = if drop @Rn    exit then
    dup 6 = if drop @Rn+   exit then
    dup 7 = if drop #K     exit then
    1 throw ;

: RRC.W   ( ex -- ) modeII RRC.W,  reset-mode# ;
: SWPB    ( ex -- ) modeII SWPB,   reset-mode# ;
: RRA.W   ( ex -- ) modeII RRA.W,  reset-mode# ;
: SXT     ( ex -- ) modeII SXT,    reset-mode# ;
: PUSH.W  ( ex -- ) modeII PUSH.W, reset-mode# ;
: CALL    ( ex -- ) modeII CALL,   reset-mode# ;
' RETI, alias RETI

: RRC.B   ( ex -- ) modeII RRC.B,  reset-mode# ;
: RRA.B   ( ex -- ) modeII RRA.B,  reset-mode# ;
: PUSH.B  ( ex -- ) modeII PUSH.B, reset-mode# ;

 ' RRC.W  alias RRC
 ' RRA.W  alias RRA
 ' PUSH.W alias PUSH



\ *** Jump Instructions ( FormatIII )
' JNE, ( adr -- )  alias JNE
' JEQ, ( adr -- )  alias JEQ
' JNC, ( adr -- )  alias JNC
' JC,  ( adr -- )  alias JC
' JN,  ( adr -- )  alias JN
' JGE, ( adr -- )  alias JGE
' JL,  ( adr -- )  alias JL
' JMP, ( adr -- )  alias JMP

  ' JNE, alias JNZ
  ' JEQ, alias JZ
  ' JNC, alias JLO
  ' JC,  alias JHS

( finis )