Mercurial > hg-old > index.cgi
annotate src/insn_misc.c @ 8:f1df096aa76f 1.1
Tagged 1.1 bugfix release
author | lost |
---|---|
date | Sun, 04 Jan 2009 05:46:07 +0000 |
parents | 34568fab6058 |
children | f736579569b4 |
rev | line source |
---|---|
0 | 1 /* |
4
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
2 insn_misc.c |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
3 Copyright © 2008 William Astle |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
4 |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
5 This file is part of LWASM. |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
6 |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
7 LWASM is free software: you can redistribute it and/or modify it under the |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
8 terms of the GNU General Public License as published by the Free Software |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
9 Foundation, either version 3 of the License, or (at your option) any later |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
10 version. |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
11 |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
12 This program is distributed in the hope that it will be useful, but WITHOUT |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
15 more details. |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
16 |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
17 You should have received a copy of the GNU General Public License along with |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
18 this program. If not, see <http://www.gnu.org/licenses/>. |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
19 |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
20 Contains code for parsing miscelaneous addressing modes |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
21 */ |
0 | 22 |
23 #include <ctype.h> | |
24 #include <stdio.h> | |
25 #include <string.h> | |
26 #include "lwasm.h" | |
27 #include "instab.h" | |
28 | |
29 extern void insn_gen_aux(asmstate_t *as, sourceline_t *cl, char **optr, int *b1, int *b2, int *b3, int *op); | |
30 | |
31 void insn_inh(asmstate_t *as, sourceline_t *cl, char **optr) | |
32 { | |
33 cl -> addrmode = OPER_INH; | |
34 emitop(instab[cl -> opcode].ops[0]); | |
35 } | |
36 | |
37 void insn_rtor(asmstate_t *as, sourceline_t *cl, char **optr) | |
38 { | |
39 int r0, r1; | |
40 static const char *regs = "D X Y U S PCW V A B CCDP0 0 E F "; | |
41 | |
42 cl -> addrmode = OPER_RTOR; | |
43 emitop(instab[cl -> opcode].ops[0]); | |
44 // register to register (r0,r1) | |
45 // registers are in order: | |
46 // D,X,Y,U,S,PC,W,V | |
47 // A,B,CC,DP,0,0,E,F | |
48 r0 = lookupreg(regs, optr); | |
49 if (r0 < 0 || *(*optr)++ != ',') | |
50 { | |
51 errorp1(ERR_BADOPER); | |
52 r0 = r1 = 0; | |
53 } | |
54 else | |
55 { | |
56 r1 = lookupreg(regs, optr); | |
57 if (r1 < 0) | |
58 { | |
59 errorp1(ERR_BADOPER); | |
60 r0=r1=0; | |
61 } | |
62 } | |
63 emit((r0 << 4) | r1); | |
64 } | |
65 | |
66 void insn_rlist(asmstate_t *as, sourceline_t *cl, char **optr) | |
67 { | |
68 int rb = 0; | |
69 int rn; | |
70 static const char *regs = "CCA B DPX Y U PCD S "; | |
71 | |
72 emitop(instab[cl -> opcode].ops[0]); | |
73 cl -> addrmode = OPER_RLIST; | |
74 while (**optr && !isspace(**optr)) | |
75 { | |
76 rn = lookupreg(regs, optr); | |
77 if (rn < 0) | |
78 { | |
79 printf("Bad reg (%s)\n", *optr); | |
80 errorp1(ERR_BADOPER); | |
81 emit(0); | |
82 return; | |
83 } | |
84 if (**optr && **optr != ',' && !isspace(**optr)) | |
85 { | |
86 printf("Bad char (%c)\n", **optr); | |
87 errorp1(ERR_BADOPER); | |
88 emit(0); | |
89 return; | |
90 } | |
91 if (**optr == ',') | |
92 (*optr)++; | |
93 if (rn == 8) | |
94 rn = 6; | |
95 else if (rn == 9) | |
96 rn = 0x40; | |
97 else | |
98 rn = 1 << rn; | |
99 rb |= rn; | |
100 } | |
101 emit(rb); | |
102 } | |
103 | |
104 // for aim, oim, eim, tim | |
105 void insn_logicmem(asmstate_t *as, sourceline_t *cl, char **optr) | |
106 { | |
107 int rval, v1; | |
108 int b1, b2, b3, op; | |
109 | |
110 if (**optr == '#') | |
111 (*optr)++; | |
112 | |
113 rval = eval_expr(as, cl, optr, &v1); | |
114 if (rval < 0) | |
115 return; | |
116 | |
117 if (v1 < -128 || v1 > 255) | |
118 { | |
119 errorp2(ERR_OVERFLOW); | |
120 v1 = 0; | |
121 } | |
122 | |
123 if (**optr != ',' && **optr != ';') | |
124 { | |
125 errorp1(ERR_BADOPER); | |
126 return; | |
127 } | |
128 | |
129 (*optr)++; | |
130 | |
131 // now we have a general addressing mode - call for it | |
132 insn_gen_aux(as, cl, optr, &b1, &b2, &b3, &op); | |
133 | |
134 emitop(op); | |
135 emit(v1 & 0xff); | |
136 if (b1 != -1) | |
137 { | |
138 emit(b1); | |
139 } | |
140 if (b2 != -1) | |
141 { | |
142 emit(b2); | |
143 } | |
144 if (b3 != -1) | |
145 { | |
146 emit(b3); | |
147 } | |
148 } | |
149 | |
150 void insn_tfm(asmstate_t *as, sourceline_t *cl, char **optr) | |
151 { | |
152 static const char *reglist = "DXYUS AB 00EF"; | |
153 int r0, r1; | |
154 char *c; | |
155 int tfm = 0; | |
156 | |
157 cl -> addrmode = OPER_TFM; | |
158 | |
159 c = strchr(reglist, toupper(*(*optr)++)); | |
160 if (!c) | |
161 { | |
162 errorp1(ERR_BADOPER); | |
163 return; | |
164 } | |
165 r0 = c - reglist; | |
166 if (**optr == '+') | |
167 { | |
168 (*optr)++; | |
169 tfm = 1; | |
170 } | |
171 else if (**optr == '-') | |
172 { | |
173 (*optr)++; | |
174 tfm = 2; | |
175 } | |
176 if (*(*optr)++ != ',') | |
177 { | |
178 errorp1(ERR_BADOPER); | |
179 return; | |
180 } | |
181 c = strchr(reglist, toupper(*(*optr)++)); | |
182 if (!c) | |
183 { | |
184 errorp1(ERR_BADOPER); | |
185 return; | |
186 } | |
187 r1 = c - reglist; | |
188 | |
189 if (**optr == '+') | |
190 { | |
191 (*optr)++; | |
192 tfm |= 4; | |
193 } | |
194 else if (**optr == '-') | |
195 { | |
196 (*optr)++; | |
197 tfm |= 8; | |
198 } | |
199 | |
200 if (**optr && !isspace(**optr)) | |
201 { | |
202 errorp1(ERR_BADOPER); | |
203 return; | |
204 } | |
205 | |
206 // valid values of tfm here are: | |
207 // 1: r0+,r1 (2) | |
208 // 4: r0,r1+ (3) | |
209 // 5: r0+,r1+ (0) | |
210 // 10: r0-,r1- (1) | |
211 switch (tfm) | |
212 { | |
213 case 5: //r0+,r1+ | |
214 emitop(instab[cl -> opcode].ops[0]); | |
215 break; | |
216 case 10: //r0-,r1- | |
217 emitop(instab[cl -> opcode].ops[1]); | |
218 break; | |
219 case 1: // r0+,r1 | |
220 emitop(instab[cl -> opcode].ops[2]); | |
221 break; | |
222 case 4: // r0,r1+ | |
223 emitop(instab[cl -> opcode].ops[3]); | |
224 break; | |
225 default: | |
226 errorp1(ERR_BADOPER); | |
227 return; | |
228 } | |
229 emit((r0 << 4) | r1); | |
230 } | |
231 | |
232 void insn_bitbit(asmstate_t *as, sourceline_t *cl, char **optr) | |
233 { | |
234 int r; | |
235 int rval; | |
236 int v1; | |
237 int tv; | |
238 | |
239 emitop(instab[cl -> opcode].ops[0]); | |
240 | |
241 cl -> addrmode = OPER_BITBIT; | |
242 | |
243 r = toupper(*(*optr)++); | |
244 if (r == 'A') | |
245 r = 1; | |
246 else if (r == 'B') | |
247 r = 2; | |
248 else if (r == 'C' && toupper(**optr) == 'C') | |
249 { | |
250 r = 0; | |
251 (*optr)++; | |
252 } | |
253 else | |
254 { | |
255 errorp1(ERR_BADREG); | |
256 return; | |
257 } | |
258 if (*(*optr)++ != ',') | |
259 { | |
260 errorp1(ERR_BADOPER); | |
261 return; | |
262 } | |
263 rval = eval_expr(as, cl, optr, &v1); | |
264 if (v1 < 0 || v1 > 7) | |
265 { | |
266 errorp2(ERR_OVERFLOW3); | |
267 v1 = 0; | |
268 } | |
269 if (*(*optr)++ != ',') | |
270 { | |
271 errorp1(ERR_BADOPER); | |
272 return; | |
273 } | |
274 r = (r << 6) | (v1 << 3); | |
275 rval = eval_expr(as, cl, optr, &v1); | |
276 if (v1 < 0 || v1 > 7) | |
277 { | |
278 errorp2(ERR_OVERFLOW3); | |
279 v1 = 0; | |
280 } | |
281 if (*(*optr)++ != ',') | |
282 { | |
283 errorp1(ERR_BADOPER); | |
284 return; | |
285 } | |
286 r |= v1; | |
287 | |
288 emit(r); | |
289 | |
290 // ignore base page address modifier | |
291 if (**optr == '<') | |
292 optr++; | |
293 | |
294 rval = eval_expr(as, cl, optr, &v1); | |
295 v1 &= 0xFFFF; | |
296 tv = v1 - ((cl -> dpval) << 8); | |
297 if (tv > 0xFF || tv < 0) | |
298 errorp2(ERR_OVERFLOW); | |
299 emit(tv & 0xff); | |
300 } | |
301 | |
302 void insn_rel8(asmstate_t *as, sourceline_t *cl, char **optr) | |
303 { | |
304 int v1, rval; | |
305 | |
306 emitop(instab[cl -> opcode].ops[0]); | |
307 cl -> addrmode = OPER_REL8; | |
308 rval = eval_expr(as, cl, optr, &v1); | |
309 v1 &= 0xFFFF; | |
310 v1 -= cl -> addr + 2; | |
311 if (v1 < -128 || v1 > 127) | |
312 errorp2(ERR_OVERFLOW); | |
313 v1 &= 0xFFFF; | |
314 emit(v1 & 0xff); | |
315 } | |
316 | |
317 void insn_rel16(asmstate_t *as, sourceline_t *cl, char **optr) | |
318 { | |
319 int v1, rval; | |
320 | |
321 emitop(instab[cl -> opcode].ops[0]); | |
322 cl -> addrmode = OPER_REL16; | |
323 rval = eval_expr(as, cl, optr, &v1); | |
324 v1 &= 0xFFFF; | |
325 v1 -= cl -> addr + 3; | |
326 if (instab[cl -> opcode].ops[0] > 0xff) | |
327 v1 -= 1; | |
328 v1 &= 0xFFFF; | |
329 emit(v1 >> 8); | |
330 emit(v1 & 0xff); | |
331 } |