(c) message in header files and doc mini adjustments.
[rmac] / eagen0.c
1 //
2 // RMAC - Reboot's Macro Assembler for all Atari computers
3 // EAGEN0.C - Effective Address Code Generation
4 //            Generated Code for eaN (Included twice by "eagen.c")
5 // Copyright (C) 199x Landon Dyer, 2011-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 vbd, v = aNexval;
13         WORD wbd, w = (WORD)(aNexattr & DEFINED);
14         WORD tdbbd, tdb = (WORD)(aNexattr & TDB);
15         vbd = aNbdexval;
16         wbd = (WORD)(aNbdexattr & DEFINED);
17         tdbbd = (WORD)(aNbdexattr & TDB);
18
19         switch (amN)
20         {
21         // "Do nothing" - they're in the opword
22         case DREG:
23         case AREG:
24         case AIND:
25         case APOSTINC:
26         case APREDEC:
27         case AM_USP:
28         case AM_CCR:
29         case AM_SR:
30         case AM_NONE:
31                 // This is a performance hit, though
32                 break;
33         case ADISP:
34                 // expr(An)
35                 if (w)
36                 {
37                         // Just deposit it
38                         if (tdb)
39                                 MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
40
41                         if ((v == 0) && optim_flags[OPT_INDIRECT_DISP] && !movep)
42                         {
43                                 // If expr is 0, size optimise the opcode. Generally the lower
44                                 // 6 bits of the opcode for expr(ax) are 101rrr where rrr=the
45                                 // number of the register, then followed by a word containing
46                                 // 'expr'. We need to change that to 010rrr.
47                                 if ((siz & 0x8000) == 0)
48                                 {
49                                         chptr_opcode[0] &= ((0xFFC7 >> 8) & 255); // mask off bits
50                                         chptr_opcode[1] &= 0xFFC7 & 255;          // mask off bits
51                                         chptr_opcode[0] |= ((0x0010 >> 8) & 255); // slap in 010 bits
52                                         chptr_opcode[1] |= 0x0010 & 255;          // slap in 010 bits
53                                 }
54                                 else
55                                 {
56                                         // Special case for move ea,ea: there are two ea fields
57                                         // there and we get a signal if it's the second ea field
58                                         // from m_ea - siz's 16th bit is set
59                                         chptr_opcode[0] &= ((0xFE3F >> 8) & 255); // mask off bits
60                                         chptr_opcode[1] &= 0xFE3F & 255;          // mask off bits
61                                         chptr_opcode[0] |= ((0x0080 >> 8) & 255); // slap in 010 bits
62                                         chptr_opcode[1] |= 0x0080 & 255;          // slap in 010 bits
63                                 }
64
65                                 if (sbra_flag)
66                                         warn("0(An) converted to (An)");
67
68                                 return OK;
69                         }
70
71                         if ((v + 0x8000) >= 0x18000)
72                                 return error(range_error);
73
74                         D_word(v);
75                 }
76                 else
77                 {
78                         // Arrange for fixup later on
79                         AddFixup(FU_WORD | FU_SEXT, sloc, aNexpr);
80                         D_word(0);
81                 }
82
83                 break;
84         case PCDISP:
85                 if (w)
86                 {
87                         // Just deposit it
88                         if ((aNexattr & TDB) == cursect)
89                                 v -= (VALUE)sloc;
90                         else if ((aNexattr & TDB) != ABS)
91                                 error(rel_error);
92
93                         if (v + 0x8000 >= 0x10000)
94                                 return error(range_error);
95
96                         D_word(v);
97                 }
98                 else
99                 {
100                         // Arrange for fixup later on
101                         AddFixup(FU_WORD | FU_SEXT | FU_PCREL, sloc, aNexpr);
102                         D_word(0);
103                 }
104
105                 break;
106         case AINDEXED:
107                 // Compute ixreg and size+scale
108                 w = (WORD)((aNixreg << 12) | aNixsiz);
109
110                 if (aNexattr & DEFINED)
111                 {
112                         // Deposit a byte...
113                         if (tdb)
114                                 // Can't mark bytes
115                                 return error(abs_error);
116
117                         if (v + 0x80 >= 0x180)
118                                 return error(range_error);
119
120                         w |= v & 0xFF;
121                         D_word(w);
122                 }
123                 else
124                 {
125                         // Fixup the byte later
126                         AddFixup(FU_BYTE | FU_SEXT, sloc + 1, aNexpr);
127                         D_word(w);
128                 }
129
130                 break;
131         case PCINDEXED:
132                 // Compute ixreg and size+scale
133                 w = (WORD)((aNixreg << 12) | aNixsiz);
134
135                 if (aNexattr & DEFINED)
136                 {
137                         // Deposit a byte...
138                         if ((aNexattr & TDB) == cursect)
139                                 v -= (VALUE)sloc;
140                         else if ((aNexattr & TDB) != ABS)
141                                 error(rel_error);
142
143                         if (v + 0x80 >= 0x100)
144                                 return error(range_error);
145
146                         w |= v & 0xFF;
147                         D_word(w);
148                 }
149                 else
150                 {
151                         // Fixup the byte later
152                         AddFixup(FU_WBYTE | FU_SEXT | FU_PCREL, sloc, aNexpr);
153                         D_word(w);
154                 }
155
156                 break;
157         case IMMED:
158                 switch (siz)
159                 {
160                 case SIZB:
161                         if (w)
162                         {
163                                 if (tdb)
164                                         return error("illegal byte-sized relative reference");
165
166                                 if (v + 0x100 >= 0x200)
167                                         return error(range_error);
168
169                                 D_word(v);
170                         }
171                         else
172                         {
173                                 AddFixup(FU_BYTE | FU_SEXT, sloc + 1, aNexpr);
174                                 D_word(0);
175                         }
176
177                         break;
178                 case SIZW:
179                 case SIZN:
180                         if (w)
181                         {
182                                 if (v + 0x10000 >= 0x20000)
183                                         return error(range_error);
184
185                                 if (tdb)
186                                         MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
187
188                                 D_word(v);
189                         }
190                         else
191                         {
192                                 AddFixup(FU_WORD | FU_SEXT, sloc, aNexpr);
193                                 D_word(0);
194                         }
195
196                         break;
197                 case SIZL:
198                         if (w)
199                         {
200                                 if (tdb)
201                                         MarkRelocatable(cursect, sloc, tdb, MLONG, NULL);
202
203                                 D_long(v);
204                         }
205                         else
206                         {
207                                 AddFixup(FU_LONG, sloc, aNexpr);
208                                 D_long(0);
209                         }
210
211                         break;
212                 default:
213                         // IMMED size problem
214                         interror(1);
215                 }
216
217                 break;
218     case SIZP:
219                 // 68881/68882/68040 only
220                 return error("Sorry, .p constant format is not implemented yet!");
221                 break;
222         case ABSW:
223                 if (w) // Defined
224                 {
225                         if (tdb)
226                                 MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
227
228                         if (v + 0x8000 >= 0x10000)
229                                 return error(range_error);
230
231                         D_word(v);
232                 }
233                 else
234                 {
235                         AddFixup(FU_WORD | FU_SEXT, sloc, aNexpr);
236                         D_word(0);
237                 }
238
239                 break;
240         case ABSL:
241                 if (w) // Defined
242                 {
243                         if (tdb)
244                                 MarkRelocatable(cursect, sloc, tdb, MLONG, NULL);
245
246                         D_long(v);
247                 }
248                 else
249                 {
250                         AddFixup(FU_LONG, sloc, aNexpr);
251                         D_long(0);
252                 }
253
254                 break;
255         case ABASE:
256         case MEMPOST:
257         case MEMPRE:
258         case PCBASE:
259         case PCMPOST:
260         case PCMPRE:
261                 D_word(aNexten);
262                 // Deposit bd (if not suppressed)
263                 if ((aNexten&0x0030)==EXT_BDSIZE0)
264                 {
265                         // Don't deposit anything (suppressed)
266                 }
267                 else if ((aNexten&0x0030)==EXT_BDSIZEW)
268                 {
269                         // Deposit word bd
270                         if (wbd)
271                         {
272                                 // Just deposit it
273                                 if (tdb)
274                                         MarkRelocatable(cursect, sloc, tdbbd, MWORD, NULL);
275
276                                 if (vbd + 0x8000 >= 0x10000)
277                                         return error(range_error);
278
279                                 D_word(vbd);
280                         }
281                         else
282                         {
283                                 // Arrange for fixup later on
284                                 AddFixup(FU_WORD|FU_SEXT, sloc, aNexpr);
285                                 D_word(0);
286                         }
287                 }
288                 else
289                 {
290                         // Deposit long bd
291                         if (wbd)
292                         {
293                                 // Just deposit it
294                                 if (tdbbd)
295                                         MarkRelocatable(cursect, sloc, tdbbd, MLONG, NULL);
296
297                                 D_long(vbd);
298                         }
299                         else
300                         {
301                                 // Arrange for fixup later on
302                                 AddFixup(FU_LONG|FU_SEXT, sloc, aNexpr);
303                                 D_long(0);
304                         }
305                 }
306                 // Deposit od (if not suppressed)
307                 if ((aNexten&7)==EXT_IISPRE0 || (aNexten&7)==EXT_IISPREN
308                         || (aNexten&7)==EXT_IISNOIN || (aNexten&7)==EXT_IISPOSN)
309                 {
310                         // Don't deposit anything (suppressed)
311                 }
312                 else if ((aNexten&7)==EXT_IISPREW
313                         || (aNexten&7)==EXT_IISPOSW || (aNexten&7)==EXT_IISNOIW)
314                 {
315                         // Deposit word od
316                         if (w)
317                         {
318                                 // Just deposit it
319                                 if (tdb)
320                                         MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
321
322                                 if (v + 0x8000 >= 0x10000)
323                                         return error(range_error);
324
325                                 D_word(v);
326                         }
327                         else
328                         {
329                                 // Arrange for fixup later on
330                                 AddFixup(FU_WORD|FU_SEXT, sloc, aNexpr);
331                                 D_word(0);
332                         }
333                 }
334                 else
335                 {
336                         // Deposit long od
337                         if (w)
338                         {
339                                 // Just deposit it
340                                 if (tdb)
341                                         MarkRelocatable(cursect, sloc, tdb, MLONG, NULL);
342
343                                 D_long(v);
344                         }
345                         else
346                         {
347                                 // Arrange for fixup later on
348                                 AddFixup(FU_LONG|FU_SEXT, sloc, aNexpr);
349                                 D_long(0);
350                         }
351                 }
352
353                 break;
354                 //return error("unsupported 68020 addressing mode");
355         default:
356                 // Bad addressing mode in ea gen
357                 interror(3);
358         }
359
360         return OK;
361 }
362
363 // Undefine dirty macros
364 #undef eaNgen
365 #undef amN
366 #undef aNexattr
367 #undef aNexval
368 #undef aNexpr
369 #undef aNixreg
370 #undef aNixsiz
371 #undef aNexten
372 #undef aNbdexval
373 #undef aNbdexattr
374 #undef AnESYM
375