Added floating point support to expression evaluator, introduced FLOAT token, fixup...
[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         uint32_t vbd, v = (uint32_t)aNexval;
13         WORD wbd, w = (WORD)(aNexattr & DEFINED);
14         WORD tdbbd, tdb = (WORD)(aNexattr & TDB);
15         vbd = (uint32_t)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) && CHECK_OPTS(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 -= (uint32_t)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 -= (uint32_t)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                 case SIZS:
213                         // 68881/68882/68040 only
214                         if (w)
215                         {
216                                 float vv;
217                                 if (tdb)
218                                         MarkRelocatable(cursect, sloc, tdb, MSINGLE, NULL);
219
220                                 vv = (float)v;
221
222                                 D_single(vv);
223                         }
224                         else
225                         {
226                                 float vv = 0;
227                                 AddFixup(FU_FLOATSING, sloc, aNexpr);
228
229                                 D_single(vv);
230                         }
231
232                 break;
233                 case SIZD:
234                         // 68881/68882/68040 only
235                         if (w)
236                         {
237                                 double vv;
238                                 unsigned long long vvv;
239                                 if (tdb)
240                                         MarkRelocatable(cursect, sloc, tdb, MDOUBLE, NULL);
241
242                                 // We want to store the IEE754 float into ram from a generic
243                                 // 32-bit int. First, convert it to double float, then cast
244                                 // that to 64-bit, then convert to big endian (if needed)
245                                 // and then store it (phew!)
246                                 vv = *(float *)&aNexval;
247                                 vvv = BYTESWAP64(*(unsigned long long *)&vv);
248
249                                 D_double(vvv);
250                         }
251                         else
252                         {
253                                 unsigned long long vvv = 0;
254                                 AddFixup(FU_FLOATDOUB, sloc, aNexpr);
255
256                                 D_double(vvv);
257                         }
258
259                         break;
260                 case SIZX:
261                         // 68881/68882/68040 only
262                         if (w)
263                         {
264                                 long double vv;
265                                 if (tdb)
266                                         MarkRelocatable(cursect, sloc, tdb, MEXTEND, NULL);
267
268                                 // We want to store the IEE754 float into ram from a generic
269                                 // 32-bit int. First, convert it to double float, then cast
270                                 // that to 96-bit, then convert to big endian (if needed)
271                                 // and then store it (phew!)
272                                 vv = (double)aNexval;
273
274                                 //*chptr++ = (char)((*(unsigned long long *)&vv) >> 32) | 0x80 /* assume that the number is normalised */;
275                                 D_extend(vv);
276                         }
277                         else
278                         {
279                                 long double vvv = 0;
280                                 AddFixup(FU_FLOATDOUB, sloc, aNexpr);
281
282                                 D_extend(vvv);
283                         }
284
285                         break;
286                 default:
287                         // IMMED size problem
288                         interror(1);
289                 }
290
291                 break;
292     case SIZP:
293                 // 68881/68882/68040 only
294                 return error("Sorry, .p constant format is not implemented yet!");
295                 break;
296         case ABSW:
297                 if (w) // Defined
298                 {
299                         if (tdb)
300                                 MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
301
302                         if (v + 0x8000 >= 0x10000)
303                                 return error(range_error);
304
305                         D_word(v);
306                 }
307                 else
308                 {
309                         AddFixup(FU_WORD | FU_SEXT, sloc, aNexpr);
310                         D_word(0);
311                 }
312
313                 break;
314         case ABSL:
315                 if (w) // Defined
316                 {
317                         if (tdb)
318                                 MarkRelocatable(cursect, sloc, tdb, MLONG, NULL);
319
320                         D_long(v);
321                 }
322                 else
323                 {
324                         AddFixup(FU_LONG, sloc, aNexpr);
325                         D_long(0);
326                 }
327
328                 break;
329         case DINDW:
330                 D_word((0x190 | (aNixreg << 12)));
331                 break;
332         case DINDL:
333                 D_word((0x990 | (aNixreg << 12)));
334                 break;
335         case ABASE:
336         case MEMPOST:
337         case MEMPRE:
338         case PCBASE:
339         case PCMPOST:
340         case PCMPRE:
341                 D_word(aNexten);
342                 // Deposit bd (if not suppressed)
343                 if ((aNexten & 0x0030) == EXT_BDSIZE0)
344                 {
345                         // Don't deposit anything (suppressed)
346                 }
347                 else if ((aNexten & 0x0030) == EXT_BDSIZEW)
348                 {
349                         // Deposit word bd
350                         if (wbd)
351                         {
352                                 // Just deposit it
353                                 if (tdb)
354                                         MarkRelocatable(cursect, sloc, tdbbd, MWORD, NULL);
355
356                                 if (vbd + 0x8000 >= 0x10000)
357                                         return error(range_error);
358
359                                 D_word(vbd);
360                         }
361                         else
362                         {
363                                 // Arrange for fixup later on
364                                 AddFixup(FU_WORD|FU_SEXT, sloc, aNbexpr);
365                                 D_word(0);
366                         }
367                 }
368                 else
369                 {
370                         // Deposit long bd
371                         if (wbd)
372                         {
373                                 // Just deposit it
374                                 if (tdbbd)
375                                         MarkRelocatable(cursect, sloc, tdbbd, MLONG, NULL);
376
377                                 D_long(vbd);
378                         }
379                         else
380                         {
381                                 // Arrange for fixup later on
382                                 AddFixup(FU_LONG, sloc, aNbexpr);
383                                 D_long(0);
384                         }
385                 }
386                 // Deposit od (if not suppressed)
387                 if ((aNexten&7)==EXT_IISPRE0 || (aNexten&7)==EXT_IISPREN
388                         || (aNexten&7)==EXT_IISNOIN || (aNexten&7)==EXT_IISPOSN)
389                 {
390                         // Don't deposit anything (suppressed)
391                 }
392                 else if ((aNexten&7)==EXT_IISPREW
393                         || (aNexten&7)==EXT_IISPOSW || (aNexten&7)==EXT_IISNOIW)
394                 {
395                         // Deposit word od
396                         if (w)
397                         {
398                                 // Just deposit it
399                                 if (tdb)
400                                         MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
401
402                                 if (v + 0x8000 >= 0x10000)
403                                         return error(range_error);
404
405                                 D_word(v);
406                         }
407                         else
408                         {
409                                 // Arrange for fixup later on
410                                 AddFixup(FU_WORD|FU_SEXT, sloc, aNexpr);
411                                 D_word(0);
412                         }
413                 }
414                 else
415                 {
416                         // Deposit long od
417                         if (w)
418                         {
419                                 // Just deposit it
420                                 if (tdb)
421                                         MarkRelocatable(cursect, sloc, tdb, MLONG, NULL);
422
423                                 D_long(v);
424                         }
425                         else
426                         {
427                                 // Arrange for fixup later on
428                                 AddFixup(FU_LONG|FU_SEXT, sloc, aNexpr);
429                                 D_long(0);
430                         }
431                 }
432
433                 break;
434                 //return error("unsupported 68020 addressing mode");
435         default:
436                 // Bad addressing mode in ea gen
437                 interror(3);
438         }
439
440         return OK;
441 }
442
443 // Undefine dirty macros
444 #undef eaNgen
445 #undef amN
446 #undef aNexattr
447 #undef aNexval
448 #undef aNexpr
449 #undef aNixreg
450 #undef aNixsiz
451 #undef aNexten
452 #undef aNbexpr
453 #undef aNbdexval
454 #undef aNbdexattr
455 #undef AnESYM
456