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