Initial commit.
[rmac] / amode.c
1 ////////////////////////////////////////////////////////////////////////////////////////////////////
2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // AMODE.C - Addressing Modes
4 // Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source Utilised with the Kind Permission of Landon Dyer
7
8 #include "amode.h"
9 #include "error.h"
10 #include "token.h"
11 #include "expr.h"
12 #include "rmac.h"
13
14 #define DEF_KW
15 #include "kwtab.h"
16 #define DEF_MN
17 #include "mntab.h"
18
19 // Address-mode information
20 int nmodes;                                                 // Number of addr'ing modes found
21 int am0;                                                    // Addressing mode
22 int a0reg;                                                  // Register
23 TOKEN a0expr[EXPRSIZE];                                     // Expression
24 VALUE a0exval;                                              // Expression's value
25 WORD a0exattr;                                              // Expression's attribute
26 int a0ixreg;                                                // Index register
27 int a0ixsiz;                                                // Index register size (and scale)
28 TOKEN a0oexpr[EXPRSIZE];                                    // Outer displacement expression
29 VALUE a0oexval;                                             // Outer displacement value
30 WORD a0oexattr;                                             // Outer displacement attribute
31 SYM *a0esym;                                                // External symbol involved in expr
32
33 int am1;                                                    // Addressing mode
34 int a1reg;                                                  // Register
35 TOKEN a1expr[EXPRSIZE];                                     // Expression
36 VALUE a1exval;                                              // Expression's value
37 WORD a1exattr;                                              // Expression's attribute
38 int a1ixreg;                                                // Index register
39 int a1ixsiz;                                                // Index register size (and scale)
40 TOKEN a1oexpr[EXPRSIZE];                                    // Outer displacement expression
41 VALUE a1oexval;                                             // Outer displacement value
42 WORD a1oexattr;                                             // Outer displacement attribute
43 SYM *a1esym;                                                // External symbol involved in expr
44
45 //
46 // --- Parse Addressing Mode -----------------------------------------------------------------------
47 //
48
49 int amode(int acount) {
50    // Initialize global return values
51         nmodes = a0reg = a1reg = 0;
52         am0 = am1 = AM_NONE;
53         a0expr[0] = a0oexpr[0] = a1expr[0] = a1oexpr[0] = ENDEXPR;
54         a0exattr = a0oexattr = a1exattr = a1oexattr = 0;
55         a0esym = a1esym = (SYM *)NULL;
56
57    // If at EOL, then no addr modes at all
58    if(*tok == EOL)
59       return(0);
60
61    // Parse first addressing mode
62    #define AnOK      a0ok
63    #define AMn       am0
64    #define AnREG     a0reg
65    #define AnIXREG   a0ixreg
66    #define AnIXSIZ   a0ixsiz
67    #define AnEXPR    a0expr
68    #define AnEXVAL   a0exval
69    #define AnEXATTR  a0exattr
70    #define AnOEXPR   a0oexpr
71    #define AnOEXVAL  a0oexval
72    #define AnOEXATTR a0oexattr
73    #define AnESYM    a0esym
74    #define AMn_IX0   am0_ix0
75    #define AMn_IXN   am0_ixn
76    #include "parmode.h"
77
78    // If caller wants only one mode, return just one (ignore comma); 
79    // If there is no second addressing mode (no comma), then return just one anyway.
80    nmodes = 1;
81    if(acount == 0 || *tok != ',')
82       return(1);
83    ++tok;                                                   // Eat comma
84
85    // Parse second addressing mode
86    #define AnOK      a1ok
87    #define AMn       am1
88    #define AnREG     a1reg
89    #define AnIXREG   a1ixreg
90    #define AnIXSIZ   a1ixsiz
91    #define AnEXPR    a1expr
92    #define AnEXVAL   a1exval
93    #define AnEXATTR  a1exattr
94    #define AnOEXPR   a1oexpr
95    #define AnOEXVAL  a1oexval
96    #define AnOEXATTR a1oexattr
97    #define AnESYM    a1esym
98    #define AMn_IX0   am1_ix0
99    #define AMn_IXN   am1_ixn
100    #include "parmode.h"
101
102    nmodes = 2;
103    return(2);
104
105    // Error messages:
106    badmode:
107
108    return(error("addressing mode syntax"));
109
110    unmode:
111
112    return(error("unimplemented addressing mode"));
113 }
114
115 //
116 // --- Parse Register List -------------------------------------------------------------------------
117 //
118
119 int reglist(WORD *a_rmask) {
120    static WORD msktab[] = {
121       0x0001, 0x0002, 0x0004, 0x0008,
122       0x0010, 0x0020, 0x0040, 0x0080,
123       0x0100, 0x0200, 0x0400, 0x0800,
124       0x1000, 0x2000, 0x4000, 0x8000
125    };
126    WORD rmask;
127    int r, cnt;
128
129    rmask = 0;
130    for(;;) {
131       if(*tok >= KW_D0 && *tok <= KW_A7)
132          r = *tok++ & 15;
133       else break;
134
135       if(*tok == '-') {
136          ++tok;
137          if(*tok >= KW_D0 && *tok <= KW_A7)
138             cnt = *tok++ & 15;
139          else 
140             return(error("register list syntax"));
141
142          if(cnt < r)
143             return(error("register list order"));
144          cnt -= r;
145       } else 
146          cnt = 0;
147
148       while(cnt-- >= 0)
149          rmask |= msktab[r++];
150       if(*tok != '/')
151          break;
152       ++tok;
153    }
154
155    *a_rmask = rmask;
156
157    return(OK);
158 }
159
160