X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-i386-intel.c;h=49f558d2785e2beea033c7ff4978f36fb4cfd84f;hb=0cfa3eb3525d46ff6cfc94559a796c6a67bdcb27;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..49f558d278 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) @@ -272,7 +283,7 @@ i386_intel_simplify_register (expressionS *e) as_bad (_("invalid use of register")); return 0; } - if (i386_regtab[reg_num].reg_type.bitfield.sreg3 + if (i386_regtab[reg_num].reg_type.bitfield.class == SReg && i386_regtab[reg_num].reg_num == RegFlat) { as_bad (_("invalid use of pseudo-register")); @@ -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 @@ -632,8 +658,9 @@ i386_intel_operand (char *operand_string, int got_a_float) || 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)) + && (current_templates->start->opcode_modifier.jump == JUMP + || current_templates->start->opcode_modifier.jump + == JUMP_DWORD)) suffix = LONG_DOUBLE_MNEM_SUFFIX; else if (got_a_float == 1) /* "f..." */ suffix = SHORT_MNEM_SUFFIX; @@ -677,25 +704,22 @@ 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: suffix = LONG_DOUBLE_MNEM_SUFFIX; /* FALLTHROUGH */ case O_near_ptr: - if (!current_templates->start->opcode_modifier.jump - && !current_templates->start->opcode_modifier.jumpdword) + if (current_templates->start->opcode_modifier.jump != JUMP + && current_templates->start->opcode_modifier.jump != JUMP_DWORD) suffix = got_a_float /* so it will cause an error */ ? BYTE_MNEM_SUFFIX : LONG_DOUBLE_MNEM_SUFFIX; @@ -716,21 +740,23 @@ i386_intel_operand (char *operand_string, int got_a_float) } /* 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 (current_templates->start->opcode_modifier.jump == JUMP + || current_templates->start->opcode_modifier.jump == JUMP_DWORD + || current_templates->start->opcode_modifier.jump == JUMP_INTERSEGMENT) { + bfd_boolean jumpabsolute = FALSE; + if (i.op[this_operand].regs || intel_state.base || intel_state.index || intel_state.is_mem > 1) - i.types[this_operand].bitfield.jumpabsolute = 1; + jumpabsolute = TRUE; else switch (intel_state.op_modifier) { case O_near_ptr: if (intel_state.seg) - i.types[this_operand].bitfield.jumpabsolute = 1; + jumpabsolute = TRUE; else intel_state.is_mem = 1; break; @@ -742,14 +768,14 @@ i386_intel_operand (char *operand_string, int got_a_float) if (intel_state.op_modifier == O_absent) { if (intel_state.is_indirect == 1) - i.types[this_operand].bitfield.jumpabsolute = 1; + jumpabsolute = TRUE; 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; + jumpabsolute = TRUE; else { i386_operand_type types; @@ -783,11 +809,14 @@ i386_intel_operand (char *operand_string, int got_a_float) } break; default: - i.types[this_operand].bitfield.jumpabsolute = 1; + jumpabsolute = TRUE; break; } - if (i.types[this_operand].bitfield.jumpabsolute) - intel_state.is_mem |= 1; + if (jumpabsolute) + { + i.jumpabsolute = TRUE; + intel_state.is_mem |= 1; + } } else if (intel_state.seg) intel_state.is_mem |= 1; @@ -816,6 +845,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) { @@ -827,9 +858,9 @@ i386_intel_operand (char *operand_string, int got_a_float) ljmp 0x9090,0x90909090 */ - if ((current_templates->start->opcode_modifier.jumpintersegment - || current_templates->start->opcode_modifier.jumpdword - || current_templates->start->opcode_modifier.jump) + if ((current_templates->start->opcode_modifier.jump == JUMP_INTERSEGMENT + || current_templates->start->opcode_modifier.jump == JUMP_DWORD + || current_templates->start->opcode_modifier.jump == JUMP) && this_operand == 1 && intel_state.seg == NULL && i.mem_operands == 1 @@ -855,7 +886,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 +900,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 +974,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; } @@ -937,12 +990,20 @@ i386_intel_operand (char *operand_string, int got_a_float) 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) + if (i386_regtab[expP->X_add_number].reg_type.bitfield.class != SReg) { 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 +1016,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