Skip to content
ARMInstrThumb2.td 51.7 KiB
Newer Older
//===- ARMInstrThumb2.td - Thumb2 support for ARM -------------------------===//
//
//                     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 Thumb2 instruction set.
//
//===----------------------------------------------------------------------===//
// IT block predicate field
def it_pred : Operand<i32> {
  let PrintMethod = "printPredicateOperand";
}

// IT block condition mask
def it_mask : Operand<i32> {
  let PrintMethod = "printThumbITMask";
}

// Table branch address
def tb_addrmode : Operand<i32> {
  let PrintMethod = "printTBAddrMode";
}

// Shifted operands. No register controlled shifts for Thumb2.
// Note: We do not support rrx shifted operands yet.
def t2_so_reg : Operand<i32>,    // reg imm
Evan Cheng's avatar
Evan Cheng committed
                ComplexPattern<i32, 2, "SelectT2ShifterOperandReg",
                               [shl,srl,sra,rotr]> {
Evan Cheng's avatar
Evan Cheng committed
  let PrintMethod = "printT2SOOperand";
  let MIOperandInfo = (ops GPR, i32imm);
}

// t2_so_imm_not_XFORM - Return the complement of a t2_so_imm value
def t2_so_imm_not_XFORM : SDNodeXForm<imm, [{
  return CurDAG->getTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32);
// t2_so_imm_neg_XFORM - Return the negation of a t2_so_imm value
def t2_so_imm_neg_XFORM : SDNodeXForm<imm, [{
  return CurDAG->getTargetConstant(-((int)N->getZExtValue()), MVT::i32);
}]>;

// t2_so_imm - Match a 32-bit immediate operand, which is an
// 8-bit immediate rotated by an arbitrary number of bits, or an 8-bit
// immediate splatted into multiple bytes of the word. t2_so_imm values are
// represented in the imm field in the same 12-bit form that they are encoded
// into t2_so_imm instructions: the 8-bit immediate is the least significant bits
// [bits 0-7], the 4-bit shift/splat amount is the next 4 bits [bits 8-11].
def t2_so_imm : Operand<i32>,
                PatLeaf<(imm), [{
  return ARM_AM::getT2SOImmVal((uint32_t)N->getZExtValue()) != -1; 
}]>;
// t2_so_imm_not - Match an immediate that is a complement 
// of a t2_so_imm.
def t2_so_imm_not : Operand<i32>,
                    PatLeaf<(imm), [{
  return ARM_AM::getT2SOImmVal(~((uint32_t)N->getZExtValue())) != -1;
}], t2_so_imm_not_XFORM>;

// t2_so_imm_neg - Match an immediate that is a negation of a t2_so_imm.
def t2_so_imm_neg : Operand<i32>,
                    PatLeaf<(imm), [{
  return ARM_AM::getT2SOImmVal(-((int)N->getZExtValue())) != -1;
}], t2_so_imm_neg_XFORM>;
// Break t2_so_imm's up into two pieces.  This handles immediates with up to 16
// bits set in them.  This uses t2_so_imm2part to match and t2_so_imm2part_[12]
// to get the first/second pieces.
def t2_so_imm2part : Operand<i32>,
                  PatLeaf<(imm), [{
      return ARM_AM::isT2SOImmTwoPartVal((unsigned)N->getZExtValue());
    }]> {
}

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

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

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

/// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095].
def imm0_4095 : Operand<i32>,
                PatLeaf<(i32 imm), [{
  return (uint32_t)N->getZExtValue() < 4096;
}]>;

def imm0_4095_neg : PatLeaf<(i32 imm), [{ 
 return (uint32_t)(-N->getZExtValue()) < 4096; 
def imm0_255_neg : PatLeaf<(i32 imm), [{
  return (uint32_t)(-N->getZExtValue()) < 255;
}], imm_neg_XFORM>; 

Evan Cheng's avatar
Evan Cheng committed
// Define Thumb2 specific addressing modes.

// t2addrmode_imm12  := reg + imm12
def t2addrmode_imm12 : Operand<i32>,
                       ComplexPattern<i32, 2, "SelectT2AddrModeImm12", []> {
  let PrintMethod = "printT2AddrModeImm12Operand";
  let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
}

Evan Cheng's avatar
Evan Cheng committed
def t2addrmode_imm8 : Operand<i32>,
                      ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
  let PrintMethod = "printT2AddrModeImm8Operand";
  let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
}

Evan Cheng's avatar
Evan Cheng committed
def t2am_imm8_offset : Operand<i32>,
                       ComplexPattern<i32, 1, "SelectT2AddrModeImm8Offset", []>{
  let PrintMethod = "printT2AddrModeImm8OffsetOperand";
}

// t2addrmode_imm8s4  := reg +/- (imm8 << 2)
def t2addrmode_imm8s4 : Operand<i32>,
                        ComplexPattern<i32, 2, "SelectT2AddrModeImm8s4", []> {
  let PrintMethod = "printT2AddrModeImm8s4Operand";
  let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
}

Evan Cheng's avatar
Evan Cheng committed
// t2addrmode_so_reg  := reg + (reg << imm2)
Evan Cheng's avatar
Evan Cheng committed
def t2addrmode_so_reg : Operand<i32>,
                        ComplexPattern<i32, 3, "SelectT2AddrModeSoReg", []> {
  let PrintMethod = "printT2AddrModeSoRegOperand";
  let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
}


//===----------------------------------------------------------------------===//
Evan Cheng's avatar
Evan Cheng committed
// Multiclass helpers...
/// T2I_un_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
/// unary operation that produces a value. These are predicable and can be
/// changed to modify CPSR.
multiclass T2I_un_irs<string opc, PatFrag opnode, bit Cheap = 0, bit ReMat = 0>{
   // shifted imm
   def i : T2sI<(outs GPR:$dst), (ins t2_so_imm:$src), IIC_iMOVi,
                [(set GPR:$dst, (opnode t2_so_imm:$src))]> {
     let isAsCheapAsAMove = Cheap;
     let isReMaterializable = ReMat;
   }
   // register
   def r : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr,
                [(set GPR:$dst, (opnode GPR:$src))]>;
   // shifted register
   def s : T2I<(outs GPR:$dst), (ins t2_so_reg:$src), IIC_iMOVsi,
               [(set GPR:$dst, (opnode t2_so_reg:$src))]>;
}

/// T2I_bin_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
//  binary operation that produces a value. These are predicable and can be
/// changed to modify CPSR.
multiclass T2I_bin_irs<string opc, PatFrag opnode, 
                       bit Commutable = 0, string wide =""> {
   def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
                 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
   def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
                 opc, !strconcat(wide, "\t$dst, $lhs, $rhs"),
                 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> {
     let isCommutable = Commutable;
   }
   def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
                 opc, !strconcat(wide, "\t$dst, $lhs, $rhs"),
                 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
/// T2I_bin_w_irs - Same as T2I_bin_irs except these operations need
//  the ".w" prefix to indicate that they are wide.
multiclass T2I_bin_w_irs<string opc, PatFrag opnode, bit Commutable = 0> :
    T2I_bin_irs<opc, opnode, Commutable, ".w">;

/// T2I_rbin_is - Same as T2I_bin_irs except the order of operands are
/// reversed. It doesn't define the 'rr' form since it's handled by its
/// T2I_bin_irs counterpart.
multiclass T2I_rbin_is<string opc, PatFrag opnode> {
Loading
Loading full blame...