diff options
author | Alkis Evlogimenos <alkis@evlogimenos.com> | 2004-02-28 22:02:05 +0000 |
---|---|---|
committer | Alkis Evlogimenos <alkis@evlogimenos.com> | 2004-02-28 22:02:05 +0000 |
commit | 5ab29b504d49d3fa84d76f79e73704260f900682 (patch) | |
tree | 2326ad9d7d7f897f547d9cc9507312d40346d3ae | |
parent | f822ee999f12e38eebf4a346f384d4bb302bdfad (diff) |
Each instruction now has both an ImmType and a MemType. This describes
the size of the immediate and the memory operand on instructions that
use them. This resolves problems with instructions that take both a
memory and an immediate operand but their sizes differ (i.e. ADDmi32b).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@11967 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/X86/Printer.cpp | 16 | ||||
-rw-r--r-- | lib/Target/X86/X86.td | 8 | ||||
-rw-r--r-- | lib/Target/X86/X86AsmPrinter.cpp | 16 | ||||
-rw-r--r-- | lib/Target/X86/X86CodeEmitter.cpp | 70 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.h | 32 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.td | 900 |
6 files changed, 542 insertions, 500 deletions
diff --git a/lib/Target/X86/Printer.cpp b/lib/Target/X86/Printer.cpp index df6c41cc4a..34061852b2 100644 --- a/lib/Target/X86/Printer.cpp +++ b/lib/Target/X86/Printer.cpp @@ -433,16 +433,14 @@ void Printer::printOp(const MachineOperand &MO, } } -static const std::string sizePtr(const TargetInstrDescriptor &Desc) { - switch (Desc.TSFlags & X86II::ArgMask) { +static const char* const sizePtr(const TargetInstrDescriptor &Desc) { + switch (Desc.TSFlags & X86II::MemMask) { default: assert(0 && "Unknown arg size!"); - case X86II::Arg8: return "BYTE PTR"; - case X86II::Arg16: return "WORD PTR"; - case X86II::Arg32: return "DWORD PTR"; - case X86II::Arg64: return "QWORD PTR"; - case X86II::ArgF32: return "DWORD PTR"; - case X86II::ArgF64: return "QWORD PTR"; - case X86II::ArgF80: return "XWORD PTR"; + case X86II::Mem8: return "BYTE PTR"; + case X86II::Mem16: return "WORD PTR"; + case X86II::Mem32: return "DWORD PTR"; + case X86II::Mem64: return "QWORD PTR"; + case X86II::Mem80: return "XWORD PTR"; } } diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td index d26ef9a73c..f92bfa10fc 100644 --- a/lib/Target/X86/X86.td +++ b/lib/Target/X86/X86.td @@ -33,10 +33,10 @@ def X86InstrInfo : InstrInfo { // Define how we want to layout our TargetSpecific information field... This // should be kept up-to-date with the fields in the X86InstrInfo.h file. - let TSFlagsFields = ["FormBits" , "hasOpSizePrefix" , "Prefix", "TypeBits", - "FPFormBits", "printImplicitUses", "Opcode"]; - let TSFlagsShifts = [ 0, 5, 6, 10, - 13, 16, 17]; + let TSFlagsFields = ["FormBits" , "hasOpSizePrefix" , "Prefix", "MemTypeBits", + "ImmTypeBits", "FPFormBits", "printImplicitUses", "Opcode"]; + let TSFlagsShifts = [0, 5, 6, 10, 13, + 15, 18, 19]; } def X86 : Target { diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp index df6c41cc4a..34061852b2 100644 --- a/lib/Target/X86/X86AsmPrinter.cpp +++ b/lib/Target/X86/X86AsmPrinter.cpp @@ -433,16 +433,14 @@ void Printer::printOp(const MachineOperand &MO, } } -static const std::string sizePtr(const TargetInstrDescriptor &Desc) { - switch (Desc.TSFlags & X86II::ArgMask) { +static const char* const sizePtr(const TargetInstrDescriptor &Desc) { + switch (Desc.TSFlags & X86II::MemMask) { default: assert(0 && "Unknown arg size!"); - case X86II::Arg8: return "BYTE PTR"; - case X86II::Arg16: return "WORD PTR"; - case X86II::Arg32: return "DWORD PTR"; - case X86II::Arg64: return "QWORD PTR"; - case X86II::ArgF32: return "DWORD PTR"; - case X86II::ArgF64: return "QWORD PTR"; - case X86II::ArgF80: return "XWORD PTR"; + case X86II::Mem8: return "BYTE PTR"; + case X86II::Mem16: return "WORD PTR"; + case X86II::Mem32: return "DWORD PTR"; + case X86II::Mem64: return "QWORD PTR"; + case X86II::Mem80: return "XWORD PTR"; } } diff --git a/lib/Target/X86/X86CodeEmitter.cpp b/lib/Target/X86/X86CodeEmitter.cpp index 1d12ce2d2c..8e0ba2a497 100644 --- a/lib/Target/X86/X86CodeEmitter.cpp +++ b/lib/Target/X86/X86CodeEmitter.cpp @@ -453,14 +453,24 @@ void Emitter::emitMemModRMByte(const MachineInstr &MI, } } +static unsigned sizeOfImm(const TargetInstrDescriptor &Desc) { + switch (Desc.TSFlags & X86II::ImmMask) { + case X86II::Imm8: return 1; + case X86II::Imm16: return 2; + case X86II::Imm32: return 4; + default: assert(0 && "Immediate size not set!"); + return 0; + } +} + static unsigned sizeOfPtr(const TargetInstrDescriptor &Desc) { - switch (Desc.TSFlags & X86II::ArgMask) { - case X86II::Arg8: return 1; - case X86II::Arg16: return 2; - case X86II::Arg32: return 4; - case X86II::ArgF32: return 4; - case X86II::ArgF64: return 8; - case X86II::ArgF80: return 10; + switch (Desc.TSFlags & X86II::MemMask) { + case X86II::Mem8: return 1; + case X86II::Mem16: return 2; + case X86II::Mem32: return 4; + case X86II::Mem64: return 8; + case X86II::Mem80: return 10; + case X86II::Mem128: return 16; default: assert(0 && "Memory size not set!"); return 0; } @@ -527,25 +537,21 @@ void Emitter::emitInstruction(MachineInstr &MI) { MCE.emitByte(BaseOpcode + getX86RegNum(MI.getOperand(0).getReg())); if (MI.getNumOperands() == 2) { MachineOperand &MO1 = MI.getOperand(1); - if (MO1.isImmediate() || MO1.getVRegValueOrNull() || - MO1.isGlobalAddress() || MO1.isExternalSymbol()) { - unsigned Size = sizeOfPtr(Desc); - if (Value *V = MO1.getVRegValueOrNull()) { - assert(Size == 4 && "Don't know how to emit non-pointer values!"); - emitGlobalAddressForPtr(cast<GlobalValue>(V)); - } else if (MO1.isGlobalAddress()) { - assert(Size == 4 && "Don't know how to emit non-pointer values!"); - assert(!MO1.isPCRelative() && "Function pointer ref is PC relative?"); - emitGlobalAddressForPtr(MO1.getGlobal()); - } else if (MO1.isExternalSymbol()) { - assert(Size == 4 && "Don't know how to emit non-pointer values!"); - - unsigned Address = MCE.getGlobalValueAddress(MO1.getSymbolName()); - assert(Address && "Unknown external symbol!"); - emitMaybePCRelativeValue(Address, MO1.isPCRelative()); - } else { - emitConstant(MO1.getImmedValue(), Size); - } + if (Value *V = MO1.getVRegValueOrNull()) { + assert(sizeOfImm(Desc) == 4 && "Don't know how to emit non-pointer values!"); + emitGlobalAddressForPtr(cast<GlobalValue>(V)); + } else if (MO1.isGlobalAddress()) { + assert(sizeOfImm(Desc) == 4 && "Don't know how to emit non-pointer values!"); + assert(!MO1.isPCRelative() && "Function pointer ref is PC relative?"); + emitGlobalAddressForPtr(MO1.getGlobal()); + } else if (MO1.isExternalSymbol()) { + assert(sizeOfImm(Desc) == 4 && "Don't know how to emit non-pointer values!"); + + unsigned Address = MCE.getGlobalValueAddress(MO1.getSymbolName()); + assert(Address && "Unknown external symbol!"); + emitMaybePCRelativeValue(Address, MO1.isPCRelative()); + } else { + emitConstant(MO1.getImmedValue(), sizeOfImm(Desc)); } } break; @@ -555,7 +561,7 @@ void Emitter::emitInstruction(MachineInstr &MI) { emitRegModRMByte(MI.getOperand(0).getReg(), getX86RegNum(MI.getOperand(1).getReg())); if (MI.getNumOperands() == 3) - emitConstant(MI.getOperand(2).getImmedValue(), sizeOfPtr(Desc)); + emitConstant(MI.getOperand(2).getImmedValue(), sizeOfImm(Desc)); break; } case X86II::MRMDestMem: @@ -569,14 +575,14 @@ void Emitter::emitInstruction(MachineInstr &MI) { emitRegModRMByte(MI.getOperand(1).getReg(), getX86RegNum(MI.getOperand(0).getReg())); if (MI.getNumOperands() == 3) - emitConstant(MI.getOperand(2).getImmedValue(), sizeOfPtr(Desc)); + emitConstant(MI.getOperand(2).getImmedValue(), sizeOfImm(Desc)); break; case X86II::MRMSrcMem: MCE.emitByte(BaseOpcode); emitMemModRMByte(MI, 1, getX86RegNum(MI.getOperand(0).getReg())); if (MI.getNumOperands() == 2+4) - emitConstant(MI.getOperand(5).getImmedValue(), sizeOfPtr(Desc)); + emitConstant(MI.getOperand(5).getImmedValue(), sizeOfImm(Desc)); break; case X86II::MRM0r: case X86II::MRM1r: @@ -588,8 +594,7 @@ void Emitter::emitInstruction(MachineInstr &MI) { (Desc.TSFlags & X86II::FormMask)-X86II::MRM0r); if (MI.getOperand(MI.getNumOperands()-1).isImmediate()) { - unsigned Size = sizeOfPtr(Desc); - emitConstant(MI.getOperand(MI.getNumOperands()-1).getImmedValue(), Size); + emitConstant(MI.getOperand(MI.getNumOperands()-1).getImmedValue(), sizeOfImm(Desc)); } break; @@ -601,9 +606,8 @@ void Emitter::emitInstruction(MachineInstr &MI) { emitMemModRMByte(MI, 0, (Desc.TSFlags & X86II::FormMask)-X86II::MRM0m); if (MI.getNumOperands() == 5) { - unsigned Size = sizeOfPtr(Desc); if (MI.getOperand(4).isImmediate()) - emitConstant(MI.getOperand(4).getImmedValue(), Size); + emitConstant(MI.getOperand(4).getImmedValue(), sizeOfImm(Desc)); else if (MI.getOperand(4).isGlobalAddress()) emitGlobalAddressForPtr(MI.getOperand(4).getGlobal()); else diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h index 438acb0f28..5c1416eb20 100644 --- a/lib/Target/X86/X86InstrInfo.h +++ b/lib/Target/X86/X86InstrInfo.h @@ -111,21 +111,29 @@ namespace X86II { //===------------------------------------------------------------------===// // This three-bit field describes the size of a memory operand. Zero is // unused so that we can tell if we forgot to set a value. - ArgShift = 10, - ArgMask = 7 << ArgShift, - Arg8 = 1 << ArgShift, - Arg16 = 2 << ArgShift, - Arg32 = 3 << ArgShift, - Arg64 = 4 << ArgShift, // 64 bit int argument for FILD64 - ArgF32 = 5 << ArgShift, - ArgF64 = 6 << ArgShift, - ArgF80 = 7 << ArgShift, + MemShift = 10, + MemMask = 7 << MemShift, + Mem8 = 1 << MemShift, + Mem16 = 2 << MemShift, + Mem32 = 3 << MemShift, + Mem64 = 4 << MemShift, + Mem80 = 5 << MemShift, + Mem128 = 6 << MemShift, + + //===------------------------------------------------------------------===// + // This tow-bit field describes the size of an immediate operand. Zero is + // unused so that we can tell if we forgot to set a value. + ImmShift = 13, + ImmMask = 7 << ImmShift, + Imm8 = 1 << ImmShift, + Imm16 = 2 << ImmShift, + Imm32 = 3 << ImmShift, //===------------------------------------------------------------------===// // FP Instruction Classification... Zero is non-fp instruction. // FPTypeMask - Mask for all of the FP types... - FPTypeShift = 13, + FPTypeShift = 15, FPTypeMask = 7 << FPTypeShift, // NotFP - The default, set for instructions that do not use FP registers. @@ -151,9 +159,9 @@ namespace X86II { SpecialFP = 5 << FPTypeShift, // PrintImplUses - Print out implicit uses in the assembly output. - PrintImplUses = 1 << 16, + PrintImplUses = 1 << 18, - OpcodeShift = 17, + OpcodeShift = 19, OpcodeMask = 0xFF << OpcodeShift, // Bits 25 -> 31 are unused }; diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index b9f804c58f..be795b85ce 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -31,20 +31,30 @@ def MRM0m : Format<24>; def MRM1m : Format<25>; def MRM2m : Format<26>; def MRM3m : Format<27>; def MRM4m : Format<28>; def MRM5m : Format<29>; def MRM6m : Format<30>; def MRM7m : Format<31>; -// ArgType - This specifies the argument type used by an instruction. This is +// ImmType - This specifies the immediate type used by an instruction. This is // part of the ad-hoc solution used to emit machine instruction encodings by our // machine code emitter. -class ArgType<bits<3> val> { +class ImmType<bits<2> val> { + bits<2> Value = val; +} +def NoImm : ImmType<0>; +def Imm8 : ImmType<1>; +def Imm16 : ImmType<2>; +def Imm32 : ImmType<3>; + +// MemType - This specifies the immediate type used by an instruction. This is +// part of the ad-hoc solution used to emit machine instruction encodings by our +// machine code emitter. +class MemType<bits<3> val> { bits<3> Value = val; } -def NoArg : ArgType<0>; -def Arg8 : ArgType<1>; -def Arg16 : ArgType<2>; -def Arg32 : ArgType<3>; -def Arg64 : ArgType<4>; // 64 bit int argument for FILD64 -def ArgF32 : ArgType<5>; -def ArgF64 : ArgType<6>; -def ArgF80 : ArgType<6>; +def NoMem : MemType<0>; +def Mem8 : MemType<1>; +def Mem16 : MemType<2>; +def Mem32 : MemType<3>; +def Mem64 : MemType<4>; +def Mem80 : MemType<4>; +def Mem128 : MemType<6>; // FPFormat - This specifies what form this FP instruction has. This is used by // the Floating-Point stackifier pass. @@ -59,15 +69,17 @@ def TwoArgFP : FPFormat<4>; def SpecialFP : FPFormat<5>; -class X86Inst<string nam, bits<8> opcod, Format f, ArgType a> : Instruction { +class X86Inst<string nam, bits<8> opcod, Format f, MemType m, ImmType i> : Instruction { let Namespace = "X86"; let Name = nam; bits<8> Opcode = opcod; Format Form = f; bits<5> FormBits = Form.Value; - ArgType Type = a; - bits<3> TypeBits = Type.Value; + MemType MemT = m; + bits<3> MemTypeBits = MemT.Value; + ImmType ImmT = i; + bits<2> ImmTypeBits = ImmT.Value; // Attributes specific to X86 instructions... bit hasOpSizePrefix = 0; // Does this inst have a 0x66 prefix? @@ -103,33 +115,57 @@ class DE { bits<4> Prefix = 9; } class DF { bits<4> Prefix = 10; } +//===----------------------------------------------------------------------===// +// Instruction templates... + +class I<string n, bits<8> o, Format f> : X86Inst<n, o, f, NoMem, NoImm>; + +class IM<string n, bits<8> o, Format f, MemType m> : X86Inst<n, o, f, m, NoImm>; +class IM8 <string n, bits<8> o, Format f> : IM<n, o, f, Mem8 >; +class IM16<string n, bits<8> o, Format f> : IM<n, o, f, Mem16>; +class IM32<string n, bits<8> o, Format f> : IM<n, o, f, Mem32>; + +class II<string n, bits<8> o, Format f, ImmType i> : X86Inst<n, o, f, NoMem, i>; +class II8 <string n, bits<8> o, Format f> : II<n, o, f, Imm8 >; +class II16<string n, bits<8> o, Format f> : II<n, o, f, Imm16>; +class II32<string n, bits<8> o, Format f> : II<n, o, f, Imm32>; + +class I8MI <string n, bits<8> o, Format f> : X86Inst<n, o, f, Mem8 , Imm8 >; +class I16MI<string n, bits<8> o, Format f> : X86Inst<n, o, f, Mem16, Imm16>; +class I32MI<string n, bits<8> o, Format f> : X86Inst<n, o, f, Mem32, Imm32>; + +class IM16I8<string n, bits<8> o, Format f> : X86Inst<n, o, f, Mem16, Imm8>; +class IM32I8<string n, bits<8> o, Format f> : X86Inst<n, o, f, Mem32, Imm8>; + +// Helper for shift instructions +class UsesCL { list<Register> Uses = [CL]; bit printImplicitUses = 1; } //===----------------------------------------------------------------------===// // Instruction list... // -def PHI : X86Inst<"PHI", 0, Pseudo, NoArg>; // PHI node... +def PHI : I<"PHI", 0, Pseudo>; // PHI node... -def NOOP : X86Inst<"nop", 0x90, RawFrm, NoArg>; // nop +def NOOP : I<"nop", 0x90, RawFrm>; // nop -def ADJCALLSTACKDOWN : X86Inst<"ADJCALLSTACKDOWN", 0, Pseudo, NoArg>; -def ADJCALLSTACKUP : X86Inst<"ADJCALLSTACKUP", 0, Pseudo, NoArg>; -def IMPLICIT_USE : X86Inst<"IMPLICIT_USE", 0, Pseudo, NoArg>; -def IMPLICIT_DEF : X86Inst<"IMPLICIT_DEF", 0, Pseudo, NoArg>; +def ADJCALLSTACKDOWN : I<"ADJCALLSTACKDOWN", 0, Pseudo>; +def ADJCALLSTACKUP : I<"ADJCALLSTACKUP", 0, Pseudo>; +def IMPLICIT_USE : I<"IMPLICIT_USE", 0, Pseudo>; +def IMPLICIT_DEF : I<"IMPLICIT_DEF", 0, Pseudo>; let isTerminator = 1 in let Defs = [FP0, FP1, FP2, FP3, FP4, FP5, FP6] in - def FP_REG_KILL : X86Inst<"FP_REG_KILL", 0, Pseudo, NoArg>; + def FP_REG_KILL : I<"FP_REG_KILL", 0, Pseudo>; //===----------------------------------------------------------------------===// // Control Flow Instructions... // // Return instruction... let isTerminator = 1, isReturn = 1 in - def RET : X86Inst<"ret", 0xC3, RawFrm, NoArg>, Pattern<(retvoid)>; + def RET : I<"ret", 0xC3, RawFrm>, Pattern<(retvoid)>; // All branches are RawFrm, Void, Branch, and Terminators let isBranch = 1, isTerminator = 1 in - class IBr<string name, bits<8> opcode> : X86Inst<name, opcode, RawFrm, NoArg>; + class IBr<string name, bits<8> opcode> : I<name, opcode, RawFrm>; def JMP : IBr<"jmp", 0xE9>, Pattern<(br basicblock)>; def JB : IBr<"jb" , 0x82>, TB; @@ -152,426 +188,420 @@ def JG : IBr<"jg" , 0x8F>, TB; let isCall = 1 in // All calls clobber the non-callee saved registers... let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6] in { - def CALLpcrel32 : X86Inst<"call", 0xE8, RawFrm, NoArg>; - def CALLr32 : X86Inst<"call", 0xFF, MRM2r , Arg32>; - def CALLm32 : X86Inst<"call", 0xFF, MRM2m , Arg32>; + def CALLpcrel32 : I <"call", 0xE8, RawFrm>; + def CALLr32 : I <"call", 0xFF, MRM2r>; + def CALLm32 : IM32<"call", 0xFF, MRM2m>; } //===----------------------------------------------------------------------===// // Miscellaneous Instructions... // -def LEAVE : X86Inst<"leave", 0xC9, RawFrm, NoArg>, Imp<[EBP,ESP],[EBP,ESP]>; -def POPr32 : X86Inst<"pop", 0x58, AddRegFrm, Arg32>, Imp<[ESP],[ESP]>; +def LEAVE : I<"leave", 0xC9, RawFrm>, Imp<[EBP,ESP],[EBP,ESP]>; +def POPr32 : I<"pop", 0x58, AddRegFrm>, Imp<[ESP],[ESP]>; -let isTwoAddress = 1 in // R32 = bswap R32 - def BSWAPr32 : X86Inst<"bswap", 0xC8, AddRegFrm, Arg32>, TB; +let isTwoAddress = 1 in // R32 = bswap R32 + def BSWAPr32 : I<"bswap", 0xC8, AddRegFrm>, TB; -def XCHGrr8 : X86Inst<"xchg", 0x86, MRMDestReg, Arg8>; // xchg R8, R8 -def XCHGrr16 : X86Inst<"xchg", 0x87, MRMDestReg, Arg16>, OpSize;// xchg R16, R16 -def XCHGrr32 : X86Inst<"xchg", 0x87, MRMDestReg, Arg32>; // xchg R32, R32 -def XCHGmr8 : X86Inst<"xchg", 0x86, MRMDestMem, Arg8>; // xchg [mem8], R8 -def XCHGmr16 : X86Inst<"xchg", 0x87, MRMDestMem, Arg16>, OpSize;// xchg [mem16], R16 -def XCHGmr32 : X86Inst<"xchg", 0x87, MRMDestMem, Arg32>; // xchg [mem32], R32 -def XCHGrm8 : X86Inst<"xchg", 0x86, MRMSrcMem , Arg8>; // xchg R8, [mem8] -def XCHGrm16 : X86Inst<"xchg", 0x87, MRMSrcMem , Arg16>, OpSize;// xchg R16, [mem16] -def XCHGrm32 : X86Inst<"xchg", 0x87, MRMSrcMem , Arg32>; // xchg R32, [mem32] +def XCHGrr8 : I <"xchg", 0x86, MRMDestReg>; // xchg R8, R8 +def XCHGrr16 : I <"xchg", 0x87, MRMDestReg>, OpSize; // xchg R16, R16 +def XCHGrr32 : I <"xchg", 0x87, MRMDestReg>; // xchg R32, R32 +def XCHGmr8 : IM8 <"xchg", 0x86, MRMDestMem>; // xchg [mem8], R8 +def XCHGmr16 : IM16<"xchg", 0x87, MRMDestMem>, OpSize; // xchg [mem16], R16 +def XCHGmr32 : IM32<"xchg", 0x87, MRMDestMem>; // xchg [mem32], R32 +def XCHGrm8 : IM8 <"xchg", 0x86, MRMSrcMem >; // xchg R8, [mem8] +def XCHGrm16 : IM16<"xchg", 0x87, MRMSrcMem >, OpSize; // xchg R16, [mem16] +def XCHGrm32 : IM32<"xchg", 0x87, MRMSrcMem >; // xchg R32, [mem32] -def LEAr16 : X86Inst<"lea", 0x8D, MRMSrcMem, Arg16>, OpSize; // R16 = lea [mem] -def LEAr32 : X86Inst<"lea", 0x8D, MRMSrcMem, Arg32>; // R32 = lea [mem] +def LEAr16 : IM32<"lea", 0x8D, MRMSrcMem>, OpSize; // R16 = lea [mem] +def LEAr32 : IM32<"lea", 0x8D, MRMSrcMem>; // R32 = lea [mem] -def REP_MOVSB : X86Inst<"rep movsb", 0xA4, RawFrm, NoArg>, REP, +def REP_MOVSB : I<"rep movsb", 0xA4, RawFrm>, REP, Imp<[ECX,EDI,ESI], [ECX,EDI,ESI]>; -def REP_MOVSW : X86Inst<"rep movsw", 0xA5, RawFrm, NoArg>, REP, OpSize, +def REP_MOVSW : I<"rep movsw", 0xA5, RawFrm>, REP, OpSize, Imp<[ECX,EDI,ESI], [ECX,EDI,ESI]>; -def REP_MOVSD : X86Inst<"rep movsd", 0xA5, RawFrm, NoArg>, REP, +def REP_MOVSD : I<"rep movsd", 0xA5, RawFrm>, REP, Imp<[ECX,EDI,ESI], [ECX,EDI,ESI]>; -def REP_STOSB : X86Inst<"rep stosb", 0xAA, RawFrm, NoArg>, REP, +def REP_STOSB : I<"rep stosb", 0xAA, RawFrm>, REP, Imp<[AL,ECX,EDI], [ECX,EDI]>; -def REP_STOSW : X86Inst<"rep stosw", 0xAB, RawFrm, NoArg>, REP, OpSize, +def REP_STOSW : I<"rep stosw", 0xAB, RawFrm>, REP, OpSize, Imp<[AX,ECX,EDI], [ECX,EDI]>; -def REP_STOSD : X86Inst<"rep stosd", 0xAB, RawFrm, NoArg>, REP, +def REP_STOSD : I<"rep stosd", 0xAB, RawFrm>, REP, Imp<[EAX,ECX,EDI], [ECX,EDI]>; //===----------------------------------------------------------------------===// // Move Instructions... // -def MOVrr8 : X86Inst<"mov", 0x88, MRMDestReg, Arg8>, Pattern<(set R8 , R8 )>; -def MOVrr16 : X86Inst<"mov", 0x89, MRMDestReg, Arg16>, OpSize, Pattern<(set R16, R16)>; -def MOVrr32 : X86Inst<"mov", 0x89, MRMDestReg, Arg32>, Pattern<(set R32, R32)>; -def MOVri8 : X86Inst<"mov", 0xB0, AddRegFrm , Arg8>, Pattern<(set R8 , imm )>; -def MOVri16 : X86Inst<"mov", 0xB8, AddRegFrm , Arg16>, OpSize, Pattern<(set R16, imm)>; -def MOVri32 : X86Inst<"mov", 0xB8, AddRegFrm , Arg32>, Pattern<(set R32, imm)>; -def MOVmi8 : X86Inst<"mov", 0xC6, MRM0m , Arg8>; // [mem8] = imm8 -def MOVmi16 : X86Inst<"mov", 0xC7, MRM0m , Arg16>, OpSize; // [mem16] = imm16 -def MOVmi32 : X86Inst<"mov", 0xC7, MRM0m , Arg32>; // [mem32] = imm32 - -def MOVrm8 : X86Inst<"mov", 0x8A, MRMSrcMem , Arg8>; // R8 = [mem8] -def MOVrm16 : X86Inst<"mov", 0x8B, MRMSrcMem , Arg16>, OpSize, // R16 = [mem16] +def MOVrr8 : I <"mov", 0x88, MRMDestReg>, Pattern<(set R8 , R8 )>; +def MOVrr16 : I <"mov", 0x89, MRMDestReg>, OpSize, Pattern<(set R16, R16)>; +def MOVrr32 : I <"mov", 0x89, MRMDestReg>, Pattern<(set R32, R32)>; +def MOVri8 : II8 <"mov", 0xB0, AddRegFrm >, Pattern<(set R8 , imm )>; +def MOVri16 : II16 <"mov", 0xB8, AddRegFrm >, OpSize, Pattern<(set R16, imm)>; +def MOVri32 : II32 <"mov", 0xB8, AddRegFrm >, Pattern<(set R32, imm)>; +def MOVmi8 : I8MI <"mov", 0xC6, MRM0m >; // [mem8] = imm8 +def MOVmi16 : I16MI<"mov", 0xC7, MRM0m >, OpSize; // [mem16] = imm16 +def MOVmi32 : I32MI<"mov", 0xC7, MRM0m >; // [mem32] = imm32 + +def MOVrm8 : IM8 <"mov", 0x8A, MRMSrcMem>; // R8 = [mem8] +def MOVrm16 : IM16 <"mov", 0x8B, MRMSrcMem>, OpSize, // R16 = [mem16] Pattern<(set R16, (load (plus R32, (plus (times imm, R32), imm))))>; -def MOVrm32 : X86Inst<"mov", 0x8B, MRMSrcMem , Arg32>, // R32 = [mem32] +def MOVrm32 : IM32 <"mov", 0x8B, MRMSrcMem>, // R32 = [mem32] Pattern<(set R32, (load (plus R32, (plus (times imm, R32), imm))))>; -def MOVmr8 : X86Inst<"mov", 0x88, MRMDestMem, Arg8>; // [mem8] = R8 -def MOVmr16 : X86Inst<"mov", 0x89, MRMDestMem, Arg16>, OpSize; // [mem16] = R16 -def MOVmr32 : X86Inst<"mov", 0x89, MRMDestMem, Arg32>; // [mem32] = R32 +def MOVmr8 : IM8 <"mov", 0x88, MRMDestMem>; // [mem8] = R8 +def MOVmr16 : IM16 <"mov", 0x89, MRMDestMem>, OpSize; // [mem16] = R16 +def MOVmr32 : IM32 <"mov", 0x89, MRMDestMem>; // [mem32] = R32 //===----------------------------------------------------------------------===// // Fixed-Register Multiplication and Division Instructions... // // Extra precision multiplication -def MULr8 : X86Inst<"mul", 0xF6, MRM4r , Arg8 >, Imp<[AL],[AX]>; // AL,AH = AL*R8 -def MULr16 : X86Inst<"mul", 0xF7, MRM4r , Arg16>, Imp<[AX],[AX,DX]>, OpSize; // AX,DX = AX*R16 -def MULr32 : X86Inst<"mul", 0xF7, MRM4r , Arg32>, Imp<[EAX],[EAX,EDX]>; // EAX,EDX = EAX*R32 -def MULm8 : X86Inst<"mul", 0xF6, MRM4m , Arg8 >, Imp<[AL],[AX]>; // AL,AH = AL*[mem8] -def MULm16 : X86Inst<"mul", 0xF7, MRM4m , Arg16>, Imp<[AX],[AX,DX]>, OpSize; // AX,DX = AX*[mem16] -def MULm32 : X86Inst<"mul", 0xF7, MRM4m , Arg32>, Imp<[EAX],[EAX,EDX]>; // EAX,EDX = EAX*[mem32] +def MULr8 : I <"mul", 0xF6, MRM4r>, Imp<[AL],[AX]>; // AL,AH = AL*R8 +def MULr16 : I <"mul", 0xF7, MRM4r>, Imp<[AX],[AX,DX]>, OpSize; // AX,DX = AX*R16 +def MULr32 : I <"mul", 0xF7, MRM4r>, Imp<[EAX],[EAX,EDX]>; // EAX,EDX = EAX*R32 +def MULm8 : IM8 <"mul", 0xF6, MRM4m>, Imp<[AL],[AX]>; // AL,AH = AL*[mem8] +def MULm16 : IM16<"mul", 0xF7, MRM4m>, Imp<[AX],[AX,DX]>, OpSize; // AX,DX = AX*[mem16] +def MULm32 : IM32<"mul", 0xF7, MRM4m>, Imp<[EAX],[EAX,EDX]>; // EAX,EDX = EAX*[mem32] // unsigned division/remainder -def DIVr8 : X86Inst<"div", 0xF6, MRM6r , Arg8 >, Imp<[AX],[AX]>; // AX/r8 = AL,AH -def DIVr16 : X86Inst<"div", 0xF7, MRM6r , Arg16>, Imp<[AX,DX],[AX,DX]>, OpSize; // DX:AX/r16 = AX,DX -def DIVr32 : X86Inst<"div", 0xF7, MRM6r , Arg32>, Imp<[EAX,EDX],[EAX,EDX]>; // EDX:EAX/r32 = EAX,EDX -def DIVm8 : X86Inst<"div", 0xF6, MRM6m , Arg8 >, Imp<[AX],[AX]>; // AX/[mem8] = AL,AH -def DIVm16 : X86Inst<"div", 0xF7, MRM6m , Arg16>, Imp<[AX,DX],[AX,DX]>, OpSize; // DX:AX/[mem16] = AX,DX -def DIVm32 : X86Inst<"div", 0xF7, MRM6m , Arg32>, Imp<[EAX,EDX],[EAX,EDX]>; // EDX:EAX/[mem32] = EAX,EDX +def DIVr8 : I <"div", 0xF6, MRM6r>, Imp<[AX],[AX]>; // AX/r8 = AL,AH +def DIVr16 : I <"div", 0xF7, MRM6r>, Imp<[AX,DX],[AX,DX]>, OpSize; // DX:AX/r16 = AX,DX +def DIVr32 : I <"div", 0xF7, MRM6r>, Imp<[EAX,EDX],[EAX,EDX]>; // EDX:EAX/r32 = EAX,EDX +def DIVm8 : IM8 <"div", 0xF6, MRM6m>, Imp<[AX],[AX]>; // AX/[mem8] = AL,AH +def DIVm16 : IM16<"div", 0xF7, MRM6m>, Imp<[AX,DX],[AX,DX]>, OpSize; // DX:AX/[mem16] = AX,DX +def DIVm32 : IM32<"div", 0xF7, MRM6m>, Imp<[EAX,EDX],[EAX,EDX]>; // EDX:EAX/[mem32] = EAX,EDX // signed division/remainder -def IDIVr8 : X86Inst<"idiv",0xF6, MRM7r , Arg8 >, Imp<[AX],[AX]>; // AX/r8 = AL,AH -def IDIVr16: X86Inst<"idiv",0xF7, MRM7r , Arg16>, Imp<[AX,DX],[AX,DX]>, OpSize; // DX:AX/r16 = AX,DX -def IDIVr32: X86Inst<"idiv",0xF7, MRM7r , Arg32>, Imp<[EAX,EDX],[EAX,EDX]>; // EDX:EAX/r32 = EAX,EDX -def IDIVm8 : X86Inst<"idiv",0xF6, MRM7m , Arg8 >, Imp<[AX],[AX]>; // AX/[mem8] = AL,AH -def IDIVm16: X86Inst<"idiv",0xF7, MRM7m , Arg16>, Imp<[AX,DX],[AX,DX]>, OpSize; // DX:AX/[mem16] = AX,DX -def IDIVm32: X86Inst<"idiv",0xF7, MRM7m , Arg32>, Imp<[EAX,EDX],[EAX,EDX]>; // EDX:EAX/[mem32] = EAX,EDX +def IDIVr8 : I <"idiv",0xF6, MRM7r>, Imp<[AX],[AX]>; // AX/r8 = AL,AH +def IDIVr16: I <"idiv",0xF7, MRM7r>, Imp<[AX,DX],[AX,DX]>, OpSize; // DX:AX/r16 = AX,DX +def IDIVr32: I <"idiv",0xF7, MRM7r>, Imp<[EAX,EDX],[EAX,EDX]>; // EDX:EAX/r32 = EAX,EDX +def IDIVm8 : IM8 <"idiv",0xF6, MRM7m>, Imp<[AX],[AX]>; // AX/[mem8] = AL,AH +def IDIVm16: IM16<"idiv",0xF7, MRM7m>, Imp<[AX,DX],[AX,DX]>, OpSize; // DX:AX/[mem16] = AX,DX +def IDIVm32: IM32<"idiv",0xF7, MRM7m>, Imp<[EAX,EDX],[EAX,EDX]>; // EDX:EAX/[mem32] = EAX,EDX // Sign-extenders for division -def CBW : X86Inst<"cbw", 0x98, RawFrm, Arg8 >, Imp<[AL],[AH]>; // AX = signext(AL) -def CWD : X86Inst<"cwd", 0x99, RawFrm, Arg8 >, Imp<[AX],[DX]>; // DX:AX = signext(AX) -def CDQ : X86Inst<"cdq", 0x99, RawFrm, Arg8 >, Imp<[EAX],[EDX]>; // EDX:EAX = signext(EAX) +def CBW : I<"cbw", 0x98, RawFrm >, Imp<[AL],[AH]>; // AX = signext(AL) +def CWD : I<"cwd", 0x99, RawFrm >, Imp<[AX],[DX]>; // DX:AX = signext(AX) +def CDQ : I<"cdq", 0x99, RawFrm >, Imp<[EAX],[EDX]>; // EDX:EAX = signext(EAX) //===----------------------------------------------------------------------===// // Two address Instructions... // -let isTwoAddress = 1 in { // Define some helper classes to make defs shorter. - class I2A8 <string n, bits<8> o, Format F> : X86Inst<n, o, F, Arg8>; - class I2A16<string n, bits<8> o, Format F> : X86Inst<n, o, F, Arg16>; - class I2A32<string n, bits<8> o, Format F> : X86Inst<n, o, F, Arg32>; -} +let isTwoAddress = 1 in { + +// Conditional moves. These are modelled as X = cmovXX Y, Z. Eventually +// register allocated to cmovXX XY, Z +def CMOVErr16 : I<"cmove", 0x44, MRMSrcReg>, TB, OpSize; // if ==, R16 = R16 +def CMOVNErr32: I<"cmovne",0x45, MRMSrcReg>, TB; // if !=, R32 = R32 +def CMOVSrr32 : I<"cmovs", 0x48, MRMSrcReg>, TB; // if signed, R32 = R32 // unary instructions -def NEGr8 : I2A8 <"neg", 0xF6, MRM3r >; // R8 = -R8 = 0-R8 -def NEGr16 : I2A16<"neg", 0xF7, MRM3r >, OpSize; // R16 = -R16 = 0-R16 -def NEGr32 : I2A32<"neg", 0xF7, MRM3r >; // R32 = -R32 = 0-R32 -def NEGm8 : I2A8 <"neg", 0xF6, MRM3m >; // [mem8] = -[mem8] = 0-[mem8] -def NEGm16 : I2A16<"neg", 0xF7, MRM3m >, OpSize; // [mem16] = -[mem16] = 0-[mem16] -def NEGm32 : I2A32<"neg", 0xF7, MRM3m >; // [mem32] = -[mem32] = 0-[mem32] - -def NOTr8 : I2A8 <"not", 0xF6, MRM2r >; // R8 = ~R8 = R8^-1 -def NOTr16 : I2A16<"not", 0xF7, MRM2r >, OpSize; // R16 = ~R16 = R16^-1 -def NOTr32 : I2A32<"not", 0xF7, MRM2r >; // R32 = ~R32 = R32^-1 -def NOTm8 : I2A8 <"not", 0xF6, MRM2m >; // [mem8] = ~[mem8] = [mem8^-1] -def NOTm16 : I2A16<"not", 0xF7, MRM2m >, OpSize; // [mem16] = ~[mem16] = [mem16^-1] -def NOTm32 : I2A32<"not", 0xF7, MRM2m >; // [mem32] = ~[mem32] = [mem32^-1] - -def INCr8 : I2A8 <"inc", 0xFE, MRM0r >; // ++R8 -def INCr16 : I2A16<"inc", 0xFF, MRM0r >, OpSize; // ++R16 -def INCr32 : I2A32<"inc", 0xFF, MRM0r >; // ++R32 -def INCm8 : I2A8 <"inc", 0xFE, MRM0m >; // ++R8 -def INCm16 : I2A16<"inc", 0xFF, MRM0m >, OpSize; // ++R16 -def INCm32 : I2A32<"inc", 0xFF, MRM0m >; // ++R32 - -def DECr8 : I2A8 <"dec", 0xFE, MRM1r >; // --R8 -def DECr16 : I2A16<"dec", 0xFF, MRM1r >, OpSize; // --R16 -def DECr32 : I2A32<"dec", 0xFF, MRM1r >; // --R32 -def DECm8 : I2A8 <"dec", 0xFE, MRM1m >; // --[mem8] -def DECm16 : I2A16<"dec", 0xFF, MRM1m >, OpSize; // --[mem16] -def DECm32 : I2A32<"dec", 0xFF, MRM1m >; // --[mem32] +def NEGr8 : I <"neg", 0xF6, MRM3r>; // R8 = -R8 = 0-R8 +def NEGr16 : I <"neg", 0xF7, MRM3r>, OpSize; // R16 = -R16 = 0-R16 +def NEGr32 : I <"neg", 0xF7, MRM3r>; // R32 = -R32 = 0-R32 +def NEGm8 : IM8 <"neg", 0xF6, MRM3m>; // [mem8] = -[mem8] = 0-[mem8] +def NEGm16 : IM16<"neg", 0xF7, MRM3m>, OpSize; // [mem16] = -[mem16] = 0-[mem16] +def NEGm32 : IM32<"neg", 0xF7, MRM3m>; // [mem32] = -[mem32] = 0-[mem32] + +def NOTr8 : I <"not", 0xF6, MRM2r>; // R8 = ~R8 = R8^-1 +def NOTr16 : I <"not", 0xF7, MRM2r>, OpSize; // R16 = ~R16 = R16^-1 +def NOTr32 : I <"not", 0xF7, MRM2r>; // R32 = ~R32 = R32^-1 +def NOTm8 : IM8 <"not", 0xF6, MRM2m>; // [mem8] = ~[mem8] = [mem8^-1] +def NOTm16 : IM16<"not", 0xF7, MRM2m>, OpSize; // [mem16] = ~[mem16] = [mem16^-1] +def NOTm32 : IM32<"not", 0xF7, MRM2m>; // [mem32] = ~[mem32] = [mem32^-1] + +def INCr8 : I <"inc", 0xFE, MRM0r>; // ++R8 +def INCr16 : I <"inc", 0xFF, MRM0r>, OpSize; // ++R16 +def INCr32 : I <"inc", 0xFF, MRM0r>; // ++R32 +def INCm8 : IM8 <"inc", 0xFE, MRM0m>; // ++R8 +def INCm16 : IM16<"inc", 0xFF, MRM0m>, OpSize; // ++R16 +def INCm32 : IM32<"inc", 0xFF, MRM0m>; // ++R32 + +def DECr8 : I <"dec", 0xFE, MRM1r>; // --R8 +def DECr16 : I <"dec", 0xFF, MRM1r>, OpSize; // --R16 +def DECr32 : I <"dec", 0xFF, MRM1r>; // --R32 +def DECm8 : IM8 <"dec", 0xFE, MRM1m>; // --[mem8] +def DECm16 : IM16<"dec", 0xFF, MRM1m>, OpSize; // --[mem16] +def DECm32 : IM32<"dec", 0xFF, MRM1m>; // --[mem32] + +// Logical operators... +def ANDrr8 : I <"and", 0x20, MRMDestReg>, Pattern<(set R8 , (and R8 , R8 ))>; +def ANDrr16 : I <"and", 0x21, MRMDestReg>, OpSize, Pattern<(set R16, (and R16, R16))>; +def ANDrr32 : I <"and", 0x21, MRMDestReg>, Pattern<(set R32, (and R32, R32))>; +def ANDmr8 : IM8 <"and", 0x20, MRMDestMem>; // [mem8] &= R8 +def ANDmr16 : IM16 <"and", 0x21, MRMDestMem>, OpSize; // [mem16] &= R16 +def ANDmr32 : IM32 <"and", 0x21, MRMDestMem>; // [mem32] &= R32 +def ANDrm8 : IM8 <"and", 0x22, MRMSrcMem >; // R8 &= [mem8] +def ANDrm16 : IM16 <"and", 0x23, MRMSrcMem >, OpSize; // R16 &= [mem16] +def ANDrm32 : IM32 <"and", 0x23, MRMSrcMem >; // R32 &= [mem32] + +def ANDri8 : II8 <"and", 0x80, MRM4r >, Pattern<(set R8 , (and R8 , imm))>; +def ANDri16 : II16 <"and", 0x81, MRM4r >, OpSize, Pattern<(set R16, (and R16, imm))>; +def ANDri32 : II32 <"and", 0x81, MRM4r >, Pattern<(set R32, (and R32, imm))>; +def ANDmi8 : I8MI <"and", 0x80, MRM4m >; // [mem8] &= imm8 +def ANDmi16 : I16MI <"and", 0x81, MRM4m >, OpSize; // [mem16] &= imm16 +def ANDmi32 : I32MI <"and", 0x81, MRM4m >; // [mem32] &= imm32 + +def ANDri16b : II8 <"and", 0x83, MRM4r >, OpSize; // R16 &= imm8 +def ANDri32b : II8 <"and", 0x83, MRM4r >; // R32 &= imm8 +def ANDmi16b : IM16I8<"and", 0x83, MRM4m >, OpSize; // [mem16] &= imm8 +def ANDmi32b : IM32I8<"and", 0x83, MRM4m >; // [mem32] &= imm8 + + +def ORrr8 : I <"or" , 0x08, MRMDestReg>, Pattern<(set R8 , (or R8 , R8 ))>; +def ORrr16 : I <"or" , 0x09, MRMDestReg>, OpSize, Pattern<(set R16, (or R16, R16))>; +def ORrr32 : I <"or" , 0x09, MRMDestReg>, Pattern<(set R32, (or R32, R32))>; +def ORmr8 : IM8 <"or" , 0x08, MRMDestMem>; // [mem8] |= R8 +def ORmr16 : IM16 <"or" , 0x09, MRMDestMem>, OpSize; // [mem16] |= R16 +def ORmr32 : IM32 <"or" , 0x09, MRMDestMem>; // [mem32] |= R32 +def ORrm8 : IM8 <"or" , 0x0A, MRMSrcMem >; // R8 |= [mem8] +def ORrm16 : IM16 <"or" , 0x0B, MRMSrcMem >, OpSize; // R16 |= [mem16] +def ORrm32 : IM32 <"or" , 0x0B, MRMSrcMem >; // R32 |= [mem32] + +def ORri8 : II8 <"or" , 0x80, MRM1r >, Pattern<(set R8 , (or R8 , imm))>; +def ORri16 : II16 <"or" , 0x81, MRM1r >, OpSize, Pattern<(set R16, (or R16, imm))>; +def ORri32 : II32 <"or" , 0x81, MRM1r >, Pattern<(set R32, (or R32, imm))>; +def ORmi8 : I8MI <"or" , 0x80, MRM1m >; // [mem8] |= imm8 +def ORmi16 : I16MI <"or" , 0x81, MRM1m >, OpSize; // [mem16] |= imm16 +def ORmi32 : I32MI <"or" , 0x81, MRM1m >; // [mem32] |= imm32 + +def ORri16b : II8 <"or" , 0x83, MRM1r >, OpSize; // R16 |= imm8 +def ORri32b : II8 <"or" , 0x83, MRM1r >; // R32 |= imm8 +def ORmi16b : IM16I8<"or" , 0x83, MRM1m >, OpSize; // [mem16] |= imm8 +def ORmi32b : IM32I8<"or" , 0x83, MRM1m >; // [mem32] |= imm8 + + +def XORrr8 : I <"xor", 0x30, MRMDestReg>, Pattern<(set R8 , (xor R8 , R8 ))>; +def XORrr16 : I <"xor", 0x31, MRMDestReg>, OpSize, Pattern<(set R16, (xor R16, R16))>; +def XORrr32 : I <"xor", 0x31, MRMDestReg>, Pattern<(set R32, (xor R32, R32))>; +def XORmr8 : IM8 <"xor", 0x30, MRMDestMem>; // [mem8] ^= R8 +def XORmr16 : IM16 <"xor", 0x31, MRMDestMem>, OpSize; // [mem16] ^= R16 +def XORmr32 : IM32 <"xor", 0x31, MRMDestMem>; // [mem32] ^= R32 +def XORrm8 : IM8 <"xor", 0x32, MRMSrcMem >; // R8 ^= [mem8] +def XORrm16 : IM16 <"xor", 0x33, MRMSrcMem >, OpSize; // R16 ^= [mem16] +def XORrm32 : IM32 <"xor", 0x33, MRMSrcMem >; // R32 ^= [mem32] + +def XORri8 : II8 <"xor", 0x80, MRM6r >, Pattern<(set R8 , (xor R8 , imm))>; +def XORri16 : II16 <"xor", 0x81, MRM6r >, OpSize, Pattern<(set R16, (xor R16, imm))>; +def XORri32 : II32 <"xor", 0x81, MRM6r >, Pattern<(set R32, (xor R32, imm))>; +def XORmi8 : I8MI <"xor", 0x80, MRM6m >; // [mem8] ^= R8 +def XORmi16 : I16MI <"xor", 0x81, MRM6m >, OpSize; // [mem16] ^= R16 +def XORmi32 : I32MI <"xor", 0x81, MRM6m >; // [mem32] ^= R32 + +def XORri16b : II8 <"xor", 0x83, MRM6r >, OpSize; // R16 ^= imm8 +def XORri32b : II8 <"xor", 0x83, MRM6r >; // R32 ^= imm8 +def XORmi16b : IM16I8<"xor", 0x83, MRM6m >, OpSize; // [mem16] ^= imm8 +def XORmi32b : IM32I8<"xor", 0x83, MRM6m >; // [mem32] ^= imm8 +// Shift instructions +def SHLrCL8 : I <"shl", 0xD2, MRM4r > , UsesCL; // R8 <<= cl +def SHLrCL16 : I <"shl", 0xD3, MRM4r >, OpSize, UsesCL; // R16 <<= cl +def SHLrCL32 : I <"shl", 0xD3, MRM4r > , UsesCL; // R32 <<= cl +def SHLmCL8 : IM8 <"shl", 0xD2, MRM4m > , UsesCL; // [mem8] <<= cl +def SHLmCL16 : IM16 <"shl", 0xD3, MRM4m >, OpSize, UsesCL; // [mem16] <<= cl +def SHLmCL32 : IM32 <"shl", 0xD3, MRM4m > , UsesCL; // [mem32] <<= cl + +def SHLri8 : II8 <"shl", 0xC0, MRM4r |