mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 19:12:56 +02:00
[X86] Merge the Has3DNow0F0FOpcode TSFlag into the OpMap encoding. NFC
The 3DNow instructions are encoded a little weird, but we can still represent it as an opcode map. llvm-svn: 328410
This commit is contained in:
parent
fa3424fd2c
commit
abad09f7ae
@ -433,6 +433,14 @@ namespace X86II {
|
||||
// XOPA - Prefix to encode 0xA in VEX.MMMM of XOP instructions.
|
||||
XOPA = 6 << OpMapShift,
|
||||
|
||||
/// ThreeDNow - This indicates that the instruction uses the
|
||||
/// wacky 0x0F 0x0F prefix for 3DNow! instructions. The manual documents
|
||||
/// this as having a 0x0F prefix with a 0x0F opcode, and each instruction
|
||||
/// storing a classifier in the imm8 field. To simplify our implementation,
|
||||
/// we handle this by storeing the classifier in the opcode field and using
|
||||
/// this flag to indicate that the encoder should do the wacky 3DNow! thing.
|
||||
ThreeDNow = 7 << OpMapShift,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// REX_W - REX prefixes are instruction prefixes used in 64-bit mode.
|
||||
// They are used to specify GPRs and SSE registers, 64-bit operand size,
|
||||
@ -562,17 +570,8 @@ namespace X86II {
|
||||
CD8_Scale_Shift = EVEX_BShift + 1,
|
||||
CD8_Scale_Mask = 127ULL << CD8_Scale_Shift,
|
||||
|
||||
/// Has3DNow0F0FOpcode - This flag indicates that the instruction uses the
|
||||
/// wacky 0x0F 0x0F prefix for 3DNow! instructions. The manual documents
|
||||
/// this as having a 0x0F prefix with a 0x0F opcode, and each instruction
|
||||
/// storing a classifier in the imm8 field. To simplify our implementation,
|
||||
/// we handle this by storeing the classifier in the opcode field and using
|
||||
/// this flag to indicate that the encoder should do the wacky 3DNow! thing.
|
||||
Has3DNow0F0FOpcodeShift = CD8_Scale_Shift + 7,
|
||||
Has3DNow0F0FOpcode = 1ULL << Has3DNow0F0FOpcodeShift,
|
||||
|
||||
/// Explicitly specified rounding control
|
||||
EVEX_RCShift = Has3DNow0F0FOpcodeShift + 1,
|
||||
EVEX_RCShift = CD8_Scale_Shift + 7,
|
||||
EVEX_RC = 1ULL << EVEX_RCShift,
|
||||
|
||||
// NOTRACK prefix
|
||||
|
@ -1163,9 +1163,10 @@ bool X86MCCodeEmitter::emitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
|
||||
|
||||
// 0x0F escape code must be emitted just before the opcode.
|
||||
switch (TSFlags & X86II::OpMapMask) {
|
||||
case X86II::TB: // Two-byte opcode map
|
||||
case X86II::T8: // 0F 38
|
||||
case X86II::TA: // 0F 3A
|
||||
case X86II::TB: // Two-byte opcode map
|
||||
case X86II::T8: // 0F 38
|
||||
case X86II::TA: // 0F 3A
|
||||
case X86II::ThreeDNow: // 0F 0F, second 0F emitted by caller.
|
||||
EmitByte(0x0F, CurByte, OS);
|
||||
break;
|
||||
}
|
||||
@ -1261,7 +1262,7 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
|
||||
uint8_t BaseOpcode = X86II::getBaseOpcodeFor(TSFlags);
|
||||
|
||||
if (TSFlags & X86II::Has3DNow0F0FOpcode)
|
||||
if ((TSFlags & X86II::OpMapMask) == X86II::ThreeDNow)
|
||||
BaseOpcode = 0x0F; // Weird 3DNow! encoding.
|
||||
|
||||
uint64_t Form = TSFlags & X86II::FormMask;
|
||||
@ -1555,7 +1556,7 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
}
|
||||
}
|
||||
|
||||
if (TSFlags & X86II::Has3DNow0F0FOpcode)
|
||||
if ((TSFlags & X86II::OpMapMask) == X86II::ThreeDNow)
|
||||
EmitByte(X86II::getBaseOpcodeFor(TSFlags), CurByte, OS);
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@ -44,14 +44,14 @@ def I3DNOW_PSHUF_ITINS : OpndItins<
|
||||
|
||||
class I3DNow<bits<8> o, Format F, dag outs, dag ins, string asm, list<dag> pat,
|
||||
InstrItinClass itin>
|
||||
: I<o, F, outs, ins, asm, pat, itin>, TB, Requires<[Has3DNow]> {
|
||||
: I<o, F, outs, ins, asm, pat, itin>, Requires<[Has3DNow]> {
|
||||
}
|
||||
|
||||
class I3DNow_binop<bits<8> o, Format F, dag ins, string Mnemonic, list<dag> pat,
|
||||
InstrItinClass itin>
|
||||
: I3DNow<o, F, (outs VR64:$dst), ins,
|
||||
!strconcat(Mnemonic, "\t{$src2, $dst|$dst, $src2}"), pat, itin>,
|
||||
Has3DNow0F0FOpcode {
|
||||
ThreeDNow {
|
||||
let Constraints = "$src1 = $dst";
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ class I3DNow_conv<bits<8> o, Format F, dag ins, string Mnemonic, list<dag> pat,
|
||||
InstrItinClass itin>
|
||||
: I3DNow<o, F, (outs VR64:$dst), ins,
|
||||
!strconcat(Mnemonic, "\t{$src, $dst|$dst, $src}"), pat, itin>,
|
||||
Has3DNow0F0FOpcode;
|
||||
ThreeDNow;
|
||||
|
||||
multiclass I3DNow_binop_rm_int<bits<8> opc, string Mn, OpndItins itins,
|
||||
bit Commutable = 0, string Ver = ""> {
|
||||
@ -111,7 +111,7 @@ defm PMULHRW : I3DNow_binop_rm_int<0xB7, "pmulhrw", I3DNOW_MISC_FUNC_ITINS, 1>;
|
||||
// FIXME: Is there a better scheduler class for EMMS/FEMMS?
|
||||
let SchedRW = [WriteMicrocoded] in
|
||||
def FEMMS : I3DNow<0x0E, RawFrm, (outs), (ins), "femms",
|
||||
[(int_x86_mmx_femms)], IIC_MMX_EMMS>;
|
||||
[(int_x86_mmx_femms)], IIC_MMX_EMMS>, TB;
|
||||
|
||||
// PREFETCHWT1 is supported we want to use it for everything but T0.
|
||||
def PrefetchWLevel : PatFrag<(ops), (i32 imm), [{
|
||||
@ -128,7 +128,7 @@ let Predicates = [Has3DNow, NoSSEPrefetch] in
|
||||
def PREFETCH : I3DNow<0x0D, MRM0m, (outs), (ins i8mem:$addr),
|
||||
"prefetch\t$addr",
|
||||
[(prefetch addr:$addr, imm, imm, (i32 1))],
|
||||
IIC_SSE_PREFETCH>;
|
||||
IIC_SSE_PREFETCH>, TB;
|
||||
|
||||
def PREFETCHW : I<0x0D, MRM1m, (outs), (ins i8mem:$addr), "prefetchw\t$addr",
|
||||
[(prefetch addr:$addr, (i32 1), (i32 PrefetchWLevel), (i32 1))],
|
||||
|
@ -136,13 +136,14 @@ def XD : Prefix<4>;
|
||||
class Map<bits<3> val> {
|
||||
bits<3> Value = val;
|
||||
}
|
||||
def OB : Map<0>;
|
||||
def TB : Map<1>;
|
||||
def T8 : Map<2>;
|
||||
def TA : Map<3>;
|
||||
def XOP8 : Map<4>;
|
||||
def XOP9 : Map<5>;
|
||||
def XOPA : Map<6>;
|
||||
def OB : Map<0>;
|
||||
def TB : Map<1>;
|
||||
def T8 : Map<2>;
|
||||
def TA : Map<3>;
|
||||
def XOP8 : Map<4>;
|
||||
def XOP9 : Map<5>;
|
||||
def XOPA : Map<6>;
|
||||
def ThreeDNow : Map<7>;
|
||||
|
||||
// Class specifying the encoding
|
||||
class Encoding<bits<2> val> {
|
||||
@ -188,6 +189,7 @@ class TA { Map OpMap = TA; }
|
||||
class XOP8 { Map OpMap = XOP8; Prefix OpPrefix = PS; }
|
||||
class XOP9 { Map OpMap = XOP9; Prefix OpPrefix = PS; }
|
||||
class XOPA { Map OpMap = XOPA; Prefix OpPrefix = PS; }
|
||||
class ThreeDNow { Map OpMap = ThreeDNow; }
|
||||
class OBXS { Prefix OpPrefix = XS; }
|
||||
class PS : TB { Prefix OpPrefix = PS; }
|
||||
class PD : TB { Prefix OpPrefix = PD; }
|
||||
@ -224,7 +226,6 @@ class EVEX_CD8<int esize, CD8VForm form> {
|
||||
bits<3> CD8_Form = form.Value;
|
||||
}
|
||||
|
||||
class Has3DNow0F0FOpcode { bit has3DNow0F0FOpcode = 1; }
|
||||
class XOP { Encoding OpEnc = EncXOP; }
|
||||
class XOP_4V : XOP { bit hasVEX_4V = 1; }
|
||||
|
||||
@ -295,7 +296,6 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
|
||||
// Declare it int rather than bits<4> so that all bits are defined when
|
||||
// assigning to bits<7>.
|
||||
int CD8_EltSize = 0; // Compressed disp8 form - element-size in bytes.
|
||||
bit has3DNow0F0FOpcode =0;// Wacky 3dNow! encoding?
|
||||
bit hasEVEX_RC = 0; // Explicitly specified rounding control in FP instruction.
|
||||
bit hasNoTrackPrefix = 0; // Does this inst has 0x3E (NoTrack) prefix?
|
||||
|
||||
@ -347,9 +347,8 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
|
||||
let TSFlags{45} = hasEVEX_B;
|
||||
// If we run out of TSFlags bits, it's possible to encode this in 3 bits.
|
||||
let TSFlags{52-46} = CD8_Scale;
|
||||
let TSFlags{53} = has3DNow0F0FOpcode;
|
||||
let TSFlags{54} = hasEVEX_RC;
|
||||
let TSFlags{55} = hasNoTrackPrefix;
|
||||
let TSFlags{53} = hasEVEX_RC;
|
||||
let TSFlags{54} = hasNoTrackPrefix;
|
||||
}
|
||||
|
||||
class PseudoI<dag oops, dag iops, list<dag> pattern,
|
||||
|
@ -90,7 +90,6 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
|
||||
HasEVEX_K = Rec->getValueAsBit("hasEVEX_K");
|
||||
HasEVEX_KZ = Rec->getValueAsBit("hasEVEX_Z");
|
||||
HasEVEX_B = Rec->getValueAsBit("hasEVEX_B");
|
||||
Has3DNow0F0FOpcode = Rec->getValueAsBit("has3DNow0F0FOpcode");
|
||||
IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly");
|
||||
ForceDisassemble = Rec->getValueAsBit("ForceDisassemble");
|
||||
CD8_Scale = byteFromRec(Rec, "CD8_Scale");
|
||||
@ -289,7 +288,7 @@ InstructionContext RecognizableInstr::insnContext() const {
|
||||
errs() << "Instruction does not use a prefix: " << Name << "\n";
|
||||
llvm_unreachable("Invalid prefix");
|
||||
}
|
||||
} else if (Has3DNow0F0FOpcode) {
|
||||
} else if (OpMap == X86Local::ThreeDNow) {
|
||||
insnContext = IC_3DNOW;
|
||||
} else if (Is64Bit || HasREX_WPrefix || AdSize == X86Local::AdSize64) {
|
||||
if (HasREX_WPrefix && (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD))
|
||||
@ -716,15 +715,17 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
|
||||
case X86Local::XOP8:
|
||||
case X86Local::XOP9:
|
||||
case X86Local::XOPA:
|
||||
case X86Local::ThreeDNow:
|
||||
switch (OpMap) {
|
||||
default: llvm_unreachable("Unexpected map!");
|
||||
case X86Local::OB: opcodeType = ONEBYTE; break;
|
||||
case X86Local::TB: opcodeType = TWOBYTE; break;
|
||||
case X86Local::T8: opcodeType = THREEBYTE_38; break;
|
||||
case X86Local::TA: opcodeType = THREEBYTE_3A; break;
|
||||
case X86Local::XOP8: opcodeType = XOP8_MAP; break;
|
||||
case X86Local::XOP9: opcodeType = XOP9_MAP; break;
|
||||
case X86Local::XOPA: opcodeType = XOPA_MAP; break;
|
||||
case X86Local::OB: opcodeType = ONEBYTE; break;
|
||||
case X86Local::TB: opcodeType = TWOBYTE; break;
|
||||
case X86Local::T8: opcodeType = THREEBYTE_38; break;
|
||||
case X86Local::TA: opcodeType = THREEBYTE_3A; break;
|
||||
case X86Local::XOP8: opcodeType = XOP8_MAP; break;
|
||||
case X86Local::XOP9: opcodeType = XOP9_MAP; break;
|
||||
case X86Local::XOPA: opcodeType = XOPA_MAP; break;
|
||||
case X86Local::ThreeDNow: opcodeType = TWOBYTE; break;
|
||||
}
|
||||
|
||||
switch (Form) {
|
||||
|
@ -122,7 +122,7 @@ namespace X86Local {
|
||||
};
|
||||
|
||||
enum {
|
||||
OB = 0, TB = 1, T8 = 2, TA = 3, XOP8 = 4, XOP9 = 5, XOPA = 6
|
||||
OB = 0, TB = 1, T8 = 2, TA = 3, XOP8 = 4, XOP9 = 5, XOPA = 6, ThreeDNow = 7
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -191,8 +191,6 @@ private:
|
||||
bool HasEVEX_KZ;
|
||||
/// The hasEVEX_B field from the record
|
||||
bool HasEVEX_B;
|
||||
/// The has3DNow0F0FOpcode field from the record
|
||||
bool Has3DNow0F0FOpcode;
|
||||
/// Indicates that the instruction uses the L and L' fields for RC.
|
||||
bool EncodeRC;
|
||||
/// The isCodeGenOnly field from the record
|
||||
|
Loading…
Reference in New Issue
Block a user