Skip to content
ARMInstrInfo.td 137 KiB
Newer Older
//===- ARMInstrInfo.td - Target Description for ARM Target -*- tablegen -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the ARM instructions in TableGen format.
//
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// ARM specific DAG Nodes.
//

// Type profiles.
def SDT_ARMCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>;
def SDT_ARMCallSeqEnd   : SDCallSeqEnd<[ SDTCisVT<0, i32>, SDTCisVT<1, i32> ]>;

def SDT_ARMSaveCallPC : SDTypeProfile<0, 1, []>;

def SDT_ARMcall    : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;

def SDT_ARMCMov    : SDTypeProfile<1, 3,
                                   [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
                                    SDTCisVT<3, i32>]>;

def SDT_ARMBrcond  : SDTypeProfile<0, 2,
                                   [SDTCisVT<0, OtherVT>, SDTCisVT<1, i32>]>;

def SDT_ARMBrJT    : SDTypeProfile<0, 3,
                                  [SDTCisPtrTy<0>, SDTCisVT<1, i32>,
                                   SDTCisVT<2, i32>]>;

def SDT_ARMBr2JT   : SDTypeProfile<0, 4,
                                  [SDTCisPtrTy<0>, SDTCisVT<1, i32>,
                                   SDTCisVT<2, i32>, SDTCisVT<3, i32>]>;

def SDT_ARMBCC_i64 : SDTypeProfile<0, 6,
                                  [SDTCisVT<0, i32>,
                                   SDTCisVT<1, i32>, SDTCisVT<2, i32>,
                                   SDTCisVT<3, i32>, SDTCisVT<4, i32>,
                                   SDTCisVT<5, OtherVT>]>;

def SDT_ARMAnd     : SDTypeProfile<1, 2,
                                   [SDTCisVT<0, i32>, SDTCisVT<1, i32>,
                                    SDTCisVT<2, i32>]>;

def SDT_ARMCmp     : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;

def SDT_ARMPICAdd  : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>,
                                          SDTCisPtrTy<1>, SDTCisVT<2, i32>]>;

def SDT_ARMThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>;
def SDT_ARMEH_SJLJ_Setjmp : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisPtrTy<1>,
                                                 SDTCisInt<2>]>;
def SDT_ARMEH_SJLJ_Longjmp: SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisInt<1>]>;
def SDT_ARMEH_SJLJ_DispatchSetup: SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;

def SDT_ARMMEMBARRIER     : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
def SDT_ARMTCRET : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;

def SDT_ARMBFI : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisVT<1, i32>,
                                      SDTCisVT<2, i32>, SDTCisVT<3, i32>]>;

// Node definitions.
def ARMWrapper       : SDNode<"ARMISD::Wrapper",     SDTIntUnaryOp>;
def ARMWrapperJT     : SDNode<"ARMISD::WrapperJT",   SDTIntBinOp>;

def ARMcallseq_start : SDNode<"ISD::CALLSEQ_START", SDT_ARMCallSeqStart,
Bill Wendling's avatar
Bill Wendling committed
                              [SDNPHasChain, SDNPOutFlag]>;
