comparison src/insn_misc.c @ 0:57495da01900

Initial checking of LWASM
author lost
date Fri, 03 Oct 2008 02:44:20 +0000
parents
children 34568fab6058
comparison
equal deleted inserted replaced
-1:000000000000 0:57495da01900
1 /*
2 * insn_misc.c
3 *
4 * parsing miscelaneous addressing modes
5 */
6
7 #include <ctype.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include "lwasm.h"
11 #include "instab.h"
12
13 extern void insn_gen_aux(asmstate_t *as, sourceline_t *cl, char **optr, int *b1, int *b2, int *b3, int *op);
14
15 void insn_inh(asmstate_t *as, sourceline_t *cl, char **optr)
16 {
17 cl -> addrmode = OPER_INH;
18 emitop(instab[cl -> opcode].ops[0]);
19 }
20
21 void insn_rtor(asmstate_t *as, sourceline_t *cl, char **optr)
22 {
23 int r0, r1;
24 static const char *regs = "D X Y U S PCW V A B CCDP0 0 E F ";
25
26 cl -> addrmode = OPER_RTOR;
27 emitop(instab[cl -> opcode].ops[0]);
28 // register to register (r0,r1)
29 // registers are in order:
30 // D,X,Y,U,S,PC,W,V
31 // A,B,CC,DP,0,0,E,F
32 r0 = lookupreg(regs, optr);
33 if (r0 < 0 || *(*optr)++ != ',')
34 {
35 errorp1(ERR_BADOPER);
36 r0 = r1 = 0;
37 }
38 else
39 {
40 r1 = lookupreg(regs, optr);
41 if (r1 < 0)
42 {
43 errorp1(ERR_BADOPER);
44 r0=r1=0;
45 }
46 }
47 emit((r0 << 4) | r1);
48 }
49
50 void insn_rlist(asmstate_t *as, sourceline_t *cl, char **optr)
51 {
52 int rb = 0;
53 int rn;
54 static const char *regs = "CCA B DPX Y U PCD S ";
55
56 emitop(instab[cl -> opcode].ops[0]);
57 cl -> addrmode = OPER_RLIST;
58 while (**optr && !isspace(**optr))
59 {
60 rn = lookupreg(regs, optr);
61 if (rn < 0)
62 {
63 printf("Bad reg (%s)\n", *optr);
64 errorp1(ERR_BADOPER);
65 emit(0);
66 return;
67 }
68 if (**optr && **optr != ',' && !isspace(**optr))
69 {
70 printf("Bad char (%c)\n", **optr);
71 errorp1(ERR_BADOPER);
72 emit(0);
73 return;
74 }
75 if (**optr == ',')
76 (*optr)++;
77 if (rn == 8)
78 rn = 6;
79 else if (rn == 9)
80 rn = 0x40;
81 else
82 rn = 1 << rn;
83 rb |= rn;
84 }
85 emit(rb);
86 }
87
88 // for aim, oim, eim, tim
89 void insn_logicmem(asmstate_t *as, sourceline_t *cl, char **optr)
90 {
91 int rval, v1;
92 int b1, b2, b3, op;
93
94 if (**optr == '#')
95 (*optr)++;
96
97 rval = eval_expr(as, cl, optr, &v1);
98 if (rval < 0)
99 return;
100
101 if (v1 < -128 || v1 > 255)
102 {
103 errorp2(ERR_OVERFLOW);
104 v1 = 0;
105 }
106
107 if (**optr != ',' && **optr != ';')
108 {
109 errorp1(ERR_BADOPER);
110 return;
111 }
112
113 (*optr)++;
114
115 // now we have a general addressing mode - call for it
116 insn_gen_aux(as, cl, optr, &b1, &b2, &b3, &op);
117
118 emitop(op);
119 emit(v1 & 0xff);
120 if (b1 != -1)
121 {
122 emit(b1);
123 }
124 if (b2 != -1)
125 {
126 emit(b2);
127 }
128 if (b3 != -1)
129 {
130 emit(b3);
131 }
132 }
133
134 void insn_tfm(asmstate_t *as, sourceline_t *cl, char **optr)
135 {
136 static const char *reglist = "DXYUS AB 00EF";
137 int r0, r1;
138 char *c;
139 int tfm = 0;
140
141 cl -> addrmode = OPER_TFM;
142
143 c = strchr(reglist, toupper(*(*optr)++));
144 if (!c)
145 {
146 errorp1(ERR_BADOPER);
147 return;
148 }
149 r0 = c - reglist;
150 if (**optr == '+')
151 {
152 (*optr)++;
153 tfm = 1;
154 }
155 else if (**optr == '-')
156 {
157 (*optr)++;
158 tfm = 2;
159 }
160 if (*(*optr)++ != ',')
161 {
162 errorp1(ERR_BADOPER);
163 return;
164 }
165 c = strchr(reglist, toupper(*(*optr)++));
166 if (!c)
167 {
168 errorp1(ERR_BADOPER);
169 return;
170 }
171 r1 = c - reglist;
172
173 if (**optr == '+')
174 {
175 (*optr)++;
176 tfm |= 4;
177 }
178 else if (**optr == '-')
179 {
180 (*optr)++;
181 tfm |= 8;
182 }
183
184 if (**optr && !isspace(**optr))
185 {
186 errorp1(ERR_BADOPER);
187 return;
188 }
189
190 // valid values of tfm here are:
191 // 1: r0+,r1 (2)
192 // 4: r0,r1+ (3)
193 // 5: r0+,r1+ (0)
194 // 10: r0-,r1- (1)
195 switch (tfm)
196 {
197 case 5: //r0+,r1+
198 emitop(instab[cl -> opcode].ops[0]);
199 break;
200 case 10: //r0-,r1-
201 emitop(instab[cl -> opcode].ops[1]);
202 break;
203 case 1: // r0+,r1
204 emitop(instab[cl -> opcode].ops[2]);
205 break;
206 case 4: // r0,r1+
207 emitop(instab[cl -> opcode].ops[3]);
208 break;
209 default:
210 errorp1(ERR_BADOPER);
211 return;
212 }
213 emit((r0 << 4) | r1);
214 }
215
216 void insn_bitbit(asmstate_t *as, sourceline_t *cl, char **optr)
217 {
218 int r;
219 int rval;
220 int v1;
221 int tv;
222
223 emitop(instab[cl -> opcode].ops[0]);
224
225 cl -> addrmode = OPER_BITBIT;
226
227 r = toupper(*(*optr)++);
228 if (r == 'A')
229 r = 1;
230 else if (r == 'B')
231 r = 2;
232 else if (r == 'C' && toupper(**optr) == 'C')
233 {
234 r = 0;
235 (*optr)++;
236 }
237 else
238 {
239 errorp1(ERR_BADREG);
240 return;
241 }
242 if (*(*optr)++ != ',')
243 {
244 errorp1(ERR_BADOPER);
245 return;
246 }
247 rval = eval_expr(as, cl, optr, &v1);
248 if (v1 < 0 || v1 > 7)
249 {
250 errorp2(ERR_OVERFLOW3);
251 v1 = 0;
252 }
253 if (*(*optr)++ != ',')
254 {
255 errorp1(ERR_BADOPER);
256 return;
257 }
258 r = (r << 6) | (v1 << 3);
259 rval = eval_expr(as, cl, optr, &v1);
260 if (v1 < 0 || v1 > 7)
261 {
262 errorp2(ERR_OVERFLOW3);
263 v1 = 0;
264 }
265 if (*(*optr)++ != ',')
266 {
267 errorp1(ERR_BADOPER);
268 return;
269 }
270 r |= v1;
271
272 emit(r);
273
274 // ignore base page address modifier
275 if (**optr == '<')
276 optr++;
277
278 rval = eval_expr(as, cl, optr, &v1);
279 v1 &= 0xFFFF;
280 tv = v1 - ((cl -> dpval) << 8);
281 if (tv > 0xFF || tv < 0)
282 errorp2(ERR_OVERFLOW);
283 emit(tv & 0xff);
284 }
285
286 void insn_rel8(asmstate_t *as, sourceline_t *cl, char **optr)
287 {
288 int v1, rval;
289
290 emitop(instab[cl -> opcode].ops[0]);
291 cl -> addrmode = OPER_REL8;
292 rval = eval_expr(as, cl, optr, &v1);
293 v1 &= 0xFFFF;
294 v1 -= cl -> addr + 2;
295 if (v1 < -128 || v1 > 127)
296 errorp2(ERR_OVERFLOW);
297 v1 &= 0xFFFF;
298 emit(v1 & 0xff);
299 }
300
301 void insn_rel16(asmstate_t *as, sourceline_t *cl, char **optr)
302 {
303 int v1, rval;
304
305 emitop(instab[cl -> opcode].ops[0]);
306 cl -> addrmode = OPER_REL16;
307 rval = eval_expr(as, cl, optr, &v1);
308 v1 &= 0xFFFF;
309 v1 -= cl -> addr + 3;
310 if (instab[cl -> opcode].ops[0] > 0xff)
311 v1 -= 1;
312 v1 &= 0xFFFF;
313 emit(v1 >> 8);
314 emit(v1 & 0xff);
315 }