Skip to content
ARMInstrThumb2.td 49.3 KiB
Newer Older
Evan Cheng's avatar
Evan Cheng committed
            (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
def : T2Pat<(ARMcmpZ  GPR:$src, t2_so_imm_neg:$imm),
Evan Cheng's avatar
Evan Cheng committed
            (t2CMNri   GPR:$src, t2_so_imm_neg:$imm)>;
defm t2TST  : T2I_cmp_is<"tst",
                         BinOpFrag<(ARMcmpZ (and node:$LHS, node:$RHS), 0)>>;
defm t2TEQ  : T2I_cmp_is<"teq",
                         BinOpFrag<(ARMcmpZ (xor node:$LHS, node:$RHS), 0)>>;

// A8.6.27  CBNZ, CBZ - Compare and branch on (non)zero.
// Short range conditional branch. Looks awesome for loops. Need to figure
// out how to use this one.


// Conditional moves
// FIXME: should be able to write a pattern for ARMcmov, but can't use
// a two-value operand where a dag node expects two operands. :( 
def t2MOVCCr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true), IIC_iCMOVr,
Evan Cheng's avatar
Evan Cheng committed
                   "mov", ".w $dst, $true",
      [/*(set GPR:$dst, (ARMcmov GPR:$false, GPR:$true, imm:$cc, CCR:$ccr))*/]>,
                RegConstraint<"$false = $dst">;

def t2MOVCCi : T2I<(outs GPR:$dst), (ins GPR:$false, t2_so_imm:$true),
                   IIC_iCMOVi, "mov", ".w $dst, $true",
[/*(set GPR:$dst, (ARMcmov GPR:$false, t2_so_imm:$true, imm:$cc, CCR:$ccr))*/]>,
                   RegConstraint<"$false = $dst">;
def t2MOVCClsl : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
                   IIC_iCMOVsi, "lsl", ".w $dst, $true, $rhs", []>,
                   RegConstraint<"$false = $dst">;
def t2MOVCClsr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
                   IIC_iCMOVsi, "lsr", ".w $dst, $true, $rhs", []>,
                   RegConstraint<"$false = $dst">;
def t2MOVCCasr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
                   IIC_iCMOVsi, "asr", ".w $dst, $true, $rhs", []>,
                   RegConstraint<"$false = $dst">;
def t2MOVCCror : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
                   IIC_iCMOVsi, "ror", ".w $dst, $true, $rhs", []>,
//===----------------------------------------------------------------------===//
// TLS Instructions
//

// __aeabi_read_tp preserves the registers r1-r3.
let isCall = 1,
  Defs = [R0, R12, LR, CPSR] in {
  def t2TPsoft : T2XI<(outs), (ins), IIC_Br,
                     "bl __aeabi_read_tp",
                     [(set R0, ARMthread_pointer)]>;
}

//===----------------------------------------------------------------------===//
// SJLJ Exception handling intrinsics
Jim Grosbach's avatar
Jim Grosbach committed
//   eh_sjlj_setjmp() is an instruction sequence to store the return
//   address and save #0 in R0 for the non-longjmp case.
//   Since by its nature we may be coming from some other function to get
//   here, and we're using the stack frame for the containing function to
//   save/restore registers, we can't keep anything live in regs across
//   the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon
//   when we get here from a longjmp(). We force everthing out of registers
//   except for our own input by listing the relevant registers in Defs. By
//   doing so, we also cause the prologue/epilogue code to actively preserve
//   all of the callee-saved resgisters, which is exactly what we want.
let Defs = 
  [ R0,  R1,  R2,  R3,  R4,  R5,  R6,  R7,  R8,  R9,  R10, R11, R12, LR,  D0,
    D1,  D2,  D3,  D4,  D5,  D6,  D7,  D8,  D9,  D10, D11, D12, D13, D14, D15,
    D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30,
    D31 ] in {
  def t2Int_eh_sjlj_setjmp : Thumb2XI<(outs), (ins GPR:$src),
                               AddrModeNone, SizeSpecial, NoItinerary,
                               "str.w sp, [$src, #+8] @ eh_setjmp begin\n"
                               "\tadr r12, 0f\n"
                               "\torr r12, #1\n"
                               "\tstr.w r12, [$src, #+4]\n"
                               "\tmovs r0, #0\n"
                               "\tb 1f\n"
                               "0:\tmovs r0, #1 @ eh_setjmp end\n"
Jim Grosbach's avatar
Jim Grosbach committed
                               "1:", "",
                               [(set R0, (ARMeh_sjlj_setjmp GPR:$src))]>;
}



//===----------------------------------------------------------------------===//
// Control-Flow Instructions
//

// FIXME: remove when we have a way to marking a MI with these properties.
// FIXME: $dst1 should be a def. But the extra ops must be in the end of the
// operand list.
// FIXME: Should pc be an implicit operand like PICADD, etc?
let isReturn = 1, isTerminator = 1, mayLoad = 1 in
  def t2LDM_RET : T2XI<(outs),
                    (ins addrmode4:$addr, pred:$p, reglist:$dst1, variable_ops),
                    IIC_Br, "ldm${addr:submode}${p}${addr:wide} $addr, $dst1",
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
let isPredicable = 1 in
def t2B   : T2XI<(outs), (ins brtarget:$target), IIC_Br,
let isNotDuplicable = 1, isIndirectBranch = 1 in {
    T2JTI<(outs),
          (ins GPR:$target, GPR:$index, jt2block_operand:$jt, i32imm:$id),
          [(ARMbr2jt GPR:$target, GPR:$index, tjumptable:$jt, imm:$id)]>;

// FIXME: Add a non-pc based case that can be predicated.
        (ins tb_addrmode:$index, jt2block_operand:$jt, i32imm:$id),
        (ins tb_addrmode:$index, jt2block_operand:$jt, i32imm:$id),
} // isBranch, isTerminator, isBarrier

// FIXME: should be able to write a pattern for ARMBrcond, but can't use
// a two-value operand where a dag node expects two operands. :(
let isBranch = 1, isTerminator = 1 in
def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
                "b", ".w $target",
                [/*(ARMbrcond bb:$target, imm:$cc)*/]>;

// IT block
def t2IT : Thumb2XI<(outs), (ins it_pred:$cc, it_mask:$mask),
                    AddrModeNone, Size2Bytes,  IIC_iALUx,
                    "it$mask $cc", "", []>;

//===----------------------------------------------------------------------===//
// Non-Instruction Patterns
//

Evan Cheng's avatar
Evan Cheng committed
// ConstantPool, GlobalAddress, and JumpTable
Evan Cheng's avatar
Evan Cheng committed
def : T2Pat<(ARMWrapper  tglobaladdr :$dst), (t2LEApcrel tglobaladdr :$dst)>;
def : T2Pat<(ARMWrapper  tconstpool  :$dst), (t2LEApcrel tconstpool  :$dst)>;
def : T2Pat<(ARMWrapperJT tjumptable:$dst, imm:$id),
            (t2LEApcrelJT tjumptable:$dst, imm:$id)>;
Evan Cheng's avatar
Evan Cheng committed
def : T2Pat<(i32 imm:$src),
            (t2MOVTi16 (t2MOVi16 (t2_lo16 imm:$src)), (t2_hi16 imm:$src))>;