if (in != stdin)
fclose(in);
+ /* Finalize parse */
+ yasm_object_finalize(object);
+
if (yasm_get_num_errors(warning_error) > 0) {
yasm_errwarn_output_all(yasm_object_get_linemap(object), warning_error,
print_yasm_error, print_yasm_warning);
/** An instruction operand (opaque type). */
typedef struct yasm_insn_operand yasm_insn_operand;
-/** A list of instruction operands (opaque type).
- * The list goes from left-to-right as parsed.
- */
-typedef struct yasm_insn_operands yasm_insn_operands;
#ifdef YASM_LIB_INTERNAL
/*@reldef@*/ STAILQ_HEAD(yasm_insn_operands, yasm_insn_operand);
#endif
* module loader's function definitions. The version number must never be
* decreased.
*/
-#define YASM_ARCH_VERSION 3
+#define YASM_ARCH_VERSION 4
/** YASM architecture module interface.
* \note All "data" in parser-related functions (yasm_arch_parse_*) needs to
/*@null@*/ yasm_valparamhead *objext_valparams,
yasm_object *object, unsigned long line);
- /** Module-level implementation of yasm_arch_parse_insn().
- * Call yasm_arch_parse_insn() instead of calling this function.
- */
- /*@null@*/ yasm_bytecode * (*parse_insn)
- (yasm_arch *arch, const unsigned long data[4], int num_operands,
- /*@null@*/ yasm_insn_operands *operands, yasm_bytecode *prev_bc,
- unsigned long line);
-
- /** Module-level implementation of yasm_arch_parse_prefix().
- * Call yasm_arch_parse_prefix() instead of calling this function.
- */
- void (*parse_prefix) (yasm_arch *arch, yasm_bytecode *bc,
- const unsigned long data[4], unsigned long line);
-
- /** Module-level implementation of yasm_arch_parse_seg_prefix().
- * Call yasm_arch_parse_seg_prefix() instead of calling this function.
- */
- void (*parse_seg_prefix) (yasm_arch *arch, yasm_bytecode *bc,
- unsigned long segreg, unsigned long line);
-
- /** Module-level implementation of yasm_arch_parse_seg_override().
- * Call yasm_arch_parse_seg_override() instead of calling this function.
+ /** Module-level implementation of yasm_arch_finalize_insn().
+ * Call yasm_arch_finalize_insn() instead of calling this function.
*/
- void (*parse_seg_override) (yasm_arch *arch, yasm_effaddr *ea,
- unsigned long segreg, unsigned long line);
+ void (*finalize_insn)
+ (yasm_arch *arch, yasm_bytecode *bc, yasm_bytecode *prev_bc,
+ const unsigned long data[4], int num_operands,
+ /*@null@*/ yasm_insn_operands *operands, int num_prefixes,
+ unsigned long **prefixes, int num_segregs,
+ const unsigned long *segregs);
/** Module-level implementation of yasm_arch_floatnum_tobytes().
* Call yasm_arch_floatnum_tobytes() instead of calling this function.
/*@null@*/ yasm_valparamhead *objext_valparams,
yasm_object *object, unsigned long line);
-/** Create an instruction. Creates a bytecode by matching the
- * instruction data and the parameters given with a valid instruction.
+/** Finalize an instruction from a semi-generic insn description. Note an
+ * existing bytecode is required.
* \param arch architecture
+ * \param bc bytecode to finalize
+ * \param prev_bc previous bytecode in section
* \param data instruction data (from parse_check_id()); all
* zero indicates an empty instruction
- * \param num_operands number of operands parsed
+ * \param num_operands number of operands
* \param operands list of operands (in parse order)
- * \param prev_bc previously parsed bytecode in section (NULL if
- * first bytecode in section)
- * \param line virtual line (from yasm_linemap)
- * \return If no match is found (the instruction is invalid), NULL,
- * otherwise newly allocated bytecode containing instruction.
- */
-/*@null@*/ yasm_bytecode *yasm_arch_parse_insn
- (yasm_arch *arch, const unsigned long data[4], int num_operands,
- /*@null@*/ yasm_insn_operands *operands, yasm_bytecode *prev_bc,
- unsigned long line);
-
-/** Handle an instruction prefix.
- * Modifies an instruction bytecode based on the prefix in data.
- * \param arch architecture
- * \param bc bytecode (must be instruction bytecode)
- * \param data prefix (from parse_check_id())
- * \param line virtual line (from yasm_linemap)
- */
-void yasm_arch_parse_prefix(yasm_arch *arch, yasm_bytecode *bc,
- const unsigned long data[4], unsigned long line);
-
-/** Handle an segment register instruction prefix.
- * Modifies an instruction bytecode based on a segment register prefix.
- * \param arch architecture
- * \param bc bytecode (must be instruction bytecode)
- * \param segreg segment register (from parse_check_id())
- * \param line virtual line (from yasm_linemap)
- */
-void yasm_arch_parse_seg_prefix(yasm_arch *arch, yasm_bytecode *bc,
- unsigned long segreg, unsigned long line);
-
-/** Handle a memory expression segment override.
- * Modifies an instruction bytecode based on a segment override in a
- * memory expression.
- * \param arch architecture
- * \param ea effective address
- * \param segreg segment register (from parse_check_id())
- * \param line virtual line (from yasm_linemap)
- */
-void yasm_arch_parse_seg_override(yasm_arch *arch, yasm_effaddr *ea,
- unsigned long segreg, unsigned long line);
+ * \param num_prefixes number of prefixes
+ * \param prefixes array of 4-element prefix data
+ * \param num_segregs number of segment register prefixes
+ * \param segregs array of segment register data
+ * \return If no match is found (the instruction is invalid), no action is
+ * performed and an error is recorded.
+ */
+void yasm_arch_finalize_insn
+ (yasm_arch *arch, yasm_bytecode *bc, yasm_bytecode *prev_bc,
+ const unsigned long data[4], int num_operands,
+ /*@null@*/ yasm_insn_operands *operands, int num_prefixes,
+ const unsigned long **prefixes, int num_segregs,
+ const unsigned long *segregs);
/** Output #yasm_floatnum to buffer. Puts the value into the least
* significant bits of the destination, or may be shifted into more
object, line) \
((yasm_arch_base *)arch)->module->parse_directive \
(arch, name, valparams, objext_valparams, object, line)
-#define yasm_arch_parse_insn(arch, data, num_operands, operands, prev_bc, \
- line) \
- ((yasm_arch_base *)arch)->module->parse_insn \
- (arch, data, num_operands, operands, prev_bc, line)
-#define yasm_arch_parse_prefix(arch, bc, data, line) \
- ((yasm_arch_base *)arch)->module->parse_prefix(arch, bc, data, line)
-#define yasm_arch_parse_seg_prefix(arch, bc, segreg, line) \
- ((yasm_arch_base *)arch)->module->parse_seg_prefix(arch, bc, segreg, line)
-#define yasm_arch_parse_seg_override(arch, ea, segreg, line) \
- ((yasm_arch_base *)arch)->module->parse_seg_override \
- (arch, ea, segreg, line)
+#define yasm_arch_finalize_insn(arch, bc, prev_bc, data, num_operands, \
+ operands, num_prefixes, prefixes, \
+ num_segregs, segregs) \
+ ((yasm_arch_base *)arch)->module->finalize_insn \
+ (arch, bc, prev_bc, data, num_operands, operands, num_prefixes, \
+ prefixes, num_segregs, segregs)
#define yasm_arch_floatnum_tobytes(arch, flt, buf, destsize, valsize, shift, \
warn, line) \
((yasm_arch_base *)arch)->module->floatnum_tobytes \
const yasm_effaddr_callback *callback; /* callback functions */
/*@only@*/ /*@null@*/ yasm_expr *disp; /* address displacement */
+ unsigned long segreg; /* segment register override (0 if none) */
unsigned char len; /* length of disp (in bytes), 0 if unknown,
* 0xff if unknown and required to be >0.
*/
};
typedef struct yasm_bytecode_callback {
- void (*destroy) (yasm_bytecode *bc);
- void (*print) (const yasm_bytecode *bc, FILE *f, int indent_level);
+ void (*destroy) (/*@only@*/ void *contents);
+ void (*print) (const void *contents, FILE *f, int indent_level);
+ void (*finalize) (yasm_bytecode *bc, yasm_bytecode *prev_bc);
yasm_bc_resolve_flags (*resolve)
(yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
int (*tobytes) (yasm_bytecode *bc, unsigned char **bufp, void *d,
/* NULL-terminated array of labels that point to this bytecode (as the
* bytecode previous to the label). NULL if no labels point here. */
/*@null@*/ yasm_symrec **symrecs;
+
+ /* bytecode-type-specific data (type identified by callback) */
+ void *contents;
};
/** Create a bytecode of any specified type.
* \param callback bytecode callback functions, if NULL, creates empty
* bytecode (may not be resolved or output)
- * \param datasize size of type-specific data (in bytes)
+ * \param contents type-specific data
* \param line virtual line (from yasm_linemap)
* \return Newly allocated bytecode of the specified type.
*/
/*@only@*/ yasm_bytecode *yasm_bc_create_common
- (/*@null@*/ const yasm_bytecode_callback *callback, size_t datasize,
- unsigned long line);
+ (/*@null@*/ const yasm_bytecode_callback *callback,
+ /*@only@*/ /*@null@*/ void *contents, unsigned long line);
+
+/** Transform a bytecode of any type into a different type.
+ * \param bc bytecode to transform
+ * \param callback new bytecode callback function
+ * \param contents new type-specific data
+ */
+void yasm_bc_transform(yasm_bytecode *bc,
+ const yasm_bytecode_callback *callback,
+ void *contents);
+
+/** Common bytecode callback finalize function, for where no finalization
+ * is ever required for this type of bytecode.
+ */
+void yasm_bc_finalize_common(yasm_bytecode *bc, yasm_bytecode *prev_bc);
#define yasm_bc__next(x) STAILQ_NEXT(x, link)
#include "expr.h"
#include "bytecode.h"
+#include "arch.h"
#include "objfmt.h"
#include "dbgfmt.h"
/* Standard bytecode types */
typedef struct bytecode_data {
- yasm_bytecode bc; /* base structure */
-
/* non-converted data (linked list) */
yasm_datavalhead datahead;
} bytecode_data;
typedef struct bytecode_reserve {
- yasm_bytecode bc; /* base structure */
-
/*@only@*/ yasm_expr *numitems; /* number of items to reserve */
unsigned char itemsize; /* size of each item (in bytes) */
} bytecode_reserve;
typedef struct bytecode_incbin {
- yasm_bytecode bc; /* base structure */
-
/*@only@*/ char *filename; /* file to include data from */
/* starting offset to read from (NULL=0) */
} bytecode_incbin;
typedef struct bytecode_align {
- yasm_bytecode bc; /* base structure */
-
unsigned long boundary; /* alignment boundary */
} bytecode_align;
+typedef struct bytecode_insn {
+ /*@dependent@*/ yasm_arch *arch;
+ unsigned long insn_data[4];
+
+ int num_operands;
+ /*@null@*/ yasm_insn_operands operands;
+
+ /* array of 4-element prefix_data arrays */
+ int num_prefixes;
+ /*@null@*/ unsigned long **prefixes;
+
+ /* array of segment prefixes */
+ int num_segregs;
+ /*@null@*/ unsigned long *segregs;
+} bytecode_insn;
+
/* Standard bytecode callback function prototypes */
-static void bc_data_destroy(yasm_bytecode *bc);
-static void bc_data_print(const yasm_bytecode *bc, FILE *f, int indent_level);
+static void bc_data_destroy(void *contents);
+static void bc_data_print(const void *contents, FILE *f, int indent_level);
static yasm_bc_resolve_flags bc_data_resolve
(yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
static int bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
yasm_output_expr_func output_expr,
/*@null@*/ yasm_output_reloc_func output_reloc);
-static void bc_reserve_destroy(yasm_bytecode *bc);
-static void bc_reserve_print(const yasm_bytecode *bc, FILE *f,
- int indent_level);
+static void bc_reserve_destroy(void *contents);
+static void bc_reserve_print(const void *contents, FILE *f, int indent_level);
static yasm_bc_resolve_flags bc_reserve_resolve
(yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
static int bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
yasm_output_expr_func output_expr,
/*@null@*/ yasm_output_reloc_func output_reloc);
-static void bc_incbin_destroy(yasm_bytecode *bc);
-static void bc_incbin_print(const yasm_bytecode *bc, FILE *f,
- int indent_level);
+static void bc_incbin_destroy(void *contents);
+static void bc_incbin_print(const void *contents, FILE *f, int indent_level);
static yasm_bc_resolve_flags bc_incbin_resolve
(yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
static int bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
yasm_output_expr_func output_expr,
/*@null@*/ yasm_output_reloc_func output_reloc);
-static void bc_align_destroy(yasm_bytecode *bc);
-static void bc_align_print(const yasm_bytecode *bc, FILE *f, int indent_level);
+static void bc_align_destroy(void *contents);
+static void bc_align_print(const void *contents, FILE *f, int indent_level);
static yasm_bc_resolve_flags bc_align_resolve
(yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
static int bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
yasm_output_expr_func output_expr,
/*@null@*/ yasm_output_reloc_func output_reloc);
+static void bc_insn_destroy(void *contents);
+static void bc_insn_print(const void *contents, FILE *f, int indent_level);
+static void bc_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+static yasm_bc_resolve_flags bc_insn_resolve
+ (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
+static int bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_expr_func output_expr,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
/* Standard bytecode callback structures */
static const yasm_bytecode_callback bc_data_callback = {
bc_data_destroy,
bc_data_print,
+ yasm_bc_finalize_common,
bc_data_resolve,
bc_data_tobytes
};
static const yasm_bytecode_callback bc_reserve_callback = {
bc_reserve_destroy,
bc_reserve_print,
+ yasm_bc_finalize_common,
bc_reserve_resolve,
bc_reserve_tobytes
};
static const yasm_bytecode_callback bc_incbin_callback = {
bc_incbin_destroy,
bc_incbin_print,
+ yasm_bc_finalize_common,
bc_incbin_resolve,
bc_incbin_tobytes
};
static const yasm_bytecode_callback bc_align_callback = {
bc_align_destroy,
bc_align_print,
+ yasm_bc_finalize_common,
bc_align_resolve,
bc_align_tobytes
};
+static const yasm_bytecode_callback bc_insn_callback = {
+ bc_insn_destroy,
+ bc_insn_print,
+ bc_insn_finalize,
+ bc_insn_resolve,
+ bc_insn_tobytes
+};
+
/* Static structures for when NULL is passed to conversion functions. */
/* for Convert*ToBytes() */
unsigned char bytes_static[16];
ptr->nosplit = (unsigned char)nosplit;
}
+void
+yasm_ea_set_segreg(yasm_effaddr *ea, unsigned long segreg, unsigned long line)
+{
+ if (!ea)
+ return;
+
+ if (segreg != 0 && ea->segreg != 0)
+ yasm__warning(YASM_WARN_GENERAL, line,
+ N_("multiple segment overrides, using leftmost"));
+
+ ea->segreg = segreg;
+}
+
/*@-nullstate@*/
void
yasm_ea_destroy(yasm_effaddr *ea)
bc->multiple = e;
}
+void
+yasm_bc_finalize_common(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+}
+
+void
+yasm_bc_transform(yasm_bytecode *bc, const yasm_bytecode_callback *callback,
+ void *contents)
+{
+ if (bc->callback)
+ bc->callback->destroy(bc->contents);
+ bc->callback = callback;
+ bc->contents = contents;
+}
+
yasm_bytecode *
-yasm_bc_create_common(const yasm_bytecode_callback *callback, size_t size,
+yasm_bc_create_common(const yasm_bytecode_callback *callback, void *contents,
unsigned long line)
{
- yasm_bytecode *bc = yasm_xmalloc(size);
+ yasm_bytecode *bc = yasm_xmalloc(sizeof(yasm_bytecode));
bc->callback = callback;
bc->symrecs = NULL;
+ bc->contents = contents;
+
return bc;
}
static void
-bc_data_destroy(yasm_bytecode *bc)
+bc_data_destroy(void *contents)
{
- bytecode_data *bc_data = (bytecode_data *)bc;
+ bytecode_data *bc_data = (bytecode_data *)contents;
yasm_dvs_destroy(&bc_data->datahead);
+ yasm_xfree(contents);
}
static void
-bc_data_print(const yasm_bytecode *bc, FILE *f, int indent_level)
+bc_data_print(const void *contents, FILE *f, int indent_level)
{
- const bytecode_data *bc_data = (const bytecode_data *)bc;
+ const bytecode_data *bc_data = (const bytecode_data *)contents;
fprintf(f, "%*s_Data_\n", indent_level, "");
fprintf(f, "%*sFinal Element Size=%u\n", indent_level+1, "",
(unsigned int)bc_data->size);
bc_data_resolve(yasm_bytecode *bc, int save,
yasm_calc_bc_dist_func calc_bc_dist)
{
- bytecode_data *bc_data = (bytecode_data *)bc;
+ bytecode_data *bc_data = (bytecode_data *)bc->contents;
yasm_dataval *dv;
size_t slen;
yasm_output_expr_func output_expr,
/*@unused@*/ yasm_output_reloc_func output_reloc)
{
- bytecode_data *bc_data = (bytecode_data *)bc;
+ bytecode_data *bc_data = (bytecode_data *)bc->contents;
yasm_dataval *dv;
size_t slen;
size_t i;
yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size,
unsigned long line)
{
- bytecode_data *data;
-
- data = (bytecode_data *)
- yasm_bc_create_common(&bc_data_callback, sizeof(bytecode_data), line);
+ bytecode_data *data = yasm_xmalloc(sizeof(bytecode_data));
data->datahead = *datahead;
data->size = (unsigned char)size;
- return (yasm_bytecode *)data;
+ return yasm_bc_create_common(&bc_data_callback, data, line);
}
static void
-bc_reserve_destroy(yasm_bytecode *bc)
+bc_reserve_destroy(void *contents)
{
- bytecode_reserve *reserve = (bytecode_reserve *)bc;
+ bytecode_reserve *reserve = (bytecode_reserve *)contents;
yasm_expr_destroy(reserve->numitems);
+ yasm_xfree(contents);
}
static void
-bc_reserve_print(const yasm_bytecode *bc, FILE *f, int indent_level)
+bc_reserve_print(const void *contents, FILE *f, int indent_level)
{
- const bytecode_reserve *reserve = (const bytecode_reserve *)bc;
+ const bytecode_reserve *reserve = (const bytecode_reserve *)contents;
fprintf(f, "%*s_Reserve_\n", indent_level, "");
fprintf(f, "%*sNum Items=", indent_level, "");
yasm_expr_print(reserve->numitems, f);
bc_reserve_resolve(yasm_bytecode *bc, int save,
yasm_calc_bc_dist_func calc_bc_dist)
{
- bytecode_reserve *reserve = (bytecode_reserve *)bc;
+ bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
yasm_bc_resolve_flags retval = YASM_BC_RESOLVE_MIN_LEN;
/*@null@*/ yasm_expr *temp;
yasm_expr **tempp;
yasm_bc_create_reserve(yasm_expr *numitems, unsigned int itemsize,
unsigned long line)
{
- bytecode_reserve *reserve;
-
- reserve = (bytecode_reserve *)
- yasm_bc_create_common(&bc_reserve_callback, sizeof(bytecode_reserve),
- line);
+ bytecode_reserve *reserve = yasm_xmalloc(sizeof(bytecode_reserve));
/*@-mustfree@*/
reserve->numitems = numitems;
/*@=mustfree@*/
reserve->itemsize = (unsigned char)itemsize;
- return (yasm_bytecode *)reserve;
+ return yasm_bc_create_common(&bc_reserve_callback, reserve, line);
}
static void
-bc_incbin_destroy(yasm_bytecode *bc)
+bc_incbin_destroy(void *contents)
{
- bytecode_incbin *incbin = (bytecode_incbin *)bc;
+ bytecode_incbin *incbin = (bytecode_incbin *)contents;
yasm_xfree(incbin->filename);
yasm_expr_destroy(incbin->start);
yasm_expr_destroy(incbin->maxlen);
+ yasm_xfree(contents);
}
static void
-bc_incbin_print(const yasm_bytecode *bc, FILE *f, int indent_level)
+bc_incbin_print(const void *contents, FILE *f, int indent_level)
{
- const bytecode_incbin *incbin = (const bytecode_incbin *)bc;
+ const bytecode_incbin *incbin = (const bytecode_incbin *)contents;
fprintf(f, "%*s_IncBin_\n", indent_level, "");
fprintf(f, "%*sFilename=`%s'\n", indent_level, "",
incbin->filename);
bc_incbin_resolve(yasm_bytecode *bc, int save,
yasm_calc_bc_dist_func calc_bc_dist)
{
- bytecode_incbin *incbin = (bytecode_incbin *)bc;
+ bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
FILE *f;
/*@null@*/ yasm_expr *temp;
yasm_expr **tempp;
yasm_output_expr_func output_expr,
/*@unused@*/ yasm_output_reloc_func output_reloc)
{
- bytecode_incbin *incbin = (bytecode_incbin *)bc;
+ bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
FILE *f;
/*@dependent@*/ /*@null@*/ const yasm_intnum *num;
unsigned long start = 0;
yasm_bc_create_incbin(char *filename, yasm_expr *start, yasm_expr *maxlen,
unsigned long line)
{
- bytecode_incbin *incbin;
-
- incbin = (bytecode_incbin *)
- yasm_bc_create_common(&bc_incbin_callback, sizeof(bytecode_incbin),
- line);
+ bytecode_incbin *incbin = yasm_xmalloc(sizeof(bytecode_incbin));
/*@-mustfree@*/
incbin->filename = filename;
incbin->maxlen = maxlen;
/*@=mustfree@*/
- return (yasm_bytecode *)incbin;
+ return yasm_bc_create_common(&bc_incbin_callback, incbin, line);
}
static void
-bc_align_destroy(yasm_bytecode *bc)
+bc_align_destroy(void *contents)
{
+ yasm_xfree(contents);
}
static void
-bc_align_print(const yasm_bytecode *bc, FILE *f, int indent_level)
+bc_align_print(const void *contents, FILE *f, int indent_level)
{
- const bytecode_align *align = (const bytecode_align *)bc;
+ const bytecode_align *align = (const bytecode_align *)contents;
fprintf(f, "%*s_Align_\n", indent_level, "");
fprintf(f, "%*sBoundary=%lu\n", indent_level, "", align->boundary);
}
yasm_bytecode *
yasm_bc_create_align(unsigned long boundary, unsigned long line)
{
- bytecode_align *align;
-
- align = (bytecode_align *)
- yasm_bc_create_common(&bc_align_callback, sizeof(bytecode_align),
- line);
+ bytecode_align *align = yasm_xmalloc(sizeof(bytecode_align));
align->boundary = boundary;
- return (yasm_bytecode *)align;
+ return yasm_bc_create_common(&bc_align_callback, align, line);
+}
+
+static void
+bc_insn_destroy(void *contents)
+{
+ bytecode_insn *insn = (bytecode_insn *)contents;
+ if (insn->num_operands > 0)
+ yasm_ops_delete(&insn->operands, 0);
+ if (insn->num_prefixes > 0) {
+ int i;
+ for (i=0; i<insn->num_prefixes; i++)
+ yasm_xfree(insn->prefixes[i]);
+ yasm_xfree(insn->prefixes);
+ }
+ if (insn->num_segregs > 0)
+ yasm_xfree(insn->segregs);
+ yasm_xfree(contents);
+}
+
+static void
+bc_insn_print(const void *contents, FILE *f, int indent_level)
+{
+}
+
+static void
+bc_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ bytecode_insn *insn = (bytecode_insn *)bc->contents;
+
+ yasm_arch_finalize_insn(insn->arch, bc, prev_bc, insn->insn_data,
+ insn->num_operands, &insn->operands,
+ insn->num_prefixes, insn->prefixes,
+ insn->num_segregs, insn->segregs);
+}
+
+static yasm_bc_resolve_flags
+bc_insn_resolve(yasm_bytecode *bc, int save,
+ yasm_calc_bc_dist_func calc_bc_dist)
+{
+ yasm_internal_error(N_("bc_insn_resolve() is not implemented"));
+ /*@notreached@*/
+ return YASM_BC_RESOLVE_ERROR;
+}
+
+static int
+bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_expr_func output_expr,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ yasm_internal_error(N_("bc_insn_tobytes() is not implemented"));
+ /*@notreached@*/
+ return 1;
+}
+
+yasm_bytecode *
+yasm_bc_create_insn(yasm_arch *arch, const unsigned long insn_data[4],
+ int num_operands, /*@null@*/ yasm_insn_operands *operands,
+ unsigned long line)
+{
+ bytecode_insn *insn = yasm_xmalloc(sizeof(bytecode_insn));
+
+ insn->arch = arch;
+ insn->insn_data[0] = insn_data[0];
+ insn->insn_data[1] = insn_data[1];
+ insn->insn_data[2] = insn_data[2];
+ insn->insn_data[3] = insn_data[3];
+ insn->num_operands = num_operands;
+ if (operands)
+ insn->operands = *operands; /* structure copy */
+ insn->num_prefixes = 0;
+ insn->prefixes = NULL;
+ insn->num_segregs = 0;
+ insn->segregs = NULL;
+
+ return yasm_bc_create_common(&bc_insn_callback, insn, line);
+}
+
+void
+yasm_bc_insn_add_prefix(yasm_bytecode *bc, const unsigned long prefix_data[4])
+{
+ bytecode_insn *insn = (bytecode_insn *)bc->contents;
+
+ assert(bc->callback == bc_insn_callback);
+
+ insn->prefixes =
+ yasm_xrealloc(insn->prefixes,
+ (insn->num_prefixes+1)*sizeof(unsigned long *));
+ insn->prefixes[insn->num_prefixes] =
+ yasm_xmalloc(4*sizeof(unsigned long));
+ insn->prefixes[insn->num_prefixes][0] = prefix_data[0];
+ insn->prefixes[insn->num_prefixes][1] = prefix_data[1];
+ insn->prefixes[insn->num_prefixes][2] = prefix_data[2];
+ insn->prefixes[insn->num_prefixes][3] = prefix_data[3];
+ insn->num_prefixes++;
+}
+
+void
+yasm_bc_insn_add_seg_prefix(yasm_bytecode *bc, unsigned long segreg)
+{
+ bytecode_insn *insn = (bytecode_insn *)bc->contents;
+
+ assert(bc->callback == bc_insn_callback);
+
+ insn->segregs =
+ yasm_xrealloc(insn->segregs,
+ (insn->num_segregs+1)*sizeof(unsigned long));
+ insn->segregs[insn->num_segregs] = segreg;
+ insn->num_segregs++;
}
yasm_section *
return;
if (bc->callback)
- bc->callback->destroy(bc);
+ bc->callback->destroy(bc->contents);
yasm_expr_destroy(bc->multiple);
yasm_xfree(bc->symrecs);
yasm_xfree(bc);
if (!bc->callback)
fprintf(f, "%*s_Empty_\n", indent_level, "");
else
- bc->callback->print(bc, f, indent_level);
+ bc->callback->print(bc->contents, f, indent_level);
fprintf(f, "%*sMultiple=", indent_level, "");
if (!bc->multiple)
fprintf(f, "nil (1)");
fprintf(f, "%*sOffset=%lx\n", indent_level, "", bc->offset);
}
+void
+yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ if (bc->callback)
+ bc->callback->finalize(bc, prev_bc);
+}
+
/*@null@*/ yasm_intnum *
yasm_common_calc_bc_dist(/*@null@*/ yasm_bytecode *precbc1,
/*@null@*/ yasm_bytecode *precbc2)
*/
void yasm_ea_set_nosplit(yasm_effaddr *ea, unsigned int nosplit);
+/** Set segment override for an effective address.
+ * Some architectures (such as x86) support segment overrides on effective
+ * addresses. A override of an override will result in a warning.
+ * \param ea effective address
+ * \param segreg segment register (0 if none)
+ */
+void yasm_ea_set_segreg(yasm_effaddr *ea, unsigned long segreg,
+ unsigned long line);
+
/** Delete (free allocated memory for) an effective address.
* \param ea effective address (only pointer to it).
*/
/*@only@*/ yasm_bytecode *yasm_bc_create_align
(unsigned long boundary, unsigned long line);
+/** Create a bytecode that represents a single instruction.
+ * \param arch instruction's architecture
+ * \param insn_data data that identifies the type of instruction
+ * \param num_operands number of operands
+ * \param operands instruction operands (may be NULL if no operands)
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode.
+ * \note Keeps the list of operands; do not call yasm_ops_delete() after
+ * giving operands to this function.
+ */
+/*@only@*/ yasm_bytecode *yasm_bc_create_insn
+ (yasm_arch *arch, const unsigned long insn_data[4], int num_operands,
+ /*@null@*/ yasm_insn_operands *operands, unsigned long line);
+
+/** Associate a prefix with an instruction bytecode.
+ * \param bc instruction bytecode
+ * \param prefix_data data the identifies the prefix
+ */
+void yasm_bc_insn_add_prefix(yasm_bytecode *bc,
+ const unsigned long prefix_data[4]);
+
+/** Associate a segment prefix with an instruction bytecode.
+ * \param bc instruction bytecode
+ * \param prefix_data data the identifies the prefix
+ */
+void yasm_bc_insn_add_seg_prefix(yasm_bytecode *bc, unsigned long segreg);
+
/** Get the section that contains a particular bytecode.
* \param bc bytecode
* \return Section containing bc (can be NULL if bytecode is not part of a
*/
void yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level);
+/** Finalize a bytecode after parsing.
+ * \param bc bytecode
+ * \param prev_bc bytecode directly preceding bc in a list of bytecodes
+ */
+void yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+
/** Common version of calc_bc_dist that takes offsets from bytecodes.
* Should be used for the final stages of optimizers as well as in yasm_objfmt
* yasm_expr output functions.
*/
typedef struct yasm_valparamhead yasm_valparamhead;
+/** A list of instruction operands (opaque type).
+ * The list goes from left-to-right as parsed.
+ * \see arch.h for related functions.
+ */
+typedef struct yasm_insn_operands yasm_insn_operands;
+
/** Expression operators usable in #yasm_expr expressions. */
typedef enum {
YASM_EXPR_IDENT, /**< No operation, just a value. */
* real bytecode in section.
*/
STAILQ_INIT(&s->bcs);
- bc = yasm_bc_create_common(NULL, sizeof(yasm_bytecode), 0);
+ bc = yasm_bc_create_common(NULL, NULL, 0);
bc->section = s;
STAILQ_INSERT_TAIL(&s->bcs, bc, link);
* real bytecode in section.
*/
STAILQ_INIT(&s->bcs);
- bc = yasm_bc_create_common(NULL, sizeof(yasm_bytecode), 0);
+ bc = yasm_bc_create_common(NULL, NULL, 0);
bc->section = s;
STAILQ_INSERT_TAIL(&s->bcs, bc, link);
}
}
+void
+yasm_object_finalize(yasm_object *object)
+{
+ yasm_section *sect;
+
+ /* Iterate through sections */
+ STAILQ_FOREACH(sect, &object->sections, link) {
+ yasm_bytecode *cur = STAILQ_FIRST(§->bcs);
+ yasm_bytecode *prev;
+
+ /* Skip our locally created empty bytecode first. */
+ prev = cur;
+ cur = STAILQ_NEXT(cur, link);
+
+ /* Iterate through the remainder, if any. */
+ while (cur) {
+ /* Finalize */
+ yasm_bc_finalize(cur, prev);
+ prev = cur;
+ cur = STAILQ_NEXT(cur, link);
+ }
+ }
+}
+
int
yasm_object_sections_traverse(yasm_object *object, /*@null@*/ void *d,
int (*func) (yasm_section *sect,
*/
void yasm_object_print(const yasm_object *object, FILE *f, int indent_level);
+/** Finalize an object after parsing.
+ * \param object object
+ */
+void yasm_object_finalize(yasm_object *object);
+
/** Traverses all sections in an object, calling a function on each section.
* \param object object
* \param d data pointer passed to func on each call
yasm_lc3b__parse_cpu,
yasm_lc3b__parse_check_id,
lc3b_parse_directive,
- yasm_lc3b__parse_insn,
- NULL, /*yasm_lc3b__parse_prefix*/
- NULL, /*yasm_lc3b__parse_seg_prefix*/
- NULL, /*yasm_lc3b__parse_seg_override*/
+ yasm_lc3b__finalize_insn,
lc3b_floatnum_tobytes,
yasm_lc3b__intnum_fixup_rel,
yasm_lc3b__intnum_tobytes,
LC3B_IMM_9_PC /* 9-bit, signed, word-multiple, PC relative */
} lc3b_imm_type;
-/* Structure with *all* inputs passed to lc3b_bytecode_new_insn().
- * IMPORTANT: im_ptr cannot be reused or freed after calling the function
- * (it doesn't make a copy).
- */
-typedef struct lc3b_new_insn_data {
- unsigned long line;
- /*@keep@*/ /*@null@*/ yasm_expr *imm;
- lc3b_imm_type imm_type;
- /*@null@*/ /*@dependent@*/ yasm_symrec *origin;
- unsigned int opcode;
-} lc3b_new_insn_data;
+/* Bytecode types */
+
+typedef struct lc3b_insn {
+ /*@null@*/ yasm_expr *imm; /* immediate or relative value */
+ lc3b_imm_type imm_type; /* size of the immediate */
+
+ /*@null@*/ /*@dependent@*/ yasm_symrec *origin; /* PC origin if needed */
-yasm_bytecode *yasm_lc3b__bc_create_insn(lc3b_new_insn_data *d);
+ unsigned int opcode; /* opcode */
+} lc3b_insn;
+
+void yasm_lc3b__bc_transform_insn(yasm_bytecode *bc, lc3b_insn *insn);
void yasm_lc3b__parse_cpu(yasm_arch *arch, const char *cpuid,
unsigned long line);
(yasm_arch *arch, unsigned long data[2], const char *id,
unsigned long line);
-/*@null@*/ yasm_bytecode *yasm_lc3b__parse_insn
- (yasm_arch *arch, const unsigned long data[2], int num_operands,
- /*@null@*/ yasm_insn_operands *operands, yasm_bytecode *prev_bc,
- unsigned long line);
+void yasm_lc3b__finalize_insn
+ (yasm_arch *arch, yasm_bytecode *bc, yasm_bytecode *prev_bc,
+ const unsigned long data[4], int num_operands,
+ /*@null@*/ yasm_insn_operands *operands, int num_prefixes,
+ unsigned long **prefixes, int num_segregs, const unsigned long *segregs);
int yasm_lc3b__intnum_fixup_rel
(yasm_arch *arch, yasm_intnum *intn, size_t valsize,
#include "lc3barch.h"
-/* Bytecode types */
-
-typedef struct lc3b_insn {
- yasm_bytecode bc; /* base structure */
-
- /*@null@*/ yasm_expr *imm; /* immediate or relative value */
- lc3b_imm_type imm_type; /* size of the immediate */
-
- /*@null@*/ /*@dependent@*/ yasm_symrec *origin; /* PC origin if needed */
-
- unsigned int opcode; /* opcode */
-} lc3b_insn;
-
/* Bytecode callback function prototypes */
-static void lc3b_bc_insn_destroy(yasm_bytecode *bc);
-static void lc3b_bc_insn_print(const yasm_bytecode *bc, FILE *f,
+static void lc3b_bc_insn_destroy(void *contents);
+static void lc3b_bc_insn_print(const void *contents, FILE *f,
int indent_level);
static yasm_bc_resolve_flags lc3b_bc_insn_resolve
(yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
static const yasm_bytecode_callback lc3b_bc_callback_insn = {
lc3b_bc_insn_destroy,
lc3b_bc_insn_print,
+ yasm_bc_finalize_common,
lc3b_bc_insn_resolve,
lc3b_bc_insn_tobytes
};
-/*@-compmempass -mustfree@*/
-yasm_bytecode *
-yasm_lc3b__bc_create_insn(lc3b_new_insn_data *d)
+void
+yasm_lc3b__bc_transform_insn(yasm_bytecode *bc, lc3b_insn *insn)
{
- lc3b_insn *insn;
-
- insn = (lc3b_insn *)yasm_bc_create_common(&lc3b_bc_callback_insn,
- sizeof(lc3b_insn), d->line);
-
- insn->imm = d->imm;
- if (d->imm)
- insn->imm_type = d->imm_type;
- else
- insn->imm_type = LC3B_IMM_NONE;
- insn->origin = d->origin;
- insn->opcode = d->opcode;
-
- return (yasm_bytecode *)insn;
+ yasm_bc_transform(bc, &lc3b_bc_callback_insn, insn);
}
-/*@=compmempass =mustfree@*/
static void
-lc3b_bc_insn_destroy(yasm_bytecode *bc)
+lc3b_bc_insn_destroy(void *contents)
{
- lc3b_insn *insn = (lc3b_insn *)bc;
+ lc3b_insn *insn = (lc3b_insn *)contents;
if (insn->imm)
yasm_expr_destroy(insn->imm);
+ yasm_xfree(contents);
}
static void
-lc3b_bc_insn_print(const yasm_bytecode *bc, FILE *f, int indent_level)
+lc3b_bc_insn_print(const void *contents, FILE *f, int indent_level)
{
- const lc3b_insn *insn = (const lc3b_insn *)bc;
+ const lc3b_insn *insn = (const lc3b_insn *)contents;
fprintf(f, "%*s_Instruction_\n", indent_level, "");
fprintf(f, "%*sImmediate Value:", indent_level, "");
lc3b_bc_insn_resolve(yasm_bytecode *bc, int save,
yasm_calc_bc_dist_func calc_bc_dist)
{
- lc3b_insn *insn = (lc3b_insn *)bc;
+ lc3b_insn *insn = (lc3b_insn *)bc->contents;
/*@null@*/ yasm_expr *temp;
/*@dependent@*/ /*@null@*/ const yasm_intnum *num;
long rel;
yasm_output_expr_func output_expr,
/*@unused@*/ yasm_output_reloc_func output_reloc)
{
- lc3b_insn *insn = (lc3b_insn *)bc;
+ lc3b_insn *insn = (lc3b_insn *)bc->contents;
/* Output opcode */
YASM_SAVE_16_L(*bufp, insn->opcode);
{ 0, 0xF000, 1, {OPT_Imm|OPA_Imm|OPI_8, 0, 0} }
};
-yasm_bytecode *
-yasm_lc3b__parse_insn(yasm_arch *arch, const unsigned long data[4],
- int num_operands, yasm_insn_operands *operands,
- yasm_bytecode *prev_bc, unsigned long line)
+void
+yasm_lc3b__finalize_insn(yasm_arch *arch, yasm_bytecode *bc,
+ yasm_bytecode *prev_bc, const unsigned long data[4],
+ int num_operands,
+ /*@null@*/ yasm_insn_operands *operands,
+ int num_prefixes, unsigned long **prefixes,
+ int num_segregs, const unsigned long *segregs)
{
- lc3b_new_insn_data d;
+ lc3b_insn *insn;
int num_info = (int)(data[1]&0xFF);
lc3b_insn_info *info = (lc3b_insn_info *)data[0];
unsigned long mod_data = data[1] >> 8;
if (!found) {
/* Didn't find a matching one */
- yasm__error(line, N_("invalid combination of opcode and operands"));
- return NULL;
+ yasm__error(bc->line,
+ N_("invalid combination of opcode and operands"));
+ return;
}
/* Copy what we can from info */
- d.line = line;
- d.imm = NULL;
- d.imm_type = LC3B_IMM_NONE;
- d.origin = NULL;
- d.opcode = info->opcode;
+ insn = yasm_xmalloc(sizeof(lc3b_insn));
+ insn->imm = NULL;
+ insn->imm_type = LC3B_IMM_NONE;
+ insn->origin = NULL;
+ insn->opcode = info->opcode;
/* Apply modifiers */
if (info->modifiers & MOD_OpHAdd) {
- d.opcode += ((unsigned int)(mod_data & 0xFF))<<8;
+ insn->opcode += ((unsigned int)(mod_data & 0xFF))<<8;
mod_data >>= 8;
}
if (info->modifiers & MOD_OpLAdd) {
- d.opcode += (unsigned int)(mod_data & 0xFF);
+ insn->opcode += (unsigned int)(mod_data & 0xFF);
/*mod_data >>= 8;*/
}
case OPA_DR:
if (op->type != YASM_INSN__OPERAND_REG)
yasm_internal_error(N_("invalid operand conversion"));
- d.opcode |= ((unsigned int)(op->data.reg & 0x7)) << 9;
+ insn->opcode |= ((unsigned int)(op->data.reg & 0x7)) << 9;
break;
case OPA_SR:
if (op->type != YASM_INSN__OPERAND_REG)
yasm_internal_error(N_("invalid operand conversion"));
- d.opcode |= ((unsigned int)(op->data.reg & 0x7)) << 6;
+ insn->opcode |= ((unsigned int)(op->data.reg & 0x7)) << 6;
break;
case OPA_Imm:
switch (op->type) {
case YASM_INSN__OPERAND_IMM:
- d.imm = op->data.val;
+ insn->imm = op->data.val;
break;
case YASM_INSN__OPERAND_REG:
- d.imm = yasm_expr_create_ident(yasm_expr_int(
+ insn->imm = yasm_expr_create_ident(yasm_expr_int(
yasm_intnum_create_uint(op->data.reg & 0x7)),
- line);
+ bc->line);
break;
default:
yasm_internal_error(N_("invalid operand conversion"));
yasm_internal_error(N_("unknown operand action"));
}
- d.imm_type = (info->operands[i] & OPI_MASK)>>3;
- if (d.imm_type == LC3B_IMM_9_PC)
- d.origin = yasm_symtab_define_label2("$", prev_bc, 0, line);
+ insn->imm_type = (info->operands[i] & OPI_MASK)>>3;
+ if (insn->imm_type == LC3B_IMM_9_PC)
+ insn->origin = yasm_symtab_define_label2("$", prev_bc, 0,
+ bc->line);
}
}
- /* Create the bytecode and return it */
- return yasm_lc3b__bc_create_insn(&d);
+ if (!insn->imm)
+ insn->imm_type = LC3B_IMM_NONE;
+
+ /* Transform the bytecode */
+ yasm_lc3b__bc_transform_insn(bc, insn);
}
fprintf(f, "%s", name[segreg&7]);
}
-static void
-x86_parse_prefix(yasm_arch *arch, yasm_bytecode *bc,
- const unsigned long data[4], unsigned long line)
-{
- switch((x86_parse_insn_prefix)data[0]) {
- case X86_LOCKREP:
- yasm_x86__bc_insn_set_lockrep_prefix(bc, data[1] & 0xff, line);
- break;
- case X86_ADDRSIZE:
- yasm_x86__bc_insn_addrsize_override(bc, data[1]);
- break;
- case X86_OPERSIZE:
- yasm_x86__bc_insn_opersize_override(bc, data[1]);
- break;
- }
-}
-
-static void
-x86_parse_seg_prefix(yasm_arch *arch, yasm_bytecode *bc, unsigned long segreg,
- unsigned long line)
-{
- yasm_x86__ea_set_segment(yasm_x86__bc_insn_get_ea(bc),
- (unsigned char)(segreg>>8), line);
-}
-
-static void
-x86_parse_seg_override(yasm_arch *arch, yasm_effaddr *ea,
- unsigned long segreg, unsigned long line)
-{
- yasm_x86__ea_set_segment(ea, (unsigned char)(segreg>>8), line);
-}
-
/* Define x86 machines -- see arch.h for details */
static yasm_arch_machine x86_machines[] = {
{ "IA-32 and derivatives", "x86" },
yasm_x86__parse_cpu,
yasm_x86__parse_check_id,
x86_parse_directive,
- yasm_x86__parse_insn,
- x86_parse_prefix,
- x86_parse_seg_prefix,
- x86_parse_seg_override,
+ yasm_x86__finalize_insn,
yasm_x86__floatnum_tobytes,
yasm_x86__intnum_fixup_rel,
yasm_x86__intnum_tobytes,
unsigned long reg, unsigned int bits,
x86_rex_bit_pos rexbit);
-void yasm_x86__ea_set_segment(/*@null@*/ yasm_effaddr *ea,
- unsigned int segment, unsigned long line);
void yasm_x86__ea_set_disponly(yasm_effaddr *ea);
yasm_effaddr *yasm_x86__ea_create_reg(unsigned long reg, unsigned char *rex,
unsigned int bits);
unsigned int prefix,
unsigned long line);
-/* Structure with *all* inputs passed to x86_bytecode_new_insn().
- * IMPORTANT: ea_ptr and im_ptr cannot be reused or freed after calling the
- * function (it doesn't make a copy).
- */
-typedef struct x86_new_insn_data {
- unsigned long line;
- /*@keep@*/ /*@null@*/ yasm_effaddr *ea;
- /*@null@*/ /*@dependent@*/ yasm_symrec *ea_origin;
- /*@keep@*/ /*@null@*/ yasm_expr *imm;
- unsigned char opersize;
- unsigned char def_opersize_64;
- unsigned char special_prefix;
- unsigned char op_len;
- unsigned char op[3];
- unsigned char spare; /* bits to go in 'spare' field of ModRM */
- unsigned char rex;
- unsigned char im_len;
- unsigned char im_sign;
+/* Bytecode types */
+
+typedef struct x86_insn {
+ /*@null@*/ yasm_effaddr *ea; /* effective address */
+
+ /*@null@*/ yasm_immval *imm; /* immediate or relative value */
+
+ unsigned char opcode[3]; /* opcode */
+ unsigned char opcode_len;
+
+ unsigned char addrsize; /* 0 or =mode_bits => no override */
+ unsigned char opersize; /* 0 or =mode_bits => no override */
+ unsigned char lockrep_pre; /* 0 indicates no prefix */
+
+ unsigned char def_opersize_64; /* default operand size in 64-bit mode */
+ unsigned char special_prefix; /* "special" prefix (0=none) */
+
+ unsigned char rex; /* REX AMD64 extension, 0 if none,
+ 0xff if not allowed (high 8 bit reg used) */
+
+ /* HACK, but a space-saving one: shift opcodes have an immediate
+ * form and a ,1 form (with no immediate). In the parser, we
+ * set this and opcode_len=1, but store the ,1 version in the
+ * second byte of the opcode array. We then choose between the
+ * two versions once we know the actual value of imm (because we
+ * don't know it in the parser module).
+ *
+ * A override to force the imm version should just leave this at
+ * 0. Then later code won't know the ,1 version even exists.
+ * TODO: Figure out how this affects CPU flags processing.
+ *
+ * Call x86_SetInsnShiftFlag() to set this flag to 1.
+ */
unsigned char shift_op;
+
+ /* HACK, similar to that for shift_op above, for optimizing instructions
+ * that take a sign-extended imm8 as well as imm values (eg, the arith
+ * instructions and a subset of the imul instructions).
+ */
unsigned char signext_imm8_op;
+
+ /* HACK, similar to those above, for optimizing long (modrm+sib) mov
+ * instructions in amd64 into short mov instructions if a 32-bit address
+ * override is applied in 64-bit mode to an EA of just an offset (no
+ * registers) and the target register is al/ax/eax/rax.
+ */
unsigned char shortmov_op;
-} x86_new_insn_data;
-yasm_bytecode *yasm_x86__bc_create_insn(yasm_arch *arch, x86_new_insn_data *d);
+ unsigned char mode_bits;
+} x86_insn;
-/* Structure with *all* inputs passed to x86_bytecode_new_jmp().
- * Pass 0 for the opcode_len if that version of the opcode doesn't exist.
- */
-typedef struct x86_new_jmp_data {
- unsigned long line;
- /*@keep@*/ yasm_expr *target;
- /*@dependent@*/ yasm_symrec *origin;
+typedef struct x86_jmp {
+ yasm_expr *target; /* target location */
+ /*@dependent@*/ yasm_symrec *origin; /* jump origin */
+
+ struct {
+ unsigned char opcode[3];
+ unsigned char opcode_len; /* 0 = no opc for this version */
+ } shortop, nearop, farop;
+
+ /* which opcode are we using? */
+ /* The *FORCED forms are specified in the source as such */
x86_jmp_opcode_sel op_sel;
- unsigned char short_op_len;
- unsigned char short_op[3];
- unsigned char near_op_len;
- unsigned char near_op[3];
- unsigned char far_op_len;
- unsigned char far_op[3];
- unsigned char addrsize;
- unsigned char opersize;
-} x86_new_jmp_data;
-
-yasm_bytecode *yasm_x86__bc_create_jmp(yasm_arch *arch, x86_new_jmp_data *d);
+
+ unsigned char addrsize; /* 0 or =mode_bits => no override */
+ unsigned char opersize; /* 0 indicates no override */
+ unsigned char lockrep_pre; /* 0 indicates no prefix */
+
+ unsigned char mode_bits;
+} x86_jmp;
+
+void yasm_x86__bc_transform_jmp(yasm_bytecode *bc, x86_jmp *jmp);
+void yasm_x86__bc_transform_insn(yasm_bytecode *bc, x86_insn *insn);
+
+void yasm_x86__bc_apply_prefixes
+ (yasm_bytecode *bc, int num_prefixes, unsigned long **prefixes,
+ int num_segregs, const unsigned long *segregs);
+
+void yasm_x86__ea_init(yasm_effaddr *ea, unsigned int spare,
+ /*@null@*/ yasm_symrec *origin);
/* Check an effective address. Returns 0 if EA was successfully determined,
* 1 if invalid EA, or 2 if indeterminate EA.
unsigned long line);
yasm_arch_check_id_retval yasm_x86__parse_check_id
- (yasm_arch *arch, unsigned long data[2], const char *id,
+ (yasm_arch *arch, unsigned long data[4], const char *id,
unsigned long line);
-/*@null@*/ yasm_bytecode *yasm_x86__parse_insn
- (yasm_arch *arch, const unsigned long data[2], int num_operands,
- /*@null@*/ yasm_insn_operands *operands, yasm_bytecode *prev_bc,
- unsigned long line);
+void yasm_x86__finalize_insn
+ (yasm_arch *arch, yasm_bytecode *bc, yasm_bytecode *prev_bc,
+ const unsigned long data[4], int num_operands,
+ /*@null@*/ yasm_insn_operands *operands, int num_prefixes,
+ unsigned long **prefixes, int num_segregs, const unsigned long *segregs);
int yasm_x86__floatnum_tobytes
(yasm_arch *arch, const yasm_floatnum *flt, unsigned char *buf,
/* PC-relative portions are for AMD64 only (RIP addressing) */
/*@null@*/ /*@dependent@*/ yasm_symrec *origin; /* pcrel origin */
- unsigned char segment; /* segment override, 0 if none */
-
/* How the spare (register) bits in Mod/RM are handled:
* Even if valid_modrm=0, the spare bits are still valid (don't overwrite!)
* They're set in bytecode_create_insn().
unsigned char pcrel; /* 1 if PC-relative transformation needed */
} x86_effaddr;
-/* Bytecode types */
-
-typedef struct x86_insn {
- yasm_bytecode bc; /* base structure */
-
- /*@null@*/ x86_effaddr *ea; /* effective address */
-
- /*@null@*/ yasm_immval *imm;/* immediate or relative value */
-
- unsigned char opcode[3]; /* opcode */
- unsigned char opcode_len;
-
- unsigned char addrsize; /* 0 or =mode_bits => no override */
- unsigned char opersize; /* 0 or =mode_bits => no override */
- unsigned char lockrep_pre; /* 0 indicates no prefix */
-
- unsigned char def_opersize_64; /* default operand size in 64-bit mode */
- unsigned char special_prefix; /* "special" prefix (0=none) */
-
- unsigned char rex; /* REX AMD64 extension, 0 if none,
- 0xff if not allowed (high 8 bit reg used) */
-
- /* HACK, but a space-saving one: shift opcodes have an immediate
- * form and a ,1 form (with no immediate). In the parser, we
- * set this and opcode_len=1, but store the ,1 version in the
- * second byte of the opcode array. We then choose between the
- * two versions once we know the actual value of imm (because we
- * don't know it in the parser module).
- *
- * A override to force the imm version should just leave this at
- * 0. Then later code won't know the ,1 version even exists.
- * TODO: Figure out how this affects CPU flags processing.
- *
- * Call x86_SetInsnShiftFlag() to set this flag to 1.
- */
- unsigned char shift_op;
-
- /* HACK, similar to that for shift_op above, for optimizing instructions
- * that take a sign-extended imm8 as well as imm values (eg, the arith
- * instructions and a subset of the imul instructions).
- */
- unsigned char signext_imm8_op;
-
- /* HACK, similar to those above, for optimizing long (modrm+sib) mov
- * instructions in amd64 into short mov instructions if a 32-bit address
- * override is applied in 64-bit mode to an EA of just an offset (no
- * registers) and the target register is al/ax/eax/rax.
- */
- unsigned char shortmov_op;
-
- unsigned char mode_bits;
-} x86_insn;
-
-typedef struct x86_jmp {
- yasm_bytecode bc; /* base structure */
-
- yasm_expr *target; /* target location */
- /*@dependent@*/ yasm_symrec *origin; /* jump origin */
-
- struct {
- unsigned char opcode[3];
- unsigned char opcode_len; /* 0 = no opc for this version */
- } shortop, nearop, farop;
-
- /* which opcode are we using? */
- /* The *FORCED forms are specified in the source as such */
- x86_jmp_opcode_sel op_sel;
-
- unsigned char addrsize; /* 0 or =mode_bits => no override */
- unsigned char opersize; /* 0 indicates no override */
- unsigned char lockrep_pre; /* 0 indicates no prefix */
-
- unsigned char mode_bits;
-} x86_jmp;
-
/* Effective address callback function prototypes */
static void x86_ea_destroy(yasm_effaddr *ea);
/* Bytecode callback function prototypes */
-static void x86_bc_insn_destroy(yasm_bytecode *bc);
-static void x86_bc_insn_print(const yasm_bytecode *bc, FILE *f,
+static void x86_bc_insn_destroy(void *contents);
+static void x86_bc_insn_print(const void *contents, FILE *f,
int indent_level);
static yasm_bc_resolve_flags x86_bc_insn_resolve
(yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
void *d, yasm_output_expr_func output_expr,
/*@null@*/ yasm_output_reloc_func output_reloc);
-static void x86_bc_jmp_destroy(yasm_bytecode *bc);
-static void x86_bc_jmp_print(const yasm_bytecode *bc, FILE *f,
- int indent_level);
+static void x86_bc_jmp_destroy(void *contents);
+static void x86_bc_jmp_print(const void *contents, FILE *f, int indent_level);
static yasm_bc_resolve_flags x86_bc_jmp_resolve
(yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
static int x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp,
static const yasm_bytecode_callback x86_bc_callback_insn = {
x86_bc_insn_destroy,
x86_bc_insn_print,
+ yasm_bc_finalize_common,
x86_bc_insn_resolve,
x86_bc_insn_tobytes
};
static const yasm_bytecode_callback x86_bc_callback_jmp = {
x86_bc_jmp_destroy,
x86_bc_jmp_print,
+ yasm_bc_finalize_common,
x86_bc_jmp_resolve,
x86_bc_jmp_tobytes
};
return 0;
}
-/*@-compmempass -mustfree@*/
-yasm_bytecode *
-yasm_x86__bc_create_insn(yasm_arch *arch, x86_new_insn_data *d)
+void
+yasm_x86__bc_transform_jmp(yasm_bytecode *bc, x86_jmp *jmp)
{
- yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
- x86_insn *insn;
-
- insn = (x86_insn *)yasm_bc_create_common(&x86_bc_callback_insn,
- sizeof(x86_insn), d->line);
-
- insn->ea = (x86_effaddr *)d->ea;
- if (d->ea) {
- insn->ea->origin = d->ea_origin;
- insn->ea->modrm &= 0xC7; /* zero spare/reg bits */
- insn->ea->modrm |= (d->spare << 3) & 0x38; /* plug in provided bits */
- }
-
- if (d->imm) {
- insn->imm = yasm_imm_create_expr(d->imm);
- insn->imm->len = d->im_len;
- insn->imm->sign = d->im_sign;
- } else
- insn->imm = NULL;
-
- insn->opcode[0] = d->op[0];
- insn->opcode[1] = d->op[1];
- insn->opcode[2] = d->op[2];
- insn->opcode_len = d->op_len;
-
- insn->addrsize = 0;
- insn->opersize = d->opersize;
- insn->def_opersize_64 = d->def_opersize_64;
- insn->special_prefix = d->special_prefix;
- insn->lockrep_pre = 0;
- insn->rex = d->rex;
- insn->shift_op = d->shift_op;
- insn->signext_imm8_op = d->signext_imm8_op;
- insn->shortmov_op = d->shortmov_op;
-
- insn->mode_bits = arch_x86->mode_bits;
-
- return (yasm_bytecode *)insn;
+ yasm_bc_transform(bc, &x86_bc_callback_jmp, jmp);
}
-/*@=compmempass =mustfree@*/
-/*@-compmempass -mustfree@*/
-yasm_bytecode *
-yasm_x86__bc_create_jmp(yasm_arch *arch, x86_new_jmp_data *d)
+void
+yasm_x86__bc_transform_insn(yasm_bytecode *bc, x86_insn *insn)
{
- yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
- x86_jmp *jmp;
-
- jmp = (x86_jmp *) yasm_bc_create_common(&x86_bc_callback_jmp,
- sizeof(x86_jmp), d->line);
-
- jmp->target = d->target;
- jmp->origin = d->origin;
- jmp->op_sel = d->op_sel;
-
- if ((d->op_sel == JMP_SHORT_FORCED) && (d->near_op_len == 0))
- yasm__error(d->line,
- N_("no SHORT form of that jump instruction exists"));
- if ((d->op_sel == JMP_NEAR_FORCED) && (d->short_op_len == 0))
- yasm__error(d->line,
- N_("no NEAR form of that jump instruction exists"));
-
- jmp->shortop.opcode[0] = d->short_op[0];
- jmp->shortop.opcode[1] = d->short_op[1];
- jmp->shortop.opcode[2] = d->short_op[2];
- jmp->shortop.opcode_len = d->short_op_len;
-
- jmp->nearop.opcode[0] = d->near_op[0];
- jmp->nearop.opcode[1] = d->near_op[1];
- jmp->nearop.opcode[2] = d->near_op[2];
- jmp->nearop.opcode_len = d->near_op_len;
-
- jmp->farop.opcode[0] = d->far_op[0];
- jmp->farop.opcode[1] = d->far_op[1];
- jmp->farop.opcode[2] = d->far_op[2];
- jmp->farop.opcode_len = d->far_op_len;
-
- jmp->addrsize = d->addrsize;
- jmp->opersize = d->opersize;
- jmp->lockrep_pre = 0;
-
- jmp->mode_bits = arch_x86->mode_bits;
-
- return (yasm_bytecode *)jmp;
+ yasm_bc_transform(bc, &x86_bc_callback_insn, insn);
}
-/*@=compmempass =mustfree@*/
void
-yasm_x86__ea_set_segment(yasm_effaddr *ea, unsigned int segment,
- unsigned long line)
+yasm_x86__ea_init(yasm_effaddr *ea, unsigned int spare, yasm_symrec *origin)
{
x86_effaddr *x86_ea = (x86_effaddr *)ea;
-
- if (!ea)
- return;
-
- if (segment != 0 && x86_ea->segment != 0)
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("multiple segment overrides, using leftmost"));
-
- x86_ea->segment = (unsigned char)segment;
+ x86_ea->origin = origin;
+ x86_ea->modrm &= 0xC7; /* zero spare/reg bits */
+ x86_ea->modrm |= (spare << 3) & 0x38; /* plug in provided bits */
}
void
x86_ea->ea.disp = (yasm_expr *)NULL;
x86_ea->ea.len = 0;
x86_ea->ea.nosplit = 0;
- x86_ea->segment = 0;
+ x86_ea->ea.segreg = 0;
x86_ea->modrm = 0xC0 | rm; /* Mod=11, R/M=Reg, Reg=0 */
x86_ea->valid_modrm = 1;
x86_ea->need_modrm = 1;
x86_ea->ea.disp = e;
x86_ea->ea.len = 0;
x86_ea->ea.nosplit = 0;
- x86_ea->segment = 0;
+ x86_ea->ea.segreg = 0;
x86_ea->modrm = 0;
x86_ea->valid_modrm = 0;
x86_ea->need_modrm = 1;
x86_ea->ea.disp = imm;
x86_ea->ea.len = (unsigned char)im_len;
x86_ea->ea.nosplit = 0;
- x86_ea->segment = 0;
+ x86_ea->ea.segreg = 0;
x86_ea->modrm = 0;
x86_ea->valid_modrm = 0;
x86_ea->need_modrm = 0;
}
/*@=compmempass@*/
-yasm_effaddr *
-yasm_x86__bc_insn_get_ea(yasm_bytecode *bc)
-{
- if (!bc)
- return NULL;
-
- if (bc->callback != &x86_bc_callback_insn)
- yasm_internal_error(N_("Trying to get EA of non-instruction"));
-
- return (yasm_effaddr *)(((x86_insn *)bc)->ea);
-}
-
void
-yasm_x86__bc_insn_opersize_override(yasm_bytecode *bc, unsigned int opersize)
+yasm_x86__bc_apply_prefixes(yasm_bytecode *bc, int num_prefixes,
+ unsigned long **prefixes, int num_segregs,
+ const unsigned long *segregs)
{
- if (!bc)
- return;
+ x86_insn *insn = (x86_insn *)bc->contents;
+ x86_jmp *jmp = (x86_jmp *)bc->contents;
+ int i;
+ unsigned char *opersize, *addrsize, *lockrep_pre;
+ /* Set pointers appropriately for bytecode type */
if (bc->callback == &x86_bc_callback_insn) {
- x86_insn *insn = (x86_insn *)bc;
- insn->opersize = (unsigned char)opersize;
- } else if (bc->callback == &x86_bc_callback_jmp) {
- x86_jmp *jmp = (x86_jmp *)bc;
- jmp->opersize = (unsigned char)opersize;
- } else
- yasm_internal_error(N_("OperSize override applied to non-instruction"));
-}
-
-void
-yasm_x86__bc_insn_addrsize_override(yasm_bytecode *bc, unsigned int addrsize)
-{
- if (!bc)
- return;
-
- if (bc->callback == &x86_bc_callback_insn) {
- x86_insn *insn = (x86_insn *)bc;
- insn->addrsize = (unsigned char)addrsize;
- } else if (bc->callback == &x86_bc_callback_jmp) {
- x86_jmp *jmp = (x86_jmp *)bc;
- jmp->addrsize = (unsigned char)addrsize;
- } else
- yasm_internal_error(N_("AddrSize override applied to non-instruction"));
-}
-
-void
-yasm_x86__bc_insn_set_lockrep_prefix(yasm_bytecode *bc, unsigned int prefix,
- unsigned long line)
-{
- unsigned char *lockrep_pre = (unsigned char *)NULL;
-
- if (!bc)
- return;
-
- if (bc->callback == &x86_bc_callback_insn) {
- x86_insn *insn = (x86_insn *)bc;
+ opersize = &insn->opersize;
+ addrsize = &insn->addrsize;
lockrep_pre = &insn->lockrep_pre;
} else if (bc->callback == &x86_bc_callback_jmp) {
- x86_jmp *jmp = (x86_jmp *)bc;
+ opersize = &jmp->opersize;
+ addrsize = &jmp->addrsize;
lockrep_pre = &jmp->lockrep_pre;
} else
- yasm_internal_error(N_("LockRep prefix applied to non-instruction"));
-
- if (*lockrep_pre != 0)
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("multiple LOCK or REP prefixes, using leftmost"));
+ yasm_internal_error(N_("Prefixes applied to non-instruction"));
+
+ for (i=0; i<num_prefixes; i++) {
+ switch ((x86_parse_insn_prefix)prefixes[i][0]) {
+ case X86_LOCKREP:
+ if (*lockrep_pre != 0)
+ yasm__warning(YASM_WARN_GENERAL, bc->line,
+ N_("multiple LOCK or REP prefixes, using leftmost"));
+ *lockrep_pre = (unsigned char)prefixes[i][1];
+ break;
+ case X86_ADDRSIZE:
+ *addrsize = (unsigned char)prefixes[i][1];
+ break;
+ case X86_OPERSIZE:
+ *opersize = (unsigned char)prefixes[i][1];
+ break;
+ }
+ }
- *lockrep_pre = (unsigned char)prefix;
+ if (bc->callback == &x86_bc_callback_insn)
+ for (i=0; i<num_segregs; i++)
+ yasm_ea_set_segreg(insn->ea, segregs[i], bc->line);
}
static void
-x86_bc_insn_destroy(yasm_bytecode *bc)
+x86_bc_insn_destroy(void *contents)
{
- x86_insn *insn = (x86_insn *)bc;
+ x86_insn *insn = (x86_insn *)contents;
if (insn->ea)
yasm_ea_destroy((yasm_effaddr *)insn->ea);
if (insn->imm) {
yasm_expr_destroy(insn->imm->val);
yasm_xfree(insn->imm);
}
+ yasm_xfree(contents);
}
static void
-x86_bc_jmp_destroy(yasm_bytecode *bc)
+x86_bc_jmp_destroy(void *contents)
{
- x86_jmp *jmp = (x86_jmp *)bc;
+ x86_jmp *jmp = (x86_jmp *)contents;
yasm_expr_destroy(jmp->target);
+ yasm_xfree(contents);
}
static void
{
const x86_effaddr *x86_ea = (const x86_effaddr *)ea;
fprintf(f, "%*sSegmentOv=%02x PCRel=%u\n", indent_level, "",
- (unsigned int)x86_ea->segment, (unsigned int)x86_ea->pcrel);
+ (unsigned int)x86_ea->ea.segreg, (unsigned int)x86_ea->pcrel);
fprintf(f, "%*sModRM=%03o ValidRM=%u NeedRM=%u\n", indent_level, "",
(unsigned int)x86_ea->modrm, (unsigned int)x86_ea->valid_modrm,
(unsigned int)x86_ea->need_modrm);
}
static void
-x86_bc_insn_print(const yasm_bytecode *bc, FILE *f, int indent_level)
+x86_bc_insn_print(const void *contents, FILE *f, int indent_level)
{
- const x86_insn *insn = (const x86_insn *)bc;
+ const x86_insn *insn = (const x86_insn *)contents;
fprintf(f, "%*s_Instruction_\n", indent_level, "");
fprintf(f, "%*sEffective Address:", indent_level, "");
}
static void
-x86_bc_jmp_print(const yasm_bytecode *bc, FILE *f, int indent_level)
+x86_bc_jmp_print(const void *contents, FILE *f, int indent_level)
{
- const x86_jmp *jmp = (const x86_jmp *)bc;
+ const x86_jmp *jmp = (const x86_jmp *)contents;
fprintf(f, "%*s_Jump_\n", indent_level, "");
fprintf(f, "%*sTarget=", indent_level, "");
x86_bc_insn_resolve(yasm_bytecode *bc, int save,
yasm_calc_bc_dist_func calc_bc_dist)
{
- x86_insn *insn = (x86_insn *)bc;
+ x86_insn *insn = (x86_insn *)bc->contents;
/*@null@*/ yasm_expr *temp;
- x86_effaddr *x86_ea = insn->ea;
+ x86_effaddr *x86_ea = (x86_effaddr *)insn->ea;
yasm_effaddr *ea = &x86_ea->ea;
yasm_immval *imm = insn->imm;
yasm_bc_resolve_flags retval = YASM_BC_RESOLVE_MIN_LEN;
/* Compute length of ea and add to total */
bc->len += eat.need_modrm + (eat.need_sib ? 1:0) + displen;
- bc->len += (eat.segment != 0) ? 1 : 0;
+ bc->len += (eat.ea.segreg != 0) ? 1 : 0;
}
if (imm) {
x86_bc_jmp_resolve(yasm_bytecode *bc, int save,
yasm_calc_bc_dist_func calc_bc_dist)
{
- x86_jmp *jmp = (x86_jmp *)bc;
+ x86_jmp *jmp = (x86_jmp *)bc->contents;
yasm_bc_resolve_flags retval = YASM_BC_RESOLVE_MIN_LEN;
/*@null@*/ yasm_expr *temp;
/*@dependent@*/ /*@null@*/ const yasm_intnum *num;
yasm_output_expr_func output_expr,
/*@unused@*/ yasm_output_reloc_func output_reloc)
{
- x86_insn *insn = (x86_insn *)bc;
- /*@null@*/ x86_effaddr *x86_ea = insn->ea;
+ x86_insn *insn = (x86_insn *)bc->contents;
+ /*@null@*/ x86_effaddr *x86_ea = (x86_effaddr *)insn->ea;
/*@null@*/ yasm_effaddr *ea = &x86_ea->ea;
yasm_immval *imm = insn->imm;
unsigned int i;
YASM_WRITE_8(*bufp, insn->special_prefix);
if (insn->lockrep_pre != 0)
YASM_WRITE_8(*bufp, insn->lockrep_pre);
- if (x86_ea && x86_ea->segment != 0)
- YASM_WRITE_8(*bufp, x86_ea->segment);
+ if (x86_ea && ea->segreg != 0)
+ YASM_WRITE_8(*bufp, (unsigned char)(ea->segreg>>8));
if (insn->opersize != 0 &&
((insn->mode_bits != 64 && insn->opersize != insn->mode_bits) ||
(insn->mode_bits == 64 && insn->opersize == 16)))
yasm_output_expr_func output_expr,
/*@unused@*/ yasm_output_reloc_func output_reloc)
{
- x86_jmp *jmp = (x86_jmp *)bc;
+ x86_jmp *jmp = (x86_jmp *)bc->contents;
unsigned char opersize;
unsigned int i;
unsigned char *bufp_orig = *bufp;
data[1] = ((mod)<<8) | \
((unsigned char)(sizeof(group##_insn)/sizeof(x86_insn_info))); \
data[2] = cpu; \
+ data[3] = arch_x86->mode_bits; \
} while (0)
#define RET_INSN(group, mod, cpu) do { \
};
-static yasm_bytecode *
-x86_new_jmp(yasm_arch *arch, const unsigned long data[4], int num_operands,
- yasm_insn_operands *operands, x86_insn_info *jinfo,
- yasm_bytecode *prev_bc, unsigned long line)
+static void
+x86_finalize_jmp(yasm_arch *arch, yasm_bytecode *bc, yasm_bytecode *prev_bc,
+ const unsigned long data[4], int num_operands,
+ yasm_insn_operands *operands, int num_prefixes,
+ unsigned long **prefixes, int num_segregs,
+ const unsigned long *segregs, x86_insn_info *jinfo)
{
yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
- x86_new_jmp_data d;
+ x86_jmp *jmp;
int num_info = (int)(data[1]&0xFF);
x86_insn_info *info = (x86_insn_info *)data[0];
unsigned long mod_data = data[1] >> 8;
+ unsigned char mode_bits = (unsigned char)data[3];
yasm_insn_operand *op;
static const unsigned char size_lookup[] = {0, 8, 16, 32, 64, 80, 128, 0};
- d.line = line;
+ jmp = yasm_xmalloc(sizeof(x86_jmp));
+ jmp->mode_bits = mode_bits;
+ jmp->lockrep_pre = 0;
/* We know the target is in operand 0, but sanity check for Imm. */
op = yasm_ops_first(operands);
/* Far target needs to become "seg imm:imm". */
if ((jinfo->operands[0] & OPTM_MASK) == OPTM_Far) {
yasm_expr *copy = yasm_expr_copy(op->data.val);
- d.target = yasm_expr_create_tree(
- yasm_expr_create_branch(YASM_EXPR_SEG, op->data.val, line),
- YASM_EXPR_SEGOFF, copy, line);
+ jmp->target = yasm_expr_create_tree(
+ yasm_expr_create_branch(YASM_EXPR_SEG, op->data.val, bc->line),
+ YASM_EXPR_SEGOFF, copy, bc->line);
} else
- d.target = op->data.val;
+ jmp->target = op->data.val;
/* Need to save jump origin for relative jumps. */
- d.origin = yasm_symtab_define_label2("$", prev_bc, 0, line);
+ jmp->origin = yasm_symtab_define_label2("$", prev_bc, 0, bc->line);
/* Initially assume no far opcode is available. */
- d.far_op_len = 0;
+ jmp->farop.opcode_len = 0;
/* See if the user explicitly specified short/near/far. */
switch ((int)(jinfo->operands[0] & OPTM_MASK)) {
case OPTM_Short:
- d.op_sel = JMP_SHORT_FORCED;
+ jmp->op_sel = JMP_SHORT_FORCED;
break;
case OPTM_Near:
- d.op_sel = JMP_NEAR_FORCED;
+ jmp->op_sel = JMP_NEAR_FORCED;
break;
case OPTM_Far:
- d.op_sel = JMP_FAR;
- d.far_op_len = info->opcode_len;
- d.far_op[0] = info->opcode[0];
- d.far_op[1] = info->opcode[1];
- d.far_op[2] = info->opcode[2];
+ jmp->op_sel = JMP_FAR;
+ jmp->farop.opcode_len = info->opcode_len;
+ jmp->farop.opcode[0] = info->opcode[0];
+ jmp->farop.opcode[1] = info->opcode[1];
+ jmp->farop.opcode[2] = info->opcode[2];
break;
default:
- d.op_sel = JMP_NONE;
+ jmp->op_sel = JMP_NONE;
}
/* Set operand size */
- d.opersize = jinfo->opersize;
+ jmp->opersize = jinfo->opersize;
/* Check for address size setting in second operand, if present */
if (jinfo->num_operands > 1 &&
(jinfo->operands[1] & OPA_MASK) == OPA_AdSizeR)
- d.addrsize = (unsigned char)size_lookup[(jinfo->operands[1] &
+ jmp->addrsize = (unsigned char)size_lookup[(jinfo->operands[1] &
OPS_MASK)>>OPS_SHIFT];
else
- d.addrsize = 0;
+ jmp->addrsize = 0;
/* Check for address size override */
if (jinfo->modifiers & MOD_AdSizeR)
- d.addrsize = (unsigned char)(mod_data & 0xFF);
+ jmp->addrsize = (unsigned char)(mod_data & 0xFF);
/* Scan through other infos for this insn looking for short/near versions.
* Needs to match opersize and number of operands, also be within CPU.
*/
- d.short_op_len = 0;
- d.near_op_len = 0;
- for (; num_info>0 && (d.short_op_len == 0 || d.near_op_len == 0);
+ jmp->shortop.opcode_len = 0;
+ jmp->nearop.opcode_len = 0;
+ for (; num_info>0 && (jmp->shortop.opcode_len == 0 ||
+ jmp->nearop.opcode_len == 0);
num_info--, info++) {
unsigned long cpu = info->cpu | data[2];
- if ((cpu & CPU_64) && arch_x86->mode_bits != 64)
+ if ((cpu & CPU_64) && mode_bits != 64)
continue;
- if ((cpu & CPU_Not64) && arch_x86->mode_bits == 64)
+ if ((cpu & CPU_Not64) && mode_bits == 64)
continue;
cpu &= ~(CPU_64 | CPU_Not64);
if ((info->operands[0] & OPA_MASK) != OPA_JmpRel)
continue;
- if (info->opersize != d.opersize)
+ if (info->opersize != jmp->opersize)
continue;
switch ((int)(info->operands[0] & OPTM_MASK)) {
case OPTM_Short:
- d.short_op_len = info->opcode_len;
- d.short_op[0] = info->opcode[0];
- d.short_op[1] = info->opcode[1];
- d.short_op[2] = info->opcode[2];
+ jmp->shortop.opcode_len = info->opcode_len;
+ jmp->shortop.opcode[0] = info->opcode[0];
+ jmp->shortop.opcode[1] = info->opcode[1];
+ jmp->shortop.opcode[2] = info->opcode[2];
if (info->modifiers & MOD_Op0Add)
- d.short_op[0] += (unsigned char)(mod_data & 0xFF);
+ jmp->shortop.opcode[0] += (unsigned char)(mod_data & 0xFF);
break;
case OPTM_Near:
- d.near_op_len = info->opcode_len;
- d.near_op[0] = info->opcode[0];
- d.near_op[1] = info->opcode[1];
- d.near_op[2] = info->opcode[2];
+ jmp->nearop.opcode_len = info->opcode_len;
+ jmp->nearop.opcode[0] = info->opcode[0];
+ jmp->nearop.opcode[1] = info->opcode[1];
+ jmp->nearop.opcode[2] = info->opcode[2];
if (info->modifiers & MOD_Op1Add)
- d.near_op[1] += (unsigned char)(mod_data & 0xFF);
+ jmp->nearop.opcode[1] += (unsigned char)(mod_data & 0xFF);
if ((info->operands[0] & OPAP_MASK) == OPAP_JmpFar) {
- d.far_op_len = 1;
- d.far_op[0] = info->opcode[info->opcode_len];
+ jmp->farop.opcode_len = 1;
+ jmp->farop.opcode[0] = info->opcode[info->opcode_len];
}
break;
}
}
- return yasm_x86__bc_create_jmp(arch, &d);
+ if ((jmp->op_sel == JMP_SHORT_FORCED) && (jmp->nearop.opcode_len == 0))
+ yasm__error(bc->line,
+ N_("no SHORT form of that jump instruction exists"));
+ if ((jmp->op_sel == JMP_NEAR_FORCED) && (jmp->shortop.opcode_len == 0))
+ yasm__error(bc->line,
+ N_("no NEAR form of that jump instruction exists"));
+
+ /* Transform the bytecode */
+ yasm_x86__bc_transform_jmp(bc, jmp);
+ yasm_x86__bc_apply_prefixes(bc, num_prefixes, prefixes, num_segregs,
+ segregs);
}
-yasm_bytecode *
-yasm_x86__parse_insn(yasm_arch *arch, const unsigned long data[4],
- int num_operands, yasm_insn_operands *operands,
- yasm_bytecode *prev_bc, unsigned long line)
+void
+yasm_x86__finalize_insn(yasm_arch *arch, yasm_bytecode *bc,
+ yasm_bytecode *prev_bc, const unsigned long data[4],
+ int num_operands,
+ /*@null@*/ yasm_insn_operands *operands,
+ int num_prefixes, unsigned long **prefixes,
+ int num_segregs, const unsigned long *segregs)
{
yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
- x86_new_insn_data d;
+ x86_insn *insn;
int num_info = (int)(data[1]&0xFF);
x86_insn_info *info = (x86_insn_info *)data[0];
unsigned long mod_data = data[1] >> 8;
+ unsigned char mode_bits = (unsigned char)data[3];
int found = 0;
yasm_insn_operand *op;
+ /*@null@*/ yasm_symrec *origin;
+ /*@null@*/ yasm_expr *imm;
+ unsigned char im_len;
+ unsigned char im_sign;
+ unsigned char spare;
int i;
static const unsigned int size_lookup[] = {0, 1, 2, 4, 8, 10, 16, 0};
/* Match CPU */
cpu = info->cpu | data[2];
- if ((cpu & CPU_64) && arch_x86->mode_bits != 64)
+ if ((cpu & CPU_64) && mode_bits != 64)
continue;
- if ((cpu & CPU_Not64) && arch_x86->mode_bits == 64)
+ if ((cpu & CPU_Not64) && mode_bits == 64)
continue;
cpu &= ~(CPU_64 | CPU_Not64);
if (!found) {
/* Didn't find a matching one */
- yasm__error(line, N_("invalid combination of opcode and operands"));
- return NULL;
+ yasm__error(bc->line,
+ N_("invalid combination of opcode and operands"));
+ return;
}
/* Extended error/warning handling */
switch ((int)((info->modifiers & MOD_ExtIndex_MASK)
>> MOD_ExtIndex_SHIFT)) {
case 0:
- yasm__error(line, N_("mismatch in operand sizes"));
+ yasm__error(bc->line, N_("mismatch in operand sizes"));
break;
case 1:
- yasm__error(line, N_("operand size not specified"));
+ yasm__error(bc->line, N_("operand size not specified"));
break;
default:
yasm_internal_error(N_("unrecognized x86 ext mod index"));
}
- return NULL; /* It was an error */
+ return; /* It was an error */
case MOD_ExtWarn:
switch ((int)((info->modifiers & MOD_ExtIndex_MASK)
>> MOD_ExtIndex_SHIFT)) {
}
/* Shortcut to JmpRel */
- if (operands && (info->operands[0] & OPA_MASK) == OPA_JmpRel)
- return x86_new_jmp(arch, data, num_operands, operands, info, prev_bc,
- line);
+ if (operands && (info->operands[0] & OPA_MASK) == OPA_JmpRel) {
+ x86_finalize_jmp(arch, bc, prev_bc, data, num_operands, operands,
+ num_prefixes, prefixes, num_segregs, segregs, info);
+ return;
+ }
/* Copy what we can from info */
- d.line = line;
- d.ea = NULL;
- d.ea_origin = NULL;
- d.imm = NULL;
- d.opersize = info->opersize;
- d.def_opersize_64 = info->def_opersize_64;
- d.special_prefix = info->special_prefix;
- d.op_len = info->opcode_len;
- d.op[0] = info->opcode[0];
- d.op[1] = info->opcode[1];
- d.op[2] = info->opcode[2];
- d.spare = info->spare;
- d.im_len = 0;
- d.im_sign = 0;
- d.shift_op = 0;
- d.signext_imm8_op = 0;
- d.shortmov_op = 0;
- d.rex = 0;
+ insn = yasm_xmalloc(sizeof(x86_insn));
+ insn->mode_bits = mode_bits;
+ insn->ea = NULL;
+ origin = NULL;
+ imm = NULL;
+ insn->addrsize = 0;
+ insn->opersize = info->opersize;
+ insn->lockrep_pre = 0;
+ insn->def_opersize_64 = info->def_opersize_64;
+ insn->special_prefix = info->special_prefix;
+ insn->opcode_len = info->opcode_len;
+ insn->opcode[0] = info->opcode[0];
+ insn->opcode[1] = info->opcode[1];
+ insn->opcode[2] = info->opcode[2];
+ spare = info->spare;
+ im_len = 0;
+ im_sign = 0;
+ insn->shift_op = 0;
+ insn->signext_imm8_op = 0;
+ insn->shortmov_op = 0;
+ insn->rex = 0;
/* Apply modifiers */
if (info->modifiers & MOD_Gap0)
mod_data >>= 8;
if (info->modifiers & MOD_Op2Add) {
- d.op[2] += (unsigned char)(mod_data & 0xFF);
+ insn->opcode[2] += (unsigned char)(mod_data & 0xFF);
mod_data >>= 8;
}
if (info->modifiers & MOD_Gap1)
mod_data >>= 8;
if (info->modifiers & MOD_Op1Add) {
- d.op[1] += (unsigned char)(mod_data & 0xFF);
+ insn->opcode[1] += (unsigned char)(mod_data & 0xFF);
mod_data >>= 8;
}
if (info->modifiers & MOD_Gap2)
mod_data >>= 8;
if (info->modifiers & MOD_Op0Add) {
- d.op[0] += (unsigned char)(mod_data & 0xFF);
+ insn->opcode[0] += (unsigned char)(mod_data & 0xFF);
mod_data >>= 8;
}
if (info->modifiers & MOD_PreAdd) {
- d.special_prefix += (unsigned char)(mod_data & 0xFF);
+ insn->special_prefix += (unsigned char)(mod_data & 0xFF);
mod_data >>= 8;
}
if (info->modifiers & MOD_SpAdd) {
- d.spare += (unsigned char)(mod_data & 0xFF);
+ spare += (unsigned char)(mod_data & 0xFF);
mod_data >>= 8;
}
if (info->modifiers & MOD_OpSizeR) {
- d.opersize = (unsigned char)(mod_data & 0xFF);
+ insn->opersize = (unsigned char)(mod_data & 0xFF);
mod_data >>= 8;
}
if (info->modifiers & MOD_Imm8) {
- d.imm = yasm_expr_create_ident(yasm_expr_int(
- yasm_intnum_create_uint(mod_data & 0xFF)), line);
- d.im_len = 1;
+ imm = yasm_expr_create_ident(yasm_expr_int(
+ yasm_intnum_create_uint(mod_data & 0xFF)), bc->line);
+ im_len = 1;
mod_data >>= 8;
}
if (info->modifiers & MOD_DOpS64R) {
- d.def_opersize_64 = (unsigned char)(mod_data & 0xFF);
+ insn->def_opersize_64 = (unsigned char)(mod_data & 0xFF);
/*mod_data >>= 8;*/
}
case OPA_EA:
switch (op->type) {
case YASM_INSN__OPERAND_REG:
- d.ea =
- yasm_x86__ea_create_reg(op->data.reg, &d.rex,
- arch_x86->mode_bits);
+ insn->ea =
+ yasm_x86__ea_create_reg(op->data.reg,
+ &insn->rex,
+ mode_bits);
break;
case YASM_INSN__OPERAND_SEGREG:
yasm_internal_error(
N_("invalid operand conversion"));
case YASM_INSN__OPERAND_MEMORY:
- d.ea = op->data.ea;
+ insn->ea = op->data.ea;
if ((info->operands[i] & OPT_MASK) == OPT_MemOffs)
/* Special-case for MOV MemOffs instruction */
- yasm_x86__ea_set_disponly(d.ea);
- else if (arch_x86->mode_bits == 64)
+ yasm_x86__ea_set_disponly(insn->ea);
+ else if (mode_bits == 64)
/* Save origin for possible RIP-relative */
- d.ea_origin = yasm_symtab_define_label2("$",
- prev_bc, 0, line);
+ origin =
+ yasm_symtab_define_label2("$", prev_bc, 0,
+ bc->line);
break;
case YASM_INSN__OPERAND_IMM:
- d.ea = yasm_x86__ea_create_imm(op->data.val,
+ insn->ea = yasm_x86__ea_create_imm(op->data.val,
size_lookup[(info->operands[i] &
OPS_MASK)>>OPS_SHIFT]);
break;
break;
case OPA_Imm:
if (op->type == YASM_INSN__OPERAND_IMM) {
- d.imm = op->data.val;
- d.im_len = size_lookup[(info->operands[i] &
- OPS_MASK)>>OPS_SHIFT];
+ imm = op->data.val;
+ im_len = size_lookup[(info->operands[i] &
+ OPS_MASK)>>OPS_SHIFT];
} else
yasm_internal_error(N_("invalid operand conversion"));
break;
case OPA_SImm:
if (op->type == YASM_INSN__OPERAND_IMM) {
- d.imm = op->data.val;
- d.im_len = size_lookup[(info->operands[i] &
- OPS_MASK)>>OPS_SHIFT];
- d.im_sign = 1;
+ imm = op->data.val;
+ im_len = size_lookup[(info->operands[i] &
+ OPS_MASK)>>OPS_SHIFT];
+ im_sign = 1;
} else
yasm_internal_error(N_("invalid operand conversion"));
break;
case OPA_Spare:
if (op->type == YASM_INSN__OPERAND_SEGREG)
- d.spare = (unsigned char)(op->data.reg&7);
+ spare = (unsigned char)(op->data.reg&7);
else if (op->type == YASM_INSN__OPERAND_REG) {
- if (yasm_x86__set_rex_from_reg(&d.rex, &d.spare,
- op->data.reg, arch_x86->mode_bits,
- X86_REX_R)) {
- yasm__error(line,
+ if (yasm_x86__set_rex_from_reg(&insn->rex, &spare,
+ op->data.reg, mode_bits, X86_REX_R)) {
+ yasm__error(bc->line,
N_("invalid combination of opcode and operands"));
- return NULL;
+ return;
}
} else
yasm_internal_error(N_("invalid operand conversion"));
case OPA_Op0Add:
if (op->type == YASM_INSN__OPERAND_REG) {
unsigned char opadd;
- if (yasm_x86__set_rex_from_reg(&d.rex, &opadd,
- op->data.reg, arch_x86->mode_bits,
- X86_REX_B)) {
- yasm__error(line,
+ if (yasm_x86__set_rex_from_reg(&insn->rex, &opadd,
+ op->data.reg, mode_bits, X86_REX_B)) {
+ yasm__error(bc->line,
N_("invalid combination of opcode and operands"));
- return NULL;
+ return;
}
- d.op[0] += opadd;
+ insn->opcode[0] += opadd;
} else
yasm_internal_error(N_("invalid operand conversion"));
break;
case OPA_Op1Add:
if (op->type == YASM_INSN__OPERAND_REG) {
unsigned char opadd;
- if (yasm_x86__set_rex_from_reg(&d.rex, &opadd,
- op->data.reg, arch_x86->mode_bits,
- X86_REX_B)) {
- yasm__error(line,
+ if (yasm_x86__set_rex_from_reg(&insn->rex, &opadd,
+ op->data.reg, mode_bits, X86_REX_B)) {
+ yasm__error(bc->line,
N_("invalid combination of opcode and operands"));
- return NULL;
+ return;
}
- d.op[1] += opadd;
+ insn->opcode[1] += opadd;
} else
yasm_internal_error(N_("invalid operand conversion"));
break;
case OPA_SpareEA:
if (op->type == YASM_INSN__OPERAND_REG) {
- d.ea = yasm_x86__ea_create_reg(op->data.reg, &d.rex,
- arch_x86->mode_bits);
- if (!d.ea ||
- yasm_x86__set_rex_from_reg(&d.rex, &d.spare,
- op->data.reg, arch_x86->mode_bits,
- X86_REX_R)) {
- yasm__error(line,
+ insn->ea = yasm_x86__ea_create_reg(op->data.reg,
+ &insn->rex,
+ mode_bits);
+ if (!insn->ea ||
+ yasm_x86__set_rex_from_reg(&insn->rex, &spare,
+ op->data.reg, mode_bits, X86_REX_R)) {
+ yasm__error(bc->line,
N_("invalid combination of opcode and operands"));
- if (d.ea)
- yasm_xfree(d.ea);
- return NULL;
+ if (insn->ea)
+ yasm_xfree(insn->ea);
+ yasm_xfree(insn);
+ return;
}
} else
yasm_internal_error(N_("invalid operand conversion"));
case OPAP_None:
break;
case OPAP_ShiftOp:
- d.shift_op = 1;
+ insn->shift_op = 1;
break;
case OPAP_SImm8Avail:
- d.signext_imm8_op = 1;
+ insn->signext_imm8_op = 1;
break;
case OPAP_ShortMov:
- d.shortmov_op = 1;
+ insn->shortmov_op = 1;
break;
default:
yasm_internal_error(
}
}
- /* Create the bytecode and return it */
- return yasm_x86__bc_create_insn(arch, &d);
+ if (insn->ea)
+ yasm_x86__ea_init(insn->ea, spare, origin);
+ if (imm) {
+ insn->imm = yasm_imm_create_expr(imm);
+ insn->imm->len = im_len;
+ insn->imm->sign = im_sign;
+ } else
+ insn->imm = NULL;
+
+ /* Transform the bytecode */
+ yasm_x86__bc_transform_insn(bc, insn);
+ yasm_x86__bc_apply_prefixes(bc, num_prefixes, prefixes, num_segregs,
+ segregs);
}
unsigned long value; /* fallthrough value if above NULL */
} stabs_stab;
-/* Bytecode types */
-
-typedef struct {
- yasm_bytecode bc; /* base structure */
- /*@only@*/ char *str;
-} stabs_bc_str;
-
-typedef struct {
- yasm_bytecode bc; /* base structure */
- stabs_stab *stab;
-} stabs_bc_stab;
-
/* Bytecode callback function prototypes */
-static void stabs_bc_str_destroy(yasm_bytecode *bc);
-static void stabs_bc_str_print(const yasm_bytecode *bc, FILE *f, int
+static void stabs_bc_str_destroy(void *contents);
+static void stabs_bc_str_print(const void *contents, FILE *f, int
indent_level);
static yasm_bc_resolve_flags stabs_bc_str_resolve
(yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
yasm_output_expr_func output_expr,
/*@null@*/ yasm_output_reloc_func output_reloc);
-static void stabs_bc_stab_destroy(yasm_bytecode *bc);
-static void stabs_bc_stab_print(const yasm_bytecode *bc, FILE *f, int
+static void stabs_bc_stab_destroy(void *contents);
+static void stabs_bc_stab_print(const void *contents, FILE *f, int
indent_level);
static yasm_bc_resolve_flags stabs_bc_stab_resolve
(yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
static const yasm_bytecode_callback stabs_bc_str_callback = {
stabs_bc_str_destroy,
stabs_bc_str_print,
+ yasm_bc_finalize_common,
stabs_bc_str_resolve,
stabs_bc_str_tobytes
};
static const yasm_bytecode_callback stabs_bc_stab_callback = {
stabs_bc_stab_destroy,
stabs_bc_stab_print,
+ yasm_bc_finalize_common,
stabs_bc_stab_resolve,
stabs_bc_stab_tobytes
};
stabs_dbgfmt_append_bcstr(yasm_section *sect, const char *str)
{
yasm_bytecode *bc, *precbc;
- stabs_bc_str *bc_str;
precbc = yasm_section_bcs_last(sect);
- bc = yasm_bc_create_common(&stabs_bc_str_callback, sizeof(stabs_bc_str),
- 0);
- bc_str = (stabs_bc_str *)bc;
-
- bc_str->str = yasm__xstrdup(str);
-
+ bc = yasm_bc_create_common(&stabs_bc_str_callback, yasm__xstrdup(str), 0);
bc->len = strlen(str)+1;
bc->offset = precbc ? precbc->offset + precbc->len : 0;
/*@null@*/ yasm_bytecode *bcvalue, unsigned long value)
{
yasm_bytecode *bc, *precbc;
- stabs_bc_stab *bc_stab;
stabs_stab *stab = yasm_xmalloc(sizeof(stabs_stab));
stab->other = 0;
stab->value = value;
precbc = yasm_section_bcs_last(sect);
- bc = yasm_bc_create_common(&stabs_bc_stab_callback, sizeof(stabs_bc_stab),
+ bc = yasm_bc_create_common(&stabs_bc_stab_callback, stab,
bcvalue ? bcvalue->line : 0);
- bc_stab = (stabs_bc_stab *)bc;
-
- bc_stab->stab = stab;
-
bc->len = info->stablen;
bc->offset = precbc ? precbc->offset + precbc->len : 0;
stabs_info info;
int new;
yasm_bytecode *dbgbc;
- stabs_bc_stab *dbgbc_stab;
stabs_stab *stab;
yasm_bytecode *filebc, *nullbc, *laststr, *firstbc;
yasm_symrec *firstsym;
/* initial pseudo-stab */
stab = yasm_xmalloc(sizeof(stabs_stab));
- dbgbc = yasm_bc_create_common(&stabs_bc_stab_callback,
- sizeof(stabs_bc_stab), 0);
- dbgbc_stab = (stabs_bc_stab *)dbgbc;
-
+ dbgbc = yasm_bc_create_common(&stabs_bc_stab_callback, stab, 0);
dbgbc->len = info.stablen;
- dbgbc_stab->stab = stab;
-
yasm_section_bcs_append(info.stab, dbgbc);
/* initial strtab bytecodes */
* needs to become endian aware. Size appears not to be an issue, as known
* 64-bit systems use truncated values in 32-bit fields. */
- stabs_bc_stab *bc_stab = (stabs_bc_stab *)bc;
+ const stabs_stab *stab = (const stabs_stab *)bc->contents;
unsigned char *buf = *bufp;
- const stabs_stab *stab = bc_stab->stab;
YASM_WRITE_32_L(buf, stab->bcstr ? stab->bcstr->offset : 0);
YASM_WRITE_8(buf, stab->type);
yasm_output_expr_func output_expr,
yasm_output_reloc_func output_reloc)
{
- stabs_bc_str *bc_str = (stabs_bc_str *)bc;
+ const char *str = (const char *)bc->contents;
unsigned char *buf = *bufp;
- const char *str = bc_str->str;
strcpy((char *)buf, str);
buf += strlen(str)+1;
}
static void
-stabs_bc_stab_destroy(yasm_bytecode *bc)
+stabs_bc_stab_destroy(void *contents)
{
- stabs_bc_stab *bc_stab = (stabs_bc_stab *)bc;
- yasm_xfree(bc_stab->stab);
+ yasm_xfree(contents);
}
static void
-stabs_bc_str_destroy(yasm_bytecode *bc)
+stabs_bc_str_destroy(void *contents)
{
- stabs_bc_str *bc_str = (stabs_bc_str *)bc;
- yasm_xfree(bc_str->str);
+ yasm_xfree(contents);
}
static void
-stabs_bc_stab_print(const yasm_bytecode *bc, FILE *f, int indent_level)
+stabs_bc_stab_print(const void *contents, FILE *f, int indent_level)
{
- const stabs_bc_stab *bc_stab = (const stabs_bc_stab *)bc;
- const stabs_stab *stab = bc_stab->stab;
+ const stabs_stab *stab = (const stabs_stab *)contents;
const char *str = "";
fprintf(f, "%*s.stabs \"%s\", 0x%x, 0x%x, 0x%x, 0x%lx\n",
indent_level, "", str, stab->type, stab->other, stab->desc,
}
static void
-stabs_bc_str_print(const yasm_bytecode *bc, FILE *f, int indent_level)
+stabs_bc_str_print(const void *contents, FILE *f, int indent_level)
{
- const stabs_bc_str *bc_str = (const stabs_bc_str *)bc;
- fprintf(f, "%*s\"%s\"\n", indent_level, "", bc_str->str);
+ fprintf(f, "%*s\"%s\"\n", indent_level, "", (const char *)contents);
}
static yasm_bc_resolve_flags
;
instr: INSN {
- $$ = yasm_arch_parse_insn(parser_nasm->arch, $1, 0, NULL,
- parser_nasm->prev_bc, cur_line);
+ $$ = yasm_bc_create_insn(parser_nasm->arch, $1, 0, NULL, cur_line);
}
| INSN operands {
- $$ = yasm_arch_parse_insn(parser_nasm->arch, $1, $2.num_operands,
- &$2.operands, parser_nasm->prev_bc,
- cur_line);
- yasm_ops_delete(&$2.operands, 0);
+ $$ = yasm_bc_create_insn(parser_nasm->arch, $1, $2.num_operands,
+ &$2.operands, cur_line);
}
| INSN error {
yasm__error(cur_line, N_("expression syntax error"));
}
| PREFIX instr {
$$ = $2;
- yasm_arch_parse_prefix(parser_nasm->arch, $$, $1, cur_line);
+ yasm_bc_insn_add_prefix($$, $1);
}
| SEGREG instr {
$$ = $2;
- yasm_arch_parse_seg_prefix(parser_nasm->arch, $$, $1[0], cur_line);
+ yasm_bc_insn_add_seg_prefix($$, $1[0]);
}
;
}
| SEGREG ':' memaddr {
$$ = $3;
- yasm_arch_parse_seg_override(parser_nasm->arch, $$, $1[0], cur_line);
+ yasm_ea_set_segreg($$, $1[0], cur_line);
}
| SIZE_OVERRIDE memaddr { $$ = $2; yasm_ea_set_len($$, $1); }
| NOSPLIT memaddr { $$ = $2; yasm_ea_set_nosplit($$, 1); }