| /* |
| * Architecture interface |
| * |
| * Copyright (C) 2001 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. |
| */ |
| #define YASM_LIB_INTERNAL |
| #define YASM_ARCH_INTERNAL |
| #include "util.h" |
| /*@unused@*/ RCSID("$IdPath$"); |
| |
| #include "coretype.h" |
| |
| #include "expr.h" |
| |
| #include "bytecode.h" |
| |
| #include "arch.h" |
| |
| |
| yasm_arch_module * |
| yasm_arch_get_module(yasm_arch *arch) |
| { |
| return arch->module; |
| } |
| |
| yasm_insn_operand * |
| yasm_operand_create_reg(unsigned long reg) |
| { |
| yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand)); |
| |
| retval->type = YASM_INSN__OPERAND_REG; |
| retval->data.reg = reg; |
| retval->targetmod = 0; |
| retval->size = 0; |
| |
| return retval; |
| } |
| |
| yasm_insn_operand * |
| yasm_operand_create_segreg(unsigned long segreg) |
| { |
| yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand)); |
| |
| retval->type = YASM_INSN__OPERAND_SEGREG; |
| retval->data.reg = segreg; |
| retval->targetmod = 0; |
| retval->size = 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->targetmod = 0; |
| retval->size = 0; |
| |
| return retval; |
| } |
| |
| yasm_insn_operand * |
| yasm_operand_create_imm(/*@only@*/ yasm_expr *val) |
| { |
| yasm_insn_operand *retval; |
| const unsigned long *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->targetmod = 0; |
| retval->size = 0; |
| } |
| |
| return retval; |
| } |
| |
| void |
| yasm_operand_print(const yasm_insn_operand *op, FILE *f, int indent_level, |
| yasm_arch *arch) |
| { |
| switch (op->type) { |
| case YASM_INSN__OPERAND_REG: |
| fprintf(f, "%*sReg=", indent_level, ""); |
| arch->module->reg_print(arch, op->data.reg, f); |
| fprintf(f, "\n"); |
| break; |
| case YASM_INSN__OPERAND_SEGREG: |
| fprintf(f, "%*sSegReg=", indent_level, ""); |
| arch->module->segreg_print(arch, op->data.reg, f); |
| fprintf(f, "\n"); |
| break; |
| case YASM_INSN__OPERAND_MEMORY: |
| fprintf(f, "%*sMemory=\n", indent_level, ""); |
| yasm_ea_print(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, "", op->targetmod); |
| fprintf(f, "%*sSize=%u\n", indent_level+1, "", op->size); |
| } |
| |
| void |
| yasm_ops_delete(yasm_insn_operandhead *headp, int content) |
| { |
| yasm_insn_operand *cur, *next; |
| |
| cur = STAILQ_FIRST(headp); |
| while (cur) { |
| next = STAILQ_NEXT(cur, link); |
| if (content) |
| switch (cur->type) { |
| case YASM_INSN__OPERAND_MEMORY: |
| yasm_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; |
| } |
| STAILQ_INIT(headp); |
| } |
| |
| /*@null@*/ yasm_insn_operand * |
| yasm_ops_append(yasm_insn_operandhead *headp, |
| /*@returned@*/ /*@null@*/ yasm_insn_operand *op) |
| { |
| if (op) { |
| STAILQ_INSERT_TAIL(headp, op, link); |
| return op; |
| } |
| return (yasm_insn_operand *)NULL; |
| } |
| |
| void |
| yasm_ops_print(const yasm_insn_operandhead *headp, FILE *f, int indent_level, |
| yasm_arch *arch) |
| { |
| yasm_insn_operand *cur; |
| |
| STAILQ_FOREACH (cur, headp, link) |
| yasm_operand_print(cur, f, indent_level, arch); |
| } |
| |
| yasm_insn_operandhead * |
| yasm_ops_create(void) |
| { |
| yasm_insn_operandhead *headp = yasm_xmalloc(sizeof(yasm_insn_operandhead)); |
| yasm_ops_initialize(headp); |
| return headp; |
| } |
| |
| void |
| yasm_ops_destroy(yasm_insn_operandhead *headp, int content) |
| { |
| yasm_ops_delete(headp, content); |
| yasm_xfree(headp); |
| } |
| |
| /* Non-macro yasm_ops_first() for non-YASM_LIB_INTERNAL users. */ |
| #undef yasm_ops_first |
| yasm_insn_operand * |
| yasm_ops_first(yasm_insn_operandhead *headp) |
| { |
| return STAILQ_FIRST(headp); |
| } |
| |
| /* Non-macro yasm_operand_next() for non-YASM_LIB_INTERNAL users. */ |
| #undef yasm_operand_next |
| yasm_insn_operand * |
| yasm_operand_next(yasm_insn_operand *cur) |
| { |
| return STAILQ_NEXT(cur, link); |
| } |