def ARMcallseq_end   : SDNode<"ISD::CALLSEQ_END",   SDT_ARMCallSeqEnd,
Bill Wendling's avatar
Bill Wendling committed
                              [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;

def ARMcall          : SDNode<"ARMISD::CALL", SDT_ARMcall,
                              [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag,
                               SDNPVariadic]>;
def ARMcall_pred    : SDNode<"ARMISD::CALL_PRED", SDT_ARMcall,
                              [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag,
                               SDNPVariadic]>;
def ARMcall_nolink   : SDNode<"ARMISD::CALL_NOLINK", SDT_ARMcall,
                              [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag,
                               SDNPVariadic]>;
Chris Lattner's avatar
Chris Lattner committed
def ARMretflag       : SDNode<"ARMISD::RET_FLAG", SDTNone,
                              [SDNPHasChain, SDNPOptInFlag]>;

def ARMcmov          : SDNode<"ARMISD::CMOV", SDT_ARMCMov,
                              [SDNPInFlag]>;
def ARMcneg          : SDNode<"ARMISD::CNEG", SDT_ARMCMov,
                              [SDNPInFlag]>;

def ARMbrcond        : SDNode<"ARMISD::BRCOND", SDT_ARMBrcond,
                              [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;

def ARMbrjt          : SDNode<"ARMISD::BR_JT", SDT_ARMBrJT,
                              [SDNPHasChain]>;
def ARMbr2jt         : SDNode<"ARMISD::BR2_JT", SDT_ARMBr2JT,
                              [SDNPHasChain]>;
def ARMBcci64        : SDNode<"ARMISD::BCC_i64", SDT_ARMBCC_i64,
                              [SDNPHasChain]>;

def ARMcmp           : SDNode<"ARMISD::CMP", SDT_ARMCmp,
                              [SDNPOutFlag]>;

def ARMcmpZ          : SDNode<"ARMISD::CMPZ", SDT_ARMCmp,
                              [SDNPOutFlag, SDNPCommutative]>;
def ARMpic_add       : SDNode<"ARMISD::PIC_ADD", SDT_ARMPICAdd>;

def ARMsrl_flag      : SDNode<"ARMISD::SRL_FLAG", SDTIntUnaryOp, [SDNPOutFlag]>;
def ARMsra_flag      : SDNode<"ARMISD::SRA_FLAG", SDTIntUnaryOp, [SDNPOutFlag]>;
def ARMrrx           : SDNode<"ARMISD::RRX"     , SDTIntUnaryOp, [SDNPInFlag ]>;

def ARMthread_pointer: SDNode<"ARMISD::THREAD_POINTER", SDT_ARMThreadPointer>;
def ARMeh_sjlj_setjmp: SDNode<"ARMISD::EH_SJLJ_SETJMP",
                               SDT_ARMEH_SJLJ_Setjmp, [SDNPHasChain]>;
def ARMeh_sjlj_longjmp: SDNode<"ARMISD::EH_SJLJ_LONGJMP",
                               SDT_ARMEH_SJLJ_Longjmp, [SDNPHasChain]>;
def ARMeh_sjlj_dispatchsetup: SDNode<"ARMISD::EH_SJLJ_DISPATCHSETUP",
                               SDT_ARMEH_SJLJ_DispatchSetup, [SDNPHasChain]>;

def ARMMemBarrier     : SDNode<"ARMISD::MEMBARRIER", SDT_ARMMEMBARRIER,
                               [SDNPHasChain]>;
def ARMMemBarrierMCR  : SDNode<"ARMISD::MEMBARRIER_MCR", SDT_ARMMEMBARRIER,
def ARMPreload        : SDNode<"ARMISD::PRELOAD", SDTPrefetch,
                               [SDNPHasChain, SDNPMayLoad, SDNPMayStore]>;
def ARMrbit          : SDNode<"ARMISD::RBIT", SDTIntUnaryOp>;

Jim Grosbach's avatar
Jim Grosbach committed
def ARMtcret         : SDNode<"ARMISD::TC_RETURN", SDT_ARMTCRET,
                        [SDNPHasChain,  SDNPOptInFlag, SDNPVariadic]>;


def ARMbfi           : SDNode<"ARMISD::BFI", SDT_ARMBFI>;

//===----------------------------------------------------------------------===//
// ARM Instruction Predicate Definitions.
//
def HasV4T           : Predicate<"Subtarget->hasV4TOps()">, AssemblerPredicate;
def NoV4T            : Predicate<"!Subtarget->hasV4TOps()">;
def HasV5T           : Predicate<"Subtarget->hasV5TOps()">;
def HasV5TE          : Predicate<"Subtarget->hasV5TEOps()">, AssemblerPredicate;
def HasV6            : Predicate<"Subtarget->hasV6Ops()">, AssemblerPredicate;
def HasV6T2          : Predicate<"Subtarget->hasV6T2Ops()">, AssemblerPredicate;
def NoV6T2           : Predicate<"!Subtarget->hasV6T2Ops()">;
def HasV7            : Predicate<"Subtarget->hasV7Ops()">, AssemblerPredicate;
def NoVFP            : Predicate<"!Subtarget->hasVFP2()">;
def HasVFP2          : Predicate<"Subtarget->hasVFP2()">, AssemblerPredicate;
def HasVFP3          : Predicate<"Subtarget->hasVFP3()">, AssemblerPredicate;
def HasNEON          : Predicate<"Subtarget->hasNEON()">, AssemblerPredicate;
def HasDivide        : Predicate<"Subtarget->hasDivide()">, AssemblerPredicate;
def HasT2ExtractPack : Predicate<"Subtarget->hasT2ExtractPack()">,
                                 AssemblerPredicate;
def HasDB            : Predicate<"Subtarget->hasDataBarrier()">,
                                 AssemblerPredicate;
def HasMP            : Predicate<"Subtarget->hasMPExtension()">,
                                 AssemblerPredicate;
def UseNEONForFP     : Predicate<"Subtarget->useNEONForSinglePrecisionFP()">;
def DontUseNEONForFP : Predicate<"!Subtarget->useNEONForSinglePrecisionFP()">;
def IsThumb          : Predicate<"Subtarget->isThumb()">, AssemblerPredicate;
def IsThumb1Only     : Predicate<"Subtarget->isThumb1Only()">;
def IsThumb2         : Predicate<"Subtarget->isThumb2()">, AssemblerPredicate;
def IsARM            : Predicate<"!Subtarget->isThumb()">, AssemblerPredicate;
def IsDarwin         : Predicate<"Subtarget->isTargetDarwin()">;
def IsNotDarwin      : Predicate<"!Subtarget->isTargetDarwin()">;
// FIXME: Eventually this will be just "hasV6T2Ops".
def UseMovt          : Predicate<"Subtarget->useMovt()">;
def DontUseMovt      : Predicate<"!Subtarget->useMovt()">;
def UseVMLx          : Predicate<"Subtarget->useVMLx()">;
//===----------------------------------------------------------------------===//
// ARM Flag Definitions.

class RegConstraint<string C> {
  string Constraints = C;
//===----------------------------------------------------------------------===//
//  ARM specific transformation functions and pattern fragments.
//

// so_imm_neg_XFORM - Return a so_imm value packed into the format described for
// so_imm_neg def below.
def so_imm_neg_XFORM : SDNodeXForm<imm, [{
  return CurDAG->getTargetConstant(-(int)N->getZExtValue(), MVT::i32);
}]>;

// so_imm_not_XFORM - Return a so_imm value packed into the format described for
// so_imm_not def below.
def so_imm_not_XFORM : SDNodeXForm<imm, [{
  return CurDAG->getTargetConstant(~(int)N->getZExtValue(), MVT::i32);
}]>;

/// imm1_15 predicate - True if the 32-bit immediate is in the range [1,15].
def imm1_15 : PatLeaf<(i32 imm), [{
  return (int32_t)N->getZExtValue() >= 1 && (int32_t)N->getZExtValue() < 16;
}]>;

/// imm16_31 predicate - True if the 32-bit immediate is in the range [16,31].
def imm16_31 : PatLeaf<(i32 imm), [{
  return (int32_t)N->getZExtValue() >= 16 && (int32_t)N->getZExtValue() < 32;
Jim Grosbach's avatar
Jim Grosbach committed
def so_imm_neg :
    return ARM_AM::getSOImmVal(-(uint32_t)N->getZExtValue()) != -1;
    return ARM_AM::getSOImmVal(~(uint32_t)N->getZExtValue()) != -1;

// sext_16_node predicate - True if the SDNode is sign-extended 16 or more bits.
def sext_16_node : PatLeaf<(i32 GPR:$a), [{
Dan Gohman's avatar
Dan Gohman committed
  return CurDAG->ComputeNumSignBits(SDValue(N,0)) >= 17;
Evan Cheng's avatar
Evan Cheng committed
/// bf_inv_mask_imm predicate - An AND mask to clear an arbitrary width bitfield
/// e.g., 0xf000ffff
def bf_inv_mask_imm : Operand<i32>,
Jim Grosbach's avatar
Jim Grosbach committed
                      PatLeaf<(imm), [{
  return ARM::isBitFieldInvertedMask(N->getZExtValue());
Evan Cheng's avatar
Evan Cheng committed
}] > {
  string EncoderMethod = "getBitfieldInvertedMaskOpValue";
Evan Cheng's avatar
Evan Cheng committed
  let PrintMethod = "printBitfieldInvMaskImmOperand";
}

/// Split a 32-bit immediate into two 16 bit parts.
def hi16 : SDNodeXForm<imm, [{
  return CurDAG->getTargetConstant((uint32_t)N->getZExtValue() >> 16, MVT::i32);
}]>;

def lo16AllZero : PatLeaf<(i32 imm), [{
  // Returns true if all low 16-bits are 0.
  return (((uint32_t)N->getZExtValue()) & 0xFFFFUL) == 0;
Jim Grosbach's avatar
Jim Grosbach committed
/// imm0_65535 predicate - True if the 32-bit immediate is in the range
/// [0.65535].
def imm0_65535 : PatLeaf<(i32 imm), [{
  return (uint32_t)N->getZExtValue() < 65536;
}]>;

class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
class UnOpFrag <dag res> : PatFrag<(ops node:$Src), res>;
/// adde and sube predicates - True based on whether the carry flag output
/// will be needed or not.
def adde_dead_carry :
  PatFrag<(ops node:$LHS, node:$RHS), (adde node:$LHS, node:$RHS),
  [{return !N->hasAnyUseOfValue(1);}]>;
def sube_dead_carry :
  PatFrag<(ops node:$LHS, node:$RHS), (sube node:$LHS, node:$RHS),
  [{return !N->hasAnyUseOfValue(1);}]>;
def adde_live_carry :
  PatFrag<(ops node:$LHS, node:$RHS), (adde node:$LHS, node:$RHS),
  [{return N->hasAnyUseOfValue(1);}]>;
def sube_live_carry :
  PatFrag<(ops node:$LHS, node:$RHS), (sube node:$LHS, node:$RHS),
  [{return N->hasAnyUseOfValue(1);}]>;

//===----------------------------------------------------------------------===//
// Operand Definitions.
//

// Branch target.
def brtarget : Operand<OtherVT> {
  string EncoderMethod = "getBranchTargetOpValue";
}
// Call target.
def bltarget : Operand<i32> {
  // Encoded the same as branch targets.
  string EncoderMethod = "getBranchTargetOpValue";
}

// A list of registers separated by comma. Used by load/store multiple.
def RegListAsmOperand : AsmOperandClass {
  let Name = "RegList";
  let SuperClasses = [];
}

Bill Wendling's avatar
Bill Wendling committed
def reglist : Operand<i32> {
  string EncoderMethod = "getRegisterListOpValue";
  let ParserMatchClass = RegListAsmOperand;
  let PrintMethod = "printRegisterList";
}

// An operand for the CONSTPOOL_ENTRY pseudo-instruction.
def cpinst_operand : Operand<i32> {
  let PrintMethod = "printCPInstOperand";
}

def jtblock_operand : Operand<i32> {
  let PrintMethod = "printJTBlockOperand";
}
def jt2block_operand : Operand<i32> {
  let PrintMethod = "printJT2BlockOperand";
}

// Local PC labels.
def pclabel : Operand<i32> {
  let PrintMethod = "printPCLabel";
}

  string EncoderMethod = "getNEONVcvtImm32OpValue";
// rot_imm: An integer that encodes a rotate amount. Must be 8, 16, or 24.
def rot_imm : Operand<i32>, PatLeaf<(i32 imm), [{
  int32_t v = (int32_t)N->getZExtValue();
  return v == 8 || v == 16 || v == 24; }]> {
  string EncoderMethod = "getRotImmOpValue";
}

// shift_imm: An integer that encodes a shift amount and the type of shift
// (currently either asr or lsl) using the same encoding used for the
// immediates in so_reg operands.
def shift_imm : Operand<i32> {
  let PrintMethod = "printShiftImmOperand";
}

// shifter_operand operands: so_reg and so_imm.
def so_reg : Operand<i32>,    // reg reg imm
             ComplexPattern<i32, 3, "SelectShifterOperandReg",
                            [shl,srl,sra,rotr]> {
  string EncoderMethod = "getSORegOpValue";
  let PrintMethod = "printSORegOperand";
  let MIOperandInfo = (ops GPR, GPR, i32imm);
}
def shift_so_reg : Operand<i32>,    // reg reg imm
                   ComplexPattern<i32, 3, "SelectShiftShifterOperandReg",
                                  [shl,srl,sra,rotr]> {
  string EncoderMethod = "getSORegOpValue";
  let PrintMethod = "printSORegOperand";
  let MIOperandInfo = (ops GPR, GPR, i32imm);
}

// so_imm - Match a 32-bit shifter_operand immediate operand, which is an
// 8-bit immediate rotated by an arbitrary number of bits.  so_imm values are
// represented in the imm field in the same 12-bit form that they are encoded
// into so_imm instructions: the 8-bit immediate is the least significant bits
// [bits 0-7], the 4-bit shift amount is the next 4 bits [bits 8-11].
def so_imm : Operand<i32>, PatLeaf<(imm), [{ return Pred_so_imm(N); }]> {
  string EncoderMethod = "getSOImmOpValue";
  let PrintMethod = "printSOImmOperand";
// Break so_imm's up into two pieces.  This handles immediates with up to 16
// bits set in them.  This uses so_imm2part to match and so_imm2part_[12] to
// get the first/second pieces.
      return ARM_AM::isSOImmTwoPartVal((unsigned)N->getZExtValue());
}]>;

/// arm_i32imm - True for +V6T2, or true only if so_imm2part is true.
///
def arm_i32imm : PatLeaf<(imm), [{
  if (Subtarget->hasV6T2Ops())
    return true;
  return ARM_AM::isSOImmTwoPartVal((unsigned)N->getZExtValue());
}]>;

def so_imm2part_1 : SDNodeXForm<imm, [{
  unsigned V = ARM_AM::getSOImmTwoPartFirst((unsigned)N->getZExtValue());
  return CurDAG->getTargetConstant(V, MVT::i32);
}]>;

def so_imm2part_2 : SDNodeXForm<imm, [{
  unsigned V = ARM_AM::getSOImmTwoPartSecond((unsigned)N->getZExtValue());
  return CurDAG->getTargetConstant(V, MVT::i32);
def so_neg_imm2part : Operand<i32>, PatLeaf<(imm), [{
      return ARM_AM::isSOImmTwoPartVal(-(int)N->getZExtValue());
    }]> {
  let PrintMethod = "printSOImm2PartOperand";
}

def so_neg_imm2part_1 : SDNodeXForm<imm, [{
  unsigned V = ARM_AM::getSOImmTwoPartFirst(-(int)N->getZExtValue());
  return CurDAG->getTargetConstant(V, MVT::i32);
}]>;

def so_neg_imm2part_2 : SDNodeXForm<imm, [{
  unsigned V = ARM_AM::getSOImmTwoPartSecond(-(int)N->getZExtValue());
  return CurDAG->getTargetConstant(V, MVT::i32);
}]>;

/// imm0_31 predicate - True if the 32-bit immediate is in the range [0,31].
def imm0_31 : Operand<i32>, PatLeaf<(imm), [{
  return (int32_t)N->getZExtValue() < 32;
}]>;
/// imm0_31_m1 - Matches and prints like imm0_31, but encodes as 'value - 1'.
def imm0_31_m1 : Operand<i32>, PatLeaf<(imm), [{
  return (int32_t)N->getZExtValue() < 32;
}]> {
  string EncoderMethod = "getImmMinusOneOpValue";
}

// Define ARM specific addressing modes.

def addrmode_imm12 : Operand<i32>,
                     ComplexPattern<i32, 2, "SelectAddrModeImm12", []> {
  // 12-bit immediate operand. Note that instructions using this encode
  // #0 and #-0 differently. We flag #-0 as the magic value INT32_MIN. All other
  // immediate values are as normal.
  string EncoderMethod = "getAddrModeImm12OpValue";
  let PrintMethod = "printAddrModeImm12Operand";
  let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
// ldst_so_reg := reg +/- reg shop imm
def ldst_so_reg : Operand<i32>,
                  ComplexPattern<i32, 3, "SelectLdStSOReg", []> {
  string EncoderMethod = "getLdStSORegOpValue";
  let PrintMethod = "printAddrMode2Operand";
  let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
}

// addrmode2 := reg +/- imm12
//           := reg +/- reg shop imm
//
def addrmode2 : Operand<i32>,
                ComplexPattern<i32, 3, "SelectAddrMode2", []> {
  let PrintMethod = "printAddrMode2Operand";
  let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
def am2offset : Operand<i32>,
                ComplexPattern<i32, 2, "SelectAddrMode2Offset",
                [], [SDNPWantRoot]> {
  let PrintMethod = "printAddrMode2OffsetOperand";
  let MIOperandInfo = (ops GPR, i32imm);
}
// addrmode3 := reg +/- reg
// addrmode3 := reg +/- imm8
//
def addrmode3 : Operand<i32>,
                ComplexPattern<i32, 3, "SelectAddrMode3", []> {
  string EncoderMethod = "getAddrMode3OpValue";
  let PrintMethod = "printAddrMode3Operand";
  let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
}
def am3offset : Operand<i32>,
                ComplexPattern<i32, 2, "SelectAddrMode3Offset",
                               [], [SDNPWantRoot]> {
  string EncoderMethod = "getAddrMode3OffsetOpValue";
  let PrintMethod = "printAddrMode3OffsetOperand";
  let MIOperandInfo = (ops GPR, i32imm);
}

def ldstm_mode : OptionalDefOperand<OtherVT, (ops i32), (ops (i32 1))> {
  string EncoderMethod = "getLdStmModeOpValue";
  let PrintMethod = "printLdStmModeOperand";
def MemMode5AsmOperand : AsmOperandClass {
  let Name = "MemMode5";
  let SuperClasses = [];
}

// addrmode5 := reg +/- imm8*4
//
def addrmode5 : Operand<i32>,
                ComplexPattern<i32, 2, "SelectAddrMode5", []> {
  let PrintMethod = "printAddrMode5Operand";
  let MIOperandInfo = (ops GPR:$base, i32imm);
  let ParserMatchClass = MemMode5AsmOperand;
  string EncoderMethod = "getAddrMode5OpValue";
// addrmode6 := reg with optional writeback
//
def addrmode6 : Operand<i32>,
                ComplexPattern<i32, 2, "SelectAddrMode6", [], [SDNPWantParent]>{
  let PrintMethod = "printAddrMode6Operand";
  let MIOperandInfo = (ops GPR:$addr, i32imm);
  string EncoderMethod = "getAddrMode6AddressOpValue";
}

def am6offset : Operand<i32> {
  let PrintMethod = "printAddrMode6OffsetOperand";
  let MIOperandInfo = (ops GPR);
  string EncoderMethod = "getAddrMode6OffsetOpValue";
// addrmodepc := pc + reg
//
def addrmodepc : Operand<i32>,
                 ComplexPattern<i32, 2, "SelectAddrModePC", []> {
  let PrintMethod = "printAddrModePCOperand";
  let MIOperandInfo = (ops GPR, i32imm);
}
def nohash_imm : Operand<i32> {
  let PrintMethod = "printNoHashImmediate";
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
Evan Cheng's avatar
Evan Cheng committed
/// AsI1_bin_irs - Defines a set of (op r, {so_imm|r|so_reg}) patterns for a
/// binop that produces a value.
multiclass AsI1_bin_irs<bits<4> opcod, string opc,
                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
                        PatFrag opnode, bit Commutable = 0> {
  // The register-immediate version is re-materializable. This is useful
  // in particular for taking the address of a local.
  let isReMaterializable = 1 in {
  def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
               iii, opc, "\t$Rd, $Rn, $imm",
               [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]> {
    bits<4> Rd;
    bits<4> Rn;
    let Inst{15-12} = Rd;
  def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm,
               iir, opc, "\t$Rd, $Rn, $Rm",
               [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]> {
    let isCommutable = Commutable;
    let Inst{15-12} = Rd;
    let Inst{11-4} = 0b00000000;
    let Inst{3-0} = Rm;
  def rs : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), DPSoRegFrm,
               iis, opc, "\t$Rd, $Rn, $shift",
               [(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]> {
    let Inst{15-12} = Rd;
    let Inst{11-0} = shift;
/// AI1_bin_s_irs - Similar to AsI1_bin_irs except it sets the 's' bit so the
Bob Wilson's avatar
Bob Wilson committed
/// instruction modifies the CPSR register.
multiclass AI1_bin_s_irs<bits<4> opcod, string opc,
                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
                         PatFrag opnode, bit Commutable = 0> {
  def ri : AI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
               iii, opc, "\t$Rd, $Rn, $imm",
               [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]> {
    bits<4> Rd;
    bits<4> Rn;
    bits<12> imm;
    let Inst{20} = 1;
    let Inst{15-12} = Rd;
  def rr : AI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm,
               iir, opc, "\t$Rd, $Rn, $Rm",
               [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]> {
    bits<4> Rd;
    bits<4> Rn;
    bits<4> Rm;
    let isCommutable = Commutable;
    let Inst{25} = 0;
    let Inst{19-16} = Rn;
    let Inst{15-12} = Rd;
    let Inst{11-4} = 0b00000000;
    let Inst{3-0} = Rm;
  }
  def rs : AI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), DPSoRegFrm,
               iis, opc, "\t$Rd, $Rn, $shift",
               [(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]> {
    bits<4> Rd;
    bits<4> Rn;
    bits<12> shift;
    let Inst{19-16} = Rn;
    let Inst{15-12} = Rd;
    let Inst{11-0} = shift;
}

/// AI1_cmp_irs - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test
/// patterns. Similar to AsI1_bin_irs except the instruction does not produce
/// a explicit result, only implicitly set CPSR.
let isCompare = 1, Defs = [CPSR] in {
multiclass AI1_cmp_irs<bits<4> opcod, string opc,
                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
                       PatFrag opnode, bit Commutable = 0> {
  def ri : AI1<opcod, (outs), (ins GPR:$Rn, so_imm:$imm), DPFrm, iii,
               opc, "\t$Rn, $imm",
               [(opnode GPR:$Rn, so_imm:$imm)]> {
    bits<4> Rn;
    bits<12> imm;
    let Inst{20} = 1;
    let Inst{15-12} = 0b0000;
  def rr : AI1<opcod, (outs), (ins GPR:$Rn, GPR:$Rm), DPFrm, iir,
               opc, "\t$Rn, $Rm",
               [(opnode GPR:$Rn, GPR:$Rm)]> {
    bits<4> Rn;
    bits<4> Rm;
    let isCommutable = Commutable;
    let Inst{25} = 0;
    let Inst{20} = 1;
    let Inst{19-16} = Rn;
    let Inst{15-12} = 0b0000;
    let Inst{11-4} = 0b00000000;
    let Inst{3-0} = Rm;
  }
  def rs : AI1<opcod, (outs), (ins GPR:$Rn, so_reg:$shift), DPSoRegFrm, iis,
               opc, "\t$Rn, $shift",
               [(opnode GPR:$Rn, so_reg:$shift)]> {
    bits<4> Rn;
    bits<12> shift;
    let Inst{19-16} = Rn;
    let Inst{15-12} = 0b0000;
    let Inst{11-0} = shift;
/// AI_ext_rrot - A unary operation with two forms: one whose operand is a
/// register and one whose operand is a register rotated by 8/16/24.
/// FIXME: Remove the 'r' variant. Its rot_imm is zero.
multiclass AI_ext_rrot<bits<8> opcod, string opc, PatFrag opnode> {
  def r     : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rm),
                 IIC_iEXTr, opc, "\t$Rd, $Rm",
                 [(set GPR:$Rd, (opnode GPR:$Rm))]>,
              Requires<[IsARM, HasV6]> {
    bits<4> Rd;
    bits<4> Rm;
    let Inst{19-16} = 0b1111;
    let Inst{15-12} = Rd;
    let Inst{3-0}   = Rm;
  def r_rot : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rm, rot_imm:$rot),
                 IIC_iEXTr, opc, "\t$Rd, $Rm, ror $rot",
                 [(set GPR:$Rd, (opnode (rotr GPR:$Rm, rot_imm:$rot)))]>,
              Requires<[IsARM, HasV6]> {
    bits<4> Rd;
    bits<4> Rm;
    let Inst{19-16} = 0b1111;
    let Inst{15-12} = Rd;
    let Inst{3-0}   = Rm;
multiclass AI_ext_rrot_np<bits<8> opcod, string opc> {
  def r     : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rm),
                 IIC_iEXTr, opc, "\t$Rd, $Rm",
                 [/* For disassembly only; pattern left blank */]>,
              Requires<[IsARM, HasV6]> {
    let Inst{19-16} = 0b1111;
    let Inst{11-10} = 0b00;
  def r_rot : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rm, rot_imm:$rot),
                 IIC_iEXTr, opc, "\t$Rd, $Rm, ror $rot",
                 [/* For disassembly only; pattern left blank */]>,
              Requires<[IsARM, HasV6]> {
    let Inst{11-10} = rot;
/// AI_exta_rrot - A binary operation with two forms: one whose operand is a
/// register and one whose operand is a register rotated by 8/16/24.
multiclass AI_exta_rrot<bits<8> opcod, string opc, PatFrag opnode> {
  def rr     : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
                  IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm",
                  [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]>,
               Requires<[IsARM, HasV6]> {
    let Inst{11-10} = 0b00;
  }
  def rr_rot : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm,
                                             rot_imm:$rot),
                  IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm, ror $rot",
                  [(set GPR:$Rd, (opnode GPR:$Rn,
                                          (rotr GPR:$Rm, rot_imm:$rot)))]>,
                  Requires<[IsARM, HasV6]> {
    bits<4> Rn;
    bits<2> rot;
    let Inst{19-16} = Rn;
    let Inst{11-10} = rot;
  }
multiclass AI_exta_rrot_np<bits<8> opcod, string opc> {
  def rr     : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
                  IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm",
                  [/* For disassembly only; pattern left blank */]>,
               Requires<[IsARM, HasV6]> {
    let Inst{11-10} = 0b00;
  }
  def rr_rot : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm,
                                             rot_imm:$rot),
                  IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm, ror $rot",
                  [/* For disassembly only; pattern left blank */]>,
                  Requires<[IsARM, HasV6]> {
    bits<4> Rn;
    bits<2> rot;
    let Inst{19-16} = Rn;
    let Inst{11-10} = rot;
  }
/// AI1_adde_sube_irs - Define instructions and patterns for adde and sube.
let Uses = [CPSR] in {
multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
                             bit Commutable = 0> {
  def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
                DPFrm, IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
               [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>,
    let Inst{15-12} = Rd;
    let Inst{19-16} = Rn;
    let Inst{11-0} = imm;
  def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
                DPFrm, IIC_iALUr, opc, "\t$Rd, $Rn, $Rm",
               [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]>,
    let isCommutable = Commutable;
    let Inst{3-0} = Rm;
    let Inst{15-12} = Rd;
    let Inst{19-16} = Rn;
  def rs : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
                DPSoRegFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift",
               [(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]>,
    let Inst{11-0} = shift;
    let Inst{15-12} = Rd;
    let Inst{19-16} = Rn;
}
// Carry setting variants
let Defs = [CPSR] in {
multiclass AI1_adde_sube_s_irs<bits<4> opcod, string opc, PatFrag opnode,
                             bit Commutable = 0> {
  def Sri : AXI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
                DPFrm, IIC_iALUi, !strconcat(opc, "\t$Rd, $Rn, $imm"),
               [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>,
    bits<4> Rd;
    bits<4> Rn;
    bits<12> imm;
    let Inst{15-12} = Rd;
    let Inst{19-16} = Rn;
    let Inst{11-0} = imm;
  def Srr : AXI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
                DPFrm, IIC_iALUr, !strconcat(opc, "\t$Rd, $Rn, $Rm"),
               [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]>,
    let isCommutable = Commutable;
    let Inst{3-0} = Rm;
    let Inst{15-12} = Rd;
    let Inst{19-16} = Rn;
  def Srs : AXI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
                DPSoRegFrm, IIC_iALUsr, !strconcat(opc, "\t$Rd, $Rn, $shift"),
               [(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]>,
    bits<4> Rd;
    bits<4> Rn;
    bits<12> shift;
    let Inst{11-0} = shift;
    let Inst{15-12} = Rd;
    let Inst{19-16} = Rn;
let canFoldAsLoad = 1, isReMaterializable = 1 in {
multiclass AI_ldr1<bit isByte, string opc, InstrItinClass iii,
           InstrItinClass iir, PatFrag opnode> {
  // Note: We use the complex addrmode_imm12 rather than just an input
  // GPR and a constrained immediate so that we can use this to match
  // frame index references and avoid matching constant pool references.
  def i12: AIldst1<0b010, 1, isByte, (outs GPR:$Rt), (ins addrmode_imm12:$addr),
                   AddrMode_i12, LdFrm, iii, opc, "\t$Rt, $addr",
                  [(set GPR:$Rt, (opnode addrmode_imm12:$addr))]> {
    bits<4>  Rt;
    bits<17> addr;
    let Inst{23}    = addr{12};     // U (add = ('U' == 1))
    let Inst{19-16} = addr{16-13};  // Rn
    let Inst{15-12} = Rt;
    let Inst{11-0}  = addr{11-0};   // imm12
  }
  def rs : AIldst1<0b011, 1, isByte, (outs GPR:$Rt), (ins ldst_so_reg:$shift),
                  AddrModeNone, LdFrm, iir, opc, "\t$Rt, $shift",
                 [(set GPR:$Rt, (opnode ldst_so_reg:$shift))]> {
    bits<4>  Rt;
    bits<17> shift;
    let Inst{23}    = shift{12};    // U (add = ('U' == 1))
    let Inst{19-16} = shift{16-13}; // Rn
multiclass AI_str1<bit isByte, string opc, InstrItinClass iii,
           InstrItinClass iir, PatFrag opnode> {
  // Note: We use the complex addrmode_imm12 rather than just an input
  // GPR and a constrained immediate so that we can use this to match
  // frame index references and avoid matching constant pool references.
  def i12 : AIldst1<0b010, 0, isByte, (outs),
                   (ins GPR:$Rt, addrmode_imm12:$addr),
                   AddrMode_i12, StFrm, iii, opc, "\t$Rt, $addr",
                  [(opnode GPR:$Rt, addrmode_imm12:$addr)]> {
    bits<4> Rt;
    bits<17> addr;
    let Inst{23}    = addr{12};     // U (add = ('U' == 1))
    let Inst{19-16} = addr{16-13};  // Rn
    let Inst{15-12} = Rt;
    let Inst{11-0}  = addr{11-0};   // imm12
  }
  def rs : AIldst1<0b011, 0, isByte, (outs), (ins GPR:$Rt, ldst_so_reg:$shift),
                  AddrModeNone, StFrm, iir, opc, "\t$Rt, $shift",
                 [(opnode GPR:$Rt, ldst_so_reg:$shift)]> {
    bits<4> Rt;
    bits<17> shift;
    let Inst{23}    = shift{12};    // U (add = ('U' == 1))
    let Inst{19-16} = shift{16-13}; // Rn
//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
//  Miscellaneous Instructions.
//

/// CONSTPOOL_ENTRY - This instruction represents a floating constant pool in
/// the function.  The first operand is the ID# for this instruction, the second
/// is the index into the MachineConstantPool that this is, the third is the
/// size in bytes of this constant pool entry.
let neverHasSideEffects = 1, isNotDuplicable = 1 in
def CONSTPOOL_ENTRY :
PseudoInst<(outs), (ins cpinst_operand:$instid, cpinst_operand:$cpidx,
                    i32imm:$size), NoItinerary, "", []>;
// FIXME: Marking these as hasSideEffects is necessary to prevent machine DCE
// from removing one half of the matched pairs. That breaks PEI, which assumes
// these will always be in pairs, and asserts if it finds otherwise. Better way?
let Defs = [SP], Uses = [SP], hasSideEffects = 1 in {
def ADJCALLSTACKUP :
PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2, pred:$p), NoItinerary, "",
           [(ARMcallseq_end timm:$amt1, timm:$amt2)]>;
Jim Grosbach's avatar
Jim Grosbach committed
def ADJCALLSTACKDOWN :
PseudoInst<(outs), (ins i32imm:$amt, pred:$p), NoItinerary, "",
           [(ARMcallseq_start timm:$amt)]>;
def NOP : AI<(outs), (ins), MiscFrm, NoItinerary, "nop", "",
             [/* For disassembly only; pattern left blank */]>,
          Requires<[IsARM, HasV6T2]> {
  let Inst{27-16} = 0b001100100000;
def YIELD : AI<(outs), (ins), MiscFrm, NoItinerary, "yield", "",
             [/* For disassembly only; pattern left blank */]>,
          Requires<[IsARM, HasV6T2]> {
  let Inst{27-16} = 0b001100100000;
  let Inst{7-0} = 0b00000001;
}

def WFE : AI<(outs), (ins), MiscFrm, NoItinerary, "wfe", "",
             [/* For disassembly only; pattern left blank */]>,
          Requires<[IsARM, HasV6T2]> {
  let Inst{27-16} = 0b001100100000;
  let Inst{7-0} = 0b00000010;
}

def WFI : AI<(outs), (ins), MiscFrm, NoItinerary, "wfi", "",
             [/* For disassembly only; pattern left blank */]>,
          Requires<[IsARM, HasV6T2]> {
  let Inst{27-16} = 0b001100100000;
def SEL : AI<(outs GPR:$dst), (ins GPR:$a, GPR:$b), DPFrm, NoItinerary, "sel",
             "\t$dst, $a, $b",
             [/* For disassembly only; pattern left blank */]>,
          Requires<[IsARM, HasV6]> {
  bits<4> Rd;
  bits<4> Rn;
  bits<4> Rm;
  let Inst{3-0} = Rm;
  let Inst{15-12} = Rd;
  let Inst{19-16} = Rn;
  let Inst{27-20} = 0b01101000;
  let Inst{7-4} = 0b1011;
def SEV : AI<(outs), (ins), MiscFrm, NoItinerary, "sev", "",
             [/* For disassembly only; pattern left blank */]>,
          Requires<[IsARM, HasV6T2]> {
  let Inst{27-16} = 0b001100100000;
// The i32imm operand $val can be used by a debugger to store more information
// about the breakpoint.
def BKPT : AI<(outs), (ins i32imm:$val), MiscFrm, NoItinerary, "bkpt", "\t$val",
              [/* For disassembly only; pattern left blank */]>,
           Requires<[IsARM]> {
  bits<16> val;
  let Inst{3-0} = val{3-0};
  let Inst{19-8} = val{15-4};
  let Inst{27-20} = 0b00010010;
  let Inst{7-4} = 0b0111;
}