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 }