]> granicus.if.org Git - yasm/commitdiff
Move generation of arch instruction bytecodes from on-the-fly during the
authorPeter Johnson <peter@tortall.net>
Sun, 14 Nov 2004 23:17:17 +0000 (23:17 -0000)
committerPeter Johnson <peter@tortall.net>
Sun, 14 Nov 2004 23:17:17 +0000 (23:17 -0000)
initial parse stage to a new pass between parse and optimization.  This
should allow for more accurate generation of arch bytecodes and other future
code simplifications in arch.

This change necessitated changing how bytecodes are extended from the base
yasm_bytecode structure; the original method did not allow for bytecodes to
be reliably changed from one type to another, as reallocation of the base
structure to fit the new type could result in the entire structure being
relocated on the heap, and thus all the pointer references to the original
bytecode being lost.  After this commit, the yasm_bytecode base structure
has a void pointer to any extension data.  This change rippled across all
bytecode-creating source files, and comprises the majority of this commit.

* bc-int.h (yasm_bytecode): Add contents pointer.
(yasm_bytecode_callback): Make destroy() and print() take void *contents
instead of bytecode pointer.
(yasm_bc_create_common): Take a pointer to contents instead of datasize.
(yasm_bc_transform): New; transforms a bytecode of any type into a
different type.
* bytecode.c (bytecode_data, bytecode_reserve, bytecode_incbin)
(bytecode_align): Remove bc base structure.
(bc_data_destroy, bc_data_print): Update to match yasm_bytecode_callback.
(bc_reserve_destroy, bc_reserve_print): Likewise.
(bc_incbin_destroy, bc_incbin_print): Likewise.
(bc_align_destroy, bc_align_print): Likewise.
(yasm_bc_create_common): Take a pointer to contents instead of datasize.
(bc_data_resolve, bc_data_tobytes, yasm_bc_create_data): Update to use
contents pointer.
(bc_reserve_resolve, bc_reserve_tobytes, yasm_bc_create_reserve): Likewise.
(bc_incbin_resolve, bc_incbin_tobytes, yasm_bc_create_incbin): Likewise.
(yasm_bc_create_align): Likewise.
(yasm_bc_destroy, yasm_bc_print): Update to match yasm_bytecode_callback.

* section.c (yasm_object_get_general, yasm_object_create_absolute): Pass
a NULL pointer instead of yasm_bytecode size to yasm_bc_create_common().

* stabs-dbgfmt.c (stabs_bc_str, stabs_bc_stab): Remove.
(stabs_bc_str_destroy, stabs_bc_str_print): Update.
(stabs_bc_stab_destroy, stabs_bc_stab_print): Likewise.
(stabs_bc_str_callback, stabs_bc_stab_callback): Add common finalize().
(stabs_dbgfmt_append_bcstr): Update to use contents pointer.
(stabs_dbgfmt_append_stab, stabs_dbgfmt_generate): Likewise.
(stabs_bc_stab_tobytes, stabs_bc_str_tobytes): Likewise.

* lc3barch.h (lc3b_insn): Move here from lc3bbc.c.
(lc3b_new_insn_data, yasm_lc3b__bc_create_insn): Remove.
(yasm_lc3b__bc_transform_insn): New.
* lc3bbc.c (lc3b_insn): Remove (moved).
(lc3b_bc_insn_destroy, lc3b_bc_insn_print): Update.
(lc3b_bc_callback_insn): Add common finalize().
(lc3b_bc_insn_resolve, lc3b_insn_tobytes): Use contents pointer.
(yasm_lc3b__bc_create_insn): Remove.
(yasm_lc3b__bc_transform_insn): New.
* lc3bid.re (yasm_lc3b__parse_insn): Directly create lc3b_insn.

