ELF support for RMAC.
[rmac] / eagen0.c
1 //
2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // EAGEN0.C - Effective Address Code Generation
4 //            Generated Code for eaN (Included twice by "eagen.c")
5 // Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends
6 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
7 // Source utilised with the kind permission of Landon Dyer
8 //
9
10 int eaNgen(WORD siz)
11 {
12         VALUE v = aNexval;
13         WORD w = (WORD)(aNexattr & DEFINED);
14         WORD tdb = (WORD)(aNexattr & TDB);
15
16         switch (amN)
17         {
18         // "Do nothing" - they're in the opword
19         case DREG:
20         case AREG:
21         case AIND:
22         case APOSTINC:
23         case APREDEC:
24         case AM_USP:
25         case AM_CCR:
26         case AM_SR:
27         case AM_NONE:
28                 // This is a performance hit, though
29                 break;
30         case ADISP:
31                 // expr(An)
32                 if (w)
33                 {
34                         // Just deposit it
35                         if (tdb)
36                                 MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
37
38                         if ((v == 0) && optim_flags[OPT_INDIRECT_DISP])
39                         {
40                                 // If expr is 0, size optimise the opcode. Generally the lower
41                                 // 6 bits of the opcode for expr(ax) are 101rrr where rrr=the
42                                 // number of the register, then followed by a word containing
43                                 // 'expr'. We need to change that to 010rrr.
44                                 if ((siz & 0x8000) == 0)
45                                 {
46                                         chptr_opcode[0] &= ((0xFFC7 >> 8) & 255); // mask off bits
47                                         chptr_opcode[1] &= 0xFFC7 & 255;          // mask off bits
48                                         chptr_opcode[0] |= ((0x0010 >> 8) & 255); // slap in 010 bits
49                                         chptr_opcode[1] |= 0x0010 & 255;          // slap in 010 bits
50                                 }
51                                 else
52                                 {
53                                         // Special case for move ea,ea: there are two ea fields
54                                         // there and we get a signal if it's the second ea field
55                                         // from m_ea - siz's 16th bit is set
56                                         chptr_opcode[0] &= ((0xFE3F >> 8) & 255); // mask off bits
57                                         chptr_opcode[1] &= 0xFE3F & 255;          // mask off bits
58                                         chptr_opcode[0] |= ((0x0080 >> 8) & 255); // slap in 010 bits
59                                         chptr_opcode[1] |= 0x0080 & 255;          // slap in 010 bits
60                                 }
61
62                                 if (sbra_flag)
63                                         warn("0(An) converted to (An)");
64
65                                 return OK;
66                         }
67
68                         if ((v + 0x8000) >= 0x18000)
69                                 return error(range_error);
70
71                         D_word(v);
72                 }
73                 else
74                 {
75                         // Arrange for fixup later on
76                         AddFixup(FU_WORD | FU_SEXT, sloc, aNexpr);
77                         D_word(0);
78                 }
79
80                 break;
81         case PCDISP:
82                 if (w)
83                 {
84                         // Just deposit it
85                         if ((aNexattr & TDB) == cursect)
86                                 v -= (VALUE)sloc;
87                         else if ((aNexattr & TDB) != ABS)
88                                 error(rel_error);
89
90                         if (v + 0x8000 >= 0x10000)
91                                 return error(range_error);
92
93                         D_word(v);
94                 }
95                 else
96                 {
97                         // Arrange for fixup later on
98                         AddFixup(FU_WORD | FU_SEXT | FU_PCREL, sloc, aNexpr);
99                         D_word(0);
100                 }
101
102                 break;
103         case AINDEXED:
104                 // Compute ixreg and size+scale
105                 w = (WORD)((aNixreg << 12) | aNixsiz);
106
107                 if (aNexattr & DEFINED)
108                 {
109                         // Deposit a byte...
110                         if (tdb)
111                                 // Can't mark bytes
112                                 return error(abs_error);
113
114                         if (v + 0x80 >= 0x180)
115                                 return error(range_error);
116
117                         w |= v & 0xFF;
118                         D_word(w);
119                 }
120                 else
121                 {
122                         // Fixup the byte later
123                         AddFixup(FU_BYTE | FU_SEXT, sloc + 1, aNexpr);
124                         D_word(w);
125                 }
126
127                 break;
128         case PCINDEXED:
129                 // Compute ixreg and size+scale
130                 w = (WORD)((aNixreg << 12) | aNixsiz);
131
132                 if (aNexattr & DEFINED)
133                 {
134                         // Deposit a byte...
135                         if ((aNexattr & TDB) == cursect)
136                                 v -= (VALUE)sloc;
137                         else if ((aNexattr & TDB) != ABS)
138                                 error(rel_error);
139
140                         if (v + 0x80 >= 0x100)
141                                 return error(range_error);
142
143                         w |= v & 0xFF;
144                         D_word(w);
145                 }
146                 else
147                 {
148                         // Fixup the byte later
149                         AddFixup(FU_WBYTE | FU_SEXT | FU_PCREL, sloc, aNexpr);
150                         D_word(w);
151                 }
152
153                 break;
154         case IMMED:
155                 switch (siz)
156                 {
157                 case SIZB:
158                         if (w)
159                         {
160                                 if (tdb)
161                                         return error("illegal byte-sized relative reference");
162
163                                 if (v + 0x100 >= 0x200)
164                                         return error(range_error);
165
166                                 D_word(v);
167                         }
168                         else
169                         {
170                                 AddFixup(FU_BYTE | FU_SEXT, sloc + 1, aNexpr);
171                                 D_word(0);
172                         }
173
174                         break;
175                 case SIZW:
176                 case SIZN:
177                         if (w)
178                         {
179                                 if (v + 0x10000 >= 0x20000)
180                                         return error(range_error);
181
182                                 if (tdb)
183                                         MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
184
185                                 D_word(v);
186                         }
187                         else
188                         {
189                                 AddFixup(FU_WORD | FU_SEXT, sloc, aNexpr);
190                                 D_word(0);
191                         }
192
193                         break;
194                 case SIZL:
195                         if (w)
196                         {
197                                 if (tdb)
198                                         MarkRelocatable(cursect, sloc, tdb, MLONG, NULL);
199
200                                 D_long(v);
201                         }
202                         else
203                         {
204                                 AddFixup(FU_LONG, sloc, aNexpr);
205                                 D_long(0);
206                         }
207
208                         break;
209                 default:
210                         // IMMED size problem
211                         interror(1);
212                 }
213
214                 break;
215         case ABSW:
216                 if (w) // Defined
217                 {
218                         if (tdb)
219                                 MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
220
221                         if (v + 0x8000 >= 0x10000)
222                                 return error(range_error);
223
224                         D_word(v);
225                 }
226                 else
227                 {
228                         AddFixup(FU_WORD | FU_SEXT, sloc, aNexpr);
229                         D_word(0);
230                 }
231
232                 break;
233         case ABSL:
234                 if (w) // Defined
235                 {
236                         if (tdb)
237                                 MarkRelocatable(cursect, sloc, tdb, MLONG, NULL);
238
239                         D_long(v);
240                 }
241                 else
242                 {
243                         AddFixup(FU_LONG, sloc, aNexpr);
244                         D_long(0);
245                 }
246
247                 break;
248         case ABASE:
249         case MEMPOST:
250         case MEMPRE:
251         case PCBASE:
252         case PCMPOST:
253         case PCMPRE:
254                 return error("unsupported 68020 addressing mode");
255         default:
256                 // Bad addressing mode in ea gen
257                 interror(3);
258         }
259
260         return OK;
261 }
262
263 // Undefine dirty macros
264 #undef eaNgen
265 #undef amN
266 #undef aNexattr
267 #undef aNexval
268 #undef aNexpr
269 #undef aNixreg
270 #undef aNixsiz
271 #undef AnESYM
272