f0734ea5916dc8f6c86007954062fd162372b1e6
[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, 2017 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         #define CHK_FOR_DISPn CheckForDisp0
79         #include "parmode.h"
80
81         // If caller wants only one mode, return just one (ignore comma);
82         // If there is no second addressing mode (no comma), then return just one anyway.
83         nmodes = 1;
84
85         if (acount == 0 || *tok != ',')
86                 return 1;
87
88         // Eat the comma
89         tok++;
90
91         // Parse second addressing mode
92         #define AnOK      a1ok
93         #define AMn       am1
94         #define AnREG     a1reg
95         #define AnIXREG   a1ixreg
96         #define AnIXSIZ   a1ixsiz
97         #define AnEXPR    a1expr
98         #define AnEXVAL   a1exval
99         #define AnEXATTR  a1exattr
100         #define AnOEXPR   a1oexpr
101         #define AnOEXVAL  a1oexval
102         #define AnOEXATTR a1oexattr
103         #define AnESYM    a1esym
104         #define AMn_IX0   am1_ix0
105         #define AMn_IXN   am1_ixn
106         #define CHK_FOR_DISPn CheckForDisp1
107         #include "parmode.h"
108
109         nmodes = 2;
110         return 2;
111
112         // Error messages:
113         badmode:
114         return error("addressing mode syntax");
115
116         unmode:
117         return error("unimplemented addressing mode");
118 }
119
120
121 //
122 // Parse register list
123 //
124 int reglist(WORD * a_rmask)
125 {
126         static WORD msktab[] = {
127                 0x0001, 0x0002, 0x0004, 0x0008,
128                 0x0010, 0x0020, 0x0040, 0x0080,
129                 0x0100, 0x0200, 0x0400, 0x0800,
130                 0x1000, 0x2000, 0x4000, 0x8000
131         };
132
133         WORD rmask = 0;
134         int r, cnt;
135
136         for(;;)
137         {
138                 if (*tok >= KW_D0 && *tok <= KW_A7)
139                         r = *tok++ & 15;
140                 else
141                         break;
142
143                 if (*tok == '-')
144                 {
145                         tok++;
146
147                         if (*tok >= KW_D0 && *tok <= KW_A7)
148                                 cnt = *tok++ & 15;
149                         else
150                                 return error("register list syntax");
151
152                         if (cnt < r)
153                                 return error("register list order");
154
155                         cnt -= r;
156                 }
157                 else
158                         cnt = 0;
159
160                 while (cnt-- >= 0)
161                         rmask |= msktab[r++];
162
163                 if (*tok != '/')
164                         break;
165
166                 tok++;
167         }
168
169         *a_rmask = rmask;
170
171         return OK;
172 }
173