-//===- ARMInstrThumb.td - Thumb support for ARM ---------------------------===//
+//===- ARMInstrThumb.td - Thumb support for ARM ------------*- tablegen -*-===//
//
// The LLVM Compiler Infrastructure
//
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.
+// 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());
}]>;
// 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
+//
+// 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.
// Indirect branches
let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
- def tBRIND : TI<(outs), (ins GPR:$Rm), IIC_Br, "mov\tpc, $Rm",
+ def tBRIND : TI<(outs), (ins GPR:$Rm),
+ IIC_Br,
+ "mov\tpc, $Rm",
[(brind GPR:$Rm)]>,
T1Special<{1,0,?,?}> {
// A8.6.97
let Inst{7-0} = regs{7-0};
}
-// All calls clobber the non-callee saved registers. SP is marked as
-// a use to prevent stack-pointer assignments that appear immediately
-// before calls from potentially appearing dead.
+// All calls clobber the non-callee saved registers. SP is marked as a use to
+// prevent stack-pointer assignments that appear immediately before calls from
+// potentially appearing dead.
let isCall = 1,
// On non-Darwin platforms R9 is callee-saved.
Defs = [R0, R1, R2, R3, R12, LR,
Uses = [SP] in {
// Also used for Thumb2
def tBL : TIx2<0b11110, 0b11, 1,
- (outs), (ins i32imm:$func, variable_ops), IIC_Br,
+ (outs), (ins bltarget:$func, variable_ops), IIC_Br,
"bl\t$func",
[(ARMtcall tglobaladdr:$func)]>,
- Requires<[IsThumb, IsNotDarwin]>;
+ Requires<[IsThumb, IsNotDarwin]> {
+ bits<24> func;
+ let Inst{26} = func{23};
+ let Inst{25-16} = func{20-11};
+ let Inst{13} = func{22};
+ let Inst{11} = func{21};
+ let Inst{10-0} = func{10-0};
+ }
// ARMv5T and above, also used for Thumb2
def tBLXi : TIx2<0b11110, 0b11, 0,
Uses = [R7, SP] in {
// Also used for Thumb2
def tBLr9 : TIx2<0b11110, 0b11, 1,
- (outs), (ins pred:$p, i32imm:$func, variable_ops), IIC_Br,
+ (outs), (ins pred:$p, bltarget:$func, variable_ops), IIC_Br,
"bl${p}\t$func",
[(ARMtcall tglobaladdr:$func)]>,
- Requires<[IsThumb, IsDarwin]>;
+ Requires<[IsThumb, IsDarwin]> {
+ bits<24> func;
+ let Inst{26} = func{23};
+ let Inst{25-16} = func{20-11};
+ let Inst{13} = func{22};
+ let Inst{11} = func{21};
+ let Inst{10-0} = func{10-0};
+ }
// ARMv5T and above, also used for Thumb2
def tBLXi_r9 : TIx2<0b11110, 0b11, 0,
Requires<[IsThumb, IsThumb1Only, IsDarwin]>;
}
-let isBranch = 1, isTerminator = 1 in {
- let isBarrier = 1 in {
- let isPredicable = 1 in
- def tB : T1I<(outs), (ins brtarget:$target), IIC_Br,
- "b\t$target", [(br bb:$target)]>,
- T1Encoding<{1,1,1,0,0,?}>;
+let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
+ let isPredicable = 1 in
+ def tB : T1I<(outs), (ins brtarget:$target), IIC_Br,
+ "b\t$target", [(br bb:$target)]>,
+ T1Encoding<{1,1,1,0,0,?}>;
// Far jump
let Defs = [LR] in
[(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]> {
list<Predicate> Predicates = [IsThumb, IsThumb1Only];
}
- }
}
// FIXME: should be able to write a pattern for ARMBrcond, but can't use
// Arithmetic Instructions.
//
+// Helper classes for encoding T1pI patterns:
+class T1pIDPEncode<bits<4> opA, dag oops, dag iops, InstrItinClass itin,
+ string opc, string asm, list<dag> pattern>
+ : T1pI<oops, iops, itin, opc, asm, pattern>,
+ T1DataProcessing<opA> {
+ bits<3> Rm;
+ bits<3> Rn;
+ let Inst{5-3} = Rm;
+ let Inst{2-0} = Rn;
+}
+class T1pIMiscEncode<bits<7> opA, dag oops, dag iops, InstrItinClass itin,
+ string opc, string asm, list<dag> pattern>
+ : T1pI<oops, iops, itin, opc, asm, pattern>,
+ T1Misc<opA> {
+ bits<3> Rm;
+ bits<3> Rd;
+ let Inst{5-3} = Rm;
+ let Inst{2-0} = Rd;
+}
+
// Helper classes for encoding T1sI patterns:
class T1sIDPEncode<bits<4> opA, dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
let isCompare = 1, Defs = [CPSR] in {
//FIXME: Disable CMN, as CCodes are backwards from compare expectations
// Compare-to-zero still works out, just not the relationals
-//def tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr,
-// "cmn", "\t$lhs, $rhs",
-// [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>,
-// T1DataProcessing<0b1011>;
-def tCMNz : T1pI<(outs), (ins tGPR:$Rn, tGPR:$Rm), IIC_iCMPr,
- "cmn", "\t$Rn, $Rm",
- [(ARMcmpZ tGPR:$Rn, (ineg tGPR:$Rm))]>,
- T1DataProcessing<0b1011> {
- // A8.6.33
- bits<3> Rm;
- bits<3> Rn;
- let Inst{5-3} = Rm;
- let Inst{2-0} = Rn;
-}
-}
+//def tCMN : // A8.6.33
+// T1pIDPEncode<0b1011, (outs), (ins tGPR:$lhs, tGPR:$rhs),
+// IIC_iCMPr,
+// "cmn", "\t$lhs, $rhs",
+// [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>;
+
+def tCMNz : // A8.6.33
+ T1pIDPEncode<0b1011, (outs), (ins tGPR:$Rn, tGPR:$Rm),
+ IIC_iCMPr,
+ "cmn", "\t$Rn, $Rm",
+ [(ARMcmpZ tGPR:$Rn, (ineg tGPR:$Rm))]>;
+
+} // isCompare = 1, Defs = [CPSR]
// CMP immediate
let isCompare = 1, Defs = [CPSR] in {
}
// CMP register
-def tCMPr : T1pI<(outs), (ins tGPR:$Rn, tGPR:$Rm), IIC_iCMPr,
- "cmp", "\t$Rn, $Rm",
- [(ARMcmp tGPR:$Rn, tGPR:$Rm)]>,
- T1DataProcessing<0b1010> {
- // A8.6.36 T1
- bits<3> Rm;
- bits<3> Rn;
- let Inst{5-3} = Rm;
- let Inst{2-0} = Rn;
-}
-def tCMPzr : T1pI<(outs), (ins tGPR:$Rn, tGPR:$Rm), IIC_iCMPr,
- "cmp", "\t$Rn, $Rm",
- [(ARMcmpZ tGPR:$Rn, tGPR:$Rm)]>,
- T1DataProcessing<0b1010> {
- // A8.6.36 T1
- bits<3> Rm;
- bits<3> Rn;
- let Inst{5-3} = Rm;
- let Inst{2-0} = Rn;
-}
+def tCMPr : // A8.6.36 T1
+ T1pIDPEncode<0b1010, (outs), (ins tGPR:$Rn, tGPR:$Rm),
+ IIC_iCMPr,
+ "cmp", "\t$Rn, $Rm",
+ [(ARMcmp tGPR:$Rn, tGPR:$Rm)]>;
+
+def tCMPzr : // A8.6.36 T1
+ T1pIDPEncode<0b1010, (outs), (ins tGPR:$Rn, tGPR:$Rm), IIC_iCMPr,
+ "cmp", "\t$Rn, $Rm",
+ [(ARMcmpZ tGPR:$Rn, tGPR:$Rm)]>;
def tCMPhir : T1pI<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_iCMPr,
"cmp", "\t$Rn, $Rm", []>,
let neverHasSideEffects = 1 in {
// FIXME: Make this predicable.
-def tMOVr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr,
- "mov\t$dst, $src", []>,
- T1Special<0b1000>;
+def tMOVr : T1I<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr,
+ "mov\t$Rd, $Rm", []>,
+ T1Special<0b1000> {
+ // A8.6.97
+ bits<4> Rd;
+ bits<4> Rm;
+ // Bits {7-6} are encoded by the T1Special value.
+ let Inst{5-3} = Rm{2-0};
+ let Inst{2-0} = Rd{2-0};
+}
let Defs = [CPSR] in
-def tMOVSr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr,
- "movs\t$dst, $src", []>, Encoding16 {
+def tMOVSr : T1I<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr,
+ "movs\t$Rd, $Rm", []>, Encoding16 {
+ // A8.6.97
+ bits<3> Rd;
+ bits<3> Rm;
let Inst{15-6} = 0b0000000000;
+ let Inst{5-3} = Rm;
+ let Inst{2-0} = Rd;
}
// FIXME: Make these predicable.
-def tMOVgpr2tgpr : T1I<(outs tGPR:$dst), (ins GPR:$src), IIC_iMOVr,
- "mov\t$dst, $src", []>,
- T1Special<{1,0,0,?}>;
-def tMOVtgpr2gpr : T1I<(outs GPR:$dst), (ins tGPR:$src), IIC_iMOVr,
- "mov\t$dst, $src", []>,
- T1Special<{1,0,?,0}>;
-def tMOVgpr2gpr : T1I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr,
- "mov\t$dst, $src", []>,
- T1Special<{1,0,?,?}>;
+def tMOVgpr2tgpr : T1I<(outs tGPR:$Rd), (ins GPR:$Rm), IIC_iMOVr,
+ "mov\t$Rd, $Rm", []>,
+ T1Special<{1,0,0,?}> {
+ // A8.6.97
+ bits<4> Rd;
+ bits<4> Rm;
+ // Bit {7} is encoded by the T1Special value.
+ let Inst{6-3} = Rm;
+ let Inst{2-0} = Rd{2-0};
+}
+def tMOVtgpr2gpr : T1I<(outs GPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr,
+ "mov\t$Rd, $Rm", []>,
+ T1Special<{1,0,?,0}> {
+ // A8.6.97
+ bits<4> Rd;
+ bits<4> Rm;
+ // Bit {6} is encoded by the T1Special value.
+ let Inst{7} = Rd{3};
+ let Inst{5-3} = Rm{2-0};
+ let Inst{2-0} = Rd{2-0};
+}
+def tMOVgpr2gpr : T1I<(outs GPR:$Rd), (ins GPR:$Rm), IIC_iMOVr,
+ "mov\t$Rd, $Rm", []>,
+ T1Special<{1,0,?,?}> {
+ // A8.6.97
+ bits<4> Rd;
+ bits<4> Rm;
+ let Inst{7} = Rd{3};
+ let Inst{6-3} = Rm;
+ let Inst{2-0} = Rd{2-0};
+}
} // neverHasSideEffects
-// multiply register
+// Multiply register
let isCommutable = 1 in
def tMUL : // A8.6.105 T1
T1sItDPEncode<0b1101, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm),
[(set tGPR:$Rdn, (or tGPR:$Rn, tGPR:$Rm))]>;
// Swaps
-def tREV : T1pI<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iUNAr,
- "rev", "\t$Rd, $Rm",
- [(set tGPR:$Rd, (bswap tGPR:$Rm))]>,
- Requires<[IsThumb, IsThumb1Only, HasV6]>,
- T1Misc<{1,0,1,0,0,0,?}> {
- // A8.6.134
- bits<3> Rm;
- bits<3> Rd;
- let Inst{5-3} = Rm;
- let Inst{2-0} = Rd;
-}
-
-def tREV16 : T1pI<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iUNAr,
- "rev16", "\t$Rd, $Rm",
+def tREV : // A8.6.134
+ T1pIMiscEncode<{1,0,1,0,0,0,?}, (outs tGPR:$Rd), (ins tGPR:$Rm),
+ IIC_iUNAr,
+ "rev", "\t$Rd, $Rm",
+ [(set tGPR:$Rd, (bswap tGPR:$Rm))]>,
+ Requires<[IsThumb, IsThumb1Only, HasV6]>;
+
+def tREV16 : // A8.6.135
+ T1pIMiscEncode<{1,0,1,0,0,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm),
+ IIC_iUNAr,
+ "rev16", "\t$Rd, $Rm",
[(set tGPR:$Rd,
(or (and (srl tGPR:$Rm, (i32 8)), 0xFF),
(or (and (shl tGPR:$Rm, (i32 8)), 0xFF00),
(or (and (srl tGPR:$Rm, (i32 8)), 0xFF0000),
(and (shl tGPR:$Rm, (i32 8)), 0xFF000000)))))]>,
- Requires<[IsThumb, IsThumb1Only, HasV6]>,
- T1Misc<{1,0,1,0,0,1,?}> {
- // A8.6.135
- bits<3> Rm;
- bits<3> Rd;
- let Inst{5-3} = Rm;
- let Inst{2-0} = Rd;
-}
-
-def tREVSH : T1pI<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iUNAr,
- "revsh", "\t$Rd, $Rm",
- [(set tGPR:$Rd,
- (sext_inreg
- (or (srl (and tGPR:$Rm, 0xFF00), (i32 8)),
- (shl tGPR:$Rm, (i32 8))), i16))]>,
- Requires<[IsThumb, IsThumb1Only, HasV6]>,
- T1Misc<{1,0,1,0,1,1,?}> {
- // A8.6.136
- bits<3> Rm;
- bits<3> Rd;
- let Inst{5-3} = Rm;
- let Inst{2-0} = Rd;
-}
+ Requires<[IsThumb, IsThumb1Only, HasV6]>;
+
+def tREVSH : // A8.6.136
+ T1pIMiscEncode<{1,0,1,0,1,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm),
+ IIC_iUNAr,
+ "revsh", "\t$Rd, $Rm",
+ [(set tGPR:$Rd,
+ (sext_inreg
+ (or (srl (and tGPR:$Rm, 0xFF00), (i32 8)),
+ (shl tGPR:$Rm, (i32 8))), i16))]>,
+ Requires<[IsThumb, IsThumb1Only, HasV6]>;
// Rotate right register
def tROR : // A8.6.139
// TODO: A7-96: STMIA - store multiple.
// Sign-extend byte
-def tSXTB : T1pI<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iUNAr,
- "sxtb", "\t$Rd, $Rm",
- [(set tGPR:$Rd, (sext_inreg tGPR:$Rm, i8))]>,
- Requires<[IsThumb, IsThumb1Only, HasV6]>,
- T1Misc<{0,0,1,0,0,1,?}> {
- // A8.6.222
- bits<3> Rm;
- bits<3> Rd;
- let Inst{5-3} = Rm;
- let Inst{2-0} = Rd;
-}
-
-// sign-extend short
-def tSXTH : T1pI<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iUNAr,
- "sxth", "\t$Rd, $Rm",
- [(set tGPR:$Rd, (sext_inreg tGPR:$Rm, i16))]>,
- Requires<[IsThumb, IsThumb1Only, HasV6]>,
- T1Misc<{0,0,1,0,0,0,?}> {
- // A8.6.224
- bits<3> Rm;
- bits<3> Rd;
- let Inst{5-3} = Rm;
- let Inst{2-0} = Rd;
-}
-
-// test
+def tSXTB : // A8.6.222
+ T1pIMiscEncode<{0,0,1,0,0,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm),
+ IIC_iUNAr,
+ "sxtb", "\t$Rd, $Rm",
+ [(set tGPR:$Rd, (sext_inreg tGPR:$Rm, i8))]>,
+ Requires<[IsThumb, IsThumb1Only, HasV6]>;
+
+// Sign-extend short
+def tSXTH : // A8.6.224
+ T1pIMiscEncode<{0,0,1,0,0,0,?}, (outs tGPR:$Rd), (ins tGPR:$Rm),
+ IIC_iUNAr,
+ "sxth", "\t$Rd, $Rm",
+ [(set tGPR:$Rd, (sext_inreg tGPR:$Rm, i16))]>,
+ Requires<[IsThumb, IsThumb1Only, HasV6]>;
+
+// Test
let isCompare = 1, isCommutable = 1, Defs = [CPSR] in
-def tTST : T1pI<(outs), (ins tGPR:$Rn, tGPR:$Rm), IIC_iTSTr,
- "tst", "\t$Rn, $Rm",
- [(ARMcmpZ (and_su tGPR:$Rn, tGPR:$Rm), 0)]>,
- T1DataProcessing<0b1000> {
- // A8.6.230
- bits<3> Rm;
- bits<3> Rn;
- let Inst{5-3} = Rm;
- let Inst{2-0} = Rn;
-}
-
-// zero-extend byte
-def tUXTB : T1pI<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iUNAr,
- "uxtb", "\t$Rd, $Rm",
- [(set tGPR:$Rd, (and tGPR:$Rm, 0xFF))]>,
- Requires<[IsThumb, IsThumb1Only, HasV6]>,
- T1Misc<{0,0,1,0,1,1,?}> {
- // A8.6.262
- bits<3> Rm;
- bits<3> Rd;
- let Inst{5-3} = Rm;
- let Inst{2-0} = Rd;
-}
-
-// zero-extend short
-def tUXTH : T1pI<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iUNAr,
- "uxth", "\t$Rd, $Rm",
- [(set tGPR:$Rd, (and tGPR:$Rm, 0xFFFF))]>,
- Requires<[IsThumb, IsThumb1Only, HasV6]>,
- T1Misc<{0,0,1,0,1,0,?}> {
- // A8.6.264
- bits<3> Rm;
- bits<3> Rd;
- let Inst{5-3} = Rm;
- let Inst{2-0} = Rd;
-}
-
+def tTST : // A8.6.230
+ T1pIDPEncode<0b1000, (outs), (ins tGPR:$Rn, tGPR:$Rm), IIC_iTSTr,
+ "tst", "\t$Rn, $Rm",
+ [(ARMcmpZ (and_su tGPR:$Rn, tGPR:$Rm), 0)]>;
+
+// Zero-extend byte
+def tUXTB : // A8.6.262
+ T1pIMiscEncode<{0,0,1,0,1,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm),
+ IIC_iUNAr,
+ "uxtb", "\t$Rd, $Rm",
+ [(set tGPR:$Rd, (and tGPR:$Rm, 0xFF))]>,
+ Requires<[IsThumb, IsThumb1Only, HasV6]>;
+
+// Zero-extend short
+def tUXTH : // A8.6.264
+ T1pIMiscEncode<{0,0,1,0,1,0,?}, (outs tGPR:$Rd), (ins tGPR:$Rm),
+ IIC_iUNAr,
+ "uxth", "\t$Rd, $Rm",
+ [(set tGPR:$Rd, (and tGPR:$Rm, 0xFFFF))]>,
+ Requires<[IsThumb, IsThumb1Only, HasV6]>;
// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC operation.
// Expanded after instruction selection into a branch sequence.
let Inst = 0xf7fffffe;
}
+//===----------------------------------------------------------------------===//
// SJLJ Exception handling intrinsics
-// 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.
-// $val is a scratch register for our use.
+//
+
+// 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.
+// $val is a scratch register for our use.
let Defs = [ R0, R1, R2, R3, R4, R5, R6, R7, R12 ],
hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1 in
def tInt_eh_sjlj_setjmp : ThumbXI<(outs),(ins tGPR:$src, tGPR:$val),
// scheduling.
let isReMaterializable = 1 in
def tLDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp),
- NoItinerary,
+ NoItinerary,
[(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)),
imm:$cp))]>,
Requires<[IsThumb, IsThumb1Only]>;