blob: b117b400344682762fab50213a808472d44db96a [file] [log] [blame]
/*
* 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
#include "util.h"
/*@unused@*/ RCSID("$IdPath$");
#include "expr.h"
#include "bytecode.h"
#include "arch.h"
static /*@dependent@*/ yasm_arch *cur_arch;
void
yasm_arch_common_initialize(yasm_arch *a)
{
cur_arch = a;
}
yasm_insn_operand *
yasm_operand_new_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_new_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_new_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_new_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_new_reg(*reg);
yasm_expr_delete(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(FILE *f, int indent_level, const yasm_insn_operand *op)
{
switch (op->type) {
case YASM_INSN__OPERAND_REG:
fprintf(f, "%*sReg=", indent_level, "");
cur_arch->reg_print(f, op->data.reg);
fprintf(f, "\n");
break;
case YASM_INSN__OPERAND_SEGREG:
fprintf(f, "%*sSegReg=", indent_level, "");
cur_arch->segreg_print(f, op->data.reg);
fprintf(f, "\n");
break;
case YASM_INSN__OPERAND_MEMORY:
fprintf(f, "%*sMemory=\n", indent_level, "");
yasm_ea_print(f, indent_level, op->data.ea);
break;
case YASM_INSN__OPERAND_IMM:
fprintf(f, "%*sImm=", indent_level, "");
yasm_expr_print(f, op->data.val);
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_delete(cur->data.ea);
break;
case YASM_INSN__OPERAND_IMM:
yasm_expr_delete(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(FILE *f, int indent_level, const yasm_insn_operandhead *headp)
{
yasm_insn_operand *cur;
STAILQ_FOREACH (cur, headp, link)
yasm_operand_print(f, indent_level, cur);
}
/* Non-macro yasm_ops_initialize() for non-YASM_INTERNAL users. */
#undef yasm_ops_initialize
void
yasm_ops_initialize(yasm_insn_operandhead *headp)
{
STAILQ_INIT(headp);
}
/* Non-macro yasm_ops_first() for non-YASM_INTERNAL users. */
#undef yasm_ops_first
yasm_insn_operand *
yasm_ops_first(yasm_insn_operandhead *headp)
{
return STAILQ_FIRST(headp);
}
/* Non-macro yasm_ops_next() for non-YASM_INTERNAL users. */
#undef yasm_ops_next
yasm_insn_operand *
yasm_ops_next(yasm_insn_operand *cur)
{
return STAILQ_NEXT(cur, link);
}