forked from OSchip/llvm-project
lets go all meta and define new X86 type wrappers that declare the associated
gunk that goes along with an MVT (e.g. reg class, preferred load operation, memory operand) llvm-svn: 115727
This commit is contained in:
parent
eadaeaab93
commit
1fc81e90f7
|
@ -495,24 +495,57 @@ let CodeSize = 2 in {
|
|||
} // CodeSize = 2
|
||||
} // Defs = [EFLAGS]
|
||||
|
||||
/// X86TypeInfo - This is a bunch of information that describes relevant X86
|
||||
/// information about value types. For example, it can tell you what the
|
||||
/// register class and preferred load to use.
|
||||
class X86TypeInfo<ValueType vt, string instrsuffix, RegisterClass regclass,
|
||||
PatFrag loadnode, X86MemOperand memoperand> {
|
||||
/// VT - This is the value type itself.
|
||||
ValueType VT = vt;
|
||||
|
||||
/// InstrSuffix - This is the suffix used on instructions with this type. For
|
||||
/// example, i8 -> "b", i16 -> "w", i32 -> "l", i64 -> "q".
|
||||
string InstrSuffix = instrsuffix;
|
||||
|
||||
/// RegClass - This is the register class associated with this type. For
|
||||
/// example, i8 -> GR8, i16 -> GR16, i32 -> GR32, i64 -> GR64.
|
||||
RegisterClass RegClass = regclass;
|
||||
|
||||
/// LoadNode - This is the load node associated with this type. For
|
||||
/// example, i8 -> loadi8, i16 -> loadi16, i32 -> loadi32, i64 -> loadi64.
|
||||
PatFrag LoadNode = loadnode;
|
||||
|
||||
/// MemOperand - This is the memory operand associated with this type. For
|
||||
/// example, i8 -> i8mem, i16 -> i16mem, i32 -> i32mem, i64 -> i64mem.
|
||||
X86MemOperand MemOperand = memoperand;
|
||||
}
|
||||
|
||||
class BinOpRR<bits<8> opcode, Format format, string mnemonic,
|
||||
X86RegisterClass regclass, SDNode opnode>
|
||||
: I<opcode, format, (outs regclass:$dst), (ins regclass:$src1,regclass:$src2),
|
||||
!strconcat(mnemonic, "{", regclass.InstrSuffix,
|
||||
def Xi8 : X86TypeInfo<i8 , "b", GR8 , loadi8 , i8mem>;
|
||||
def Xi16 : X86TypeInfo<i16, "w", GR16, loadi16, i16mem>;
|
||||
def Xi32 : X86TypeInfo<i32, "l", GR32, loadi32, i32mem>;
|
||||
def Xi64 : X86TypeInfo<i64, "q", GR64, loadi64, i64mem>;
|
||||
|
||||
|
||||
class BinOpRR<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
||||
SDNode opnode, Format format>
|
||||
: I<opcode, format,
|
||||
(outs typeinfo.RegClass:$dst),
|
||||
(ins typeinfo.RegClass:$src1, typeinfo.RegClass:$src2),
|
||||
!strconcat(mnemonic, "{", typeinfo.InstrSuffix,
|
||||
"}\t{$src2, $dst|$dst, $src2}"),
|
||||
[(set regclass:$dst, EFLAGS, (opnode regclass:$src1, regclass:$src2))]>;
|
||||
[(set typeinfo.RegClass:$dst, EFLAGS,
|
||||
(opnode typeinfo.RegClass:$src1, typeinfo.RegClass:$src2))]>;
|
||||
|
||||
|
||||
class BinOpRM<bits<8> opcode, string mnemonic,
|
||||
X86RegisterClass regclass, SDNode opnode, PatFrag loadnode,
|
||||
X86MemOperand operand>
|
||||
class BinOpRM<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
||||
SDNode opnode, PatFrag loadnode>
|
||||
: I<opcode, MRMSrcMem,
|
||||
(outs regclass:$dst), (ins regclass:$src1, operand:$src2),
|
||||
!strconcat(mnemonic, "{", regclass.InstrSuffix,
|
||||
(outs typeinfo.RegClass:$dst),
|
||||
(ins typeinfo.RegClass:$src1, typeinfo.MemOperand:$src2),
|
||||
!strconcat(mnemonic, "{", typeinfo.InstrSuffix,
|
||||
"}\t{$src2, $dst|$dst, $src2}"),
|
||||
[(set regclass:$dst, EFLAGS, (opnode regclass:$src1,
|
||||
(loadnode addr:$src2)))]>;
|
||||
[(set typeinfo.RegClass:$dst, EFLAGS,
|
||||
(opnode typeinfo.RegClass:$src1, (loadnode addr:$src2)))]>;
|
||||
|
||||
|
||||
// Logical operators.
|
||||
|
@ -520,10 +553,10 @@ let Defs = [EFLAGS] in {
|
|||
let Constraints = "$src1 = $dst" in {
|
||||
|
||||
let isCommutable = 1 in { // X = AND Y, Z --> X = AND Z, Y
|
||||
def AND8rr : BinOpRR<0x20, MRMDestReg, "and", GR8 , X86and_flag>;
|
||||
def AND16rr : BinOpRR<0x21, MRMDestReg, "and", GR16, X86and_flag>, OpSize;
|
||||
def AND32rr : BinOpRR<0x21, MRMDestReg, "and", GR32, X86and_flag>;
|
||||
def AND64rr : BinOpRR<0x21, MRMDestReg, "and", GR64, X86and_flag>, REX_W;
|
||||
def AND8rr : BinOpRR<0x20, "and", Xi8 , X86and_flag, MRMDestReg>;
|
||||
def AND16rr : BinOpRR<0x21, "and", Xi16, X86and_flag, MRMDestReg>, OpSize;
|
||||
def AND32rr : BinOpRR<0x21, "and", Xi32, X86and_flag, MRMDestReg>;
|
||||
def AND64rr : BinOpRR<0x21, "and", Xi64, X86and_flag, MRMDestReg>, REX_W;
|
||||
} // isCommutable
|
||||
|
||||
|
||||
|
@ -543,10 +576,10 @@ def AND64rr_REV : RI<0x23, MRMSrcReg, (outs GR64:$dst),
|
|||
"and{q}\t{$src2, $dst|$dst, $src2}", []>;
|
||||
}
|
||||
|
||||
def AND8rm : BinOpRM<0x22, "and", GR8 , X86and_flag, loadi8 , i8mem>;
|
||||
def AND16rm : BinOpRM<0x23, "and", GR16, X86and_flag, loadi16, i16mem>, OpSize;
|
||||
def AND32rm : BinOpRM<0x23, "and", GR32, X86and_flag, loadi32, i32mem>;
|
||||
def AND64rm : BinOpRM<0x23, "and", GR64, X86and_flag, loadi64, i64mem>, REX_W;
|
||||
def AND8rm : BinOpRM<0x22, "and", Xi8 , X86and_flag, loadi8 >;
|
||||
def AND16rm : BinOpRM<0x23, "and", Xi16, X86and_flag, loadi16>, OpSize;
|
||||
def AND32rm : BinOpRM<0x23, "and", Xi32, X86and_flag, loadi32>;
|
||||
def AND64rm : BinOpRM<0x23, "and", Xi64, X86and_flag, loadi64>, REX_W;
|
||||
|
||||
def AND8ri : Ii8<0x80, MRM4r,
|
||||
(outs GR8 :$dst), (ins GR8 :$src1, i8imm :$src2),
|
||||
|
|
|
@ -261,16 +261,6 @@ let Namespace = "X86" in {
|
|||
// implicitly defined to be the register allocation order.
|
||||
//
|
||||
|
||||
class X86RegisterClass<string namespace, list<ValueType> regTypes,
|
||||
int alignment, string instrsuffix,
|
||||
list<Register> regList>
|
||||
: RegisterClass<namespace, regTypes, alignment, regList> {
|
||||
// This is the suffix used on instructions with this class of register. For
|
||||
// example, GR8 -> "b", GR16 -> "w", GR32 -> "l", GR64 -> "q".
|
||||
string InstrSuffix = instrsuffix;
|
||||
}
|
||||
|
||||
|
||||
// List call-clobbered registers before callee-save registers. RBX, RBP, (and
|
||||
// R12, R13, R14, and R15 for X86-64) are callee-save registers.
|
||||
// In 64-mode, there are 12 additional i8 registers, SIL, DIL, BPL, SPL, and
|
||||
|
@ -282,9 +272,9 @@ class X86RegisterClass<string namespace, list<ValueType> regTypes,
|
|||
// instruction requiring a REX prefix, while SIL, DIL, BPL, R8D, etc.
|
||||
// require a REX prefix. For example, "addb %ah, %dil" and "movzbl %ah, %r8d"
|
||||
// cannot be encoded.
|
||||
def GR8 : X86RegisterClass<"X86", [i8], 8, "b",
|
||||
[AL, CL, DL, AH, CH, DH, BL, BH, SIL, DIL, BPL, SPL,
|
||||
R8B, R9B, R10B, R11B, R14B, R15B, R12B, R13B]> {
|
||||
def GR8 : RegisterClass<"X86", [i8], 8,
|
||||
[AL, CL, DL, AH, CH, DH, BL, BH, SIL, DIL, BPL, SPL,
|
||||
R8B, R9B, R10B, R11B, R14B, R15B, R12B, R13B]> {
|
||||
let MethodProtos = [{
|
||||
iterator allocation_order_begin(const MachineFunction &MF) const;
|
||||
iterator allocation_order_end(const MachineFunction &MF) const;
|
||||
|
@ -326,9 +316,9 @@ def GR8 : X86RegisterClass<"X86", [i8], 8, "b",
|
|||
}];
|
||||
}
|
||||
|
||||
def GR16 : X86RegisterClass<"X86", [i16], 16, "w",
|
||||
[AX, CX, DX, SI, DI, BX, BP, SP,
|
||||
R8W, R9W, R10W, R11W, R14W, R15W, R12W, R13W]> {
|
||||
def GR16 : RegisterClass<"X86", [i16], 16,
|
||||
[AX, CX, DX, SI, DI, BX, BP, SP,
|
||||
R8W, R9W, R10W, R11W, R14W, R15W, R12W, R13W]> {
|
||||
let SubRegClasses = [(GR8 sub_8bit, sub_8bit_hi)];
|
||||
let MethodProtos = [{
|
||||
iterator allocation_order_begin(const MachineFunction &MF) const;
|
||||
|
@ -378,9 +368,9 @@ def GR16 : X86RegisterClass<"X86", [i16], 16, "w",
|
|||
}];
|
||||
}
|
||||
|
||||
def GR32 : X86RegisterClass<"X86", [i32], 32, "l",
|
||||
[EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP,
|
||||
R8D, R9D, R10D, R11D, R14D, R15D, R12D, R13D]> {
|
||||
def GR32 : RegisterClass<"X86", [i32], 32,
|
||||
[EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP,
|
||||
R8D, R9D, R10D, R11D, R14D, R15D, R12D, R13D]> {
|
||||
let SubRegClasses = [(GR8 sub_8bit, sub_8bit_hi), (GR16 sub_16bit)];
|
||||
let MethodProtos = [{
|
||||
iterator allocation_order_begin(const MachineFunction &MF) const;
|
||||
|
@ -433,9 +423,9 @@ def GR32 : X86RegisterClass<"X86", [i32], 32, "l",
|
|||
// GR64 - 64-bit GPRs. This oddly includes RIP, which isn't accurate, since
|
||||
// RIP isn't really a register and it can't be used anywhere except in an
|
||||
// address, but it doesn't cause trouble.
|
||||
def GR64 : X86RegisterClass<"X86", [i64], 64, "q",
|
||||
[RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11,
|
||||
RBX, R14, R15, R12, R13, RBP, RSP, RIP]> {
|
||||
def GR64 : RegisterClass<"X86", [i64], 64,
|
||||
[RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11,
|
||||
RBX, R14, R15, R12, R13, RBP, RSP, RIP]> {
|
||||
let SubRegClasses = [(GR8 sub_8bit, sub_8bit_hi),
|
||||
(GR16 sub_16bit),
|
||||
(GR32 sub_32bit)];
|
||||
|
|
Loading…
Reference in New Issue