Mercurial > hg-old > index.cgi
comparison lwasm/insn_gen.c @ 151:427e268e876b
renamed src to lwasm to better reflect its purpose
author | lost |
---|---|
date | Fri, 30 Jan 2009 04:01:55 +0000 |
parents | src/insn_gen.c@81fc353d4d69 |
children | 2e6a1e914104 |
comparison
equal
deleted
inserted
replaced
150:f0881c115010 | 151:427e268e876b |
---|---|
1 /* | |
2 insn_gen.c, Copyright © 2009 William Astle | |
3 | |
4 This file is part of LWASM. | |
5 | |
6 LWASM is free software: you can redistribute it and/or modify it under the | |
7 terms of the GNU General Public License as published by the Free Software | |
8 Foundation, either version 3 of the License, or (at your option) any later | |
9 version. | |
10 | |
11 This program is distributed in the hope that it will be useful, but WITHOUT | |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
14 more details. | |
15 | |
16 You should have received a copy of the GNU General Public License along with | |
17 this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | |
19 Contains code for parsing general addressing modes (IMM+DIR+EXT+IND) | |
20 */ | |
21 | |
22 #include <ctype.h> | |
23 #include <stdlib.h> | |
24 | |
25 #include "lwasm.h" | |
26 #include "instab.h" | |
27 #include "expr.h" | |
28 | |
29 extern void insn_indexed_aux(asmstate_t *as, lwasm_line_t *l, const char **p, int *b1, int *b2, int *b3); | |
30 | |
31 // "extra" is required due to the way OIM, EIM, TIM, and AIM work | |
32 void insn_gen_aux(asmstate_t *as, lwasm_line_t *l, char **optr, int opnum, int extra) | |
33 { | |
34 int b1 = -1, b2 = -1, b3 = -1; | |
35 | |
36 const char *optr2; | |
37 int v1, tv, rval; | |
38 lwasm_expr_stack_t *s; | |
39 int f8 = 0; | |
40 int f16 = 0; | |
41 int isdp = 0; | |
42 | |
43 optr2 = *optr; | |
44 while (*optr2 && !isspace(*optr2) && *optr2 != ',') optr2++ | |
45 /* do nothing */ ; | |
46 | |
47 if (*optr2 != ',' && **optr != '[') | |
48 { | |
49 // not indexed | |
50 if (l -> fsize == 1) | |
51 f8 = 1; | |
52 else if (l -> fsize == 2) | |
53 f16 = 1; | |
54 | |
55 if (**optr == '<') | |
56 { | |
57 (*optr)++; | |
58 f8 = 1; | |
59 } | |
60 else if (**optr == '>') | |
61 { | |
62 (*optr)++; | |
63 f16 = 1; | |
64 } | |
65 rval = lwasm_expr_result2(as, l, optr, 0, &v1, 0); | |
66 if (rval != 0) | |
67 { | |
68 f16 = 1; | |
69 v1 = 0; | |
70 l -> fsize = 2; | |
71 } | |
72 | |
73 if (((v1 >> 8) & 0xff) == (as -> dpval & 0xff)) | |
74 isdp = 1; | |
75 | |
76 // disallow non-explicit DP in obj target | |
77 if (as -> outformat == OUTPUT_OBJ && !f8) | |
78 f16 = 1; | |
79 | |
80 if (f8 || (!f16 && isdp)) | |
81 { | |
82 v1 = v1 & 0xffff; | |
83 tv = v1 - ((as -> dpval) << 8); | |
84 if (tv < 0 || tv > 0xff) | |
85 { | |
86 register_error(as, l, 2, "Byte overflow"); | |
87 } | |
88 v1 = v1 & 0xff; | |
89 lwasm_emitop(as, l, instab[opnum].ops[0]); | |
90 if (extra != -1) | |
91 lwasm_emit(as, l, extra); | |
92 lwasm_emit(as, l, v1 & 0xff); | |
93 return; | |
94 } | |
95 else | |
96 { | |
97 // everything else is 16 bit.... | |
98 lwasm_emitop(as, l, instab[opnum].ops[2]); | |
99 if (extra != -1) | |
100 lwasm_emit(as, l, extra); | |
101 l -> relocoff = as -> addr - l -> codeaddr; | |
102 lwasm_emit(as, l, v1 >> 8); | |
103 lwasm_emit(as, l, v1 & 0xff); | |
104 return; | |
105 } | |
106 } | |
107 | |
108 lwasm_emitop(as, l, instab[opnum].ops[1]); | |
109 if (extra != -1) | |
110 lwasm_emit(as, l, extra); | |
111 insn_indexed_aux(as, l, (const char **)optr, &b1, &b2, &b3); | |
112 if (b1 != -1) | |
113 lwasm_emit(as, l, b1); | |
114 if (b2 != -1) | |
115 lwasm_emit(as, l, b2); | |
116 if (b3 != -1) | |
117 lwasm_emit(as, l, b3); | |
118 return; | |
119 } | |
120 | |
121 // the various insn_gen? functions have an immediate mode of ? bits | |
122 OPFUNC(insn_gen0) | |
123 { | |
124 if (**p == '#') | |
125 { | |
126 register_error(as, l, 1, "Immediate mode not allowed"); | |
127 return; | |
128 } | |
129 | |
130 // handle non-immediate | |
131 insn_gen_aux(as, l, p, opnum, -1); | |
132 } | |
133 | |
134 OPFUNC(insn_gen8) | |
135 { | |
136 int rval; | |
137 int r; | |
138 | |
139 if (**p == '#') | |
140 { | |
141 lwasm_emitop(as, l, instab[opnum].ops[3]); | |
142 (*p)++; | |
143 r = lwasm_expr_result2(as, l, p, 0, &rval, 0); | |
144 if (r != 0) | |
145 rval = 0; | |
146 if (r == 1 && as -> passnum == 2) | |
147 register_error(as, l, 2, "Illegal external or intersegment reference"); | |
148 lwasm_emit(as, l, rval & 0xff); | |
149 return; | |
150 } | |
151 | |
152 insn_gen_aux(as, l, p, opnum, -1); | |
153 } | |
154 | |
155 OPFUNC(insn_gen16) | |
156 { | |
157 int rval, r; | |
158 | |
159 if (**p == '#') | |
160 { | |
161 lwasm_emitop(as, l, instab[opnum].ops[3]); | |
162 (*p)++; | |
163 | |
164 r = lwasm_expr_result2(as, l, p, 0, &rval, 0); | |
165 if (r != 0) | |
166 rval = 0; | |
167 if (r == 1 && as -> passnum == 2) | |
168 { | |
169 l -> relocoff = as -> addr - l -> codeaddr; | |
170 } | |
171 lwasm_emit(as, l, (rval >> 8) & 0xff); | |
172 lwasm_emit(as, l, rval & 0xff); | |
173 return; | |
174 } | |
175 | |
176 insn_gen_aux(as, l, p, opnum, -1); | |
177 } | |
178 | |
179 OPFUNC(insn_gen32) | |
180 { | |
181 int r, rval; | |
182 | |
183 if (**p == '#') | |
184 { | |
185 lwasm_emitop(as, l, instab[opnum].ops[3]); | |
186 (*p)++; | |
187 | |
188 r = lwasm_expr_result2(as, l, p, 0, &rval, 0); | |
189 if (r != 0) | |
190 rval = 0; | |
191 if (r == 1 && as -> passnum == 2) | |
192 { | |
193 register_error(as, l, 2, "Illegal external or intersegment reference"); | |
194 } | |
195 | |
196 lwasm_emit(as, l, (rval >> 24) & 0xff); | |
197 lwasm_emit(as, l, (rval >> 16) & 0xff); | |
198 lwasm_emit(as, l, (rval >> 8) & 0xff); | |
199 lwasm_emit(as, l, rval & 0xff); | |
200 return; | |
201 } | |
202 | |
203 insn_gen_aux(as, l, p, opnum, -1); | |
204 } | |
205 | |
206 OPFUNC(insn_imm8) | |
207 { | |
208 int r, rval; | |
209 | |
210 if (**p == '#') | |
211 { | |
212 lwasm_emitop(as, l, instab[opnum].ops[0]); | |
213 (*p)++; | |
214 | |
215 r = lwasm_expr_result2(as, l, p, 0, &rval, 0); | |
216 if (r != 0) | |
217 rval = 0; | |
218 if (r == 1 && as -> passnum == 2) | |
219 register_error(as, l, 2, "Illegal external or intersegment reference"); | |
220 | |
221 if (rval < -128 || rval > 255) | |
222 register_error(as, l, 2, "Byte overflow"); | |
223 lwasm_emit(as, l, rval & 0xff); | |
224 return; | |
225 } | |
226 | |
227 register_error(as, l, 1, "Bad operand"); | |
228 } |