def SDT_ARMEH_SJLJ_DispatchSetup: SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
-def SDT_ARMMEMBARRIER : SDTypeProfile<0, 0, []>;
-def SDT_ARMSYNCBARRIER : SDTypeProfile<0, 0, []>;
-def SDT_ARMMEMBARRIERMCR : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
-def SDT_ARMSYNCBARRIERMCR : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
+def SDT_ARMMEMBARRIER : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
def SDT_ARMTCRET : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
def ARMMemBarrier : SDNode<"ARMISD::MEMBARRIER", SDT_ARMMEMBARRIER,
[SDNPHasChain]>;
-def ARMSyncBarrier : SDNode<"ARMISD::SYNCBARRIER", SDT_ARMMEMBARRIER,
- [SDNPHasChain]>;
-def ARMMemBarrierMCR : SDNode<"ARMISD::MEMBARRIER", SDT_ARMMEMBARRIERMCR,
- [SDNPHasChain]>;
-def ARMSyncBarrierMCR : SDNode<"ARMISD::SYNCBARRIER", SDT_ARMMEMBARRIERMCR,
+def ARMMemBarrierMCR : SDNode<"ARMISD::MEMBARRIER_MCR", SDT_ARMMEMBARRIER,
[SDNPHasChain]>;
def ARMrbit : SDNode<"ARMISD::RBIT", SDTIntUnaryOp>;
// A list of registers separated by comma. Used by load/store multiple.
def reglist : Operand<i32> {
+ string EncoderMethod = "getRegisterListOpValue";
let PrintMethod = "printRegisterList";
}
}
def neon_vcvt_imm32 : Operand<i32> {
- string EncoderMethod = "getNEONVcvtImm32";
+ string EncoderMethod = "getNEONVcvtImm32OpValue";
}
// rot_imm: An integer that encodes a rotate amount. Must be 8, 16, or 24.
//
def addrmode_imm12 : Operand<i32>,
ComplexPattern<i32, 2, "SelectAddrModeImm12", []> {
+ // 12-bit immediate operand. Note that instructions using this encode
+ // #0 and #-0 differently. We flag #-0 as the magic value INT32_MIN. All other
+ // immediate values are as normal.
string EncoderMethod = "getAddrModeImm12OpValue";
let PrintMethod = "printAddrModeImm12Operand";
let MIOperandInfo = (ops GPR:$addr, i32imm);
}
+def ARMMemMode5AsmOperand : AsmOperandClass {
+ let Name = "MemMode5";
+ let SuperClasses = [];
+}
+
// addrmode5 := reg +/- imm8*4
//
def addrmode5 : Operand<i32>,
ComplexPattern<i32, 2, "SelectAddrMode5", []> {
let PrintMethod = "printAddrMode5Operand";
let MIOperandInfo = (ops GPR:$base, i32imm);
+ let ParserMatchClass = ARMMemMode5AsmOperand;
}
// addrmode6 := reg with optional writeback
// The neg_zero operand translates -0 to -1, -1 to -2, ..., etc.
multiclass APreLoad<bit data, bit read, string opc> {
- def i : AXI<(outs), (ins GPR:$base, neg_zero:$imm), MiscFrm, NoItinerary,
- !strconcat(opc, "\t[$base, $imm]"), []> {
+ def i12 : AXI<(outs), (ins addrmode_imm12:$addr), MiscFrm, NoItinerary,
+ !strconcat(opc, "\t$addr"), []> {
+ bits<4> Rt;
+ bits<17> addr;
let Inst{31-26} = 0b111101;
let Inst{25} = 0; // 0 for immediate form
let Inst{24} = data;
+ let Inst{23} = addr{12}; // U (add = ('U' == 1))
let Inst{22} = read;
let Inst{21-20} = 0b01;
+ let Inst{19-16} = addr{16-13}; // Rn
+ let Inst{15-12} = Rt;
+ let Inst{11-0} = addr{11-0}; // imm12
}
- def r : AXI<(outs), (ins addrmode2:$addr), MiscFrm, NoItinerary,
- !strconcat(opc, "\t$addr"), []> {
+ def rs : AXI<(outs), (ins ldst_so_reg:$shift), MiscFrm, NoItinerary,
+ !strconcat(opc, "\t$shift"), []> {
+ bits<4> Rt;
+ bits<17> shift;
let Inst{31-26} = 0b111101;
let Inst{25} = 1; // 1 for register form
let Inst{24} = data;
+ let Inst{23} = shift{12}; // U (add = ('U' == 1))
let Inst{22} = read;
let Inst{21-20} = 0b01;
- let Inst{4} = 0;
+ let Inst{19-16} = shift{16-13}; // Rn
+ let Inst{11-0} = shift{11-0};
}
}
// classes (AXI1, et.al.) and so have encoding information and such,
// which is suboptimal. Once the rest of the code emitter (including
// JIT) is MC-ized we should look at refactoring these into true
-// pseudos.
+// pseudos. As is, the encoding information ends up being ignored,
+// as these instructions are lowered to individual MC-insts.
let isNotDuplicable = 1 in {
def PICADD : AXI1<0b0100, (outs GPR:$dst), (ins GPR:$a, pclabel:$cp, pred:$p),
Pseudo, IIC_iALUr, "",
Requires<[IsARM, HasV4T]> {
bits<4> dst;
let Inst{31-4} = 0b1110000100101111111111110001;
- let Inst{3-0} = dst;
+ let Inst{3-0} = dst;
}
// ARMV4 only
RegConstraint<"$false = $Rd">, UnaryDP {
bits<4> Rd;
bits<4> Rm;
-
- let Inst{11-4} = 0b00000000;
let Inst{25} = 0;
- let Inst{3-0} = Rm;
+ let Inst{20} = 0;
let Inst{15-12} = Rd;
let Inst{11-4} = 0b00000000;
- let Inst{25} = 0;
+ let Inst{3-0} = Rm;
}
-def MOVCCs : AI1<0b1101, (outs GPR:$dst),
- (ins GPR:$false, so_reg:$true), DPSoRegFrm, IIC_iCMOVsr,
- "mov", "\t$dst, $true",
- [/*(set GPR:$dst, (ARMcmov GPR:$false, so_reg:$true, imm:$cc, CCR:$ccr))*/]>,
- RegConstraint<"$false = $dst">, UnaryDP {
+def MOVCCs : AI1<0b1101, (outs GPR:$Rd),
+ (ins GPR:$false, so_reg:$shift), DPSoRegFrm, IIC_iCMOVsr,
+ "mov", "\t$Rd, $shift",
+ [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_reg:$shift, imm:$cc, CCR:$ccr))*/]>,
+ RegConstraint<"$false = $Rd">, UnaryDP {
+ bits<4> Rd;
+ bits<4> Rn;
+ bits<12> shift;
let Inst{25} = 0;
+ let Inst{20} = 0;
+ let Inst{19-16} = Rn;
+ let Inst{15-12} = Rd;
+ let Inst{11-0} = shift;
}
-def MOVCCi16 : AI1<0b1000, (outs GPR:$dst), (ins GPR:$false, i32imm:$src),
+def MOVCCi16 : AI1<0b1000, (outs GPR:$Rd), (ins GPR:$false, i32imm:$imm),
DPFrm, IIC_iMOVi,
- "movw", "\t$dst, $src",
+ "movw", "\t$Rd, $imm",
[]>,
- RegConstraint<"$false = $dst">, Requires<[IsARM, HasV6T2]>,
+ RegConstraint<"$false = $Rd">, Requires<[IsARM, HasV6T2]>,
UnaryDP {
- let Inst{20} = 0;
+ bits<4> Rd;
+ bits<16> imm;
let Inst{25} = 1;
+ let Inst{20} = 0;
+ let Inst{19-16} = imm{15-12};
+ let Inst{15-12} = Rd;
+ let Inst{11-0} = imm{11-0};
}
-def MOVCCi : AI1<0b1101, (outs GPR:$dst),
- (ins GPR:$false, so_imm:$true), DPFrm, IIC_iCMOVi,
- "mov", "\t$dst, $true",
- [/*(set GPR:$dst, (ARMcmov GPR:$false, so_imm:$true, imm:$cc, CCR:$ccr))*/]>,
- RegConstraint<"$false = $dst">, UnaryDP {
+def MOVCCi : AI1<0b1101, (outs GPR:$Rd),
+ (ins GPR:$false, so_imm:$imm), DPFrm, IIC_iCMOVi,
+ "mov", "\t$Rd, $imm",
+ [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_imm:$imm, imm:$cc, CCR:$ccr))*/]>,
+ RegConstraint<"$false = $Rd">, UnaryDP {
+ bits<4> Rd;
+ bits<12> imm;
let Inst{25} = 1;
+ let Inst{20} = 0;
+ let Inst{19-16} = 0b0000;
+ let Inst{15-12} = Rd;
+ let Inst{11-0} = imm;
}
} // neverHasSideEffects
// Atomic operations intrinsics
//
+def memb_opt : Operand<i32> {
+ let PrintMethod = "printMemBOption";
+}
+
// memory barriers protect the atomic sequences
let hasSideEffects = 1 in {
-def DMBsy : AInoP<(outs), (ins), MiscFrm, NoItinerary, "dmb", "",
- [(ARMMemBarrier)]>, Requires<[IsARM, HasDB]> {
+def DMB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary,
+ "dmb", "\t$opt", [(ARMMemBarrier (i32 imm:$opt))]>,
+ Requires<[IsARM, HasDB]> {
+ bits<4> opt;
let Inst{31-4} = 0xf57ff05;
- // FIXME: add support for options other than a full system DMB
- // See DMB disassembly-only variants below.
- let Inst{3-0} = 0b1111;
-}
-
-def DSBsy : AInoP<(outs), (ins), MiscFrm, NoItinerary, "dsb", "",
- [(ARMSyncBarrier)]>, Requires<[IsARM, HasDB]> {
- let Inst{31-4} = 0xf57ff04;
- // FIXME: add support for options other than a full system DSB
- // See DSB disassembly-only variants below.
- let Inst{3-0} = 0b1111;
+ let Inst{3-0} = opt;
}
def DMB_MCR : AInoP<(outs), (ins GPR:$zero), MiscFrm, NoItinerary,
"mcr", "\tp15, 0, $zero, c7, c10, 5",
[(ARMMemBarrierMCR GPR:$zero)]>,
Requires<[IsARM, HasV6]> {
- // FIXME: add support for options other than a full system DMB
- // FIXME: add encoding
-}
-
-def DSB_MCR : AInoP<(outs), (ins GPR:$zero), MiscFrm, NoItinerary,
- "mcr", "\tp15, 0, $zero, c7, c10, 4",
- [(ARMSyncBarrierMCR GPR:$zero)]>,
- Requires<[IsARM, HasV6]> {
- // FIXME: add support for options other than a full system DSB
// FIXME: add encoding
}
}
-// Memory Barrier Operations Variants -- for disassembly only
-
-def memb_opt : Operand<i32> {
- let PrintMethod = "printMemBOption";
-}
-
-class AMBI<bits<4> op7_4, string opc>
- : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary, opc, "\t$opt",
- [/* For disassembly only; pattern left blank */]>,
- Requires<[IsARM, HasDB]> {
- let Inst{31-8} = 0xf57ff0;
- let Inst{7-4} = op7_4;
+def DSB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary,
+ "dsb", "\t$opt",
+ [/* For disassembly only; pattern left blank */]>,
+ Requires<[IsARM, HasDB]> {
+ bits<4> opt;
+ let Inst{31-4} = 0xf57ff04;
+ let Inst{3-0} = opt;
}
-// These DMB variants are for disassembly only.
-def DMBvar : AMBI<0b0101, "dmb">;
-
-// These DSB variants are for disassembly only.
-def DSBvar : AMBI<0b0100, "dsb">;
-
// ISB has only full system option -- for disassembly only
-def ISBsy : AInoP<(outs), (ins), MiscFrm, NoItinerary, "isb", "", []>,
- Requires<[IsARM, HasDB]> {
+def ISB : AInoP<(outs), (ins), MiscFrm, NoItinerary, "isb", "", []>,
+ Requires<[IsARM, HasDB]> {
let Inst{31-4} = 0xf57ff06;
let Inst{3-0} = 0b1111;
}
}
let mayLoad = 1 in {
-def LDREXB : AIldrex<0b10, (outs GPR:$dest), (ins GPR:$ptr), NoItinerary,
- "ldrexb", "\t$dest, [$ptr]",
+def LDREXB : AIldrex<0b10, (outs GPR:$Rt), (ins GPR:$Rn), NoItinerary,
+ "ldrexb", "\t$Rt, [$Rn]",
[]>;
-def LDREXH : AIldrex<0b11, (outs GPR:$dest), (ins GPR:$ptr), NoItinerary,
- "ldrexh", "\t$dest, [$ptr]",
+def LDREXH : AIldrex<0b11, (outs GPR:$Rt), (ins GPR:$Rn), NoItinerary,
+ "ldrexh", "\t$Rt, [$Rn]",
[]>;
-def LDREX : AIldrex<0b00, (outs GPR:$dest), (ins GPR:$ptr), NoItinerary,
- "ldrex", "\t$dest, [$ptr]",
+def LDREX : AIldrex<0b00, (outs GPR:$Rt), (ins GPR:$Rn), NoItinerary,
+ "ldrex", "\t$Rt, [$Rn]",
[]>;
-def LDREXD : AIldrex<0b01, (outs GPR:$dest, GPR:$dest2), (ins GPR:$ptr),
+def LDREXD : AIldrex<0b01, (outs GPR:$Rt, GPR:$Rt2), (ins GPR:$Rn),
NoItinerary,
- "ldrexd", "\t$dest, $dest2, [$ptr]",
+ "ldrexd", "\t$Rt, $Rt2, [$Rn]",
[]>;
}
-let mayStore = 1, Constraints = "@earlyclobber $success" in {
-def STREXB : AIstrex<0b10, (outs GPR:$success), (ins GPR:$src, GPR:$ptr),
+let mayStore = 1, Constraints = "@earlyclobber $Rd" in {
+def STREXB : AIstrex<0b10, (outs GPR:$Rd), (ins GPR:$src, GPR:$Rn),
NoItinerary,
- "strexb", "\t$success, $src, [$ptr]",
+ "strexb", "\t$Rd, $src, [$Rn]",
[]>;
-def STREXH : AIstrex<0b11, (outs GPR:$success), (ins GPR:$src, GPR:$ptr),
+def STREXH : AIstrex<0b11, (outs GPR:$Rd), (ins GPR:$Rt, GPR:$Rn),
NoItinerary,
- "strexh", "\t$success, $src, [$ptr]",
+ "strexh", "\t$Rd, $Rt, [$Rn]",
[]>;
-def STREX : AIstrex<0b00, (outs GPR:$success), (ins GPR:$src, GPR:$ptr),
+def STREX : AIstrex<0b00, (outs GPR:$Rd), (ins GPR:$Rt, GPR:$Rn),
NoItinerary,
- "strex", "\t$success, $src, [$ptr]",
+ "strex", "\t$Rd, $Rt, [$Rn]",
[]>;
-def STREXD : AIstrex<0b01, (outs GPR:$success),
- (ins GPR:$src, GPR:$src2, GPR:$ptr),
+def STREXD : AIstrex<0b01, (outs GPR:$Rd),
+ (ins GPR:$Rt, GPR:$Rt2, GPR:$Rn),
NoItinerary,
- "strexd", "\t$success, $src, $src2, [$ptr]",
+ "strexd", "\t$Rd, $Rt, $Rt2, [$Rn]",
[]>;
}
def CLREX : AXI<(outs), (ins), MiscFrm, NoItinerary, "clrex",
[/* For disassembly only; pattern left blank */]>,
Requires<[IsARM, HasV7]> {
- let Inst{31-20} = 0xf57;
- let Inst{7-4} = 0b0001;
+ let Inst{31-0} = 0b11110101011111111111000000011111;
}
// SWP/SWPB are deprecated in V6/V7 and for disassembly only.
let mayLoad = 1 in {
-def SWP : AI<(outs GPR:$dst), (ins GPR:$src, GPR:$ptr), LdStExFrm, NoItinerary,
- "swp", "\t$dst, $src, [$ptr]",
- [/* For disassembly only; pattern left blank */]> {
- let Inst{27-23} = 0b00010;
- let Inst{22} = 0; // B = 0
- let Inst{21-20} = 0b00;
- let Inst{7-4} = 0b1001;
-}
-
-def SWPB : AI<(outs GPR:$dst), (ins GPR:$src, GPR:$ptr), LdStExFrm, NoItinerary,
- "swpb", "\t$dst, $src, [$ptr]",
- [/* For disassembly only; pattern left blank */]> {
- let Inst{27-23} = 0b00010;
- let Inst{22} = 1; // B = 1
- let Inst{21-20} = 0b00;
- let Inst{7-4} = 0b1001;
-}
+def SWP : AIswp<0, (outs GPR:$Rt), (ins GPR:$Rt2, GPR:$Rn), "swp",
+ [/* For disassembly only; pattern left blank */]>;
+def SWPB : AIswp<1, (outs GPR:$Rt), (ins GPR:$Rt2, GPR:$Rn), "swpb",
+ [/* For disassembly only; pattern left blank */]>;
}
//===----------------------------------------------------------------------===//
//
// __aeabi_read_tp preserves the registers r1-r3.
+// FIXME: This needs to be a pseudo of some sort so that we can get the
+// encoding right, complete with fixup for the aeabi_read_tp function.
let isCall = 1,
Defs = [R0, R12, LR, CPSR] in {
def TPsoft : ABXI<0b1011, (outs), (ins), IIC_Br,
// 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.
+//
+// These are pseudo-instructions and are lowered to individual MC-insts, so
+// no encoding information is necessary.
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,
}
// eh.sjlj.dispatchsetup pseudo-instruction.
-// This pseudo is usef for ARM, Thumb1 and Thumb2. Any differences are
+// This pseudo is used 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
// Large immediate handling.
// Two piece so_imms.
-// 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,
- "mov", "\t$dst, $src",
- [(set GPR:$dst, so_imm2part:$src)]>,
+def MOVi2pieces : PseudoInst<(outs GPR:$dst), (ins so_imm2part:$src),
+ IIC_iMOVix2, "",
+ [(set GPR:$dst, (so_imm2part:$src))]>,
Requires<[IsARM, NoV6T2]>;
def : ARMPat<(or GPR:$LHS, so_imm2part:$RHS),
Requires<[IsARM, IsDarwin]>;
// zextload i1 -> zextload i8
-//def : ARMPat<(zextloadi1 addrmode2:$addr), (LDRB addrmode2:$addr)>;
def : ARMPat<(zextloadi1 addrmode_imm12:$addr), (LDRBi12 addrmode_imm12:$addr)>;
def : ARMPat<(zextloadi1 ldst_so_reg:$addr), (LDRBrs ldst_so_reg:$addr)>;