From: Peter Johnson Date: Mon, 3 Oct 2005 05:52:04 +0000 (-0000) Subject: Implement align and org bytecodes. While we're here, implement .zero X-Git-Tag: v0.5.0rc1~114 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d660906db518af6802fa41d47f47f1474d39a12d;p=yasm Implement align and org bytecodes. While we're here, implement .zero 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 --- diff --git a/libyasm/arch.h b/libyasm/arch.h index 72564c75..d4dc6fb7 100644 --- a/libyasm/arch.h +++ b/libyasm/arch.h @@ -166,6 +166,11 @@ typedef struct yasm_arch_module { /*@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. */ @@ -456,6 +461,13 @@ int yasm_arch_parse_directive(yasm_arch *arch, const char *name, /*@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 @@ -616,6 +628,8 @@ 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_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) \ diff --git a/libyasm/bytecode.c b/libyasm/bytecode.c index 2c212b04..bf424d36 100644 --- a/libyasm/bytecode.c +++ b/libyasm/bytecode.c @@ -81,9 +81,22 @@ typedef struct bytecode_incbin { } 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]; @@ -128,12 +141,21 @@ static int bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, 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); @@ -172,11 +194,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_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, @@ -689,6 +719,9 @@ yasm_bc_create_incbin(char *filename, yasm_expr *start, yasm_expr *maxlen, static void bc_align_destroy(void *contents) { + bytecode_align *align = (bytecode_align *)contents; + if (align->fill) + yasm_expr_destroy(align->fill); yasm_xfree(contents); } @@ -697,16 +730,54 @@ bc_align_print(const void *contents, FILE *f, int indent_level) { const bytecode_align *align = (const bytecode_align *)contents; fprintf(f, "%*s_Align_\n", indent_level, ""); - fprintf(f, "%*sBoundary=%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 @@ -714,21 +785,125 @@ bc_align_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_("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; istart = start; + + return yasm_bc_create_common(&bc_org_callback, org, line); +} + static void bc_insn_destroy(void *contents) { diff --git a/libyasm/bytecode.h b/libyasm/bytecode.h index 79d940b9..c3b478bb 100644 --- a/libyasm/bytecode.h +++ b/libyasm/bytecode.h @@ -166,11 +166,29 @@ void yasm_bc_set_multiple(yasm_bytecode *bc, /*@keep@*/ yasm_expr *e); /** 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 diff --git a/modules/arch/lc3b/lc3barch.c b/modules/arch/lc3b/lc3barch.c index e2071ab8..f8f26c53 100644 --- a/modules/arch/lc3b/lc3barch.c +++ b/modules/arch/lc3b/lc3barch.c @@ -89,6 +89,35 @@ lc3b_parse_directive(/*@unused@*/ yasm_arch *arch, 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) { @@ -147,6 +176,7 @@ yasm_arch_module yasm_lc3b_LTX_arch = { 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, diff --git a/modules/arch/x86/tests/gas32/Makefile.inc b/modules/arch/x86/tests/gas32/Makefile.inc index 4fa07307..e8b5d1d2 100644 --- a/modules/arch/x86/tests/gas32/Makefile.inc +++ b/modules/arch/x86/tests/gas32/Makefile.inc @@ -3,6 +3,9 @@ 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 diff --git a/modules/arch/x86/tests/gas32/align32.asm b/modules/arch/x86/tests/gas32/align32.asm new file mode 100644 index 00000000..7d5dfa61 --- /dev/null +++ b/modules/arch/x86/tests/gas32/align32.asm @@ -0,0 +1,82 @@ +.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 + diff --git a/modules/arch/x86/tests/gas32/align32.errwarn b/modules/arch/x86/tests/gas32/align32.errwarn new file mode 100644 index 00000000..e69de29b diff --git a/modules/arch/x86/tests/gas32/align32.hex b/modules/arch/x86/tests/gas32/align32.hex new file mode 100644 index 00000000..66b48bb9 --- /dev/null +++ b/modules/arch/x86/tests/gas32/align32.hex @@ -0,0 +1,536 @@ +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 diff --git a/modules/arch/x86/tests/gas64/Makefile.inc b/modules/arch/x86/tests/gas64/Makefile.inc index 050d1f75..8d87fd9a 100644 --- a/modules/arch/x86/tests/gas64/Makefile.inc +++ b/modules/arch/x86/tests/gas64/Makefile.inc @@ -3,6 +3,9 @@ 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 diff --git a/modules/arch/x86/tests/gas64/align64.asm b/modules/arch/x86/tests/gas64/align64.asm new file mode 100644 index 00000000..7d5dfa61 --- /dev/null +++ b/modules/arch/x86/tests/gas64/align64.asm @@ -0,0 +1,82 @@ +.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 + diff --git a/modules/arch/x86/tests/gas64/align64.errwarn b/modules/arch/x86/tests/gas64/align64.errwarn new file mode 100644 index 00000000..e69de29b diff --git a/modules/arch/x86/tests/gas64/align64.hex b/modules/arch/x86/tests/gas64/align64.hex new file mode 100644 index 00000000..3e9c5c1d --- /dev/null +++ b/modules/arch/x86/tests/gas64/align64.hex @@ -0,0 +1,672 @@ +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 diff --git a/modules/arch/x86/x86arch.c b/modules/arch/x86/x86arch.c index 7486afb2..b6aaeab0 100644 --- a/modules/arch/x86/x86arch.c +++ b/modules/arch/x86/x86arch.c @@ -128,6 +128,108 @@ x86_parse_directive(yasm_arch *arch, const char *name, 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) { @@ -269,6 +371,7 @@ yasm_arch_module yasm_x86_LTX_arch = { 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, diff --git a/modules/parsers/gas/gas-bison.y b/modules/parsers/gas/gas-bison.y index b608f369..0148090f 100644 --- a/modules/parsers/gas/gas-bison.y +++ b/modules/parsers/gas/gas-bison.y @@ -48,6 +48,9 @@ static yasm_section *gas_get_section(yasm_parser_gas *parser_gas, char *name, /*@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, @@ -102,7 +105,7 @@ static void gas_parser_directive %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 line lineexp instr @@ -155,26 +158,20 @@ 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 { @@ -274,6 +271,16 @@ lineexp: instr $$ = 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); @@ -351,6 +358,10 @@ lineexp: instr /* TODO */ $$ = NULL; } + | DIR_FILE STRING { + /* TODO */ + $$ = NULL; + } | DIR_LOC INTNUM INTNUM INTNUM { /* TODO */ $$ = NULL; @@ -671,6 +682,49 @@ gas_switch_section(yasm_parser_gas *parser_gas, char *name, 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 * diff --git a/modules/parsers/gas/gas-parser.c b/modules/parsers/gas/gas-parser.c index 31bf78a7..8b98fa93 100644 --- a/modules/parsers/gas/gas-parser.c +++ b/modules/parsers/gas/gas-parser.c @@ -77,6 +77,8 @@ gas_parser_do_parse(yasm_object *object, yasm_preproc *pp, yasm_arch *a, 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; diff --git a/modules/parsers/gas/gas-parser.h b/modules/parsers/gas/gas-parser.h index 50137960..acdbe3ef 100644 --- a/modules/parsers/gas/gas-parser.h +++ b/modules/parsers/gas/gas-parser.h @@ -70,6 +70,8 @@ typedef struct yasm_parser_gas { INITIAL, SECTION_DIRECTIVE } state; + + int code_section; } yasm_parser_gas; /* shorter access names to commonly used parser_gas fields */ diff --git a/modules/parsers/gas/gas-token.re b/modules/parsers/gas/gas-token.re index 1d775e35..18c5134a 100644 --- a/modules/parsers/gas/gas-token.re +++ b/modules/parsers/gas/gas-token.re @@ -324,6 +324,7 @@ scan: ".type" { RETURN(DIR_TYPE); } ".quad" { RETURN(DIR_QUAD); } ".word" { RETURN(DIR_WORD); } + ".zero" { RETURN(DIR_ZERO); } /* label or maybe directive */ [.][a-zA-Z0-9_$.]* {