* x86arch.h (x86_insn, x86_jmp): Move here from x86bc.c
(x86_new_insn_data, x86_new_jmp_data): Remove.
(yasm_x86__bc_create_insn, yasm_x86__bc_create_jmp): Remove.
(yasm_x86__bc_transform_insn, yasm_x86__bc_transform_jmp): New.
* x86bc.c (x86_insn, x86_jmp): Remove (moved).
(x86_bc_insn_destroy, x86_bc_insn_print): Update.
(x86_bc_jmp_destroy, x86_bc_jmp_print): Likewise.
(x86_bc_callback_insn, x86_bc_callback_jmp): Add common finalize().
(x86_bc_insn_resolve, x86_insn_tobytes): Use contents pointer.
(x86_bc_jmp_resolve, x86_jmp_tobytes): Likewise.
(yasm_x86__bc_create_insn, yasm_x86__bc_create_jmp): Remove.
(yasm_x86__bc_transform_insn, yasm_x86__bc_transform_jmp): New.
* x86id.re (yasm_x86__parse_insn, x86_parse_jmp): Directly create bytecode
contents.

* bc-int.h (yasm_bytecode_callback): Add new finalize() that will finalize
a bytecode after the parse stage.
(yasm_bc_finalize_common): New; common version of bytecode callback
finalize function.
* bytecode.h (yasm_bc_finalize): New wrapper around callback finalize().
* bytecode.c (yasm_bc_finalize): Implementation.
(yasm_bc_finalize_common): Likewise.
(bc_data_callback, bc_data_reserve_callback, bc_incbin_callback)
(bc_align_callback): Add yasm_bc_finalize_common() as finalize() function.

* section.h (yasm_object_finalize): New; finalizes an entire object.
* section.c (yasm_object_finalize): Implementation.

* yasm.c (main): Call yasm_object_finalize() after parse.

* bc-int.h (yasm_effaddr): Add segreg.
* bytecode.h (yasm_ea_set_segreg): New function to set segreg.
* bytecode.c (yasm_ea_set_segreg): Implement.

* x86bc.c (yasm_x86__ea_create_reg, x86_ea_print, x86_bc_insn_resolve)
(x86_bc_insn_tobytes): Use new EA segreg location.

* coretype.h: Move yasm_insn_operands definition from arch.h to here, as it
is now used in prototypes in bytecode.h.

* bytecode.c (bytecode_insn): New instruction bytecode.
(bc_insn_destroy, bc_insn_print, bc_insn_finalize, bc_insn_resolve)
(bc_insn_tobytes): New callback support functions.
(bc_insn_callback): New.
(yasm_bc_create_insn, yasm_bc_insn_add_prefix, yasm_bc_insn_add_seg_prefix):
New parser-callable functions.
* bytecode.h (yasm_bc_create_insn, yasm_bc_insn_add_prefix)
(yasm_bc_insn_add_seg_prefix): Likewise.

* nasm-bison.y: Call new insn bytecode functions rather than arch functions.

* arch.h (YASM_ARCH_VERSION): Bump version.
(yasm_arch): Rename and extend parse_insn to finalize_insn.  Remove
parse_prefix, parse_seg_prefix, and parse_seg_override.
(yasm_arch_parse_insn): Rename to yasm_arch_finalize_insn.
(yasm_arch_parse_prefix, yasm_arch_parse_seg_prefix)
(yasm_arch_parse_seg_override): Remove.

* lc3barch.c (yasm_lc3b_LTX_arch): Update to match new yasm_arch.
* lc3barch.h (yasm_lc3b__parse_insn): Rename to yasm_lc3b__finalize_insn.
* lc3bid.re (yasm_lc3b__parse_insn): Likewise.

* x86arch.c (x86_parse_prefix, x86_parse_seg_prefix)
(x86_parse_seg_override): Remove.
(yasm_x86_LTX_arch): Update to match new yasm_arch.
* x86arch.h (yasm_x86__parse_insn): Rename to yasm_x86__finalize_insn.
* x86id.re (yasm_x86__parse_insn): Likewise.
(x86_new_jmp): Rename to x86_finalize_jmp.

* x86arch.h (yasm_x86__bc_apply_prefixes, yasm_x86__ea_init): New.
* x86bc.c (yasm_x86__bc_apply_prefixes, yasm_x86__ea_init): Likewise.

svn path=/trunk/yasm/; revision=1177

