1
0
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:
Craig Topper 2018-03-24 06:04:12 +00:00
parent fa3424fd2c
commit abad09f7ae
6 changed files with 42 additions and 44 deletions

View File

@ -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

View File

@ -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

View File

@ -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))],

View File

@ -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,

View File

@ -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) {

View File

@ -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