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