aboutsummaryrefslogtreecommitdiff
path: root/libyasm/insn.c
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2013-03-28 15:33:02 +0000
committerTorne (Richard Coles) <torne@google.com>2013-03-28 15:33:02 +0000
commitc580f3c787d8ad2dcccceb4438b7572d9713a296 (patch)
treed8f5d6b20552cfe016f9af38440fd9caacf4a188 /libyasm/insn.c
parent1fe0cccaa99357259c9ab42ce88626b95856b77c (diff)
parent53137eb420065ea05c21ae0728a67ead80f17e1f (diff)
downloadpatched-yasm-c580f3c787d8ad2dcccceb4438b7572d9713a296.tar.gz
This commit was generated by merge_to_master.py. Change-Id: I1975b1fce5e96446e4fa27feda7009fe340d4cff
Diffstat (limited to 'libyasm/insn.c')
-rw-r--r--libyasm/insn.c295
1 files changed, 295 insertions, 0 deletions
diff --git a/libyasm/insn.c b/libyasm/insn.c
new file mode 100644
index 0000000..8f7a4c1
--- /dev/null
+++ b/libyasm/insn.c
@@ -0,0 +1,295 @@
+/*
+ * Mnemonic instruction bytecode
+ *
+ * Copyright (C) 2005-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+
+#include "errwarn.h"
+#include "expr.h"
+#include "value.h"
+
+#include "bytecode.h"
+#include "insn.h"
+#include "arch.h"
+
+
+void
+yasm_ea_set_segreg(yasm_effaddr *ea, uintptr_t segreg)
+{
+ if (!ea)
+ return;
+
+ if (segreg != 0 && ea->segreg != 0)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("multiple segment overrides, using leftmost"));
+
+ ea->segreg = segreg;
+}
+
+yasm_insn_operand *
+yasm_operand_create_reg(uintptr_t reg)
+{
+ yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand));
+
+ retval->type = YASM_INSN__OPERAND_REG;
+ retval->data.reg = reg;
+ retval->seg = 0;
+ retval->targetmod = 0;
+ retval->size = 0;
+ retval->deref = 0;
+ retval->strict = 0;
+
+ return retval;
+}
+
+yasm_insn_operand *
+yasm_operand_create_segreg(uintptr_t segreg)
+{
+ yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand));
+
+ retval->type = YASM_INSN__OPERAND_SEGREG;
+ retval->data.reg = segreg;
+ retval->seg = 0;
+ retval->targetmod = 0;
+ retval->size = 0;
+ retval->deref = 0;
+ retval->strict = 0;
+
+ return retval;
+}
+
+yasm_insn_operand *
+yasm_operand_create_mem(/*@only@*/ yasm_effaddr *ea)
+{
+ yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand));
+
+ retval->type = YASM_INSN__OPERAND_MEMORY;
+ retval->data.ea = ea;
+ retval->seg = 0;
+ retval->targetmod = 0;
+ retval->size = 0;
+ retval->deref = 0;
+ retval->strict = 0;
+ retval->size = ea->data_len * 8;
+
+ return retval;
+}
+
+yasm_insn_operand *
+yasm_operand_create_imm(/*@only@*/ yasm_expr *val)
+{
+ yasm_insn_operand *retval;
+ const uintptr_t *reg;
+
+ reg = yasm_expr_get_reg(&val, 0);
+ if (reg) {
+ retval = yasm_operand_create_reg(*reg);
+ yasm_expr_destroy(val);
+ } else {
+ retval = yasm_xmalloc(sizeof(yasm_insn_operand));
+ retval->type = YASM_INSN__OPERAND_IMM;
+ retval->data.val = val;
+ retval->seg = 0;
+ retval->targetmod = 0;
+ retval->size = 0;
+ retval->deref = 0;
+ retval->strict = 0;
+ }
+
+ return retval;
+}
+
+yasm_insn_operand *
+yasm_insn_ops_append(yasm_insn *insn, yasm_insn_operand *op)
+{
+ if (op) {
+ insn->num_operands++;
+ STAILQ_INSERT_TAIL(&insn->operands, op, link);
+ return op;
+ }
+ return (yasm_insn_operand *)NULL;
+}
+
+void
+yasm_insn_add_prefix(yasm_insn *insn, uintptr_t prefix)
+{
+ insn->prefixes =
+ yasm_xrealloc(insn->prefixes,
+ (insn->num_prefixes+1)*sizeof(uintptr_t));
+ insn->prefixes[insn->num_prefixes] = prefix;
+ insn->num_prefixes++;
+}
+
+void
+yasm_insn_add_seg_prefix(yasm_insn *insn, uintptr_t segreg)
+{
+ insn->segregs =
+ yasm_xrealloc(insn->segregs, (insn->num_segregs+1)*sizeof(uintptr_t));
+ insn->segregs[insn->num_segregs] = segreg;
+ insn->num_segregs++;
+}
+
+void
+yasm_insn_initialize(yasm_insn *insn)
+{
+ STAILQ_INIT(&insn->operands);
+
+ insn->prefixes = NULL;
+ insn->segregs = NULL;
+
+ insn->num_operands = 0;
+ insn->num_prefixes = 0;
+ insn->num_segregs = 0;
+}
+
+void
+yasm_insn_delete(yasm_insn *insn,
+ void (*ea_destroy) (/*@only@*/ yasm_effaddr *))
+{
+ if (insn->num_operands > 0) {
+ yasm_insn_operand *cur, *next;
+
+ cur = STAILQ_FIRST(&insn->operands);
+ while (cur) {
+ next = STAILQ_NEXT(cur, link);
+ switch (cur->type) {
+ case YASM_INSN__OPERAND_MEMORY:
+ ea_destroy(cur->data.ea);
+ break;
+ case YASM_INSN__OPERAND_IMM:
+ yasm_expr_destroy(cur->data.val);
+ break;
+ default:
+ break;
+ }
+ yasm_xfree(cur);
+ cur = next;
+ }
+ }
+ if (insn->num_prefixes > 0)
+ yasm_xfree(insn->prefixes);
+ if (insn->num_segregs > 0)
+ yasm_xfree(insn->segregs);
+}
+
+void
+yasm_insn_print(const yasm_insn *insn, FILE *f, int indent_level)
+{
+ const yasm_insn_operand *op;
+
+ STAILQ_FOREACH (op, &insn->operands, link) {
+ switch (op->type) {
+ case YASM_INSN__OPERAND_REG:
+ fprintf(f, "%*sReg=", indent_level, "");
+ /*yasm_arch_reg_print(arch, op->data.reg, f);*/
+ fprintf(f, "\n");
+ break;
+ case YASM_INSN__OPERAND_SEGREG:
+ fprintf(f, "%*sSegReg=", indent_level, "");
+ /*yasm_arch_segreg_print(arch, op->data.reg, f);*/
+ fprintf(f, "\n");
+ break;
+ case YASM_INSN__OPERAND_MEMORY:
+ fprintf(f, "%*sMemory=\n", indent_level, "");
+ /*yasm_arch_ea_print(arch, op->data.ea, f, indent_level);*/
+ break;
+ case YASM_INSN__OPERAND_IMM:
+ fprintf(f, "%*sImm=", indent_level, "");
+ yasm_expr_print(op->data.val, f);
+ fprintf(f, "\n");
+ break;
+ }
+ fprintf(f, "%*sTargetMod=%lx\n", indent_level+1, "",
+ (unsigned long)op->targetmod);
+ fprintf(f, "%*sSize=%u\n", indent_level+1, "", op->size);
+ fprintf(f, "%*sDeref=%d, Strict=%d\n", indent_level+1, "",
+ (int)op->deref, (int)op->strict);
+ }
+}
+
+void
+yasm_insn_finalize(yasm_insn *insn)
+{
+ unsigned int i;
+ yasm_insn_operand *op;
+ yasm_error_class eclass;
+ char *str, *xrefstr;
+ unsigned long xrefline;
+
+ /* Simplify the operands' expressions first. */
+ for (i = 0, op = yasm_insn_ops_first(insn);
+ op && i<insn->num_operands; op = yasm_insn_op_next(op), i++) {
+ /* Check operand type */
+ switch (op->type) {
+ case YASM_INSN__OPERAND_MEMORY:
+ /* Don't get over-ambitious here; some archs' memory expr
+ * parser are sensitive to the presence of *1, etc, so don't
+ * simplify reg*1 identities.
+ */
+ if (op->data.ea)
+ op->data.ea->disp.abs =
+ yasm_expr__level_tree(op->data.ea->disp.abs, 1, 1, 0,
+ 0, NULL, NULL);
+ if (yasm_error_occurred()) {
+ /* Add a pointer to where it was used to the error */
+ yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr);
+ if (xrefstr) {
+ yasm_error_set_xref(xrefline, "%s", xrefstr);
+ yasm_xfree(xrefstr);
+ }
+ if (str) {
+ yasm_error_set(eclass, "%s in memory expression", str);
+ yasm_xfree(str);
+ }
+ return;
+ }
+ break;
+ case YASM_INSN__OPERAND_IMM:
+ op->data.val =
+ yasm_expr__level_tree(op->data.val, 1, 1, 1, 0, NULL,
+ NULL);
+ if (yasm_error_occurred()) {
+ /* Add a pointer to where it was used to the error */
+ yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr);
+ if (xrefstr) {
+ yasm_error_set_xref(xrefline, "%s", xrefstr);
+ yasm_xfree(xrefstr);
+ }
+ if (str) {
+ yasm_error_set(eclass, "%s in immediate expression",
+ str);
+ yasm_xfree(str);
+ }
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}