directive for GAS (it's generated by GCC).
* bytecode.c (bytecode_align): Update for full align implementation.
(yasm_bc_create_align): Likewise.
(bc_align_finalize): New.
(bc_align_resolve, bc_align_tobytes): Real implementation.
* bytecode.h (yasm_bc_create_align): Update to match.
* arch.h (get_fill, yasm_arch_get_fill): New, to get NOP fill patterns.
* x86arch.c (x86_get_fill): Implement.
* lc3barch.c (lc3b_get_fill): Likewise (probably buggy, there's no real NOP).
* bytecode.c (bytecode_org): New org bytecode.
(bc_org_callback, bc_org_destroy, bc_org_print, bc_org_resolve)
(bc_org_tobytes, yasm_bc_create_org): Implement.
* gas-parser.h (yasm_parser_gas): Add code_section flag to indicate when to
use code fill vs. data fill.
* gas-parser.c: Initialize flag.
* gas-bison.y: Update flag in various places. Generate org bytecode.
Call gas_parser_align to generate align bytecode.
(gas_parser_align): Generate align bytecode.
* gas-bison.y: Implement .zero directive.
* gas-token.re: Likewise.
* align32, align64: New tests to test align directive NOP generation.
svn path=/trunk/yasm/; revision=1263
/*@null@*/ yasm_valparamhead *objext_valparams,
yasm_object *object, unsigned long line);
+ /** Module-level implementation of yasm_arch_get_fill().
+ * Call yasm_arch_get_fill() instead of calling this function.
+ */
+ const unsigned char ** (*get_fill) (const yasm_arch *arch);
+
/** Module-level implementation of yasm_arch_finalize_insn().
* Call yasm_arch_finalize_insn() instead of calling this function.
*/
/*@null@*/ yasm_valparamhead *objext_valparams,
yasm_object *object, unsigned long line);
+/** Get NOP fill patterns for 1-15 bytes of fill.
+ * \param arch architecture
+ * \return 16-entry array of arrays; [0] is unused, [1] - [15] point to arrays
+ * of 1-15 bytes (respectively) in length.
+ */
+const unsigned char **yasm_arch_get_fill(const yasm_arch *arch);
+
/** Finalize an instruction from a semi-generic insn description. Note an
* existing bytecode is required.
* \param arch architecture
object, line) \
((yasm_arch_base *)arch)->module->parse_directive \
(arch, name, valparams, objext_valparams, object, line)
+#define yasm_arch_get_fill(arch) \
+ ((yasm_arch_base *)arch)->module->get_fill(arch)
#define yasm_arch_finalize_insn(arch, bc, prev_bc, data, num_operands, \
operands, num_prefixes, prefixes, \
num_segregs, segregs) \
} bytecode_incbin;
typedef struct bytecode_align {
- unsigned long boundary; /* alignment boundary */
+ /*@only@*/ yasm_expr *boundary; /* alignment boundary */
+
+ /* What to fill intervening locations with, NULL if using code_fill */
+ /*@only@*/ /*@null@*/ yasm_expr *fill;
+
+ /* Maximum number of bytes to skip, NULL if no maximum. */
+ /*@only@*/ /*@null@*/ yasm_expr *maxskip;
+
+ /* Code fill, NULL if using 0 fill */
+ /*@null@*/ const unsigned char **code_fill;
} bytecode_align;
+typedef struct bytecode_org {
+ unsigned long start; /* target starting offset within section */
+} bytecode_org;
+
typedef struct bytecode_insn {
/*@dependent@*/ yasm_arch *arch;
unsigned long insn_data[4];
static void bc_align_destroy(void *contents);
static void bc_align_print(const void *contents, FILE *f, int indent_level);
+static void bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
static yasm_bc_resolve_flags bc_align_resolve
(yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
static int bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
yasm_output_expr_func output_expr,
/*@null@*/ yasm_output_reloc_func output_reloc);
+static void bc_org_destroy(void *contents);
+static void bc_org_print(const void *contents, FILE *f, int indent_level);
+static yasm_bc_resolve_flags bc_org_resolve
+ (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
+static int bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_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 const yasm_bytecode_callback bc_align_callback = {
bc_align_destroy,
bc_align_print,
- yasm_bc_finalize_common,
+ bc_align_finalize,
bc_align_resolve,
bc_align_tobytes
};
+static const yasm_bytecode_callback bc_org_callback = {
+ bc_org_destroy,
+ bc_org_print,
+ yasm_bc_finalize_common,
+ bc_org_resolve,
+ bc_org_tobytes
+};
+
static const yasm_bytecode_callback bc_insn_callback = {
bc_insn_destroy,
bc_insn_print,
static void
bc_align_destroy(void *contents)
{
+ bytecode_align *align = (bytecode_align *)contents;
+ if (align->fill)
+ yasm_expr_destroy(align->fill);
yasm_xfree(contents);
}
{
const bytecode_align *align = (const bytecode_align *)contents;
fprintf(f, "%*s_Align_\n", indent_level, "");
- fprintf(f, "%*sBoundary=%lu\n", indent_level, "", align->boundary);
+ fprintf(f, "%*sBoundary=", indent_level, "");
+ yasm_expr_print(align->boundary, f);
+ fprintf(f, "\n%*sFill=", indent_level, "");
+ yasm_expr_print(align->fill, f);
+ fprintf(f, "\n%*sMax Skip=", indent_level, "");
+ yasm_expr_print(align->maxskip, f);
+ fprintf(f, "\n");
+}
+
+static void
+bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ bytecode_align *align = (bytecode_align *)bc->contents;
+ if (!yasm_expr_get_intnum(&align->boundary, NULL))
+ yasm__error(bc->line, N_("align boundary must be a constant"));
+ if (align->fill && !yasm_expr_get_intnum(&align->fill, NULL))
+ yasm__error(bc->line, N_("align fill must be a constant"));
+ if (align->maxskip && !yasm_expr_get_intnum(&align->maxskip, NULL))
+ yasm__error(bc->line, N_("align maximum skip must be a constant"));
}
static yasm_bc_resolve_flags
bc_align_resolve(yasm_bytecode *bc, int save,
yasm_calc_bc_dist_func calc_bc_dist)
{
- yasm_internal_error(N_("TODO: align bytecode not implemented!"));
- /*@notreached@*/
- return YASM_BC_RESOLVE_ERROR;
+ bytecode_align *align = (bytecode_align *)bc->contents;
+ unsigned long end;
+ unsigned long boundary =
+ yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, NULL));
+
+ if (boundary == 0) {
+ bc->len = 0;
+ return YASM_BC_RESOLVE_MIN_LEN;
+ }
+
+ end = bc->offset;
+ if (bc->offset & (boundary-1))
+ end = (bc->offset & ~(boundary-1)) + boundary;
+
+ bc->len = end - bc->offset;
+
+ if (align->maxskip) {
+ unsigned long maxskip =
+ yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, NULL));
+ if ((end - bc->offset) > maxskip)
+ bc->len = 0;
+ }
+ return YASM_BC_RESOLVE_MIN_LEN;
}
static int
yasm_output_expr_func output_expr,
/*@unused@*/ yasm_output_reloc_func output_reloc)
{
- yasm_internal_error(N_("TODO: align bytecode not implemented!"));
- /*@notreached@*/
- return 1;
+ bytecode_align *align = (bytecode_align *)bc->contents;
+ unsigned long len, i;
+ unsigned long boundary =
+ yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, NULL));
+
+ if (boundary == 0)
+ return 0;
+ else {
+ unsigned long end = bc->offset;
+ if (bc->offset & (boundary-1))
+ end = (bc->offset & ~(boundary-1)) + boundary;
+ len = end - bc->offset;
+ if (len == 0)
+ return 0;
+ if (align->maxskip) {
+ unsigned long maxskip =
+ yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip,
+ NULL));
+ if (len > maxskip)
+ return 0;
+ }
+ }
+
+ if (align->fill) {
+ unsigned long v;
+ v = yasm_intnum_get_uint(yasm_expr_get_intnum(&align->fill, NULL));
+ memset(*bufp, (int)v, len);
+ *bufp += len;
+ } else if (align->code_fill) {
+ while (len > 15) {
+ memcpy(*bufp, align->code_fill[15], 15);
+ *bufp += 15;
+ len -= 15;
+ }
+ memcpy(*bufp, align->code_fill[len], len);
+ *bufp += len;
+ } else {
+ /* Just fill with 0 */
+ memset(*bufp, 0, len);
+ *bufp += len;
+ }
+ return 0;
}
yasm_bytecode *
-yasm_bc_create_align(unsigned long boundary, unsigned long line)
+yasm_bc_create_align(yasm_expr *boundary, yasm_expr *fill,
+ yasm_expr *maxskip, const unsigned char **code_fill,
+ unsigned long line)
{
bytecode_align *align = yasm_xmalloc(sizeof(bytecode_align));
align->boundary = boundary;
+ align->fill = fill;
+ align->maxskip = maxskip;
+ align->code_fill = code_fill;
return yasm_bc_create_common(&bc_align_callback, align, line);
}
+static void
+bc_org_destroy(void *contents)
+{
+ yasm_xfree(contents);
+}
+
+static void
+bc_org_print(const void *contents, FILE *f, int indent_level)
+{
+ const bytecode_org *org = (const bytecode_org *)contents;
+ fprintf(f, "%*s_Org_\n", indent_level, "");
+ fprintf(f, "%*sStart=%lu\n", indent_level, "", org->start);
+}
+
+static yasm_bc_resolve_flags
+bc_org_resolve(yasm_bytecode *bc, int save,
+ yasm_calc_bc_dist_func calc_bc_dist)
+{
+ bytecode_org *org = (bytecode_org *)bc->contents;
+
+ /* Check for overrun */
+ if (bc->offset > org->start) {
+ yasm__error(bc->line, N_("ORG overlap with already existing data"));
+ return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
+ }
+
+ /* Generate space to start offset */
+ bc->len = org->start - bc->offset;
+ return YASM_BC_RESOLVE_MIN_LEN;
+}
+
+static int
+bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_expr_func output_expr,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ bytecode_org *org = (bytecode_org *)bc->contents;
+ unsigned long len, i;
+
+ /* Sanity check for overrun */
+ if (bc->offset > org->start) {
+ yasm__error(bc->line, N_("ORG overlap with already existing data"));
+ return 1;
+ }
+ len = org->start - bc->offset;
+ for (i=0; i<len; i++)
+ YASM_WRITE_8(*bufp, 0);
+ return 0;
+}
+
+yasm_bytecode *
+yasm_bc_create_org(unsigned long start, unsigned long line)
+{
+ bytecode_org *org = yasm_xmalloc(sizeof(bytecode_org));
+
+ org->start = start;
+
+ return yasm_bc_create_common(&bc_org_callback, org, line);
+}
+
static void
bc_insn_destroy(void *contents)
{
/** Create a bytecode that aligns the following bytecode to a boundary.
* \param boundary byte alignment (must be a power of two)
+ * \param fill fill data (if NULL, code_fill or 0 is used)
+ * \param maxskip maximum number of bytes to skip
+ * \param code_fill code fill data (if NULL, 0 is used)
* \param line virtual line (from yasm_linemap)
* \return Newly allocated bytecode.
+ * \note The precedence on generated fill is as follows:
+ * - from fill parameter (if not NULL)
+ * - from code_fill parameter (if not NULL)
+ * - 0
*/
/*@only@*/ yasm_bytecode *yasm_bc_create_align
- (unsigned long boundary, unsigned long line);
+ (/*@keep@*/ yasm_expr *boundary, /*@keep@*/ /*@null@*/ yasm_expr *fill,
+ /*@keep@*/ /*@null@*/ yasm_expr *maxskip,
+ /*@null@*/ const unsigned char **code_fill, unsigned long line);
+
+/** Create a bytecode that puts the following bytecode at a fixed section
+ * offset.
+ * \param start section offset of following bytecode
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode.
+ */
+/*@only@*/ yasm_bytecode *yasm_bc_create_org
+ (unsigned long start, unsigned long line);
/** Create a bytecode that represents a single instruction.
* \param arch instruction's architecture
return 1;
}
+static const unsigned char **
+lc3b_get_fill(const yasm_arch *arch)
+{
+ /* NOP pattern is AND r0, r0, r0 repeated */
+ static const char *fill[16] = {
+ NULL, /* unused */
+ NULL, /* 1 - illegal; all opcodes are 2 bytes long */
+ "\x50\x00", /* 4 */
+ NULL, /* 3 - illegal */
+ "\x50\x00\x50\x00", /* 4 */
+ NULL, /* 5 - illegal */
+ "\x50\x00\x50\x00\x50\x00", /* 6 */
+ NULL, /* 7 - illegal */
+ "\x50\x00\x50\x00\x50\x00" /* 8 */
+ "\x50\x00",
+ NULL, /* 9 - illegal */
+ "\x50\x00\x50\x00\x50\x00" /* 10 */
+ "\x50\x00\x50\x00",
+ NULL, /* 11 - illegal */
+ "\x50\x00\x50\x00\x50\x00" /* 12 */
+ "\x50\x00\x50\x00\x50\x00",
+ NULL, /* 13 - illegal */
+ "\x50\x00\x50\x00\x50\x00" /* 14 */
+ "\x50\x00\x50\x00\x50\x00\x50\x00",
+ NULL /* 15 - illegal */
+ };
+ return (const unsigned char **)fill;
+}
+
static unsigned int
lc3b_get_reg_size(/*@unused@*/ yasm_arch *arch, /*@unused@*/ unsigned long reg)
{
yasm_lc3b__parse_check_prefix,
yasm_lc3b__parse_check_targetmod,
lc3b_parse_directive,
+ lc3b_get_fill,
yasm_lc3b__finalize_insn,
lc3b_floatnum_tobytes,
yasm_lc3b__intnum_fixup_rel,
TESTS += modules/arch/x86/tests/gas32/x86_gas32_test.sh
EXTRA_DIST += modules/arch/x86/tests/gas32/x86_gas32_test.sh
+EXTRA_DIST += modules/arch/x86/tests/gas32/align32.asm
+EXTRA_DIST += modules/arch/x86/tests/gas32/align32.errwarn
+EXTRA_DIST += modules/arch/x86/tests/gas32/align32.hex
EXTRA_DIST += modules/arch/x86/tests/gas32/gas-movdq32.asm
EXTRA_DIST += modules/arch/x86/tests/gas32/gas-movdq32.errwarn
EXTRA_DIST += modules/arch/x86/tests/gas32/gas-movdq32.hex
--- /dev/null
+.text
+# 15 fill
+.byte 0xff
+.p2align 4
+# 14 fill
+.byte 0xff
+.byte 0xff
+.p2align 4
+# 13 fill
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.p2align 4
+# 12 fill
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.p2align 4
+# 11 fill
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.p2align 4
+# 10 fill
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.p2align 4
+# 9 fill
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.p2align 4
+# 8 fill
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.p2align 4
+# 7 fill
+.byte 0xff
+.p2align 3
+# 6 fill
+.byte 0xff
+.byte 0xff
+.p2align 3
+# 5 fill
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.p2align 3
+# 4 fill
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.p2align 3
+# 3 fill
+.byte 0xff
+.p2align 2
+# 2 fill
+.byte 0xff
+.byte 0xff
+.p2align 2
+# 1 fill
+.byte 0xff
+.p2align 1
+
--- /dev/null
+7f
+45
+4c
+46
+01
+01
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+01
+00
+03
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+50
+01
+00
+00
+00
+00
+00
+00
+34
+00
+00
+00
+00
+00
+28
+00
+05
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ff
+eb
+0d
+90
+90
+90
+90
+90
+90
+90
+90
+90
+90
+90
+90
+90
+ff
+ff
+8d
+b4
+26
+00
+00
+00
+00
+8d
+bc
+27
+00
+00
+00
+00
+ff
+ff
+ff
+8d
+b6
+00
+00
+00
+00
+8d
+bc
+27
+00
+00
+00
+00
+ff
+ff
+ff
+ff
+8d
+b6
+00
+00
+00
+00
+8d
+bf
+00
+00
+00
+00
+ff
+ff
+ff
+ff
+ff
+8d
+74
+26
+00
+8d
+bc
+27
+00
+00
+00
+00
+ff
+ff
+ff
+ff
+ff
+ff
+8d
+76
+00
+8d
+bc
+27
+00
+00
+00
+00
+ff
+ff
+ff
+ff
+ff
+ff
+ff
+89
+f6
+8d
+bc
+27
+00
+00
+00
+00
+ff
+ff
+ff
+ff
+ff
+ff
+ff
+ff
+90
+8d
+b4
+26
+00
+00
+00
+00
+ff
+8d
+b4
+26
+00
+00
+00
+00
+ff
+ff
+8d
+b6
+00
+00
+00
+00
+ff
+ff
+ff
+90
+8d
+74
+26
+00
+ff
+ff
+ff
+ff
+8d
+74
+26
+00
+ff
+8d
+76
+00
+ff
+ff
+89
+f6
+ff
+90
+00
+00
+00
+2e
+74
+65
+78
+74
+00
+2e
+73
+74
+72
+74
+61
+62
+00
+2e
+73
+79
+6d
+74
+61
+62
+00
+2e
+73
+68
+73
+74
+72
+74
+61
+62
+00
+00
+00
+00
+00
+2d
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+04
+00
+f1
+ff
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+03
+00
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+17
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ec
+00
+00
+00
+21
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+07
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+01
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+0f
+00
+00
+00
+02
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+14
+01
+00
+00
+30
+00
+00
+00
+02
+00
+00
+00
+03
+00
+00
+00
+04
+00
+00
+00
+10
+00
+00
+00
+01
+00
+00
+00
+01
+00
+00
+00
+06
+00
+00
+00
+00
+00
+00
+00
+40
+00
+00
+00
+aa
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+00
+00
+00
+00
+00
+00
+00
TESTS += modules/arch/x86/tests/gas64/x86_gas64_test.sh
EXTRA_DIST += modules/arch/x86/tests/gas64/x86_gas64_test.sh
+EXTRA_DIST += modules/arch/x86/tests/gas64/align64.asm
+EXTRA_DIST += modules/arch/x86/tests/gas64/align64.errwarn
+EXTRA_DIST += modules/arch/x86/tests/gas64/align64.hex
EXTRA_DIST += modules/arch/x86/tests/gas64/gas-cbw.asm
EXTRA_DIST += modules/arch/x86/tests/gas64/gas-cbw.errwarn
EXTRA_DIST += modules/arch/x86/tests/gas64/gas-cbw.hex
--- /dev/null
+.text
+# 15 fill
+.byte 0xff
+.p2align 4
+# 14 fill
+.byte 0xff
+.byte 0xff
+.p2align 4
+# 13 fill
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.p2align 4
+# 12 fill
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.p2align 4
+# 11 fill
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.p2align 4
+# 10 fill
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.p2align 4
+# 9 fill
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.p2align 4
+# 8 fill
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.p2align 4
+# 7 fill
+.byte 0xff
+.p2align 3
+# 6 fill
+.byte 0xff
+.byte 0xff
+.p2align 3
+# 5 fill
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.p2align 3
+# 4 fill
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.byte 0xff
+.p2align 3
+# 3 fill
+.byte 0xff
+.p2align 2
+# 2 fill
+.byte 0xff
+.byte 0xff
+.p2align 2
+# 1 fill
+.byte 0xff
+.p2align 1
+
--- /dev/null
+7f
+45
+4c
+46
+02
+01
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+01
+00
+3e
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+60
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+40
+00
+00
+00
+00
+00
+40
+00
+05
+00
+01
+00
+ff
+66
+66
+66
+90
+66
+66
+66
+90
+66
+66
+66
+90
+66
+66
+90
+ff
+ff
+66
+66
+66
+90
+66
+66
+66
+90
+66
+66
+90
+66
+66
+90
+ff
+ff
+ff
+66
+66
+66
+90
+66
+66
+90
+66
+66
+90
+66
+66
+90
+ff
+ff
+ff
+ff
+66
+66
+66
+90
+66
+66
+66
+90
+66
+66
+66
+90
+ff
+ff
+ff
+ff
+ff
+66
+66
+66
+90
+66
+66
+66
+90
+66
+66
+90
+ff
+ff
+ff
+ff
+ff
+ff
+66
+66
+66
+90
+66
+66
+90
+66
+66
+90
+ff
+ff
+ff
+ff
+ff
+ff
+ff
+66
+66
+90
+66
+66
+90
+66
+66
+90
+ff
+ff
+ff
+ff
+ff
+ff
+ff
+ff
+66
+66
+66
+90
+66
+66
+66
+90
+ff
+66
+66
+66
+90
+66
+66
+90
+ff
+ff
+66
+66
+90
+66
+66
+90
+ff
+ff
+ff
+66
+66
+90
+66
+90
+ff
+ff
+ff
+ff
+66
+66
+66
+90
+ff
+66
+66
+90
+ff
+ff
+66
+90
+ff
+90
+00
+00
+00
+2e
+74
+65
+78
+74
+00
+2e
+73
+74
+72
+74
+61
+62
+00
+2e
+73
+79
+6d
+74
+61
+62
+00
+2e
+73
+68
+73
+74
+72
+74
+61
+62
+00
+00
+00
+00
+00
+2d
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+01
+00
+00
+00
+04
+00
+f1
+ff
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+03
+00
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+17
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ec
+00
+00
+00
+00
+00
+00
+00
+21
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+07
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+01
+00
+00
+00
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+0f
+00
+00
+00
+02
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+14
+01
+00
+00
+00
+00
+00
+00
+48
+00
+00
+00
+00
+00
+00
+00
+02
+00
+00
+00
+03
+00
+00
+00
+08
+00
+00
+00
+00
+00
+00
+00
+18
+00
+00
+00
+00
+00
+00
+00
+01
+00
+00
+00
+01
+00
+00
+00
+06
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+40
+00
+00
+00
+00
+00
+00
+00
+aa
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
return 1;
}
+static const unsigned char **
+x86_get_fill(const yasm_arch *arch)
+{
+ const yasm_arch_x86 *arch_x86 = (const yasm_arch_x86 *)arch;
+
+ /* Fill patterns that GAS uses. */
+ static const char *fill16[16] = {
+ NULL, /* unused */
+ "\x90", /* 1 - nop */
+ "\x89\xf6", /* 2 - mov si, si */
+ "\x8d\x74\x00", /* 3 - lea si, [si+byte 0] */
+ "\x8d\xb4\x00\x00", /* 4 - lea si, [si+word 0] */
+ "\x90" /* 5 - nop */
+ "\x8d\xb4\x00\x00", /* lea si, [si+word 0] */
+ "\x89\xf6" /* 6 - mov si, si */
+ "\x8d\xbd\x00\x00", /* lea di, [di+word 0] */
+ "\x8d\x74\x00" /* 7 - lea si, [si+byte 0] */
+ "\x8d\xbd\x00\x00", /* lea di, [di+word 0] */
+ "\x8d\xb4\x00\x00" /* 8 - lea si, [si+word 0] */
+ "\x8d\xbd\x00\x00" /* lea di, [di+word 0] */
+ "\xeb\x07\x90\x90\x90\x90\x90" /* 9 - jmp $+9; nop fill */
+ "\x90\x90",
+ "\xeb\x08\x90\x90\x90\x90\x90" /* 10 - jmp $+10; nop fill */
+ "\x90\x90\x90",
+ "\xeb\x09\x90\x90\x90\x90\x90" /* 11 - jmp $+11; nop fill */
+ "\x90\x90\x90\x90",
+ "\xeb\x0a\x90\x90\x90\x90\x90" /* 12 - jmp $+12; nop fill */
+ "\x90\x90\x90\x90\x90",
+ "\xeb\x0b\x90\x90\x90\x90\x90" /* 13 - jmp $+13; nop fill */
+ "\x90\x90\x90\x90\x90\x90",
+ "\xeb\x0c\x90\x90\x90\x90\x90" /* 14 - jmp $+14; nop fill */
+ "\x90\x90\x90\x90\x90\x90\x90",
+ "\xeb\x0d\x90\x90\x90\x90\x90" /* 15 - jmp $+15; nop fill */
+ "\x90\x90\x90\x90\x90\x90\x90\x90"
+ };
+ static const char *fill32[16] = {
+ NULL, /* unused */
+ "\x90", /* 1 - nop */
+ "\x89\xf6", /* 2 - mov esi, esi */
+ "\x8d\x76\x00", /* 3 - lea esi, [esi+byte 0] */
+ "\x8d\x74\x26\x00", /* 4 - lea esi, [esi*1+byte 0] */
+ "\x90" /* 5 - nop */
+ "\x8d\x74\x26\x00", /* lea esi, [esi*1+byte 0] */
+ "\x8d\xb6\x00\x00\x00\x00", /* 6 - lea esi, [esi+dword 0] */
+ "\x8d\xb4\x26\x00\x00\x00\x00", /* 7 - lea esi, [esi*1+dword 0] */
+ "\x90" /* 8 - nop */
+ "\x8d\xb4\x26\x00\x00\x00\x00", /* lea esi, [esi*1+dword 0] */
+ "\x89\xf6" /* 9 - mov esi, esi */
+ "\x8d\xbc\x27\x00\x00\x00\x00", /* lea edi, [edi*1+dword 0] */
+ "\x8d\x76\x00" /* 10 - lea esi, [esi+byte 0] */
+ "\x8d\xbc\x27\x00\x00\x00\x00", /* lea edi, [edi+dword 0] */
+ "\x8d\x74\x26\x00" /* 11 - lea esi, [esi*1+byte 0] */
+ "\x8d\xbc\x27\x00\x00\x00\x00", /* lea edi, [edi*1+dword 0]*/
+ "\x8d\xb6\x00\x00\x00\x00" /* 12 - lea esi, [esi+dword 0] */
+ "\x8d\xbf\x00\x00\x00\x00", /* lea edi, [edi+dword 0] */
+ "\x8d\xb6\x00\x00\x00\x00" /* 13 - lea esi, [esi+dword 0] */
+ "\x8d\xbc\x27\x00\x00\x00\x00", /* lea edi, [edi*1+dword 0]*/
+ "\x8d\xb4\x26\x00\x00\x00\x00" /* 14 - lea esi, [esi*1+dword 0]*/
+ "\x8d\xbc\x27\x00\x00\x00\x00", /* lea edi, [edi*1+dword 0]*/
+ "\xeb\x0d\x90\x90\x90\x90\x90" /* 15 - jmp $+15; nop fill */
+ "\x90\x90\x90\x90\x90\x90\x90\x90"
+ };
+ static const char *fill64[16] = {
+ NULL, /* unused */
+ "\x90", /* 1 - nop */
+ "\x66\x90", /* 2 - o16; nop */
+ "\x66\x66\x90", /* 3 - o16; o16; nop */
+ "\x66\x66\x66\x90", /* 4 - o16; o16; o16; nop */
+ "\x66\x66\x90\x66\x90", /* 5 */
+ "\x66\x66\x90\x66\x66\x90", /* 6 */
+ "\x66\x66\x66\x90\x66\x66\x90", /* 7 */
+ "\x66\x66\x66\x90\x66\x66\x66" /* 8 */
+ "\x90",
+ "\x66\x66\x90\x66\x66\x90\x66" /* 9 */
+ "\x66\x90",
+ "\x66\x66\x66\x90\x66\x66\x90" /* 10 */
+ "\x66\x66\x90",
+ "\x66\x66\x66\x90\x66\x66\x66" /* 11 */
+ "\x90\x66\x66\x90",
+ "\x66\x66\x66\x90\x66\x66\x66" /* 12 */
+ "\x90\x66\x66\x66\x90",
+ "\x66\x66\x66\x90\x66\x66\x90" /* 13 */
+ "\x66\x66\x90\x66\x66\x90",
+ "\x66\x66\x66\x90\x66\x66\x66" /* 14 */
+ "\x90\x66\x66\x90\x66\x66\x90",
+ "\x66\x66\x66\x90\x66\x66\x66" /* 15 */
+ "\x90\x66\x66\x66\x90\x66\x66\x90"
+ };
+ switch (arch_x86->mode_bits) {
+ case 16:
+ return (const unsigned char **)fill16;
+ case 32:
+ return (const unsigned char **)fill32;
+ case 64:
+ return (const unsigned char **)fill64;
+ default:
+ yasm_internal_error(N_("Invalid mode_bits in x86_get_fill"));
+ /*@notreached@*/
+ return NULL;
+ }
+}
+
unsigned int
yasm_x86__get_reg_size(yasm_arch *arch, unsigned long reg)
{
yasm_x86__parse_check_prefix,
yasm_x86__parse_check_targetmod,
x86_parse_directive,
+ x86_get_fill,
yasm_x86__finalize_insn,
yasm_x86__floatnum_tobytes,
yasm_x86__intnum_fixup_rel,
/*@null@*/ char *type);
static void gas_switch_section(yasm_parser_gas *parser_gas, char *name,
/*@null@*/ char *flags, /*@null@*/ char *type);
+static yasm_bytecode *gas_parser_align(yasm_parser_gas *parser_gas,
+ yasm_valparamhead *valparams,
+ int power2);
static yasm_bytecode *gas_define_strings(yasm_parser_gas *parser_gas,
yasm_valparamhead *vps, int withzero);
static yasm_bytecode *gas_define_data(yasm_parser_gas *parser_gas,
%token DIR_EQU DIR_FILE DIR_FLOAT DIR_GLOBAL DIR_IDENT DIR_INT DIR_LOC
%token DIR_LCOMM DIR_OCTA DIR_ORG DIR_P2ALIGN DIR_REPT DIR_SECTION
%token DIR_SHORT DIR_SIZE DIR_SKIP DIR_STRING
-%token DIR_TEXT DIR_TFLOAT DIR_TYPE DIR_QUAD DIR_WORD
+%token DIR_TEXT DIR_TFLOAT DIR_TYPE DIR_QUAD DIR_WORD DIR_ZERO
%type <bc> line lineexp instr
}
/* Alignment directives */
| DIR_ALIGN datavals2 {
- /* FIXME: Whether this is power-of-two or not depends on arch */
- /*@dependent@*/ yasm_valparam *bound, *fill = NULL, *maxskip = NULL;
- bound = yasm_vps_first(&$2);
- if (bound)
- fill = yasm_vps_next(bound);
- else
- yasm__error(cur_line,
- N_("align directive must specify alignment"));
- if (fill)
- maxskip = yasm_vps_next(fill);
- $$ = (yasm_bytecode *)NULL;
+ /* FIXME: Whether this is power-of-two or not depends on arch and
+ * objfmt.
+ */
+ $$ = gas_parser_align(parser_gas, &$2, 0);
}
| DIR_P2ALIGN datavals2 {
- $$ = (yasm_bytecode *)NULL;
+ $$ = gas_parser_align(parser_gas, &$2, 1);
}
| DIR_BALIGN datavals2 {
- $$ = (yasm_bytecode *)NULL;
+ $$ = gas_parser_align(parser_gas, &$2, 0);
}
- | DIR_ORG expr {
- $$ = (yasm_bytecode *)NULL;
+ | DIR_ORG INTNUM {
+ /* TODO: support expr instead of intnum */
+ $$ = yasm_bc_create_org(yasm_intnum_get_uint($2), cur_line);
}
/* Data visibility directives */
| DIR_GLOBAL label_id {
$$ = gas_define_data(parser_gas, &$2, 16);
yasm_vps_delete(&$2);
}
+ | DIR_ZERO expr {
+ yasm_datavalhead dvs;
+
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(
+ p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0)))));
+ $$ = yasm_bc_create_data(&dvs, 1, cur_line);
+
+ yasm_bc_set_multiple($$, $2);
+ }
/* Floating point data definition directives */
| DIR_FLOAT datavals {
$$ = gas_define_data(parser_gas, &$2, 4);
/* TODO */
$$ = NULL;
}
+ | DIR_FILE STRING {
+ /* TODO */
+ $$ = NULL;
+ }
| DIR_LOC INTNUM INTNUM INTNUM {
/* TODO */
$$ = NULL;
parser_gas->prev_bc = yasm_section_bcs_last(new_section);
} else
yasm__error(cur_line, N_("invalid section name `%s'"), name);
+ parser_gas->code_section = !strcmp(name, ".text");
+}
+
+static yasm_bytecode *
+gas_parser_align(yasm_parser_gas *parser_gas, yasm_valparamhead *valparams,
+ int power2)
+{
+ /*@dependent@*/ yasm_valparam *bound, *fill = NULL, *maxskip = NULL;
+ yasm_expr *boundval, *fillval = NULL, *maxskipval = NULL;
+
+ bound = yasm_vps_first(valparams);
+ boundval = bound->param;
+ bound->param = NULL;
+ if (bound && boundval) {
+ fill = yasm_vps_next(bound);
+ } else {
+ yasm__error(cur_line, N_("align directive must specify alignment"));
+ return NULL;
+ }
+
+ if (fill) {
+ fillval = fill->param;
+ fill->param = NULL;
+ maxskip = yasm_vps_next(fill);
+ }
+
+ if (maxskip) {
+ maxskipval = maxskip->param;
+ maxskip->param = NULL;
+ }
+
+ yasm_vps_delete(valparams);
+
+ /* Convert power of two to number of bytes if necessary */
+ if (power2)
+ boundval = yasm_expr_create(YASM_EXPR_SHL,
+ yasm_expr_int(yasm_intnum_create_uint(1)),
+ yasm_expr_expr(boundval), cur_line);
+
+ return yasm_bc_create_align(boundval, fillval, maxskipval,
+ parser_gas->code_section ?
+ yasm_arch_get_fill(parser_gas->arch) : NULL,
+ cur_line);
}
static yasm_bytecode *
parser_gas.state = INITIAL;
+ parser_gas.code_section = !strcmp(yasm_section_get_name(def_sect), ".text");
+
/* yacc debugging, needs YYDEBUG set in bison.y.in to work */
parser_gas.debug = 1;
INITIAL,
SECTION_DIRECTIVE
} state;
+
+ int code_section;
} yasm_parser_gas;
/* shorter access names to commonly used parser_gas fields */
".type" { RETURN(DIR_TYPE); }
".quad" { RETURN(DIR_QUAD); }
".word" { RETURN(DIR_WORD); }
+ ".zero" { RETURN(DIR_ZERO); }
/* label or maybe directive */
[.][a-zA-Z0-9_$.]* {