Removed -w flag, added +o[n], ~o[n] switches to control individual optimisations...
[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                                 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 (tdb)
183                                         rmark(cursect, sloc, tdb, MWORD, NULL);
184
185                                 if (v + 0x10000 >= 0x20000)
186                                         return error(range_error);
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                                         rmark(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 ABSW:
219                 if (w)
220                 {
221                         if (tdb)
222                                 rmark(cursect, sloc, tdb, MWORD, NULL);
223
224                         if (v + 0x8000 >= 0x10000)
225                                 return error(range_error);
226
227                         D_word(v);
228                 }
229                 else
230                 {
231                         AddFixup(FU_WORD|FU_SEXT, sloc, aNexpr);
232                         D_word(0);
233                 }
234
235                 break;
236         case ABSL:
237                 if (w)
238                 {
239                         if (tdb)
240                                 rmark(cursect, sloc, tdb, MLONG, NULL);
241
242                         D_long(v);
243                 }
244                 else
245                 {
246                         AddFixup(FU_LONG, sloc, aNexpr);
247                         D_long(0);
248                 }
249
250                 break;
251         case ABASE:
252         case MEMPOST:
253         case MEMPRE:
254         case PCBASE:
255         case PCMPOST:
256         case PCMPRE:
257                 return error("unsupported 68020 addressing mode");
258         default:
259                 // Bad addressing mode in ea gen 
260                 interror(3);
261         }
262
263         return OK;
264 }
265
266 // Undefine dirty macros
267 #undef eaNgen
268 #undef amN
269 #undef aNexattr
270 #undef aNexval
271 #undef aNexpr
272 #undef aNixreg
273 #undef aNixsiz
274