2 // RMAC - Renamed Macro Assembler for all Atari computers
3 // AMODE.C - Addressing Modes
4 // Copyright (C) 199x Landon Dyer, 2011-2021 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
23 extern char unsupport[];
25 // Address-mode information
26 int nmodes; // Number of addr'ing modes found
27 int am0; // Addressing mode
28 int a0reg; // Register
29 TOKEN a0expr[EXPRSIZE]; // Expression
30 uint64_t a0exval; // Expression's value
31 WORD a0exattr; // Expression's attribute
32 int a0ixreg; // Index register
33 int a0ixsiz; // Index register size (and scale)
34 SYM * a0esym; // External symbol involved in expr
35 TOKEN a0bexpr[EXPRSIZE]; // Base displacement expression
36 uint64_t a0bexval; // Base displacement value
37 WORD a0bexattr; // Base displacement attribute
38 WORD a0bsize; // Base displacement size
39 WORD a0extension; // 020+ extension address word
40 WORD am0_030; // ea bits for 020+ addressing modes
42 int am1; // Addressing mode
43 int a1reg; // Register
44 TOKEN a1expr[EXPRSIZE]; // Expression
45 uint64_t a1exval; // Expression's value
46 WORD a1exattr; // Expression's attribute
47 int a1ixreg; // Index register
48 int a1ixsiz; // Index register size (and scale)
49 SYM * a1esym; // External symbol involved in expr
50 TOKEN a1bexpr[EXPRSIZE]; // Base displacement expression
51 uint64_t a1bexval; // Base displacement value
52 WORD a1bexattr; // Base displacement attribute
53 WORD a1bsize; // Base displacement size
54 WORD a1extension; // 020+ extension address word
55 WORD am1_030; // ea bits for 020+ addressing modes
57 int a2reg; // Register for div.l (68020+)
59 int bfparam1; // bfxxx / fmove instruction parameter 1
60 int bfparam2; // bfxxx / fmove instruction parameter 2
61 int bfval1; // bfxxx / fmove value 1
62 int bfval2; // bfxxx / fmove value 2
63 TOKEN bf0expr[EXPRSIZE]; // Expression
64 uint64_t bf0exval; // Expression's value
65 WORD bf0exattr; // Expression's attribute
66 SYM * bf0esym; // External symbol involved in expr
68 // Function prototypes
69 int Check030Bitfield(void);
73 // Parse addressing mode
77 // Initialize global return values
78 nmodes = a0reg = a1reg = 0;
80 a0expr[0] = a1expr[0] = ENDEXPR;
81 a0exattr = a1exattr = 0;
82 a0esym = a1esym = NULL;
83 a0bexpr[0] = a1bexpr[0] = ENDEXPR;
84 a0bexval = a1bexval = 0;
85 a0bsize = a0extension = a1bsize = a1extension = 0;
86 am0_030 = am1_030 = 0;
87 bfparam1 = bfparam2 = 0;
92 // If at EOL, then no addr modes at all
96 // Parse first addressing mode
100 #define AnIXREG a0ixreg
101 #define AnIXSIZ a0ixsiz
102 #define AnEXPR a0expr
103 #define AnEXVAL a0exval
104 #define AnEXATTR a0exattr
105 #define AnESYM a0esym
106 #define AMn_IX0 am0_ix0
107 #define AMn_IXN am0_ixn
108 #define CHK_FOR_DISPn CheckForDisp0
109 #define AnBEXPR a0bexpr
110 #define AnBEXVAL a0bexval
111 #define AnBEXATTR a0bexattr
112 #define AnBZISE a0bsize
113 #define AnEXTEN a0extension
114 #define AMn_030 am0_030
115 #define IS_SUPPRESSEDn IS_SUPPRESSED0
116 #define CHECKODn CHECKOD0
119 // If caller wants only one mode, return just one (ignore comma);. If there
120 // is no second addressing mode (no comma), then return just one anyway.
123 // it's a bitfield instruction--check the parameters inside the {} block
126 if (Check030Bitfield() == ERROR)
129 if ((acount == 0) || (*tok != ','))
135 // Parse second addressing mode
139 #define AnIXREG a1ixreg
140 #define AnIXSIZ a1ixsiz
141 #define AnEXPR a1expr
142 #define AnEXVAL a1exval
143 #define AnEXATTR a1exattr
144 #define AnESYM a1esym
145 #define AMn_IX0 am1_ix0
146 #define AMn_IXN am1_ixn
147 #define CHK_FOR_DISPn CheckForDisp1
148 #define AnBEXPR a1bexpr
149 #define AnBEXVAL a1bexval
150 #define AnBEXATTR a1bexattr
151 #define AnBZISE a1bsize
152 #define AnEXTEN a1extension
153 #define AMn_030 am1_030
154 #define IS_SUPPRESSEDn IS_SUPPRESSED1
155 #define CHECKODn CHECKOD1
158 // It's a bitfield instruction--check the parameters inside the {} block
161 if (Check030Bitfield() == ERROR)
164 // At this point, it is legal for 020+ to have a ':'. For example divu.l
168 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
169 return error(unsupport);
171 // TODO: protect this from combinations like Dx:FPx etc :)
172 tok++; //eat the colon
174 if ((*tok >= KW_D0) && (*tok <= KW_D7))
175 a2reg = (*tok++) & 7;
176 else if ((*tok >= KW_FP0) && (*tok <= KW_FP7))
177 a2reg = (*tok++) & 7;
179 return error("a data or FPU register must follow a :");
183 // If no ':' is present then maybe we have something like divs.l d0,d1
184 // which sould translate to divs.l d0,d1:d1
193 return error("addressing mode syntax");
198 // Parse register list
200 int reglist(WORD * a_rmask)
202 static WORD msktab[] = {
203 0x0001, 0x0002, 0x0004, 0x0008,
204 0x0010, 0x0020, 0x0040, 0x0080,
205 0x0100, 0x0200, 0x0400, 0x0800,
206 0x1000, 0x2000, 0x4000, 0x8000
214 if ((*tok >= KW_D0) && (*tok <= KW_A7))
223 if ((*tok >= KW_D0) && (*tok <= KW_A7))
226 return error("register list syntax");
229 return error("register list order");
237 rmask |= msktab[r++];
252 // Parse FPU register list
254 int fpu_reglist_left(WORD * a_rmask)
256 static WORD msktab_minus[] = {
257 0x0080, 0x0040, 0x0020, 0x0010,
258 0x0008, 0x0004, 0x0002, 0x0001
266 if ((*tok >= KW_FP0) && (*tok <= KW_FP7))
275 if ((*tok >= KW_FP0) && (*tok <= KW_FP7))
278 return error("register list syntax");
281 return error("register list order");
291 rmask |= msktab_minus[r++];
305 int fpu_reglist_right(WORD * a_rmask)
307 static WORD msktab_plus[] = {
308 0x0080, 0x0040, 0x0020, 0x0010,
309 0x0008, 0x0004, 0x0002, 0x0001
317 if ((*tok >= KW_FP0) && (*tok <= KW_FP7))
326 if ((*tok >= KW_FP0) && (*tok <= KW_FP7))
329 return error("register list syntax");
332 return error("register list order");
340 rmask |= msktab_plus[r++];
355 // Check for bitfield instructions extra params
356 // These are 020+ instructions and have the following syntax:
357 // bfxxx <ea>{param1,param2}
358 // param1/2 are either data registers or immediate values
360 int Check030Bitfield(void)
369 bfval1 = (int)*tp.u64++;
372 // Do=0, offset=immediate - shift it to place
373 bfparam1 = (0 << 11);
375 else if (*tok == SYMBOL)
377 if (expr(bf0expr, &bf0exval, &bf0exattr, &bf0esym) != OK)
380 if (!(bf0exattr & DEFINED))
381 return error("bfxxx offset: immediate value must evaluate");
383 bfval1 = (int)bf0exval;
385 // Do=0, offset=immediate - shift it to place
386 bfparam1 = (0 << 11);
388 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
390 // Do=1, offset=data register - shift it to place
391 bfparam1 = (1 << 11);
392 bfval1 = (*(int *)tok - 128);
398 // Eat the ':', if any
402 if (*tok == '}' && tok[1] == EOL)
404 // It is ok to have }, EOL here - it might be "fmove fpn,<ea> {dx}"
412 bfval2 = (int)*tp.u64++;
415 // Do=0, offset=immediate - shift it to place
418 else if (*tok == SYMBOL)
420 if (expr(bf0expr, &bf0exval, &bf0exattr, &bf0esym) != OK)
423 bfval2 = (int)bf0exval;
425 if (!(bf0exattr & DEFINED))
426 return error("bfxxx width: immediate value must evaluate");
428 // Do=0, offset=immediate - shift it to place
431 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
433 // Do=1, offset=data register - shift it to place
434 bfval2 = (*(int *)tok - 128);
441 tok++; // Eat the '}'