Fixed subtle bug in expr().
[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         case DREG:                                            // "Do nothing" - they're in the opword
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                 break;                                             // This is a performance hit, though
32         case ADISP:                                           // expr(An)
33                 if (w)
34                 {                                            // Just deposit it 
35                         if (tdb)
36                                 rmark(cursect, sloc, tdb, MWORD, NULL);
37
38                         if (v + 0x8000 >= 0x18000)
39                                 return error(range_error);
40
41                         D_word(v);
42                 }
43                 else
44                 {                                           // Arrange for fixup later on 
45                         fixup(FU_WORD|FU_SEXT, sloc, aNexpr);
46                         D_word(0);
47                 }
48
49                 break;
50         case PCDISP:
51                 if (w)
52                 {                                            // Just deposit it 
53                         if ((aNexattr & TDB) == cursect)
54                                 v -= (VALUE)sloc;
55                         else if ((aNexattr & TDB) != ABS)
56                                 error(rel_error);
57
58                         if (v + 0x8000 >= 0x10000)
59                                 return error(range_error);
60
61                         D_word(v);
62                 }
63                 else
64                 {                                           // Arrange for fixup later on 
65                         fixup(FU_WORD|FU_SEXT|FU_PCREL, sloc, aNexpr);
66                         D_word(0);
67                 }
68
69                 break;
70         case AINDEXED:
71                 w = (WORD)((aNixreg << 12) | aNixsiz);             // Compute ixreg and size+scale
72
73                 if (aNexattr & DEFINED)
74                 {                           // Deposit a byte... 
75                         if (tdb)
76                                 return error(abs_error);                    // Can't mark bytes 
77
78                         if (v + 0x80 >= 0x180)
79                                 return error(range_error);
80
81                         w |= v & 0xff;
82                         D_word(w);
83                 }
84                 else
85                 {                                           // Fixup the byte later
86                         fixup(FU_BYTE|FU_SEXT, sloc+1, aNexpr);
87                         D_word(w);
88                 }
89
90                 break;
91         case PCINDEXED:
92                 w = (WORD)((aNixreg << 12) | aNixsiz);             // Compute ixreg and size+scale
93
94                 if (aNexattr & DEFINED)
95                 {                           // Deposit a byte... 
96                         if ((aNexattr & TDB) == cursect) 
97                                 v -= (VALUE)sloc;
98                         else if ((aNexattr & TDB) != ABS)
99                                 error(rel_error);
100
101                         if (v + 0x80 >= 0x100)
102                                 return error(range_error);
103
104                         w |= v & 0xff;
105                         D_word(w);
106                 }
107                 else
108                 {                                           // Fixup the byte later 
109                         fixup(FU_WBYTE|FU_SEXT|FU_PCREL, sloc, aNexpr);
110                         D_word(w);
111                 }
112
113                 break;
114         case IMMED:
115                 switch (siz)
116                 {
117                 case SIZB:
118                         if (w)
119                         {
120                                 if (tdb)
121                                         return error("illegal byte-sized relative reference");
122
123                                 if (v + 0x100 >= 0x200)
124                                         return error(range_error);
125
126                                 D_word(v);
127                         }
128                         else
129                         {
130                                 fixup(FU_BYTE|FU_SEXT, sloc+1, aNexpr);
131                                 D_word(0);
132                         }
133
134                         break;
135                 case SIZW:
136                 case SIZN:
137                         if (w)
138                         {
139                                 if (tdb)
140                                         rmark(cursect, sloc, tdb, MWORD, NULL);
141
142                                 if (v + 0x10000 >= 0x20000)
143                                         return error(range_error);
144
145                                 D_word(v);
146                         }
147                         else
148                         {
149                                 fixup(FU_WORD|FU_SEXT, sloc, aNexpr);
150                                 D_word(0);
151                         }
152
153                         break;
154                 case SIZL:
155                         if (w)
156                         {
157                                 if (tdb)
158                                         rmark(cursect, sloc, tdb, MLONG, NULL);
159
160                                 D_long(v);
161                         }
162                         else
163                         {
164                                 fixup(FU_LONG, sloc, aNexpr);
165                                 D_long(0);
166                         }
167
168                         break;
169                 default:
170                         interror(1);                                 // IMMED size problem
171                 }
172
173                 break;
174         case ABSW:
175                 if (w)
176                 {
177                         if (tdb)
178                                 rmark(cursect, sloc, tdb, MWORD, NULL);
179
180                         if (v + 0x8000 >= 0x10000)
181                                 return error(range_error);
182
183                         D_word(v);
184                 }
185                 else
186                 {
187                         fixup(FU_WORD|FU_SEXT, sloc, aNexpr);
188                         D_word(0);
189                 }
190
191                 break;
192         case ABSL:
193                 if (w)
194                 {
195                         if (tdb)
196                                 rmark(cursect, sloc, tdb, MLONG, NULL);
197
198                         D_long(v);
199                 }
200                 else
201                 {
202                         fixup(FU_LONG, sloc, aNexpr);
203                         D_long(0);
204                 }
205
206                 break;
207         case ABASE:
208         case MEMPOST:
209         case MEMPRE:
210         case PCBASE:
211         case PCMPOST:
212         case PCMPRE:
213                 return error("unsupported 68020 addressing mode");
214         default:
215                 interror(3);                                       // Bad addressing mode in ea gen 
216         }
217
218         return OK;
219 }
220
221 // Undefine dirty macros
222 #undef eaNgen
223 #undef amN
224 #undef aNexattr
225 #undef aNexval
226 #undef aNexpr
227 #undef aNixreg
228 #undef aNixsiz