Skip to content
ARMInstrThumb2.td 110 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 = "printMandatoryPredicateOperand";
}

// 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]> {
  string EncoderMethod = "getT2SORegOpValue";
Evan Cheng's avatar
Evan Cheng committed
  let PrintMethod = "printT2SOOperand";
  let MIOperandInfo = (ops rGPR, 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
Jim Grosbach's avatar
Jim Grosbach committed
// 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 Pred_t2_so_imm(N); }]> {
  string EncoderMethod = "getT2SOImmOpValue";
}
Jim Grosbach's avatar
Jim Grosbach committed
// 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(-((uint32_t)N->getZExtValue())) != -1;
// 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);
}]>;

def t2_so_neg_imm2part : Operand<i32>, PatLeaf<(imm), [{
      return ARM_AM::isT2SOImmTwoPartVal(-(int)N->getZExtValue());
    }]> {
}

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

def t2_so_neg_imm2part_2 : SDNodeXForm<imm, [{
  unsigned V = ARM_AM::getT2SOImmTwoPartSecond(-(int)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;
}]>;
Jim Grosbach's avatar
Jim Grosbach committed
def imm0_4095_neg : PatLeaf<(i32 imm), [{
 return (uint32_t)(-N->getZExtValue()) < 4096;
}], imm_neg_XFORM>;
def imm0_255_neg : PatLeaf<(i32 imm), [{
  return (uint32_t)(-N->getZExtValue()) < 255;
Jim Grosbach's avatar
Jim Grosbach committed
}], imm_neg_XFORM>;
def imm0_255_not : PatLeaf<(i32 imm), [{
  return (uint32_t)(~N->getZExtValue()) < 255;
}], imm_comp_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 = "printAddrModeImm12Operand";
Evan Cheng's avatar
Evan Cheng committed
  let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
}

// t2addrmode_imm8  := reg +/- imm8
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",
                                      [], [SDNPWantRoot]> {
  let PrintMethod = "printT2AddrModeImm8OffsetOperand";
}

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

def t2am_imm8s4_offset : Operand<i32> {
  let PrintMethod = "printT2AddrModeImm8s4OffsetOperand";
}

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, rGPR:$offsreg, i32imm:$offsimm);
//===----------------------------------------------------------------------===//
Evan Cheng's avatar
Evan Cheng committed
// Multiclass helpers...
class T2TwoRegShiftedImm<dag oops, dag iops, InstrItinClass itin,
           string opc, string asm, list<dag> pattern>
  : T2sI<oops, iops, itin, opc, asm, pattern> {
  bits<4> Rd;
  bits<4> Rn;
  bits<12> imm;
  
  let Inst{11-8}  = Rd{3-0};
  let Inst{19-16} = Rn{3-0};
  let Inst{26}    = imm{11};
  let Inst{14-12} = imm{10-8};
  let Inst{7-0}   = imm{7-0};
}

class T2ThreeReg<dag oops, dag iops, InstrItinClass itin,
           string opc, string asm, list<dag> pattern>
  : T2sI<oops, iops, itin, opc, asm, pattern> { 
  bits<4> Rd;
  bits<4> Rn;
  bits<4> Rm;
     
  let Inst{11-8}  = Rd{3-0};
  let Inst{19-16} = Rn{3-0};
  let Inst{3-0}   = Rm{3-0};
}

class T2TwoRegShiftedReg<dag oops, dag iops, InstrItinClass itin,
           string opc, string asm, list<dag> pattern>
  : T2sI<oops, iops, itin, opc, asm, pattern> {
  bits<4> Rd;
  bits<4> Rn;
  bits<12> ShiftedRm;
  
  let Inst{11-8}  = Rd{3-0};
  let Inst{19-16} = Rn{3-0};
  let Inst{3-0}   = ShiftedRm{3-0};
  let Inst{5-4}   = ShiftedRm{6-5};
  let Inst{14-12} = ShiftedRm{11-9};
  let Inst{7-6}   = ShiftedRm{8-7};
}

