| //===-- PPCRegisterInfo.td - The PowerPC Register File -----*- tablegen -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // |
| //===----------------------------------------------------------------------===// |
| |
| include "PPCOperands.td" |
| include "PPCRegisterClasses.td" |
| |
| let Namespace = "PPC" in { |
| def sub_lt : SubRegIndex<1>; |
| def sub_gt : SubRegIndex<1, 1>; |
| def sub_eq : SubRegIndex<1, 2>; |
| def sub_un : SubRegIndex<1, 3>; |
| def sub_32 : SubRegIndex<32>; |
| def sub_32_hi_phony : SubRegIndex<32,32>; |
| def sub_64 : SubRegIndex<64>; |
| def sub_64_hi_phony : SubRegIndex<64,64>; |
| def sub_vsx0 : SubRegIndex<128>; |
| def sub_vsx1 : SubRegIndex<128, 128>; |
| def sub_gp8_x0 : SubRegIndex<64>; |
| def sub_gp8_x1 : SubRegIndex<64, 64>; |
| def sub_fp0 : SubRegIndex<64>; |
| def sub_fp1 : SubRegIndex<64, 64>; |
| } |
| |
| class PPCReg<string n> : Register<n> { |
| let Namespace = "PPC"; |
| } |
| |
| // We identify all our registers with a 5-bit ID, for consistency's sake. |
| |
| // GPR - One of the 32 32-bit general-purpose registers |
| class GPR<bits<5> num, string n> : PPCReg<n> { |
| let HWEncoding{4-0} = num; |
| } |
| |
| // GP8 - One of the 32 64-bit general-purpose registers |
| class GP8<GPR SubReg, string n> : PPCReg<n> { |
| let HWEncoding = SubReg.HWEncoding; |
| let SubRegs = [SubReg]; |
| let SubRegIndices = [sub_32]; |
| } |
| |
| class SPE<string n, bits<5> Enc, list<Register> subregs = []> : PPCReg<n> { |
| let HWEncoding{4-0} = Enc; |
| let SubRegs = subregs; |
| let SubRegIndices = [sub_32, sub_32_hi_phony]; |
| let CoveredBySubRegs = 1; |
| } |
| // SPR - One of the 32-bit special-purpose registers |
| class SPR<bits<10> num, string n> : PPCReg<n> { |
| let HWEncoding{9-0} = num; |
| } |
| |
| // FPR - One of the 32 64-bit floating-point registers |
| class FPR<bits<5> num, string n> : PPCReg<n> { |
| let HWEncoding{4-0} = num; |
| } |
| |
| // FPPair - A pair of 64-bit floating-point registers. |
| class FPPair<string n, bits<5> EvenIndex> : PPCReg<n> { |
| assert !eq(EvenIndex{0}, 0), "Index should be even."; |
| let HWEncoding{4-0} = EvenIndex; |
| let SubRegs = [!cast<FPR>("F"#EvenIndex), !cast<FPR>("F"#!add(EvenIndex, 1))]; |
| let DwarfNumbers = [-1, -1]; |
| let SubRegIndices = [sub_fp0, sub_fp1]; |
| } |
| |
| // VF - One of the 32 64-bit floating-point subregisters of the vector |
| // registers (used by VSX). |
| class VF<bits<5> num, string n> : PPCReg<n> { |
| let HWEncoding{4-0} = num; |
| let HWEncoding{5} = 1; |
| } |
| |
| // VR - One of the 32 128-bit vector registers |
| class VR<VF SubReg, VF SubRegH, string n> : PPCReg<n> { |
| let HWEncoding{4-0} = SubReg.HWEncoding{4-0}; |
| let HWEncoding{5} = 0; |
| let SubRegs = [SubReg, SubRegH]; |
| let SubRegIndices = [sub_64, sub_64_hi_phony]; |
| } |
| |
| // VSRL - One of the 32 128-bit VSX registers that overlap with the scalar |
| // floating-point registers. |
| class VSRL<FPR SubReg, FPR SubRegH, string n> : PPCReg<n> { |
| let HWEncoding = SubReg.HWEncoding; |
| let SubRegs = [SubReg, SubRegH]; |
| let SubRegIndices = [sub_64, sub_64_hi_phony]; |
| } |
| |
| // VSXReg - One of the VSX registers in the range vs32-vs63 with numbering |
| // and encoding to match. |
| class VSXReg<bits<6> num, string n> : PPCReg<n> { |
| let HWEncoding{5-0} = num; |
| } |
| |
| // CR - One of the 8 4-bit condition registers |
| class CR<bits<3> num, string n, list<Register> subregs> : PPCReg<n> { |
| let HWEncoding{2-0} = num; |
| let SubRegs = subregs; |
| } |
| |
| // CRBIT - One of the 32 1-bit condition register fields |
| class CRBIT<bits<5> num> : PPCReg<!cast<string>(num)> { |
| let HWEncoding{4-0} = num; |
| } |
| |
| // VSR Pairs - One of the 32 paired even-odd consecutive VSRs. |
| class VSRPair<bits<5> num, string n, list<Register> subregs> : PPCReg<n> { |
| let HWEncoding{4-0} = num; |
| let SubRegs = subregs; |
| } |
| |
| // GP8Pair - Consecutive even-odd paired GP8. |
| class GP8Pair<string n, bits<5> EvenIndex> : PPCReg<n> { |
| assert !eq(EvenIndex{0}, 0), "Index should be even."; |
| let HWEncoding{4-0} = EvenIndex; |
| let SubRegs = [!cast<GP8>("X"#EvenIndex), !cast<GP8>("X"#!add(EvenIndex, 1))]; |
| let DwarfNumbers = [-1, -1]; |
| let SubRegIndices = [sub_gp8_x0, sub_gp8_x1]; |
| } |
| |
| // General-purpose registers |
| foreach Index = 0-31 in { |
| def R#Index : GPR<Index, "r"#Index>, DwarfRegNum<[-2, Index]>; |
| } |
| |
| let isArtificial = 1 in { |
| foreach Index = 0-31 in { |
| def H#Index : GPR<-1,"">; |
| } |
| } |
| |
| // 64-bit General-purpose registers |
| foreach Index = 0-31 in { |
| def X#Index : GP8<!cast<GPR>("R"#Index), "r"#Index>, |
| DwarfRegNum<[Index, -2]>; |
| } |
| |
| // SPE registers |
| foreach Index = 0-31 in { |
| def S#Index : SPE<"r"#Index, Index, [!cast<GPR>("R"#Index), !cast<GPR>("H"#Index)]>, |
| DwarfRegNum<[!add(Index, 1200), !add(Index, 1200)]>; |
| |
| } |
| |
| // Floating-point registers |
| foreach Index = 0-31 in { |
| def F#Index : FPR<Index, "f"#Index>, |
| DwarfRegNum<[!add(Index, 32), !add(Index, 32)]>; |
| } |
| |
| // The FH and VFH registers have been marked as Artifical because there are no |
| // instructions on PowerPC that use those register classes. They only exist |
| // in order to ensure that the super registers (V and VSL) are covered by their |
| // subregisters and have correct subregister lane masks. |
| let isArtificial = 1 in { |
| foreach Index = 0-31 in { |
| def FH#Index : FPR<-1, "">; |
| def VFH#Index : VF<-1, "">; |
| } |
| } |
| |
| let CopyCost = -1 in { |
| def VFHRC : PPCNonAllocatableRegisterClass<[f64], 64, (sequence "VFH%u", 0, 31)>; |
| def FHRC : PPCNonAllocatableRegisterClass<[f64], 64, (sequence "FH%u", 0, 31)>; |
| } |
| |
| // Floating-point pair registers |
| foreach Index = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 } in { |
| def Fpair#Index : FPPair<"fp"#Index, Index>; |
| } |
| |
| // 64-bit Floating-point subregisters of Altivec registers |
| // Note: the register names are v0-v31 or vs32-vs63 depending on the use. |
| // Custom C++ code is used to produce the correct name and encoding. |
| foreach Index = 0-31 in { |
| def VF#Index : VF<Index, "v" #Index>, |
| DwarfRegNum<[!add(Index, 77), !add(Index, 77)]>; |
| } |
| |
| let CoveredBySubRegs = 1 in { |
| // Vector registers |
| foreach Index = 0-31 in { |
| def V#Index : VR<!cast<VF>("VF"#Index), !cast<VF>("VFH"#Index), "v"#Index>, |
| DwarfRegNum<[!add(Index, 77), !add(Index, 77)]>; |
| } |
| // VSX registers |
| foreach Index = 0-31 in { |
| def VSL#Index : VSRL<!cast<FPR>("F"#Index), !cast<FPR>("FH"#Index), "vs"#Index>, |
| DwarfRegAlias<!cast<FPR>("F"#Index)>; |
| } |
| } |
| |
| // Dummy VSX registers, this defines string: "vs32"-"vs63", and is only used for |
| // asm printing. |
| foreach Index = 32-63 in { |
| def VSX#Index : VSXReg<Index, "vs"#Index>; |
| } |
| |
| let SubRegIndices = [sub_vsx0, sub_vsx1] in { |
| // VSR pairs 0 - 15 (corresponding to VSRs 0 - 30 paired with 1 - 31). |
| foreach Index = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 } in { |
| def VSRp#!srl(Index, 1) : VSRPair<!srl(Index, 1), "vsp"#Index, |
| [!cast<VSRL>("VSL"#Index), !cast<VSRL>("VSL"#!add(Index, 1))]>, |
| DwarfRegNum<[-1, -1]>; |
| } |
| |
| // VSR pairs 16 - 31 (corresponding to VSRs 32 - 62 paired with 33 - 63). |
| foreach Index = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 } in { |
| def VSRp#!add(!srl(Index, 1), 16) : |
| VSRPair<!add(!srl(Index, 1), 16), "vsp"#!add(Index, 32), |
| [!cast<VR>("V"#Index), !cast<VR>("V"#!add(Index, 1))]>, |
| DwarfRegAlias<!cast<VR>("V"#Index)>; |
| } |
| } |
| |
| // 16 paired even-odd consecutive GP8s. |
| foreach Index = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 } in { |
| def G8p#!srl(Index, 1) : GP8Pair<"r"#Index, Index>; |
| } |
| |
| // The representation of r0 when treated as the constant 0. |
| let isConstant = true in { |
| def ZERO : GPR<0, "0">, DwarfRegAlias<R0>; |
| def ZERO8 : GP8<ZERO, "0">, DwarfRegAlias<X0>; |
| } // isConstant = true |
| |
| // Representations of the frame pointer used by ISD::FRAMEADDR. |
| def FP : GPR<0 /* arbitrary */, "**FRAME POINTER**">; |
| def FP8 : GP8<FP, "**FRAME POINTER**">; |
| |
| // Representations of the base pointer used by setjmp. |
| def BP : GPR<0 /* arbitrary */, "**BASE POINTER**">; |
| def BP8 : GP8<BP, "**BASE POINTER**">; |
| |
| // Condition register bits |
| foreach Index = 0-7 in { |
| foreach CmpIdx = 0-3 in { |
| def CR#Index#["LT", "GT", "EQ", "UN"][CmpIdx] : |
| CRBIT<!add(!mul(Index, 4), CmpIdx)>; |
| } |
| } |
| |
| // Condition registers |
| let SubRegIndices = [sub_lt, sub_gt, sub_eq, sub_un] in { |
| def CR0 : CR<0, "cr0", [CR0LT, CR0GT, CR0EQ, CR0UN]>, DwarfRegNum<[68, 68]>; |
| def CR1 : CR<1, "cr1", [CR1LT, CR1GT, CR1EQ, CR1UN]>, DwarfRegNum<[69, 69]>; |
| def CR2 : CR<2, "cr2", [CR2LT, CR2GT, CR2EQ, CR2UN]>, DwarfRegNum<[70, 70]>; |
| def CR3 : CR<3, "cr3", [CR3LT, CR3GT, CR3EQ, CR3UN]>, DwarfRegNum<[71, 71]>; |
| def CR4 : CR<4, "cr4", [CR4LT, CR4GT, CR4EQ, CR4UN]>, DwarfRegNum<[72, 72]>; |
| def CR5 : CR<5, "cr5", [CR5LT, CR5GT, CR5EQ, CR5UN]>, DwarfRegNum<[73, 73]>; |
| def CR6 : CR<6, "cr6", [CR6LT, CR6GT, CR6EQ, CR6UN]>, DwarfRegNum<[74, 74]>; |
| def CR7 : CR<7, "cr7", [CR7LT, CR7GT, CR7EQ, CR7UN]>, DwarfRegNum<[75, 75]>; |
| } |
| |
| // Link register |
| def LR : SPR<8, "lr">, DwarfRegNum<[-2, 65]>; |
| def LR8 : SPR<8, "lr">, DwarfRegNum<[65, -2]> { |
| let Aliases = [LR]; |
| } |
| |
| // Count register |
| def CTR : SPR<9, "ctr">, DwarfRegNum<[-2, 66]>; |
| def CTR8 : SPR<9, "ctr">, DwarfRegNum<[66, -2]> { |
| let Aliases = [CTR]; |
| } |
| |
| // VRsave register |
| def VRSAVE: SPR<256, "vrsave">, DwarfRegNum<[109]>; |
| |
| // SPE extra registers |
| def SPEFSCR: SPR<512, "spefscr">, DwarfRegNum<[612, 112]>; |
| |
| def XER: SPR<1, "xer">, DwarfRegNum<[76]>; |
| |
| // Carry bit. In the architecture this is really bit 0 of the XER register |
| // (which really is SPR register 1); this is the only bit interesting to a |
| // compiler. |
| def CARRY: SPR<1, "xer">, DwarfRegNum<[76]> { |
| let Aliases = [XER]; |
| } |
| |
| // FP rounding mode: bits 30 and 31 of the FP status and control register |
| // This is not allocated as a normal register; it appears only in |
| // Uses and Defs. The ABI says it needs to be preserved by a function, |
| // but this is not achieved by saving and restoring it as with |
| // most registers, it has to be done in code; to make this work all the |
| // return and call instructions are described as Uses of RM, so instructions |
| // that do nothing but change RM will not get deleted. |
| def RM: PPCReg<"**ROUNDING MODE**">; |
| |
| def GPRC32 : PPCNonAllocatableRegisterClass<[i32,f32], 32, |
| (add (sequence "H%u", 2, 12), |
| (sequence "H%u", 30, 13), |
| H31, H0, H1)>; |
| |
| /// Register classes |
| // Allocate volatiles first |
| // then nonvolatiles in reverse order since stmw/lmw save from rN to r31 |
| def GPRC : PPCGPRRegisterClass<[i32,f32], 32, |
| (add (sequence "R%u", 2, 12), |
| (sequence "R%u", 30, 13), |
| R31, R0, R1, FP, BP), |
| // On non-Darwin PPC64 systems, R2 can be allocated, but must be restored, so |
| // put it at the end of the list. |
| (add (sub GPRC, R2), R2), |
| // On AIX, CSRs are allocated starting from R31 according to: |
| // https://www.ibm.com/docs/en/ssw_aix_72/assembler/assembler_pdf.pdf. |
| // This also helps setting the correct `NumOfGPRsSaved' in traceback table. |
| (add (sequence "R%u", 2, 12), |
| (sequence "R%u", 31, 13), R0, R1, FP, BP)>; |
| |
| def G8RC : PPCGPRRegisterClass<[i64], 64, |
| (add (sequence "X%u", 2, 12), |
| (sequence "X%u", 30, 14), |
| X31, X13, X0, X1, FP8, BP8), |
| // On non-Darwin PPC64 systems, R2 can be allocated, but must be restored, so |
| // put it at the end of the list. |
| (add (sub G8RC, X2), X2), |
| (add (sequence "X%u", 2, 12), |
| (sequence "X%u", 31, 13), X0, X1, FP8, BP8)>; |
| |
| // For some instructions r0 is special (representing the value 0 instead of |
| // the value in the r0 register), and we use these register subclasses to |
| // prevent r0 from being allocated for use by those instructions. |
| def GPRC_NOR0 : PPCGPRRegisterClass<[i32,f32], 32, |
| (add (sub GPRC, R0), ZERO), |
| // On non-Darwin PPC64 systems, R2 can be allocated, but must be restored, so |
| // put it at the end of the list. |
| (add (sub GPRC_NOR0, R2), R2), |
| (add (sequence "R%u", 2, 12), |
| (sequence "R%u", 31, 13), R1, FP, BP, ZERO)>; |
| |
| def G8RC_NOX0 : PPCGPRRegisterClass<[i64], 64, |
| (add (sub G8RC, X0), ZERO8), |
| // On non-Darwin PPC64 systems, R2 can be allocated, but must be restored, so |
| // put it at the end of the list. |
| (add (sub G8RC_NOX0, X2), X2), |
| (add (sequence "X%u", 2, 12), |
| (sequence "X%u", 31, 13), X1, FP8, BP8, ZERO8)>; |
| |
| def SPERC : PPCRegisterClass<[f64], 64, |
| (add (sequence "S%u", 2, 12), |
| (sequence "S%u", 30, 13), |
| S31, S0, S1)>; |
| |
| // Allocate volatiles first, then non-volatiles in reverse order. With the SVR4 |
| // ABI the size of the Floating-point register save area is determined by the |
| // allocated non-volatile register with the lowest register number, as FP |
| // register N is spilled to offset 8 * (32 - N) below the back chain word of the |
| // previous stack frame. By allocating non-volatiles in reverse order we make |
| // sure that the Floating-point register save area is always as small as |
| // possible because there aren't any unused spill slots. |
| def F8RC : PPCRegisterClass<[f64], 64, (add (sequence "F%u", 0, 13), |
| (sequence "F%u", 31, 14))>; |
| def F4RC : PPCRegisterClass<[f32], 32, (add F8RC)>; |
| |
| // Floating point pair registers. |
| // Note that the type used for this register class is ppcf128. This is not |
| // completely correct. However, since we are not pattern matching any |
| // instructions for these registers and we are not register allocating or |
| // scheduling any of these instructions it should be safe to do this. |
| // The reason we didn't use the correct type (Decimal Floating Point) is that |
| // at the time of this implementation the correct type was not available. |
| def FpRC : PPCRegisterClassWithSize<[ppcf128], 128, |
| (add Fpair0, Fpair2, Fpair4, Fpair6, Fpair8, Fpair10, Fpair12, |
| Fpair14, Fpair16, Fpair18, Fpair20, Fpair22, Fpair24, |
| Fpair26, Fpair28, Fpair30), 128>; |
| |
| def VRRC : PPCRegisterClassWithSize<[v16i8,v8i16,v4i32,v2i64,v1i128,v4f32,v2f64, f128], |
| 128, |
| (add V2, V3, V4, V5, V0, V1, V6, V7, V8, V9, V10, V11, |
| V12, V13, V14, V15, V16, V17, V18, V19, V31, V30, |
| V29, V28, V27, V26, V25, V24, V23, V22, V21, V20), 128>; |
| |
| // VSX register classes (the allocation order mirrors that of the corresponding |
| // subregister classes). |
| def VSLRC : PPCRegisterClassWithSize<[v4i32,v4f32,v2f64,v2i64], 128, |
| (add (sequence "VSL%u", 0, 13), |
| (sequence "VSL%u", 31, 14)), 128>; |
| |
| def VSRC : PPCRegisterClassWithSize<[v4i32,v4f32,v2f64,v2i64], 128, |
| (add VSLRC, VRRC), 128>; |
| |
| // Register classes for the 64-bit "scalar" VSX subregisters. |
| def VFRC : PPCRegisterClass<[f64], 64, |
| (add VF2, VF3, VF4, VF5, VF0, VF1, VF6, VF7, |
| VF8, VF9, VF10, VF11, VF12, VF13, VF14, |
| VF15, VF16, VF17, VF18, VF19, VF31, VF30, |
| VF29, VF28, VF27, VF26, VF25, VF24, VF23, |
| VF22, VF21, VF20)>; |
| |
| def VSFRC : PPCRegisterClass<[f64], 64, (add F8RC, VFRC)>; |
| |
| // Allow spilling GPR's into caller-saved VSR's. |
| def SPILLTOVSRRC : PPCRegisterClass<[i64, f64], 64, |
| (add G8RC, (sub VSFRC, (sequence "VF%u", 31, 20), |
| (sequence "F%u", 31, 14)))>; |
| |
| // Register class for single precision scalars in VSX registers |
| def VSSRC : PPCRegisterClass<[f32], 32, (add VSFRC)>; |
| |
| def CRBITRC : PPCRegisterClassWithSize<[i1], 32, |
| (add CR2LT, CR2GT, CR2EQ, CR2UN, |
| CR3LT, CR3GT, CR3EQ, CR3UN, |
| CR4LT, CR4GT, CR4EQ, CR4UN, |
| CR5LT, CR5GT, CR5EQ, CR5UN, |
| CR6LT, CR6GT, CR6EQ, CR6UN, |
| CR7LT, CR7GT, CR7EQ, CR7UN, |
| CR1LT, CR1GT, CR1EQ, CR1UN, |
| CR0LT, CR0GT, CR0EQ, CR0UN), 32> { |
| let AltOrders = [(sub CRBITRC, CR2LT, CR2GT, CR2EQ, CR2UN, CR3LT, CR3GT, |
| CR3EQ, CR3UN, CR4LT, CR4GT, CR4EQ, CR4UN)]; |
| let AltOrderSelect = [{ |
| return MF.getSubtarget<PPCSubtarget>().isELFv2ABI() && |
| MF.getInfo<PPCFunctionInfo>()->isNonVolatileCRDisabled(); |
| }]; |
| } |
| |
| def CRRC : PPCRegisterClass<[i32], 32, |
| (add CR0, CR1, CR5, CR6, |
| CR7, CR2, CR3, CR4)> { |
| let AltOrders = [(sub CRRC, CR2, CR3, CR4)]; |
| let AltOrderSelect = [{ |
| return MF.getSubtarget<PPCSubtarget>().isELFv2ABI() && |
| MF.getInfo<PPCFunctionInfo>()->isNonVolatileCRDisabled(); |
| }]; |
| } |
| |
| // The CTR registers are not allocatable because they're used by the |
| // decrement-and-branch instructions, and thus need to stay live across |
| // multiple basic blocks. |
| def CTRRC : PPCNonAllocatableRegisterClass<[i32], 32, (add CTR)>; |
| def CTRRC8 : PPCNonAllocatableRegisterClass<[i64], 64, (add CTR8)>; |
| |
| def LRRC : PPCNonAllocatableRegisterClass<[i32], 32, (add LR)>; |
| def LR8RC : PPCNonAllocatableRegisterClass<[i64], 64, (add LR8)>; |
| |
| def VRSAVERC : PPCRegisterClass<[i32], 32, (add VRSAVE)>; |
| def CARRYRC : PPCNonAllocatableRegisterClass<[i32], 32, (add CARRY, XER)> { |
| let CopyCost = -1; |
| } |
| |
| // Make AllocationOrder as similar as G8RC's to avoid potential spilling. |
| // Similarly, we have an AltOrder for 64-bit ELF ABI which r2 is allocated |
| // at last. |
| def G8pRC : PPCRegisterClassWithSize<[untyped], 128, |
| (add (sequence "G8p%u", 1, 5), |
| (sequence "G8p%u", 14, 7), |
| G8p15, G8p6, G8p0), 128> { |
| let AltOrders = [(add (sub G8pRC, G8p1), G8p1)]; |
| let AltOrderSelect = [{ |
| return MF.getSubtarget<PPCSubtarget>().is64BitELFABI(); |
| }]; |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // PowerPC Register Operand Definitions. |
| |
| // In the default PowerPC assembler syntax, registers are specified simply |
| // by number, so they cannot be distinguished from immediate values (without |
| // looking at the opcode). This means that the default operand matching logic |
| // for the asm parser does not work, and we need to specify custom matchers. |
| // Since those can only be specified with RegisterOperand classes and not |
| // directly on the RegisterClass, all instructions patterns used by the asm |
| // parser need to use a RegisterOperand (instead of a RegisterClass) for |
| // all their register operands. |
| // For this purpose, we define one RegisterOperand for each RegisterClass, |
| // using the same name as the class, just in lower case. |
| |
| defm GPRC : PPCRegOperand<"isRegNumber">; |
| defm G8RC : PPCRegOperand<"isRegNumber">; |
| defm GPRC_NOR0 : PPCRegOperand<"isRegNumber">; |
| defm G8RC_NOX0 : PPCRegOperand<"isRegNumber">; |
| defm SPERC : PPCRegOperand<"isRegNumber">; |
| defm F8RC : PPCRegOperand<"isRegNumber">; |
| defm F4RC : PPCRegOperand<"isRegNumber">; |
| defm FpRC : PPCRegOperand<"isEvenRegNumber", "fpairrc">; |
| defm VRRC : PPCRegOperand<"isRegNumber">; |
| defm VSRC : PPCRegOperand<"isVSRegNumber">; |
| defm VFRC : PPCRegOperand<"isRegNumber">; |
| defm VSFRC : PPCRegOperand<"isVSRegNumber">; |
| defm SPILLTOVSRRC : PPCRegOperand<"isVSRegNumber">; |
| defm VSSRC : PPCRegOperand<"isVSRegNumber">; |
| defm CRBITRC : PPCRegOperand<"isCRBitNumber">; |
| defm CRRC : PPCRegOperand<"isCCRegNumber">; |
| defm G8pRC : PPCRegOperand<"isEvenRegNumber">; |
| |
| // Special case: spe4rc uses GPRC register class and its AsmOperandClass |
| def spe4rc : PPCRegOperandOnly<"GPRC">; |
| |
| // Address operands |
| // A version of ptr_rc which excludes R0 (or X0 in 64-bit mode). |
| def PPCRegGxRCNoR0Operand : AsmOperandClass { |
| let Name = "RegGxRCNoR0"; let PredicateMethod = "isRegNumber"; |
| } |
| |
| def ppc_ptr_rc : RegClassByHwMode< |
| [PPC32, PPC64], |
| [GPRC, G8RC]>; |
| |
| def ptr_rc_nor0_by_hwmode : RegClassByHwMode< |
| [PPC32, PPC64], |
| [GPRC_NOR0, G8RC_NOX0]>; |
| |
| def ptr_rc_nor0 : RegisterOperand<ptr_rc_nor0_by_hwmode> { |
| let ParserMatchClass = PPCRegGxRCNoR0Operand; |
| } |
| |
| // A version of ptr_rc usable with the asm parser. |
| def PPCRegGxRCOperand : AsmOperandClass { |
| let Name = "RegGxRC"; let PredicateMethod = "isRegNumber"; |
| } |
| |
| def ptr_rc_idx_by_hwmode : RegClassByHwMode<[PPC32, PPC64], |
| [GPRC, G8RC]>; |
| |
| def ptr_rc_idx : RegisterOperand<ptr_rc_idx_by_hwmode> { |
| let ParserMatchClass = PPCRegGxRCOperand; |
| } |
| |
| include "PPCRegisterInfoMMA.td" |
| include "PPCRegisterInfoDMR.td" |
| |
| //===----------------------------------------------------------------------===// |
| // Memory operands (depend on register operands defined above) |
| //===----------------------------------------------------------------------===// |
| |
| def memri34 : Operand<iPTR> { // memri, imm is a 34-bit value. |
| let PrintMethod = "printMemRegImm34"; |
| let MIOperandInfo = (ops dispRI34:$imm, ptr_rc_nor0:$reg); |
| } |
| // memri, imm is a 34-bit value for pc-relative instructions where |
| // base register is set to zero. |
| def memri34_pcrel : Operand<iPTR> { // memri, imm is a 34-bit value. |
| let PrintMethod = "printMemRegImm34PCRel"; |
| let MIOperandInfo = (ops dispRI34_pcrel:$imm, immZero:$reg); |
| } |
| |
| def memri : Operand<iPTR> { |
| let PrintMethod = "printMemRegImm"; |
| let MIOperandInfo = (ops dispRI:$imm, ptr_rc_nor0:$reg); |
| let OperandType = "OPERAND_MEMORY"; |
| } |
| def memrr : Operand<iPTR> { |
| let PrintMethod = "printMemRegReg"; |
| let MIOperandInfo = (ops ptr_rc_nor0:$ptrreg, ptr_rc_idx:$offreg); |
| let OperandType = "OPERAND_MEMORY"; |
| } |
| def memrix : Operand<iPTR> { // memri where the imm is 4-aligned. |
| let PrintMethod = "printMemRegImm"; |
| let MIOperandInfo = (ops dispRIX:$imm, ptr_rc_nor0:$reg); |
| let OperandType = "OPERAND_MEMORY"; |
| } |
| def memrihash : Operand<iPTR> { |
| // memrihash 8-aligned for ROP Protection Instructions. |
| let PrintMethod = "printMemRegImmHash"; |
| let MIOperandInfo = (ops dispRIHash:$imm, ptr_rc_nor0:$reg); |
| let OperandType = "OPERAND_MEMORY"; |
| } |
| def memrix16 : Operand<iPTR> { // memri, imm is 16-aligned, 12-bit, Inst{16:27} |
| let PrintMethod = "printMemRegImm"; |
| let MIOperandInfo = (ops dispRIX16:$imm, ptr_rc_nor0:$reg); |
| let OperandType = "OPERAND_MEMORY"; |
| } |
| def spe8dis : Operand<iPTR> { // SPE displacement where the imm is 8-aligned. |
| let PrintMethod = "printMemRegImm"; |
| let MIOperandInfo = (ops dispSPE8:$imm, ptr_rc_nor0:$reg); |
| let OperandType = "OPERAND_MEMORY"; |
| } |
| def spe4dis : Operand<iPTR> { // SPE displacement where the imm is 4-aligned. |
| let PrintMethod = "printMemRegImm"; |
| let MIOperandInfo = (ops dispSPE4:$imm, ptr_rc_nor0:$reg); |
| let OperandType = "OPERAND_MEMORY"; |
| } |
| def spe2dis : Operand<iPTR> { // SPE displacement where the imm is 2-aligned. |
| let PrintMethod = "printMemRegImm"; |
| let MIOperandInfo = (ops dispSPE2:$imm, ptr_rc_nor0:$reg); |
| let OperandType = "OPERAND_MEMORY"; |
| } |
| |
| // A single-register address. This is used with the SjLj |
| // pseudo-instructions which translates to LD/LWZ. These instructions requires |
| // G8RC_NOX0 registers. |
| def memr : Operand<iPTR> { |
| let MIOperandInfo = (ops ptr_rc_nor0:$ptrreg); |
| let OperandType = "OPERAND_MEMORY"; |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Predicate operand (depends on register operands defined above) |
| //===----------------------------------------------------------------------===// |
| |
| // PowerPC Predicate operand. |
| def pred : Operand<OtherVT> { |
| let PrintMethod = "printPredicateOperand"; |
| let MIOperandInfo = (ops i32imm:$bibo, crrc:$reg); |
| } |