X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-i386-intel.c;h=3c01b5ee9e27696b3bfc5e8a4311c2b4b126e7f0;hb=9a01ec4c0368048fb5ea1ba1b3af9afbd651b529;hp=b55d985f5a068c724483e1c38215b518b2c06f22;hpb=4b95cf5c0c75d6efc1b2f96af72317aecca079f1;p=binutils-gdb.git diff --git a/gas/config/tc-i386-intel.c b/gas/config/tc-i386-intel.c index b55d985f5a0..3c01b5ee9e2 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-2014 Free Software Foundation, Inc. + Copyright (C) 2009-2021 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). */ @@ -52,18 +52,20 @@ intel_state; #define O_dword_ptr O_md26 /* qword ptr X_add_symbol */ #define O_qword_ptr O_md25 -/* oword ptr X_add_symbol */ -#define O_oword_ptr O_md24 +/* mmword ptr X_add_symbol */ +#define O_mmword_ptr O_qword_ptr /* fword ptr X_add_symbol */ -#define O_fword_ptr O_md23 +#define O_fword_ptr O_md24 /* tbyte ptr X_add_symbol */ -#define O_tbyte_ptr O_md22 +#define O_tbyte_ptr O_md23 +/* oword ptr X_add_symbol */ +#define O_oword_ptr O_md22 /* xmmword ptr X_add_symbol */ -#define O_xmmword_ptr O_md21 +#define O_xmmword_ptr O_oword_ptr /* ymmword ptr X_add_symbol */ -#define O_ymmword_ptr O_md20 +#define O_ymmword_ptr O_md21 /* zmmword ptr X_add_symbol */ -#define O_zmmword_ptr O_md19 +#define O_zmmword_ptr O_md20 static struct { @@ -105,6 +107,7 @@ const i386_types[] = I386_TYPE(dword, 4), I386_TYPE(fword, 6), I386_TYPE(qword, 8), + I386_TYPE(mmword, 8), I386_TYPE(tbyte, 10), I386_TYPE(oword, 16), I386_TYPE(xmmword, 16), @@ -120,6 +123,16 @@ operatorT i386_operator (const char *name, unsigned int operands, char *pc) { unsigned int j; +#ifdef SVR4_COMMENT_CHARS + if (!name && operands == 2 && *input_line_pointer == '\\') + switch (input_line_pointer[1]) + { + case '/': input_line_pointer += 2; return O_divide; + case '%': input_line_pointer += 2; return O_modulus; + case '*': input_line_pointer += 2; return O_multiply; + } +#endif + if (!intel_syntax) return O_absent; @@ -141,9 +154,7 @@ operatorT i386_operator (const char *name, unsigned int operands, char *pc) int adjust = 0; char *gotfree_input_line = lex_got (&i.reloc[this_operand], &adjust, - &intel_state.reloc_types, - (i.bnd_prefix != NULL - || add_bnd_prefix)); + &intel_state.reloc_types); if (!gotfree_input_line) break; @@ -170,13 +181,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) @@ -184,7 +200,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; } @@ -267,6 +283,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) @@ -274,7 +296,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")); @@ -283,17 +305,24 @@ 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; else if (!intel_state.index) { + const insn_template *t = current_templates->start; + if (intel_state.in_scale - || current_templates->start->base_opcode == 0xf30f1b /* bndmk */ - || (current_templates->start->base_opcode & ~1) == 0x0f1a /* bnd{ld,st}x */ + || (t->opcode_modifier.opcodeprefix == PREFIX_0XF3 + && t->opcode_modifier.opcodespace == SPACE_0F + && t->base_opcode == 0x1b /* bndmk */) + || (t->opcode_modifier.opcodeprefix == PREFIX_NONE + && t->opcode_modifier.opcodespace == SPACE_0F + && (t->base_opcode & ~1) == 0x1a /* bnd{ld,st}x */) || i386_regtab[reg_num].reg_type.bitfield.baseindex) intel_state.index = i386_regtab + reg_num; else @@ -306,7 +335,7 @@ i386_intel_simplify_register (expressionS *e) else { /* esp is invalid as index */ - intel_state.index = i386_regtab + REGNAM_EAX + ESP_REG_NUM; + intel_state.index = reg_eax + ESP_REG_NUM; } return 2; } @@ -373,10 +402,9 @@ static int i386_intel_simplify (expressionS *e) case O_word_ptr: case O_dword_ptr: case O_fword_ptr: - case O_qword_ptr: + case O_qword_ptr: /* O_mmword_ptr */ case O_tbyte_ptr: - case O_oword_ptr: - case O_xmmword_ptr: + case O_oword_ptr: /* O_xmmword_ptr */ case O_ymmword_ptr: case O_zmmword_ptr: case O_near_ptr: @@ -408,7 +436,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; @@ -434,7 +474,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; } @@ -460,7 +500,7 @@ static int i386_intel_simplify (expressionS *e) break; default: /* esp is invalid as index */ - intel_state.index = i386_regtab + REGNAM_EAX + ESP_REG_NUM; + intel_state.index = reg_eax + ESP_REG_NUM; break; } @@ -485,7 +525,7 @@ static int i386_intel_simplify (expressionS *e) /* FALLTHROUGH */ default: -fallthrough: + fallthrough: if (e->X_add_symbol && !i386_intel_simplify_symbol (e->X_add_symbol)) return 0; @@ -575,12 +615,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 @@ -602,7 +644,8 @@ i386_intel_operand (char *operand_string, int got_a_float) return 0; if (intel_state.op_modifier != O_absent - && current_templates->start->base_opcode != 0x8d /* lea */) + && (current_templates->start->opcode_modifier.opcodespace != SPACE_BASE + || current_templates->start->base_opcode != 0x8d /* lea */)) { i.types[this_operand].bitfield.unspecified = 0; @@ -615,12 +658,7 @@ i386_intel_operand (char *operand_string, int got_a_float) 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..." */ + if (got_a_float == 2) /* "fi..." */ suffix = SHORT_MNEM_SUFFIX; else suffix = WORD_MNEM_SUFFIX; @@ -631,12 +669,15 @@ i386_intel_operand (char *operand_string, int got_a_float) 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 */) + || (current_templates->start->opcode_modifier.opcodespace == SPACE_BASE + && 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 (flag_code != CODE_32BIT + && (current_templates->start->opcode_modifier.jump == JUMP + || current_templates->start->opcode_modifier.jump + == JUMP_DWORD)) + suffix = flag_code == CODE_16BIT ? LONG_DOUBLE_MNEM_SUFFIX + : WORD_MNEM_SUFFIX; else if (got_a_float == 1) /* "f..." */ suffix = SHORT_MNEM_SUFFIX; else @@ -655,13 +696,12 @@ i386_intel_operand (char *operand_string, int got_a_float) 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: + case O_qword_ptr: /* O_mmword_ptr */ i.types[this_operand].bitfield.qword = 1; - if (current_templates->start->base_opcode == 0x62 /* bound */ + if ((current_templates->start->opcode_modifier.opcodespace == SPACE_BASE + && current_templates->start->base_opcode == 0x62 /* bound */) || got_a_float == 1) /* "f..." */ suffix = LONG_MNEM_SUFFIX; else @@ -672,35 +712,40 @@ i386_intel_operand (char *operand_string, int got_a_float) i.types[this_operand].bitfield.tbyte = 1; if (got_a_float == 1) suffix = LONG_DOUBLE_MNEM_SUFFIX; + else if ((current_templates->start->operand_types[0].bitfield.fword + || current_templates->start->operand_types[0].bitfield.tbyte + || current_templates->start->opcode_modifier.jump == JUMP_DWORD + || current_templates->start->opcode_modifier.jump == JUMP) + && flag_code == CODE_64BIT) + suffix = QWORD_MNEM_SUFFIX; /* l[fgs]s, [ls][gi]dt, call, jmp */ else - suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */ + i.types[this_operand].bitfield.byte = 1; /* cause an error */ break; - case O_oword_ptr: - case O_xmmword_ptr: + case O_oword_ptr: /* 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) - suffix = got_a_float /* so it will cause an error */ - ? BYTE_MNEM_SUFFIX - : LONG_DOUBLE_MNEM_SUFFIX; + if (current_templates->start->opcode_modifier.jump != JUMP + && current_templates->start->opcode_modifier.jump != JUMP_DWORD) + { + /* cause an error */ + i.types[this_operand].bitfield.byte = 1; + i.types[this_operand].bitfield.tbyte = 1; + suffix = i.suffix; + } break; default: @@ -718,21 +763,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) { + bool 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; @@ -744,14 +791,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; @@ -785,11 +832,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; @@ -818,6 +868,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) { @@ -829,9 +881,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 @@ -857,7 +909,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; @@ -871,26 +923,50 @@ 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; if (!i.prefix[ADDR_PREFIX]) { i.types[this_operand].bitfield.disp64 = 1; i.types[this_operand].bitfield.disp32s = 1; } + else + i.types[this_operand].bitfield.disp32 = 1; } else if (!i.prefix[ADDR_PREFIX] ^ (flag_code == CODE_16BIT)) i.types[this_operand].bitfield.disp32 = 1; @@ -922,15 +998,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; } @@ -939,47 +1014,32 @@ 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 (i386_regtab[expP->X_add_number].reg_num) + switch (ret) { - 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; + case check_error: + as_bad (_("redundant segment overrides")); + return 0; + case check_warning: + as_warn (_("redundant segment overrides")); + 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_regtab[expP->X_add_number].reg_num == RegFlat) + i.seg[i.mem_operands] = NULL; + else + i.seg[i.mem_operands] = &i386_regtab[expP->X_add_number]; } 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