Add packaging files for Tizen
[profile/ivi/yasm.git] / libyasm / insn.c
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
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 *
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 *
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 *
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 *
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 *
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
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
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
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
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
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
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 }