diff options
author | Peter Johnson <peter@tortall.net> | 2010-01-19 07:57:43 +0000 |
---|---|---|
committer | Peter Johnson <peter@tortall.net> | 2010-01-19 07:57:43 +0000 |
commit | cb7f1a254c41586e905a3fa1b5e85c73fb276ad4 (patch) | |
tree | be085eb8b3a53f323653d92104b9add78e5504c3 | |
parent | 14888572a63cc9622d9c3bf4ab44b3cd8ba4b709 (diff) | |
download | yasm-cb7f1a254c41586e905a3fa1b5e85c73fb276ad4.tar.gz |
Add .intel_syntax and .gas_syntax support to GAS parser.
Uses the NASM parser for the .intel_syntax parsing heavy lifting.
Contributed by: Alexei Svitkine
svn path=/trunk/yasm/; revision=2279
-rw-r--r-- | modules/arch/x86/x86arch.c | 3 | ||||
-rw-r--r-- | modules/arch/x86/x86arch.h | 15 | ||||
-rw-r--r-- | modules/arch/x86/x86bc.c | 2 | ||||
-rw-r--r-- | modules/arch/x86/x86id.c | 11 | ||||
-rw-r--r-- | modules/parsers/gas/CMakeLists.txt | 1 | ||||
-rw-r--r-- | modules/parsers/gas/Makefile.inc | 1 | ||||
-rw-r--r-- | modules/parsers/gas/gas-parse-intel.c | 91 | ||||
-rw-r--r-- | modules/parsers/gas/gas-parse.c | 36 | ||||
-rw-r--r-- | modules/parsers/gas/gas-parser.c | 2 | ||||
-rw-r--r-- | modules/parsers/gas/gas-parser.h | 4 | ||||
-rw-r--r-- | modules/parsers/gas/tests/bin/Makefile.inc | 2 | ||||
-rw-r--r-- | modules/parsers/gas/tests/bin/gas-intel_syntax-noprefix.asm | 19 | ||||
-rw-r--r-- | modules/parsers/gas/tests/bin/gas-intel_syntax-noprefix.hex | 58 | ||||
-rw-r--r-- | modules/parsers/nasm/nasm-parse.c | 22 | ||||
-rwxr-xr-x | splint.sh | 1 |
15 files changed, 257 insertions, 11 deletions
diff --git a/modules/arch/x86/x86arch.c b/modules/arch/x86/x86arch.c index 73192ecc..95b7e385 100644 --- a/modules/arch/x86/x86arch.c +++ b/modules/arch/x86/x86arch.c @@ -68,6 +68,7 @@ x86_create(const char *machine, const char *parser, arch_x86->mode_bits = 0; arch_x86->force_strict = 0; arch_x86->default_rel = 0; + arch_x86->gas_intel_mode = 0; arch_x86->nop = X86_NOP_BASIC; if (yasm__strcasecmp(parser, "nasm") == 0) @@ -133,6 +134,8 @@ x86_set_var(yasm_arch *arch, const char *var, unsigned long val) N_("ignoring default rel in non-64-bit mode")); else arch_x86->default_rel = (unsigned int)val; + } else if (yasm__strcasecmp(var, "gas_intel_mode") == 0) { + arch_x86->gas_intel_mode = (unsigned int)val; } else return 1; return 0; diff --git a/modules/arch/x86/x86arch.h b/modules/arch/x86/x86arch.h index 29d8f7a4..e33f132f 100644 --- a/modules/arch/x86/x86arch.h +++ b/modules/arch/x86/x86arch.h @@ -74,6 +74,14 @@ #define CPU_FMA4 40 /* AMD Fused-Multiply-Add extensions */ #define CPU_CVT16 41 /* AMD CVT16 extensions */ +enum x86_parser_type { + X86_PARSER_NASM = 0, + X86_PARSER_TASM = 1, + X86_PARSER_GAS = 2 +}; + +#define PARSER(arch) (((arch)->parser == X86_PARSER_GAS && (arch)->gas_intel_mode) ? X86_PARSER_NASM : (arch)->parser) + typedef struct yasm_arch_x86 { yasm_arch_base arch; /* base structure */ @@ -83,14 +91,11 @@ typedef struct yasm_arch_x86 { wordptr *cpu_enables; unsigned int amd64_machine; - enum { - X86_PARSER_NASM = 0, - X86_PARSER_TASM = 1, - X86_PARSER_GAS = 2 - } parser; + enum x86_parser_type parser; unsigned int mode_bits; unsigned int force_strict; unsigned int default_rel; + unsigned int gas_intel_mode; enum { X86_NOP_BASIC = 0, diff --git a/modules/arch/x86/x86bc.c b/modules/arch/x86/x86bc.c index 844a3342..c329f2ea 100644 --- a/modules/arch/x86/x86bc.c +++ b/modules/arch/x86/x86bc.c @@ -226,7 +226,7 @@ yasm_x86__ea_create_expr(yasm_arch *arch, yasm_expr *e) x86_ea = ea_create(); if (arch_x86->parser == X86_PARSER_GAS) { - /* Need to change foo+rip into foo wrt rip. + /* Need to change foo+rip into foo wrt rip (even in .intel_syntax mode). * Note this assumes a particular ordering coming from the parser * to work (it's not very smart)! */ diff --git a/modules/arch/x86/x86id.c b/modules/arch/x86/x86id.c index c446d462..c734d335 100644 --- a/modules/arch/x86/x86id.c +++ b/modules/arch/x86/x86id.c @@ -1753,7 +1753,7 @@ yasm_x86__parse_check_insnprefix(yasm_arch *arch, const char *id, lcaseid[i] = tolower(id[i]); lcaseid[id_len] = '\0'; - switch (arch_x86->parser) { + switch (PARSER(arch_x86)) { case X86_PARSER_NASM: pdata = insnprefix_nasm_find(lcaseid, id_len); break; @@ -1793,7 +1793,8 @@ yasm_x86__parse_check_insnprefix(yasm_arch *arch, const char *id, id_insn->mode_bits = arch_x86->mode_bits; id_insn->suffix = 0; id_insn->misc_flags = 0; - id_insn->parser = arch_x86->parser; + id_insn->parser = PARSER(arch_x86); + id_insn->force_strict = arch_x86->force_strict != 0; id_insn->default_rel = arch_x86->default_rel != 0; *bc = yasm_bc_create_common(&x86_id_insn_callback, id_insn, line); @@ -1824,7 +1825,7 @@ yasm_x86__parse_check_insnprefix(yasm_arch *arch, const char *id, id_insn->mode_bits = arch_x86->mode_bits; id_insn->suffix = pdata->flags; id_insn->misc_flags = pdata->misc_flags; - id_insn->parser = arch_x86->parser; + id_insn->parser = PARSER(arch_x86); id_insn->force_strict = arch_x86->force_strict != 0; id_insn->default_rel = arch_x86->default_rel != 0; *bc = yasm_bc_create_common(&x86_id_insn_callback, id_insn, line); @@ -1885,9 +1886,9 @@ yasm_x86__create_empty_insn(yasm_arch *arch, unsigned long line) id_insn->mod_data[2] = 0; id_insn->num_info = NELEMS(empty_insn); id_insn->mode_bits = arch_x86->mode_bits; - id_insn->suffix = (arch_x86->parser == X86_PARSER_GAS) ? SUF_Z : 0; + id_insn->suffix = (PARSER(arch_x86) == X86_PARSER_GAS) ? SUF_Z : 0; id_insn->misc_flags = 0; - id_insn->parser = arch_x86->parser; + id_insn->parser = PARSER(arch_x86); id_insn->force_strict = arch_x86->force_strict != 0; id_insn->default_rel = arch_x86->default_rel != 0; diff --git a/modules/parsers/gas/CMakeLists.txt b/modules/parsers/gas/CMakeLists.txt index de23426f..d4ecb3ea 100644 --- a/modules/parsers/gas/CMakeLists.txt +++ b/modules/parsers/gas/CMakeLists.txt @@ -7,5 +7,6 @@ YASM_RE2C( YASM_ADD_MODULE(parser_gas parsers/gas/gas-parser.c parsers/gas/gas-parse.c + parsers/gas/gas-parse-intel.c gas-token.c ) diff --git a/modules/parsers/gas/Makefile.inc b/modules/parsers/gas/Makefile.inc index 84fa4190..ebc36576 100644 --- a/modules/parsers/gas/Makefile.inc +++ b/modules/parsers/gas/Makefile.inc @@ -3,6 +3,7 @@ libyasm_a_SOURCES += modules/parsers/gas/gas-parser.c libyasm_a_SOURCES += modules/parsers/gas/gas-parser.h libyasm_a_SOURCES += modules/parsers/gas/gas-parse.c +libyasm_a_SOURCES += modules/parsers/gas/gas-parse-intel.c nodist_libyasm_a_SOURCES += gas-token.c YASM_MODULES += parser_gas parser_gnu diff --git a/modules/parsers/gas/gas-parse-intel.c b/modules/parsers/gas/gas-parse-intel.c new file mode 100644 index 00000000..ca54d2ed --- /dev/null +++ b/modules/parsers/gas/gas-parse-intel.c @@ -0,0 +1,91 @@ +/* + * GAS-compatible parser Intel syntax support + * + * Copyright (C) 2010 Alexei Svitkine + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <util.h> +RCSID("$Id$"); + +#include <libyasm.h> + +#include "modules/parsers/gas/gas-parser.h" +#include "modules/parsers/nasm/nasm-parser-struct.h" + +extern yasm_bytecode *gas_intel_syntax_parse_instr(yasm_parser_nasm *parser_nasm, unsigned char *instr); + +#define SET_FIELDS(to, from) \ + (to)->object = (from)->object; \ + (to)->locallabel_base = (from)->locallabel_base; \ + (to)->locallabel_base_len = (from)->locallabel_base_len; \ + (to)->preproc = (from)->preproc; \ + (to)->errwarns = (from)->errwarns; \ + (to)->linemap = (from)->linemap; \ + (to)->prev_bc = (from)->prev_bc; + +yasm_bytecode *parse_instr_intel(yasm_parser_gas *parser_gas) +{ + char *stok, *slim; + unsigned char *line; + size_t length; + + yasm_parser_nasm parser_nasm; + yasm_bytecode *bc; + + memset(&parser_nasm, 0, sizeof(parser_nasm)); + + yasm_arch_set_var(parser_gas->object->arch, "gas_intel_mode", 1); + SET_FIELDS(&parser_nasm, parser_gas); + parser_nasm.masm = 1; + + stok = (char *) parser_gas->s.tok; + slim = (char *) parser_gas->s.lim; + length = 0; + while (&stok[length] < slim && stok[length] != '\n') { + length++; + } + + if (&stok[length] == slim && parser_gas->line) { + line = yasm_xmalloc(length + parser_gas->lineleft + 1); + memcpy(line, parser_gas->s.tok, length); + memcpy(line + length, parser_gas->linepos, parser_gas->lineleft); + length += parser_gas->lineleft; + if (line[length - 1] == '\n') length--; + } else { + line = yasm_xmalloc(length + 1); + memcpy(line, parser_gas->s.tok, length); + } + line[length] = '\0'; + + bc = gas_intel_syntax_parse_instr(&parser_nasm, line); + + SET_FIELDS(parser_gas, &parser_nasm); + yasm_arch_set_var(parser_gas->object->arch, "gas_intel_mode", 0); + + yasm_xfree(line); + + return bc; +} diff --git a/modules/parsers/gas/gas-parse.c b/modules/parsers/gas/gas-parse.c index b3e318df..8ab7a41b 100644 --- a/modules/parsers/gas/gas-parse.c +++ b/modules/parsers/gas/gas-parse.c @@ -881,6 +881,26 @@ dir_file(yasm_parser_gas *parser_gas, unsigned int param) return NULL; } + +static yasm_bytecode * +dir_intel_syntax(yasm_parser_gas *parser_gas, unsigned int param) +{ + parser_gas->intel_syntax = 1; + + do { + destroy_curtok(); + get_next_token(); + } while (!is_eol()); + return NULL; +} + +static yasm_bytecode * +dir_att_syntax(yasm_parser_gas *parser_gas, unsigned int param) +{ + parser_gas->intel_syntax = 0; + return NULL; +} + static yasm_bytecode * parse_instr(yasm_parser_gas *parser_gas) { @@ -889,6 +909,19 @@ parse_instr(yasm_parser_gas *parser_gas) size_t id_len; uintptr_t prefix; + if (parser_gas->intel_syntax) { + bc = parse_instr_intel(parser_gas); + if (bc) { + yasm_warn_disable(YASM_WARN_UNREC_CHAR); + do { + destroy_curtok(); + get_next_token(); + } while (!is_eol()); + yasm_warn_enable(YASM_WARN_UNREC_CHAR); + } + return bc; + } + if (curtok != ID) return NULL; @@ -1673,6 +1706,9 @@ static dir_lookup dirs_static[] = { {".space", dir_skip, 0, INITIAL}, {".fill", dir_fill, 0, INITIAL}, {".zero", dir_zero, 0, INITIAL}, + /* syntax directives */ + {".intel_syntax", dir_intel_syntax, 0, INITIAL}, + {".att_syntax", dir_att_syntax, 0, INITIAL}, /* other directives */ {".equ", dir_equ, 0, INITIAL}, {".file", dir_file, 0, INITIAL}, diff --git a/modules/parsers/gas/gas-parser.c b/modules/parsers/gas/gas-parser.c index d4211539..948341d9 100644 --- a/modules/parsers/gas/gas-parser.c +++ b/modules/parsers/gas/gas-parser.c @@ -74,6 +74,8 @@ gas_parser_do_parse(yasm_object *object, yasm_preproc *pp, for (i=0; i<10; i++) parser_gas.local[i] = 0; + parser_gas.intel_syntax = 0; + parser_gas.is_cpp_preproc = yasm__strcasecmp(((yasm_preproc_base*)pp)->module->keyword, "cpp") == 0; parser_gas.is_nasm_preproc = diff --git a/modules/parsers/gas/gas-parser.h b/modules/parsers/gas/gas-parser.h index fe8a0bc0..2b1d311a 100644 --- a/modules/parsers/gas/gas-parser.h +++ b/modules/parsers/gas/gas-parser.h @@ -122,6 +122,8 @@ typedef struct yasm_parser_gas { /* Parser-handled directives HAMT lookup */ HAMT *dirs; + int intel_syntax; + int is_nasm_preproc; int is_cpp_preproc; } yasm_parser_gas; @@ -152,6 +154,8 @@ typedef struct yasm_parser_gas { #define p_expr_new_branch(o,r) yasm_expr_create_branch(o,r,cur_line) #define p_expr_new_ident(r) yasm_expr_create_ident(r,cur_line) +yasm_bytecode *parse_instr_intel(yasm_parser_gas *parser_gas); + void gas_parser_parse(yasm_parser_gas *parser_gas); void gas_parser_cleanup(yasm_parser_gas *parser_gas); int gas_parser_lex(YYSTYPE *lvalp, yasm_parser_gas *parser_gas); diff --git a/modules/parsers/gas/tests/bin/Makefile.inc b/modules/parsers/gas/tests/bin/Makefile.inc index e7d97831..c318defa 100644 --- a/modules/parsers/gas/tests/bin/Makefile.inc +++ b/modules/parsers/gas/tests/bin/Makefile.inc @@ -6,6 +6,8 @@ EXTRA_DIST += modules/parsers/gas/tests/bin/gas_bin_test.sh EXTRA_DIST += modules/parsers/gas/tests/bin/gas-comment.asm EXTRA_DIST += modules/parsers/gas/tests/bin/gas-comment.errwarn EXTRA_DIST += modules/parsers/gas/tests/bin/gas-comment.hex +EXTRA_DIST += modules/parsers/gas/tests/bin/gas-intel_syntax-noprefix.asm +EXTRA_DIST += modules/parsers/gas/tests/bin/gas-intel_syntax-noprefix.hex EXTRA_DIST += modules/parsers/gas/tests/bin/gas-llabel.asm EXTRA_DIST += modules/parsers/gas/tests/bin/gas-llabel.hex EXTRA_DIST += modules/parsers/gas/tests/bin/gas-set.asm diff --git a/modules/parsers/gas/tests/bin/gas-intel_syntax-noprefix.asm b/modules/parsers/gas/tests/bin/gas-intel_syntax-noprefix.asm new file mode 100644 index 00000000..25c65076 --- /dev/null +++ b/modules/parsers/gas/tests/bin/gas-intel_syntax-noprefix.asm @@ -0,0 +1,19 @@ +.intel_syntax noprefix +.section .rodata +.LC0: +.string "Hello" +.text + lea ecx, 4 [esp] + and esp, -16 + push DWORD PTR [ecx-4] + push ebp + fstp st(0) + ffree st(1) + mov ebp, esp + push ecx + sub esp, 4 + mov DWORD PTR [esp], OFFSET FLAT:.LC0 + add esp, 4 + pop ebp + lea esp, [ecx-4] + ret diff --git a/modules/parsers/gas/tests/bin/gas-intel_syntax-noprefix.hex b/modules/parsers/gas/tests/bin/gas-intel_syntax-noprefix.hex new file mode 100644 index 00000000..fe0fdafa --- /dev/null +++ b/modules/parsers/gas/tests/bin/gas-intel_syntax-noprefix.hex @@ -0,0 +1,58 @@ +67 +66 +8d +4c +24 +04 +66 +83 +e4 +f0 +67 +66 +ff +71 +fc +66 +55 +dd +d8 +dd +c1 +66 +89 +e5 +66 +51 +66 +83 +ec +04 +67 +66 +c7 +04 +24 +34 +00 +00 +00 +66 +83 +c4 +04 +66 +5d +67 +66 +8d +61 +fc +c3 +00 +48 +65 +6c +6c +6f +00 diff --git a/modules/parsers/nasm/nasm-parse.c b/modules/parsers/nasm/nasm-parse.c index 72db7775..0c4820ff 100644 --- a/modules/parsers/nasm/nasm-parse.c +++ b/modules/parsers/nasm/nasm-parse.c @@ -1664,3 +1664,25 @@ nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name, if (objext_valparams) yasm_vps_delete(objext_valparams); } + +yasm_bytecode * +gas_intel_syntax_parse_instr(yasm_parser_nasm *parser_nasm, unsigned char *instr) +{ + yasm_bytecode *bc = NULL; + char *sinstr = (char *) instr; + + parser_nasm->s.bot = instr; + parser_nasm->s.tok = instr; + parser_nasm->s.ptr = instr; + parser_nasm->s.cur = instr; + parser_nasm->s.lim = instr + strlen(sinstr) + 1; + parser_nasm->s.top = parser_nasm->s.lim; + parser_nasm->peek_token = NONE; + + get_next_token(); + if (!is_eol()) { + bc = parse_instr(parser_nasm); + } + + return bc; +} @@ -78,6 +78,7 @@ splint \ modules/objfmts/rdf/rdf-objfmt.c \ modules/objfmts/xdf/xdf-objfmt.c \ modules/parsers/gas/gas-parse.c \ + modules/parsers/gas/gas-parse-intel.c \ modules/parsers/gas/gas-parser.c \ modules/parsers/nasm/nasm-parse.c \ modules/parsers/nasm/nasm-parser.c \ |