From a4959f3f6eb9b6ab3cbbe085a2797208682e96c6 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sun, 25 Aug 2013 22:23:38 +0000 Subject: [PATCH] First round of fixes for the x86 fixes for the x86 move accumulator from/to memory offset instructions. -Assembly parser now properly check the size of the memory operation specified in intel syntax. So 'mov word ptr [5], al' is no longer accepted. -x86-32 disassembly of these instructions no longer sign extends the 32-bit address immediate based on size. -Intel syntax printing prints the ptr size and places brackets around the address immediate. Known remaining issues with these instructions: -Segment override prefix is not supported. PR16962 and PR16961. -Immediate size should be changed by address size prefix. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189201 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/AsmParser/X86AsmParser.cpp | 39 +++++++++++++++ .../X86/Disassembler/X86Disassembler.cpp | 29 +++++------ .../X86/InstPrinter/X86ATTInstPrinter.cpp | 16 ++++++ .../X86/InstPrinter/X86ATTInstPrinter.h | 16 +++++- .../X86/InstPrinter/X86IntelInstPrinter.cpp | 16 ++++++ .../X86/InstPrinter/X86IntelInstPrinter.h | 20 +++++++- lib/Target/X86/X86InstrInfo.td | 50 +++++++++++++++---- test/MC/Disassembler/X86/intel-syntax-32.txt | 26 ++++++++-- test/MC/Disassembler/X86/intel-syntax.txt | 30 +++++++++++ test/MC/Disassembler/X86/x86-32.txt | 18 +++++++ 10 files changed, 226 insertions(+), 34 deletions(-) diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index ced12fc9977..a090b336557 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -849,6 +849,23 @@ struct X86Operand : public MCParsedAsmOperand { !getMemIndexReg() && getMemScale() == 1; } + bool isMemOffs8() const { + return Kind == Memory && !getMemSegReg() && !getMemBaseReg() && + !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 8); + } + bool isMemOffs16() const { + return Kind == Memory && !getMemSegReg() && !getMemBaseReg() && + !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 16); + } + bool isMemOffs32() const { + return Kind == Memory && !getMemSegReg() && !getMemBaseReg() && + !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 32); + } + bool isMemOffs64() const { + return Kind == Memory && !getMemSegReg() && !getMemBaseReg() && + !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 64); + } + bool isReg() const { return Kind == Register; } void addExpr(MCInst &Inst, const MCExpr *Expr) const { @@ -931,6 +948,28 @@ struct X86Operand : public MCParsedAsmOperand { Inst.addOperand(MCOperand::CreateExpr(getMemDisp())); } + void addMemOffs8Operands(MCInst &Inst, unsigned N) const { + addMemOffsOperands(Inst, N); + } + void addMemOffs16Operands(MCInst &Inst, unsigned N) const { + addMemOffsOperands(Inst, N); + } + void addMemOffs32Operands(MCInst &Inst, unsigned N) const { + addMemOffsOperands(Inst, N); + } + void addMemOffs64Operands(MCInst &Inst, unsigned N) const { + addMemOffsOperands(Inst, N); + } + + void addMemOffsOperands(MCInst &Inst, unsigned N) const { + assert((N == 1) && "Invalid number of operands!"); + // Add as immediates when possible. + if (const MCConstantExpr *CE = dyn_cast(getMemDisp())) + Inst.addOperand(MCOperand::CreateImm(CE->getValue())); + else + Inst.addOperand(MCOperand::CreateExpr(getMemDisp())); + } + static X86Operand *CreateToken(StringRef Str, SMLoc Loc) { SMLoc EndLoc = SMLoc::getFromPointer(Loc.getPointer() + Str.size()); X86Operand *Res = new X86Operand(Token, Loc, EndLoc); diff --git a/lib/Target/X86/Disassembler/X86Disassembler.cpp b/lib/Target/X86/Disassembler/X86Disassembler.cpp index 9cda49c361b..903e36cfe6c 100644 --- a/lib/Target/X86/Disassembler/X86Disassembler.cpp +++ b/lib/Target/X86/Disassembler/X86Disassembler.cpp @@ -231,16 +231,18 @@ static void translateImmediate(MCInst &mcInst, uint64_t immediate, default: break; case 1: - type = TYPE_MOFFS8; + if(immediate & 0x80) + immediate |= ~(0xffull); break; case 2: - type = TYPE_MOFFS16; + if(immediate & 0x8000) + immediate |= ~(0xffffull); break; case 4: - type = TYPE_MOFFS32; + if(immediate & 0x80000000) + immediate |= ~(0xffffffffull); break; case 8: - type = TYPE_MOFFS64; break; } } @@ -263,16 +265,18 @@ static void translateImmediate(MCInst &mcInst, uint64_t immediate, Opcode != X86::VMPSADBWrri && Opcode != X86::VDPPSYrri && Opcode != X86::VDPPSYrmi && Opcode != X86::VDPPDrri && Opcode != X86::VINSERTPSrr) - type = TYPE_MOFFS8; + if(immediate & 0x80) + immediate |= ~(0xffull); break; case ENCODING_IW: - type = TYPE_MOFFS16; + if(immediate & 0x8000) + immediate |= ~(0xffffull); break; case ENCODING_ID: - type = TYPE_MOFFS32; + if(immediate & 0x80000000) + immediate |= ~(0xffffffffull); break; case ENCODING_IO: - type = TYPE_MOFFS64; break; } } @@ -292,25 +296,16 @@ static void translateImmediate(MCInst &mcInst, uint64_t immediate, case TYPE_REL8: isBranch = true; pcrel = insn.startLocation + insn.immediateOffset + insn.immediateSize; - // fall through to sign extend the immediate if needed. - case TYPE_MOFFS8: if(immediate & 0x80) immediate |= ~(0xffull); break; - case TYPE_MOFFS16: - if(immediate & 0x8000) - immediate |= ~(0xffffull); - break; case TYPE_REL32: case TYPE_REL64: isBranch = true; pcrel = insn.startLocation + insn.immediateOffset + insn.immediateSize; - // fall through to sign extend the immediate if needed. - case TYPE_MOFFS32: if(immediate & 0x80000000) immediate |= ~(0xffffffffull); break; - case TYPE_MOFFS64: default: // operand is 64 bits wide. Do nothing. break; diff --git a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp index b9d008209e5..44393115cc4 100644 --- a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp +++ b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp @@ -215,3 +215,19 @@ void X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op, O << markup(">"); } + +void X86ATTInstPrinter::printMemOffset(const MCInst *MI, unsigned Op, + raw_ostream &O) { + const MCOperand &DispSpec = MI->getOperand(Op); + + O << markup(""); +} diff --git a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h index 8d0525623fd..a8fab72bc0d 100644 --- a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h +++ b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h @@ -42,7 +42,8 @@ public: void printSSECC(const MCInst *MI, unsigned Op, raw_ostream &OS); void printAVXCC(const MCInst *MI, unsigned Op, raw_ostream &OS); void printPCRelImm(const MCInst *MI, unsigned OpNo, raw_ostream &OS); - + void printMemOffset(const MCInst *MI, unsigned OpNo, raw_ostream &OS); + void printopaquemem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { printMemReference(MI, OpNo, O); } @@ -86,6 +87,19 @@ public: void printf512mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { printMemReference(MI, OpNo, O); } + + void printMemOffs8(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printMemOffset(MI, OpNo, O); + } + void printMemOffs16(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printMemOffset(MI, OpNo, O); + } + void printMemOffs32(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printMemOffset(MI, OpNo, O); + } + void printMemOffs64(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printMemOffset(MI, OpNo, O); + } }; } diff --git a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp index 9dfc9a9aa74..e7e7b151c3b 100644 --- a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp +++ b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp @@ -200,3 +200,19 @@ void X86IntelInstPrinter::printMemReference(const MCInst *MI, unsigned Op, O << ']'; } + +void X86IntelInstPrinter::printMemOffset(const MCInst *MI, unsigned Op, + raw_ostream &O) { + const MCOperand &DispSpec = MI->getOperand(Op); + + O << '['; + + if (DispSpec.isImm()) { + O << formatImm(DispSpec.getImm()); + } else { + assert(DispSpec.isExpr() && "non-immediate displacement?"); + O << *DispSpec.getExpr(); + } + + O << ']'; +} diff --git a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h index 45beeda2215..590bf681241 100644 --- a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h +++ b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h @@ -39,7 +39,8 @@ public: void printSSECC(const MCInst *MI, unsigned Op, raw_ostream &O); void printAVXCC(const MCInst *MI, unsigned Op, raw_ostream &O); void printPCRelImm(const MCInst *MI, unsigned OpNo, raw_ostream &O); - + void printMemOffset(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printopaquemem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { O << "opaque ptr "; printMemReference(MI, OpNo, O); @@ -97,6 +98,23 @@ public: O << "zmmword ptr "; printMemReference(MI, OpNo, O); } + + void printMemOffs8(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + O << "byte ptr "; + printMemOffset(MI, OpNo, O); + } + void printMemOffs16(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + O << "word ptr "; + printMemOffset(MI, OpNo, O); + } + void printMemOffs32(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + O << "dword ptr "; + printMemOffset(MI, OpNo, O); + } + void printMemOffs64(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + O << "qword ptr "; + printMemOffset(MI, OpNo, O); + } }; } diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index f4118daa360..adad17ac8f5 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -439,17 +439,45 @@ let OperandType = "OPERAND_PCREL", def i32imm_pcrel : Operand; def i16imm_pcrel : Operand; -def offset8 : Operand; -def offset16 : Operand; -def offset32 : Operand; -def offset64 : Operand; - // Branch targets have OtherVT type and print as pc-relative values. def brtarget : Operand; def brtarget8 : Operand; } +def X86MemOffs8AsmOperand : AsmOperandClass { + let Name = "MemOffs8"; + let SuperClasses = [X86Mem8AsmOperand]; +} +def X86MemOffs16AsmOperand : AsmOperandClass { + let Name = "MemOffs16"; + let SuperClasses = [X86Mem16AsmOperand]; +} +def X86MemOffs32AsmOperand : AsmOperandClass { + let Name = "MemOffs32"; + let SuperClasses = [X86Mem32AsmOperand]; +} +def X86MemOffs64AsmOperand : AsmOperandClass { + let Name = "MemOffs64"; + let SuperClasses = [X86Mem64AsmOperand]; +} + +let OperandType = "OPERAND_MEMORY" in { +def offset8 : Operand { + let ParserMatchClass = X86MemOffs8AsmOperand; + let PrintMethod = "printMemOffs8"; } +def offset16 : Operand { + let ParserMatchClass = X86MemOffs16AsmOperand; + let PrintMethod = "printMemOffs16"; } +def offset32 : Operand { + let ParserMatchClass = X86MemOffs32AsmOperand; + let PrintMethod = "printMemOffs32"; } +def offset64 : Operand { + let ParserMatchClass = X86MemOffs64AsmOperand; + let PrintMethod = "printMemOffs64"; } +} + + def SSECC : Operand { let PrintMethod = "printSSECC"; let OperandType = "OPERAND_IMMEDIATE"; @@ -1104,13 +1132,13 @@ def MOV32ao32 : Ii32 <0xA3, RawFrm, (outs offset32:$dst), (ins), // These forms all have full 64-bit absolute addresses in their instructions // and use the movabs mnemonic to indicate this specific form. let mayLoad = 1 in { -def MOV64o8a : RIi64_NOREX<0xA0, RawFrm, (outs), (ins offset64:$src), +def MOV64o8a : RIi64_NOREX<0xA0, RawFrm, (outs), (ins offset8:$src), "movabs{b}\t{$src, %al|al, $src}", []>, Requires<[In64BitMode]>; -def MOV64o16a : RIi64_NOREX<0xA1, RawFrm, (outs), (ins offset64:$src), +def MOV64o16a : RIi64_NOREX<0xA1, RawFrm, (outs), (ins offset16:$src), "movabs{w}\t{$src, %ax|ax, $src}", []>, OpSize, Requires<[In64BitMode]>; -def MOV64o32a : RIi64_NOREX<0xA1, RawFrm, (outs), (ins offset64:$src), +def MOV64o32a : RIi64_NOREX<0xA1, RawFrm, (outs), (ins offset32:$src), "movabs{l}\t{$src, %eax|eax, $src}", []>, Requires<[In64BitMode]>; def MOV64o64a : RIi64<0xA1, RawFrm, (outs), (ins offset64:$src), @@ -1119,13 +1147,13 @@ def MOV64o64a : RIi64<0xA1, RawFrm, (outs), (ins offset64:$src), } let mayStore = 1 in { -def MOV64ao8 : RIi64_NOREX<0xA2, RawFrm, (outs offset64:$dst), (ins), +def MOV64ao8 : RIi64_NOREX<0xA2, RawFrm, (outs offset8:$dst), (ins), "movabs{b}\t{%al, $dst|$dst, al}", []>, Requires<[In64BitMode]>; -def MOV64ao16 : RIi64_NOREX<0xA3, RawFrm, (outs offset64:$dst), (ins), +def MOV64ao16 : RIi64_NOREX<0xA3, RawFrm, (outs offset16:$dst), (ins), "movabs{w}\t{%ax, $dst|$dst, ax}", []>, OpSize, Requires<[In64BitMode]>; -def MOV64ao32 : RIi64_NOREX<0xA3, RawFrm, (outs offset64:$dst), (ins), +def MOV64ao32 : RIi64_NOREX<0xA3, RawFrm, (outs offset32:$dst), (ins), "movabs{l}\t{%eax, $dst|$dst, eax}", []>, Requires<[In64BitMode]>; def MOV64ao64 : RIi64<0xA3, RawFrm, (outs offset64:$dst), (ins), diff --git a/test/MC/Disassembler/X86/intel-syntax-32.txt b/test/MC/Disassembler/X86/intel-syntax-32.txt index 08bae6ec675..2298823604a 100644 --- a/test/MC/Disassembler/X86/intel-syntax-32.txt +++ b/test/MC/Disassembler/X86/intel-syntax-32.txt @@ -1,13 +1,31 @@ # RUN: llvm-mc --disassemble %s -triple=i386 --output-asm-variant=1 | FileCheck %s -# CHECK: sgdt +# CHECK: sgdt opaque ptr [eax] 0x0f 0x01 0x00 -# CHECK: sidt +# CHECK: sidt opaque ptr [eax] 0x0f 0x01 0x08 -# CHECK: lgdt +# CHECK: lgdt opaque ptr [eax] 0x0f 0x01 0x10 -# CHECK: lidt +# CHECK: lidt opaque ptr [eax] 0x0f 0x01 0x18 + +# CHECK: mov al, byte ptr [878082192] +0xa0 0x90 0x78 0x56 0x34 + +# CHECK: mov ax, word ptr [878082192] +0x66 0xa1 0x90 0x78 0x56 0x34 + +# CHECK: mov eax, dword ptr [878082192] +0xa1 0x90 0x78 0x56 0x34 + +# CHECK: mov byte ptr [878082192], al +0xa2 0x90 0x78 0x56 0x34 + +# CHECK: mov word ptr [878082192], ax +0x66 0xa3 0x90 0x78 0x56 0x34 + +# CHECK: mov dword ptr [878082192], eax +0xa3 0x90 0x78 0x56 0x34 diff --git a/test/MC/Disassembler/X86/intel-syntax.txt b/test/MC/Disassembler/X86/intel-syntax.txt index 6c0c239fb80..6a63102eaa7 100644 --- a/test/MC/Disassembler/X86/intel-syntax.txt +++ b/test/MC/Disassembler/X86/intel-syntax.txt @@ -119,3 +119,33 @@ # CHECK: xsaveopt64 opaque ptr [rax] 0x48 0x0f 0xae 0x30 + +# CHECK: movabs al, byte ptr [-6066930261531658096] +0xa0 0x90 0x78 0x56 0x34 0x12 0xef 0xcd 0xab + +# CHECK: movabs al, byte ptr [-6066930261531658096] +0x48 0xa0 0x90 0x78 0x56 0x34 0x12 0xef 0xcd 0xab + +# CHECK: movabs ax, word ptr [-6066930261531658096] +0x66 0xa1 0x90 0x78 0x56 0x34 0x12 0xef 0xcd 0xab + +# CHECK: movabs eax, dword ptr [-6066930261531658096] +0xa1 0x90 0x78 0x56 0x34 0x12 0xef 0xcd 0xab + +# CHECK: movabs rax, qword ptr [-6066930261531658096] +0x48 0xa1 0x90 0x78 0x56 0x34 0x12 0xef 0xcd 0xab + +# CHECK: movabs byte ptr [-6066930261531658096], al +0xa2 0x90 0x78 0x56 0x34 0x12 0xef 0xcd 0xab + +# CHECK: movabs byte ptr [-6066930261531658096], al +0x48 0xa2 0x90 0x78 0x56 0x34 0x12 0xef 0xcd 0xab + +# CHECK: movabs word ptr [-6066930261531658096], ax +0x66 0xa3 0x90 0x78 0x56 0x34 0x12 0xef 0xcd 0xab + +# CHECK: movabs dword ptr [-6066930261531658096], eax +0xa3 0x90 0x78 0x56 0x34 0x12 0xef 0xcd 0xab + +# CHECK: movabs qword ptr [-6066930261531658096], rax +0x48 0xa3 0x90 0x78 0x56 0x34 0x12 0xef 0xcd 0xab diff --git a/test/MC/Disassembler/X86/x86-32.txt b/test/MC/Disassembler/X86/x86-32.txt index 76d67d352cc..d53da5b7d29 100644 --- a/test/MC/Disassembler/X86/x86-32.txt +++ b/test/MC/Disassembler/X86/x86-32.txt @@ -648,3 +648,21 @@ # CHECK: adoxl (%eax), %eax 0xf3 0x0f 0x38 0xf6 0x00 + +# CHECK: movb 878082192, %al +0xa0 0x90 0x78 0x56 0x34 + +# CHECK: movw 878082192, %ax +0x66 0xa1 0x90 0x78 0x56 0x34 + +# CHECK: movl 878082192, %eax +0xa1 0x90 0x78 0x56 0x34 + +# CHECK: movb %al, 878082192 +0xa2 0x90 0x78 0x56 0x34 + +# CHECK: movw %ax, 878082192 +0x66 0xa3 0x90 0x78 0x56 0x34 + +# CHECK: movl %eax, 878082192 +0xa3 0x90 0x78 0x56 0x34 -- 2.34.1