Mercurial > hg-old > index.cgi
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 } |