/// 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<bits<4> opcod, string opc,
                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
                      PatFrag opnode, bit Cheap = 0, bit ReMat = 0> {
   def i : T2sI<(outs rGPR:$dst), (ins t2_so_imm:$src), iii,
                [(set rGPR:$dst, (opnode t2_so_imm:$src))]> {
     let isAsCheapAsAMove = Cheap;
     let isReMaterializable = ReMat;
     let Inst{31-27} = 0b11110;
     let Inst{25} = 0;
     let Inst{24-21} = opcod;
     let Inst{20} = ?; // The S bit.
     let Inst{19-16} = 0b1111; // Rn
     let Inst{15} = 0;
   def r : T2sI<(outs rGPR:$dst), (ins rGPR:$src), iir,
                [(set rGPR:$dst, (opnode rGPR:$src))]> {
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{24-21} = opcod;
     let Inst{20} = ?; // The S bit.
     let Inst{19-16} = 0b1111; // Rn
     let Inst{14-12} = 0b000; // imm3
     let Inst{7-6} = 0b00; // imm2
     let Inst{5-4} = 0b00; // type
   }
   def s : T2sI<(outs rGPR:$dst), (ins t2_so_reg:$src), iis,
                [(set rGPR:$dst, (opnode t2_so_reg:$src))]> {
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{24-21} = opcod;
     let Inst{20} = ?; // The S bit.
     let Inst{19-16} = 0b1111; // Rn
   }
}

/// 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
multiclass T2I_bin_irs<bits<4> opcod, string opc,
                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
                       PatFrag opnode, bit Commutable = 0, string wide = ""> {
   def ri : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, t2_so_imm:$rhs), iii,
                 opc, "\t$dst, $lhs, $rhs",
                 [(set rGPR:$dst, (opnode rGPR:$lhs, t2_so_imm:$rhs))]> {
     let Inst{31-27} = 0b11110;
     let Inst{25} = 0;
     let Inst{24-21} = opcod;
   def rr : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, rGPR:$rhs), iir,
                 opc, !strconcat(wide, "\t$dst, $lhs, $rhs"),
                 [(set rGPR:$dst, (opnode rGPR:$lhs, rGPR:$rhs))]> {
     let isCommutable = Commutable;
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{24-21} = opcod;
     let Inst{14-12} = 0b000; // imm3
     let Inst{7-6} = 0b00; // imm2
     let Inst{5-4} = 0b00; // type
   def rs : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, t2_so_reg:$rhs), iis,
                 opc, !strconcat(wide, "\t$dst, $lhs, $rhs"),
                 [(set rGPR:$dst, (opnode rGPR:$lhs, t2_so_reg:$rhs))]> {
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{24-21} = opcod;
/// 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<bits<4> opcod, string opc,
                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
                         PatFrag opnode, bit Commutable = 0> :
    T2I_bin_irs<opcod, opc, iii, iir, iis, opnode, Commutable, ".w">;
/// T2I_rbin_is - Same as T2I_bin_irs except the order of operands are
/// reversed.  The 'rr' form is only defined for the disassembler; for codegen
/// it is equivalent to the T2I_bin_irs counterpart.
multiclass T2I_rbin_irs<bits<4> opcod, string opc, PatFrag opnode> {
   def ri : T2sI<(outs rGPR:$dst), (ins rGPR:$rhs, t2_so_imm:$lhs), IIC_iALUi,
                 opc, ".w\t$dst, $rhs, $lhs",
                 [(set rGPR:$dst, (opnode t2_so_imm:$lhs, rGPR:$rhs))]> {
     let Inst{31-27} = 0b11110;
     let Inst{25} = 0;
     let Inst{24-21} = opcod;
   def rr : T2sI<(outs rGPR:$dst), (ins rGPR:$rhs, rGPR:$lhs), IIC_iALUr,
                 opc, "\t$dst, $rhs, $lhs",
                 [/* For disassembly only; pattern left blank */]> {
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{24-21} = opcod;
     let Inst{20} = ?; // The S bit.
     let Inst{14-12} = 0b000; // imm3
     let Inst{7-6} = 0b00; // imm2
     let Inst{5-4} = 0b00; // type
   }
   def rs : T2sI<(outs rGPR:$dst), (ins rGPR:$rhs, t2_so_reg:$lhs), IIC_iALUsir,
                 opc, "\t$dst, $rhs, $lhs",
                 [(set rGPR:$dst, (opnode t2_so_reg:$lhs, rGPR:$rhs))]> {
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{24-21} = opcod;
/// T2I_bin_s_irs - Similar to T2I_bin_irs except it sets the 's' bit so the
/// instruction modifies the CPSR register.
let Defs = [CPSR] in {
multiclass T2I_bin_s_irs<bits<4> opcod, string opc,
                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
                         PatFrag opnode, bit Commutable = 0> {
   def ri : T2I<(outs rGPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), iii,
                !strconcat(opc, "s"), ".w\t$dst, $lhs, $rhs",
                [(set rGPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]> {
     let Inst{31-27} = 0b11110;
     let Inst{25} = 0;
     let Inst{24-21} = opcod;
     let Inst{20} = 1; // The S bit.
     let Inst{15} = 0;
   }
   def rr : T2I<(outs rGPR:$dst), (ins GPR:$lhs, rGPR:$rhs), iir,
                !strconcat(opc, "s"), ".w\t$dst, $lhs, $rhs",
                [(set rGPR:$dst, (opnode GPR:$lhs, rGPR:$rhs))]> {
     let isCommutable = Commutable;
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{24-21} = opcod;
     let Inst{20} = 1; // The S bit.
     let Inst{14-12} = 0b000; // imm3
     let Inst{7-6} = 0b00; // imm2
     let Inst{5-4} = 0b00; // type
   def rs : T2I<(outs rGPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), iis,
                !strconcat(opc, "s"), ".w\t$dst, $lhs, $rhs",
                [(set rGPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]> {
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{24-21} = opcod;
     let Inst{20} = 1; // The S bit.
   }
/// T2I_bin_ii12rs - Defines a set of (op reg, {so_imm|imm0_4095|r|so_reg})
/// patterns for a binary operation that produces a value.
multiclass T2I_bin_ii12rs<bits<3> op23_21, string opc, 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 : T2sI<(outs rGPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
                 opc, ".w\t$dst, $lhs, $rhs",
                 [(set rGPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]> {
     let Inst{31-27} = 0b11110;
     let Inst{25} = 0;
     let Inst{24} = 1;
     let Inst{23-21} = op23_21;
     let Inst{20} = 0; // The S bit.
     let Inst{15} = 0;
   }
   def ri12 : T2I<(outs rGPR:$dst), (ins GPR:$lhs, imm0_4095:$rhs), IIC_iALUi,
                  !strconcat(opc, "w"), "\t$dst, $lhs, $rhs",
                  [(set rGPR:$dst, (opnode GPR:$lhs, imm0_4095:$rhs))]> {
     let Inst{31-27} = 0b11110;
     let Inst{25} = 1;
     let Inst{24} = 0;
     let Inst{23-21} = op23_21;
     let Inst{20} = 0; // The S bit.
     let Inst{15} = 0;
   }
   def rr : T2sI<(outs rGPR:$dst), (ins GPR:$lhs, rGPR:$rhs), IIC_iALUr,
                 opc, ".w\t$dst, $lhs, $rhs",
                 [(set rGPR:$dst, (opnode GPR:$lhs, rGPR:$rhs))]> {
     let isCommutable = Commutable;
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{24} = 1;
     let Inst{23-21} = op23_21;
     let Inst{20} = 0; // The S bit.
     let Inst{14-12} = 0b000; // imm3
     let Inst{7-6} = 0b00; // imm2
     let Inst{5-4} = 0b00; // type
   def rs : T2sI<(outs rGPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
                 opc, ".w\t$dst, $lhs, $rhs",
                 [(set rGPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]> {
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{23-21} = op23_21;
     let Inst{20} = 0; // The S bit.
   }
Jim Grosbach's avatar
Jim Grosbach committed
/// T2I_adde_sube_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns
/// for a binary operation that produces a value and use the carry
Jim Grosbach's avatar
Jim Grosbach committed
/// bit. It's not predicable.
Jim Grosbach's avatar
Jim Grosbach committed
multiclass T2I_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
                             bit Commutable = 0> {
   def ri : T2TwoRegShiftedImm<(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm),
                 IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
                 [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>,
     let Inst{31-27} = 0b11110;
     let Inst{25} = 0;
     let Inst{24-21} = opcod;
     let Inst{20} = 0; // The S bit.
     let Inst{15} = 0;
   }
   def rr : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUr,
                 opc, ".w\t$Rd, $Rn, $Rm",
                 [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]>,
     let isCommutable = Commutable;
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{24-21} = opcod;
     let Inst{20} = 0; // The S bit.
     let Inst{14-12} = 0b000; // imm3
     let Inst{7-6} = 0b00; // imm2
     let Inst{5-4} = 0b00; // type
   def rs : T2TwoRegShiftedReg<
                 (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm), 
                 IIC_iALUsi, opc, ".w\t$Rd, $Rn, $ShiftedRm",
                 [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>,
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{24-21} = opcod;
     let Inst{20} = 0; // The S bit.
   }
}

// Carry setting variants
let Defs = [CPSR] in {
Jim Grosbach's avatar
Jim Grosbach committed
multiclass T2I_adde_sube_s_irs<bits<4> opcod, string opc, PatFrag opnode,
                               bit Commutable = 0> {
   def ri : T2TwoRegShiftedImm<
                 (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm), IIC_iALUi,
                 opc, "\t$Rd, $Rn, $imm",
                 [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>,
     let Inst{31-27} = 0b11110;
     let Inst{25} = 0;
     let Inst{24-21} = opcod;
     let Inst{20} = 1; // The S bit.
     let Inst{15} = 0;
   }
   def rr : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUr,
                 opc, ".w\t$Rd, $Rn, $Rm",
                 [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]>,
     let isCommutable = Commutable;
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{24-21} = opcod;
     let Inst{20} = 1; // The S bit.
     let Inst{14-12} = 0b000; // imm3
     let Inst{7-6} = 0b00; // imm2
     let Inst{5-4} = 0b00; // type
   def rs : T2TwoRegShiftedReg<
                 (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm),
                 IIC_iALUsi, opc, ".w\t$Rd, $Rn, $ShiftedRm",
                 [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>,
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{24-21} = opcod;
     let Inst{20} = 1; // The S bit.
/// T2I_rbin_s_is - Same as T2I_rbin_irs except sets 's' bit and the register
/// version is not needed since this is only for codegen.
multiclass T2I_rbin_s_is<bits<4> opcod, string opc, PatFrag opnode> {
   def ri : T2I<(outs rGPR:$dst), (ins rGPR:$rhs, t2_so_imm:$lhs), IIC_iALUi,
                !strconcat(opc, "s"), ".w\t$dst, $rhs, $lhs",
                [(set rGPR:$dst, (opnode t2_so_imm:$lhs, rGPR:$rhs))]> {
     let Inst{31-27} = 0b11110;
     let Inst{25} = 0;
     let Inst{24-21} = opcod;
     let Inst{20} = 1; // The S bit.
     let Inst{15} = 0;
   }
   def rs : T2I<(outs rGPR:$dst), (ins rGPR:$rhs, t2_so_reg:$lhs), IIC_iALUsi,
                !strconcat(opc, "s"), "\t$dst, $rhs, $lhs",
                [(set rGPR:$dst, (opnode t2_so_reg:$lhs, rGPR:$rhs))]> {
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{24-21} = opcod;
     let Inst{20} = 1; // The S bit.
   }
/// T2I_sh_ir - Defines a set of (op reg, {so_imm|r}) patterns for a shift /
//  rotate operation that produces a value.
multiclass T2I_sh_ir<bits<2> opcod, string opc, PatFrag opnode> {
   def ri : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, i32imm:$rhs), IIC_iMOVsi,
                 [(set rGPR:$dst, (opnode rGPR:$lhs, imm1_31:$rhs))]> {
     let Inst{31-27} = 0b11101;
     let Inst{26-21} = 0b010010;
     let Inst{19-16} = 0b1111; // Rn
     let Inst{5-4} = opcod;
   }
   def rr : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, rGPR:$rhs), IIC_iMOVsr,
                 [(set rGPR:$dst, (opnode rGPR:$lhs, rGPR:$rhs))]> {
     let Inst{31-27} = 0b11111;
     let Inst{26-23} = 0b0100;
     let Inst{22-21} = opcod;
     let Inst{15-12} = 0b1111;
     let Inst{7-4} = 0b0000;
   }
/// T2I_cmp_irs - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test
/// patterns. Similar to T2I_bin_irs except the instruction does not produce
/// a explicit result, only implicitly set CPSR.
let isCompare = 1, Defs = [CPSR] in {
multiclass T2I_cmp_irs<bits<4> opcod, string opc,
                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
                       PatFrag opnode> {
   def ri : T2I<(outs), (ins GPR:$lhs, t2_so_imm:$rhs), iii,
                [(opnode GPR:$lhs, t2_so_imm:$rhs)]> {
     let Inst{31-27} = 0b11110;
     let Inst{25} = 0;
     let Inst{24-21} = opcod;
     let Inst{20} = 1; // The S bit.
     let Inst{15} = 0;
     let Inst{11-8} = 0b1111; // Rd
   }
   def rr : T2I<(outs), (ins GPR:$lhs, rGPR:$rhs), iir,
                [(opnode GPR:$lhs, rGPR:$rhs)]> {
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{24-21} = opcod;
     let Inst{20} = 1; // The S bit.
     let Inst{14-12} = 0b000; // imm3
     let Inst{11-8} = 0b1111; // Rd
     let Inst{7-6} = 0b00; // imm2
     let Inst{5-4} = 0b00; // type
   }
   def rs : T2I<(outs), (ins GPR:$lhs, t2_so_reg:$rhs), iis,
                [(opnode GPR:$lhs, t2_so_reg:$rhs)]> {
     let Inst{31-27} = 0b11101;
     let Inst{26-25} = 0b01;
     let Inst{24-21} = opcod;
     let Inst{20} = 1; // The S bit.
     let Inst{11-8} = 0b1111; // Rd
   }
/// T2I_ld - Defines a set of (op r, {imm12|imm8|so_reg}) load patterns.
multiclass T2I_ld<bit signed, bits<2> opcod, string opc,
                  InstrItinClass iii, InstrItinClass iis, PatFrag opnode> {
  def i12 : T2Ii12<(outs GPR:$dst), (ins t2addrmode_imm12:$addr), iii,
                   [(set GPR:$dst, (opnode t2addrmode_imm12:$addr))]> {
    let Inst{31-27} = 0b11111;
    let Inst{26-25} = 0b00;
    let Inst{24} = signed;
    let Inst{23} = 1;
    let Inst{22-21} = opcod;
    let Inst{20} = 1; // load
  }
  def i8  : T2Ii8 <(outs GPR:$dst), (ins t2addrmode_imm8:$addr), iii,
                   [(set GPR:$dst, (opnode t2addrmode_imm8:$addr))]> {
    let Inst{31-27} = 0b11111;
    let Inst{26-25} = 0b00;
    let Inst{24} = signed;
    let Inst{23} = 0;
    let Inst{22-21} = opcod;
    let Inst{20} = 1; // load
    let Inst{11} = 1;
    // Offset: index==TRUE, wback==FALSE
    let Inst{10} = 1; // The P bit.
    let Inst{8} = 0; // The W bit.
  }
  def s   : T2Iso <(outs GPR:$dst), (ins t2addrmode_so_reg:$addr), iis,
                   [(set GPR:$dst, (opnode t2addrmode_so_reg:$addr))]> {
    let Inst{31-27} = 0b11111;
    let Inst{26-25} = 0b00;
    let Inst{24} = signed;
    let Inst{23} = 0;
    let Inst{22-21} = opcod;
    let Inst{20} = 1; // load
    let Inst{11-6} = 0b000000;
  }

  // FIXME: Is the pci variant actually needed?
  def pci : T2Ipc <(outs GPR:$dst), (ins i32imm:$addr), iii,
                   [(set GPR:$dst, (opnode (ARMWrapper tconstpool:$addr)))]> {
    let isReMaterializable = 1;
    let Inst{31-27} = 0b11111;
    let Inst{26-25} = 0b00;
    let Inst{24} = signed;
    let Inst{23} = ?; // add = (U == '1')
    let Inst{22-21} = opcod;
    let Inst{20} = 1; // load
    let Inst{19-16} = 0b1111; // Rn
/// T2I_st - Defines a set of (op r, {imm12|imm8|so_reg}) store patterns.
multiclass T2I_st<bits<2> opcod, string opc,
                  InstrItinClass iii, InstrItinClass iis, PatFrag opnode> {
  def i12 : T2Ii12<(outs), (ins GPR:$src, t2addrmode_imm12:$addr), iii,
                   [(opnode GPR:$src, t2addrmode_imm12:$addr)]> {
    let Inst{31-27} = 0b11111;
    let Inst{26-23} = 0b0001;
    let Inst{22-21} = opcod;
    let Inst{20} = 0; // !load
  }
  def i8  : T2Ii8 <(outs), (ins GPR:$src, t2addrmode_imm8:$addr), iii,
                   [(opnode GPR:$src, t2addrmode_imm8:$addr)]> {
    let Inst{31-27} = 0b11111;
    let Inst{26-23} = 0b0000;
    let Inst{22-21} = opcod;
    let Inst{20} = 0; // !load
    let Inst{11} = 1;
    // Offset: index==TRUE, wback==FALSE
    let Inst{10} = 1; // The P bit.
    let Inst{8} = 0; // The W bit.
  }
  def s   : T2Iso <(outs), (ins GPR:$src, t2addrmode_so_reg:$addr), iis,
                   [(opnode GPR:$src, t2addrmode_so_reg:$addr)]> {
    let Inst{31-27} = 0b11111;
    let Inst{26-23} = 0b0000;
    let Inst{22-21} = opcod;
    let Inst{20} = 0; // !load
    let Inst{11-6} = 0b000000;
  }
/// T2I_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.
multiclass T2I_ext_rrot<bits<3> opcod, string opc, PatFrag opnode> {
  def r     : T2I<(outs rGPR:$dst), (ins rGPR:$src), IIC_iEXTr,
                 [(set rGPR:$dst, (opnode rGPR:$src))]> {
     let Inst{31-27} = 0b11111;
     let Inst{26-23} = 0b0100;
     let Inst{22-20} = opcod;
     let Inst{19-16} = 0b1111; // Rn
     let Inst{15-12} = 0b1111;
     let Inst{7} = 1;
     let Inst{5-4} = 0b00; // rotate
   }
  def r_rot : T2I<(outs rGPR:$dst), (ins rGPR:$src, i32imm:$rot), IIC_iEXTr,
                 [(set rGPR:$dst, (opnode (rotr rGPR:$src, rot_imm:$rot)))]> {
     let Inst{31-27} = 0b11111;
     let Inst{26-23} = 0b0100;
     let Inst{22-20} = opcod;
     let Inst{19-16} = 0b1111; // Rn
     let Inst{15-12} = 0b1111;
     let Inst{7} = 1;
     let Inst{5-4} = {?,?}; // rotate
   }
// UXTB16 - Requres T2ExtractPack, does not need the .w qualifier.
multiclass T2I_ext_rrot_uxtb16<bits<3> opcod, string opc, PatFrag opnode> {
  def r     : T2I<(outs rGPR:$dst), (ins rGPR:$src), IIC_iEXTr,
                 [(set rGPR:$dst, (opnode rGPR:$src))]>,
                 Requires<[HasT2ExtractPack, IsThumb2]> {
     let Inst{31-27} = 0b11111;
     let Inst{26-23} = 0b0100;
     let Inst{22-20} = opcod;
     let Inst{19-16} = 0b1111; // Rn
     let Inst{15-12} = 0b1111;
     let Inst{7} = 1;
     let Inst{5-4} = 0b00; // rotate
   }
  def r_rot : T2I<(outs rGPR:$dst), (ins rGPR:$src, i32imm:$rot), IIC_iEXTr,
                 [(set rGPR:$dst, (opnode (rotr rGPR:$src, rot_imm:$rot)))]>,
                 Requires<[HasT2ExtractPack, IsThumb2]> {
     let Inst{31-27} = 0b11111;
     let Inst{26-23} = 0b0100;
     let Inst{22-20} = opcod;
     let Inst{19-16} = 0b1111; // Rn
     let Inst{15-12} = 0b1111;
     let Inst{7} = 1;
     let Inst{5-4} = {?,?}; // rotate
   }
}

// SXTB16 - Requres T2ExtractPack, does not need the .w qualifier, no pattern
// supported yet.
multiclass T2I_ext_rrot_sxtb16<bits<3> opcod, string opc> {
  def r     : T2I<(outs rGPR:$dst), (ins rGPR:$src), IIC_iEXTr,
                  opc, "\t$dst, $src", []> {
     let Inst{31-27} = 0b11111;
     let Inst{26-23} = 0b0100;
     let Inst{22-20} = opcod;
     let Inst{19-16} = 0b1111; // Rn
     let Inst{15-12} = 0b1111;
     let Inst{7} = 1;
     let Inst{5-4} = 0b00; // rotate
   }
  def r_rot : T2I<(outs rGPR:$dst), (ins rGPR:$src, i32imm:$rot), IIC_iEXTr,
                  opc, "\t$dst, $src, ror $rot", []> {
     let Inst{31-27} = 0b11111;
     let Inst{26-23} = 0b0100;
     let Inst{22-20} = opcod;
     let Inst{19-16} = 0b1111; // Rn
     let Inst{15-12} = 0b1111;
     let Inst{7} = 1;
     let Inst{5-4} = {?,?}; // rotate
   }
}

/// T2I_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 T2I_exta_rrot<bits<3> opcod, string opc, PatFrag opnode> {
  def rr     : T2I<(outs rGPR:$dst), (ins rGPR:$LHS, rGPR:$RHS), IIC_iEXTAr,
                  [(set rGPR:$dst, (opnode rGPR:$LHS, rGPR:$RHS))]>,
                  Requires<[HasT2ExtractPack, IsThumb2]> {
     let Inst{31-27} = 0b11111;
     let Inst{26-23} = 0b0100;
     let Inst{22-20} = opcod;
     let Inst{15-12} = 0b1111;
     let Inst{7} = 1;
     let Inst{5-4} = 0b00; // rotate
   }
  def rr_rot : T2I<(outs rGPR:$dst), (ins rGPR:$LHS, rGPR:$RHS, i32imm:$rot),
                  IIC_iEXTAsr, opc, "\t$dst, $LHS, $RHS, ror $rot",
                  [(set rGPR:$dst, (opnode rGPR:$LHS,
                                          (rotr rGPR:$RHS, rot_imm:$rot)))]>,
                  Requires<[HasT2ExtractPack, IsThumb2]> {
     let Inst{31-27} = 0b11111;
     let Inst{26-23} = 0b0100;
     let Inst{22-20} = opcod;
     let Inst{15-12} = 0b1111;
     let Inst{7} = 1;
     let Inst{5-4} = {?,?}; // rotate
   }
// DO variant - disassembly only, no pattern

multiclass T2I_exta_rrot_DO<bits<3> opcod, string opc> {
  def rr     : T2I<(outs rGPR:$dst), (ins rGPR:$LHS, rGPR:$RHS), IIC_iEXTAr,
                  opc, "\t$dst, $LHS, $RHS", []> {
     let Inst{31-27} = 0b11111;
     let Inst{26-23} = 0b0100;
     let Inst{22-20} = opcod;
     let Inst{15-12} = 0b1111;
     let Inst{7} = 1;
     let Inst{5-4} = 0b00; // rotate
   }
  def rr_rot : T2I<(outs rGPR:$dst), (ins rGPR:$LHS, rGPR:$RHS, i32imm:$rot),
                  IIC_iEXTAsr, opc, "\t$dst, $LHS, $RHS, ror $rot", []> {
     let Inst{31-27} = 0b11111;
     let Inst{26-23} = 0b0100;
     let Inst{22-20} = opcod;
     let Inst{15-12} = 0b1111;
     let Inst{7} = 1;
     let Inst{5-4} = {?,?}; // rotate
   }
}

Evan Cheng's avatar
Evan Cheng committed
//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//

Evan Cheng's avatar
Evan Cheng committed
//===----------------------------------------------------------------------===//
//  Miscellaneous Instructions.
//

// LEApcrel - Load a pc-relative address into a register without offending the
// assembler.
def t2LEApcrel : T2XI<(outs rGPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALUi,
                      "adr${p}.w\t$dst, #$label", []> {
  let Inst{31-27} = 0b11110;
  let Inst{25-24} = 0b10;
  // Inst{23:21} = '11' (add = FALSE) or '00' (add = TRUE)
  let Inst{22} = 0;
  let Inst{20} = 0;
  let Inst{19-16} = 0b1111; // Rn
  let Inst{15} = 0;
}
def t2LEApcrelJT : T2XI<(outs rGPR:$dst),
                        (ins i32imm:$label, nohash_imm:$id, pred:$p), IIC_iALUi,
                        "adr${p}.w\t$dst, #${label}_${id}", []> {
  let Inst{31-27} = 0b11110;
  let Inst{25-24} = 0b10;
  // Inst{23:21} = '11' (add = FALSE) or '00' (add = TRUE)
  let Inst{22} = 0;
  let Inst{20} = 0;
  let Inst{19-16} = 0b1111; // Rn
  let Inst{15} = 0;
}
def t2ADDrSPi   : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm),
                        IIC_iALUi, "add", ".w\t$dst, $sp, $imm", []> {
  let Inst{31-27} = 0b11110;
  let Inst{25} = 0;
  let Inst{24-21} = 0b1000;
  let Inst{20} = ?; // The S bit.
  let Inst{19-16} = 0b1101; // Rn = sp
def t2ADDrSPi12 : T2I<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm),
                       IIC_iALUi, "addw", "\t$dst, $sp, $imm", []> {
  let Inst{31-27} = 0b11110;
  let Inst{25} = 1;
  let Inst{24-21} = 0b0000;
  let Inst{20} = 0; // The S bit.
  let Inst{19-16} = 0b1101; // Rn = sp
  let Inst{15} = 0;
}
def t2ADDrSPs   : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs),
                        IIC_iALUsi, "add", ".w\t$dst, $sp, $rhs", []> {
  let Inst{31-27} = 0b11101;
  let Inst{26-25} = 0b01;
  let Inst{24-21} = 0b1000;
  let Inst{20} = ?; // The S bit.
  let Inst{19-16} = 0b1101; // Rn = sp
  let Inst{15} = 0;
}
def t2SUBrSPi   : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm),
                        IIC_iALUi, "sub", ".w\t$dst, $sp, $imm", []> {
  let Inst{31-27} = 0b11110;
  let Inst{25} = 0;
  let Inst{24-21} = 0b1101;
  let Inst{20} = ?; // The S bit.
  let Inst{19-16} = 0b1101; // Rn = sp
  let Inst{15} = 0;
}
def t2SUBrSPi12 : T2I<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm),
                       IIC_iALUi, "subw", "\t$dst, $sp, $imm", []> {
  let Inst{31-27} = 0b11110;
  let Inst{25} = 1;
  let Inst{24-21} = 0b0101;
  let Inst{20} = 0; // The S bit.
  let Inst{19-16} = 0b1101; // Rn = sp
  let Inst{15} = 0;
}
def t2SUBrSPs   : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs),
                       IIC_iALUsi,
                       "sub", "\t$dst, $sp, $rhs", []> {
  let Inst{31-27} = 0b11101;
  let Inst{26-25} = 0b01;
  let Inst{24-21} = 0b1101;
  let Inst{20} = ?; // The S bit.
  let Inst{19-16} = 0b1101; // Rn = sp
  let Inst{15} = 0;
}
// Signed and unsigned division on v7-M
def t2SDIV : T2I<(outs rGPR:$dst), (ins rGPR:$a, rGPR:$b), IIC_iALUi, 
                 [(set rGPR:$dst, (sdiv rGPR:$a, rGPR:$b))]>,
  let Inst{31-27} = 0b11111;
  let Inst{26-21} = 0b011100;
  let Inst{20} = 0b1;
  let Inst{15-12} = 0b1111;
  let Inst{7-4} = 0b1111;
}

def t2UDIV : T2I<(outs rGPR:$dst), (ins rGPR:$a, rGPR:$b), IIC_iALUi, 
                 [(set rGPR:$dst, (udiv rGPR:$a, rGPR:$b))]>,
  let Inst{31-27} = 0b11111;
  let Inst{26-21} = 0b011101;
  let Inst{20} = 0b1;
  let Inst{15-12} = 0b1111;
  let Inst{7-4} = 0b1111;
}

Evan Cheng's avatar
Evan Cheng committed
//===----------------------------------------------------------------------===//
//  Load / store Instructions.
//

Evan Cheng's avatar
Evan Cheng committed
// Load
let canFoldAsLoad = 1, isReMaterializable = 1  in
defm t2LDR   : T2I_ld<0, 0b10, "ldr", IIC_iLoad_i, IIC_iLoad_si,
                      UnOpFrag<(load node:$Src)>>;

// Loads with zero extension
defm t2LDRH  : T2I_ld<0, 0b01, "ldrh", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
                      UnOpFrag<(zextloadi16 node:$Src)>>;
defm t2LDRB  : T2I_ld<0, 0b00, "ldrb", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
                      UnOpFrag<(zextloadi8  node:$Src)>>;

// Loads with sign extension
defm t2LDRSH : T2I_ld<1, 0b01, "ldrsh", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
                      UnOpFrag<(sextloadi16 node:$Src)>>;
defm t2LDRSB : T2I_ld<1, 0b00, "ldrsb", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
                      UnOpFrag<(sextloadi8  node:$Src)>>;
let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1,
    isCodeGenOnly = 1 in { // $dst doesn't exist in asmstring?
// Load doubleword
def t2LDRDi8  : T2Ii8s4<1, 0, 1, (outs rGPR:$dst1, rGPR:$dst2),
                        (ins t2addrmode_imm8s4:$addr),
                        IIC_iLoad_d_i, "ldrd", "\t$dst1, $addr", []>;
def t2LDRDpci : T2Ii8s4<1, 0, 1, (outs rGPR:$dst1, rGPR:$dst2),
                        (ins i32imm:$addr), IIC_iLoad_d_i,
                       "ldrd", "\t$dst1, $addr", []> {
  let Inst{19-16} = 0b1111; // Rn
}
} // mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1

// zextload i1 -> zextload i8
def : T2Pat<(zextloadi1 t2addrmode_imm12:$addr),
            (t2LDRBi12  t2addrmode_imm12:$addr)>;
def : T2Pat<(zextloadi1 t2addrmode_imm8:$addr),
            (t2LDRBi8   t2addrmode_imm8:$addr)>;