Mercurial > hg-old > index.cgi
annotate lwasm/insn_indexed.c @ 212:bae1e3ecdce1
More preparation for gnulib integration
author | lost |
---|---|
date | Fri, 24 Apr 2009 06:43:02 +0000 |
parents | 427e268e876b |
children | 0df2a39a268c |
rev | line source |
---|---|
32 | 1 /* |
2 insn_indexed.c | |
33
74a3fef7c8d0
Added general addressing modes (immediate, base page, extended, indexed)
lost
parents:
32
diff
changeset
|
3 Copyright © 2009 William Astle |
32 | 4 |
5 This file is part of LWASM. | |
6 | |
7 LWASM is free software: you can redistribute it and/or modify it under the | |
8 terms of the GNU General Public License as published by the Free Software | |
9 Foundation, either version 3 of the License, or (at your option) any later | |
10 version. | |
11 | |
12 This program is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
15 more details. | |
16 | |
17 You should have received a copy of the GNU General Public License along with | |
18 this program. If not, see <http://www.gnu.org/licenses/>. | |
19 */ | |
20 | |
21 /* | |
22 for handling indexed mode instructions | |
23 */ | |
24 | |
25 #define __insn_indexed_c_seen__ | |
26 | |
212 | 27 #include <config.h> |
28 | |
32 | 29 #include <ctype.h> |
30 #include <string.h> | |
31 | |
32 #include "lwasm.h" | |
33 #include "instab.h" | |
34 #include "expr.h" | |
35 | |
36 void insn_indexed_aux(asmstate_t *as, lwasm_line_t *l, const char **p, int *b1, int *b2, int *b3) | |
37 { | |
38 static const char *regs = "X Y U S W PCRPC "; | |
39 static const struct { char *opstr; int pb; } simpleindex[] = | |
40 { | |
41 {",x", 0x84}, {",y", 0xa4}, {",u", 0xc4}, {",s", 0xe4}, | |
42 {",x+", 0x80}, {",y+", 0xa0}, {",u+", 0xc0}, {",s+", 0xe0}, | |
43 {",x++", 0x81}, {",y++", 0xa1}, {",u++", 0xc1}, {",s++", 0xe1}, | |
44 {",-x", 0x82}, {",-y", 0xa2}, {",-u", 0xc2}, {",-s", 0xe2}, | |
45 {",--x", 0x83}, {",--y", 0xa3}, {",--u", 0xc3}, {",--s", 0xe3}, | |
46 {"a,x", 0x86}, {"a,y", 0xa6}, {"a,u", 0xc6}, {"a,s", 0xe6}, | |
47 {"b,x", 0x85}, {"b,y", 0xa5}, {"b,u", 0xc5}, {"b,s", 0xe5}, | |
48 {"e,x", 0x87}, {"e,y", 0xa7}, {"e,u", 0xc7}, {"e,s", 0xe7}, | |
49 {"f,x", 0x8a}, {"f,y", 0xaa}, {"f,u", 0xca}, {"f,s", 0xea}, | |
50 {"d,x", 0x8b}, {"d,y", 0xab}, {"d,u", 0xcb}, {"d,s", 0xed}, | |
51 {"w,x", 0x8e}, {"w,y", 0xae}, {"w,u", 0xce}, {"w,s", 0xee}, | |
52 {",w", 0x8f}, {",w++", 0xcf}, {",--w", 0xef}, | |
53 | |
54 {"[,x]", 0x94}, {"[,y]", 0xb4}, {"[,u", 0xd4}, {"[,s]", 0xf4}, | |
55 {"[,x++]", 0x91}, {"[,y++]", 0xb1}, {"[,u++]", 0xd1}, {"[,s++]", 0xf1}, | |
56 {"[,--x]", 0x93}, {"[,--y]", 0xb3}, {"[,--u]", 0xd3}, {"[,--s]", 0xf3}, | |
57 {"[a,x]", 0x96}, {"[a,y]", 0xb6}, {"[a,u]", 0xd6}, {"[a,s]", 0xf6}, | |
58 {"[b,x]", 0x95}, {"[b,y]", 0xb5}, {"[b,u]", 0xd5}, {"[b,s]", 0xf5}, | |
59 {"[e,x]", 0x97}, {"[e,y]", 0xb7}, {"[e,u]", 0xd7}, {"[e,s]", 0xf7}, | |
60 {"[f,x]", 0x9a}, {"[f,y]", 0xba}, {"[f,u]", 0xda}, {"[f,s]", 0xfa}, | |
61 {"[d,x]", 0x9b}, {"[d,y]", 0xbb}, {"[d,u]", 0xdb}, {"[d,s]", 0xfd}, | |
62 {"[w,x]", 0x9e}, {"[w,y]", 0xbe}, {"[w,u]", 0xde}, {"[w,s]", 0xfe}, | |
63 {"[,w]", 0x90}, {"[,w++]", 0xd0}, {"[,--w]", 0xf0}, | |
64 | |
65 { "", -1 } | |
66 }; | |
67 char stbuf[25]; | |
81 | 68 int i, j, rn; |
69 int f8 = 0, f16 = 0, f0 = 0; | |
70 int r, v; | |
32 | 71 int indir = 0; |
101
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
72 int fs8 = 0, fs16 = 0; |
81 | 73 |
74 // initialize output bytes | |
32 | 75 *b1 = *b2 = *b3 = -1; |
76 | |
81 | 77 // fetch out operand for lookup |
32 | 78 for (i = 0; i < 24; i++) |
79 { | |
80 if (*((*p) + i) && !isspace(*((*p) + i))) | |
81 stbuf[i] = *((*p) + i); | |
82 else | |
83 break; | |
84 } | |
85 stbuf[i] = '\0'; | |
81 | 86 |
87 // now look up operand in "simple" table | |
32 | 88 if (!*((*p) + i) || isspace(*((*p) + i))) |
89 { | |
90 // do simple lookup | |
91 for (j = 0; simpleindex[j].opstr[0]; j++) | |
92 { | |
93 if (!strcasecmp(stbuf, simpleindex[j].opstr)) | |
94 break; | |
95 } | |
96 if (simpleindex[j].opstr[0]) | |
97 { | |
98 *b1 = simpleindex[j].pb; | |
99 (*p) += i; | |
100 return; | |
101 } | |
102 } | |
81 | 103 |
104 // now do the "hard" ones | |
105 | |
106 // is it indirect? | |
32 | 107 if (**p == '[') |
108 { | |
109 indir = 1; | |
110 (*p)++; | |
111 } | |
112 | |
81 | 113 // look for a "," - all indexed modes have a "," except extended indir |
32 | 114 rn = 0; |
115 for (i = 0; (*p)[i] && !isspace((*p)[i]); i++) | |
116 { | |
117 if ((*p)[i] == ',') | |
118 { | |
119 rn = 1; | |
120 break; | |
121 } | |
122 } | |
81 | 123 |
124 // if no "," and indirect, do extended indir | |
32 | 125 if (!rn && indir) |
126 { | |
127 // extended indir | |
128 *b1 = 0x9f; | |
129 *b2 = 0; | |
130 *b3 = 0; | |
81 | 131 r = lwasm_expr_result2(as, l, (char **)p, 0, &v, 0); |
132 if (r < 0) | |
32 | 133 { |
134 return; | |
135 } | |
136 if (**p != ']') | |
137 { | |
138 register_error(as, l, 1, "Bad operand"); | |
139 return; | |
140 } | |
81 | 141 |
32 | 142 (*p)++; |
81 | 143 |
144 if (r == 1 && as -> passnum == 2) | |
32 | 145 { |
81 | 146 l -> relocoff = as -> addr - l -> codeaddr + 1; |
32 | 147 } |
81 | 148 |
149 *b2 = (v >> 8) & 0xff; | |
150 *b3 = v & 0xff; | |
32 | 151 return; |
152 } | |
153 | |
81 | 154 // if we've previously forced the offset size, make a note of it |
155 if (l -> fsize == 1) | |
156 f8 = 1; | |
157 else if (l -> fsize == 2) | |
158 f16 = 1; | |
159 | |
32 | 160 if (**p == '<') |
161 { | |
101
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
162 fs8 = 1; |
32 | 163 (*p)++; |
164 } | |
165 else if (**p == '>') | |
166 { | |
101
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
167 fs16 = 1; |
32 | 168 (*p)++; |
169 } | |
170 | |
171 if (**p == '0' && *(*p+1) == ',') | |
172 { | |
173 f0 = 1; | |
174 } | |
175 | |
176 // now we have to evaluate the expression | |
81 | 177 r = lwasm_expr_result2(as, l, (char **)p, 0, &v, 0); |
178 if (r < 0) | |
32 | 179 { |
180 return; | |
181 } | |
182 // now look for a comma; if not present, explode | |
183 if (*(*p)++ != ',') | |
184 { | |
185 // syntax error; force 0 bit | |
186 *b1 = 00; | |
81 | 187 l -> fsize = 0; |
32 | 188 return; |
189 } | |
190 | |
191 // now get the register | |
192 rn = lwasm_lookupreg3(regs, p); | |
193 if (rn < 0) | |
81 | 194 { |
195 *b1 = 0; | |
196 l -> fsize = 0; | |
197 register_error(as, l, 1, "Bad register"); | |
198 return; | |
199 } | |
200 | |
32 | 201 if (indir) |
202 { | |
203 if (**p != ']') | |
81 | 204 { |
205 register_error(as, l, 1, "Bad operand"); | |
206 l -> fsize = 0; | |
207 *b1 = 0; | |
208 return; | |
209 } | |
32 | 210 else |
211 (*p)++; | |
212 } | |
213 | |
81 | 214 // incomplete reference on pass 1 forces 16 bit |
215 if (r == 1 && as -> passnum == 1) | |
216 { | |
217 f16 = 1; | |
218 l -> fsize = 2; | |
219 } | |
220 | |
221 // incomplete reference on pass 2 needs relocoff set | |
222 if (r == 1 && as -> passnum == 2) | |
223 { | |
224 l -> relocoff = as -> addr - l -> codeaddr + 1; | |
225 } | |
226 | |
227 // nnnn,W is only 16 bit (or 0 bit) | |
32 | 228 if (rn == 4) |
229 { | |
230 if (f8) | |
81 | 231 { |
232 register_error(as, l, 1, "n,W cannot be 8 bit"); | |
233 l -> fsize = 0; | |
234 *b1 = 0; | |
235 return; | |
236 } | |
237 // note: set f16 above for incomplete references | |
238 // also set reloc offset | |
239 if (!f16 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE) && v == 0) | |
32 | 240 { |
241 if (indir) | |
242 *b1 = 0x90; | |
243 else | |
244 *b1 = 0x8f; | |
245 return; | |
246 } | |
81 | 247 |
32 | 248 if (indir) |
249 *b1 = 0xb0; | |
250 else | |
251 *b1 = 0xcf; | |
81 | 252 *b2 = (v >> 8) & 0xff; |
253 *b3 = v & 0xff; | |
32 | 254 return; |
255 } | |
256 | |
81 | 257 // set indir to correct bit value |
32 | 258 if (indir) indir = 0x10; |
259 | |
81 | 260 // PCR? then we have PC relative addressing (like B??, LB??) |
32 | 261 if (rn == 5) |
262 { | |
101
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
263 lwasm_expr_term_t *t; |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
264 // external references are handled exactly the same as for |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
265 // relative addressing modes |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
266 // on pass 1, adjust the expression for a subtraction of the |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
267 // current address |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
268 |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
269 // need to re-evaluate the expression with "SECTCONST"... |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
270 r = lwasm_expr_result2(as, l, (char **)p, EXPR_SECTCONST | EXPR_REEVAL, &v, 0); |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
271 if (r != 0) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
272 v = 0; |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
273 if (as -> passnum == 1) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
274 { |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
275 l -> fsize = 0; |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
276 } |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
277 f8 = f16 = 0; |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
278 if (r == 1 && as -> passnum == 1 && !fs8) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
279 { |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
280 l -> fsize = 2; |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
281 f16 = 1; |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
282 } |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
283 if (fs8) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
284 f8 = 1; |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
285 if (fs16) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
286 f16 = 1; |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
287 if (l -> fsize == 2) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
288 f16 = 1; |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
289 else if (l -> fsize == 1) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
290 f8 = 1; |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
291 if (as -> passnum == 1) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
292 v -= as -> addr; |
32 | 293 |
294 // we have a slight problem here | |
295 // PCR based on current insn loc is really | |
296 // -125 <= offset <= +130 (8 bit offset) | |
297 // NOTE: when we are called, we already have the opcode emitted | |
298 // so we only need to worry about the size of the operand | |
299 // hence the 2 and 3 magic numbers below instead of 3 and 4 | |
300 // (and that also avoids errors with two byte opcodes, etc) | |
81 | 301 if (f8 || (!f16 && v >= -125 && v <= 130)) |
32 | 302 { |
101
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
303 f8 = 1; |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
304 l -> fsize = 1; |
32 | 305 *b1 = indir | 0x8C; |
101
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
306 if (as -> passnum == 1) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
307 v -= 2; |
81 | 308 if (v < -128 || v > 127) |
32 | 309 register_error(as, l, 2, "Byte overflow"); |
81 | 310 *b2 = v & 0xff; |
101
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
311 if (r != 0 && as -> passnum == 2) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
312 { |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
313 register_error(as, l, 2, "Illegal incomplete reference"); |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
314 } |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
315 goto finpcr; |
32 | 316 } |
317 | |
318 // anything else is 16 bit offset | |
319 // need 16 bit | |
101
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
320 |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
321 l -> fsize = 2; |
32 | 322 *b1 = indir | 0x8D; |
101
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
323 if (as -> passnum == 1) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
324 v -= 3; |
81 | 325 *b2 = (v >> 8) & 0xff; |
326 *b3 = v & 0xff; | |
101
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
327 if (as -> passnum == 2 && r == 1) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
328 { |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
329 t = lwasm_expr_term_create_secbase(); |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
330 lwasm_expr_stack_push(l -> exprs[0], t); |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
331 lwasm_expr_term_free(t); |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
332 t = lwasm_expr_term_create_oper(LWASM_OPER_MINUS); |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
333 lwasm_expr_stack_push(l -> exprs[0], t); |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
334 lwasm_expr_term_free(t); |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
335 } |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
336 |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
337 finpcr: |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
338 if (as -> passnum == 1) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
339 { |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
340 // need to adjust the expression |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
341 if (l -> exprs[0]) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
342 { |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
343 t = lwasm_expr_term_create_int(as -> addr + (f8 ? 2 : 3)); |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
344 lwasm_expr_stack_push(l -> exprs[0], t); |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
345 lwasm_expr_term_free(t); |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
346 t = lwasm_expr_term_create_oper(LWASM_OPER_MINUS); |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
347 lwasm_expr_stack_push(l -> exprs[0], t); |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
348 lwasm_expr_term_free(t); |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
349 } |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
350 else |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
351 { |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
352 l -> exprvals[0] -= as -> addr + (f8 ? 2 : 3); |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
353 } |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
354 } |
32 | 355 return; |
356 } | |
101
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
357 if (fs16) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
358 f16 = 1; |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
359 if (fs8) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
360 f8 = 1; |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
361 |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
362 if (f8 && r != 0) |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
363 { |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
364 register_error(as, l, 2, "Illegal external or inter-section reference"); |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
365 r = 0; |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
366 v = 0; |
f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
lost
parents:
84
diff
changeset
|
367 } |
32 | 368 |
81 | 369 // constant offset from PC (using PC as regular register :) ) |
370 // FIXME: handle external references intelligently | |
32 | 371 if (rn == 6) |
372 { | |
81 | 373 if (f8 || (!f16 && v >= -128 && v <= 127)) |
32 | 374 { |
375 *b1 = indir | 0x8C; | |
81 | 376 if (v < -128 || v > 127) |
32 | 377 register_error(as, l, 2, "Byte overflow"); |
81 | 378 *b2 = v & 0xff; |
32 | 379 return; |
380 } | |
381 | |
382 // everything else must be 16 bit | |
383 // need 16 bit | |
384 *b1 = indir | 0x8D; | |
81 | 385 *b2 = (v >> 8) & 0xff; |
386 *b3 = v & 0xff; | |
32 | 387 return; |
388 } | |
389 | |
390 // we only have to deal with x,y,u,s here | |
81 | 391 if (!f8 && !f16 && v >= -16 && v <= 15) |
32 | 392 { |
81 | 393 // zero offset going to ,R? |
394 if (v == 0 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE)) | |
32 | 395 { |
396 *b1 = rn << 5 | indir | 0x80 | 0x04; | |
397 return; | |
398 } | |
81 | 399 |
400 // no 5 bit on indirect | |
32 | 401 if (indir) |
402 { | |
403 f8 = 1; | |
81 | 404 l -> fsize = 1; |
32 | 405 goto no5bit; |
406 } | |
81 | 407 |
408 // 5 bit addressing | |
409 *b1 = rn << 5 | (v & 0x1F); | |
32 | 410 return; |
411 } | |
81 | 412 |
32 | 413 no5bit: |
81 | 414 if (f16 || (!f8 && (v < -128 || v > 127))) |
32 | 415 { |
416 // must be a 16 bit offset here | |
417 *b1 = rn << 5 | indir | 0x80 | 0x09; | |
81 | 418 *b2 = (v >> 8) & 0xff; |
419 *b3 = v & 0xff; | |
32 | 420 return; |
421 } | |
422 | |
423 // if we're here, we have an 8 bit offset | |
81 | 424 // note: cannot get here if incomplete reference detected above |
32 | 425 *b1 = rn << 5 | indir | 0x80 | 0x08; |
81 | 426 if (v < -128 || v > 127) |
32 | 427 register_error(as, l, 2, "Byte overflow"); |
81 | 428 *b2 = v & 0xff; |
32 | 429 return; |
430 } | |
431 | |
432 OPFUNC(insn_indexed) | |
433 { | |
434 int b1, b2, b3; | |
435 | |
436 lwasm_emitop(as, l, instab[opnum].ops[0]); | |
437 | |
438 insn_indexed_aux(as, l, (const char **)p, &b1, &b2, &b3); | |
439 if (b1 != -1) | |
440 lwasm_emit(as, l, b1); | |
441 if (b2 != -1) | |
442 lwasm_emit(as, l, b2); | |
443 if (b3 != -1) | |
444 lwasm_emit(as, l, b3); | |
445 } |