From: Jan Beulich Date: Mon, 20 Apr 2009 06:31:50 +0000 (+0000) Subject: gas/ X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ee86248ceef0286d7b2b074a88718176ebd6ada6;p=binutils-gdb.git gas/ 2009-04-20 Jan Beulich * Makefile.am: Add explicit dependency of tc-i386.o on tc-i386-intel.c. * Makefile.in: Likewise. * config/tc-i386.c (i386_finalize_immediate): Declare, broken out from i386_immediate. (i386_immediate): Slightly re-arrange, call i386_finalize_immediate. (i386_finalize_displacement): Declare, broken out from i386_displacement. (i386_displacement): Slightly re-arrange, call i386_finalize_displacement. (i386_intel_simplify, i386_intel_parse_name): Declare. (this_operand): Initialize to -1. (set_intel_syntax): Set expression rank for O_full_ptr. (md_assemble): Set this_operand back to -1 after parsing operands. (x86_cons): Negate intel_syntax to indicate state. Call i386_intel_simplify. (md_operand): Convert if to switch. Handle '[' for Intel syntax. (i386_intel_operand): Delete, including all helper functions and data. * config/tc-i386-intel.c: New file, all new code. * config/tc-i386.h (i386_operator): Declare. (md_operator): Define to i386_operator. (i386_need_index_operator): Declare. (md_need_index_operator): Define to i386_need_index_operator. (O_full_ptr): Define. gas/testsuite/ 2009-04-20 Jan Beulich * gas/i386/equ.s: Adjust. * gas/i386/equ.d: Remove reference to equ.e. * gas/i386/equ.e: Delete. * gas/i386/intel-expr.s: New. * gas/i386/intel-expr.d: New. * gas/i386/i386.exp: Run new test. * gas/i386/intel.s: Adjust. * gas/i386/intel.e: Remove no longer valid warning messages. * gas/i386/intel16.s: Adjust. * gas/i386/intel16.d: Remove reference to intel16.e. * gas/i386/intel16.e: Delete. * gas/i386/intelbad.s: Add more tests. * gas/i386/intelbad.l: Adjust. * gas/i386/intelok.s: Remove now unneeded equates. Add more tests. * gas/i386/intelok.d: Remove reference to intelok.e. Adjust. * gas/i386/intelok.e: Delete. * gas/i386/x86_64.s: Adjust. * gas/i386/x86_64.d: Remove reference to x86_64.e. * gas/i386/x86_64.e: Delete. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index cf41843190d..9caad736039 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,34 @@ +2009-04-20 Jan Beulich + + * Makefile.am: Add explicit dependency of tc-i386.o on + tc-i386-intel.c. + * Makefile.in: Likewise. + * config/tc-i386.c (i386_finalize_immediate): Declare, broken + out from i386_immediate. + (i386_immediate): Slightly re-arrange, call + i386_finalize_immediate. + (i386_finalize_displacement): Declare, broken out from + i386_displacement. + (i386_displacement): Slightly re-arrange, call + i386_finalize_displacement. + (i386_intel_simplify, i386_intel_parse_name): Declare. + (this_operand): Initialize to -1. + (set_intel_syntax): Set expression rank for O_full_ptr. + (md_assemble): Set this_operand back to -1 after parsing + operands. + (x86_cons): Negate intel_syntax to indicate state. Call + i386_intel_simplify. + (md_operand): Convert if to switch. Handle '[' for Intel + syntax. + (i386_intel_operand): Delete, including all helper functions + and data. + * config/tc-i386-intel.c: New file, all new code. + * config/tc-i386.h (i386_operator): Declare. + (md_operator): Define to i386_operator. + (i386_need_index_operator): Declare. + (md_need_index_operator): Define to i386_need_index_operator. + (O_full_ptr): Define. + 2009-04-20 Jan Beulich * expr.c (operand): Call md_need_index_operator() and diff --git a/gas/Makefile.am b/gas/Makefile.am index f5c7a84ad7b..40c52be39e2 100644 --- a/gas/Makefile.am +++ b/gas/Makefile.am @@ -614,6 +614,8 @@ e-crisaout.o: $(srcdir)/config/e-crisaout.c e-criself.o: $(srcdir)/config/e-criself.c $(COMPILE) -c $(srcdir)/config/e-criself.c +tc-i386.o: $(srcdir)/config/tc-i386-intel.c + xtensa-relax.o: $(srcdir)/config/xtensa-relax.c $(COMPILE) -c $(srcdir)/config/xtensa-relax.c diff --git a/gas/Makefile.in b/gas/Makefile.in index 084407fffaa..d65f8e41dd5 100644 --- a/gas/Makefile.in +++ b/gas/Makefile.in @@ -2667,6 +2667,8 @@ e-crisaout.o: $(srcdir)/config/e-crisaout.c e-criself.o: $(srcdir)/config/e-criself.c $(COMPILE) -c $(srcdir)/config/e-criself.c +tc-i386.o: $(srcdir)/config/tc-i386-intel.c + xtensa-relax.o: $(srcdir)/config/xtensa-relax.c $(COMPILE) -c $(srcdir)/config/xtensa-relax.c diff --git a/gas/config/tc-i386-intel.c b/gas/config/tc-i386-intel.c new file mode 100644 index 00000000000..e7a53889e53 --- /dev/null +++ b/gas/config/tc-i386-intel.c @@ -0,0 +1,845 @@ +/* tc-i386.c -- Assemble Intel syntax code for ix86/x86-64 + Copyright 2009 + Free Software Foundation, Inc. + + This file is part of GAS, the GNU Assembler. + + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +static struct + { + operatorT op_modifier; /* Operand modifier. */ + int is_mem; /* 1 if operand is memory reference. */ + unsigned int in_offset; /* >=1 if processing operand of offset. */ + unsigned int in_bracket; /* >=1 if processing operand in brackets. */ + unsigned int in_scale; /* >=1 if processing multipication operand + * in brackets. */ + i386_operand_type reloc_types; /* Value obtained from lex_got(). */ + const reg_entry *base; /* Base register (if any). */ + const reg_entry *index; /* Index register (if any). */ + offsetT scale_factor; /* Accumulated scale factor. */ + symbolS *seg; + } +intel_state; + +/* offset X_add_symbol */ +#define O_offset O_md32 +/* byte ptr X_add_symbol */ +#define O_byte_ptr O_md31 +/* word ptr X_add_symbol */ +#define O_word_ptr O_md30 +/* dword ptr X_add_symbol */ +#define O_dword_ptr O_md29 +/* qword ptr X_add_symbol */ +#define O_qword_ptr O_md28 +/* oword ptr X_add_symbol */ +#define O_oword_ptr O_md27 +/* fword ptr X_add_symbol */ +#define O_fword_ptr O_md26 +/* tbyte ptr X_add_symbol */ +#define O_tbyte_ptr O_md25 +/* xmmword ptr X_add_symbol */ +#define O_xmmword_ptr O_md24 +/* ymmword ptr X_add_symbol */ +#define O_ymmword_ptr O_md23 +/* near ptr X_add_symbol */ +#define O_near_ptr O_md22 +/* far ptr X_add_symbol */ +#define O_far_ptr O_md21 +/* offset X_add_symbol */ +#define O_short O_md20 + +static struct + { + const char *name; + operatorT operator; + unsigned int operands; + } +const i386_operators[] = + { + { "and", O_bit_and, 2 }, + { "eq", O_eq, 2 }, + { "ge", O_ge, 2 }, + { "gt", O_gt, 2 }, + { "le", O_le, 2 }, + { "lt", O_lt, 2 }, + { "mod", O_modulus, 2 }, + { "ne", O_ne, 2 }, + { "not", O_bit_not, 1 }, + { "offset", O_offset, 1 }, + { "or", O_bit_inclusive_or, 2 }, + { "shl", O_left_shift, 2 }, + { "short", O_short, 1 }, + { "shr", O_right_shift, 2 }, + { "xor", O_bit_exclusive_or, 2 }, + { NULL, O_illegal, 0 } + }; + +static struct + { + const char *name; + operatorT operator; + unsigned short sz[3]; + } +const i386_types[] = + { +#define I386_TYPE(t, n) { #t, O_##t##_ptr, { n, n, n } } + I386_TYPE(byte, 1), + I386_TYPE(word, 2), + I386_TYPE(dword, 4), + I386_TYPE(fword, 6), + I386_TYPE(qword, 8), + I386_TYPE(tbyte, 10), + I386_TYPE(oword, 16), + I386_TYPE(xmmword, 16), + I386_TYPE(ymmword, 32), +#undef I386_TYPE + { "near", O_near_ptr, { 0xff04, 0xff02, 0xff08 } }, + { "far", O_far_ptr, { 0xff06, 0xff05, 0xff06 } }, + { NULL, O_illegal, { 0, 0, 0 } } + }; + +operatorT i386_operator (const char *name, unsigned int operands, char *pc) +{ + unsigned int j; + + if (!intel_syntax) + return O_absent; + + if (!name) + { + if (operands != 2) + return O_illegal; + switch (*input_line_pointer) + { + case ':': + ++input_line_pointer; + return O_full_ptr; + case '[': + ++input_line_pointer; + return O_index; + case '@': + if (this_operand >= 0 && i.reloc[this_operand] == NO_RELOC) + { + int adjust = 0; + char *gotfree_input_line = lex_got (&i.reloc[this_operand], + &adjust, + &intel_state.reloc_types); + + if (!gotfree_input_line) + break; + free (gotfree_input_line); + *input_line_pointer++ = '+'; + memset (input_line_pointer, '0', adjust - 1); + input_line_pointer[adjust - 1] = ' '; + return O_add; + } + break; + } + return O_illegal; + } + + for (j = 0; i386_operators[j].name; ++j) + if (strcasecmp(i386_operators[j].name, name) == 0) + { + if (i386_operators[j].operands + && i386_operators[j].operands != operands) + return O_illegal; + return i386_operators[j].operator; + } + + for (j = 0; i386_types[j].name; ++j) + if (strcasecmp(i386_types[j].name, name) == 0) + break; + if (i386_types[j].name && *pc == ' ') + { + char *name = ++input_line_pointer; + char c = get_symbol_end (); + + if (strcasecmp (name, "ptr") == 0) + { + name[-1] = *pc; + *pc = c; + if (intel_syntax > 0 || operands != 1) + return O_illegal; + return i386_types[j].operator; + } + + *input_line_pointer = c; + input_line_pointer = name - 1; + } + + return O_absent; +} + +static int i386_intel_parse_name (const char *name, expressionS *e) +{ + unsigned int i; + + for (i = 0; i386_types[i].name; ++i) + if (strcasecmp(i386_types[i].name, name) == 0) + { + e->X_op = O_constant; + e->X_add_number = i386_types[i].sz[flag_code]; + e->X_add_symbol = NULL; + e->X_op_symbol = NULL; + return 1; + } + + return 0; +} + +static INLINE int i386_intel_check (const reg_entry *reg, + const reg_entry *base, + const reg_entry *index) +{ + if ((this_operand >= 0 && reg != i.op[this_operand].regs) + || base != intel_state.base || index != intel_state.index) + { + as_bad (_("invalid use of register")); + return 0; + } + return 1; +} + +static INLINE void i386_intel_fold (expressionS *e, symbolS *sym) +{ + if (S_GET_SEGMENT (sym) == absolute_section) + { + offsetT val = e->X_add_number; + + *e = *symbol_get_value_expression (sym); + e->X_add_number += val; + } + else + { + e->X_add_symbol = sym; + e->X_op_symbol = NULL; + e->X_op = O_symbol; + } +} + +static int i386_intel_simplify (expressionS *); + +static INLINE int i386_intel_simplify_symbol(symbolS *sym) +{ + int ret = i386_intel_simplify (symbol_get_value_expression (sym)); + + if (ret == 2) + { + S_SET_SEGMENT(sym, absolute_section); + ret = 1; + } + return ret; +} + +static int i386_intel_simplify (expressionS *e) +{ + const reg_entry *reg = this_operand >= 0 ? i.op[this_operand].regs : NULL; + const reg_entry *base = intel_state.base; + const reg_entry *index = intel_state.index; + int ret; + + if (!intel_syntax) + return 1; + + switch (e->X_op) + { + case O_index: + if (e->X_add_symbol) + { + if (!i386_intel_simplify_symbol (e->X_add_symbol) + || !i386_intel_check(reg, intel_state.base, intel_state.index)) + return 0;; + } + if (!intel_state.in_offset) + ++intel_state.in_bracket; + ret = i386_intel_simplify_symbol (e->X_op_symbol); + if (!intel_state.in_offset) + --intel_state.in_bracket; + if (!ret) + return 0; + if (e->X_add_symbol) + e->X_op = O_add; + else + i386_intel_fold (e, e->X_op_symbol); + break; + + case O_offset: + ++intel_state.in_offset; + ret = i386_intel_simplify_symbol (e->X_add_symbol); + --intel_state.in_offset; + if (!ret || !i386_intel_check(reg, base, index)) + return 0; + i386_intel_fold (e, e->X_add_symbol); + return ret; + + case O_byte_ptr: + case O_word_ptr: + case O_dword_ptr: + case O_fword_ptr: + case O_qword_ptr: + case O_tbyte_ptr: + case O_oword_ptr: + case O_xmmword_ptr: + case O_ymmword_ptr: + case O_near_ptr: + case O_far_ptr: + if (intel_state.op_modifier == O_absent) + intel_state.op_modifier = e->X_op; + /* FALLTHROUGH */ + case O_short: + if (symbol_get_value_expression (e->X_add_symbol)->X_op == O_register) + { + as_bad (_("invalid use of register")); + return 0; + } + if (!i386_intel_simplify_symbol (e->X_add_symbol)) + return 0; + i386_intel_fold (e, e->X_add_symbol); + break; + + case O_full_ptr: + if (symbol_get_value_expression (e->X_op_symbol)->X_op == O_register) + { + as_bad (_("invalid use of register")); + return 0; + } + if (!i386_intel_simplify_symbol (e->X_op_symbol) + || !i386_intel_check(reg, intel_state.base, intel_state.index)) + return 0; + if (!intel_state.in_offset) + intel_state.seg = e->X_add_symbol; + i386_intel_fold (e, e->X_op_symbol); + break; + + case O_register: + if (this_operand < 0 || intel_state.in_offset) + { + as_bad (_("invalid use of register")); + return 0; + } + if (!intel_state.in_bracket) + { + if (i.op[this_operand].regs) + { + as_bad (_("invalid use of register")); + return 0; + } + if (i386_regtab[e->X_add_number].reg_type.bitfield.sreg3 + && i386_regtab[e->X_add_number].reg_num == RegFlat) + { + as_bad (_("invalid use of pseudo-register")); + return 0; + } + i.op[this_operand].regs = i386_regtab + e->X_add_number; + } + else if (!intel_state.base && !intel_state.in_scale) + intel_state.base = i386_regtab + e->X_add_number; + else if (!intel_state.index) + intel_state.index = i386_regtab + e->X_add_number; + else + { + /* esp is invalid as index */ + intel_state.index = i386_regtab + REGNAM_EAX + 4; + } + e->X_op = O_constant; + e->X_add_number = 0; + return 2; + + case O_multiply: + if (this_operand >= 0 && intel_state.in_bracket) + { + expressionS *scale = NULL; + + if (intel_state.index) + --scale; + + if (!intel_state.in_scale++) + intel_state.scale_factor = 1; + + ret = i386_intel_simplify_symbol (e->X_add_symbol); + if (ret && !scale && intel_state.index) + scale = symbol_get_value_expression (e->X_op_symbol); + + if (ret) + ret = i386_intel_simplify_symbol (e->X_op_symbol); + if (ret && !scale && intel_state.index) + scale = symbol_get_value_expression (e->X_add_symbol); + + if (ret && scale && (scale + 1)) + { + resolve_expression (scale); + if (scale->X_op != O_constant + || intel_state.index->reg_type.bitfield.reg16) + scale->X_add_number = 0; + intel_state.scale_factor *= scale->X_add_number; + } + + --intel_state.in_scale; + if (!ret) + return 0; + + if (!intel_state.in_scale) + switch (intel_state.scale_factor) + { + case 1: + i.log2_scale_factor = 0; + break; + case 2: + i.log2_scale_factor = 1; + break; + case 4: + i.log2_scale_factor = 2; + break; + case 8: + i.log2_scale_factor = 3; + break; + default: + /* esp is invalid as index */ + intel_state.index = i386_regtab + REGNAM_EAX + 4; + break; + } + + break; + } + /* FALLTHROUGH */ + default: + if (e->X_add_symbol && !i386_intel_simplify_symbol (e->X_add_symbol)) + return 0; + if (e->X_op == O_add || e->X_op == O_subtract) + { + base = intel_state.base; + index = intel_state.index; + } + if (!i386_intel_check (reg, base, index) + || (e->X_op_symbol && !i386_intel_simplify_symbol (e->X_op_symbol)) + || !i386_intel_check (reg, + e->X_op != O_add ? base : intel_state.base, + e->X_op != O_add ? index : intel_state.index)) + return 0; + break; + } + + if (this_operand >= 0 && e->X_op == O_symbol && !intel_state.in_offset) + { + segT seg = S_GET_SEGMENT (e->X_add_symbol); + + if (seg != absolute_section + && seg != reg_section + && seg != expr_section) + intel_state.is_mem |= 2 - !intel_state.in_bracket; + } + + return 1; +} + +int i386_need_index_operator (void) +{ + return intel_syntax < 0; +} + +static int +i386_intel_operand (char *operand_string, int got_a_float) +{ + char *saved_input_line_pointer, *buf; + segT exp_seg; + expressionS exp, *expP; + char suffix = 0; + int ret; + + /* Initialize state structure. */ + intel_state.op_modifier = O_absent; + intel_state.is_mem = 0; + intel_state.base = NULL; + intel_state.index = NULL; + intel_state.seg = NULL; + operand_type_set (&intel_state.reloc_types, ~0); + assert (!intel_state.in_offset); + assert (!intel_state.in_bracket); + assert (!intel_state.in_scale); + + saved_input_line_pointer = input_line_pointer; + input_line_pointer = buf = xstrdup (operand_string); + + intel_syntax = -1; + memset (&exp, 0, sizeof(exp)); + exp_seg = expression (&exp); + ret = i386_intel_simplify (&exp); + intel_syntax = 1; + + SKIP_WHITESPACE (); + if (!is_end_of_line[(unsigned char) *input_line_pointer]) + { + as_bad (_("junk `%s' after expression"), input_line_pointer); + ret = 0; + } + else if (exp.X_op == O_illegal || exp.X_op == O_absent) + { + as_bad (_("invalid expression")); + ret = 0; + } + + input_line_pointer = saved_input_line_pointer; + free (buf); + + assert (!intel_state.in_offset); + assert (!intel_state.in_bracket); + assert (!intel_state.in_scale); + + if (!ret) + return 0; + + if (intel_state.op_modifier != O_absent + && current_templates->start->base_opcode != 0x8d /* lea */) + { + i.types[this_operand].bitfield.unspecified = 0; + + switch (intel_state.op_modifier) + { + case O_byte_ptr: + i.types[this_operand].bitfield.byte = 1; + suffix = BYTE_MNEM_SUFFIX; + break; + + case O_word_ptr: + i.types[this_operand].bitfield.word = 1; + if ((current_templates->start->name[0] == 'l' + && current_templates->start->name[2] == 's' + && current_templates->start->name[3] == 0) + || current_templates->start->base_opcode == 0x62 /* bound */) + suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */ + else if (got_a_float == 2) /* "fi..." */ + suffix = SHORT_MNEM_SUFFIX; + else + suffix = WORD_MNEM_SUFFIX; + break; + + case O_dword_ptr: + i.types[this_operand].bitfield.dword = 1; + if ((current_templates->start->name[0] == 'l' + && current_templates->start->name[2] == 's' + && current_templates->start->name[3] == 0) + || current_templates->start->base_opcode == 0x62 /* bound */) + suffix = WORD_MNEM_SUFFIX; + else if (flag_code == CODE_16BIT + && (current_templates->start->opcode_modifier.jump + || current_templates->start->opcode_modifier.jumpdword)) + suffix = LONG_DOUBLE_MNEM_SUFFIX; + else if (got_a_float == 1) /* "f..." */ + suffix = SHORT_MNEM_SUFFIX; + else + suffix = LONG_MNEM_SUFFIX; + break; + + case O_fword_ptr: + i.types[this_operand].bitfield.fword = 1; + if (current_templates->start->name[0] == 'l' + && current_templates->start->name[2] == 's' + && current_templates->start->name[3] == 0) + suffix = LONG_MNEM_SUFFIX; + else if (!got_a_float) + { + if (flag_code == CODE_16BIT) + add_prefix (DATA_PREFIX_OPCODE); + suffix = LONG_DOUBLE_MNEM_SUFFIX; + } + else + suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */ + break; + + case O_qword_ptr: + i.types[this_operand].bitfield.qword = 1; + if (current_templates->start->base_opcode == 0x62 /* bound */ + || got_a_float == 1) /* "f..." */ + suffix = LONG_MNEM_SUFFIX; + else + suffix = QWORD_MNEM_SUFFIX; + break; + + case O_tbyte_ptr: + i.types[this_operand].bitfield.tbyte = 1; + if (got_a_float == 1) + suffix = LONG_DOUBLE_MNEM_SUFFIX; + else + suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */ + break; + + case O_oword_ptr: + case O_xmmword_ptr: + i.types[this_operand].bitfield.xmmword = 1; + suffix = XMMWORD_MNEM_SUFFIX; + break; + + case O_ymmword_ptr: + i.types[this_operand].bitfield.ymmword = 1; + suffix = YMMWORD_MNEM_SUFFIX; + break; + + case O_far_ptr: + suffix = LONG_DOUBLE_MNEM_SUFFIX; + /* FALLTHROUGH */ + case O_near_ptr: + if (!current_templates->start->opcode_modifier.jump + && !current_templates->start->opcode_modifier.jumpdword) + suffix = got_a_float /* so it will cause an error */ + ? BYTE_MNEM_SUFFIX + : LONG_DOUBLE_MNEM_SUFFIX; + break; + + default: + BAD_CASE (intel_state.op_modifier); + break; + } + + if (!i.suffix) + i.suffix = suffix; + else if (i.suffix != suffix) + { + as_bad (_("conflicting operand size modifiers")); + return 0; + } + } + + /* Operands for jump/call need special consideration. */ + if (current_templates->start->opcode_modifier.jump + || current_templates->start->opcode_modifier.jumpdword + || current_templates->start->opcode_modifier.jumpintersegment) + { + if (i.op[this_operand].regs || intel_state.base || intel_state.index + || intel_state.is_mem > 1) + i.types[this_operand].bitfield.jumpabsolute = 1; + else + switch (intel_state.op_modifier) + { + case O_near_ptr: + if (intel_state.seg) + i.types[this_operand].bitfield.jumpabsolute = 1; + else + intel_state.is_mem = 1; + break; + case O_far_ptr: + case O_absent: + if (!intel_state.seg) + { + intel_state.is_mem = 1; + if (intel_state.op_modifier == O_absent) + break; + as_bad (_("cannot infer the segment part of the operand")); + return 0; + } + else if (S_GET_SEGMENT (intel_state.seg) == reg_section) + i.types[this_operand].bitfield.jumpabsolute = 1; + else + { + i386_operand_type types; + + if (i.imm_operands >= MAX_IMMEDIATE_OPERANDS) + { + as_bad (_("at most %d immediate operands are allowed"), + MAX_IMMEDIATE_OPERANDS); + return 0; + } + expP = &im_expressions[i.imm_operands++]; + memset (expP, 0, sizeof(*expP)); + expP->X_op = O_symbol; + expP->X_add_symbol = intel_state.seg; + i.op[this_operand].imms = expP; + + resolve_expression (expP); + operand_type_set (&types, ~0); + if (!i386_finalize_immediate (S_GET_SEGMENT (intel_state.seg), + expP, types, operand_string)) + return 0; + if (i.operands < MAX_OPERANDS) + { + this_operand = i.operands++; + i.types[this_operand].bitfield.unspecified = 1; + } + if (suffix == LONG_DOUBLE_MNEM_SUFFIX) + i.suffix = 0; + intel_state.seg = NULL; + intel_state.is_mem = 0; + } + break; + default: + i.types[this_operand].bitfield.jumpabsolute = 1; + break; + } + if (i.types[this_operand].bitfield.jumpabsolute) + intel_state.is_mem |= 1; + } + else if (intel_state.seg) + intel_state.is_mem |= 1; + + if (i.op[this_operand].regs) + { + i386_operand_type temp; + + /* Register operand. */ + if (intel_state.base || intel_state.index || intel_state.seg) + { + as_bad (_("invalid operand")); + return 0; + } + + temp = i.op[this_operand].regs->reg_type; + temp.bitfield.baseindex = 0; + i.types[this_operand] = operand_type_or (i.types[this_operand], temp); + i.types[this_operand].bitfield.unspecified = 0; + ++i.reg_operands; + } + else if (intel_state.base || intel_state.index || intel_state.seg + || intel_state.is_mem) + { + /* Memory operand. */ + if (i.mem_operands + >= 2 - !current_templates->start->opcode_modifier.isstring) + { + as_bad (_("too many memory references for `%s'"), + current_templates->start->name); + return 0; + } + + expP = &disp_expressions[i.disp_operands]; + memcpy (expP, &exp, sizeof(exp)); + resolve_expression (expP); + + if (expP->X_op != O_constant || expP->X_add_number + || (!intel_state.base && !intel_state.index)) + { + i.op[this_operand].disps = expP; + i.disp_operands++; + + if (flag_code == CODE_64BIT) + { + i.types[this_operand].bitfield.disp32 = 1; + if (!i.prefix[ADDR_PREFIX]) + { + i.types[this_operand].bitfield.disp64 = 1; + i.types[this_operand].bitfield.disp32s = 1; + } + } + else if (!i.prefix[ADDR_PREFIX] ^ (flag_code == CODE_16BIT)) + i.types[this_operand].bitfield.disp32 = 1; + else + i.types[this_operand].bitfield.disp16 = 1; + +#if defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) + /* + * exp_seg is used only for verification in + * i386_finalize_displacement, and we can end up seeing reg_section + * here - but we know we removed all registers from the expression + * (or error-ed on any remaining ones) in i386_intel_simplify. I + * consider the check in i386_finalize_displacement bogus anyway, in + * particular because it doesn't allow for expr_section, so I'd + * rather see that check (and the similar one in + * i386_finalize_immediate) use SEG_NORMAL(), but not being an a.out + * expert I can't really say whether that would have other bad side + * effects. + */ + if (OUTPUT_FLAVOR == bfd_target_aout_flavour + && exp_seg == reg_section) + exp_seg = expP->X_op != O_constant ? undefined_section + : absolute_section; +#endif + + if (!i386_finalize_displacement (exp_seg, expP, + intel_state.reloc_types, + operand_string)) + return 0; + } + + if (intel_state.base || intel_state.index) + i.types[this_operand].bitfield.baseindex = 1; + + if (intel_state.seg) + { + for (;;) + { + expP = symbol_get_value_expression (intel_state.seg); + if (expP->X_op != O_full_ptr) + break; + intel_state.seg = expP->X_add_symbol; + } + if (expP->X_op != O_register) + { + as_bad (_("segment register name expected")); + return 0; + } + if (!i386_regtab[expP->X_add_number].reg_type.bitfield.sreg2 + && !i386_regtab[expP->X_add_number].reg_type.bitfield.sreg3) + { + as_bad (_("invalid use of register")); + return 0; + } + switch (i386_regtab[expP->X_add_number].reg_num) + { + case 0: i.seg[i.mem_operands] = &es; break; + case 1: i.seg[i.mem_operands] = &cs; break; + case 2: i.seg[i.mem_operands] = &ss; break; + case 3: i.seg[i.mem_operands] = &ds; break; + case 4: i.seg[i.mem_operands] = &fs; break; + case 5: i.seg[i.mem_operands] = &gs; break; + case RegFlat: i.seg[i.mem_operands] = NULL; break; + } + } + + /* Swap base and index in 16-bit memory operands like + [si+bx]. Since i386_index_check is also used in AT&T + mode we have to do that here. */ + if (intel_state.base + && intel_state.index + && intel_state.base->reg_type.bitfield.reg16 + && intel_state.index->reg_type.bitfield.reg16 + && intel_state.base->reg_num >= 6 + && intel_state.index->reg_num < 6) + { + i.base_reg = intel_state.index; + i.index_reg = intel_state.base; + } + else + { + i.base_reg = intel_state.base; + i.index_reg = intel_state.index; + } + + if (!i386_index_check (operand_string)) + return 0; + + i.types[this_operand].bitfield.mem = 1; + ++i.mem_operands; + } + else + { + /* Immediate. */ + if (i.imm_operands >= MAX_IMMEDIATE_OPERANDS) + { + as_bad (_("at most %d immediate operands are allowed"), + MAX_IMMEDIATE_OPERANDS); + return 0; + } + + expP = &im_expressions[i.imm_operands++]; + i.op[this_operand].imms = expP; + *expP = exp; + + return i386_finalize_immediate (exp_seg, expP, intel_state.reloc_types, + operand_string); + } + + return 1; +} diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 67b477974c2..767d1fcee34 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -171,8 +171,14 @@ static void pe_directive_secrel (int); #endif static void signed_cons (int); static char *output_invalid (int c); +static int i386_finalize_immediate (segT, expressionS *, i386_operand_type, + const char *); +static int i386_finalize_displacement (segT, expressionS *, i386_operand_type, + const char *); static int i386_att_operand (char *); static int i386_intel_operand (char *, int); +static int i386_intel_simplify (expressionS *); +static int i386_intel_parse_name (const char *, expressionS *); static const reg_entry *parse_register (char *, char **); static char *parse_insn (char *, char *); static char *parse_operands (char *, const char *); @@ -377,7 +383,7 @@ static expressionS disp_expressions[MAX_MEMORY_OPERANDS]; static expressionS im_expressions[MAX_IMMEDIATE_OPERANDS]; /* Current operand we are working on. */ -static int this_operand; +static int this_operand = -1; /* We support four different modes. FLAG_CODE variable is used to distinguish these. */ @@ -1895,6 +1901,8 @@ set_intel_syntax (int syntax_flag) else allow_naked_reg = (ask_naked_reg < 0); + expr_set_rank (O_full_ptr, syntax_flag ? 10 : 0); + identifier_chars['%'] = intel_syntax && allow_naked_reg ? '%' : 0; identifier_chars['$'] = intel_syntax ? '$' : 0; register_prefix = allow_naked_reg ? "" : "%"; @@ -2748,6 +2756,7 @@ md_assemble (char *line) return; line = parse_operands (line, mnemonic); + this_operand = -1; if (line == NULL) return; @@ -6453,6 +6462,8 @@ lex_got (enum bfd_reloc_code_real *reloc, void x86_cons (expressionS *exp, int size) { + intel_syntax = -intel_syntax; + if (size == 4 || (object_64bit && size == 8)) { /* Handle @GOTOFF and the like in an expression. */ @@ -6491,6 +6502,11 @@ x86_cons (expressionS *exp, int size) } else expression (exp); + + intel_syntax = -intel_syntax; + + if (intel_syntax) + i386_intel_simplify (exp); } #endif @@ -6563,14 +6579,21 @@ i386_immediate (char *imm_start) input_line_pointer = save_input_line_pointer; if (gotfree_input_line) - free (gotfree_input_line); + { + free (gotfree_input_line); + + if (exp->X_op == O_constant || exp->X_op == O_register) + exp->X_op = O_illegal; + } - if (exp->X_op == O_absent - || exp->X_op == O_illegal - || exp->X_op == O_big - || (gotfree_input_line - && (exp->X_op == O_constant - || exp->X_op == O_register))) + return i386_finalize_immediate (exp_seg, exp, types, imm_start); +} + +static int +i386_finalize_immediate (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp, + i386_operand_type types, const char *imm_start) +{ + if (exp->X_op == O_absent || exp->X_op == O_illegal || exp->X_op == O_big) { as_bad (_("missing or invalid immediate expression `%s'"), imm_start); @@ -6803,8 +6826,26 @@ i386_displacement (char *disp_start, char *disp_end) #endif input_line_pointer = save_input_line_pointer; if (gotfree_input_line) - free (gotfree_input_line); - ret = 1; + { + free (gotfree_input_line); + + if (exp->X_op == O_constant || exp->X_op == O_register) + exp->X_op = O_illegal; + } + + ret = i386_finalize_displacement (exp_seg, exp, types, disp_start); + + RESTORE_END_STRING (disp_end); + + return ret; +} + +static int +i386_finalize_displacement (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp, + i386_operand_type types, const char *disp_start) +{ + i386_operand_type bigdisp; + int ret = 1; /* We do this to make sure that the section symbol is in the symbol table. We will ultimately change the relocation @@ -6831,10 +6872,7 @@ i386_displacement (char *disp_start, char *disp_end) else if (exp->X_op == O_absent || exp->X_op == O_illegal - || exp->X_op == O_big - || (gotfree_input_line - && (exp->X_op == O_constant - || exp->X_op == O_register))) + || exp->X_op == O_big) { inv_disp: as_bad (_("missing or invalid displacement expression `%s'"), @@ -6857,8 +6895,6 @@ i386_displacement (char *disp_start, char *disp_end) } #endif - RESTORE_END_STRING (disp_end); - /* Check if this is a displacement only operand. */ bigdisp = i.types[this_operand]; bigdisp.bitfield.disp8 = 0; @@ -7913,23 +7949,45 @@ i386_parse_name (char *name, expressionS *e, char *nextcharP) } input_line_pointer = end; *end = 0; - return 0; + return intel_syntax ? i386_intel_parse_name (name, e) : 0; } void md_operand (expressionS *e) { - if (*input_line_pointer == REGISTER_PREFIX) - { - char *end; - const reg_entry *r = parse_real_register (input_line_pointer, &end); + char *end; + const reg_entry *r; + switch (*input_line_pointer) + { + case REGISTER_PREFIX: + r = parse_real_register (input_line_pointer, &end); if (r) { e->X_op = O_register; e->X_add_number = r - i386_regtab; input_line_pointer = end; } + break; + + case '[': + assert (intel_syntax); + end = input_line_pointer++; + expression (e); + if (*input_line_pointer == ']') + { + ++input_line_pointer; + e->X_op_symbol = make_expr_symbol (e); + e->X_add_symbol = NULL; + e->X_add_number = 0; + e->X_op = O_index; + } + else + { + e->X_op = O_absent; + input_line_pointer = end; + } + break; } } @@ -8642,1352 +8700,7 @@ tc_gen_reloc (section, fixp) return rel; } - -/* Parse operands using Intel syntax. This implements a recursive descent - parser based on the BNF grammar published in Appendix B of the MASM 6.1 - Programmer's Guide. - - FIXME: We do not recognize the full operand grammar defined in the MASM - documentation. In particular, all the structure/union and - high-level macro operands are missing. - - Uppercase words are terminals, lower case words are non-terminals. - Objects surrounded by double brackets '[[' ']]' are optional. Vertical - bars '|' denote choices. Most grammar productions are implemented in - functions called 'intel_'. - - Initial production is 'expr'. - - addOp + | - - - alpha [a-zA-Z] - - binOp & | AND | \| | OR | ^ | XOR - - byteRegister AL | AH | BL | BH | CL | CH | DL | DH - - constant digits [[ radixOverride ]] - - dataType BYTE | WORD | DWORD | FWORD | QWORD | TBYTE | OWORD | XMMWORD | YMMWORD - - digits decdigit - | digits decdigit - | digits hexdigit - - decdigit [0-9] - - e04 e04 addOp e05 - | e05 - - e05 e05 binOp e06 - | e06 - - e06 e06 mulOp e09 - | e09 - - e09 OFFSET e10 - | SHORT e10 - | + e10 - | - e10 - | ~ e10 - | NOT e10 - | e09 PTR e10 - | e09 : e10 - | e10 - - e10 e10 [ expr ] - | e11 - - e11 ( expr ) - | [ expr ] - | constant - | dataType - | id - | $ - | register - - => expr expr cmpOp e04 - | e04 - - gpRegister AX | EAX | BX | EBX | CX | ECX | DX | EDX - | BP | EBP | SP | ESP | DI | EDI | SI | ESI - - hexdigit a | b | c | d | e | f - | A | B | C | D | E | F - - id alpha - | id alpha - | id decdigit - - mulOp * | / | % | MOD | << | SHL | >> | SHR - - quote " | ' - - register specialRegister - | gpRegister - | byteRegister - - segmentRegister CS | DS | ES | FS | GS | SS - - specialRegister CR0 | CR2 | CR3 | CR4 - | DR0 | DR1 | DR2 | DR3 | DR6 | DR7 - | TR3 | TR4 | TR5 | TR6 | TR7 - - We simplify the grammar in obvious places (e.g., register parsing is - done by calling parse_register) and eliminate immediate left recursion - to implement a recursive-descent parser. - - expr e04 expr' - - expr' cmpOp e04 expr' - | Empty - - e04 e05 e04' - - e04' addOp e05 e04' - | Empty - - e05 e06 e05' - - e05' binOp e06 e05' - | Empty - - e06 e09 e06' - - e06' mulOp e09 e06' - | Empty - - e09 OFFSET e10 e09' - | SHORT e10' - | + e10' - | - e10' - | ~ e10' - | NOT e10' - | e10 e09' - - e09' PTR e10 e09' - | : e10 e09' - | Empty - - e10 e11 e10' - - e10' [ expr ] e10' - | Empty - - e11 ( expr ) - | [ expr ] - | BYTE - | WORD - | DWORD - | FWORD - | QWORD - | TBYTE - | OWORD - | XMMWORD - | YMMWORD - | . - | $ - | register - | id - | constant */ - -/* Parsing structure for the intel syntax parser. Used to implement the - semantic actions for the operand grammar. */ -struct intel_parser_s - { - char *op_string; /* The string being parsed. */ - int got_a_float; /* Whether the operand is a float. */ - int op_modifier; /* Operand modifier. */ - int is_mem; /* 1 if operand is memory reference. */ - int in_offset; /* >=1 if parsing operand of offset. */ - int in_bracket; /* >=1 if parsing operand in brackets. */ - const reg_entry *reg; /* Last register reference found. */ - char *disp; /* Displacement string being built. */ - char *next_operand; /* Resume point when splitting operands. */ - }; - -static struct intel_parser_s intel_parser; - -/* Token structure for parsing intel syntax. */ -struct intel_token - { - int code; /* Token code. */ - const reg_entry *reg; /* Register entry for register tokens. */ - char *str; /* String representation. */ - }; - -static struct intel_token cur_token, prev_token; - -/* Token codes for the intel parser. Since T_SHORT is already used - by COFF, undefine it first to prevent a warning. */ -#define T_NIL -1 -#define T_CONST 1 -#define T_REG 2 -#define T_BYTE 3 -#define T_WORD 4 -#define T_DWORD 5 -#define T_FWORD 6 -#define T_QWORD 7 -#define T_TBYTE 8 -#define T_XMMWORD 9 -#undef T_SHORT -#define T_SHORT 10 -#define T_OFFSET 11 -#define T_PTR 12 -#define T_ID 13 -#define T_SHL 14 -#define T_SHR 15 -#define T_YMMWORD 16 - -/* Prototypes for intel parser functions. */ -static int intel_match_token (int); -static void intel_putback_token (void); -static void intel_get_token (void); -static int intel_expr (void); -static int intel_e04 (void); -static int intel_e05 (void); -static int intel_e06 (void); -static int intel_e09 (void); -static int intel_e10 (void); -static int intel_e11 (void); - -static int -i386_intel_operand (char *operand_string, int got_a_float) -{ - int ret; - char *p; - const reg_entry *final_base = i.base_reg; - const reg_entry *final_index = i.index_reg; - - p = intel_parser.op_string = xstrdup (operand_string); - intel_parser.disp = (char *) xmalloc (strlen (operand_string) + 1); - - for (;;) - { - /* Initialize token holders. */ - cur_token.code = prev_token.code = T_NIL; - cur_token.reg = prev_token.reg = NULL; - cur_token.str = prev_token.str = NULL; - - /* Initialize parser structure. */ - intel_parser.got_a_float = got_a_float; - intel_parser.op_modifier = 0; - intel_parser.is_mem = 0; - intel_parser.in_offset = 0; - intel_parser.in_bracket = 0; - intel_parser.reg = NULL; - intel_parser.disp[0] = '\0'; - intel_parser.next_operand = NULL; - - i.base_reg = NULL; - i.index_reg = NULL; - - /* Read the first token and start the parser. */ - intel_get_token (); - ret = intel_expr (); - - if (!ret) - break; - - if (cur_token.code != T_NIL) - { - as_bad (_("invalid operand for '%s' ('%s' unexpected)"), - current_templates->start->name, cur_token.str); - ret = 0; - } - /* If we found a memory reference, hand it over to i386_displacement - to fill in the rest of the operand fields. */ - else if (intel_parser.is_mem) - { - if ((i.mem_operands == 1 - && !current_templates->start->opcode_modifier.isstring) - || i.mem_operands == 2) - { - as_bad (_("too many memory references for '%s'"), - current_templates->start->name); - ret = 0; - } - else - { - char *s = intel_parser.disp; - - if (!quiet_warnings && intel_parser.is_mem < 0) - /* See the comments in intel_bracket_expr. */ - as_warn (_("Treating `%s' as memory reference"), operand_string); - - /* Add the displacement expression. */ - if (*s != '\0') - ret = i386_displacement (s, s + strlen (s)); - if (ret) - { - /* Swap base and index in 16-bit memory operands like - [si+bx]. Since i386_index_check is also used in AT&T - mode we have to do that here. */ - if (i.base_reg - && i.index_reg - && i.base_reg->reg_type.bitfield.reg16 - && i.index_reg->reg_type.bitfield.reg16 - && i.base_reg->reg_num >= 6 - && i.index_reg->reg_num < 6) - { - const reg_entry *base = i.index_reg; - - i.index_reg = i.base_reg; - i.base_reg = base; - } - ret = i386_index_check (operand_string); - } - if (ret) - { - i.types[this_operand].bitfield.mem = 1; - i.mem_operands++; - } - } - } - - /* Constant and OFFSET expressions are handled by i386_immediate. */ - else if ((intel_parser.op_modifier & (1 << T_OFFSET)) - || intel_parser.reg == NULL) - { - if (i.mem_operands < 2 && i.seg[i.mem_operands]) - { - if (!(intel_parser.op_modifier & (1 << T_OFFSET))) - as_warn (_("Segment override ignored")); - i.seg[i.mem_operands] = NULL; - } - ret = i386_immediate (intel_parser.disp); - } - - if (!final_base && !final_index) - { - final_base = i.base_reg; - final_index = i.index_reg; - } - - if (intel_parser.next_operand && this_operand >= MAX_OPERANDS - 1) - ret = 0; - if (!ret || !intel_parser.next_operand) - break; - intel_parser.op_string = intel_parser.next_operand; - this_operand = i.operands++; - i.types[this_operand].bitfield.unspecified = 1; - } - - free (p); - free (intel_parser.disp); - - if (final_base || final_index) - { - i.base_reg = final_base; - i.index_reg = final_index; - } - - return ret; -} - -#define NUM_ADDRESS_REGS (!!i.base_reg + !!i.index_reg) - -/* expr e04 expr' - - expr' cmpOp e04 expr' - | Empty */ -static int -intel_expr (void) -{ - /* XXX Implement the comparison operators. */ - return intel_e04 (); -} - -/* e04 e05 e04' - - e04' addOp e05 e04' - | Empty */ -static int -intel_e04 (void) -{ - int nregs = -1; - - for (;;) - { - if (!intel_e05()) - return 0; - - if (nregs >= 0 && NUM_ADDRESS_REGS > nregs) - i.base_reg = i386_regtab + REGNAM_AL; /* al is invalid as base */ - - if (cur_token.code == '+') - nregs = -1; - else if (cur_token.code == '-') - nregs = NUM_ADDRESS_REGS; - else - return 1; - - strcat (intel_parser.disp, cur_token.str); - intel_match_token (cur_token.code); - } -} - -/* e05 e06 e05' - - e05' binOp e06 e05' - | Empty */ -static int -intel_e05 (void) -{ - int nregs = ~NUM_ADDRESS_REGS; - - for (;;) - { - if (!intel_e06()) - return 0; - - if (cur_token.code == '&' - || cur_token.code == '|' - || cur_token.code == '^') - { - char str[2]; - - str[0] = cur_token.code; - str[1] = 0; - strcat (intel_parser.disp, str); - } - else - break; - - intel_match_token (cur_token.code); - - if (nregs < 0) - nregs = ~nregs; - } - if (nregs >= 0 && NUM_ADDRESS_REGS > nregs) - i.base_reg = i386_regtab + REGNAM_AL + 1; /* cl is invalid as base */ - return 1; -} - -/* e06 e09 e06' - - e06' mulOp e09 e06' - | Empty */ -static int -intel_e06 (void) -{ - int nregs = ~NUM_ADDRESS_REGS; - - for (;;) - { - if (!intel_e09()) - return 0; - - if (cur_token.code == '*' - || cur_token.code == '/' - || cur_token.code == '%') - { - char str[2]; - - str[0] = cur_token.code; - str[1] = 0; - strcat (intel_parser.disp, str); - } - else if (cur_token.code == T_SHL) - strcat (intel_parser.disp, "<<"); - else if (cur_token.code == T_SHR) - strcat (intel_parser.disp, ">>"); - else - break; - - intel_match_token (cur_token.code); - - if (nregs < 0) - nregs = ~nregs; - } - if (nregs >= 0 && NUM_ADDRESS_REGS > nregs) - i.base_reg = i386_regtab + REGNAM_AL + 2; /* dl is invalid as base */ - return 1; -} - -/* e09 OFFSET e09 - | SHORT e09 - | + e09 - | - e09 - | ~ e09 - | NOT e09 - | e10 e09' - - e09' PTR e10 e09' - | : e10 e09' - | Empty */ -static int -intel_e09 (void) -{ - int nregs = ~NUM_ADDRESS_REGS; - int in_offset = 0; - - for (;;) - { - /* Don't consume constants here. */ - if (cur_token.code == '+' || cur_token.code == '-') - { - /* Need to look one token ahead - if the next token - is a constant, the current token is its sign. */ - int next_code; - - intel_match_token (cur_token.code); - next_code = cur_token.code; - intel_putback_token (); - if (next_code == T_CONST) - break; - } - - /* e09 OFFSET e09 */ - if (cur_token.code == T_OFFSET) - { - if (!in_offset++) - ++intel_parser.in_offset; - } - - /* e09 SHORT e09 */ - else if (cur_token.code == T_SHORT) - intel_parser.op_modifier |= 1 << T_SHORT; - - /* e09 + e09 */ - else if (cur_token.code == '+') - strcat (intel_parser.disp, "+"); - - /* e09 - e09 - | ~ e09 - | NOT e09 */ - else if (cur_token.code == '-' || cur_token.code == '~') - { - char str[2]; - - if (nregs < 0) - nregs = ~nregs; - str[0] = cur_token.code; - str[1] = 0; - strcat (intel_parser.disp, str); - } - - /* e09 e10 e09' */ - else - break; - - intel_match_token (cur_token.code); - } - - for (;;) - { - if (!intel_e10 ()) - return 0; - - /* e09' PTR e10 e09' */ - if (cur_token.code == T_PTR) - { - char suffix; - - if (prev_token.code == T_BYTE) - { - suffix = BYTE_MNEM_SUFFIX; - i.types[this_operand].bitfield.byte = 1; - } - - else if (prev_token.code == T_WORD) - { - if ((current_templates->start->name[0] == 'l' - && current_templates->start->name[2] == 's' - && current_templates->start->name[3] == 0) - || current_templates->start->base_opcode == 0x62 /* bound */) - suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */ - else if (intel_parser.got_a_float == 2) /* "fi..." */ - suffix = SHORT_MNEM_SUFFIX; - else - suffix = WORD_MNEM_SUFFIX; - i.types[this_operand].bitfield.word = 1; - } - - else if (prev_token.code == T_DWORD) - { - if ((current_templates->start->name[0] == 'l' - && current_templates->start->name[2] == 's' - && current_templates->start->name[3] == 0) - || current_templates->start->base_opcode == 0x62 /* bound */) - suffix = WORD_MNEM_SUFFIX; - else if (flag_code == CODE_16BIT - && (current_templates->start->opcode_modifier.jump - || current_templates->start->opcode_modifier.jumpdword)) - suffix = LONG_DOUBLE_MNEM_SUFFIX; - else if (intel_parser.got_a_float == 1) /* "f..." */ - suffix = SHORT_MNEM_SUFFIX; - else - suffix = LONG_MNEM_SUFFIX; - i.types[this_operand].bitfield.dword = 1; - } - - else if (prev_token.code == T_FWORD) - { - if (current_templates->start->name[0] == 'l' - && current_templates->start->name[2] == 's' - && current_templates->start->name[3] == 0) - suffix = LONG_MNEM_SUFFIX; - else if (!intel_parser.got_a_float) - { - if (flag_code == CODE_16BIT) - add_prefix (DATA_PREFIX_OPCODE); - suffix = LONG_DOUBLE_MNEM_SUFFIX; - } - else - suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */ - i.types[this_operand].bitfield.fword = 1; - } - - else if (prev_token.code == T_QWORD) - { - if (current_templates->start->base_opcode == 0x62 /* bound */ - || intel_parser.got_a_float == 1) /* "f..." */ - suffix = LONG_MNEM_SUFFIX; - else - suffix = QWORD_MNEM_SUFFIX; - i.types[this_operand].bitfield.qword = 1; - } - - else if (prev_token.code == T_TBYTE) - { - if (intel_parser.got_a_float == 1) - suffix = LONG_DOUBLE_MNEM_SUFFIX; - else - suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */ - } - - else if (prev_token.code == T_XMMWORD) - { - suffix = XMMWORD_MNEM_SUFFIX; - i.types[this_operand].bitfield.xmmword = 1; - } - - else if (prev_token.code == T_YMMWORD) - { - suffix = YMMWORD_MNEM_SUFFIX; - i.types[this_operand].bitfield.ymmword = 1; - } - - else - { - as_bad (_("Unknown operand modifier `%s'"), prev_token.str); - return 0; - } - - i.types[this_operand].bitfield.unspecified = 0; - - /* Operands for jump/call using 'ptr' notation denote absolute - addresses. */ - if (current_templates->start->opcode_modifier.jump - || current_templates->start->opcode_modifier.jumpdword) - i.types[this_operand].bitfield.jumpabsolute = 1; - - if (current_templates->start->base_opcode == 0x8d /* lea */) - ; - else if (!i.suffix) - i.suffix = suffix; - else if (i.suffix != suffix) - { - as_bad (_("Conflicting operand modifiers")); - return 0; - } - - } - - /* e09' : e10 e09' */ - else if (cur_token.code == ':') - { - if (prev_token.code != T_REG) - { - /* While {call,jmp} SSSS:OOOO is MASM syntax only when SSSS is a - segment/group identifier (which we don't have), using comma - as the operand separator there is even less consistent, since - there all branches only have a single operand. */ - if (this_operand != 0 - || intel_parser.in_offset - || intel_parser.in_bracket - || (!current_templates->start->opcode_modifier.jump - && !current_templates->start->opcode_modifier.jumpdword - && !current_templates->start->opcode_modifier.jumpintersegment - && !current_templates->start->operand_types[0].bitfield.jumpabsolute)) - return intel_match_token (T_NIL); - /* Remember the start of the 2nd operand and terminate 1st - operand here. - XXX This isn't right, yet (when SSSS:OOOO is right operand of - another expression), but it gets at least the simplest case - (a plain number or symbol on the left side) right. */ - intel_parser.next_operand = intel_parser.op_string; - *--intel_parser.op_string = '\0'; - return intel_match_token (':'); - } - } - - /* e09' Empty */ - else - break; - - intel_match_token (cur_token.code); - - } - - if (in_offset) - { - --intel_parser.in_offset; - if (nregs < 0) - nregs = ~nregs; - if (NUM_ADDRESS_REGS > nregs) - { - as_bad (_("Invalid operand to `OFFSET'")); - return 0; - } - intel_parser.op_modifier |= 1 << T_OFFSET; - } - - if (nregs >= 0 && NUM_ADDRESS_REGS > nregs) - i.base_reg = i386_regtab + REGNAM_AL + 3; /* bl is invalid as base */ - return 1; -} - -static int -intel_bracket_expr (void) -{ - int was_offset = intel_parser.op_modifier & (1 << T_OFFSET); - const char *start = intel_parser.op_string; - int len; - - if (i.op[this_operand].regs) - return intel_match_token (T_NIL); - - intel_match_token ('['); - - /* Mark as a memory operand only if it's not already known to be an - offset expression. If it's an offset expression, we need to keep - the brace in. */ - if (!intel_parser.in_offset) - { - ++intel_parser.in_bracket; - - /* Operands for jump/call inside brackets denote absolute addresses. */ - if (current_templates->start->opcode_modifier.jump - || current_templates->start->opcode_modifier.jumpdword) - i.types[this_operand].bitfield.jumpabsolute = 1; - - /* Unfortunately gas always diverged from MASM in a respect that can't - be easily fixed without risking to break code sequences likely to be - encountered (the testsuite even check for this): MASM doesn't consider - an expression inside brackets unconditionally as a memory reference. - When that is e.g. a constant, an offset expression, or the sum of the - two, this is still taken as a constant load. gas, however, always - treated these as memory references. As a compromise, we'll try to make - offset expressions inside brackets work the MASM way (since that's - less likely to be found in real world code), but make constants alone - continue to work the traditional gas way. In either case, issue a - warning. */ - intel_parser.op_modifier &= ~was_offset; - } - else - strcat (intel_parser.disp, "["); - - /* Add a '+' to the displacement string if necessary. */ - if (*intel_parser.disp != '\0' - && *(intel_parser.disp + strlen (intel_parser.disp) - 1) != '+') - strcat (intel_parser.disp, "+"); - - if (intel_expr () - && (len = intel_parser.op_string - start - 1, - intel_match_token (']'))) - { - /* Preserve brackets when the operand is an offset expression. */ - if (intel_parser.in_offset) - strcat (intel_parser.disp, "]"); - else - { - --intel_parser.in_bracket; - if (i.base_reg || i.index_reg) - intel_parser.is_mem = 1; - if (!intel_parser.is_mem) - { - if (!(intel_parser.op_modifier & (1 << T_OFFSET))) - /* Defer the warning until all of the operand was parsed. */ - intel_parser.is_mem = -1; - else if (!quiet_warnings) - as_warn (_("`[%.*s]' taken to mean just `%.*s'"), - len, start, len, start); - } - } - intel_parser.op_modifier |= was_offset; - - return 1; - } - return 0; -} - -/* e10 e11 e10' - - e10' [ expr ] e10' - | Empty */ -static int -intel_e10 (void) -{ - if (!intel_e11 ()) - return 0; - - while (cur_token.code == '[') - { - if (!intel_bracket_expr ()) - return 0; - } - - return 1; -} - -/* e11 ( expr ) - | [ expr ] - | BYTE - | WORD - | DWORD - | FWORD - | QWORD - | TBYTE - | OWORD - | XMMWORD - | YMMWORD - | $ - | . - | register - | id - | constant */ -static int -intel_e11 (void) -{ - switch (cur_token.code) - { - /* e11 ( expr ) */ - case '(': - intel_match_token ('('); - strcat (intel_parser.disp, "("); - - if (intel_expr () && intel_match_token (')')) - { - strcat (intel_parser.disp, ")"); - return 1; - } - return 0; - - /* e11 [ expr ] */ - case '[': - return intel_bracket_expr (); - - /* e11 $ - | . */ - case '.': - strcat (intel_parser.disp, cur_token.str); - intel_match_token (cur_token.code); - - /* Mark as a memory operand only if it's not already known to be an - offset expression. */ - if (!intel_parser.in_offset) - intel_parser.is_mem = 1; - - return 1; - - /* e11 register */ - case T_REG: - { - const reg_entry *reg = intel_parser.reg = cur_token.reg; - - intel_match_token (T_REG); - - /* Check for segment change. */ - if (cur_token.code == ':') - { - if (!reg->reg_type.bitfield.sreg2 - && !reg->reg_type.bitfield.sreg3) - { - as_bad (_("`%s' is not a valid segment register"), - reg->reg_name); - return 0; - } - else if (i.mem_operands >= 2) - as_warn (_("Segment override ignored")); - else if (i.seg[i.mem_operands]) - as_warn (_("Extra segment override ignored")); - else - { - if (!intel_parser.in_offset) - intel_parser.is_mem = 1; - switch (reg->reg_num) - { - case 0: - i.seg[i.mem_operands] = &es; - break; - case 1: - i.seg[i.mem_operands] = &cs; - break; - case 2: - i.seg[i.mem_operands] = &ss; - break; - case 3: - i.seg[i.mem_operands] = &ds; - break; - case 4: - i.seg[i.mem_operands] = &fs; - break; - case 5: - i.seg[i.mem_operands] = &gs; - break; - } - } - } - - else if (reg->reg_type.bitfield.sreg3 && reg->reg_num == RegFlat) - { - as_bad (_("cannot use `FLAT' here")); - return 0; - } - - /* Not a segment register. Check for register scaling. */ - else if (cur_token.code == '*') - { - if (!intel_parser.in_bracket) - { - as_bad (_("Register scaling only allowed in memory operands")); - return 0; - } - - if (reg->reg_type.bitfield.reg16) /* Disallow things like [si*1]. */ - reg = i386_regtab + REGNAM_AX + 4; /* sp is invalid as index */ - else if (i.index_reg) - reg = i386_regtab + REGNAM_EAX + 4; /* esp is invalid as index */ - - /* What follows must be a valid scale. */ - intel_match_token ('*'); - i.index_reg = reg; - i.types[this_operand].bitfield.baseindex = 1; - - /* Set the scale after setting the register (otherwise, - i386_scale will complain) */ - if (cur_token.code == '+' || cur_token.code == '-') - { - char *str, sign = cur_token.code; - intel_match_token (cur_token.code); - if (cur_token.code != T_CONST) - { - as_bad (_("Syntax error: Expecting a constant, got `%s'"), - cur_token.str); - return 0; - } - str = (char *) xmalloc (strlen (cur_token.str) + 2); - strcpy (str + 1, cur_token.str); - *str = sign; - if (!i386_scale (str)) - return 0; - free (str); - } - else if (!i386_scale (cur_token.str)) - return 0; - intel_match_token (cur_token.code); - } - - /* No scaling. If this is a memory operand, the register is either a - base register (first occurrence) or an index register (second - occurrence). */ - else if (intel_parser.in_bracket) - { - - if (!i.base_reg) - i.base_reg = reg; - else if (!i.index_reg) - i.index_reg = reg; - else - { - as_bad (_("Too many register references in memory operand")); - return 0; - } - - i.types[this_operand].bitfield.baseindex = 1; - } - - /* It's neither base nor index. */ - else if (!intel_parser.in_offset && !intel_parser.is_mem) - { - i386_operand_type temp = reg->reg_type; - temp.bitfield.baseindex = 0; - i.types[this_operand] = operand_type_or (i.types[this_operand], - temp); - i.types[this_operand].bitfield.unspecified = 0; - i.op[this_operand].regs = reg; - i.reg_operands++; - } - else - { - as_bad (_("Invalid use of register")); - return 0; - } - - /* Since registers are not part of the displacement string (except - when we're parsing offset operands), we may need to remove any - preceding '+' from the displacement string. */ - if (*intel_parser.disp != '\0' - && !intel_parser.in_offset) - { - char *s = intel_parser.disp; - s += strlen (s) - 1; - if (*s == '+') - *s = '\0'; - } - - return 1; - } - - /* e11 BYTE - | WORD - | DWORD - | FWORD - | QWORD - | TBYTE - | OWORD - | XMMWORD - | YMMWORD */ - case T_BYTE: - case T_WORD: - case T_DWORD: - case T_FWORD: - case T_QWORD: - case T_TBYTE: - case T_XMMWORD: - case T_YMMWORD: - intel_match_token (cur_token.code); - - if (cur_token.code == T_PTR) - return 1; - - /* It must have been an identifier. */ - intel_putback_token (); - cur_token.code = T_ID; - /* FALLTHRU */ - - /* e11 id - | constant */ - case T_ID: - if (!intel_parser.in_offset && intel_parser.is_mem <= 0) - { - symbolS *symbolP; - - /* The identifier represents a memory reference only if it's not - preceded by an offset modifier and if it's not an equate. */ - symbolP = symbol_find(cur_token.str); - if (!symbolP || S_GET_SEGMENT(symbolP) != absolute_section) - intel_parser.is_mem = 1; - } - /* FALLTHRU */ - - case T_CONST: - case '-': - case '+': - { - char *save_str, sign = 0; - - /* Allow constants that start with `+' or `-'. */ - if (cur_token.code == '-' || cur_token.code == '+') - { - sign = cur_token.code; - intel_match_token (cur_token.code); - if (cur_token.code != T_CONST) - { - as_bad (_("Syntax error: Expecting a constant, got `%s'"), - cur_token.str); - return 0; - } - } - - save_str = (char *) xmalloc (strlen (cur_token.str) + 2); - strcpy (save_str + !!sign, cur_token.str); - if (sign) - *save_str = sign; - - /* Get the next token to check for register scaling. */ - intel_match_token (cur_token.code); - - /* Check if this constant is a scaling factor for an - index register. */ - if (cur_token.code == '*') - { - if (intel_match_token ('*') && cur_token.code == T_REG) - { - const reg_entry *reg = cur_token.reg; - - if (!intel_parser.in_bracket) - { - as_bad (_("Register scaling only allowed " - "in memory operands")); - return 0; - } - - /* Disallow things like [1*si]. - sp and esp are invalid as index. */ - if (reg->reg_type.bitfield.reg16) - reg = i386_regtab + REGNAM_AX + 4; - else if (i.index_reg) - reg = i386_regtab + REGNAM_EAX + 4; - - /* The constant is followed by `* reg', so it must be - a valid scale. */ - i.index_reg = reg; - i.types[this_operand].bitfield.baseindex = 1; - - /* Set the scale after setting the register (otherwise, - i386_scale will complain) */ - if (!i386_scale (save_str)) - return 0; - intel_match_token (T_REG); - - /* Since registers are not part of the displacement - string, we may need to remove any preceding '+' from - the displacement string. */ - if (*intel_parser.disp != '\0') - { - char *s = intel_parser.disp; - s += strlen (s) - 1; - if (*s == '+') - *s = '\0'; - } - - free (save_str); - - return 1; - } - - /* The constant was not used for register scaling. Since we have - already consumed the token following `*' we now need to put it - back in the stream. */ - intel_putback_token (); - } - - /* Add the constant to the displacement string. */ - strcat (intel_parser.disp, save_str); - free (save_str); - - return 1; - } - } - - as_bad (_("Unrecognized token '%s'"), cur_token.str); - return 0; -} - -/* Match the given token against cur_token. If they match, read the next - token from the operand string. */ -static int -intel_match_token (int code) -{ - if (cur_token.code == code) - { - intel_get_token (); - return 1; - } - else - { - as_bad (_("Unexpected token `%s'"), cur_token.str); - return 0; - } -} - -/* Read a new token from intel_parser.op_string and store it in cur_token. */ -static void -intel_get_token (void) -{ - char *end_op; - const reg_entry *reg; - struct intel_token new_token; - - new_token.code = T_NIL; - new_token.reg = NULL; - new_token.str = NULL; - - /* Free the memory allocated to the previous token and move - cur_token to prev_token. */ - if (prev_token.str) - free (prev_token.str); - - prev_token = cur_token; - - /* Skip whitespace. */ - while (is_space_char (*intel_parser.op_string)) - intel_parser.op_string++; - - /* Return an empty token if we find nothing else on the line. */ - if (*intel_parser.op_string == '\0') - { - cur_token = new_token; - return; - } - - /* The new token cannot be larger than the remainder of the operand - string. */ - new_token.str = (char *) xmalloc (strlen (intel_parser.op_string) + 1); - new_token.str[0] = '\0'; - - if (strchr ("0123456789", *intel_parser.op_string)) - { - char *p = new_token.str; - char *q = intel_parser.op_string; - new_token.code = T_CONST; - - /* Allow any kind of identifier char to encompass floating point and - hexadecimal numbers. */ - while (is_identifier_char (*q)) - *p++ = *q++; - *p = '\0'; - - /* Recognize special symbol names [0-9][bf]. */ - if (strlen (intel_parser.op_string) == 2 - && (intel_parser.op_string[1] == 'b' - || intel_parser.op_string[1] == 'f')) - new_token.code = T_ID; - } - - else if ((reg = parse_register (intel_parser.op_string, &end_op)) != NULL) - { - size_t len = end_op - intel_parser.op_string; - - new_token.code = T_REG; - new_token.reg = reg; - - memcpy (new_token.str, intel_parser.op_string, len); - new_token.str[len] = '\0'; - } - - else if (is_identifier_char (*intel_parser.op_string)) - { - char *p = new_token.str; - char *q = intel_parser.op_string; - - /* A '.' or '$' followed by an identifier char is an identifier. - Otherwise, it's operator '.' followed by an expression. */ - if ((*q == '.' || *q == '$') && !is_identifier_char (*(q + 1))) - { - new_token.code = '.'; - new_token.str[0] = '.'; - new_token.str[1] = '\0'; - } - else - { - while (is_identifier_char (*q) || *q == '@') - *p++ = *q++; - *p = '\0'; - - if (strcasecmp (new_token.str, "NOT") == 0) - new_token.code = '~'; - - else if (strcasecmp (new_token.str, "MOD") == 0) - new_token.code = '%'; - - else if (strcasecmp (new_token.str, "AND") == 0) - new_token.code = '&'; - - else if (strcasecmp (new_token.str, "OR") == 0) - new_token.code = '|'; - - else if (strcasecmp (new_token.str, "XOR") == 0) - new_token.code = '^'; - - else if (strcasecmp (new_token.str, "SHL") == 0) - new_token.code = T_SHL; - - else if (strcasecmp (new_token.str, "SHR") == 0) - new_token.code = T_SHR; - - else if (strcasecmp (new_token.str, "BYTE") == 0) - new_token.code = T_BYTE; - - else if (strcasecmp (new_token.str, "WORD") == 0) - new_token.code = T_WORD; - - else if (strcasecmp (new_token.str, "DWORD") == 0) - new_token.code = T_DWORD; - - else if (strcasecmp (new_token.str, "FWORD") == 0) - new_token.code = T_FWORD; - - else if (strcasecmp (new_token.str, "QWORD") == 0) - new_token.code = T_QWORD; - - else if (strcasecmp (new_token.str, "TBYTE") == 0 - /* XXX remove (gcc still uses it) */ - || strcasecmp (new_token.str, "XWORD") == 0) - new_token.code = T_TBYTE; - - else if (strcasecmp (new_token.str, "XMMWORD") == 0 - || strcasecmp (new_token.str, "OWORD") == 0) - new_token.code = T_XMMWORD; - - else if (strcasecmp (new_token.str, "YMMWORD") == 0) - new_token.code = T_YMMWORD; - - else if (strcasecmp (new_token.str, "PTR") == 0) - new_token.code = T_PTR; - - else if (strcasecmp (new_token.str, "SHORT") == 0) - new_token.code = T_SHORT; - - else if (strcasecmp (new_token.str, "OFFSET") == 0) - { - new_token.code = T_OFFSET; - - /* ??? This is not mentioned in the MASM grammar but gcc - makes use of it with -mintel-syntax. OFFSET may be - followed by FLAT: */ - if (strncasecmp (q, " FLAT:", 6) == 0) - strcat (new_token.str, " FLAT:"); - } - - else - new_token.code = T_ID; - } - } - - else if (strchr ("+-/*%|&^:[]()~", *intel_parser.op_string)) - { - new_token.code = *intel_parser.op_string; - new_token.str[0] = *intel_parser.op_string; - new_token.str[1] = '\0'; - } - - else if (strchr ("<>", *intel_parser.op_string) - && *intel_parser.op_string == *(intel_parser.op_string + 1)) - { - new_token.code = *intel_parser.op_string == '<' ? T_SHL : T_SHR; - new_token.str[0] = *intel_parser.op_string; - new_token.str[1] = *intel_parser.op_string; - new_token.str[2] = '\0'; - } - - else - as_bad (_("Unrecognized token `%s'"), intel_parser.op_string); - - intel_parser.op_string += strlen (new_token.str); - cur_token = new_token; -} - -/* Put cur_token back into the token stream and make cur_token point to - prev_token. */ -static void -intel_putback_token (void) -{ - if (cur_token.code != T_NIL) - { - intel_parser.op_string -= strlen (cur_token.str); - free (cur_token.str); - } - cur_token = prev_token; - - /* Forget prev_token. */ - prev_token.code = T_NIL; - prev_token.reg = NULL; - prev_token.str = NULL; -} +#include "tc-i386-intel.c" void tc_x86_parse_to_dw2regnum (expressionS *exp) diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h index ea2b6530de5..dab3c55b8c3 100644 --- a/gas/config/tc-i386.h +++ b/gas/config/tc-i386.h @@ -157,6 +157,12 @@ extern int tc_i386_fix_adjustable (struct fix *); extern int i386_parse_name (char *, expressionS *, char *); #define md_parse_name(s, e, m, c) i386_parse_name (s, e, c) +extern operatorT i386_operator (const char *name, unsigned int operands, char *); +#define md_operator i386_operator + +extern int i386_need_index_operator (void); +#define md_need_index_operator i386_need_index_operator + #define md_register_arithmetic 0 extern const struct relax_type md_relax_table[]; @@ -281,4 +287,7 @@ void tc_pe_dwarf2_emit_offset (symbolS *, unsigned int); #endif /* TE_PE */ +/* X_add_symbol:X_op_symbol (Intel mode only) */ +#define O_full_ptr O_md2 + #endif /* TC_I386 */ diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 66a68b90a13..ad97bc95cb1 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,26 @@ +2009-04-20 Jan Beulich + + * gas/i386/equ.s: Adjust. + * gas/i386/equ.d: Remove reference to equ.e. + * gas/i386/equ.e: Delete. + * gas/i386/intel-expr.s: New. + * gas/i386/intel-expr.d: New. + * gas/i386/i386.exp: Run new test. + * gas/i386/intel.s: Adjust. + * gas/i386/intel.e: Remove no longer valid warning messages. + * gas/i386/intel16.s: Adjust. + * gas/i386/intel16.d: Remove reference to intel16.e. + * gas/i386/intel16.e: Delete. + * gas/i386/intelbad.s: Add more tests. + * gas/i386/intelbad.l: Adjust. + * gas/i386/intelok.s: Remove now unneeded equates. Add more + tests. + * gas/i386/intelok.d: Remove reference to intelok.e. Adjust. + * gas/i386/intelok.e: Delete. + * gas/i386/x86_64.s: Adjust. + * gas/i386/x86_64.d: Remove reference to x86_64.e. + * gas/i386/x86_64.e: Delete. + 2009-04-16 Alan Modra * gas/all/gas.exp: Disable assign and assign-ok tests on blackfin. diff --git a/gas/testsuite/gas/i386/equ.d b/gas/testsuite/gas/i386/equ.d index f023abf5650..c23616fa361 100644 --- a/gas/testsuite/gas/i386/equ.d +++ b/gas/testsuite/gas/i386/equ.d @@ -1,6 +1,5 @@ #objdump: -drw #name: i386 equates -#stderr: equ.e .*: +file format .* diff --git a/gas/testsuite/gas/i386/equ.e b/gas/testsuite/gas/i386/equ.e deleted file mode 100644 index 8a485d1ee94..00000000000 --- a/gas/testsuite/gas/i386/equ.e +++ /dev/null @@ -1,2 +0,0 @@ -.*: Assembler messages: -.*:30: Warning: Treating .* as memory reference diff --git a/gas/testsuite/gas/i386/equ.s b/gas/testsuite/gas/i386/equ.s index 1b7a796ad04..94ec81d384c 100644 --- a/gas/testsuite/gas/i386/equ.s +++ b/gas/testsuite/gas/i386/equ.s @@ -27,7 +27,7 @@ _start: .equ r, -2 .equ s, -2 mov eax, r - mov eax, [r] + mov eax, FLAT:[r] .equ r, xtrn mov eax, offset r mov eax, [r] diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp index 09d773a6040..5352bac981a 100644 --- a/gas/testsuite/gas/i386/i386.exp +++ b/gas/testsuite/gas/i386/i386.exp @@ -197,6 +197,7 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]] } if [expr [istarget "i*86-*-*"] || [istarget "x86_64-*-*"]] then { + run_dump_test "intel-expr" run_dump_test "string-ok" run_list_test "string-bad" "" } diff --git a/gas/testsuite/gas/i386/intel.e b/gas/testsuite/gas/i386/intel.e index 6f7b365638d..9c0e76c8c29 100644 --- a/gas/testsuite/gas/i386/intel.e +++ b/gas/testsuite/gas/i386/intel.e @@ -1,10 +1,4 @@ .*: Assembler messages: -.*:154: Warning: Treating `\[0x90909090\]' as memory reference -.*:155: Warning: Treating `\[0x90909090\]' as memory reference -.*:156: Warning: Treating `\[0x90909090\]' as memory reference -.*:157: Warning: Treating `\[0x90909090\]' as memory reference -.*:494: Warning: Treating `\[0x90909090\]' as memory reference -.*:495: Warning: Treating `\[0x90909090\]' as memory reference .*:635: Warning: translating to `faddp' .*:644: Warning: translating to `fdivp' .*:653: Warning: translating to `fdivp st\(3\),st' diff --git a/gas/testsuite/gas/i386/intel.s b/gas/testsuite/gas/i386/intel.s index 7c247e9bb99..a3a07b336a4 100644 --- a/gas/testsuite/gas/i386/intel.s +++ b/gas/testsuite/gas/i386/intel.s @@ -145,16 +145,16 @@ foo: xchg edi, eax cwde cdq - call 0x9090,0x90909090 + call 0x9090:0x90909090 fwait pushf popf sahf lahf - mov al, [0x90909090] - mov eax, [0x90909090] - mov [0x90909090], al - mov [0x90909090], eax + mov al, FLAT:[0x90909090] + mov eax, FLAT:[0x90909090] + mov FLAT:[0x90909090], al + mov FLAT:[0x90909090], eax movs byte ptr es:[edi], byte ptr ds:[esi] movs dword ptr es:[edi], dword ptr ds:[esi] cmps byte ptr ds:[esi], byte ptr es:[edi] @@ -226,7 +226,7 @@ foo: out 0x90, eax call .+5+0x90909090 jmp .+5+0x90909090 - jmp 0x9090,0x90909090 + jmp 0x9090:0x90909090 jmp .+2-0x70 in al, dx in eax, dx @@ -488,11 +488,11 @@ foo: xchg di, ax cbw cwd - callw 0x9090,0x9090 + callw 0x9090:0x9090 pushfw popfw - mov ax, [0x90909090] - mov [0x90909090], ax + mov ax, FLAT:[0x90909090] + mov FLAT:[0x90909090], ax movs word ptr es:[edi], word ptr ds:[esi] cmps word ptr ds:[esi], word ptr es:[edi] test ax, 0x9090 @@ -525,7 +525,7 @@ foo: in ax, 0x90 out 0x90, ax callw .+3+0x9090 - jmpw 0x9090,0x9090 + jmpw 0x9090:0x9090 in ax, dx out dx, ax not word ptr 0x90909090[eax] @@ -599,7 +599,7 @@ rot5: mov eax, [ebx*2] adc BYTE PTR [eax*4+0x90909090], dl das - jmp 0x9090,0x90909090 + jmp 0x9090:0x90909090 movs WORD PTR es:[edi], WORD PTR ds:[esi] jo .+2-0x70 @@ -617,7 +617,7 @@ rot5: mov ax, word ptr [ebx+2*eax+(2*(4095+1)*2)] jmp eax jmp [eax] - jmp [bar] + jmp FLAT:[bar] jmp bar # Check arithmetic operators diff --git a/gas/testsuite/gas/i386/intel16.d b/gas/testsuite/gas/i386/intel16.d index e6d0ee28f83..45bb2030db8 100644 --- a/gas/testsuite/gas/i386/intel16.d +++ b/gas/testsuite/gas/i386/intel16.d @@ -1,6 +1,5 @@ #objdump: -dw -mi8086 #name: i386 intel16 -#stderr: intel16.e .*: +file format .* diff --git a/gas/testsuite/gas/i386/intel16.e b/gas/testsuite/gas/i386/intel16.e deleted file mode 100644 index 62da8a775eb..00000000000 --- a/gas/testsuite/gas/i386/intel16.e +++ /dev/null @@ -1,7 +0,0 @@ -.*: Assembler messages: -.*:5: Warning: Treating .word ptr \[0\]. as memory reference -.*:6: Warning: Treating .byte ptr \[0\]. as memory reference -.*:7: Warning: Treating .byte ptr \[0\]. as memory reference -.*:8: Warning: Treating .word ptr \[0\]. as memory reference -.*:9: Warning: Treating .byte ptr \[0\]. as memory reference -.*:10: Warning: Treating .byte ptr \[0\]. as memory reference diff --git a/gas/testsuite/gas/i386/intel16.s b/gas/testsuite/gas/i386/intel16.s index e27b017310d..14a97924795 100644 --- a/gas/testsuite/gas/i386/intel16.s +++ b/gas/testsuite/gas/i386/intel16.s @@ -2,12 +2,12 @@ .code16 .text - movsx eax,word ptr [0] - movsx eax,byte ptr [0] - movsx ax,byte ptr [0] - movzx eax,word ptr [0] - movzx eax,byte ptr [0] - movzx ax,byte ptr [0] + movsx eax,word ptr ds:[0] + movsx eax,byte ptr ds:[0] + movsx ax,byte ptr ds:[0] + movzx eax,word ptr ds:[0] + movzx eax,byte ptr ds:[0] + movzx ax,byte ptr ds:[0] lea ax, [si+bx] lea ax, [si+bp] diff --git a/gas/testsuite/gas/i386/intelbad.l b/gas/testsuite/gas/i386/intelbad.l index b10a6c443c5..bdc2645c85a 100644 --- a/gas/testsuite/gas/i386/intelbad.l +++ b/gas/testsuite/gas/i386/intelbad.l @@ -76,8 +76,9 @@ .*:79: Error: .* .*:80: Error: .* .*:91: Error: .* -.*:92: Error: .* +.*:92: (Warning|Error): .* .*:93: Error: .* +#... .*:96: Error: .* .*:97: Error: .* .*:98: Error: .* @@ -99,6 +100,7 @@ .*:114: Error: .* .*:115: Error: .* .*:116: Error: .* +#... .*:117: Error: .* .*:119: Error: .* .*:120: Error: .* @@ -131,18 +133,23 @@ .*:151: Error: .* .*:152: Error: .* .*:153: Error: .* -#... .*:154: Error: .* -#... .*:155: Error: .* .*:156: Error: .* -.*:157: Error: .* -.*:158: Error: .* +#XXX? .*:157: Error: .* +#XXX? .*:158: Error: .* +.*:159: Error: .* +#... .*:160: Error: .* .*:161: Error: .* .*:162: Error: .* -.*:163: Warning: .* -.*:164: Warning: .* +.*:163: Error: .* +.*:164: Error: .* +.*:165: Error: .* .*:166: Error: .* -.*:167: Warning: .* +#... .*:167: Error: .* +.*:168: Error: .* +.*:169: Error: .* +.*:170: Error: .* +.*:172: Error: .* diff --git a/gas/testsuite/gas/i386/intelbad.s b/gas/testsuite/gas/i386/intelbad.s index 2489c1211d3..9df2aa24cb3 100644 --- a/gas/testsuite/gas/i386/intelbad.s +++ b/gas/testsuite/gas/i386/intelbad.s @@ -149,19 +149,24 @@ start: mov eax, [ah] mov eax, [ax] mov eax, [eax+bx] + mov eax, offset [eax] + mov eax, offset eax + mov eax, offset offset eax mov eax, offset [1*eax] mov eax, offset 1*eax - mov eax, offset x[eax] # ugly diag - mov eax, offset [x][eax] # ugly diag +#XXX? mov eax, offset x[eax] +#XXX? mov eax, offset [x][eax] mov eax, flat x mov eax, flat [x] mov eax, es:eax - - mov eax, offset [eax] - mov eax, offset eax - mov eax, offset offset eax - mov eax, es:ss:[eax] - mov eax, es:[eax]+ss:[eax] + mov eax, eax[ebp] + movzx eax, 1 ptr [eax] + movzx eax, byte word ptr [eax] + movzx eax, [byte ptr eax] + movzx eax, byte [ptr [eax]] + movzx eax, byte ptr [gs:eax] + movzx eax, byte gs:ptr [eax] + movzx eax, byte ptr 1 + movzx eax, byte ptr [1] mov eax, 3:5 - call 3:[5] diff --git a/gas/testsuite/gas/i386/intelok.d b/gas/testsuite/gas/i386/intelok.d index 27f1217b2b7..e4ede94f624 100644 --- a/gas/testsuite/gas/i386/intelok.d +++ b/gas/testsuite/gas/i386/intelok.d @@ -1,7 +1,6 @@ #as: -J --divide #objdump: -dwMintel #name: i386 intel-ok -#stderr: intelok.e .*: +file format .* @@ -108,6 +107,19 @@ Disassembly of section .text: [ ]*[0-9a-f]+: 8b 40 12[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+0x12\] [ ]*[0-9a-f]+: 8b 04 85 02 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*4\+(0x)?2\] [ ]*[0-9a-f]+: 8b 04 85 02 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*4\+(0x)?2\] +[ ]*[0-9a-f]+: 0f b7 00[ ]+movzx[ ]+eax,WORD PTR \[eax\] +[ ]*[0-9a-f]+: 0f b6 00[ ]+movzx[ ]+eax,BYTE PTR \[eax\] +[ ]*[0-9a-f]+: 26 0f b7 00[ ]+movzx[ ]+eax,WORD PTR es:\[eax\] +[ ]*[0-9a-f]+: 64 0f b6 00[ ]+movzx[ ]+eax,BYTE PTR fs:\[eax\] +[ ]*[0-9a-f]+: 65 0f b7 00[ ]+movzx[ ]+eax,WORD PTR gs:\[eax\] +[ ]*[0-9a-f]+: a1 01 00 00 00[ ]+mov[ ]+eax,ds:(0x)?1 +[ ]*[0-9a-f]+: a1 01 00 00 00[ ]+mov[ ]+eax,ds:(0x)?1 +[ ]*[0-9a-f]+: 65 a1 01 00 00 00[ ]+mov[ ]+eax,gs:(0x)?1 +[ ]*[0-9a-f]+: 65 a1 01 00 00 00[ ]+mov[ ]+eax,gs:(0x)?1 +[ ]*[0-9a-f]+: a1 00 00 00 00[ ]+mov[ ]+eax,ds:(0x)?0 +[ ]*[0-9a-f]+: a1 00 00 00 00[ ]+mov[ ]+eax,ds:(0x)?0 +[ ]*[0-9a-f]+: 65 a1 00 00 00 00[ ]+mov[ ]+eax,gs:(0x)?0 +[ ]*[0-9a-f]+: a1 00 00 00 00[ ]+mov[ ]+eax,ds:(0x)?0 [ ]*[0-9a-f]+: 8b 04 05 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*1\+(0x)?0] [ ]*[0-9a-f]+: 8b 04 05 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*1\+(0x)?0] [ ]*[0-9a-f]+: 8b 04 05 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*1\+(0x)?0] @@ -123,15 +135,20 @@ Disassembly of section .text: [ ]*[0-9a-f]+: 8b 40 10[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+0x10\] [ ]*[0-9a-f]+: 8b 40 10[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+0x10\] [ ]*[0-9a-f]+: 8b 44 08 10[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+0x10\] +[ ]*[0-9a-f]+: 8b 04 08[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\] [ ]*[0-9a-f]+: 8b 44 08 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?1\] -[ ]*[0-9a-f]+: 8b 44 08 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?1\] -[ ]*[0-9a-f]+: 8b 44 08 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?1\] -[ ]*[0-9a-f]+: 8b 44 08 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?1\] -[ ]*[0-9a-f]+: 8b 44 08 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?1\] +[ ]*[0-9a-f]+: 8b 44 08 02[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?2\] +[ ]*[0-9a-f]+: 8b 44 08 03[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?3\] +[ ]*[0-9a-f]+: 8b 44 08 04[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?4\] +[ ]*[0-9a-f]+: 8b 44 08 05[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?5\] +[ ]*[0-9a-f]+: 8b 44 08 06[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?6\] +[ ]*[0-9a-f]+: 8b 44 88 07[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*4\+(0x)?7\] +[ ]*[0-9a-f]+: 8b 44 88 08[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*4\+(0x)?8\] [ ]*[0-9a-f]+: 8b 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\] [ ]*[0-9a-f]+: 8b 04 08[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\] [ ]*[0-9a-f]+: 8b 04 08[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\] [ ]*[0-9a-f]+: 26 8b 00[ ]+mov[ ]+eax,(DWORD PTR )?es:\[eax\] +[ ]*[0-9a-f]+: 64 8b 00[ ]+mov[ ]+eax,(DWORD PTR )?fs:\[eax\] [ ]*[0-9a-f]+: 6a 01[ ]+push[ ]+0x1 [ ]*[0-9a-f]+: 6a ff[ ]+push[ ]+0xffffffff [ ]*[0-9a-f]+: 6a fe[ ]+push[ ]+0xfffffffe @@ -151,31 +168,40 @@ Disassembly of section .text: [ ]*[0-9a-f]+: 6a fb[ ]+push[ ]+0xfffffffb [ ]*[0-9a-f]+: 6a 03[ ]+push[ ]+0x3 [ ]*[0-9a-f]+: 6a 04[ ]+push[ ]+0x4 -[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0 -[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0 -[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0 -[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0 -[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0 -[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0 -[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0 +[ ]*[0-9a-f]+: b8 01 00 00 00[ ]+mov[ ]+eax,(0x)?1 +[ ]*[0-9a-f]+: b8 01 00 00 00[ ]+mov[ ]+eax,(0x)?1 +[ ]*[0-9a-f]+: b8 01 00 00 00[ ]+mov[ ]+eax,(0x)?1 +[ ]*[0-9a-f]+: b8 01 00 00 00[ ]+mov[ ]+eax,(0x)?1 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0 +[ ]*[0-9a-f]+: a1 00 00 00 00[ ]+mov[ ]+eax,ds:(0x)?0 +[ ]*[0-9a-f]+: 65 a1 00 00 00 00[ ]+mov[ ]+eax,gs:(0x)?0 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0 +[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0 [ ]*[0-9a-f]+: 8b 80 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+(0x)?0\] [ ]*[0-9a-f]+: 8b 40 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+(0x)?1] [ ]*[0-9a-f]+: 8b 80 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+(0x)?0\] +[ ]*[0-9a-f]+: 8b 40 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+(0x)?1] [ ]*[0-9a-f]+: 8b 80 01 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+(0x)?1\] [ ]*[0-9a-f]+: 8b 80 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+(0x)?0\] [ ]*[0-9a-f]+: 8b 40 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+(0x)?1\] -[ ]*[0-9a-f]+: a1 01 00 00 00[ ]+mov[ ]+eax,ds:0x1 -[ ]*[0-9a-f]+: a1 ff ff ff ff[ ]+mov[ ]+eax,ds:0xffffffff -[ ]*[0-9a-f]+: 26 a1 02 00 00 00[ ]+mov[ ]+eax,es:0x2 -#... -[ ]*[0-9a-f]+: b8 03 00 00 00[ ]+mov[ ]+eax,0x3 -[ ]*[0-9a-f]+: a1 04 00 00 00[ ]+mov[ ]+eax,ds:0x4 -[ ]*[0-9a-f]+: a1 05 00 00 00[ ]+mov[ ]+eax,ds:0x5 -[ ]*[0-9a-f]+: 36 a1 06 00 00 00[ ]+mov[ ]+eax,ss:0x6 -[ ]*[0-9a-f]+: 36 a1 07 00 00 00[ ]+mov[ ]+eax,ss:0x7 -[ ]*[0-9a-f]+: a1 08 00 00 00[ ]+mov[ ]+eax,ds:0x8 +[ ]*[0-9a-f]+: b8 01 00 00 00[ ]+mov[ ]+eax,(0x)?1 +[ ]*[0-9a-f]+: b8 ff ff ff ff[ ]+mov[ ]+eax,(0xffffffff|-1) +[ ]*[0-9a-f]+: 26 a1 02 00 00 00[ ]+mov[ ]+eax,es:(0x)?2 +[ ]*[0-9a-f]+: b8 03 00 00 00[ ]+mov[ ]+eax,(0x)?3 +[ ]*[0-9a-f]+: b8 04 00 00 00[ ]+mov[ ]+eax,(0x)?4 +[ ]*[0-9a-f]+: b8 05 00 00 00[ ]+mov[ ]+eax,(0x)?5 +[ ]*[0-9a-f]+: 36 a1 06 00 00 00[ ]+mov[ ]+eax,ss:(0x)?6 +[ ]*[0-9a-f]+: 36 a1 07 00 00 00[ ]+mov[ ]+eax,ss:(0x)?7 [ ]*[0-9a-f]+: 9a 05 00 00 00 03 00[ ]+l?call[ ]+0x3[,:]0x5 [ ]*[0-9a-f]+: ea 03 00 00 00 05 00[ ]+l?jmp[ ]+0x5[,:]0x3 -[ ]*[0-9a-f]+: ff 15 00 00 00 00[ ]+call[ ]+(DWORD PTR )?(ds:)?0x0 -[ ]*[0-9a-f]+: 66 ff 25 00 00 00 00[ ]+jmp[ ]+(WORD PTR )?(ds:)?0x0 +[ ]*[0-9a-f]+: ff 15 00 00 00 00[ ]+call[ ]+DWORD PTR (ds:)?(0x)?0 +[ ]*[0-9a-f]+: 66 ff 25 00 00 00 00[ ]+jmp[ ]+WORD PTR (ds:)?(0x)?0 #pass diff --git a/gas/testsuite/gas/i386/intelok.e b/gas/testsuite/gas/i386/intelok.e deleted file mode 100644 index e49436ed636..00000000000 --- a/gas/testsuite/gas/i386/intelok.e +++ /dev/null @@ -1,8 +0,0 @@ -.*: Assembler messages: -.*:175: Warning: .* taken to mean just .* -.*:182: Warning: Treating .* as memory reference -.*:183: Warning: .* taken to mean just .* -.*:183: Warning: Treating .* as memory reference -.*:186: Warning: Treating .* as memory reference -.*:187: Warning: Treating .* as memory reference -.*:190: Warning: Treating .* as memory reference diff --git a/gas/testsuite/gas/i386/intelok.s b/gas/testsuite/gas/i386/intelok.s index 2f78929d1b8..00cf4da717a 100644 --- a/gas/testsuite/gas/i386/intelok.s +++ b/gas/testsuite/gas/i386/intelok.s @@ -1,12 +1,4 @@ .intel_syntax noprefix - .equiv byte, 1 - .equiv word, 2 - .equiv dword, 4 - .equiv fword, 6 - .equiv qword, 8 - .equiv tbyte, 10 - .equiv oword, 16 - .equiv xmmword, 16 .text start: @@ -115,6 +107,20 @@ start: mov eax, tbyte[eax+dword*2] mov eax, [word+eax*dword] mov eax, word[eax*dword] + movzx eax, word ptr byte ptr [eax] + movzx eax, byte ptr [word ptr [eax]] + movzx eax, word ptr es:[eax] + movzx eax, byte ptr [fs:[eax]] + movzx eax, gs:word ptr [eax] + + mov eax, FLAT:1 + mov eax, FLAT:[1] + mov eax, gs:1 + mov eax, gs:[1] + mov eax, x + mov eax, FLAT:x + mov eax, gs:x + mov eax, [x] mov eax, [eax*1] mov eax, [eax*+1] @@ -127,19 +133,24 @@ start: mov eax, [eax]+1 mov eax, [eax - 5 + ecx] mov eax, [eax + 5 and 3 + ecx] - mov eax, [eax + 5*3 + ecx] + mov eax, [eax + 5 * 3 + ecx] mov eax, [oword][eax] mov eax, [eax][oword] mov eax, xmmword[eax][ecx] + mov eax, [eax]+[ecx] mov eax, [eax]+1[ecx] - mov eax, [eax][ecx]+1 - mov eax, [1][eax][ecx] - mov eax, [eax][1][ecx] - mov eax, [eax][ecx][1] + mov eax, [eax+2[ecx]] + mov eax, [eax][ecx]+3 + mov eax, [4][eax][ecx] + mov eax, [eax][5][ecx] + mov eax, [eax][ecx][6] + mov eax, [eax+ecx*(2+2)+7] + mov eax, [eax+(ecx+2)*4] mov eax, [[eax]] mov eax, [eax[ecx]] mov eax, [[eax][ecx]] mov eax, es:[eax] + mov eax, fs:gs:[eax] # expressions @@ -166,6 +177,10 @@ start: # offset expressions + mov eax, 1 + mov eax, [1] + mov eax, dword ptr 1 + mov eax, dword ptr [1] mov eax, offset x mov eax, offset flat:x mov eax, offset gs:x @@ -173,10 +188,17 @@ start: mov eax, offset flat:[x] mov eax, offset gs:[x] mov eax, [offset x] + mov eax, [offset [x]] + mov eax, dword ptr [offset [x]] + mov eax, FLAT:[offset [x]] + mov eax, gs:[offset [x]] + mov eax, offset [dword ptr [x]] + mov eax, offset [gs:[x]] mov eax, [eax + offset x] mov eax, [eax + offset 1] mov eax, [offset x + eax] - mov eax, offset x+1[eax] + mov eax, [offset 1 + eax] + mov eax, offset x + 1[eax] mov eax, [eax] + offset x mov eax, [eax] + offset 1 mov eax, offset x + [1] @@ -187,11 +209,10 @@ start: mov eax, [5] + [offset x] mov eax, ss:[6] + offset x mov eax, ss:[7] + [offset x] - mov eax, dword ptr [8] # other operands call 3:5 - jmp 5:3 + jmp 5:[3] call dword ptr xtrn jmp word ptr xtrn diff --git a/gas/testsuite/gas/i386/x86_64.d b/gas/testsuite/gas/i386/x86_64.d index cbf769aa40d..086cc3ace42 100644 --- a/gas/testsuite/gas/i386/x86_64.d +++ b/gas/testsuite/gas/i386/x86_64.d @@ -1,7 +1,6 @@ #as: -J #objdump: -dw #name: x86_64 -#stderr: x86_64.e .*: +file format .* Disassembly of section .text: diff --git a/gas/testsuite/gas/i386/x86_64.e b/gas/testsuite/gas/i386/x86_64.e deleted file mode 100644 index e11e90358fd..00000000000 --- a/gas/testsuite/gas/i386/x86_64.e +++ /dev/null @@ -1,9 +0,0 @@ -.*.s: Assembler messages: -.*:51: Warning: Treating .\[0x22222222\]. as memory reference -.*:89: Warning: Treating .DWORD PTR \[0x22222222\]. as memory reference -.*:91: Warning: Treating .\[0x8877665544332211\]. as memory reference -.*:92: Warning: Treating .\[0x8877665544332211\]. as memory reference -.*:93: Warning: Treating .\[0x8877665544332211\]. as memory reference -.*:94: Warning: Treating .\[0x8877665544332211\]. as memory reference -.*:95: Warning: Treating .\[0x8877665544332211\]. as memory reference -.*:96: Warning: Treating .\[0x8877665544332211\]. as memory reference diff --git a/gas/testsuite/gas/i386/x86_64.s b/gas/testsuite/gas/i386/x86_64.s index 34c8cdf8f2d..ef887d5b5f3 100644 --- a/gas/testsuite/gas/i386/x86_64.s +++ b/gas/testsuite/gas/i386/x86_64.s @@ -48,7 +48,7 @@ ADD R8D,[R8] ADD RAX,[R8] ADD EAX,[0x22222222+RIP] ADD EAX,[RBP+0x00] -ADD EAX,[0x22222222] +ADD EAX,FLAT:[0x22222222] ADD EAX,[R13+0] ADD EAX,[RAX+RAX*4] ADD EAX,[R8+RAX*4] @@ -86,14 +86,14 @@ ADD DWORD PTR [RAX*8+0x22222222],0x33 ADD DWORD PTR [RAX+0x22222222],0x33 ADD DWORD PTR [RAX+0x22222222],0x33 ADD DWORD PTR [R8+RBP*8],0x33 -ADD DWORD PTR [0x22222222],0x33 +ADD DWORD PTR FLAT:[0x22222222],0x33 #new instructions -MOVABS AL,[0x8877665544332211] -MOVABS EAX,[0x8877665544332211] -MOVABS [0x8877665544332211],AL -MOVABS [0x8877665544332211],EAX -MOVABS RAX,[0x8877665544332211] -MOVABS [0x8877665544332211],RAX +MOVABS AL,FLAT:[0x8877665544332211] +MOVABS EAX,FLAT:[0x8877665544332211] +MOVABS FLAT:[0x8877665544332211],AL +MOVABS FLAT:[0x8877665544332211],EAX +MOVABS RAX,FLAT:[0x8877665544332211] +MOVABS FLAT:[0x8877665544332211],RAX cqo cdqe movsx rax, eax