18 files changed:
frontends/yasm/yasm.c
libyasm/arch.h
libyasm/bc-int.h
libyasm/bytecode.c
libyasm/bytecode.h
libyasm/coretype.h
libyasm/section.c
libyasm/section.h
modules/arch/lc3b/lc3barch.c
modules/arch/lc3b/lc3barch.h
modules/arch/lc3b/lc3bbc.c
modules/arch/lc3b/lc3bid.re
modules/arch/x86/x86arch.c
modules/arch/x86/x86arch.h
modules/arch/x86/x86bc.c
modules/arch/x86/x86id.re
modules/dbgfmts/stabs/stabs-dbgfmt.c
modules/parsers/nasm/nasm-bison.y

index decbdfbf3bbc4acc6911b34d0d5a4c71a9f6ca20..5a9cc7558a7abfc1ecab5d930bc57e15013e643d 100644 (file)
@@ -616,6 +616,9 @@ main(int argc, char *argv[])
     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);
index 79a2313903ae89480d00dafabb056038d263b987..896d4e54a8c79e195c3ca78e2ca549dfe1005d91 100644 (file)
@@ -46,10 +46,6 @@ typedef enum {
 
 /** 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
@@ -104,7 +100,7 @@ typedef struct yasm_arch_machine {
  * 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
@@ -174,31 +170,15 @@ typedef struct yasm_arch_module {
                            /*@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.
@@ -384,54 +364,28 @@ int yasm_arch_parse_directive(yasm_arch *arch, const char *name,
                              /*@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
@@ -545,17 +499,12 @@ yasm_effaddr *yasm_arch_ea_create(yasm_arch *arch, /*@keep@*/ yasm_expr *e);
                                  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 \
index 8ea33b1097f8dd1af7c8dd2fa436e51cf205b9f8..251e53d0843747854694556241600313715ecb8d 100644 (file)
@@ -36,6 +36,7 @@ struct yasm_effaddr {
     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.
                                 */
@@ -51,8 +52,9 @@ struct yasm_immval {
 };
 
 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,
@@ -86,18 +88,35 @@ struct yasm_bytecode {
     /* 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)
 
index d7880cefd33377c61061728fa87c386b5d67e9bf..b4b331dcc61e56779907d1d930a839810c6b71d8 100644 (file)
@@ -36,6 +36,7 @@
 #include "expr.h"
 
 #include "bytecode.h"
+#include "arch.h"
 #include "objfmt.h"
 #include "dbgfmt.h"
 
@@ -57,8 +58,6 @@ struct yasm_dataval {
 /* Standard bytecode types */
 
 typedef struct bytecode_data {
-    yasm_bytecode bc;  /* base structure */
-
     /* non-converted data (linked list) */
     yasm_datavalhead datahead;
 
@@ -67,15 +66,11 @@ typedef struct bytecode_data {
 } 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) */
@@ -86,52 +81,74 @@ typedef struct bytecode_incbin {
 } 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
 };
@@ -139,6 +156,7 @@ static const yasm_bytecode_callback bc_data_callback = {
 static const yasm_bytecode_callback bc_reserve_callback = {
     bc_reserve_destroy,
     bc_reserve_print,
+    yasm_bc_finalize_common,
     bc_reserve_resolve,
     bc_reserve_tobytes
 };
@@ -146,6 +164,7 @@ static const yasm_bytecode_callback bc_reserve_callback = {
 static const yasm_bytecode_callback bc_incbin_callback = {
     bc_incbin_destroy,
     bc_incbin_print,
+    yasm_bc_finalize_common,
     bc_incbin_resolve,
     bc_incbin_tobytes
 };
@@ -153,10 +172,19 @@ static const yasm_bytecode_callback bc_incbin_callback = {
 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];
@@ -210,6 +238,19 @@ yasm_ea_set_nosplit(yasm_effaddr *ptr, unsigned int nosplit)
     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)
@@ -242,11 +283,26 @@ yasm_bc_set_multiple(yasm_bytecode *bc, yasm_expr *e)
        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;
 
@@ -263,20 +319,23 @@ yasm_bc_create_common(const yasm_bytecode_callback *callback, size_t size,
 
     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);
@@ -288,7 +347,7 @@ 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;
+    bytecode_data *bc_data = (bytecode_data *)bc->contents;
     yasm_dataval *dv;
     size_t slen;
 
@@ -317,7 +376,7 @@ bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
                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;
@@ -356,28 +415,26 @@ yasm_bytecode *
 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);
@@ -389,7 +446,7 @@ 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;
+    bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
     yasm_bc_resolve_flags retval = YASM_BC_RESOLVE_MIN_LEN;
     /*@null@*/ yasm_expr *temp;
     yasm_expr **tempp;
@@ -435,33 +492,30 @@ yasm_bytecode *
 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);
