bytecode outputs just space and not data.
* bytecode.pxi: Update to match.
* bytecode.c (yasm_bc_tobytes): Use reserve flag instead of checking
against bytecode_reserve as special case.
* dwarf2-info.c, dwarf2-line.c, dwarf2-dbgfmt.c, cv-symline.c, cv-type.c,
* stabs-dbgfmt.c, lc3bbc.c, x86bc.c: Update to set reserve=0.
* bc-align.c, bc-insn.c, bc-reserve.c, bc-org.c, bc-incbin.c, bc-data.c,
* bytecode.c: Split out bytecodes into separate files. While we're here,
merge LEB128 into general data bytecode.
svn path=/trunk/yasm/; revision=1532
libyasm_a_SOURCES += libyasm/arch.c
libyasm_a_SOURCES += libyasm/assocdat.c
libyasm_a_SOURCES += libyasm/bitvect.c
+libyasm_a_SOURCES += libyasm/bc-align.c
+libyasm_a_SOURCES += libyasm/bc-data.c
+libyasm_a_SOURCES += libyasm/bc-incbin.c
+libyasm_a_SOURCES += libyasm/bc-insn.c
+libyasm_a_SOURCES += libyasm/bc-org.c
+libyasm_a_SOURCES += libyasm/bc-reserve.c
libyasm_a_SOURCES += libyasm/bytecode.c
libyasm_a_SOURCES += libyasm/errwarn.c
libyasm_a_SOURCES += libyasm/expr.c
--- /dev/null
+/*
+ * Align bytecode
+ *
+ * Copyright (C) 2005-2006 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("$Id$");
+
+#include "coretype.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+
+#include "bytecode.h"
+
+#include "bc-int.h"
+
+
+typedef struct bytecode_align {
+ /*@only@*/ yasm_expr *boundary; /* alignment boundary */
+
+ /* What to fill intervening locations with, NULL if using code_fill */
+ /*@only@*/ /*@null@*/ yasm_expr *fill;
+
+ /* Maximum number of bytes to skip, NULL if no maximum. */
+ /*@only@*/ /*@null@*/ yasm_expr *maxskip;
+
+ /* Code fill, NULL if using 0 fill */
+ /*@null@*/ const unsigned char **code_fill;
+} bytecode_align;
+
+static void bc_align_destroy(void *contents);
+static void bc_align_print(const void *contents, FILE *f, int indent_level);
+static void bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+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_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static const yasm_bytecode_callback bc_align_callback = {
+ bc_align_destroy,
+ bc_align_print,
+ bc_align_finalize,
+ bc_align_resolve,
+ bc_align_tobytes,
+ 0
+};
+
+
+static void
+bc_align_destroy(void *contents)
+{
+ bytecode_align *align = (bytecode_align *)contents;
+ if (align->boundary)
+ yasm_expr_destroy(align->boundary);
+ if (align->fill)
+ yasm_expr_destroy(align->fill);
+ if (align->maxskip)
+ yasm_expr_destroy(align->maxskip);
+ yasm_xfree(contents);
+}
+
+static void
+bc_align_print(const void *contents, FILE *f, int indent_level)
+{
+ const bytecode_align *align = (const bytecode_align *)contents;
+ fprintf(f, "%*s_Align_\n", indent_level, "");
+ fprintf(f, "%*sBoundary=", indent_level, "");
+ yasm_expr_print(align->boundary, f);
+ fprintf(f, "\n%*sFill=", indent_level, "");
+ yasm_expr_print(align->fill, f);
+ fprintf(f, "\n%*sMax Skip=", indent_level, "");
+ yasm_expr_print(align->maxskip, f);
+ fprintf(f, "\n");
+}
+
+static void
+bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ bytecode_align *align = (bytecode_align *)bc->contents;
+ if (!yasm_expr_get_intnum(&align->boundary, NULL))
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("align boundary must be a constant"));
+ if (align->fill && !yasm_expr_get_intnum(&align->fill, NULL))
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("align fill must be a constant"));
+ if (align->maxskip && !yasm_expr_get_intnum(&align->maxskip, NULL))
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("align maximum skip must be a constant"));
+}
+
+static yasm_bc_resolve_flags
+bc_align_resolve(yasm_bytecode *bc, int save,
+ yasm_calc_bc_dist_func calc_bc_dist)
+{
+ bytecode_align *align = (bytecode_align *)bc->contents;
+ unsigned long end;
+ unsigned long boundary =
+ yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, NULL));
+
+ if (boundary == 0) {
+ bc->len = 0;
+ return YASM_BC_RESOLVE_MIN_LEN;
+ }
+
+ end = bc->offset;
+ if (bc->offset & (boundary-1))
+ end = (bc->offset & ~(boundary-1)) + boundary;
+
+ bc->len = end - bc->offset;
+
+ if (align->maxskip) {
+ unsigned long maxskip =
+ yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, NULL));
+ if ((end - bc->offset) > maxskip)
+ bc->len = 0;
+ }
+ return YASM_BC_RESOLVE_MIN_LEN;
+}
+
+static int
+bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ bytecode_align *align = (bytecode_align *)bc->contents;
+ unsigned long len;
+ unsigned long boundary =
+ yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, NULL));
+
+ if (boundary == 0)
+ return 0;
+ else {
+ unsigned long end = bc->offset;
+ if (bc->offset & (boundary-1))
+ end = (bc->offset & ~(boundary-1)) + boundary;
+ len = end - bc->offset;
+ if (len == 0)
+ return 0;
+ if (align->maxskip) {
+ unsigned long maxskip =
+ yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip,
+ NULL));
+ if (len > maxskip)
+ return 0;
+ }
+ }
+
+ if (align->fill) {
+ unsigned long v;
+ v = yasm_intnum_get_uint(yasm_expr_get_intnum(&align->fill, NULL));
+ memset(*bufp, (int)v, len);
+ *bufp += len;
+ } else if (align->code_fill) {
+ unsigned long maxlen = 15;
+ while (!align->code_fill[maxlen] && maxlen>0)
+ maxlen--;
+ if (maxlen == 0) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("could not find any code alignment size"));
+ return 1;
+ }
+
+ /* Fill with maximum code fill as much as possible */
+ while (len > maxlen) {
+ memcpy(*bufp, align->code_fill[maxlen], maxlen);
+ *bufp += maxlen;
+ len -= maxlen;
+ }
+
+ if (!align->code_fill[len]) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("invalid alignment size %d"), len);
+ return 1;
+ }
+ /* Handle rest of code fill */
+ memcpy(*bufp, align->code_fill[len], len);
+ *bufp += len;
+ } else {
+ /* Just fill with 0 */
+ memset(*bufp, 0, len);
+ *bufp += len;
+ }
+ return 0;
+}
+
+yasm_bytecode *
+yasm_bc_create_align(yasm_expr *boundary, yasm_expr *fill,
+ yasm_expr *maxskip, const unsigned char **code_fill,
+ unsigned long line)
+{
+ bytecode_align *align = yasm_xmalloc(sizeof(bytecode_align));
+
+ align->boundary = boundary;
+ align->fill = fill;
+ align->maxskip = maxskip;
+ align->code_fill = code_fill;
+
+ return yasm_bc_create_common(&bc_align_callback, align, line);
+}
--- /dev/null
+/*
+ * Data (and LEB128) bytecode
+ *
+ * Copyright (C) 2001-2006 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("$Id$");
+
+#include "coretype.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "value.h"
+
+#include "bytecode.h"
+#include "arch.h"
+
+#include "bc-int.h"
+
+
+struct yasm_dataval {
+ /*@reldef@*/ STAILQ_ENTRY(yasm_dataval) link;
+
+ enum { DV_EMPTY, DV_VALUE, DV_RAW, DV_ULEB128, DV_SLEB128 } type;
+
+ union {
+ yasm_value val;
+ struct {
+ /*@only@*/ unsigned char *contents;
+ unsigned long len;
+ } raw;
+ } data;
+};
+
+typedef struct bytecode_data {
+ /* converted data (linked list) */
+ yasm_datavalhead datahead;
+
+ /* final (converted) size of each value element (in bytes) */
+ unsigned int size;
+} bytecode_data;
+
+static void bc_data_destroy(void *contents);
+static void bc_data_print(const void *contents, FILE *f, int indent_level);
+static void bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+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_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static const yasm_bytecode_callback bc_data_callback = {
+ bc_data_destroy,
+ bc_data_print,
+ bc_data_finalize,
+ bc_data_resolve,
+ bc_data_tobytes,
+ 0
+};
+
+
+static void
+bc_data_destroy(void *contents)
+{
+ bytecode_data *bc_data = (bytecode_data *)contents;
+ yasm_dvs_destroy(&bc_data->datahead);
+ yasm_xfree(contents);
+}
+
+static void
+bc_data_print(const void *contents, FILE *f, int indent_level)
+{
+ const bytecode_data *bc_data = (const bytecode_data *)contents;
+ fprintf(f, "%*s_Data_\n", indent_level, "");
+ fprintf(f, "%*sElements:\n", indent_level+1, "");
+ yasm_dvs_print(&bc_data->datahead, f, indent_level+2);
+}
+
+static void
+bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ bytecode_data *bc_data = (bytecode_data *)bc->contents;
+ yasm_dataval *dv;
+ yasm_intnum *intn;
+
+ /* Convert values from simple expr to value. */
+ STAILQ_FOREACH(dv, &bc_data->datahead, link) {
+ switch (dv->type) {
+ case DV_VALUE:
+ if (yasm_value_finalize(&dv->data.val)) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("data expression too complex"));
+ return;
+ }
+ break;
+ case DV_ULEB128:
+ case DV_SLEB128:
+ intn = yasm_expr_get_intnum(&dv->data.val.abs, NULL);
+ if (!intn) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("LEB128 requires constant values"));
+ return;
+ }
+ /* Warn for negative values in unsigned environment.
+ * This could be an error instead: the likelihood this is
+ * desired is very low!
+ */
+ if (yasm_intnum_sign(intn) == -1 && dv->type == DV_ULEB128)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("negative value in unsigned LEB128"));
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static yasm_bc_resolve_flags
+bc_data_resolve(yasm_bytecode *bc, int save,
+ yasm_calc_bc_dist_func calc_bc_dist)
+{
+ bytecode_data *bc_data = (bytecode_data *)bc->contents;
+ yasm_dataval *dv;
+ yasm_intnum *intn;
+
+ /* Count up element sizes, rounding up string length. */
+ STAILQ_FOREACH(dv, &bc_data->datahead, link) {
+ switch (dv->type) {
+ case DV_EMPTY:
+ break;
+ case DV_VALUE:
+ bc->len += bc_data->size;
+ break;
+ case DV_RAW:
+ bc->len += dv->data.raw.len;
+ break;
+ case DV_ULEB128:
+ case DV_SLEB128:
+ intn = yasm_expr_get_intnum(&dv->data.val.abs, NULL);
+ if (!intn)
+ yasm_internal_error(N_("non-constant in data_tobytes"));
+ bc->len +=
+ yasm_intnum_size_leb128(intn, dv->type == DV_SLEB128);
+ break;
+ }
+ }
+
+ return YASM_BC_RESOLVE_MIN_LEN;
+}
+
+static int
+bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ bytecode_data *bc_data = (bytecode_data *)bc->contents;
+ yasm_dataval *dv;
+ unsigned char *bufp_orig = *bufp;
+ yasm_intnum *intn;
+
+ STAILQ_FOREACH(dv, &bc_data->datahead, link) {
+ switch (dv->type) {
+ case DV_EMPTY:
+ break;
+ case DV_VALUE:
+ if (output_value(&dv->data.val, *bufp, bc_data->size,
+ (size_t)(bc_data->size*8), 0,
+ (unsigned long)(*bufp-bufp_orig), bc, 1, d))
+ return 1;
+ *bufp += bc_data->size;
+ break;
+ case DV_RAW:
+ memcpy(*bufp, dv->data.raw.contents, dv->data.raw.len);
+ *bufp += dv->data.raw.len;
+ break;
+ case DV_ULEB128:
+ case DV_SLEB128:
+ intn = yasm_expr_get_intnum(&dv->data.val.abs, NULL);
+ if (!intn)
+ yasm_internal_error(N_("non-constant in data_tobytes"));
+ *bufp +=
+ yasm_intnum_get_leb128(intn, *bufp, dv->type == DV_SLEB128);
+ }
+ }
+
+ return 0;
+}
+
+yasm_bytecode *
+yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size,
+ int append_zero, yasm_arch *arch, unsigned long line)
+{
+ bytecode_data *data = yasm_xmalloc(sizeof(bytecode_data));
+ yasm_bytecode *bc = yasm_bc_create_common(&bc_data_callback, data, line);
+ yasm_dataval *dv, *dv2, *dvo;
+ yasm_intnum *intn;
+ unsigned long len = 0, rlen, i;
+
+
+ yasm_dvs_initialize(&data->datahead);
+ data->size = size;
+
+ /* Prescan input data for length, etc. Careful: this needs to be
+ * precisely paired with the second loop.
+ */
+ STAILQ_FOREACH(dv, datahead, link) {
+ switch (dv->type) {
+ case DV_EMPTY:
+ break;
+ case DV_VALUE:
+ case DV_ULEB128:
+ case DV_SLEB128:
+ intn = yasm_expr_get_intnum(&dv->data.val.abs, NULL);
+ if (intn && dv->type == DV_VALUE && (arch || size == 1))
+ len += size;
+ else if (intn && dv->type == DV_ULEB128)
+ len += yasm_intnum_size_leb128(intn, 0);
+ else if (intn && dv->type == DV_SLEB128)
+ len += yasm_intnum_size_leb128(intn, 1);
+ else {
+ if (len > 0) {
+ /* Create bytecode for all previous len */
+ dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
+ STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
+ len = 0;
+ }
+
+ /* Create bytecode for this value */
+ dvo = yasm_xmalloc(sizeof(yasm_dataval));
+ STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
+ }
+ break;
+ case DV_RAW:
+ rlen = dv->data.raw.len;
+ /* find count, rounding up to nearest multiple of size */
+ rlen = (rlen + size - 1) / size;
+ len += rlen*size;
+ break;
+ }
+ if (append_zero)
+ len++;
+ }
+
+ /* Create final dataval for any trailing length */
+ if (len > 0) {
+ dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
+ STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
+ }
+
+ /* Second iteration: copy data and delete input datavals. */
+ dv = STAILQ_FIRST(datahead);
+ dvo = STAILQ_FIRST(&data->datahead);
+ len = 0;
+ while (dv) {
+ switch (dv->type) {
+ case DV_EMPTY:
+ break;
+ case DV_VALUE:
+ case DV_ULEB128:
+ case DV_SLEB128:
+ intn = yasm_expr_get_intnum(&dv->data.val.abs, NULL);
+ if (intn && dv->type == DV_VALUE && (arch || size == 1)) {
+ if (size == 1)
+ yasm_intnum_get_sized(intn,
+ &dvo->data.raw.contents[len],
+ 1, 8, 0, 0, 1);
+ else
+ yasm_arch_intnum_tobytes(arch, intn,
+ &dvo->data.raw.contents[len],
+ size, size*8, 0, bc, 1);
+ yasm_value_delete(&dv->data.val);
+ len += size;
+ } else if (intn && dv->type == DV_ULEB128) {
+ len += yasm_intnum_get_leb128(intn,
+ &dvo->data.raw.contents[len],
+ 0);
+ } else if (intn && dv->type == DV_SLEB128) {
+ len += yasm_intnum_get_leb128(intn,
+ &dvo->data.raw.contents[len],
+ 1);
+ } else {
+ dvo->type = dv->type;
+ dvo->data.val = dv->data.val; /* structure copy */
+ dvo = STAILQ_NEXT(dvo, link);
+ len = 0;
+ }
+ break;
+ case DV_RAW:
+ rlen = dv->data.raw.len;
+ memcpy(&dvo->data.raw.contents[len], dv->data.raw.contents,
+ rlen);
+ yasm_xfree(dv->data.raw.contents);
+ len += rlen;
+ /* pad with 0's to nearest multiple of size */
+ rlen %= size;
+ if (rlen > 0) {
+ rlen = size-rlen;
+ for (i=0; i<rlen; i++)
+ dvo->data.raw.contents[len++] = 0;
+ }
+ break;
+ }
+ if (append_zero)
+ dvo->data.raw.contents[len++] = 0;
+ dv2 = STAILQ_NEXT(dv, link);
+ yasm_xfree(dv);
+ dv = dv2;
+ }
+
+ return bc;
+}
+
+yasm_bytecode *
+yasm_bc_create_leb128(yasm_datavalhead *datahead, int sign, unsigned long line)
+{
+ yasm_dataval *dv;
+
+ /* Convert all values into LEB type, error on strings/raws */
+ STAILQ_FOREACH(dv, datahead, link) {
+ switch (dv->type) {
+ case DV_VALUE:
+ dv->type = sign ? DV_SLEB128 : DV_ULEB128;
+ break;
+ case DV_RAW:
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("LEB128 does not allow string constants"));
+ break;
+ default:
+ break;
+ }
+ }
+
+ return yasm_bc_create_data(datahead, 0, 0, 0, line);
+}
+
+yasm_dataval *
+yasm_dv_create_expr(yasm_expr *e)
+{
+ yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
+
+ retval->type = DV_VALUE;
+ yasm_value_initialize(&retval->data.val, e);
+
+ return retval;
+}
+
+yasm_dataval *
+yasm_dv_create_raw(unsigned char *contents, unsigned long len)
+{
+ yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
+
+ retval->type = DV_RAW;
+ retval->data.raw.contents = contents;
+ retval->data.raw.len = len;
+
+ return retval;
+}
+
+void
+yasm_dvs_destroy(yasm_datavalhead *headp)
+{
+ yasm_dataval *cur, *next;
+
+ cur = STAILQ_FIRST(headp);
+ while (cur) {
+ next = STAILQ_NEXT(cur, link);
+ switch (cur->type) {
+ case DV_VALUE:
+ yasm_value_delete(&cur->data.val);
+ break;
+ case DV_RAW:
+ yasm_xfree(cur->data.raw.contents);
+ break;
+ default:
+ break;
+ }
+ yasm_xfree(cur);
+ cur = next;
+ }
+ STAILQ_INIT(headp);
+}
+
+yasm_dataval *
+yasm_dvs_append(yasm_datavalhead *headp, yasm_dataval *dv)
+{
+ if (dv) {
+ STAILQ_INSERT_TAIL(headp, dv, link);
+ return dv;
+ }
+ return (yasm_dataval *)NULL;
+}
+
+void
+yasm_dvs_print(const yasm_datavalhead *head, FILE *f, int indent_level)
+{
+ yasm_dataval *cur;
+ unsigned long i;
+
+ STAILQ_FOREACH(cur, head, link) {
+ switch (cur->type) {
+ case DV_EMPTY:
+ fprintf(f, "%*sEmpty\n", indent_level, "");
+ break;
+ case DV_VALUE:
+ fprintf(f, "%*sValue:\n", indent_level, "");
+ yasm_value_print(&cur->data.val, f, indent_level+1);
+ break;
+ case DV_RAW:
+ fprintf(f, "%*sLength=%lu\n", indent_level, "",
+ cur->data.raw.len);
+ fprintf(f, "%*sBytes=[", indent_level, "");
+ for (i=0; i<cur->data.raw.len; i++)
+ fprintf(f, "0x%02x, ", cur->data.raw.contents[i]);
+ fprintf(f, "]\n");
+ break;
+ case DV_ULEB128:
+ fprintf(f, "%*sULEB128 value:\n", indent_level, "");
+ yasm_value_print(&cur->data.val, f, indent_level+1);
+ break;
+ case DV_SLEB128:
+ fprintf(f, "%*sSLEB128 value:\n", indent_level, "");
+ yasm_value_print(&cur->data.val, f, indent_level+1);
+ break;
+ }
+ }
+}
+
+/* Non-macro yasm_dvs_initialize() for non-YASM_LIB_INTERNAL users. */
+#undef yasm_dvs_initialize
+void
+yasm_dvs_initialize(yasm_datavalhead *headp)
+{
+ STAILQ_INIT(headp);
+}
--- /dev/null
+/*
+ * Incbin bytecode
+ *
+ * Copyright (C) 2001-2006 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("$Id$");
+
+#include "coretype.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "value.h"
+
+#include "bytecode.h"
+
+#include "bc-int.h"
+
+
+typedef struct bytecode_incbin {
+ /*@only@*/ char *filename; /* file to include data from */
+
+ /* starting offset to read from (NULL=0) */
+ /*@only@*/ /*@null@*/ yasm_expr *start;
+
+ /* maximum number of bytes to read (NULL=no limit) */
+ /*@only@*/ /*@null@*/ yasm_expr *maxlen;
+} bytecode_incbin;
+
+static void bc_incbin_destroy(void *contents);
+static void bc_incbin_print(const void *contents, FILE *f, int indent_level);
+static void bc_incbin_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+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_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static const yasm_bytecode_callback bc_incbin_callback = {
+ bc_incbin_destroy,
+ bc_incbin_print,
+ bc_incbin_finalize,
+ bc_incbin_resolve,
+ bc_incbin_tobytes,
+ 0
+};
+
+
+static void
+bc_incbin_destroy(void *contents)
+{
+ 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 void *contents, FILE *f, int indent_level)
+{
+ const bytecode_incbin *incbin = (const bytecode_incbin *)contents;
+ fprintf(f, "%*s_IncBin_\n", indent_level, "");
+ fprintf(f, "%*sFilename=`%s'\n", indent_level, "",
+ incbin->filename);
+ fprintf(f, "%*sStart=", indent_level, "");
+ if (!incbin->start)
+ fprintf(f, "nil (0)");
+ else
+ yasm_expr_print(incbin->start, f);
+ fprintf(f, "%*sMax Len=", indent_level, "");
+ if (!incbin->maxlen)
+ fprintf(f, "nil (unlimited)");
+ else
+ yasm_expr_print(incbin->maxlen, f);
+ fprintf(f, "\n");
+}
+
+static void
+bc_incbin_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
+ yasm_value val;
+
+ if (yasm_value_finalize_expr(&val, incbin->start))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("start expression too complex"));
+ else if (val.rel)
+ yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
+ N_("start expression not absolute"));
+ incbin->start = val.abs;
+
+ if (yasm_value_finalize_expr(&val, incbin->maxlen))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("maximum length expression too complex"));
+ else if (val.rel)
+ yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
+ N_("maximum length expression not absolute"));
+ incbin->maxlen = val.abs;
+}
+
+static yasm_bc_resolve_flags
+bc_incbin_resolve(yasm_bytecode *bc, int save,
+ yasm_calc_bc_dist_func calc_bc_dist)
+{
+ bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
+ FILE *f;
+ /*@null@*/ yasm_expr *temp;
+ yasm_expr **tempp;
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
+ unsigned long start = 0, maxlen = 0xFFFFFFFFUL, flen;
+
+ /* Try to convert start to integer value */
+ if (incbin->start) {
+ if (save) {
+ temp = NULL;
+ tempp = &incbin->start;
+ } else {
+ temp = yasm_expr_copy(incbin->start);
+ assert(temp != NULL);
+ tempp = &temp;
+ }
+ num = yasm_expr_get_intnum(tempp, calc_bc_dist);
+ if (num)
+ start = yasm_intnum_get_uint(num);
+ yasm_expr_destroy(temp);
+ if (!num)
+ return YASM_BC_RESOLVE_UNKNOWN_LEN;
+ }
+
+ /* Try to convert maxlen to integer value */
+ if (incbin->maxlen) {
+ if (save) {
+ temp = NULL;
+ tempp = &incbin->maxlen;
+ } else {
+ temp = yasm_expr_copy(incbin->maxlen);
+ assert(temp != NULL);
+ tempp = &temp;
+ }
+ num = yasm_expr_get_intnum(tempp, calc_bc_dist);
+ if (num)
+ maxlen = yasm_intnum_get_uint(num);
+ yasm_expr_destroy(temp);
+ if (!num)
+ return YASM_BC_RESOLVE_UNKNOWN_LEN;
+ }
+
+ /* FIXME: Search include path for filename. Save full path back into
+ * filename if save is true.
+ */
+
+ /* Open file and determine its length */
+ f = fopen(incbin->filename, "rb");
+ if (!f) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("`incbin': unable to open file `%s'"),
+ incbin->filename);
+ return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
+ }
+ if (fseek(f, 0L, SEEK_END) < 0) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("`incbin': unable to seek on file `%s'"),
+ incbin->filename);
+ return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
+ }
+ flen = (unsigned long)ftell(f);
+ fclose(f);
+
+ /* Compute length of incbin from start, maxlen, and len */
+ if (start > flen) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("`incbin': start past end of file `%s'"),
+ incbin->filename);
+ start = flen;
+ }
+ flen -= start;
+ if (incbin->maxlen)
+ if (maxlen < flen)
+ flen = maxlen;
+ bc->len += flen;
+ return YASM_BC_RESOLVE_MIN_LEN;
+}
+
+static int
+bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
+ FILE *f;
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
+ unsigned long start = 0;
+
+ /* Convert start to integer value */
+ if (incbin->start) {
+ num = yasm_expr_get_intnum(&incbin->start, NULL);
+ if (!num)
+ yasm_internal_error(
+ N_("could not determine start in bc_tobytes_incbin"));
+ start = yasm_intnum_get_uint(num);
+ }
+
+ /* Open file */
+ f = fopen(incbin->filename, "rb");
+ if (!f) {
+ yasm_error_set(YASM_ERROR_IO, N_("`incbin': unable to open file `%s'"),
+ incbin->filename);
+ return 1;
+ }
+
+ /* Seek to start of data */
+ if (fseek(f, (long)start, SEEK_SET) < 0) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("`incbin': unable to seek on file `%s'"),
+ incbin->filename);
+ fclose(f);
+ return 1;
+ }
+
+ /* Read len bytes */
+ if (fread(*bufp, 1, (size_t)bc->len, f) < (size_t)bc->len) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("`incbin': unable to read %lu bytes from file `%s'"),
+ bc->len, incbin->filename);
+ fclose(f);
+ return 1;
+ }
+
+ *bufp += bc->len;
+ fclose(f);
+ return 0;
+}
+
+yasm_bytecode *
+yasm_bc_create_incbin(char *filename, yasm_expr *start, yasm_expr *maxlen,
+ unsigned long line)
+{
+ bytecode_incbin *incbin = yasm_xmalloc(sizeof(bytecode_incbin));
+
+ /*@-mustfree@*/
+ incbin->filename = filename;
+ incbin->start = start;
+ incbin->maxlen = maxlen;
+ /*@=mustfree@*/
+
+ return yasm_bc_create_common(&bc_incbin_callback, incbin, line);
+}
--- /dev/null
+/*
+ * Insn bytecode
+ *
+ * Copyright (C) 2005-2006 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("$Id$");
+
+#include "coretype.h"
+
+#include "errwarn.h"
+#include "expr.h"
+#include "value.h"
+
+#include "bytecode.h"
+#include "arch.h"
+
+#include "bc-int.h"
+
+
+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;
+
+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_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static const yasm_bytecode_callback bc_insn_callback = {
+ bc_insn_destroy,
+ bc_insn_print,
+ bc_insn_finalize,
+ bc_insn_resolve,
+ bc_insn_tobytes,
+ 0
+};
+
+
+yasm_immval *
+yasm_imm_create_expr(yasm_expr *e)
+{
+ yasm_immval *im = yasm_xmalloc(sizeof(yasm_immval));
+
+ if (yasm_value_finalize_expr(&im->val, e))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("immediate expression too complex"));
+ im->len = 0;
+ im->sign = 0;
+
+ return im;
+}
+
+const yasm_expr *
+yasm_ea_get_disp(const yasm_effaddr *ea)
+{
+ return ea->disp.abs;
+}
+
+void
+yasm_ea_set_len(yasm_effaddr *ptr, unsigned int len)
+{
+ if (!ptr)
+ return;
+
+ /* Currently don't warn if length truncated, as this is called only from
+ * an explicit override, where we expect the user knows what they're doing.
+ */
+
+ ptr->disp_len = (unsigned char)len;
+}
+
+void
+yasm_ea_set_nosplit(yasm_effaddr *ptr, unsigned int nosplit)
+{
+ if (!ptr)
+ return;
+
+ ptr->nosplit = (unsigned char)nosplit;
+}
+
+void
+yasm_ea_set_strong(yasm_effaddr *ptr, unsigned int strong)
+{
+ if (!ptr)
+ return;
+
+ ptr->strong = (unsigned char)strong;
+}
+
+void
+yasm_ea_set_segreg(yasm_effaddr *ea, unsigned long 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;
+}
+
+/*@-nullstate@*/
+void
+yasm_ea_destroy(yasm_effaddr *ea)
+{
+ ea->callback->destroy(ea);
+ yasm_value_delete(&ea->disp);
+ yasm_xfree(ea);
+}
+/*@=nullstate@*/
+
+/*@-nullstate@*/
+void
+yasm_ea_print(const yasm_effaddr *ea, FILE *f, int indent_level)
+{
+ fprintf(f, "%*sDisp:\n", indent_level, "");
+ yasm_value_print(&ea->disp, f, indent_level+1);
+ fprintf(f, "%*sLen=%u\n", indent_level, "", (unsigned int)ea->disp_len);
+ fprintf(f, "%*sNoSplit=%u\n", indent_level, "", (unsigned int)ea->nosplit);
+ ea->callback->print(ea, f, indent_level);
+}
+/*@=nullstate@*/
+
+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;
+ 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_ops_first(&insn->operands);
+ op && i<insn->num_operands; op = yasm_operand_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,
+ NULL, NULL, 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, NULL, NULL,
+ 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;
+ }
+ }
+
+ 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_value_func output_value,
+ /*@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 */
+ else
+ yasm_ops_initialize(&insn->operands);
+ insn->num_prefixes = 0;
+ insn->prefixes = NULL;
+ insn->num_segregs = 0;
+ insn->segregs = NULL;
+
+ return yasm_bc_create_common(&bc_insn_callback, insn, line);
+}
+
+yasm_bytecode *
+yasm_bc_create_empty_insn(yasm_arch *arch, unsigned long line)
+{
+ bytecode_insn *insn = yasm_xmalloc(sizeof(bytecode_insn));
+
+ insn->arch = arch;
+ insn->insn_data[0] = 0;
+ insn->insn_data[1] = 0;
+ insn->insn_data[2] = 0;
+ insn->insn_data[3] = 0;
+ insn->num_operands = 0;
+ yasm_ops_initialize(&insn->operands);
+ 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++;
+}
int (*tobytes) (yasm_bytecode *bc, unsigned char **bufp, void *d,
yasm_output_value_func output_value,
/*@null@*/ yasm_output_reloc_func output_reloc);
+ int reserve; /* Reserve space instead of outputting data */
} yasm_bytecode_callback;
struct yasm_bytecode {
--- /dev/null
+/*
+ * ORG bytecode
+ *
+ * Copyright (C) 2005-2006 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("$Id$");
+
+#include "coretype.h"
+#include "file.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "value.h"
+
+#include "bytecode.h"
+
+#include "bc-int.h"
+
+
+typedef struct bytecode_org {
+ unsigned long start; /* target starting offset within section */
+} bytecode_org;
+
+static void bc_org_destroy(void *contents);
+static void bc_org_print(const void *contents, FILE *f, int indent_level);
+static void bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+static yasm_bc_resolve_flags bc_org_resolve
+ (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
+static int bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static const yasm_bytecode_callback bc_org_callback = {
+ bc_org_destroy,
+ bc_org_print,
+ bc_org_finalize,
+ bc_org_resolve,
+ bc_org_tobytes,
+ 0
+};
+
+
+static void
+bc_org_destroy(void *contents)
+{
+ yasm_xfree(contents);
+}
+
+static void
+bc_org_print(const void *contents, FILE *f, int indent_level)
+{
+ const bytecode_org *org = (const bytecode_org *)contents;
+ fprintf(f, "%*s_Org_\n", indent_level, "");
+ fprintf(f, "%*sStart=%lu\n", indent_level, "", org->start);
+}
+
+static void
+bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+}
+
+static yasm_bc_resolve_flags
+bc_org_resolve(yasm_bytecode *bc, int save,
+ yasm_calc_bc_dist_func calc_bc_dist)
+{
+ bytecode_org *org = (bytecode_org *)bc->contents;
+
+ /* Check for overrun */
+ if (bc->offset > org->start) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("ORG overlap with already existing data"));
+ return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
+ }
+
+ /* Generate space to start offset */
+ bc->len = org->start - bc->offset;
+ return YASM_BC_RESOLVE_MIN_LEN;
+}
+
+static int
+bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ bytecode_org *org = (bytecode_org *)bc->contents;
+ unsigned long len, i;
+
+ /* Sanity check for overrun */
+ if (bc->offset > org->start) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("ORG overlap with already existing data"));
+ return 1;
+ }
+ len = org->start - bc->offset;
+ for (i=0; i<len; i++)
+ YASM_WRITE_8(*bufp, 0);
+ return 0;
+}
+
+yasm_bytecode *
+yasm_bc_create_org(unsigned long start, unsigned long line)
+{
+ bytecode_org *org = yasm_xmalloc(sizeof(bytecode_org));
+
+ org->start = start;
+
+ return yasm_bc_create_common(&bc_org_callback, org, line);
+}
--- /dev/null
+/*
+ * Bytecode utility functions
+ *
+ * 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("$Id$");
+
+#include "coretype.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "value.h"
+
+#include "bytecode.h"
+
+#include "bc-int.h"
+#include "expr-int.h"
+
+
+typedef struct bytecode_reserve {
+ /*@only@*/ /*@null@*/ yasm_expr *numitems; /* number of items to reserve */
+ unsigned char itemsize; /* size of each item (in bytes) */
+} bytecode_reserve;
+
+static void bc_reserve_destroy(void *contents);
+static void bc_reserve_print(const void *contents, FILE *f, int indent_level);
+static void bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+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_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static const yasm_bytecode_callback bc_reserve_callback = {
+ bc_reserve_destroy,
+ bc_reserve_print,
+ bc_reserve_finalize,
+ bc_reserve_resolve,
+ bc_reserve_tobytes,
+ 1
+};
+
+
+static void
+bc_reserve_destroy(void *contents)
+{
+ bytecode_reserve *reserve = (bytecode_reserve *)contents;
+ yasm_expr_destroy(reserve->numitems);
+ yasm_xfree(contents);
+}
+
+static void
+bc_reserve_print(const void *contents, FILE *f, int indent_level)
+{
+ 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);
+ fprintf(f, "\n%*sItem Size=%u\n", indent_level, "",
+ (unsigned int)reserve->itemsize);
+}
+
+static void
+bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
+ yasm_value val;
+
+ if (yasm_value_finalize_expr(&val, reserve->numitems))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("reserve expression too complex"));
+ else if (val.rel)
+ yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
+ N_("reserve expression not absolute"));
+ else if (val.abs && yasm_expr__contains(val.abs, YASM_EXPR_FLOAT))
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("expression must not contain floating point value"));
+ reserve->numitems = val.abs;
+}
+
+static yasm_bc_resolve_flags
+bc_reserve_resolve(yasm_bytecode *bc, int save,
+ yasm_calc_bc_dist_func calc_bc_dist)
+{
+ bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
+ yasm_bc_resolve_flags retval = YASM_BC_RESOLVE_MIN_LEN;
+ /*@null@*/ yasm_expr *temp;
+ yasm_expr **tempp;
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
+
+ if (!reserve->numitems)
+ return YASM_BC_RESOLVE_MIN_LEN;
+
+ if (save) {
+ temp = NULL;
+ tempp = &reserve->numitems;
+ } else {
+ temp = yasm_expr_copy(reserve->numitems);
+ assert(temp != NULL);
+ tempp = &temp;
+ }
+ num = yasm_expr_get_intnum(tempp, calc_bc_dist);
+ if (!num) {
+ /* For reserve, just say non-constant quantity instead of allowing
+ * the circular reference error to filter through.
+ */
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("attempt to reserve non-constant quantity of space"));
+ retval = YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
+ } else
+ bc->len += yasm_intnum_get_uint(num)*reserve->itemsize;
+ yasm_expr_destroy(temp);
+ return retval;
+}
+
+static int
+bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ yasm_internal_error(N_("bc_reserve_tobytes called"));
+ /*@notreached@*/
+ return 1;
+}
+
+yasm_bytecode *
+yasm_bc_create_reserve(yasm_expr *numitems, unsigned int itemsize,
+ unsigned long line)
+{
+ bytecode_reserve *reserve = yasm_xmalloc(sizeof(bytecode_reserve));
+
+ /*@-mustfree@*/
+ reserve->numitems = numitems;
+ /*@=mustfree@*/
+ reserve->itemsize = (unsigned char)itemsize;
+
+ return yasm_bc_create_common(&bc_reserve_callback, reserve, line);
+}
/*@unused@*/ RCSID("$Id$");
#include "coretype.h"
-#include "file.h"
#include "errwarn.h"
#include "intnum.h"
#include "symrec.h"
#include "bytecode.h"
-#include "arch.h"
-#include "objfmt.h"
-#include "dbgfmt.h"
#include "bc-int.h"
#include "expr-int.h"
-struct yasm_dataval {
- /*@reldef@*/ STAILQ_ENTRY(yasm_dataval) link;
-
- enum { DV_EMPTY, DV_VALUE, DV_RAW } type;
-
- union {
- yasm_value val;
- struct {
- /*@only@*/ unsigned char *contents;
- unsigned long len;
- } raw;
- } data;
-};
-
-/* Standard bytecode types */
-
-typedef struct bytecode_data {
- /* converted data (linked list) */
- yasm_datavalhead datahead;
-
- /* final (converted) size of each value element (in bytes) */
- unsigned int size;
-} bytecode_data;
-
-typedef struct bytecode_leb128 {
- /* source data (linked list) */
- yasm_datavalhead datahead;
-
- /* signedness (0=unsigned, 1=signed) */
- int sign;
-
- /* total length (calculated at finalize time) */
- unsigned long len;
-} bytecode_leb128;
-
-typedef struct bytecode_reserve {
- /*@only@*/ /*@null@*/ yasm_expr *numitems; /* number of items to reserve */
- unsigned char itemsize; /* size of each item (in bytes) */
-} bytecode_reserve;
-
-typedef struct bytecode_incbin {
- /*@only@*/ char *filename; /* file to include data from */
-
- /* starting offset to read from (NULL=0) */
- /*@only@*/ /*@null@*/ yasm_expr *start;
-
- /* maximum number of bytes to read (NULL=no limit) */
- /*@only@*/ /*@null@*/ yasm_expr *maxlen;
-} bytecode_incbin;
-
-typedef struct bytecode_align {
- /*@only@*/ yasm_expr *boundary; /* alignment boundary */
-
- /* What to fill intervening locations with, NULL if using code_fill */
- /*@only@*/ /*@null@*/ yasm_expr *fill;
-
- /* Maximum number of bytes to skip, NULL if no maximum. */
- /*@only@*/ /*@null@*/ yasm_expr *maxskip;
-
- /* Code fill, NULL if using 0 fill */
- /*@null@*/ const unsigned char **code_fill;
-} bytecode_align;
-
-typedef struct bytecode_org {
- unsigned long start; /* target starting offset within section */
-} bytecode_org;
-
-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(void *contents);
-static void bc_data_print(const void *contents, FILE *f, int indent_level);
-static void bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
-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_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc);
-
-static void bc_leb128_destroy(void *contents);
-static void bc_leb128_print(const void *contents, FILE *f, int indent_level);
-static void bc_leb128_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
-static yasm_bc_resolve_flags bc_leb128_resolve
- (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
-static int bc_leb128_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
- yasm_output_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc);
-
-static void bc_reserve_destroy(void *contents);
-static void bc_reserve_print(const void *contents, FILE *f, int indent_level);
-static void bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
-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_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc);
-
-static void bc_incbin_destroy(void *contents);
-static void bc_incbin_print(const void *contents, FILE *f, int indent_level);
-static void bc_incbin_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
-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_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc);
-
-static void bc_align_destroy(void *contents);
-static void bc_align_print(const void *contents, FILE *f, int indent_level);
-static void bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
-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_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc);
-
-static void bc_org_destroy(void *contents);
-static void bc_org_print(const void *contents, FILE *f, int indent_level);
-static void bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
-static yasm_bc_resolve_flags bc_org_resolve
- (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
-static int bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
- yasm_output_value_func output_value,
- /*@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_value_func output_value,
- /*@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,
- bc_data_finalize,
- bc_data_resolve,
- bc_data_tobytes
-};
-
-static const yasm_bytecode_callback bc_leb128_callback = {
- bc_leb128_destroy,
- bc_leb128_print,
- bc_leb128_finalize,
- bc_leb128_resolve,
- bc_leb128_tobytes
-};
-
-static const yasm_bytecode_callback bc_reserve_callback = {
- bc_reserve_destroy,
- bc_reserve_print,
- bc_reserve_finalize,
- bc_reserve_resolve,
- bc_reserve_tobytes
-};
-
-static const yasm_bytecode_callback bc_incbin_callback = {
- bc_incbin_destroy,
- bc_incbin_print,
- bc_incbin_finalize,
- bc_incbin_resolve,
- bc_incbin_tobytes
-};
-
-static const yasm_bytecode_callback bc_align_callback = {
- bc_align_destroy,
- bc_align_print,
- bc_align_finalize,
- bc_align_resolve,
- bc_align_tobytes
-};
-
-static const yasm_bytecode_callback bc_org_callback = {
- bc_org_destroy,
- bc_org_print,
- bc_org_finalize,
- bc_org_resolve,
- bc_org_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];
-
-
-yasm_immval *
-yasm_imm_create_expr(yasm_expr *e)
-{
- yasm_immval *im = yasm_xmalloc(sizeof(yasm_immval));
-
- if (yasm_value_finalize_expr(&im->val, e))
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("immediate expression too complex"));
- im->len = 0;
- im->sign = 0;
-
- return im;
-}
-
-const yasm_expr *
-yasm_ea_get_disp(const yasm_effaddr *ea)
-{
- return ea->disp.abs;
-}
-
-void
-yasm_ea_set_len(yasm_effaddr *ptr, unsigned int len)
-{
- if (!ptr)
- return;
-
- /* Currently don't warn if length truncated, as this is called only from
- * an explicit override, where we expect the user knows what they're doing.
- */
-
- ptr->disp_len = (unsigned char)len;
-}
-
-void
-yasm_ea_set_nosplit(yasm_effaddr *ptr, unsigned int nosplit)
-{
- if (!ptr)
- return;
-
- ptr->nosplit = (unsigned char)nosplit;
-}
-
-void
-yasm_ea_set_strong(yasm_effaddr *ptr, unsigned int strong)
-{
- if (!ptr)
- return;
-
- ptr->strong = (unsigned char)strong;
-}
-
-void
-yasm_ea_set_segreg(yasm_effaddr *ea, unsigned long 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;
-}
-
-/*@-nullstate@*/
-void
-yasm_ea_destroy(yasm_effaddr *ea)
-{
- ea->callback->destroy(ea);
- yasm_value_delete(&ea->disp);
- yasm_xfree(ea);
-}
-/*@=nullstate@*/
-
-/*@-nullstate@*/
-void
-yasm_ea_print(const yasm_effaddr *ea, FILE *f, int indent_level)
-{
- fprintf(f, "%*sDisp:\n", indent_level, "");
- yasm_value_print(&ea->disp, f, indent_level+1);
- fprintf(f, "%*sLen=%u\n", indent_level, "", (unsigned int)ea->disp_len);
- fprintf(f, "%*sNoSplit=%u\n", indent_level, "", (unsigned int)ea->nosplit);
- ea->callback->print(ea, f, indent_level);
-}
-/*@=nullstate@*/
-
void
yasm_bc_set_multiple(yasm_bytecode *bc, yasm_expr *e)
{
return bc;
}
-static void
-bc_data_destroy(void *contents)
-{
- bytecode_data *bc_data = (bytecode_data *)contents;
- yasm_dvs_destroy(&bc_data->datahead);
- yasm_xfree(contents);
-}
-
-static void
-bc_data_print(const void *contents, FILE *f, int indent_level)
-{
- const bytecode_data *bc_data = (const bytecode_data *)contents;
- fprintf(f, "%*s_Data_\n", indent_level, "");
- fprintf(f, "%*sElements:\n", indent_level+1, "");
- yasm_dvs_print(&bc_data->datahead, f, indent_level+2);
-}
-
-static void
-bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
-{
- bytecode_data *bc_data = (bytecode_data *)bc->contents;
- yasm_dataval *dv;
-
- /* Convert values from simple expr to value. */
- STAILQ_FOREACH(dv, &bc_data->datahead, link) {
- if (dv->type == DV_VALUE) {
- if (yasm_value_finalize(&dv->data.val))
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("data expression too complex"));
- }
- }
-}
-
-static yasm_bc_resolve_flags
-bc_data_resolve(yasm_bytecode *bc, int save,
- yasm_calc_bc_dist_func calc_bc_dist)
-{
- bytecode_data *bc_data = (bytecode_data *)bc->contents;
- yasm_dataval *dv;
-
- /* Count up element sizes, rounding up string length. */
- STAILQ_FOREACH(dv, &bc_data->datahead, link) {
- switch (dv->type) {
- case DV_EMPTY:
- break;
- case DV_VALUE:
- bc->len += bc_data->size;
- break;
- case DV_RAW:
- bc->len += dv->data.raw.len;
- break;
- }
- }
-
- return YASM_BC_RESOLVE_MIN_LEN;
-}
-
-static int
-bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
- yasm_output_value_func output_value,
- /*@unused@*/ yasm_output_reloc_func output_reloc)
-{
- bytecode_data *bc_data = (bytecode_data *)bc->contents;
- yasm_dataval *dv;
- unsigned char *bufp_orig = *bufp;
-
- STAILQ_FOREACH(dv, &bc_data->datahead, link) {
- switch (dv->type) {
- case DV_EMPTY:
- break;
- case DV_VALUE:
- if (output_value(&dv->data.val, *bufp, bc_data->size,
- (size_t)(bc_data->size*8), 0,
- (unsigned long)(*bufp-bufp_orig), bc, 1, d))
- return 1;
- *bufp += bc_data->size;
- break;
- case DV_RAW:
- memcpy(*bufp, dv->data.raw.contents, dv->data.raw.len);
- *bufp += dv->data.raw.len;
- break;
- }
- }
-
- return 0;
-}
-
-yasm_bytecode *
-yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size,
- int append_zero, yasm_arch *arch, unsigned long line)
-{
- bytecode_data *data = yasm_xmalloc(sizeof(bytecode_data));
- yasm_bytecode *bc = yasm_bc_create_common(&bc_data_callback, data, line);
- yasm_dataval *dv, *dv2, *dvo;
- yasm_intnum *intn;
- unsigned long len = 0, rlen, i;
-
-
- yasm_dvs_initialize(&data->datahead);
- data->size = size;
-
- /* Prescan input data for length, etc. Careful: this needs to be
- * precisely paired with the second loop.
- */
- STAILQ_FOREACH(dv, datahead, link) {
- switch (dv->type) {
- case DV_EMPTY:
- break;
- case DV_VALUE:
- if ((arch || size == 1) && dv->data.val.abs &&
- yasm_expr_get_intnum(&dv->data.val.abs, NULL))
- len += size;
- else {
- if (len > 0) {
- /* Create bytecode for all previous len */
- dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
- STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
- len = 0;
- }
-
- /* Create bytecode for this value */
- dvo = yasm_xmalloc(sizeof(yasm_dataval));
- STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
- }
- break;
- case DV_RAW:
- rlen = dv->data.raw.len;
- /* find count, rounding up to nearest multiple of size */
- rlen = (rlen + size - 1) / size;
- len += rlen*size;
- break;
- }
- if (append_zero)
- len++;
- }
-
- /* Create final dataval for any trailing length */
- if (len > 0) {
- dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
- STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
- }
-
- /* Second iteration: copy data and delete input datavals. */
- dv = STAILQ_FIRST(datahead);
- dvo = STAILQ_FIRST(&data->datahead);
- len = 0;
- while (dv) {
- switch (dv->type) {
- case DV_EMPTY:
- break;
- case DV_VALUE:
- if ((arch || size == 1) && dv->data.val.abs &&
- (intn = yasm_expr_get_intnum(&dv->data.val.abs, NULL))) {
- if (size == 1)
- yasm_intnum_get_sized(intn,
- &dvo->data.raw.contents[len],
- 1, 8, 0, 0, 1);
- else
- yasm_arch_intnum_tobytes(arch, intn,
- &dvo->data.raw.contents[len],
- size, size*8, 0, bc, 1);
- yasm_value_delete(&dv->data.val);
- len += size;
- } else {
- dvo->type = DV_VALUE;
- dvo->data.val = dv->data.val; /* structure copy */
- dvo = STAILQ_NEXT(dvo, link);
- len = 0;
- }
- break;
- case DV_RAW:
- rlen = dv->data.raw.len;
- memcpy(&dvo->data.raw.contents[len], dv->data.raw.contents,
- rlen);
- yasm_xfree(dv->data.raw.contents);
- len += rlen;
- /* pad with 0's to nearest multiple of size */
- rlen %= size;
- if (rlen > 0) {
- rlen = size-rlen;
- for (i=0; i<rlen; i++)
- dvo->data.raw.contents[len++] = 0;
- }
- break;
- }
- if (append_zero)
- dvo->data.raw.contents[len++] = 0;
- dv2 = STAILQ_NEXT(dv, link);
- yasm_xfree(dv);
- dv = dv2;
- }
-
- return bc;
-}
-
-static void
-bc_leb128_destroy(void *contents)
-{
- bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)contents;
- yasm_dvs_destroy(&bc_leb128->datahead);
- yasm_xfree(contents);
-}
-
-static void
-bc_leb128_print(const void *contents, FILE *f, int indent_level)
-{
- const bytecode_leb128 *bc_leb128 = (const bytecode_leb128 *)contents;
- fprintf(f, "%*s_Data_\n", indent_level, "");
- fprintf(f, "%*sSign=%u\n", indent_level+1, "",
- (unsigned int)bc_leb128->sign);
- fprintf(f, "%*sElements:\n", indent_level+1, "");
- yasm_dvs_print(&bc_leb128->datahead, f, indent_level+2);
-}
-
-static void
-bc_leb128_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
-{
- bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)bc->contents;
- yasm_dataval *dv;
- /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
-
- /* Only constant expressions are allowed.
- * Because of this, go ahead and calculate length.
- */
- bc_leb128->len = 0;
- STAILQ_FOREACH(dv, &bc_leb128->datahead, link) {
- switch (dv->type) {
- case DV_EMPTY:
- break;
- case DV_VALUE:
- intn = yasm_expr_get_intnum(&dv->data.val.abs, NULL);
- if (!intn) {
- yasm_error_set(YASM_ERROR_NOT_CONSTANT,
- N_("LEB128 requires constant values"));
- return;
- }
- /* Warn for negative values in unsigned environment.
- * This could be an error instead: the likelihood this is
- * desired is very low!
- */
- if (yasm_intnum_sign(intn) == -1 && !bc_leb128->sign)
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("negative value in unsigned LEB128"));
- bc_leb128->len +=
- yasm_intnum_size_leb128(intn, bc_leb128->sign);
- break;
- case DV_RAW:
- yasm_error_set(YASM_ERROR_VALUE,
- N_("LEB128 does not allow string constants"));
- return;
- }
- }
-}
-
-static yasm_bc_resolve_flags
-bc_leb128_resolve(yasm_bytecode *bc, int save,
- yasm_calc_bc_dist_func calc_bc_dist)
-{
- bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)bc->contents;
- bc->len += bc_leb128->len;
- return YASM_BC_RESOLVE_MIN_LEN;
-}
-
-static int
-bc_leb128_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
- yasm_output_value_func output_value,
- /*@unused@*/ yasm_output_reloc_func output_reloc)
-{
- bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)bc->contents;
- yasm_dataval *dv;
- /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
-
- STAILQ_FOREACH(dv, &bc_leb128->datahead, link) {
- switch (dv->type) {
- case DV_EMPTY:
- break;
- case DV_VALUE:
- intn = yasm_expr_get_intnum(&dv->data.val.abs, NULL);
- if (!intn)
- yasm_internal_error(N_("non-constant in leb128_tobytes"));
- *bufp += yasm_intnum_get_leb128(intn, *bufp, bc_leb128->sign);
- break;
- case DV_RAW:
- yasm_internal_error(N_("raw in leb128_tobytes"));
- }
- }
-
- return 0;
-}
-
-yasm_bytecode *
-yasm_bc_create_leb128(yasm_datavalhead *datahead, int sign, unsigned long line)
-{
- bytecode_leb128 *leb128 = yasm_xmalloc(sizeof(bytecode_leb128));
-
- leb128->datahead = *datahead;
- leb128->sign = sign;
-
- return yasm_bc_create_common(&bc_leb128_callback, leb128, line);
-}
-
-static void
-bc_reserve_destroy(void *contents)
-{
- bytecode_reserve *reserve = (bytecode_reserve *)contents;
- yasm_expr_destroy(reserve->numitems);
- yasm_xfree(contents);
-}
-
-static void
-bc_reserve_print(const void *contents, FILE *f, int indent_level)
-{
- 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);
- fprintf(f, "\n%*sItem Size=%u\n", indent_level, "",
- (unsigned int)reserve->itemsize);
-}
-
-static void
-bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
-{
- bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
- yasm_value val;
-
- if (yasm_value_finalize_expr(&val, reserve->numitems))
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("reserve expression too complex"));
- else if (val.rel)
- yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
- N_("reserve expression not absolute"));
- else if (val.abs && yasm_expr__contains(val.abs, YASM_EXPR_FLOAT))
- yasm_error_set(YASM_ERROR_VALUE,
- N_("expression must not contain floating point value"));
- reserve->numitems = val.abs;
-}
-
-static yasm_bc_resolve_flags
-bc_reserve_resolve(yasm_bytecode *bc, int save,
- yasm_calc_bc_dist_func calc_bc_dist)
-{
- bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
- yasm_bc_resolve_flags retval = YASM_BC_RESOLVE_MIN_LEN;
- /*@null@*/ yasm_expr *temp;
- yasm_expr **tempp;
- /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
-
- if (!reserve->numitems)
- return YASM_BC_RESOLVE_MIN_LEN;
-
- if (save) {
- temp = NULL;
- tempp = &reserve->numitems;
- } else {
- temp = yasm_expr_copy(reserve->numitems);
- assert(temp != NULL);
- tempp = &temp;
- }
- num = yasm_expr_get_intnum(tempp, calc_bc_dist);
- if (!num) {
- /* For reserve, just say non-constant quantity instead of allowing
- * the circular reference error to filter through.
- */
- yasm_error_set(YASM_ERROR_NOT_CONSTANT,
- N_("attempt to reserve non-constant quantity of space"));
- retval = YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
- } else
- bc->len += yasm_intnum_get_uint(num)*reserve->itemsize;
- yasm_expr_destroy(temp);
- return retval;
-}
-
-static int
-bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
- yasm_output_value_func output_value,
- /*@unused@*/ yasm_output_reloc_func output_reloc)
-{
- yasm_internal_error(N_("bc_reserve_tobytes called"));
- /*@notreached@*/
- return 1;
-}
-
-yasm_bytecode *
-yasm_bc_create_reserve(yasm_expr *numitems, unsigned int itemsize,
- unsigned long line)
-{
- bytecode_reserve *reserve = yasm_xmalloc(sizeof(bytecode_reserve));
-
- /*@-mustfree@*/
- reserve->numitems = numitems;
- /*@=mustfree@*/
- reserve->itemsize = (unsigned char)itemsize;
-
- return yasm_bc_create_common(&bc_reserve_callback, reserve, line);
-}
-
-static void
-bc_incbin_destroy(void *contents)
-{
- 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 void *contents, FILE *f, int indent_level)
-{
- const bytecode_incbin *incbin = (const bytecode_incbin *)contents;
- fprintf(f, "%*s_IncBin_\n", indent_level, "");
- fprintf(f, "%*sFilename=`%s'\n", indent_level, "",
- incbin->filename);
- fprintf(f, "%*sStart=", indent_level, "");
- if (!incbin->start)
- fprintf(f, "nil (0)");
- else
- yasm_expr_print(incbin->start, f);
- fprintf(f, "%*sMax Len=", indent_level, "");
- if (!incbin->maxlen)
- fprintf(f, "nil (unlimited)");
- else
- yasm_expr_print(incbin->maxlen, f);
- fprintf(f, "\n");
-}
-
-static void
-bc_incbin_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
-{
- bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
- yasm_value val;
-
- if (yasm_value_finalize_expr(&val, incbin->start))
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("start expression too complex"));
- else if (val.rel)
- yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
- N_("start expression not absolute"));
- incbin->start = val.abs;
-
- if (yasm_value_finalize_expr(&val, incbin->maxlen))
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("maximum length expression too complex"));
- else if (val.rel)
- yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
- N_("maximum length expression not absolute"));
- incbin->maxlen = val.abs;
-}
-
-static yasm_bc_resolve_flags
-bc_incbin_resolve(yasm_bytecode *bc, int save,
- yasm_calc_bc_dist_func calc_bc_dist)
-{
- bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
- FILE *f;
- /*@null@*/ yasm_expr *temp;
- yasm_expr **tempp;
- /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
- unsigned long start = 0, maxlen = 0xFFFFFFFFUL, flen;
-
- /* Try to convert start to integer value */
- if (incbin->start) {
- if (save) {
- temp = NULL;
- tempp = &incbin->start;
- } else {
- temp = yasm_expr_copy(incbin->start);
- assert(temp != NULL);
- tempp = &temp;
- }
- num = yasm_expr_get_intnum(tempp, calc_bc_dist);
- if (num)
- start = yasm_intnum_get_uint(num);
- yasm_expr_destroy(temp);
- if (!num)
- return YASM_BC_RESOLVE_UNKNOWN_LEN;
- }
-
- /* Try to convert maxlen to integer value */
- if (incbin->maxlen) {
- if (save) {
- temp = NULL;
- tempp = &incbin->maxlen;
- } else {
- temp = yasm_expr_copy(incbin->maxlen);
- assert(temp != NULL);
- tempp = &temp;
- }
- num = yasm_expr_get_intnum(tempp, calc_bc_dist);
- if (num)
- maxlen = yasm_intnum_get_uint(num);
- yasm_expr_destroy(temp);
- if (!num)
- return YASM_BC_RESOLVE_UNKNOWN_LEN;
- }
-
- /* FIXME: Search include path for filename. Save full path back into
- * filename if save is true.
- */
-
- /* Open file and determine its length */
- f = fopen(incbin->filename, "rb");
- if (!f) {
- yasm_error_set(YASM_ERROR_IO,
- N_("`incbin': unable to open file `%s'"),
- incbin->filename);
- return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
- }
- if (fseek(f, 0L, SEEK_END) < 0) {
- yasm_error_set(YASM_ERROR_IO,
- N_("`incbin': unable to seek on file `%s'"),
- incbin->filename);
- return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
- }
- flen = (unsigned long)ftell(f);
- fclose(f);
-
- /* Compute length of incbin from start, maxlen, and len */
- if (start > flen) {
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("`incbin': start past end of file `%s'"),
- incbin->filename);
- start = flen;
- }
- flen -= start;
- if (incbin->maxlen)
- if (maxlen < flen)
- flen = maxlen;
- bc->len += flen;
- return YASM_BC_RESOLVE_MIN_LEN;
-}
-
-static int
-bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
- yasm_output_value_func output_value,
- /*@unused@*/ yasm_output_reloc_func output_reloc)
-{
- bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
- FILE *f;
- /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
- unsigned long start = 0;
-
- /* Convert start to integer value */
- if (incbin->start) {
- num = yasm_expr_get_intnum(&incbin->start, NULL);
- if (!num)
- yasm_internal_error(
- N_("could not determine start in bc_tobytes_incbin"));
- start = yasm_intnum_get_uint(num);
- }
-
- /* Open file */
- f = fopen(incbin->filename, "rb");
- if (!f) {
- yasm_error_set(YASM_ERROR_IO, N_("`incbin': unable to open file `%s'"),
- incbin->filename);
- return 1;
- }
-
- /* Seek to start of data */
- if (fseek(f, (long)start, SEEK_SET) < 0) {
- yasm_error_set(YASM_ERROR_IO,
- N_("`incbin': unable to seek on file `%s'"),
- incbin->filename);
- fclose(f);
- return 1;
- }
-
- /* Read len bytes */
- if (fread(*bufp, 1, (size_t)bc->len, f) < (size_t)bc->len) {
- yasm_error_set(YASM_ERROR_IO,
- N_("`incbin': unable to read %lu bytes from file `%s'"),
- bc->len, incbin->filename);
- fclose(f);
- return 1;
- }
-
- *bufp += bc->len;
- fclose(f);
- return 0;
-}
-
-yasm_bytecode *
-yasm_bc_create_incbin(char *filename, yasm_expr *start, yasm_expr *maxlen,
- unsigned long line)
-{
- bytecode_incbin *incbin = yasm_xmalloc(sizeof(bytecode_incbin));
-
- /*@-mustfree@*/
- incbin->filename = filename;
- incbin->start = start;
- incbin->maxlen = maxlen;
- /*@=mustfree@*/
-
- return yasm_bc_create_common(&bc_incbin_callback, incbin, line);
-}
-
-static void
-bc_align_destroy(void *contents)
-{
- bytecode_align *align = (bytecode_align *)contents;
- if (align->boundary)
- yasm_expr_destroy(align->boundary);
- if (align->fill)
- yasm_expr_destroy(align->fill);
- if (align->maxskip)
- yasm_expr_destroy(align->maxskip);
- yasm_xfree(contents);
-}
-
-static void
-bc_align_print(const void *contents, FILE *f, int indent_level)
-{
- const bytecode_align *align = (const bytecode_align *)contents;
- fprintf(f, "%*s_Align_\n", indent_level, "");
- fprintf(f, "%*sBoundary=", indent_level, "");
- yasm_expr_print(align->boundary, f);
- fprintf(f, "\n%*sFill=", indent_level, "");
- yasm_expr_print(align->fill, f);
- fprintf(f, "\n%*sMax Skip=", indent_level, "");
- yasm_expr_print(align->maxskip, f);
- fprintf(f, "\n");
-}
-
-static void
-bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
-{
- bytecode_align *align = (bytecode_align *)bc->contents;
- if (!yasm_expr_get_intnum(&align->boundary, NULL))
- yasm_error_set(YASM_ERROR_NOT_CONSTANT,
- N_("align boundary must be a constant"));
- if (align->fill && !yasm_expr_get_intnum(&align->fill, NULL))
- yasm_error_set(YASM_ERROR_NOT_CONSTANT,
- N_("align fill must be a constant"));
- if (align->maxskip && !yasm_expr_get_intnum(&align->maxskip, NULL))
- yasm_error_set(YASM_ERROR_NOT_CONSTANT,
- N_("align maximum skip must be a constant"));
-}
-
-static yasm_bc_resolve_flags
-bc_align_resolve(yasm_bytecode *bc, int save,
- yasm_calc_bc_dist_func calc_bc_dist)
-{
- bytecode_align *align = (bytecode_align *)bc->contents;
- unsigned long end;
- unsigned long boundary =
- yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, NULL));
-
- if (boundary == 0) {
- bc->len = 0;
- return YASM_BC_RESOLVE_MIN_LEN;
- }
-
- end = bc->offset;
- if (bc->offset & (boundary-1))
- end = (bc->offset & ~(boundary-1)) + boundary;
-
- bc->len = end - bc->offset;
-
- if (align->maxskip) {
- unsigned long maxskip =
- yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, NULL));
- if ((end - bc->offset) > maxskip)
- bc->len = 0;
- }
- return YASM_BC_RESOLVE_MIN_LEN;
-}
-
-static int
-bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
- yasm_output_value_func output_value,
- /*@unused@*/ yasm_output_reloc_func output_reloc)
-{
- bytecode_align *align = (bytecode_align *)bc->contents;
- unsigned long len;
- unsigned long boundary =
- yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, NULL));
-
- if (boundary == 0)
- return 0;
- else {
- unsigned long end = bc->offset;
- if (bc->offset & (boundary-1))
- end = (bc->offset & ~(boundary-1)) + boundary;
- len = end - bc->offset;
- if (len == 0)
- return 0;
- if (align->maxskip) {
- unsigned long maxskip =
- yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip,
- NULL));
- if (len > maxskip)
- return 0;
- }
- }
-
- if (align->fill) {
- unsigned long v;
- v = yasm_intnum_get_uint(yasm_expr_get_intnum(&align->fill, NULL));
- memset(*bufp, (int)v, len);
- *bufp += len;
- } else if (align->code_fill) {
- unsigned long maxlen = 15;
- while (!align->code_fill[maxlen] && maxlen>0)
- maxlen--;
- if (maxlen == 0) {
- yasm_error_set(YASM_ERROR_GENERAL,
- N_("could not find any code alignment size"));
- return 1;
- }
-
- /* Fill with maximum code fill as much as possible */
- while (len > maxlen) {
- memcpy(*bufp, align->code_fill[maxlen], maxlen);
- *bufp += maxlen;
- len -= maxlen;
- }
-
- if (!align->code_fill[len]) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("invalid alignment size %d"), len);
- return 1;
- }
- /* Handle rest of code fill */
- memcpy(*bufp, align->code_fill[len], len);
- *bufp += len;
- } else {
- /* Just fill with 0 */
- memset(*bufp, 0, len);
- *bufp += len;
- }
- return 0;
-}
-
-yasm_bytecode *
-yasm_bc_create_align(yasm_expr *boundary, yasm_expr *fill,
- yasm_expr *maxskip, const unsigned char **code_fill,
- unsigned long line)
-{
- bytecode_align *align = yasm_xmalloc(sizeof(bytecode_align));
-
- align->boundary = boundary;
- align->fill = fill;
- align->maxskip = maxskip;
- align->code_fill = code_fill;
-
- return yasm_bc_create_common(&bc_align_callback, align, line);
-}
-
-static void
-bc_org_destroy(void *contents)
-{
- yasm_xfree(contents);
-}
-
-static void
-bc_org_print(const void *contents, FILE *f, int indent_level)
-{
- const bytecode_org *org = (const bytecode_org *)contents;
- fprintf(f, "%*s_Org_\n", indent_level, "");
- fprintf(f, "%*sStart=%lu\n", indent_level, "", org->start);
-}
-
-static void
-bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
-{
-}
-
-static yasm_bc_resolve_flags
-bc_org_resolve(yasm_bytecode *bc, int save,
- yasm_calc_bc_dist_func calc_bc_dist)
-{
- bytecode_org *org = (bytecode_org *)bc->contents;
-
- /* Check for overrun */
- if (bc->offset > org->start) {
- yasm_error_set(YASM_ERROR_GENERAL,
- N_("ORG overlap with already existing data"));
- return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
- }
-
- /* Generate space to start offset */
- bc->len = org->start - bc->offset;
- return YASM_BC_RESOLVE_MIN_LEN;
-}
-
-static int
-bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
- yasm_output_value_func output_value,
- /*@unused@*/ yasm_output_reloc_func output_reloc)
-{
- bytecode_org *org = (bytecode_org *)bc->contents;
- unsigned long len, i;
-
- /* Sanity check for overrun */
- if (bc->offset > org->start) {
- yasm_error_set(YASM_ERROR_GENERAL,
- N_("ORG overlap with already existing data"));
- return 1;
- }
- len = org->start - bc->offset;
- for (i=0; i<len; i++)
- YASM_WRITE_8(*bufp, 0);
- return 0;
-}
-
-yasm_bytecode *
-yasm_bc_create_org(unsigned long start, unsigned long line)
-{
- bytecode_org *org = yasm_xmalloc(sizeof(bytecode_org));
-
- org->start = start;
-
- return yasm_bc_create_common(&bc_org_callback, org, 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;
- 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_ops_first(&insn->operands);
- op && i<insn->num_operands; op = yasm_operand_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,
- NULL, NULL, 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, NULL, NULL,
- 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;
- }
- }
-
- 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_value_func output_value,
- /*@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 */
- else
- yasm_ops_initialize(&insn->operands);
- insn->num_prefixes = 0;
- insn->prefixes = NULL;
- insn->num_segregs = 0;
- insn->segregs = NULL;
-
- return yasm_bc_create_common(&bc_insn_callback, insn, line);
-}
-
-yasm_bytecode *
-yasm_bc_create_empty_insn(yasm_arch *arch, unsigned long line)
-{
- bytecode_insn *insn = yasm_xmalloc(sizeof(bytecode_insn));
-
- insn->arch = arch;
- insn->insn_data[0] = 0;
- insn->insn_data[1] = 0;
- insn->insn_data[2] = 0;
- insn->insn_data[3] = 0;
- insn->num_operands = 0;
- yasm_ops_initialize(&insn->operands);
- 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 *
yasm_bc_get_section(yasm_bytecode *bc)
{
datasize = bc->len / (*multiple);
/* special case for reserve bytecodes */
- if (bc->callback == &bc_reserve_callback) {
+ if (bc->callback->reserve) {
*bufsize = datasize;
*gap = 1;
return NULL; /* we didn't allocate a buffer */
N_("written length does not match optimized length"));
return mybuf;
}
-
-yasm_dataval *
-yasm_dv_create_expr(yasm_expr *e)
-{
- yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
-
- retval->type = DV_VALUE;
- yasm_value_initialize(&retval->data.val, e);
-
- return retval;
-}
-
-yasm_dataval *
-yasm_dv_create_raw(unsigned char *contents, unsigned long len)
-{
- yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
-
- retval->type = DV_RAW;
- retval->data.raw.contents = contents;
- retval->data.raw.len = len;
-
- return retval;
-}
-
-void
-yasm_dvs_destroy(yasm_datavalhead *headp)
-{
- yasm_dataval *cur, *next;
-
- cur = STAILQ_FIRST(headp);
- while (cur) {
- next = STAILQ_NEXT(cur, link);
- switch (cur->type) {
- case DV_VALUE:
- yasm_value_delete(&cur->data.val);
- break;
- case DV_RAW:
- yasm_xfree(cur->data.raw.contents);
- break;
- default:
- break;
- }
- yasm_xfree(cur);
- cur = next;
- }
- STAILQ_INIT(headp);
-}
-
-yasm_dataval *
-yasm_dvs_append(yasm_datavalhead *headp, yasm_dataval *dv)
-{
- if (dv) {
- STAILQ_INSERT_TAIL(headp, dv, link);
- return dv;
- }
- return (yasm_dataval *)NULL;
-}
-
-void
-yasm_dvs_print(const yasm_datavalhead *head, FILE *f, int indent_level)
-{
- yasm_dataval *cur;
- unsigned long i;
-
- STAILQ_FOREACH(cur, head, link) {
- switch (cur->type) {
- case DV_EMPTY:
- fprintf(f, "%*sEmpty\n", indent_level, "");
- break;
- case DV_VALUE:
- fprintf(f, "%*sValue:\n", indent_level, "");
- yasm_value_print(&cur->data.val, f, indent_level+1);
- break;
- case DV_RAW:
- fprintf(f, "%*sLength=%lu\n", indent_level, "",
- cur->data.raw.len);
- fprintf(f, "%*sBytes=[", indent_level, "");
- for (i=0; i<cur->data.raw.len; i++)
- fprintf(f, "0x%02x, ", cur->data.raw.contents[i]);
- fprintf(f, "]\n");
- break;
- }
- }
-}
-
-/* Non-macro yasm_dvs_initialize() for non-YASM_LIB_INTERNAL users. */
-#undef yasm_dvs_initialize
-void
-yasm_dvs_initialize(yasm_datavalhead *headp)
-{
- STAILQ_INIT(headp);
-}
lc3b_bc_insn_print,
yasm_bc_finalize_common,
lc3b_bc_insn_resolve,
- lc3b_bc_insn_tobytes
+ lc3b_bc_insn_tobytes,
+ 0
};
x86_bc_insn_print,
yasm_bc_finalize_common,
x86_bc_insn_resolve,
- x86_bc_insn_tobytes
+ x86_bc_insn_tobytes,
+ 0
};
static const yasm_bytecode_callback x86_bc_callback_jmp = {
x86_bc_jmp_print,
yasm_bc_finalize_common,
x86_bc_jmp_resolve,
- x86_bc_jmp_tobytes
+ x86_bc_jmp_tobytes,
+ 0
};
static const yasm_bytecode_callback x86_bc_callback_jmpfar = {
x86_bc_jmpfar_print,
yasm_bc_finalize_common,
x86_bc_jmpfar_resolve,
- x86_bc_jmpfar_tobytes
+ x86_bc_jmpfar_tobytes,
+ 0
};
int
cv8_symhead_bc_print,
yasm_bc_finalize_common,
cv8_symhead_bc_resolve,
- cv8_symhead_bc_tobytes
+ cv8_symhead_bc_tobytes,
+ 0
};
static const yasm_bytecode_callback cv8_fileinfo_bc_callback = {
cv8_fileinfo_bc_print,
yasm_bc_finalize_common,
cv8_fileinfo_bc_resolve,
- cv8_fileinfo_bc_tobytes
+ cv8_fileinfo_bc_tobytes,
+ 0
};
static const yasm_bytecode_callback cv8_lineinfo_bc_callback = {
cv8_lineinfo_bc_print,
yasm_bc_finalize_common,
cv8_lineinfo_bc_resolve,
- cv8_lineinfo_bc_tobytes
+ cv8_lineinfo_bc_tobytes,
+ 0
};
static const yasm_bytecode_callback cv_sym_bc_callback = {
cv_sym_bc_print,
yasm_bc_finalize_common,
cv_sym_bc_resolve,
- cv_sym_bc_tobytes
+ cv_sym_bc_tobytes,
+ 0
};
static cv8_symhead *cv8_add_symhead(yasm_dbgfmt_cv *dbgfmt_cv,
cv_type_bc_print,
yasm_bc_finalize_common,
cv_type_bc_resolve,
- cv_type_bc_tobytes
+ cv_type_bc_tobytes,
+ 0
};
static cv_type *cv_type_create(yasm_dbgfmt_cv *dbgfmt_cv, unsigned long indx);
dwarf2_head_bc_print,
yasm_bc_finalize_common,
dwarf2_head_bc_resolve,
- dwarf2_head_bc_tobytes
+ dwarf2_head_bc_tobytes,
+ 0
};
/* Section data callback function prototypes */
dwarf2_abbrev_bc_print,
yasm_bc_finalize_common,
dwarf2_abbrev_bc_resolve,
- dwarf2_abbrev_bc_tobytes
+ dwarf2_abbrev_bc_tobytes,
+ 0
};
dwarf2_spp_bc_print,
yasm_bc_finalize_common,
dwarf2_spp_bc_resolve,
- dwarf2_spp_bc_tobytes
+ dwarf2_spp_bc_tobytes,
+ 0
};
static const yasm_bytecode_callback dwarf2_line_op_bc_callback = {
dwarf2_line_op_bc_print,
yasm_bc_finalize_common,
dwarf2_line_op_bc_resolve,
- dwarf2_line_op_bc_tobytes
+ dwarf2_line_op_bc_tobytes,
+ 0
};
stabs_bc_str_print,
yasm_bc_finalize_common,
stabs_bc_str_resolve,
- stabs_bc_str_tobytes
+ stabs_bc_str_tobytes,
+ 0
};
static const yasm_bytecode_callback stabs_bc_stab_callback = {
stabs_bc_stab_print,
yasm_bc_finalize_common,
stabs_bc_stab_resolve,
- stabs_bc_stab_tobytes
+ stabs_bc_stab_tobytes,
+ 0
};
yasm_dbgfmt_module yasm_stabs_LTX_dbgfmt;
int (*tobytes) (yasm_bytecode *bc, unsigned char **bufp, void *d,
yasm_output_value_func output_value,
yasm_output_reloc_func output_reloc)
+ int reserve
cdef struct yasm_bytecode:
yasm_bytecode_callback *callback