X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-i386-intel.c;h=a2cd286572d3fd7ab712fd3d49eba06755feb537;hb=4288405d5ec2c68c7e9d8d68a090c6c9ff3825d1;hp=2bdcf3520f4c0bb1fce825ecb73f06baa42ea8c0;hpb=b90efa5b79ac1524ec260f8eb89d1be37e0219a7;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-i386-intel.c b/gas/config/tc-i386-intel.c index 2bdcf3520f..a2cd286572 100644 --- a/gas/config/tc-i386-intel.c +++ b/gas/config/tc-i386-intel.c @@ -1,5 +1,5 @@ /* tc-i386.c -- Assemble Intel syntax code for ix86/x86-64 - Copyright (C) 2009-2015 Free Software Foundation, Inc. + Copyright (C) 2009-2019 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -26,7 +26,7 @@ static struct int has_offset; /* 1 if operand has offset. */ 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 + unsigned int in_scale; /* >=1 if processing multiplication operand * in brackets. */ i386_operand_type reloc_types; /* Value obtained from lex_got(). */ const reg_entry *base; /* Base register (if any). */ @@ -168,13 +168,18 @@ operatorT i386_operator (const char *name, unsigned int operands, char *pc) for (j = 0; i386_types[j].name; ++j) if (strcasecmp (i386_types[j].name, name) == 0) break; + if (i386_types[j].name && *pc == ' ') { - char *pname = ++input_line_pointer; - char c = get_symbol_end (); + char *pname; + char c; + + ++input_line_pointer; + c = get_symbol_name (&pname); if (strcasecmp (pname, "ptr") == 0) { + /* FIXME: What if c == '"' ? */ pname[-1] = *pc; *pc = c; if (intel_syntax > 0 || operands != 1) @@ -182,7 +187,7 @@ operatorT i386_operator (const char *name, unsigned int operands, char *pc) return i386_types[j].op; } - *input_line_pointer = c; + (void) restore_line_pointer (c); input_line_pointer = pname - 1; } @@ -265,6 +270,12 @@ i386_intel_simplify_register (expressionS *e) else reg_num = e->X_md - 1; + if (reg_num < 0 || reg_num >= (int) i386_regtab_size) + { + as_bad (_("invalid register number")); + return 0; + } + if (!intel_state.in_bracket) { if (i.op[this_operand].regs) @@ -281,9 +292,10 @@ i386_intel_simplify_register (expressionS *e) i.op[this_operand].regs = i386_regtab + reg_num; } else if (!intel_state.index - && (i386_regtab[reg_num].reg_type.bitfield.regxmm - || i386_regtab[reg_num].reg_type.bitfield.regymm - || i386_regtab[reg_num].reg_type.bitfield.regzmm)) + && (i386_regtab[reg_num].reg_type.bitfield.xmmword + || i386_regtab[reg_num].reg_type.bitfield.ymmword + || i386_regtab[reg_num].reg_type.bitfield.zmmword + || i386_regtab[reg_num].reg_num == RegIZ)) intel_state.index = i386_regtab + reg_num; else if (!intel_state.base && !intel_state.in_scale) intel_state.base = i386_regtab + reg_num; @@ -406,7 +418,19 @@ static int i386_intel_simplify (expressionS *e) intel_state.index)) return 0; if (!intel_state.in_offset) - intel_state.seg = e->X_add_symbol; + { + if (!intel_state.seg) + intel_state.seg = e->X_add_symbol; + else + { + expressionS exp; + + exp.X_op = O_full_ptr; + exp.X_add_symbol = e->X_add_symbol; + exp.X_op_symbol = intel_state.seg; + intel_state.seg = make_expr_symbol (&exp); + } + } i386_intel_fold (e, e->X_op_symbol); break; @@ -432,7 +456,7 @@ static int i386_intel_simplify (expressionS *e) { resolve_expression (scale); if (scale->X_op != O_constant - || intel_state.index->reg_type.bitfield.reg16) + || intel_state.index->reg_type.bitfield.word) scale->X_add_number = 0; intel_state.scale_factor *= scale->X_add_number; } @@ -573,12 +597,14 @@ i386_intel_operand (char *operand_string, int got_a_float) if (!is_end_of_line[(unsigned char) *input_line_pointer]) { - as_bad (_("junk `%s' after expression"), input_line_pointer); + if (ret) + 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")); + if (ret) + as_bad (_("invalid expression")); ret = 0; } else if (!intel_state.has_offset @@ -677,17 +703,14 @@ i386_intel_operand (char *operand_string, int got_a_float) 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_zmmword_ptr: i.types[this_operand].bitfield.zmmword = 1; - suffix = ZMMWORD_MNEM_SUFFIX; break; case O_far_ptr: @@ -816,6 +839,8 @@ i386_intel_operand (char *operand_string, int got_a_float) || intel_state.is_mem) { /* Memory operand. */ + if (i.mem_operands == 1 && !maybe_adjust_templates ()) + return 0; if ((int) i.mem_operands >= 2 - !current_templates->start->opcode_modifier.isstring) { @@ -855,7 +880,7 @@ i386_intel_operand (char *operand_string, int got_a_float) i.mem_operands = 0; i.disp_operands = 0; i.imm_operands = 2; - i.types[0].bitfield.mem = 0; + i.flags[0] &= ~Operand_Mem; i.types[0].bitfield.disp16 = 0; i.types[0].bitfield.disp32 = 0; i.types[0].bitfield.disp32s = 0; @@ -869,18 +894,41 @@ i386_intel_operand (char *operand_string, int got_a_float) return 0; } + /* 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 this here. */ + if (intel_state.base + && intel_state.index + && intel_state.base->reg_type.bitfield.word + && intel_state.index->reg_type.bitfield.word + && 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 (i.base_reg || i.index_reg) + i.types[this_operand].bitfield.baseindex = 1; + 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.types[this_operand].bitfield.baseindex) { i.op[this_operand].disps = expP; i.disp_operands++; + i386_addressing_mode (); + if (flag_code == CODE_64BIT) { i.types[this_operand].bitfield.disp32 = 1; @@ -920,15 +968,14 @@ i386_intel_operand (char *operand_string, int got_a_float) return 0; } - if (intel_state.base || intel_state.index) - i.types[this_operand].bitfield.baseindex = 1; - if (intel_state.seg) { - for (;;) + for (ret = check_none; ; ret = operand_check) { expP = symbol_get_value_expression (intel_state.seg); - if (expP->X_op != O_full_ptr) + if (expP->X_op != O_full_ptr + || symbol_get_value_expression (expP->X_op_symbol)->X_op + != O_register) break; intel_state.seg = expP->X_add_symbol; } @@ -943,6 +990,15 @@ i386_intel_operand (char *operand_string, int got_a_float) as_bad (_("invalid use of register")); return 0; } + switch (ret) + { + case check_error: + as_bad (_("redundant segment overrides")); + return 0; + case check_warning: + as_warn (_("redundant segment overrides")); + break; + } switch (i386_regtab[expP->X_add_number].reg_num) { case 0: i.seg[i.mem_operands] = &es; break; @@ -955,29 +1011,12 @@ i386_intel_operand (char *operand_string, int got_a_float) } } - /* 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.flags[this_operand] |= Operand_Mem; + if (i.mem_operands == 0) + i.memop1_string = xstrdup (operand_string); ++i.mem_operands; } else