@@ -482,7 +536,7 @@ 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;
+    bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
     FILE *f;
     /*@null@*/ yasm_expr *temp;
     yasm_expr **tempp;
@@ -564,7 +618,7 @@ bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
                  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;
@@ -612,11 +666,7 @@ yasm_bytecode *
 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;
@@ -624,18 +674,19 @@ yasm_bc_create_incbin(char *filename, yasm_expr *start, yasm_expr *maxlen,
     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);
 }
@@ -662,15 +713,119 @@ bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
 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 *
@@ -707,7 +862,7 @@ yasm_bc_destroy(yasm_bytecode *bc)
        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);
@@ -719,7 +874,7 @@ yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level)
     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)");
@@ -730,6 +885,13 @@ yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level)
     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)
index c4514811daec0380562a5cbcfbbebcaf280c5263..542d06694831d1e1f34730489ee983a75970b99a 100644 (file)
@@ -92,6 +92,15 @@ void yasm_ea_set_len(yasm_effaddr *ea, unsigned int len);
  */
 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).
  */
@@ -152,6 +161,33 @@ void yasm_bc_set_multiple(yasm_bytecode *bc, /*@keep@*/ yasm_expr *e);
 /*@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
@@ -181,6 +217,12 @@ void yasm_bc_destroy(/*@only@*/ /*@null@*/ yasm_bytecode *bc);
  */
 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.
index 83fd0b70376a54f539219ccbea7f2c81589fd7f7..ccc89d809fc8cde0e8cf25791cef9ddfd0578fcb 100644 (file)
@@ -110,6 +110,12 @@ typedef struct yasm_valparam yasm_valparam;
  */
 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. */
index 6e297adddca98c11bae135668a37a3dd0fce2d59..6ebbaffe25a3e8cbe38704d8c606700d96443597 100644 (file)
@@ -145,7 +145,7 @@ yasm_object_get_general(yasm_object *object, const char *name,
      * 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);
 
@@ -179,7 +179,7 @@ yasm_object_create_absolute(yasm_object *object, yasm_expr *start,
      * 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);
 
@@ -279,6 +279,30 @@ yasm_object_print(const yasm_object *object, FILE *f, int indent_level)
     }
 }
 
