From 01c99892ca5608241653b86bf9e3145e24a552b2 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 3 Jan 2015 00:00:20 +0000 Subject: [PATCH] [X86] Disassembler support for move to/from %rax with a 32-bit memory offset is REX.W and AdSize prefix are both present. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225099 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/AsmParser/X86Operand.h | 3 +++ .../Disassembler/X86DisassemblerDecoderCommon.h | 2 ++ lib/Target/X86/X86InstrInfo.td | 17 +++++++++++++++++ test/MC/Disassembler/X86/prefixes.txt | 4 ++-- test/MC/Disassembler/X86/x86-64.txt | 12 ++++++++++++ utils/TableGen/X86DisassemblerTables.cpp | 10 ++++++++-- utils/TableGen/X86RecognizableInstr.cpp | 4 ++++ 7 files changed, 48 insertions(+), 4 deletions(-) diff --git a/lib/Target/X86/AsmParser/X86Operand.h b/lib/Target/X86/AsmParser/X86Operand.h index 04614332755..4362fc5026d 100644 --- a/lib/Target/X86/AsmParser/X86Operand.h +++ b/lib/Target/X86/AsmParser/X86Operand.h @@ -316,6 +316,9 @@ struct X86Operand : public MCParsedAsmOperand { bool isMemOffs32_32() const { return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 32); } + bool isMemOffs32_64() const { + return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 64); + } bool isMemOffs64_8() const { return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 8); } diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h index d04d8c0f063..3e8172e6cee 100644 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h +++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h @@ -93,6 +93,8 @@ enum attributeBits { "operands change width") \ ENUM_ENTRY(IC_64BIT_REXW, 5, "requires a REX.W prefix, so operands "\ "change width; overrides IC_OPSIZE") \ + ENUM_ENTRY(IC_64BIT_REXW_ADSIZE, 6, "requires a REX.W prefix and 0x67 " \ + "prefix") \ ENUM_ENTRY(IC_64BIT_OPSIZE, 3, "Just as meaningful as IC_OPSIZE") \ ENUM_ENTRY(IC_64BIT_ADSIZE, 3, "Just as meaningful as IC_ADSIZE") \ ENUM_ENTRY(IC_64BIT_OPSIZE_ADSIZE, 4, "Just as meaningful as IC_OPSIZE/" \ diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 0efbd06548b..5a9b51aa0cc 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -494,6 +494,11 @@ def X86MemOffs32_32AsmOperand : AsmOperandClass { let RenderMethod = "addMemOffsOperands"; let SuperClasses = [X86Mem32AsmOperand]; } +def X86MemOffs32_64AsmOperand : AsmOperandClass { + let Name = "MemOffs32_64"; + let RenderMethod = "addMemOffsOperands"; + let SuperClasses = [X86Mem64AsmOperand]; +} def X86MemOffs64_8AsmOperand : AsmOperandClass { let Name = "MemOffs64_8"; let RenderMethod = "addMemOffsOperands"; @@ -571,6 +576,10 @@ def offset32_32 : Operand { let ParserMatchClass = X86MemOffs32_32AsmOperand; let MIOperandInfo = (ops i64imm, i8imm); let PrintMethod = "printMemOffs32"; } +def offset32_64 : Operand { + let ParserMatchClass = X86MemOffs32_64AsmOperand; + let MIOperandInfo = (ops i64imm, i8imm); + let PrintMethod = "printMemOffs64"; } def offset64_8 : Operand { let ParserMatchClass = X86MemOffs64_8AsmOperand; let MIOperandInfo = (ops i64imm, i8imm); @@ -1318,6 +1327,10 @@ let Defs = [EAX] in def MOV32ao32 : Ii32<0xA1, RawFrmMemOffs, (outs), (ins offset32_32:$src), "mov{l}\t{$src, %eax|eax, $src}", [], IIC_MOV_MEM>, OpSize32, AdSize32; +let Defs = [RAX] in +def MOV64ao32 : RIi32<0xA1, RawFrmMemOffs, (outs), (ins offset32_64:$src), + "mov{q}\t{$src, %rax|rax, $src}", [], IIC_MOV_MEM>, + AdSize32; let Defs = [AL] in def MOV8ao16 : Ii16<0xA0, RawFrmMemOffs, (outs), (ins offset16_8:$src), @@ -1343,6 +1356,10 @@ let Uses = [EAX] in def MOV32o32a : Ii32<0xA3, RawFrmMemOffs, (outs offset32_32:$dst), (ins), "mov{l}\t{%eax, $dst|$dst, eax}", [], IIC_MOV_MEM>, OpSize32, AdSize32; +let Uses = [RAX] in +def MOV64o32a : RIi32<0xA3, RawFrmMemOffs, (outs offset32_64:$dst), (ins), + "mov{q}\t{%rax, $dst|$dst, rax}", [], IIC_MOV_MEM>, + AdSize32; let Uses = [AL] in def MOV8o16a : Ii16<0xA2, RawFrmMemOffs, (outs offset16_8:$dst), (ins), diff --git a/test/MC/Disassembler/X86/prefixes.txt b/test/MC/Disassembler/X86/prefixes.txt index ee0ba086618..9e002fab465 100644 --- a/test/MC/Disassembler/X86/prefixes.txt +++ b/test/MC/Disassembler/X86/prefixes.txt @@ -8,11 +8,11 @@ 0x64 0x48 0x8b 0x3c 0x25 0x00 0x03 0x00 0x00 # CHECK: rep -# CHECK-NEXT: stosq +# CHECK-NEXT: stosq %rax, %es:(%rdi) 0xf3 0x48 0xab # CHECK: rep -# CHECK-NEXT: stosl +# CHECK-NEXT: stosq %rax, %es:(%edi) 0xf3 0x67 0x48 0xab # CHECK: movl 32(%rbp), %eax diff --git a/test/MC/Disassembler/X86/x86-64.txt b/test/MC/Disassembler/X86/x86-64.txt index 6f072df7e4b..70c8ae0dcc0 100644 --- a/test/MC/Disassembler/X86/x86-64.txt +++ b/test/MC/Disassembler/X86/x86-64.txt @@ -265,3 +265,15 @@ # CHECK: $0, 305419896(%rbp) 0x80 0x84 0x25 0x78 0x56 0x34 0x12 0x00 + +# CHECK: movabsq 6510615555426900570, %rax +0x48 0xa1 0x5a 0x5a 0x5a 0x5a 0x5a 0x5a 0x5a 0x5a + +# CHECK: movq 1515870810, %rax +0x67, 0x48 0xa1 0x5a 0x5a 0x5a 0x5a + +# CHECK: movabsq %rax, 6510615555426900570 +0x48 0xa3 0x5a 0x5a 0x5a 0x5a 0x5a 0x5a 0x5a 0x5a + +# CHECK: movq %rax, 1515870810 +0x67, 0x48 0xa3 0x5a 0x5a 0x5a 0x5a diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index 138a34b4dc9..fbe5502bc90 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -114,10 +114,12 @@ static inline bool inheritsFrom(InstructionContext child, case IC_64BIT_REXW: return(inheritsFrom(child, IC_64BIT_REXW_XS) || inheritsFrom(child, IC_64BIT_REXW_XD) || - inheritsFrom(child, IC_64BIT_REXW_OPSIZE)); + inheritsFrom(child, IC_64BIT_REXW_OPSIZE) || + (!AdSize64 && inheritsFrom(child, IC_64BIT_REXW_ADSIZE))); case IC_64BIT_OPSIZE: return inheritsFrom(child, IC_64BIT_REXW_OPSIZE) || - (!AdSize64 && inheritsFrom(child, IC_64BIT_OPSIZE_ADSIZE)); + (!AdSize64 && inheritsFrom(child, IC_64BIT_OPSIZE_ADSIZE)) || + (!AdSize64 && inheritsFrom(child, IC_64BIT_REXW_ADSIZE)); case IC_64BIT_XD: return(inheritsFrom(child, IC_64BIT_REXW_XD)); case IC_64BIT_XS: @@ -128,6 +130,7 @@ static inline bool inheritsFrom(InstructionContext child, case IC_64BIT_REXW_XD: case IC_64BIT_REXW_XS: case IC_64BIT_REXW_OPSIZE: + case IC_64BIT_REXW_ADSIZE: return false; case IC_VEX: return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W)) || @@ -720,6 +723,9 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const { else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) o << "IC_64BIT_REXW_OPSIZE"; + else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && + (index & ATTR_ADSIZE)) + o << "IC_64BIT_REXW_ADSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE)) o << "IC_64BIT_XD_OPSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE)) diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index 91c64aa049e..56976d3ec38 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -408,6 +408,8 @@ InstructionContext RecognizableInstr::insnContext() const { } else if (Is64Bit || HasREX_WPrefix || AdSize == X86Local::AdSize64) { if (HasREX_WPrefix && (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD)) insnContext = IC_64BIT_REXW_OPSIZE; + else if (HasREX_WPrefix && AdSize == X86Local::AdSize32) + insnContext = IC_64BIT_REXW_ADSIZE; else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XD) insnContext = IC_64BIT_XD_OPSIZE; else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS) @@ -984,6 +986,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("offset32_8", TYPE_MOFFS8) TYPE("offset32_16", TYPE_MOFFS16) TYPE("offset32_32", TYPE_MOFFS32) + TYPE("offset32_64", TYPE_MOFFS64) TYPE("offset64_8", TYPE_MOFFS8) TYPE("offset64_16", TYPE_MOFFS16) TYPE("offset64_32", TYPE_MOFFS32) @@ -1219,6 +1222,7 @@ RecognizableInstr::relocationEncodingFromString(const std::string &s, ENCODING("offset32_8", ENCODING_Ia) ENCODING("offset32_16", ENCODING_Ia) ENCODING("offset32_32", ENCODING_Ia) + ENCODING("offset32_64", ENCODING_Ia) ENCODING("offset64_8", ENCODING_Ia) ENCODING("offset64_16", ENCODING_Ia) ENCODING("offset64_32", ENCODING_Ia)