//===- ARMInstrThumb.td - Thumb 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 Thumb instruction set.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Thumb specific DAG Nodes.
//
def ARMtcall : SDNode<"ARMISD::tCALL", SDT_ARMcall,
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag,
SDNPVariadic]>;
def imm_neg_XFORM : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(-(int)N->getZExtValue(), MVT::i32);
}]>;
def imm_comp_XFORM : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32);
}]>;
/// imm0_7 predicate - True if the 32-bit immediate is in the range [0,7].
def imm0_7 : PatLeaf<(i32 imm), [{
return (uint32_t)N->getZExtValue() < 8;
}]>;
def imm0_7_neg : PatLeaf<(i32 imm), [{
return (uint32_t)-N->getZExtValue() < 8;
}], imm_neg_XFORM>;
def imm0_255 : PatLeaf<(i32 imm), [{
return (uint32_t)N->getZExtValue() < 256;
}]>;
def imm0_255_comp : PatLeaf<(i32 imm), [{
return ~((uint32_t)N->getZExtValue()) < 256;
}]>;
def imm8_255 : PatLeaf<(i32 imm), [{
return (uint32_t)N->getZExtValue() >= 8 && (uint32_t)N->getZExtValue() < 256;
}]>;
def imm8_255_neg : PatLeaf<(i32 imm), [{
unsigned Val = -N->getZExtValue();
return Val >= 8 && Val < 256;
}], imm_neg_XFORM>;
// Break imm's up into two pieces: an immediate + a left shift.
// This uses thumb_immshifted to match and thumb_immshifted_val and
// thumb_immshifted_shamt to get the val/shift pieces.
def thumb_immshifted : PatLeaf<(imm), [{
return ARM_AM::isThumbImmShiftedVal((unsigned)N->getZExtValue());
}]>;
def thumb_immshifted_val : SDNodeXForm<imm, [{
unsigned V = ARM_AM::getThumbImmNonShiftedVal((unsigned)N->getZExtValue());
return CurDAG->getTargetConstant(V, MVT::i32);
}]>;
def thumb_immshifted_shamt : SDNodeXForm<imm, [{
unsigned V = ARM_AM::getThumbImmValShift((unsigned)N->getZExtValue());
return CurDAG->getTargetConstant(V, MVT::i32);
}]>;
// Scaled 4 immediate.
def t_imm_s4 : Operand<i32> {
let PrintMethod = "printThumbS4ImmOperand";
}
// Define Thumb specific addressing modes.
// t_addrmode_rr := reg + reg
//
def t_addrmode_rr : Operand<i32>,
ComplexPattern<i32, 2, "SelectThumbAddrModeRR", []> {
let PrintMethod = "printThumbAddrModeRROperand";
let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
}
// t_addrmode_s4 := reg + reg
// reg + imm5 * 4
//
def t_addrmode_s4 : Operand<i32>,
ComplexPattern<i32, 3, "SelectThumbAddrModeS4", []> {
let PrintMethod = "printThumbAddrModeS4Operand";
let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
}
// t_addrmode_s2 := reg + reg
// reg + imm5 * 2
//
def t_addrmode_s2 : Operand<i32>,
ComplexPattern<i32, 3, "SelectThumbAddrModeS2", []> {
let PrintMethod = "printThumbAddrModeS2Operand";
let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
}
// t_addrmode_s1 := reg + reg
// reg + imm5
//
def t_addrmode_s1 : Operand<i32>,
ComplexPattern<i32, 3, "SelectThumbAddrModeS1", []> {
let PrintMethod = "printThumbAddrModeS1Operand";
let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
}
// t_addrmode_sp := sp + imm8 * 4
//
def t_addrmode_sp : Operand<i32>,
ComplexPattern<i32, 2, "SelectThumbAddrModeSP", []> {
let PrintMethod = "printThumbAddrModeSPOperand";
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
}
//===----------------------------------------------------------------------===//
// Miscellaneous Instructions.
//
// 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 tADJCALLSTACKUP :
PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2), NoItinerary,
[(ARMcallseq_end imm:$amt1, imm:$amt2)]>,
Requires<[IsThumb, IsThumb1Only]>;
def tADJCALLSTACKDOWN :
PseudoInst<(outs), (ins i32imm:$amt), NoItinerary,
[(ARMcallseq_start imm:$amt)]>,
Requires<[IsThumb, IsThumb1Only]>;
}
def tNOP : T1pI<(outs), (ins), NoItinerary, "nop", "",
[/* For disassembly only; pattern left blank */]>,
T1Encoding<0b101111> {
// A8.6.110
let Inst{9-8} = 0b11;
let Inst{7-0} = 0x00;
}
def tYIELD : T1pI<(outs), (ins), NoItinerary, "yield", "",
[/* For disassembly only; pattern left blank */]>,
T1Encoding<0b101111> {
// A8.6.410
let Inst{9-8} = 0b11;
let Inst{7-0} = 0x10;
}
def tWFE : T1pI<(outs), (ins), NoItinerary, "wfe", "",
[/* For disassembly only; pattern left blank */]>,
T1Encoding<0b101111> {
// A8.6.408
let Inst{9-8} = 0b11;
let Inst{7-0} = 0x20;
}
def tWFI : T1pI<(outs), (ins), NoItinerary, "wfi", "",
[/* For disassembly only; pattern left blank */]>,
T1Encoding<0b101111> {
// A8.6.409
let Inst{9-8} = 0b11;
let Inst{7-0} = 0x30;
}
def tSEV : T1pI<(outs), (ins), NoItinerary, "sev", "",
[/* For disassembly only; pattern left blank */]>,
T1Encoding<0b101111> {
// A8.6.157
let Inst{9-8} = 0b11;
let Inst{7-0} = 0x40;
}
def tSETENDBE : T1I<(outs), (ins), NoItinerary, "setend\tbe",
[/* For disassembly only; pattern left blank */]>,
T1Encoding<0b101101> {
// A8.6.156
let Inst{9-5} = 0b10010;
let Inst{4} = 1;
let Inst{3} = 1; // Big-Endian
let Inst{2-0} = 0b000;
}
def tSETENDLE : T1I<(outs), (ins), NoItinerary, "setend\tle",
[/* For disassembly only; pattern left blank */]>,
T1Encoding<0b101101> {
// A8.6.156
let Inst{9-5} = 0b10010;
let Inst{4} = 1;
let Inst{3} = 0; // Little-Endian
let Inst{2-0} = 0b000;
}
// The i32imm operand $val can be used by a debugger to store more information
// about the breakpoint.
def tBKPT : T1I<(outs), (ins i32imm:$val), NoItinerary, "bkpt\t$val",
[/* For disassembly only; pattern left blank */]>,
T1Encoding<0b101111> {
// A8.6.22
bits<8> val;
let Inst{9-8} = 0b10;
let Inst{7-0} = val;
}
// Change Processor State is a system instruction -- for disassembly only.
// The singleton $opt operand contains the following information:
// opt{4-0} = mode ==> don't care
// opt{5} = changemode ==> 0 (false for 16-bit Thumb instr)
// opt{8-6} = AIF from Inst{2-0}
// opt{10-9} = 1:imod from Inst{4} with 0b10 as enable and 0b11 as disable
//
// The opt{4-0} and opt{5} sub-fields are to accommodate 32-bit Thumb and ARM
// CPS which has more options.
def tCPS : T1I<(outs), (ins cps_opt:$opt), NoItinerary, "cps$opt",
[/* For disassembly only; pattern left blank */]>,
T1Misc<0b0110011> {
// A8.6.38 & B6.1.1
let Inst{3} = 0; // FIXME: Finish encoding.
}
// For both thumb1 and thumb2.
let isNotDuplicable = 1, isCodeGenOnly = 1 in
def tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, "",
[(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>,
T1Special<{0,0,?,?}> {
// A8.6.6 Rm = pc
bits<3> dst;
let Inst{6-3} = 0b1111;
let Inst{2-0} = dst;
}
// PC relative add.
def tADDrPCi : T1I<(outs tGPR:$dst), (ins t_imm_s4:$rhs), IIC_iALUi,
"add\t$dst, pc, $rhs", []>,
T1Encoding<{1,0,1,0,0,?}> {
// A6.2 & A8.6.10
bits<3> dst;
bits<8> rhs;
let Inst{10-8}