[PATCH v2 2/2] x86: fold AddrPrefixOpReg templates
Jan Beulich
jbeulich@suse.com
Fri Feb 14 12:47:00 GMT 2020
More information about the Binutils mailing list
Fri Feb 14 12:47:00 GMT 2020
- Previous message (by thread): [PATCH v2 0/2] x86: MONITOR and alike adjustments
- Next message (by thread): [PATCH v2 1/2] x86/Intel: don't swap operands of MONITOR{,X} and MWAIT{,X}
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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/ 2020-02-XX Jan Beulich <jbeulich@suse.com> * 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. opcodes/ 2020-02-XX Jan Beulich <jbeulich@suse.com> * i386-opc.tbl (AddrPrefixOpReg): Define. (monitor, invlpga, vmload, vmrun, vmsave, clzero, monitorx, umonitor, movdir64b, enqcmd, enqcmds): Fold Cpu64 and CpuNo64 templates. Drop NoRex64. * i386-tbl.h: Re-generate. --- v2: New. --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -6297,7 +6297,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; --- a/opcodes/i386-opc.tbl +++ b/opcodes/i386-opc.tbl @@ -72,6 +72,8 @@ #define IsStringEsOp0 IsString=IS_STRING_ES_OP0 #define IsStringEsOp1 IsString=IS_STRING_ES_OP1 +#define AddrPrefixOpReg AddrPrefixOpReg|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf + #define VexW0 VexW=VEXW0 #define VexW1 VexW=VEXW1 #define VexWIG VexW=VEXWIG @@ -1568,10 +1570,9 @@ monitor, 0, 0xf01c8, None, 3, CpuSSE3, N // monitor is very special. CX and DX are always 32 bits. The // address size override prefix can be used to overrride the AX size in // all modes. -monitor, 3, 0xf01c8, None, 3, CpuSSE3|CpuNo64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg|NoAVX, { Acc|Word|Dword, RegC|Dword, RegD|Dword } -monitor, 3, 0xf01c8, None, 3, CpuSSE3|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg|NoRex64|NoAVX, { Acc|Dword|Qword, RegC|Dword, RegD|Dword } +monitor, 3, 0xf01c8, None, 3, CpuSSE3, AddrPrefixOpReg|NoAVX, { Acc|Word|Dword|Qword, RegC|Dword, RegD|Dword } // The 64-bit form exists only for compatibility with older gas. -monitor, 3, 0xf01c8, None, 3, CpuSSE3|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg|NoRex64|NoAVX, { Acc|Dword|Qword, RegC|Qword, RegD|Qword } +monitor, 3, 0xf01c8, None, 3, CpuSSE3|Cpu64, AddrPrefixOpReg|NoAVX, { Acc|Dword|Qword, RegC|Qword, RegD|Qword } movddup, 2, 0xf212, None, 1, CpuAVX, Modrm|Vex|VexOpcode=0|VexW=1|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|SSE2AVX, { Qword|Unspecified|BaseIndex|RegXMM, RegXMM } movddup, 2, 0xf20f12, None, 2, CpuSSE3, Modrm|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Qword|Unspecified|BaseIndex|RegXMM, RegXMM } movshdup, 2, 0xf316, None, 1, CpuAVX, Modrm|Vex|VexOpcode=0|VexW=1|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|SSE2AVX, { RegXMM|Unspecified|BaseIndex, RegXMM } @@ -2824,21 +2825,17 @@ rdtscp, 0, 0xf01f9, None, 3, CpuRdtscp, // AMD Pacifica additions. clgi, 0, 0xf01dd, None, 3, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 } invlpga, 0, 0xf01df, None, 3, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 } -invlpga, 2, 0xf01df, None, 3, CpuSVME|CpuNo64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg, { Acc|Word|Dword, RegC|Dword } -invlpga, 2, 0xf01df, None, 3, CpuSVME|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg|NoRex64, { Acc|Dword|Qword, RegC|Dword } +invlpga, 2, 0xf01df, None, 3, CpuSVME, AddrPrefixOpReg, { Acc|Word|Dword|Qword, RegC|Dword } skinit, 0, 0xf01de, None, 3, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 } skinit, 1, 0xf01de, None, 3, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Acc|Dword } stgi, 0, 0xf01dc, None, 3, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 } vmload, 0, 0xf01da, None, 3, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 } -vmload, 1, 0xf01da, None, 3, CpuSVME|CpuNo64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg, { Acc|Word|Dword } -vmload, 1, 0xf01da, None, 3, CpuSVME|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg|NoRex64, { Acc|Dword|Qword } +vmload, 1, 0xf01da, None, 3, CpuSVME, AddrPrefixOpReg, { Acc|Word|Dword|Qword } vmmcall, 0, 0xf01d9, None, 3, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 } vmrun, 0, 0xf01d8, None, 3, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 } -vmrun, 1, 0xf01d8, None, 3, CpuSVME|CpuNo64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg, { Acc|Word|Dword } -vmrun, 1, 0xf01d8, None, 3, CpuSVME|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg|NoRex64, { Acc|Dword|Qword } +vmrun, 1, 0xf01d8, None, 3, CpuSVME, AddrPrefixOpReg, { Acc|Word|Dword|Qword } vmsave, 0, 0xf01db, None, 3, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 } -vmsave, 1, 0xf01db, None, 3, CpuSVME|CpuNo64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg, { Acc|Word|Dword } -vmsave, 1, 0xf01db, None, 3, CpuSVME|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg|NoRex64, { Acc|Dword|Qword } +vmsave, 1, 0xf01db, None, 3, CpuSVME, AddrPrefixOpReg, { Acc|Word|Dword|Qword } // SSE4a instructions @@ -4683,18 +4680,16 @@ vpclmulhqhqdq, 3, 0x6644, 0x11, 1, CpuVP // CLZERO instructions clzero, 0, 0xf01fc, None, 3, CpuCLZERO, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 } -clzero, 1, 0xf01fc, None, 3, CpuCLZERO|CpuNo64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg, { Acc|Word|Dword } -clzero, 1, 0xf01fc, None, 3, CpuCLZERO|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg|NoRex64, { Acc|Dword|Qword } +clzero, 1, 0xf01fc, None, 3, CpuCLZERO, AddrPrefixOpReg, { Acc|Word|Dword|Qword } // CLZERO instructions end // MONITORX/MWAITX instructions monitorx, 0, 0xf01fa, None, 3, CpuMWAITX, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 } -monitorx, 3, 0xf01fa, None, 3, CpuMWAITX|CpuNo64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg, { Acc|Word|Dword, RegC|Dword, RegD|Dword } -monitorx, 3, 0xf01fa, None, 3, CpuMWAITX|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg|NoRex64, { Acc|Dword|Qword, RegC|Dword, RegD|Dword } +monitorx, 3, 0xf01fa, None, 3, CpuMWAITX, AddrPrefixOpReg, { Acc|Word|Dword|Qword, RegC|Dword, RegD|Dword } // The 64-bit form exists only for compatibility with older gas. -monitorx, 3, 0xf01fa, None, 3, CpuMWAITX|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg|NoRex64, { Acc|Dword|Qword, RegC|Qword, RegD|Qword } +monitorx, 3, 0xf01fa, None, 3, CpuMWAITX|Cpu64, AddrPrefixOpReg, { Acc|Dword|Qword, RegC|Qword, RegD|Qword } mwaitx, 0, 0xf01fb, None, 3, CpuMWAITX, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 } // The 64-bit form exists only for compatibility with older gas. @@ -4758,8 +4753,7 @@ pconfig, 0, 0x0f01c5, None, 3, CpuPCONFI // WAITPKG instructions. -umonitor, 1, 0xf30fae, 0x6, 2, CpuWAITPKG|CpuNo64, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg, { Reg16|Reg32 } -umonitor, 1, 0xf30fae, 0x6, 2, CpuWAITPKG|Cpu64, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg|NoRex64, { Reg32|Reg64 } +umonitor, 1, 0xf30fae, 0x6, 2, CpuWAITPKG, Modrm|AddrPrefixOpReg, { Reg16|Reg32|Reg64 } tpause, 1, 0x660fae, 0x6, 2, CpuWAITPKG, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|NoRex64, { Reg32|Reg64 } @@ -4777,8 +4771,7 @@ cldemote, 1, 0x0f1c, 0x0, 2, CpuCLDEMOTE movdiri, 2, 0xf38f9, None, 3, CpuMOVDIRI, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg32|Reg64, Dword|Qword|Unspecified|BaseIndex } -movdir64b, 2, 0x660f38f8, None, 3, CpuMOVDIR64B|CpuNo64, Modrm|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg, { Unspecified|BaseIndex, Reg16|Reg32 } -movdir64b, 2, 0x660f38f8, None, 3, CpuMOVDIR64B|Cpu64, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|NoRex64|AddrPrefixOpReg, { Unspecified|BaseIndex, Reg32|Reg64 } +movdir64b, 2, 0x660f38f8, None, 3, CpuMOVDIR64B, Modrm|AddrPrefixOpReg, { Unspecified|BaseIndex, Reg16|Reg32|Reg64 } // MOVEDIR instructions end. @@ -4798,10 +4791,8 @@ vdpbf16ps, 3, 0xf352, None, 1, CpuAVX512 // ENQCMD instructions. -enqcmd, 2, 0xf20f38f8, None, 3, CpuENQCMD|CpuNo64, Modrm|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg, { Unspecified|BaseIndex, Reg16|Reg32 } -enqcmd, 2, 0xf20f38f8, None, 3, CpuENQCMD|Cpu64, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|NoRex64|AddrPrefixOpReg, { Unspecified|BaseIndex, Reg32|Reg64 } -enqcmds, 2, 0xf30f38f8, None, 3, CpuENQCMD|CpuNo64, Modrm|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|AddrPrefixOpReg, { Unspecified|BaseIndex, Reg16|Reg32 } -enqcmds, 2, 0xf30f38f8, None, 3, CpuENQCMD|Cpu64, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|NoRex64|AddrPrefixOpReg, { Unspecified|BaseIndex, Reg32|Reg64 } +enqcmd, 2, 0xf20f38f8, None, 3, CpuENQCMD, Modrm|AddrPrefixOpReg, { Unspecified|BaseIndex, Reg16|Reg32|Reg64 } +enqcmds, 2, 0xf30f38f8, None, 3, CpuENQCMD, Modrm|AddrPrefixOpReg, { Unspecified|BaseIndex, Reg16|Reg32|Reg64 } // ENQCMD instructions end.
- Previous message (by thread): [PATCH v2 0/2] x86: MONITOR and alike adjustments
- Next message (by thread): [PATCH v2 1/2] x86/Intel: don't swap operands of MONITOR{,X} and MWAIT{,X}
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Binutils mailing list