From c8f8eebc3fc3662fdb9077355ecde9c88bd33727 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 17 Feb 2020 08:59:07 +0100 Subject: x86: fold AddrPrefixOpReg templates There's no need to have separate Cpu64 and CpuNo64 templates: There already is special logic handling the attribute, and all that's needed is rejecting 16-bit address registers in 64-bit mode. Suppress suffix guessing and group all involved logic together, outside of suffix processing (arguably it doesn't even belong in process_suffix()). Also, since no AddrPrefixOpReg template permits any suffixes, move the No_*Suf specifiers for them to a central place. Along with this drop the no longer relevant NoRex64 from there. --- gas/ChangeLog | 7 ++++ gas/config/tc-i386.c | 113 +++++++++++++++++++++++++++++---------------------- 2 files changed, 72 insertions(+), 48 deletions(-) (limited to 'gas') diff --git a/gas/ChangeLog b/gas/ChangeLog index 112aedb..b6ce3ef 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,12 @@ 2020-02-17 Jan Beulich + * config/tc-i386.c (process_suffix): Don't try to guess a suffix + for AddrPrefixOpReg templates. Combine the two pieces of + addrprefixopreg handling. Reject 16-bit address reg in 64-bit + mode. + +2020-02-17 Jan Beulich + PR gas/14439 * config/tc-i386.c (md_assemble): Also suppress operand swapping for MONITOR{,X} and MWAIT{,X}. diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 4074a90..c4c94ca 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -6298,7 +6298,8 @@ process_suffix (void) else if (i.tm.opcode_modifier.size == SIZE64) i.suffix = QWORD_MNEM_SUFFIX; else if (i.reg_operands - && (i.operands > 1 || i.types[0].bitfield.class == Reg)) + && (i.operands > 1 || i.types[0].bitfield.class == Reg) + && !i.tm.opcode_modifier.addrprefixopreg) { unsigned int numop = i.operands; @@ -6613,28 +6614,13 @@ process_suffix (void) /* Now select between word & dword operations via the operand size prefix, except for instructions that will ignore this prefix anyway. */ - if (i.reg_operands > 0 - && i.types[0].bitfield.class == Reg - && i.tm.opcode_modifier.addrprefixopreg - && (i.tm.operand_types[0].bitfield.instance == Accum - || i.operands == 1)) - { - /* The address size override prefix changes the size of the - first operand. */ - if ((flag_code == CODE_32BIT - && i.op[0].regs->reg_type.bitfield.word) - || (flag_code != CODE_32BIT - && i.op[0].regs->reg_type.bitfield.dword)) - if (!add_prefix (ADDR_PREFIX_OPCODE)) - return 0; - } - else if (i.suffix != QWORD_MNEM_SUFFIX - && !i.tm.opcode_modifier.ignoresize - && !i.tm.opcode_modifier.floatmf - && !is_any_vex_encoding (&i.tm) - && ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT) - || (flag_code == CODE_64BIT - && i.tm.opcode_modifier.jump == JUMP_BYTE))) + if (i.suffix != QWORD_MNEM_SUFFIX + && !i.tm.opcode_modifier.ignoresize + && !i.tm.opcode_modifier.floatmf + && !is_any_vex_encoding (&i.tm) + && ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT) + || (flag_code == CODE_64BIT + && i.tm.opcode_modifier.jump == JUMP_BYTE))) { unsigned int prefix = DATA_PREFIX_OPCODE; @@ -6663,39 +6649,70 @@ process_suffix (void) break; } - if (i.reg_operands != 0 - && i.operands > 1 - && i.tm.opcode_modifier.addrprefixopreg - && i.tm.operand_types[0].bitfield.instance != Accum) + if (i.tm.opcode_modifier.addrprefixopreg) { - /* Check invalid register operand when the address size override - prefix changes the size of register operands. */ - unsigned int op; - enum { need_word, need_dword, need_qword } need; + gas_assert (!i.suffix); + gas_assert (i.reg_operands); + + if (i.tm.operand_types[0].bitfield.instance == Accum + || i.operands == 1) + { + /* The address size override prefix changes the size of the + first operand. */ + if (flag_code == CODE_64BIT + && i.op[0].regs->reg_type.bitfield.word) + { + as_bad (_("16-bit addressing unavailable for `%s'"), + i.tm.name); + return 0; + } - if (flag_code == CODE_32BIT) - need = i.prefix[ADDR_PREFIX] ? need_word : need_dword; + if ((flag_code == CODE_32BIT + ? i.op[0].regs->reg_type.bitfield.word + : i.op[0].regs->reg_type.bitfield.dword) + && !add_prefix (ADDR_PREFIX_OPCODE)) + return 0; + } else { - if (i.prefix[ADDR_PREFIX]) + /* Check invalid register operand when the address size override + prefix changes the size of register operands. */ + unsigned int op; + enum { need_word, need_dword, need_qword } need; + + if (flag_code == CODE_32BIT) + need = i.prefix[ADDR_PREFIX] ? need_word : need_dword; + else if (i.prefix[ADDR_PREFIX]) need = need_dword; else need = flag_code == CODE_64BIT ? need_qword : need_word; - } - for (op = 0; op < i.operands; op++) - if (i.types[op].bitfield.class == Reg - && ((need == need_word - && !i.op[op].regs->reg_type.bitfield.word) - || (need == need_dword - && !i.op[op].regs->reg_type.bitfield.dword) - || (need == need_qword - && !i.op[op].regs->reg_type.bitfield.qword))) - { - as_bad (_("invalid register operand size for `%s'"), - i.tm.name); - return 0; - } + for (op = 0; op < i.operands; op++) + { + if (i.types[op].bitfield.class != Reg) + continue; + + switch (need) + { + case need_word: + if (i.op[op].regs->reg_type.bitfield.word) + continue; + break; + case need_dword: + if (i.op[op].regs->reg_type.bitfield.dword) + continue; + break; + case need_qword: + if (i.op[op].regs->reg_type.bitfield.qword) + continue; + break; + } + + as_bad (_("invalid register operand size for `%s'"), + i.tm.name); + return 0; + } + } } return 1; -- cgit v1.1