1 /*
2 * Mnemonic instruction bytecode
3 *
4 * Copyright (C) 2005-2007 Peter Johnson
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27 #include "util.h"
28
29 #include "libyasm-stdint.h"
30 #include "coretype.h"
31
32 #include "errwarn.h"
33 #include "expr.h"
34 #include "value.h"
35
36 #include "bytecode.h"
37 #include "insn.h"
38 #include "arch.h"
39
40
41 void
yasm_ea_set_segreg(yasm_effaddr * ea,uintptr_t segreg)42 yasm_ea_set_segreg(yasm_effaddr *ea, uintptr_t segreg)
43 {
44 if (!ea)
45 return;
46
47 if (segreg != 0 && ea->segreg != 0)
48 yasm_warn_set(YASM_WARN_GENERAL,
49 N_("multiple segment overrides, using leftmost"));
50
51 ea->segreg = segreg;
52 }
53
54 yasm_insn_operand *
yasm_operand_create_reg(uintptr_t reg)55 yasm_operand_create_reg(uintptr_t reg)
56 {
57 yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand));
58
59 retval->type = YASM_INSN__OPERAND_REG;
60 retval->data.reg = reg;
61 retval->seg = 0;
62 retval->targetmod = 0;
63 retval->size = 0;
64 retval->deref = 0;
65 retval->strict = 0;
66
67 return retval;
68 }
69
70 yasm_insn_operand *
yasm_operand_create_segreg(uintptr_t segreg)71 yasm_operand_create_segreg(uintptr_t segreg)
72 {
73 yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand));
74
75 retval->type = YASM_INSN__OPERAND_SEGREG;
76 retval->data.reg = segreg;
77 retval->seg = 0;
78 retval->targetmod = 0;
79 retval->size = 0;
80 retval->deref = 0;
81 retval->strict = 0;
82
83 return retval;
84 }
85
86 yasm_insn_operand *
yasm_operand_create_mem(yasm_effaddr * ea)87 yasm_operand_create_mem(/*@only@*/ yasm_effaddr *ea)
88 {
89 yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand));
90
91 retval->type = YASM_INSN__OPERAND_MEMORY;
92 retval->data.ea = ea;
93 retval->seg = 0;
94 retval->targetmod = 0;
95 retval->size = 0;
96 retval->deref = 0;
97 retval->strict = 0;
98 retval->size = ea->data_len * 8;
99
100 return retval;
101 }
102
103 yasm_insn_operand *
yasm_operand_create_imm(yasm_expr * val)104 yasm_operand_create_imm(/*@only@*/ yasm_expr *val)
105 {
106 yasm_insn_operand *retval;
107 const uintptr_t *reg;
108
109 reg = yasm_expr_get_reg(&val, 0);
110 if (reg) {
111 retval = yasm_operand_create_reg(*reg);
112 yasm_expr_destroy(val);
113 } else {
114 retval = yasm_xmalloc(sizeof(yasm_insn_operand));
115 retval->type = YASM_INSN__OPERAND_IMM;
116 retval->data.val = val;
117 retval->seg = 0;
118 retval->targetmod = 0;
119 retval->size = 0;
120 retval->deref = 0;
121 retval->strict = 0;
122 }
123
124 return retval;
125 }
126
127 yasm_insn_operand *
yasm_insn_ops_append(yasm_insn * insn,yasm_insn_operand * op)128 yasm_insn_ops_append(yasm_insn *insn, yasm_insn_operand *op)
129 {
130 if (op) {
131 insn->num_operands++;
132 STAILQ_INSERT_TAIL(&insn->operands, op, link);
133 return op;
134 }
135 return (yasm_insn_operand *)NULL;
136 }
137
138 void
yasm_insn_add_prefix(yasm_insn * insn,uintptr_t prefix)139 yasm_insn_add_prefix(yasm_insn *insn, uintptr_t prefix)
140 {
141 insn->prefixes =
142 yasm_xrealloc(insn->prefixes,
143 (insn->num_prefixes+1)*sizeof(uintptr_t));
144 insn->prefixes[insn->num_prefixes] = prefix;
145 insn->num_prefixes++;
146 }
147
148 void
yasm_insn_add_seg_prefix(yasm_insn * insn,uintptr_t segreg)149 yasm_insn_add_seg_prefix(yasm_insn *insn, uintptr_t segreg)
150 {
151 insn->segregs =
152 yasm_xrealloc(insn->segregs, (insn->num_segregs+1)*sizeof(uintptr_t));
153 insn->segregs[insn->num_segregs] = segreg;
154 insn->num_segregs++;
155 }
156
157 void
yasm_insn_initialize(yasm_insn * insn)158 yasm_insn_initialize(yasm_insn *insn)
159 {
160 STAILQ_INIT(&insn->operands);
161
162 insn->prefixes = NULL;
163 insn->segregs = NULL;
164
165 insn->num_operands = 0;
166 insn->num_prefixes = 0;
167 insn->num_segregs = 0;
168 }
169
170 void
yasm_insn_delete(yasm_insn * insn,void (* ea_destroy)(yasm_effaddr *))171 yasm_insn_delete(yasm_insn *insn,
172 void (*ea_destroy) (/*@only@*/ yasm_effaddr *))
173 {
174 if (insn->num_operands > 0) {
175 yasm_insn_operand *cur, *next;
176
177 cur = STAILQ_FIRST(&insn->operands);
178 while (cur) {
179 next = STAILQ_NEXT(cur, link);
180 switch (cur->type) {
181 case YASM_INSN__OPERAND_MEMORY:
182 ea_destroy(cur->data.ea);
183 break;
184 case YASM_INSN__OPERAND_IMM:
185 yasm_expr_destroy(cur->data.val);
186 break;
187 default:
188 break;
189 }
190 yasm_xfree(cur);
191 cur = next;
192 }
193 }
194 if (insn->num_prefixes > 0)
195 yasm_xfree(insn->prefixes);
196 if (insn->num_segregs > 0)
197 yasm_xfree(insn->segregs);
198 }
199
200 void
yasm_insn_print(const yasm_insn * insn,FILE * f,int indent_level)201 yasm_insn_print(const yasm_insn *insn, FILE *f, int indent_level)
202 {
203 const yasm_insn_operand *op;
204
205 STAILQ_FOREACH (op, &insn->operands, link) {
206 switch (op->type) {
207 case YASM_INSN__OPERAND_REG:
208 fprintf(f, "%*sReg=", indent_level, "");
209 /*yasm_arch_reg_print(arch, op->data.reg, f);*/
210 fprintf(f, "\n");
211 break;
212 case YASM_INSN__OPERAND_SEGREG:
213 fprintf(f, "%*sSegReg=", indent_level, "");
214 /*yasm_arch_segreg_print(arch, op->data.reg, f);*/
215 fprintf(f, "\n");
216 break;
217 case YASM_INSN__OPERAND_MEMORY:
218 fprintf(f, "%*sMemory=\n", indent_level, "");
219 /*yasm_arch_ea_print(arch, op->data.ea, f, indent_level);*/
220 break;
221 case YASM_INSN__OPERAND_IMM:
222 fprintf(f, "%*sImm=", indent_level, "");
223 yasm_expr_print(op->data.val, f);
224 fprintf(f, "\n");
225 break;
226 }
227 fprintf(f, "%*sTargetMod=%lx\n", indent_level+1, "",
228 (unsigned long)op->targetmod);
229 fprintf(f, "%*sSize=%u\n", indent_level+1, "", op->size);
230 fprintf(f, "%*sDeref=%d, Strict=%d\n", indent_level+1, "",
231 (int)op->deref, (int)op->strict);
232 }
233 }
234
235 void
yasm_insn_finalize(yasm_insn * insn)236 yasm_insn_finalize(yasm_insn *insn)
237 {
238 unsigned int i;
239 yasm_insn_operand *op;
240 yasm_error_class eclass;
241 char *str, *xrefstr;
242 unsigned long xrefline;
243
244 /* Simplify the operands' expressions first. */
245 for (i = 0, op = yasm_insn_ops_first(insn);
246 op && i<insn->num_operands; op = yasm_insn_op_next(op), i++) {
247 /* Check operand type */
248 switch (op->type) {
249 case YASM_INSN__OPERAND_MEMORY:
250 /* Don't get over-ambitious here; some archs' memory expr
251 * parser are sensitive to the presence of *1, etc, so don't
252 * simplify reg*1 identities.
253 */
254 if (op->data.ea)
255 op->data.ea->disp.abs =
256 yasm_expr__level_tree(op->data.ea->disp.abs, 1, 1, 0,
257 0, NULL, NULL);
258 if (yasm_error_occurred()) {
259 /* Add a pointer to where it was used to the error */
260 yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr);
261 if (xrefstr) {
262 yasm_error_set_xref(xrefline, "%s", xrefstr);
263 yasm_xfree(xrefstr);
264 }
265 if (str) {
266 yasm_error_set(eclass, "%s in memory expression", str);
267 yasm_xfree(str);
268 }
269 return;
270 }
271 break;
272 case YASM_INSN__OPERAND_IMM:
273 op->data.val =
274 yasm_expr__level_tree(op->data.val, 1, 1, 1, 0, NULL,
275 NULL);
276 if (yasm_error_occurred()) {
277 /* Add a pointer to where it was used to the error */
278 yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr);
279 if (xrefstr) {
280 yasm_error_set_xref(xrefline, "%s", xrefstr);
281 yasm_xfree(xrefstr);
282 }
283 if (str) {
284 yasm_error_set(eclass, "%s in immediate expression",
285 str);
286 yasm_xfree(str);
287 }
288 return;
289 }
290 break;
291 default:
292 break;
293 }
294 }
295 }
296