//===-- PPCOperands.td - PowerPC instruction operands -------*- 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 // //===----------------------------------------------------------------------===// // // This file defines PowerPC instruction operands, including immediate // operands and addressing modes. // //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // Immediate operand base classes //===----------------------------------------------------------------------===// // Base class for immediate AsmOperandClass definitions. class ImmediateAsmOperand : AsmOperandClass { let Name = NAME; let PredicateMethod = predicate; let RenderMethod = render; } // Base class for signed immediate operands. class ImmediateOp : Operand { let PrintMethod = "printSImmOperand<"#width#">"; let DecoderMethod = "decodeSImmOperand<"#width#">"; let ParserMatchClass = !cast(asmop); let OperandType = "OPERAND_IMMEDIATE"; } // Base class for unsigned immediate operands. class UImmediateOp : ImmediateOp { let PrintMethod = "printUImmOperand<"#width#">"; let DecoderMethod = "decodeUImmOperand<"#width#">"; } // Base class for signed immediate operands with relocation. class ImmediateRelocOp : Operand { let PrintMethod = "print"#asmop#"Operand"; let DecoderMethod = !if(!eq(decoder, ""), "decodeSImmOperand<"#width#">", decoder); let ParserMatchClass = !cast(asmop); let EncoderMethod = "getImmEncoding<" # fixup # ">"; let OperandType = "OPERAND_IMMEDIATE"; } // Base class for unsigned immediate operands with relocation. class UImmediateRelocOp : ImmediateRelocOp { let DecoderMethod = !if(!eq(decoder, ""), "decodeUImmOperand<"#width#">", decoder); } //===----------------------------------------------------------------------===// // Multiclasses for complete immediate definitions // (AsmOperand + Operand + ImmLeaf). //===----------------------------------------------------------------------===// multiclass ImmPatterns { def _pat : ImmLeaf; def _timm : TImmLeaf; } multiclass SignedImmediate : ImmPatterns { def "" : ImmediateOp; } multiclass UnsignedImmediate : ImmPatterns { def "" : UImmediateOp; } multiclass SignedImmediateReloc : ImmPatterns { def "" : ImmediateRelocOp; } // Helper multiclass for unsigned immediates with relocation fixup string. multiclass UnsignedImmediateReloc : ImmPatterns { def "" : UImmediateRelocOp; } // Multiclass for signed immediate operands with both regular and // PC-relative versions. multiclass SignedImmediateWithPCRel : SignedImmediateReloc { // PC-relative immediate: instantiate with PC-relative fixup defm _pcrel : SignedImmediateReloc; } //===----------------------------------------------------------------------===// // Immediate transformation functions //===----------------------------------------------------------------------===// // NEG_S32 - Negate a signed 32-bit immediate value def NEG_S32 : SDNodeXFormgetSExtValue(), SDLoc(N)); }]>; //===----------------------------------------------------------------------===// // Immediate AsmOperand definitions //===----------------------------------------------------------------------===// def U1Imm : ImmediateAsmOperand<"isUImm<1>">; def U2Imm : ImmediateAsmOperand<"isUImm<2>">; def U3Imm : ImmediateAsmOperand<"isUImm<3>">; def U4Imm : ImmediateAsmOperand<"isUImm<4>">; def U5Imm : ImmediateAsmOperand<"isUImm<5>">; def U6Imm : ImmediateAsmOperand<"isUImm<6>">; def U7Imm : ImmediateAsmOperand<"isUImm<7>">; def U8Imm : ImmediateAsmOperand<"isUImm<8>">; def U10Imm : ImmediateAsmOperand<"isUImm<10>">; def U12Imm : ImmediateAsmOperand<"isUImm<12>">; def U32Imm : ImmediateAsmOperand<"isUImm<32>">; def S5Imm : ImmediateAsmOperand<"isSImm<5>">; // Special cases that have custom predicat and/or render method. def ATBitsAsHint : ImmediateAsmOperand<"isATBitsAsHint">; //Predicate always fails. def ImmZero : ImmediateAsmOperand<"isImmZero">; def U16Imm : ImmediateAsmOperand<"isU16Imm","addU16ImmOperands">; def S16Imm : ImmediateAsmOperand<"isS16Imm","addS16ImmOperands">; def S17Imm : ImmediateAsmOperand<"isS17Imm","addS16ImmOperands">; def S32Imm : ImmediateAsmOperand<"isS32Imm">; def S34Imm : ImmediateAsmOperand<"isS34Imm">; def NegS32Imm : ImmediateAsmOperand<"isS32Imm","addNegImmOperands">; //===----------------------------------------------------------------------===// // i32 immediate operands //===----------------------------------------------------------------------===// defm u1imm : UnsignedImmediate(Imm); }], NOOP_SDNodeXForm, "U1Imm", 1>; defm u2imm : UnsignedImmediate(Imm); }], NOOP_SDNodeXForm, "U2Imm", 2>; defm u3imm : UnsignedImmediate(Imm); }], NOOP_SDNodeXForm, "U3Imm", 3>; defm u4imm : UnsignedImmediate(Imm); }], NOOP_SDNodeXForm, "U4Imm", 4>; defm u5imm : UnsignedImmediate(Imm); }], NOOP_SDNodeXForm, "U5Imm", 5>; defm u6imm : UnsignedImmediate(Imm); }], NOOP_SDNodeXForm, "U6Imm", 6>; defm u7imm : UnsignedImmediate(Imm); }], NOOP_SDNodeXForm, "U7Imm", 7>; defm u8imm : UnsignedImmediate(Imm); }], NOOP_SDNodeXForm, "U8Imm", 8>; // Truncating version for BUILD_VECTOR operands that may be sign-extended. // Uses the same parser class as u8imm but with a truncating print method. def u8imm_trunc : UImmediateOp { let PrintMethod = "printU8ImmOperandTrunc"; } defm u10imm : UnsignedImmediate(Imm); }], NOOP_SDNodeXForm, "U10Imm", 10>; defm u12imm : UnsignedImmediate(Imm); }], NOOP_SDNodeXForm, "U12Imm", 12>; defm u32imm : UnsignedImmediate(Imm); }], NOOP_SDNodeXForm, "U32Imm", 32>; defm s5imm : SignedImmediate(Imm); }], NOOP_SDNodeXForm, "S5Imm", 5>; defm s32imm : SignedImmediateWithPCRel(Imm); }], NOOP_SDNodeXForm, "S32Imm", 32, "PPC::fixup_ppc_imm32", "PPC::fixup_ppc_pcrel32">; defm s34imm : SignedImmediateReloc(Imm); }], NOOP_SDNodeXForm, "S34Imm", 34, "PPC::fixup_ppc_imm34">; defm neg_s32imm : SignedImmediateReloc(Imm); }], NEG_S32, "NegS32Imm", 32, "PPC::fixup_ppc_imm32">; //===----------------------------------------------------------------------===// // i64 immediate operands //===----------------------------------------------------------------------===// defm s32imm64 : SignedImmediateWithPCRel(Imm); }], NOOP_SDNodeXForm, "S32Imm", 32, "PPC::fixup_ppc_imm32", "PPC::fixup_ppc_pcrel32">; defm s34imm64 : SignedImmediateWithPCRel(Imm); }], NOOP_SDNodeXForm, "S34Imm", 34, "PPC::fixup_ppc_imm34", "PPC::fixup_ppc_pcrel34">; defm neg_s32imm64 : SignedImmediateReloc(Imm); }], NEG_S32, "NegS32Imm", 32, "PPC::fixup_ppc_imm32">; //===----------------------------------------------------------------------===// // Special case immediate operands //===----------------------------------------------------------------------===// // immZero represents a hardcoded zero register encoding, it is NOT used in DAG // patterns. It is only used as an instruction operand for assembly/disassembly, // specifically to represent a hardcoded zero register value in PC-relative // addressing modes. def immZero : Operand { let PrintMethod = "printImmZeroOperand"; let ParserMatchClass = ImmZero; let DecoderMethod = "decodeImmZeroOperand"; let OperandType = "OPERAND_IMMEDIATE"; } // atimm is used to represent branch prediction hints, not a general immediate // value. It's a 2-bit AT (Address Translation) field in PPC branch instructions // and is an assembly-only operand that prints as `+` or `-` symbols, not // numeric values. def atimm : Operand { let PrintMethod = "printATBitsAsHint"; let ParserMatchClass = ATBitsAsHint; let OperandType = "OPERAND_IMMEDIATE"; } // Special cases: s16imm and u16imm have custom encoder methods. defm s16imm : SignedImmediateReloc(Imm); }], NOOP_SDNodeXForm, "S16Imm", 16, "PPC::fixup_ppc_half16">; defm u16imm : UnsignedImmediateReloc(Imm); }], NOOP_SDNodeXForm, "U16Imm", 16, "PPC::fixup_ppc_half16">; // s16imm64 uses imm64SExt16 pattern to match the operand type. def s16imm64 : ImmediateRelocOp; // u16imm64 uses two different patterns depending on the instruction context: // * immZExt16 - For low 16-bit immediates // * imm16ShiftedZExt - For high 16-bit immediates (shifted) def u16imm64 : UImmediateRelocOp; // Special case: s17imm uses S16Imm print method but accepts wider range. // This operand type is used for addis/lis to allow the assembler parser // to accept immediates in the range -65536..65535 for compatibility // with the GNU assembler. The operand is treated as 16-bit otherwise. def s17imm : ImmediateRelocOp { let PrintMethod = "printS16ImmOperand"; } def s17imm64 : ImmediateRelocOp { let PrintMethod = "printS16ImmOperand"; } //===----------------------------------------------------------------------===// // Branch target operands //===----------------------------------------------------------------------===// def PPCDirectBrAsmOperand : AsmOperandClass { let Name = "DirectBr"; let PredicateMethod = "isDirectBr"; let RenderMethod = "addBranchTargetOperands"; } def directbrtarget : Operand { let PrintMethod = "printBranchOperand"; let EncoderMethod = "getDirectBrEncoding"; let DecoderMethod = "decodeDirectBrTarget"; let ParserMatchClass = PPCDirectBrAsmOperand; let OperandType = "OPERAND_PCREL"; } def absdirectbrtarget : Operand { let PrintMethod = "printAbsBranchOperand"; let EncoderMethod = "getAbsDirectBrEncoding"; let DecoderMethod = "decodeDirectBrTarget"; let ParserMatchClass = PPCDirectBrAsmOperand; } def PPCCondBrAsmOperand : AsmOperandClass { let Name = "CondBr"; let PredicateMethod = "isCondBr"; let RenderMethod = "addBranchTargetOperands"; } def condbrtarget : Operand { let PrintMethod = "printBranchOperand"; let EncoderMethod = "getCondBrEncoding"; let DecoderMethod = "decodeCondBrTarget"; let ParserMatchClass = PPCCondBrAsmOperand; let OperandType = "OPERAND_PCREL"; } def abscondbrtarget : Operand { let PrintMethod = "printAbsBranchOperand"; let EncoderMethod = "getAbsCondBrEncoding"; let DecoderMethod = "decodeCondBrTarget"; let ParserMatchClass = PPCCondBrAsmOperand; } def calltarget : Operand { let PrintMethod = "printBranchOperand"; let EncoderMethod = "getDirectBrEncoding"; let DecoderMethod = "decodeDirectBrTarget"; let ParserMatchClass = PPCDirectBrAsmOperand; let OperandType = "OPERAND_PCREL"; } def abscalltarget : Operand { let PrintMethod = "printAbsBranchOperand"; let EncoderMethod = "getAbsDirectBrEncoding"; let DecoderMethod = "decodeDirectBrTarget"; let ParserMatchClass = PPCDirectBrAsmOperand; } //===----------------------------------------------------------------------===// // CR bit mask operand //===----------------------------------------------------------------------===// def PPCCRBitMaskOperand : AsmOperandClass { let Name = "CRBitMask"; let PredicateMethod = "isCRBitMask"; } def crbitm: Operand { let PrintMethod = "printcrbitm"; let EncoderMethod = "get_crbitm_encoding"; let DecoderMethod = "decodeCRBitMOperand"; let ParserMatchClass = PPCCRBitMaskOperand; } //===----------------------------------------------------------------------===// // Displacement operands //===----------------------------------------------------------------------===// def PPCDispRI34Operand : AsmOperandClass { let Name = "DispRI34"; let PredicateMethod = "isS34Imm"; let RenderMethod = "addImmOperands"; } def dispRI34 : Operand { let ParserMatchClass = PPCDispRI34Operand; let EncoderMethod = "getDispRI34Encoding"; let DecoderMethod = "decodeSImmOperand<34>"; } def dispRI34_pcrel : Operand { let ParserMatchClass = PPCDispRI34Operand; let EncoderMethod = "getDispRI34PCRelEncoding"; let DecoderMethod = "decodeSImmOperand<34>"; } def PPCDispRIOperand : AsmOperandClass { let Name = "DispRI"; let PredicateMethod = "isS16Imm"; let RenderMethod = "addS16ImmOperands"; } def dispRI : Operand { let ParserMatchClass = PPCDispRIOperand; let EncoderMethod = "getDispRIEncoding"; } def PPCDispRIXOperand : AsmOperandClass { let Name = "DispRIX"; let PredicateMethod = "isS16ImmX4"; let RenderMethod = "addS16ImmOperands"; } def dispRIX : Operand { let ParserMatchClass = PPCDispRIXOperand; let EncoderMethod = "getDispRIXEncoding"; let DecoderMethod = "decodeDispRIXOperand"; } def PPCDispRIHashOperand : AsmOperandClass { let Name = "DispRIHash"; let PredicateMethod = "isHashImmX8"; let RenderMethod = "addImmOperands"; } def dispRIHash : Operand { let ParserMatchClass = PPCDispRIHashOperand; let EncoderMethod = "getDispRIHashEncoding"; let DecoderMethod = "decodeDispRIHashOperand"; } def PPCDispRIX16Operand : AsmOperandClass { let Name = "DispRIX16"; let PredicateMethod = "isS16ImmX16"; let RenderMethod = "addS16ImmOperands"; } def dispRIX16 : Operand { let ParserMatchClass = PPCDispRIX16Operand; let EncoderMethod = "getDispRIX16Encoding"; let DecoderMethod = "decodeDispRIX16Operand"; } def PPCDispSPE8Operand : AsmOperandClass { let Name = "DispSPE8"; let PredicateMethod = "isU8ImmX8"; let RenderMethod = "addImmOperands"; } def dispSPE8 : Operand { let ParserMatchClass = PPCDispSPE8Operand; let DecoderMethod = "decodeDispSPE8Operand"; let EncoderMethod = "getDispSPE8Encoding"; } def PPCDispSPE4Operand : AsmOperandClass { let Name = "DispSPE4"; let PredicateMethod = "isU7ImmX4"; let RenderMethod = "addImmOperands"; } def dispSPE4 : Operand { let ParserMatchClass = PPCDispSPE4Operand; let DecoderMethod = "decodeDispSPE4Operand"; let EncoderMethod = "getDispSPE4Encoding"; } def PPCDispSPE2Operand : AsmOperandClass { let Name = "DispSPE2"; let PredicateMethod = "isU6ImmX2"; let RenderMethod = "addImmOperands"; } def dispSPE2 : Operand { let ParserMatchClass = PPCDispSPE2Operand; let DecoderMethod = "decodeDispSPE2Operand"; let EncoderMethod = "getDispSPE2Encoding"; } //===----------------------------------------------------------------------===// // TLS operands //===----------------------------------------------------------------------===// def PPCTLSRegOperand : AsmOperandClass { let Name = "TLSReg"; let PredicateMethod = "isTLSReg"; let RenderMethod = "addTLSRegOperands"; } def tlsreg32 : Operand { let EncoderMethod = "getTLSRegEncoding"; let ParserMatchClass = PPCTLSRegOperand; } def tlsgd32 : Operand {} def tlscall32 : Operand { let PrintMethod = "printTLSCall"; let MIOperandInfo = (ops calltarget:$func, tlsgd32:$sym); let EncoderMethod = "getTLSCallEncoding"; }