forked from OSchip/llvm-project
[X86] Create a new instruction format to handle MemOp4 encoding. This saves one bit in TSFlags and simplifies MRMSrcMem/MRMSrcReg format handling.
llvm-svn: 279423
This commit is contained in:
parent
61b62e56b7
commit
9b20fece81
|
@ -277,6 +277,11 @@ namespace X86II {
|
|||
///
|
||||
MRMSrcMem = 33,
|
||||
|
||||
/// MRMSrcMemOp4 - This form is used for instructions that use the Mod/RM
|
||||
/// byte to specify the fourth source, which in this case is memory.
|
||||
///
|
||||
MRMSrcMemOp4 = 34,
|
||||
|
||||
/// MRMXm - This form is used for instructions that use the Mod/RM byte
|
||||
/// to specify a memory source, but doesn't use the middle field.
|
||||
///
|
||||
|
@ -296,6 +301,11 @@ namespace X86II {
|
|||
///
|
||||
MRMSrcReg = 49,
|
||||
|
||||
/// MRMSrcRegOp4 - This form is used for instructions that use the Mod/RM
|
||||
/// byte to specify the fourth source, which in this case is a register.
|
||||
///
|
||||
MRMSrcRegOp4 = 50,
|
||||
|
||||
/// MRMXr - This form is used for instructions that use the Mod/RM byte
|
||||
/// to specify a register source, but doesn't use the middle field.
|
||||
///
|
||||
|
@ -536,13 +546,8 @@ namespace X86II {
|
|||
Has3DNow0F0FOpcodeShift = CD8_Scale_Shift + 7,
|
||||
Has3DNow0F0FOpcode = 1ULL << Has3DNow0F0FOpcodeShift,
|
||||
|
||||
/// MemOp4 - Used to indicate swapping of operand 3 and 4 to be encoded in
|
||||
/// ModRM or I8IMM. This is used for FMA4 and XOP instructions.
|
||||
MemOp4Shift = Has3DNow0F0FOpcodeShift + 1,
|
||||
MemOp4 = 1ULL << MemOp4Shift,
|
||||
|
||||
/// Explicitly specified rounding control
|
||||
EVEX_RCShift = MemOp4Shift + 1,
|
||||
EVEX_RCShift = Has3DNow0F0FOpcodeShift + 1,
|
||||
EVEX_RC = 1ULL << EVEX_RCShift
|
||||
};
|
||||
|
||||
|
@ -649,7 +654,6 @@ namespace X86II {
|
|||
///
|
||||
inline int getMemoryOperandNo(uint64_t TSFlags) {
|
||||
bool HasVEX_4V = TSFlags & X86II::VEX_4V;
|
||||
bool HasMemOp4 = TSFlags & X86II::MemOp4;
|
||||
bool HasEVEX_K = TSFlags & X86II::EVEX_K;
|
||||
|
||||
switch (TSFlags & X86II::FormMask) {
|
||||
|
@ -669,9 +673,13 @@ namespace X86II {
|
|||
case X86II::MRMSrcMem:
|
||||
// Start from 1, skip any registers encoded in VEX_VVVV or I8IMM, or a
|
||||
// mask register.
|
||||
return 1 + HasVEX_4V + HasMemOp4 + HasEVEX_K;
|
||||
return 1 + HasVEX_4V + HasEVEX_K;
|
||||
case X86II::MRMSrcMemOp4:
|
||||
// Skip registers encoded in reg, VEX_VVVV, and I8IMM.
|
||||
return 3;
|
||||
case X86II::MRMDestReg:
|
||||
case X86II::MRMSrcReg:
|
||||
case X86II::MRMSrcRegOp4:
|
||||
case X86II::MRMXr:
|
||||
case X86II::MRM0r: case X86II::MRM1r:
|
||||
case X86II::MRM2r: case X86II::MRM3r:
|
||||
|
|
|
@ -603,7 +603,6 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
|
|||
bool HasEVEX_K = TSFlags & X86II::EVEX_K;
|
||||
bool HasVEX_4V = TSFlags & X86II::VEX_4V;
|
||||
bool HasVEX_4VOp3 = TSFlags & X86II::VEX_4VOp3;
|
||||
bool HasMemOp4 = TSFlags & X86II::MemOp4;
|
||||
bool HasEVEX_RC = TSFlags & X86II::EVEX_RC;
|
||||
|
||||
// VEX_R: opcode externsion equivalent to REX.R in
|
||||
|
@ -749,7 +748,6 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
|
|||
//
|
||||
// FMA4:
|
||||
// dst(ModR/M.reg), src1(VEX_4V), src2(ModR/M), src3(Imm[7:4])
|
||||
// dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M),
|
||||
unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
|
||||
VEX_R = ~(RegEnc >> 3) & 1;
|
||||
EVEX_R2 = ~(RegEnc >> 4) & 1;
|
||||
|
@ -779,6 +777,20 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
|
|||
VEX_4V = ~getX86RegEncoding(MI, CurOp + X86::AddrNumOperands) & 0xf;
|
||||
break;
|
||||
}
|
||||
case X86II::MRMSrcMemOp4: {
|
||||
// dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M),
|
||||
unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
|
||||
VEX_R = ~(RegEnc >> 3) & 1;
|
||||
|
||||
unsigned VRegEnc = getX86RegEncoding(MI, CurOp++);
|
||||
VEX_4V = ~VRegEnc & 0xf;
|
||||
|
||||
unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg);
|
||||
VEX_B = ~(BaseRegEnc >> 3) & 1;
|
||||
unsigned IndexRegEnc = getX86RegEncoding(MI, MemOperand+X86::AddrIndexReg);
|
||||
VEX_X = ~(IndexRegEnc >> 3) & 1;
|
||||
break;
|
||||
}
|
||||
case X86II::MRM0m: case X86II::MRM1m:
|
||||
case X86II::MRM2m: case X86II::MRM3m:
|
||||
case X86II::MRM4m: case X86II::MRM5m:
|
||||
|
@ -808,7 +820,6 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
|
|||
// dst(ModR/M), src1(ModR/M), imm8
|
||||
//
|
||||
// FMA4:
|
||||
// dst(ModR/M.reg), src1(VEX_4V), src2(ModR/M), src3(Imm[7:4])
|
||||
// dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M),
|
||||
unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
|
||||
VEX_R = ~(RegEnc >> 3) & 1;
|
||||
|
@ -823,9 +834,6 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
|
|||
EVEX_V2 = ~(VRegEnc >> 4) & 1;
|
||||
}
|
||||
|
||||
if (HasMemOp4) // Skip second register source (encoded in Imm[7:4])
|
||||
CurOp++;
|
||||
|
||||
RegEnc = getX86RegEncoding(MI, CurOp++);
|
||||
VEX_B = ~(RegEnc >> 3) & 1;
|
||||
VEX_X = ~(RegEnc >> 4) & 1;
|
||||
|
@ -841,6 +849,22 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case X86II::MRMSrcRegOp4: {
|
||||
// dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M),
|
||||
unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
|
||||
VEX_R = ~(RegEnc >> 3) & 1;
|
||||
|
||||
unsigned VRegEnc = getX86RegEncoding(MI, CurOp++);
|
||||
VEX_4V = ~VRegEnc & 0xf;
|
||||
|
||||
// Skip second register source (encoded in Imm[7:4])
|
||||
++CurOp;
|
||||
|
||||
RegEnc = getX86RegEncoding(MI, CurOp++);
|
||||
VEX_B = ~(RegEnc >> 3) & 1;
|
||||
VEX_X = ~(RegEnc >> 4) & 1;
|
||||
break;
|
||||
}
|
||||
case X86II::MRMDestReg: {
|
||||
// MRMDestReg instructions forms:
|
||||
// dst(ModR/M), src(ModR/M)
|
||||
|
@ -1134,9 +1158,7 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
|||
// It uses the VEX.VVVV field?
|
||||
bool HasVEX_4V = TSFlags & X86II::VEX_4V;
|
||||
bool HasVEX_4VOp3 = TSFlags & X86II::VEX_4VOp3;
|
||||
bool HasMemOp4 = TSFlags & X86II::MemOp4;
|
||||
bool HasVEX_I8Reg = (TSFlags & X86II::ImmMask) == X86II::Imm8Reg;
|
||||
assert((!HasMemOp4 || HasVEX_I8Reg) && "MemOp4 should imply VEX_I8Reg");
|
||||
|
||||
// It uses the EVEX.aaa field?
|
||||
bool HasEVEX_K = TSFlags & X86II::EVEX_K;
|
||||
|
@ -1312,21 +1334,34 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
|||
if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV)
|
||||
++SrcRegNum;
|
||||
|
||||
if (HasMemOp4) // Capture 2nd src (which is encoded in Imm[7:4])
|
||||
I8RegNum = getX86RegEncoding(MI, SrcRegNum++);
|
||||
|
||||
EmitRegModRMByte(MI.getOperand(SrcRegNum),
|
||||
GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS);
|
||||
CurOp = SrcRegNum + 1;
|
||||
if (HasVEX_4VOp3)
|
||||
++CurOp;
|
||||
if (!HasMemOp4 && HasVEX_I8Reg)
|
||||
if (HasVEX_I8Reg)
|
||||
I8RegNum = getX86RegEncoding(MI, CurOp++);
|
||||
// do not count the rounding control operand
|
||||
if (HasEVEX_RC)
|
||||
--NumOps;
|
||||
break;
|
||||
}
|
||||
case X86II::MRMSrcRegOp4: {
|
||||
EmitByte(BaseOpcode, CurByte, OS);
|
||||
unsigned SrcRegNum = CurOp + 1;
|
||||
|
||||
// Skip 1st src (which is encoded in VEX_VVVV)
|
||||
++SrcRegNum;
|
||||
|
||||
// Capture 2nd src (which is encoded in Imm[7:4])
|
||||
assert(HasVEX_I8Reg && "MRMSrcRegOp4 should imply VEX_I8Reg");
|
||||
I8RegNum = getX86RegEncoding(MI, SrcRegNum++);
|
||||
|
||||
EmitRegModRMByte(MI.getOperand(SrcRegNum),
|
||||
GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS);
|
||||
CurOp = SrcRegNum + 1;
|
||||
break;
|
||||
}
|
||||
case X86II::MRMSrcMem: {
|
||||
unsigned FirstMemOp = CurOp+1;
|
||||
|
||||
|
@ -1336,9 +1371,6 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
|||
if (HasVEX_4V)
|
||||
++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV).
|
||||
|
||||
if (HasMemOp4) // Capture second register source (encoded in Imm[7:4])
|
||||
I8RegNum = getX86RegEncoding(MI, FirstMemOp++);
|
||||
|
||||
EmitByte(BaseOpcode, CurByte, OS);
|
||||
|
||||
emitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)),
|
||||
|
@ -1346,10 +1378,26 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
|||
CurOp = FirstMemOp + X86::AddrNumOperands;
|
||||
if (HasVEX_4VOp3)
|
||||
++CurOp;
|
||||
if (!HasMemOp4 && HasVEX_I8Reg)
|
||||
if (HasVEX_I8Reg)
|
||||
I8RegNum = getX86RegEncoding(MI, CurOp++);
|
||||
break;
|
||||
}
|
||||
case X86II::MRMSrcMemOp4: {
|
||||
unsigned FirstMemOp = CurOp+1;
|
||||
|
||||
++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV).
|
||||
|
||||
// Capture second register source (encoded in Imm[7:4])
|
||||
assert(HasVEX_I8Reg && "MRMSrcRegOp4 should imply VEX_I8Reg");
|
||||
I8RegNum = getX86RegEncoding(MI, FirstMemOp++);
|
||||
|
||||
EmitByte(BaseOpcode, CurByte, OS);
|
||||
|
||||
emitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)),
|
||||
TSFlags, Rex, CurByte, OS, Fixups, STI);
|
||||
CurOp = FirstMemOp + X86::AddrNumOperands;
|
||||
break;
|
||||
}
|
||||
|
||||
case X86II::MRMXr:
|
||||
case X86II::MRM0r: case X86II::MRM1r:
|
||||
|
|
|
@ -269,18 +269,18 @@ multiclass fma4s<bits<8> opc, string OpcodeStr, RegisterClass RC,
|
|||
X86MemOperand x86memop, ValueType OpVT, SDNode OpNode,
|
||||
PatFrag mem_frag> {
|
||||
let isCommutable = 1 in
|
||||
def rr : FMA4<opc, MRMSrcReg, (outs RC:$dst),
|
||||
def rr : FMA4<opc, MRMSrcRegOp4, (outs RC:$dst),
|
||||
(ins RC:$src1, RC:$src2, RC:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
||||
[(set RC:$dst,
|
||||
(OpVT (OpNode RC:$src1, RC:$src2, RC:$src3)))]>, VEX_W, VEX_LIG, MemOp4;
|
||||
def rm : FMA4<opc, MRMSrcMem, (outs RC:$dst),
|
||||
(OpVT (OpNode RC:$src1, RC:$src2, RC:$src3)))]>, VEX_W, VEX_LIG;
|
||||
def rm : FMA4<opc, MRMSrcMemOp4, (outs RC:$dst),
|
||||
(ins RC:$src1, RC:$src2, x86memop:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
||||
[(set RC:$dst, (OpNode RC:$src1, RC:$src2,
|
||||
(mem_frag addr:$src3)))]>, VEX_W, VEX_LIG, MemOp4;
|
||||
(mem_frag addr:$src3)))]>, VEX_W, VEX_LIG;
|
||||
def mr : FMA4<opc, MRMSrcMem, (outs RC:$dst),
|
||||
(ins RC:$src1, x86memop:$src2, RC:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
|
@ -300,18 +300,18 @@ multiclass fma4s_int<bits<8> opc, string OpcodeStr, Operand memop,
|
|||
ComplexPattern mem_cpat, Intrinsic Int> {
|
||||
let isCodeGenOnly = 1 in {
|
||||
let isCommutable = 1 in
|
||||
def rr_Int : FMA4<opc, MRMSrcReg, (outs VR128:$dst),
|
||||
def rr_Int : FMA4<opc, MRMSrcRegOp4, (outs VR128:$dst),
|
||||
(ins VR128:$src1, VR128:$src2, VR128:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
||||
[(set VR128:$dst,
|
||||
(Int VR128:$src1, VR128:$src2, VR128:$src3))]>, VEX_W, VEX_LIG, MemOp4;
|
||||
def rm_Int : FMA4<opc, MRMSrcMem, (outs VR128:$dst),
|
||||
(Int VR128:$src1, VR128:$src2, VR128:$src3))]>, VEX_W, VEX_LIG;
|
||||
def rm_Int : FMA4<opc, MRMSrcMemOp4, (outs VR128:$dst),
|
||||
(ins VR128:$src1, VR128:$src2, memop:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
||||
[(set VR128:$dst, (Int VR128:$src1, VR128:$src2,
|
||||
mem_cpat:$src3))]>, VEX_W, VEX_LIG, MemOp4;
|
||||
mem_cpat:$src3))]>, VEX_W, VEX_LIG;
|
||||
def mr_Int : FMA4<opc, MRMSrcMem, (outs VR128:$dst),
|
||||
(ins VR128:$src1, memop:$src2, VR128:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
|
@ -325,19 +325,19 @@ multiclass fma4p<bits<8> opc, string OpcodeStr, SDNode OpNode,
|
|||
ValueType OpVT128, ValueType OpVT256,
|
||||
PatFrag ld_frag128, PatFrag ld_frag256> {
|
||||
let isCommutable = 1 in
|
||||
def rr : FMA4<opc, MRMSrcReg, (outs VR128:$dst),
|
||||
def rr : FMA4<opc, MRMSrcRegOp4, (outs VR128:$dst),
|
||||
(ins VR128:$src1, VR128:$src2, VR128:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
||||
[(set VR128:$dst,
|
||||
(OpVT128 (OpNode VR128:$src1, VR128:$src2, VR128:$src3)))]>,
|
||||
VEX_W, MemOp4;
|
||||
def rm : FMA4<opc, MRMSrcMem, (outs VR128:$dst),
|
||||
VEX_W;
|
||||
def rm : FMA4<opc, MRMSrcMemOp4, (outs VR128:$dst),
|
||||
(ins VR128:$src1, VR128:$src2, f128mem:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
||||
[(set VR128:$dst, (OpNode VR128:$src1, VR128:$src2,
|
||||
(ld_frag128 addr:$src3)))]>, VEX_W, MemOp4;
|
||||
(ld_frag128 addr:$src3)))]>, VEX_W;
|
||||
def mr : FMA4<opc, MRMSrcMem, (outs VR128:$dst),
|
||||
(ins VR128:$src1, f128mem:$src2, VR128:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
|
@ -345,19 +345,19 @@ multiclass fma4p<bits<8> opc, string OpcodeStr, SDNode OpNode,
|
|||
[(set VR128:$dst,
|
||||
(OpNode VR128:$src1, (ld_frag128 addr:$src2), VR128:$src3))]>;
|
||||
let isCommutable = 1 in
|
||||
def Yrr : FMA4<opc, MRMSrcReg, (outs VR256:$dst),
|
||||
def Yrr : FMA4<opc, MRMSrcRegOp4, (outs VR256:$dst),
|
||||
(ins VR256:$src1, VR256:$src2, VR256:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
||||
[(set VR256:$dst,
|
||||
(OpVT256 (OpNode VR256:$src1, VR256:$src2, VR256:$src3)))]>,
|
||||
VEX_W, MemOp4, VEX_L;
|
||||
def Yrm : FMA4<opc, MRMSrcMem, (outs VR256:$dst),
|
||||
VEX_W, VEX_L;
|
||||
def Yrm : FMA4<opc, MRMSrcMemOp4, (outs VR256:$dst),
|
||||
(ins VR256:$src1, VR256:$src2, f256mem:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
||||
[(set VR256:$dst, (OpNode VR256:$src1, VR256:$src2,
|
||||
(ld_frag256 addr:$src3)))]>, VEX_W, MemOp4, VEX_L;
|
||||
(ld_frag256 addr:$src3)))]>, VEX_W, VEX_L;
|
||||
def Ymr : FMA4<opc, MRMSrcMem, (outs VR256:$dst),
|
||||
(ins VR256:$src1, f256mem:$src2, VR256:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
|
|
|
@ -27,14 +27,16 @@ def RawFrmDst : Format<5>;
|
|||
def RawFrmDstSrc : Format<6>;
|
||||
def RawFrmImm8 : Format<7>;
|
||||
def RawFrmImm16 : Format<8>;
|
||||
def MRMDestMem : Format<32>;
|
||||
def MRMSrcMem : Format<33>;
|
||||
def MRMDestMem : Format<32>;
|
||||
def MRMSrcMem : Format<33>;
|
||||
def MRMSrcMemOp4 : Format<34>;
|
||||
def MRMXm : Format<39>;
|
||||
def MRM0m : Format<40>; def MRM1m : Format<41>; def MRM2m : Format<42>;
|
||||
def MRM3m : Format<43>; def MRM4m : Format<44>; def MRM5m : Format<45>;
|
||||
def MRM6m : Format<46>; def MRM7m : Format<47>;
|
||||
def MRMDestReg : Format<48>;
|
||||
def MRMSrcReg : Format<49>;
|
||||
def MRMDestReg : Format<48>;
|
||||
def MRMSrcReg : Format<49>;
|
||||
def MRMSrcRegOp4 : Format<50>;
|
||||
def MRMXr : Format<55>;
|
||||
def MRM0r : Format<56>; def MRM1r : Format<57>; def MRM2r : Format<58>;
|
||||
def MRM3r : Format<59>; def MRM4r : Format<60>; def MRM5r : Format<61>;
|
||||
|
@ -218,7 +220,6 @@ class EVEX_CD8<int esize, CD8VForm form> {
|
|||
}
|
||||
|
||||
class Has3DNow0F0FOpcode { bit has3DNow0F0FOpcode = 1; }
|
||||
class MemOp4 { bit hasMemOp4Prefix = 1; }
|
||||
class XOP { Encoding OpEnc = EncXOP; }
|
||||
class XOP_4V : XOP { bit hasVEX_4V = 1; }
|
||||
class XOP_4VOp3 : XOP { bit hasVEX_4VOp3 = 1; }
|
||||
|
@ -284,7 +285,6 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
|
|||
// assigning to bits<7>.
|
||||
int CD8_EltSize = 0; // Compressed disp8 form - element-size in bytes.
|
||||
bit has3DNow0F0FOpcode =0;// Wacky 3dNow! encoding?
|
||||
bit hasMemOp4Prefix = 0; // Same bit as VEX_W, but used for swapping operands
|
||||
bit hasEVEX_RC = 0; // Explicitly specified rounding control in FP instruction.
|
||||
|
||||
bits<2> EVEX_LL;
|
||||
|
@ -330,8 +330,7 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
|
|||
// If we run out of TSFlags bits, it's possible to encode this in 3 bits.
|
||||
let TSFlags{53-47} = CD8_Scale;
|
||||
let TSFlags{54} = has3DNow0F0FOpcode;
|
||||
let TSFlags{55} = hasMemOp4Prefix;
|
||||
let TSFlags{56} = hasEVEX_RC;
|
||||
let TSFlags{55} = hasEVEX_RC;
|
||||
}
|
||||
|
||||
class PseudoI<dag oops, dag iops, list<dag> pattern>
|
||||
|
|
|
@ -232,14 +232,14 @@ multiclass xop4op<bits<8> opc, string OpcodeStr, SDNode OpNode,
|
|||
(vt128 (OpNode (vt128 VR128:$src1), (vt128 VR128:$src2),
|
||||
(vt128 VR128:$src3))))]>,
|
||||
XOP_4V;
|
||||
def rrm : IXOPi8Reg<opc, MRMSrcMem, (outs VR128:$dst),
|
||||
def rrm : IXOPi8Reg<opc, MRMSrcMemOp4, (outs VR128:$dst),
|
||||
(ins VR128:$src1, VR128:$src2, i128mem:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
||||
[(set VR128:$dst,
|
||||
(vt128 (OpNode (vt128 VR128:$src1), (vt128 VR128:$src2),
|
||||
(vt128 (bitconvert (loadv2i64 addr:$src3))))))]>,
|
||||
XOP_4V, VEX_W, MemOp4;
|
||||
XOP_4V, VEX_W;
|
||||
def rmr : IXOPi8Reg<opc, MRMSrcMem, (outs VR128:$dst),
|
||||
(ins VR128:$src1, i128mem:$src2, VR128:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
|
@ -250,11 +250,11 @@ multiclass xop4op<bits<8> opc, string OpcodeStr, SDNode OpNode,
|
|||
XOP_4V;
|
||||
// For disassembler
|
||||
let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in
|
||||
def rrr_REV : IXOPi8Reg<opc, MRMSrcReg, (outs VR128:$dst),
|
||||
def rrr_REV : IXOPi8Reg<opc, MRMSrcRegOp4, (outs VR128:$dst),
|
||||
(ins VR128:$src1, VR128:$src2, VR128:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
||||
[]>, XOP_4V, VEX_W, MemOp4;
|
||||
[]>, XOP_4V, VEX_W;
|
||||
}
|
||||
|
||||
let ExeDomain = SSEPackedInt in {
|
||||
|
@ -271,14 +271,14 @@ multiclass xop4op_int<bits<8> opc, string OpcodeStr,
|
|||
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
||||
[(set VR128:$dst, (Int128 VR128:$src1, VR128:$src2, VR128:$src3))]>,
|
||||
XOP_4V;
|
||||
def rrm : IXOPi8Reg<opc, MRMSrcMem, (outs VR128:$dst),
|
||||
def rrm : IXOPi8Reg<opc, MRMSrcMemOp4, (outs VR128:$dst),
|
||||
(ins VR128:$src1, VR128:$src2, i128mem:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
||||
[(set VR128:$dst,
|
||||
(Int128 VR128:$src1, VR128:$src2,
|
||||
(bitconvert (loadv2i64 addr:$src3))))]>,
|
||||
XOP_4V, VEX_W, MemOp4;
|
||||
XOP_4V, VEX_W;
|
||||
def rmr : IXOPi8Reg<opc, MRMSrcMem, (outs VR128:$dst),
|
||||
(ins VR128:$src1, i128mem:$src2, VR128:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
|
@ -289,11 +289,11 @@ multiclass xop4op_int<bits<8> opc, string OpcodeStr,
|
|||
XOP_4V;
|
||||
// For disassembler
|
||||
let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in
|
||||
def rrr_REV : IXOPi8Reg<opc, MRMSrcReg, (outs VR128:$dst),
|
||||
def rrr_REV : IXOPi8Reg<opc, MRMSrcRegOp4, (outs VR128:$dst),
|
||||
(ins VR128:$src1, VR128:$src2, VR128:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
||||
[]>, XOP_4V, VEX_W, MemOp4;
|
||||
[]>, XOP_4V, VEX_W;
|
||||
|
||||
// 256-bit Instruction
|
||||
def rrrY : IXOPi8Reg<opc, MRMSrcReg, (outs VR256:$dst),
|
||||
|
@ -302,14 +302,14 @@ multiclass xop4op_int<bits<8> opc, string OpcodeStr,
|
|||
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
||||
[(set VR256:$dst, (Int256 VR256:$src1, VR256:$src2, VR256:$src3))]>,
|
||||
XOP_4V, VEX_L;
|
||||
def rrmY : IXOPi8Reg<opc, MRMSrcMem, (outs VR256:$dst),
|
||||
def rrmY : IXOPi8Reg<opc, MRMSrcMemOp4, (outs VR256:$dst),
|
||||
(ins VR256:$src1, VR256:$src2, i256mem:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
||||
[(set VR256:$dst,
|
||||
(Int256 VR256:$src1, VR256:$src2,
|
||||
(bitconvert (loadv4i64 addr:$src3))))]>,
|
||||
XOP_4V, VEX_W, MemOp4, VEX_L;
|
||||
XOP_4V, VEX_W, VEX_L;
|
||||
def rmrY : IXOPi8Reg<opc, MRMSrcMem, (outs VR256:$dst),
|
||||
(ins VR256:$src1, f256mem:$src2, VR256:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
|
@ -320,11 +320,11 @@ multiclass xop4op_int<bits<8> opc, string OpcodeStr,
|
|||
XOP_4V, VEX_L;
|
||||
// For disassembler
|
||||
let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in
|
||||
def rrrY_REV : IXOPi8Reg<opc, MRMSrcReg, (outs VR256:$dst),
|
||||
def rrrY_REV : IXOPi8Reg<opc, MRMSrcRegOp4, (outs VR256:$dst),
|
||||
(ins VR256:$src1, VR256:$src2, VR256:$src3),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
||||
[]>, XOP_4V, VEX_W, MemOp4, VEX_L;
|
||||
[]>, XOP_4V, VEX_W, VEX_L;
|
||||
}
|
||||
|
||||
let ExeDomain = SSEPackedInt in {
|
||||
|
@ -353,7 +353,7 @@ multiclass xop5op<bits<8> opc, string OpcodeStr, SDNode OpNode,
|
|||
[(set VR128:$dst,
|
||||
(vt128 (OpNode (vt128 VR128:$src1), (vt128 VR128:$src2),
|
||||
(id128 VR128:$src3), (i8 imm:$src4))))]>;
|
||||
def rm : IXOP5<opc, MRMSrcMem, (outs VR128:$dst),
|
||||
def rm : IXOP5<opc, MRMSrcMemOp4, (outs VR128:$dst),
|
||||
(ins VR128:$src1, VR128:$src2, i128mem:$src3, u8imm:$src4),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src4, $src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3, $src4}"),
|
||||
|
@ -361,7 +361,7 @@ multiclass xop5op<bits<8> opc, string OpcodeStr, SDNode OpNode,
|
|||
(vt128 (OpNode (vt128 VR128:$src1), (vt128 VR128:$src2),
|
||||
(id128 (bitconvert (loadv2i64 addr:$src3))),
|
||||
(i8 imm:$src4))))]>,
|
||||
VEX_W, MemOp4;
|
||||
VEX_W;
|
||||
def mr : IXOP5<opc, MRMSrcMem, (outs VR128:$dst),
|
||||
(ins VR128:$src1, f128mem:$src2, VR128:$src3, u8imm:$src4),
|
||||
!strconcat(OpcodeStr,
|
||||
|
@ -372,11 +372,11 @@ multiclass xop5op<bits<8> opc, string OpcodeStr, SDNode OpNode,
|
|||
(id128 VR128:$src3), (i8 imm:$src4))))]>;
|
||||
// For disassembler
|
||||
let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in
|
||||
def rr_REV : IXOP5<opc, MRMSrcReg, (outs VR128:$dst),
|
||||
def rr_REV : IXOP5<opc, MRMSrcRegOp4, (outs VR128:$dst),
|
||||
(ins VR128:$src1, VR128:$src2, VR128:$src3, u8imm:$src4),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src4, $src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3, $src4}"),
|
||||
[]>, VEX_W, MemOp4;
|
||||
[]>, VEX_W;
|
||||
|
||||
def rrY : IXOP5<opc, MRMSrcReg, (outs VR256:$dst),
|
||||
(ins VR256:$src1, VR256:$src2, VR256:$src3, u8imm:$src4),
|
||||
|
@ -385,14 +385,14 @@ multiclass xop5op<bits<8> opc, string OpcodeStr, SDNode OpNode,
|
|||
[(set VR256:$dst,
|
||||
(vt256 (OpNode (vt256 VR256:$src1), (vt256 VR256:$src2),
|
||||
(id256 VR256:$src3), (i8 imm:$src4))))]>, VEX_L;
|
||||
def rmY : IXOP5<opc, MRMSrcMem, (outs VR256:$dst),
|
||||
def rmY : IXOP5<opc, MRMSrcMemOp4, (outs VR256:$dst),
|
||||
(ins VR256:$src1, VR256:$src2, i256mem:$src3, u8imm:$src4),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src4, $src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3, $src4}"),
|
||||
[(set VR256:$dst,
|
||||
(vt256 (OpNode (vt256 VR256:$src1), (vt256 VR256:$src2),
|
||||
(id256 (bitconvert (loadv4i64 addr:$src3))),
|
||||
(i8 imm:$src4))))]>, VEX_W, MemOp4, VEX_L;
|
||||
(i8 imm:$src4))))]>, VEX_W, VEX_L;
|
||||
def mrY : IXOP5<opc, MRMSrcMem, (outs VR256:$dst),
|
||||
(ins VR256:$src1, f256mem:$src2, VR256:$src3, u8imm:$src4),
|
||||
!strconcat(OpcodeStr,
|
||||
|
@ -403,11 +403,11 @@ multiclass xop5op<bits<8> opc, string OpcodeStr, SDNode OpNode,
|
|||
(id256 VR256:$src3), (i8 imm:$src4))))]>, VEX_L;
|
||||
// For disassembler
|
||||
let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in
|
||||
def rrY_REV : IXOP5<opc, MRMSrcReg, (outs VR256:$dst),
|
||||
def rrY_REV : IXOP5<opc, MRMSrcRegOp4, (outs VR256:$dst),
|
||||
(ins VR256:$src1, VR256:$src2, VR256:$src3, u8imm:$src4),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$src4, $src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3, $src4}"),
|
||||
[]>, VEX_W, MemOp4, VEX_L;
|
||||
[]>, VEX_W, VEX_L;
|
||||
}
|
||||
|
||||
let ExeDomain = SSEPackedDouble in
|
||||
|
|
|
@ -100,13 +100,15 @@ namespace X86Local {
|
|||
RawFrmDstSrc = 6,
|
||||
RawFrmImm8 = 7,
|
||||
RawFrmImm16 = 8,
|
||||
MRMDestMem = 32,
|
||||
MRMSrcMem = 33,
|
||||
MRMDestMem = 32,
|
||||
MRMSrcMem = 33,
|
||||
MRMSrcMemOp4 = 34,
|
||||
MRMXm = 39,
|
||||
MRM0m = 40, MRM1m = 41, MRM2m = 42, MRM3m = 43,
|
||||
MRM4m = 44, MRM5m = 45, MRM6m = 46, MRM7m = 47,
|
||||
MRMDestReg = 48,
|
||||
MRMSrcReg = 49,
|
||||
MRMDestReg = 48,
|
||||
MRMSrcReg = 49,
|
||||
MRMSrcRegOp4 = 50,
|
||||
MRMXr = 55,
|
||||
MRM0r = 56, MRM1r = 57, MRM2r = 58, MRM3r = 59,
|
||||
MRM4r = 60, MRM5r = 61, MRM6r = 62, MRM7r = 63,
|
||||
|
@ -201,7 +203,6 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
|
|||
HasVEX_4V = Rec->getValueAsBit("hasVEX_4V");
|
||||
HasVEX_4VOp3 = Rec->getValueAsBit("hasVEX_4VOp3");
|
||||
HasVEX_WPrefix = Rec->getValueAsBit("hasVEX_WPrefix");
|
||||
HasMemOp4Prefix = Rec->getValueAsBit("hasMemOp4Prefix");
|
||||
IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L");
|
||||
HasEVEX_L2Prefix = Rec->getValueAsBit("hasEVEX_L2");
|
||||
HasEVEX_K = Rec->getValueAsBit("hasEVEX_K");
|
||||
|
@ -653,19 +654,24 @@ void RecognizableInstr::emitInstructionSpecifier() {
|
|||
// in ModRMVEX and the one above the one in the VEX.VVVV field
|
||||
HANDLE_OPERAND(vvvvRegister)
|
||||
|
||||
if (HasMemOp4Prefix)
|
||||
HANDLE_OPERAND(immediate)
|
||||
|
||||
HANDLE_OPERAND(rmRegister)
|
||||
|
||||
if (HasVEX_4VOp3)
|
||||
HANDLE_OPERAND(vvvvRegister)
|
||||
|
||||
if (!HasMemOp4Prefix)
|
||||
HANDLE_OPTIONAL(immediate)
|
||||
HANDLE_OPTIONAL(immediate)
|
||||
HANDLE_OPTIONAL(immediate) // above might be a register in 7:4
|
||||
HANDLE_OPTIONAL(immediate)
|
||||
break;
|
||||
case X86Local::MRMSrcRegOp4:
|
||||
assert(numPhysicalOperands >= 4 && numPhysicalOperands <= 5 &&
|
||||
"Unexpected number of operands for MRMSrcRegOp4Frm");
|
||||
HANDLE_OPERAND(roRegister)
|
||||
HANDLE_OPERAND(vvvvRegister)
|
||||
HANDLE_OPERAND(immediate) // Register in imm[7:4]
|
||||
HANDLE_OPERAND(rmRegister)
|
||||
HANDLE_OPTIONAL(immediate)
|
||||
break;
|
||||
case X86Local::MRMSrcMem:
|
||||
// Operand 1 is a register operand in the Reg/Opcode field.
|
||||
// Operand 2 is a memory operand (possibly SIB-extended)
|
||||
|
@ -686,18 +692,23 @@ void RecognizableInstr::emitInstructionSpecifier() {
|
|||
// in ModRMVEX and the one above the one in the VEX.VVVV field
|
||||
HANDLE_OPERAND(vvvvRegister)
|
||||
|
||||
if (HasMemOp4Prefix)
|
||||
HANDLE_OPERAND(immediate)
|
||||
|
||||
HANDLE_OPERAND(memory)
|
||||
|
||||
if (HasVEX_4VOp3)
|
||||
HANDLE_OPERAND(vvvvRegister)
|
||||
|
||||
if (!HasMemOp4Prefix)
|
||||
HANDLE_OPTIONAL(immediate)
|
||||
HANDLE_OPTIONAL(immediate)
|
||||
HANDLE_OPTIONAL(immediate) // above might be a register in 7:4
|
||||
break;
|
||||
case X86Local::MRMSrcMemOp4:
|
||||
assert(numPhysicalOperands >= 4 && numPhysicalOperands <= 5 &&
|
||||
"Unexpected number of operands for MRMSrcMemOp4Frm");
|
||||
HANDLE_OPERAND(roRegister)
|
||||
HANDLE_OPERAND(vvvvRegister)
|
||||
HANDLE_OPERAND(immediate) // Register in imm[7:4]
|
||||
HANDLE_OPERAND(memory)
|
||||
HANDLE_OPTIONAL(immediate)
|
||||
break;
|
||||
case X86Local::MRMXr:
|
||||
case X86Local::MRM0r:
|
||||
case X86Local::MRM1r:
|
||||
|
@ -842,11 +853,13 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
|
|||
break;
|
||||
case X86Local::MRMDestReg:
|
||||
case X86Local::MRMSrcReg:
|
||||
case X86Local::MRMSrcRegOp4:
|
||||
case X86Local::MRMXr:
|
||||
filter = new ModFilter(true);
|
||||
break;
|
||||
case X86Local::MRMDestMem:
|
||||
case X86Local::MRMSrcMem:
|
||||
case X86Local::MRMSrcMemOp4:
|
||||
case X86Local::MRMXm:
|
||||
filter = new ModFilter(false);
|
||||
break;
|
||||
|
|
|
@ -61,8 +61,6 @@ private:
|
|||
bool HasVEX_WPrefix;
|
||||
/// Inferred from the operands; indicates whether the L bit in the VEX prefix is set
|
||||
bool HasVEX_LPrefix;
|
||||
/// The hasMemOp4Prefix field from the record
|
||||
bool HasMemOp4Prefix;
|
||||
/// The ignoreVEX_L field from the record
|
||||
bool IgnoresVEX_L;
|
||||
/// The hasEVEX_L2Prefix field from the record
|
||||
|
|
Loading…
Reference in New Issue