]> granicus.if.org Git - yasm/commitdiff
Add .intel_syntax and .gas_syntax support to GAS parser.
authorPeter Johnson <peter@tortall.net>
Tue, 19 Jan 2010 07:57:43 +0000 (07:57 -0000)
committerPeter Johnson <peter@tortall.net>
Tue, 19 Jan 2010 07:57:43 +0000 (07:57 -0000)
Uses the NASM parser for the .intel_syntax parsing heavy lifting.

Contributed by: Alexei Svitkine

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

15 files changed:
modules/arch/x86/x86arch.c
modules/arch/x86/x86arch.h
modules/arch/x86/x86bc.c
modules/arch/x86/x86id.c
modules/parsers/gas/CMakeLists.txt
modules/parsers/gas/Makefile.inc
modules/parsers/gas/gas-parse-intel.c [new file with mode: 0644]
modules/parsers/gas/gas-parse.c
modules/parsers/gas/gas-parser.c
modules/parsers/gas/gas-parser.h
modules/parsers/gas/tests/bin/Makefile.inc
modules/parsers/gas/tests/bin/gas-intel_syntax-noprefix.asm [new file with mode: 0644]
modules/parsers/gas/tests/bin/gas-intel_syntax-noprefix.hex [new file with mode: 0644]
modules/parsers/nasm/nasm-parse.c
splint.sh

index 73192ecc09fa89616b4db979dd61b236c09ef6a8..95b7e385fa0c45aefc7d425209b8eeb874a656ca 100644 (file)
@@ -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;
index 29d8f7a4cef57b3d9d4b21e01b87f8bdbbc4b437..e33f132fd8f4cd5d81b563a56b17f5454c9e1883 100644 (file)
 #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,
index 844a33428d2b34710bf1c5f9808b6a856dff9afc..c329f2eaa1fa1bcca214f9b7a90d1891ce48b426 100644 (file)
@@ -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)!
          */
index c446d46285df616cfe6e00b18713aa4eecda2c06..c734d33567edfe66c2d2f2558cf60a12a3e28b14 100644 (file)
@@ -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;
 
index de23426ffa7e64222ead5c52d21493616a451690..d4ecb3ea56041035d11afedf568dd86e003ff248 100644 (file)
@@ -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
     )
index 84fa41909cfafbdbf65e75b852f710802293364e..ebc365762e58bb2abc86850b3ad3bf5804600381 100644 (file)
@@ -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 (file)
index 0000000..ca54d2e
--- /dev/null
@@ -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;
+}
index b3e318df3666ee4125a0e8da0498cd5e42ce9375..8ab7a41beac6c67bcd423cab430b3564c8021b34 100644 (file)
@@ -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},
index d421153985e5c2f8711e19a74226285aaf1940e1..948341d91c5f024c04b0aa388ab884bf4438a2fd 100644 (file)
@@ -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 =
index fe8a0bc044a3d14c47ea605980a68fb044b98ca8..2b1d311aabb9987de90e963219eaae07df97e2b2 100644 (file)
@@ -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);
index e7d978319a4d5f068149662c0835d58515df9a96..c318defa3bc15aff919ade24e219116ba1bbbfeb 100644 (file)
@@ -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 (file)
index 0000000..25c6507
--- /dev/null
@@ -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 (file)
index 0000000..fe0fdaf
--- /dev/null
@@ -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 
index 72db77755a8a239716fe66d5d6a5e50f5ba0a886..0c4820ff2c37e73db942e4000108d9b4348ec307 100644 (file)
@@ -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;
+}
index 0a1192818f29e81afb189027fdce3491d2f3bb74..56850ff39d5d4ebe393f8bc1504daccd2848d8f9 100755 (executable)
--- a/splint.sh
+++ b/splint.sh
@@ -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 \