Newer
Older
// address and save #0 in R0 for the non-longjmp case.
Jim Grosbach
committed
// 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
Jim Grosbach
committed
// 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.
// A constant value is passed in $val, and we use the location as a scratch.
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 ], hasSideEffects = 1, isBarrier = 1 in {
def Int_eh_sjlj_setjmp : XI<(outs), (ins GPR:$src, GPR:$val),
David Goodwin
committed
AddrModeNone, SizeSpecial, IndexModeNone,
Pseudo, NoItinerary, "", "",
[(set R0, (ARMeh_sjlj_setjmp GPR:$src, GPR:$val))]>,
Requires<[IsARM, HasVFP2]>;
}
let Defs =
[ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR ],
hasSideEffects = 1, isBarrier = 1 in {
def Int_eh_sjlj_setjmp_nofp : XI<(outs), (ins GPR:$src, GPR:$val),
AddrModeNone, SizeSpecial, IndexModeNone,
Pseudo, NoItinerary, "", "",
[(set R0, (ARMeh_sjlj_setjmp GPR:$src, GPR:$val))]>,
Requires<[IsARM, NoVFP]>;
Jim Grosbach
committed
}
// FIXME: Non-Darwin version(s)
let isBarrier = 1, hasSideEffects = 1, isTerminator = 1,
Defs = [ R7, LR, SP ] in {
def Int_eh_sjlj_longjmp : XI<(outs), (ins GPR:$src, GPR:$scratch),
AddrModeNone, SizeSpecial, IndexModeNone,
Pseudo, NoItinerary, "", "",
[(ARMeh_sjlj_longjmp GPR:$src, GPR:$scratch)]>,
Requires<[IsARM, IsDarwin]>;
}
// eh.sjlj.dispatchsetup pseudo-instruction.
// This pseudo is usef for ARM, Thumb1 and Thumb2. Any differences are
// handled when the pseudo is expanded (which happens before any passes
// that need the instruction size).
let isBarrier = 1, hasSideEffects = 1 in
def Int_eh_sjlj_dispatchsetup :
PseudoInst<(outs), (ins GPR:$src), NoItinerary, "",
[(ARMeh_sjlj_dispatchsetup GPR:$src)]>,
Requires<[IsDarwin]>;
//===----------------------------------------------------------------------===//
// Non-Instruction Patterns
//
// FIXME: Expand this in ARMExpandPseudoInsts.
// FIXME: Remove this when we can do generalized remat.
let isReMaterializable = 1 in
def MOVi2pieces : AI1x2<(outs GPR:$dst), (ins so_imm2part:$src),
Pseudo, IIC_iMOVix2,
Evan Cheng
committed
"mov", "\t$dst, $src",
Evan Cheng
committed
[(set GPR:$dst, so_imm2part:$src)]>,
Requires<[IsARM, NoV6T2]>;
def : ARMPat<(or GPR:$LHS, so_imm2part:$RHS),
(ORRri (ORRri GPR:$LHS, (so_imm2part_1 imm:$RHS)),
(so_imm2part_2 imm:$RHS))>;
def : ARMPat<(xor GPR:$LHS, so_imm2part:$RHS),
(EORri (EORri GPR:$LHS, (so_imm2part_1 imm:$RHS)),
(so_imm2part_2 imm:$RHS))>;
Jim Grosbach
committed
def : ARMPat<(add GPR:$LHS, so_imm2part:$RHS),
(ADDri (ADDri GPR:$LHS, (so_imm2part_1 imm:$RHS)),
(so_imm2part_2 imm:$RHS))>;
Jim Grosbach
committed
def : ARMPat<(add GPR:$LHS, so_neg_imm2part:$RHS),
(SUBri (SUBri GPR:$LHS, (so_neg_imm2part_1 imm:$RHS)),
(so_neg_imm2part_2 imm:$RHS))>;
Evan Cheng
committed
// 32-bit immediate using movw + movt.
Chris Lattner
committed
// This is a single pseudo instruction, the benefit is that it can be remat'd
// as a single unit instead of having to handle reg inputs.
// FIXME: Remove this when we can do generalized remat.
Evan Cheng
committed
let isReMaterializable = 1 in
def MOVi32imm : PseudoInst<(outs GPR:$dst), (ins i32imm:$src), IIC_iMOVix2, "",
[(set GPR:$dst, (i32 imm:$src))]>,
Requires<[IsARM, HasV6T2]>;
// ConstantPool, GlobalAddress, and JumpTable
def : ARMPat<(ARMWrapper tglobaladdr :$dst), (LEApcrel tglobaladdr :$dst)>,
Requires<[IsARM, DontUseMovt]>;
def : ARMPat<(ARMWrapper tconstpool :$dst), (LEApcrel tconstpool :$dst)>;
def : ARMPat<(ARMWrapper tglobaladdr :$dst), (MOVi32imm tglobaladdr :$dst)>,
Requires<[IsARM, UseMovt]>;
def : ARMPat<(ARMWrapperJT tjumptable:$dst, imm:$id),
(LEApcrelJT tjumptable:$dst, imm:$id)>;
def : ARMPat<(ARMtcret tcGPR:$dst),
(TCRETURNri tcGPR:$dst)>, Requires<[IsDarwin]>;
def : ARMPat<(ARMtcret (i32 tglobaladdr:$dst)),
(TCRETURNdi texternalsym:$dst)>, Requires<[IsDarwin]>;
def : ARMPat<(ARMtcret (i32 texternalsym:$dst)),
(TCRETURNdi texternalsym:$dst)>, Requires<[IsDarwin]>;
def : ARMPat<(ARMtcret tcGPR:$dst),
(TCRETURNriND tcGPR:$dst)>, Requires<[IsNotDarwin]>;
def : ARMPat<(ARMtcret (i32 tglobaladdr:$dst)),
(TCRETURNdiND texternalsym:$dst)>, Requires<[IsNotDarwin]>;
def : ARMPat<(ARMtcret (i32 texternalsym:$dst)),
(TCRETURNdiND texternalsym:$dst)>, Requires<[IsNotDarwin]>;
def : ARMPat<(ARMcall texternalsym:$func), (BL texternalsym:$func)>,
Requires<[IsARM, IsNotDarwin]>;
def : ARMPat<(ARMcall texternalsym:$func), (BLr9 texternalsym:$func)>,
Requires<[IsARM, IsDarwin]>;
// zextload i1 -> zextload i8
def : ARMPat<(zextloadi1 addrmode2:$addr), (LDRB addrmode2:$addr)>;
// extload -> zextload
def : ARMPat<(extloadi1 addrmode2:$addr), (LDRB addrmode2:$addr)>;
def : ARMPat<(extloadi8 addrmode2:$addr), (LDRB addrmode2:$addr)>;
def : ARMPat<(extloadi16 addrmode3:$addr), (LDRH addrmode3:$addr)>;
def : ARMPat<(extloadi8 addrmodepc:$addr), (PICLDRB addrmodepc:$addr)>;
def : ARMPat<(extloadi16 addrmodepc:$addr), (PICLDRH addrmodepc:$addr)>;
// smul* and smla*
def : ARMV5TEPat<(mul (sra (shl GPR:$a, (i32 16)), (i32 16)),
(sra (shl GPR:$b, (i32 16)), (i32 16))),
(SMULBB GPR:$a, GPR:$b)>;
def : ARMV5TEPat<(mul sext_16_node:$a, sext_16_node:$b),
(SMULBB GPR:$a, GPR:$b)>;
def : ARMV5TEPat<(mul (sra (shl GPR:$a, (i32 16)), (i32 16)),
(sra GPR:$b, (i32 16))),
(SMULBT GPR:$a, GPR:$b)>;
def : ARMV5TEPat<(mul sext_16_node:$a, (sra GPR:$b, (i32 16))),
(SMULBT GPR:$a, GPR:$b)>;
def : ARMV5TEPat<(mul (sra GPR:$a, (i32 16)),
(sra (shl GPR:$b, (i32 16)), (i32 16))),
(SMULTB GPR:$a, GPR:$b)>;
def : ARMV5TEPat<(mul (sra GPR:$a, (i32 16)), sext_16_node:$b),
(SMULTB GPR:$a, GPR:$b)>;
def : ARMV5TEPat<(sra (mul GPR:$a, (sra (shl GPR:$b, (i32 16)), (i32 16))),
(i32 16)),
(SMULWB GPR:$a, GPR:$b)>;
def : ARMV5TEPat<(sra (mul GPR:$a, sext_16_node:$b), (i32 16)),
(SMULWB GPR:$a, GPR:$b)>;
def : ARMV5TEPat<(add GPR:$acc,
(mul (sra (shl GPR:$a, (i32 16)), (i32 16)),
(sra (shl GPR:$b, (i32 16)), (i32 16)))),
(SMLABB GPR:$a, GPR:$b, GPR:$acc)>;
def : ARMV5TEPat<(add GPR:$acc,
(mul sext_16_node:$a, sext_16_node:$b)),
(SMLABB GPR:$a, GPR:$b, GPR:$acc)>;
def : ARMV5TEPat<(add GPR:$acc,
(mul (sra (shl GPR:$a, (i32 16)), (i32 16)),
(sra GPR:$b, (i32 16)))),
(SMLABT GPR:$a, GPR:$b, GPR:$acc)>;
def : ARMV5TEPat<(add GPR:$acc,
(mul sext_16_node:$a, (sra GPR:$b, (i32 16)))),
(SMLABT GPR:$a, GPR:$b, GPR:$acc)>;
def : ARMV5TEPat<(add GPR:$acc,
(mul (sra GPR:$a, (i32 16)),
(sra (shl GPR:$b, (i32 16)), (i32 16)))),
(SMLATB GPR:$a, GPR:$b, GPR:$acc)>;
def : ARMV5TEPat<(add GPR:$acc,
(mul (sra GPR:$a, (i32 16)), sext_16_node:$b)),
(SMLATB GPR:$a, GPR:$b, GPR:$acc)>;
def : ARMV5TEPat<(add GPR:$acc,
(sra (mul GPR:$a, (sra (shl GPR:$b, (i32 16)), (i32 16))),
(i32 16))),
(SMLAWB GPR:$a, GPR:$b, GPR:$acc)>;
def : ARMV5TEPat<(add GPR:$acc,
(sra (mul GPR:$a, sext_16_node:$b), (i32 16))),
(SMLAWB GPR:$a, GPR:$b, GPR:$acc)>;
//===----------------------------------------------------------------------===//
// Thumb Support
//
//===----------------------------------------------------------------------===//
// Thumb2 Support
//
include "ARMInstrThumb2.td"
//===----------------------------------------------------------------------===//
// Floating Point Support
//
//===----------------------------------------------------------------------===//
// Advanced SIMD (NEON) Support
//
include "ARMInstrNEON.td"
//===----------------------------------------------------------------------===//
// Coprocessor Instructions. For disassembly only.
//
def CDP : ABI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1,
nohash_imm:$CRd, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2),
NoItinerary, "cdp", "\tp$cop, $opc1, cr$CRd, cr$CRn, cr$CRm, $opc2",
[/* For disassembly only; pattern left blank */]> {
let Inst{4} = 0;
}
def CDP2 : ABXI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1,
nohash_imm:$CRd, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2),
NoItinerary, "cdp2\tp$cop, $opc1, cr$CRd, cr$CRn, cr$CRm, $opc2",
[/* For disassembly only; pattern left blank */]> {
let Inst{31-28} = 0b1111;
let Inst{4} = 0;
}
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
class ACI<dag oops, dag iops, string opc, string asm>
: I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, BrFrm, NoItinerary,
opc, asm, "", [/* For disassembly only; pattern left blank */]> {
let Inst{27-25} = 0b110;
}
multiclass LdStCop<bits<4> op31_28, bit load, string opc> {
def _OFFSET : ACI<(outs),
(ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
opc, "\tp$cop, cr$CRd, $addr"> {
let Inst{31-28} = op31_28;
let Inst{24} = 1; // P = 1
let Inst{21} = 0; // W = 0
let Inst{22} = 0; // D = 0
let Inst{20} = load;
}
def _PRE : ACI<(outs),
(ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
opc, "\tp$cop, cr$CRd, $addr!"> {
let Inst{31-28} = op31_28;
let Inst{24} = 1; // P = 1
let Inst{21} = 1; // W = 1
let Inst{22} = 0; // D = 0
let Inst{20} = load;
}
def _POST : ACI<(outs),
(ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset),
opc, "\tp$cop, cr$CRd, [$base], $offset"> {
let Inst{31-28} = op31_28;
let Inst{24} = 0; // P = 0
let Inst{21} = 1; // W = 1
let Inst{22} = 0; // D = 0
let Inst{20} = load;
}
def _OPTION : ACI<(outs),
(ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, i32imm:$option),
opc, "\tp$cop, cr$CRd, [$base], $option"> {
let Inst{31-28} = op31_28;
let Inst{24} = 0; // P = 0
let Inst{23} = 1; // U = 1
let Inst{21} = 0; // W = 0
let Inst{22} = 0; // D = 0
let Inst{20} = load;
}
def L_OFFSET : ACI<(outs),
(ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
Johnny Chen
committed
!strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr"> {
let Inst{31-28} = op31_28;
let Inst{24} = 1; // P = 1
let Inst{21} = 0; // W = 0
let Inst{22} = 1; // D = 1
let Inst{20} = load;
}
def L_PRE : ACI<(outs),
(ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
Johnny Chen
committed
!strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr!"> {
let Inst{31-28} = op31_28;
let Inst{24} = 1; // P = 1
let Inst{21} = 1; // W = 1
let Inst{22} = 1; // D = 1
let Inst{20} = load;
}
def L_POST : ACI<(outs),
(ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset),
Johnny Chen
committed
!strconcat(opc, "l"), "\tp$cop, cr$CRd, [$base], $offset"> {
let Inst{31-28} = op31_28;
let Inst{24} = 0; // P = 0
let Inst{21} = 1; // W = 1
let Inst{22} = 1; // D = 1
let Inst{20} = load;
}
def L_OPTION : ACI<(outs),
(ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, nohash_imm:$option),
Johnny Chen
committed
!strconcat(opc, "l"), "\tp$cop, cr$CRd, [$base], $option"> {
let Inst{31-28} = op31_28;
let Inst{24} = 0; // P = 0
let Inst{23} = 1; // U = 1
let Inst{21} = 0; // W = 0
let Inst{22} = 1; // D = 1
let Inst{20} = load;
}
}
defm LDC : LdStCop<{?,?,?,?}, 1, "ldc">;
defm LDC2 : LdStCop<0b1111, 1, "ldc2">;
defm STC : LdStCop<{?,?,?,?}, 0, "stc">;
defm STC2 : LdStCop<0b1111, 0, "stc2">;
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
def MCR : ABI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1,
GPR:$Rt, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2),
NoItinerary, "mcr", "\tp$cop, $opc1, $Rt, cr$CRn, cr$CRm, $opc2",
[/* For disassembly only; pattern left blank */]> {
let Inst{20} = 0;
let Inst{4} = 1;
}
def MCR2 : ABXI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1,
GPR:$Rt, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2),
NoItinerary, "mcr2\tp$cop, $opc1, $Rt, cr$CRn, cr$CRm, $opc2",
[/* For disassembly only; pattern left blank */]> {
let Inst{31-28} = 0b1111;
let Inst{20} = 0;
let Inst{4} = 1;
}
def MRC : ABI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1,
GPR:$Rt, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2),
NoItinerary, "mrc", "\tp$cop, $opc1, $Rt, cr$CRn, cr$CRm, $opc2",
[/* For disassembly only; pattern left blank */]> {
let Inst{20} = 1;
let Inst{4} = 1;
}
def MRC2 : ABXI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1,
GPR:$Rt, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2),
NoItinerary, "mrc2\tp$cop, $opc1, $Rt, cr$CRn, cr$CRm, $opc2",
[/* For disassembly only; pattern left blank */]> {
let Inst{31-28} = 0b1111;
let Inst{20} = 1;
let Inst{4} = 1;
}
def MCRR : ABI<0b1100, (outs), (ins nohash_imm:$cop, i32imm:$opc,
GPR:$Rt, GPR:$Rt2, nohash_imm:$CRm),
NoItinerary, "mcrr", "\tp$cop, $opc, $Rt, $Rt2, cr$CRm",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0100;
}
def MCRR2 : ABXI<0b1100, (outs), (ins nohash_imm:$cop, i32imm:$opc,
GPR:$Rt, GPR:$Rt2, nohash_imm:$CRm),
NoItinerary, "mcrr2\tp$cop, $opc, $Rt, $Rt2, cr$CRm",
[/* For disassembly only; pattern left blank */]> {
let Inst{31-28} = 0b1111;
let Inst{23-20} = 0b0100;
}
def MRRC : ABI<0b1100, (outs), (ins nohash_imm:$cop, i32imm:$opc,
GPR:$Rt, GPR:$Rt2, nohash_imm:$CRm),
NoItinerary, "mrrc", "\tp$cop, $opc, $Rt, $Rt2, cr$CRm",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0101;
}
def MRRC2 : ABXI<0b1100, (outs), (ins nohash_imm:$cop, i32imm:$opc,
GPR:$Rt, GPR:$Rt2, nohash_imm:$CRm),
NoItinerary, "mrrc2\tp$cop, $opc, $Rt, $Rt2, cr$CRm",
[/* For disassembly only; pattern left blank */]> {
let Inst{31-28} = 0b1111;
let Inst{23-20} = 0b0101;
}
//===----------------------------------------------------------------------===//
// Move between special register and ARM core register -- for disassembly only
//
def MRS : ABI<0b0001,(outs GPR:$dst),(ins), NoItinerary, "mrs", "\t$dst, cpsr",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0000;
let Inst{7-4} = 0b0000;
}
def MRSsys : ABI<0b0001,(outs GPR:$dst),(ins), NoItinerary,"mrs","\t$dst, spsr",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0100;
let Inst{7-4} = 0b0000;
}
Johnny Chen
committed
def MSR : ABI<0b0001, (outs), (ins GPR:$src, msr_mask:$mask), NoItinerary,
"msr", "\tcpsr$mask, $src",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0010;
let Inst{7-4} = 0b0000;
}
Johnny Chen
committed
def MSRi : ABI<0b0011, (outs), (ins so_imm:$a, msr_mask:$mask), NoItinerary,
"msr", "\tcpsr$mask, $a",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0010;
let Inst{7-4} = 0b0000;
}
Johnny Chen
committed
def MSRsys : ABI<0b0001, (outs), (ins GPR:$src, msr_mask:$mask), NoItinerary,
"msr", "\tspsr$mask, $src",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0110;
let Inst{7-4} = 0b0000;
}
Johnny Chen
committed
def MSRsysi : ABI<0b0011, (outs), (ins so_imm:$a, msr_mask:$mask), NoItinerary,
"msr", "\tspsr$mask, $a",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0110;
let Inst{7-4} = 0b0000;
}