Fix for "*" getting bad section attributes, reported by A. Seed.
[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         // Eat the comma
88         tok++;
89
90         // Parse second addressing mode
91         #define AnOK      a1ok
92         #define AMn       am1
93         #define AnREG     a1reg
94         #define AnIXREG   a1ixreg
95         #define AnIXSIZ   a1ixsiz
96         #define AnEXPR    a1expr
97         #define AnEXVAL   a1exval
98         #define AnEXATTR  a1exattr
99         #define AnOEXPR   a1oexpr
100         #define AnOEXVAL  a1oexval
101         #define AnOEXATTR a1oexattr
102         #define AnESYM    a1esym
103         #define AMn_IX0   am1_ix0
104         #define AMn_IXN   am1_ixn
105         #include "parmode.h"
106
107         nmodes = 2;
108         return 2;
109
110         // Error messages:
111         badmode:
112         return error("addressing mode syntax");
113
114         unmode:
115         return error("unimplemented addressing mode");
116 }
117
118
119 //
120 // Parse register list
121 //
122 int reglist(WORD * a_rmask)
123 {
124         static WORD msktab[] = {
125                 0x0001, 0x0002, 0x0004, 0x0008,
126                 0x0010, 0x0020, 0x0040, 0x0080,
127                 0x0100, 0x0200, 0x0400, 0x0800,
128                 0x1000, 0x2000, 0x4000, 0x8000
129         };
130
131         WORD rmask = 0;
132         int r, cnt;
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 }
171