+void
+yasm_object_finalize(yasm_object *object)
+{
+    yasm_section *sect;
+
+    /* Iterate through sections */
+    STAILQ_FOREACH(sect, &object->sections, link) {
+       yasm_bytecode *cur = STAILQ_FIRST(&sect->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,
index 7a38e6995334cffa82d97bc2d6e438526095fac4..1ad9f2f96caf7cd91d280eabe2040db48734f70d 100644 (file)
@@ -95,6 +95,11 @@ void yasm_object_destroy(/*@only@*/ yasm_object *object);
  */
 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
index 4a6b10b53c008bef345e7cf1154b0bab25170701..64a5b38dad1bcce9862defd23d89232e6820c270 100644 (file)
@@ -125,10 +125,7 @@ yasm_arch_module yasm_lc3b_LTX_arch = {
     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,
index 4b8c860e392a390fce34295761291cbf13f38f1f..1dbaa16337ad0ed09d036f96f17814938069c1f3 100644 (file)
@@ -39,19 +39,18 @@ typedef enum lc3b_imm_type {
     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);
@@ -60,10 +59,11 @@ yasm_arch_check_id_retval yasm_lc3b__parse_check_id
     (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,
index 87fdf27945666b693a95bb15bf2b0ee79e38ba14..6f189d402164e3d748371bcb671f8f2424fd42e0 100644 (file)
 #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);
@@ -63,44 +50,31 @@ static int lc3b_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp,
 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, "");
@@ -153,7 +127,7 @@ static yasm_bc_resolve_flags
 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;
@@ -192,7 +166,7 @@ lc3b_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
                     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);
index 6b610484e2f71e4ae3baf13c7925560adc1ace9d..552ab8f5df726d981a9f82fd5e6eae9b64160904 100644 (file)
@@ -172,12 +172,15 @@ static const lc3b_insn_info trap_insn[] = {
     { 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;
@@ -229,24 +232,25 @@ yasm_lc3b__parse_insn(yasm_arch *arch, const unsigned long data[4],
 
     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;*/
     }
 
@@ -263,22 +267,22 @@ yasm_lc3b__parse_insn(yasm_arch *arch, const unsigned long data[4],
                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"));
@@ -288,14 +292,18 @@ yasm_lc3b__parse_insn(yasm_arch *arch, const unsigned long data[4],
                    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);
 }
 
 
index ca66258439f70163cb6287cdb4d72307355e66a7..54b60db7f73a5e1e585390ee4e6f1a231a58d92d 100644 (file)
@@ -207,38 +207,6 @@ x86_segreg_print(yasm_arch *arch, unsigned long segreg, FILE *f)
     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" },
@@ -258,10 +226,7 @@ yasm_arch_module yasm_x86_LTX_arch = {
     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,
index c7fb9df48748d3cdca6883a1860dc3d65608c8ab..e2a1ce83a0df72eb79b5e169ce0e77429adf2382 100644 (file)
@@ -126,8 +126,6 @@ int yasm_x86__set_rex_from_reg(unsigned char *rex, unsigned char *low3,
                               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);
@@ -147,50 +145,86 @@ void yasm_x86__bc_insn_set_lockrep_prefix(yasm_bytecode *bc,
                                          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.
@@ -206,13 +240,14 @@ void yasm_x86__parse_cpu(yasm_arch *arch, const char *cpuid,
                         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,
index a959d2616a50239b9902742760dfc68446478d4b..bf56b1b0890bd968d2f359e2836799a9ea79194c 100644 (file)
@@ -43,8 +43,6 @@ typedef struct x86_effaddr {
     /* 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().
@@ -61,81 +59,6 @@ typedef struct x86_effaddr {
     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);
@@ -143,8 +66,8 @@ static void x86_ea_print(const yasm_effaddr *ea, FILE *f, int indent_level);
 
 /* 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);
@@ -152,9 +75,8 @@ static int x86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp,
                               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,
@@ -173,6 +95,7 @@ static const yasm_effaddr_callback x86_ea_callback = {
 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
 };
@@ -180,6 +103,7 @@ static const yasm_bytecode_callback x86_bc_callback_insn = {
 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
 };
@@ -209,111 +133,25 @@ yasm_x86__set_rex_from_reg(unsigned char *rex, unsigned char *low3,
     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
@@ -344,7 +182,7 @@ yasm_x86__ea_create_reg(unsigned long reg, unsigned char *rex,
     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;
@@ -367,7 +205,7 @@ yasm_x86__ea_create_expr(yasm_arch *arch, yasm_expr *e)
     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;
@@ -394,7 +232,7 @@ yasm_x86__ea_create_imm(yasm_expr *imm, unsigned int im_len)
     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;
@@ -407,92 +245,69 @@ yasm_x86__ea_create_imm(yasm_expr *imm, unsigned int im_len)
 }
 /*@=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
@@ -505,7 +320,7 @@ x86_ea_print(const yasm_effaddr *ea, FILE *f, int indent_level)
 {
     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);
@@ -515,9 +330,9 @@ x86_ea_print(const yasm_effaddr *ea, FILE *f, int indent_level)
 }
 
 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, "");
@@ -561,9 +376,9 @@ x86_bc_insn_print(const yasm_bytecode *bc, FILE *f, int 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, "");
@@ -637,9 +452,9 @@ static yasm_bc_resolve_flags
 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;
@@ -714,7 +529,7 @@ x86_bc_insn_resolve(yasm_bytecode *bc, int save,
 
        /* 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) {
@@ -779,7 +594,7 @@ static yasm_bc_resolve_flags
 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;
@@ -953,8 +768,8 @@ x86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
                    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;
@@ -965,8 +780,8 @@ x86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
        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)))
@@ -1076,7 +891,7 @@ x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
                   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;
index b02702e4494fa92e0c8abbba7e48f16cdcb7d8c0..688bec90144747c65713a9a4511a4d96429c7113 100644 (file)
@@ -259,6 +259,7 @@ typedef struct x86_insn_info {
     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 { \
@@ -1701,20 +1702,25 @@ static const x86_insn_info xbts_insn[] = {
 };
 
 
-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);
@@ -1724,64 +1730,65 @@ x86_new_jmp(yasm_arch *arch, const unsigned long data[4], int num_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);
 
@@ -1794,48 +1801,67 @@ x86_new_jmp(yasm_arch *arch, const unsigned long data[4], int num_operands,
        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};
 
@@ -1850,9 +1876,9 @@ yasm_x86__parse_insn(yasm_arch *arch, const unsigned long data[4],
        /* 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);
 
@@ -2100,8 +2126,9 @@ yasm_x86__parse_insn(yasm_arch *arch, const unsigned long data[4],
 
     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 */
@@ -2113,15 +2140,15 @@ yasm_x86__parse_insn(yasm_arch *arch, const unsigned long data[4],
            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)) {
@@ -2134,69 +2161,74 @@ yasm_x86__parse_insn(yasm_arch *arch, const unsigned long data[4],
     }
 
     /* 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;*/
     }
 
@@ -2222,25 +2254,27 @@ yasm_x86__parse_insn(yasm_arch *arch, const unsigned long data[4],
                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;
@@ -2248,31 +2282,30 @@ yasm_x86__parse_insn(yasm_arch *arch, const unsigned long data[4],
                    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"));
@@ -2280,44 +2313,43 @@ yasm_x86__parse_insn(yasm_arch *arch, const unsigned long data[4],
                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"));
@@ -2330,13 +2362,13 @@ yasm_x86__parse_insn(yasm_arch *arch, const unsigned long data[4],
                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(
@@ -2345,8 +2377,19 @@ yasm_x86__parse_insn(yasm_arch *arch, const unsigned long data[4],
        }
     }
 
-    /* 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);
 }
 
 
index 9cdead875da042b66bf866f62703df481560005a..861fac0601faeb6101303f3d2f1e52d59c453ea3 100644 (file)
@@ -117,22 +117,10 @@ typedef struct {
     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);
@@ -141,8 +129,8 @@ static int stabs_bc_str_tobytes
      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);
@@ -156,6 +144,7 @@ static int stabs_bc_stab_tobytes
 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
 };
@@ -163,6 +152,7 @@ static const yasm_bytecode_callback stabs_bc_str_callback = {
 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
 };
@@ -197,15 +187,9 @@ static yasm_bytecode *
 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;
 
@@ -224,7 +208,6 @@ stabs_dbgfmt_append_stab(stabs_info *info, yasm_section *sect,
                         /*@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;
@@ -236,12 +219,8 @@ stabs_dbgfmt_append_stab(stabs_info *info, yasm_section *sect,
     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;
 
@@ -342,7 +321,6 @@ stabs_dbgfmt_generate(yasm_dbgfmt *dbgfmt)
     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;
@@ -386,13 +364,8 @@ stabs_dbgfmt_generate(yasm_dbgfmt *dbgfmt)
 
     /* 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 */
@@ -432,9 +405,8 @@ stabs_bc_stab_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
      * 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);
@@ -463,9 +435,8 @@ stabs_bc_str_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
                     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;
@@ -475,24 +446,21 @@ stabs_bc_str_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
 }
 
 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,
@@ -500,10 +468,9 @@ stabs_bc_stab_print(const yasm_bytecode *bc, FILE *f, int indent_level)
 }
 
 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
index aa23cda2251eb9383945f043f7dae72db0bb8540..adf6c943cf512620e4347dfc837ff82ac76ec173 100644 (file)
@@ -214,14 +214,11 @@ exp: instr
 ;
 
 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"));
@@ -229,11 +226,11 @@ instr: INSN               {
     }
     | 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]);
     }
 ;
 
@@ -325,7 +322,7 @@ memaddr: expr                   {
     }
     | 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); }