SDTCisInt<2>]>;
def SDT_ARMEH_SJLJ_Longjmp: SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisInt<1>]>;
-def SDT_ARMEH_SJLJ_DispatchSetup: SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
+def SDT_ARMEH_SJLJ_DispatchSetup: SDTypeProfile<0, 0, []>;
def SDT_ARMMEMBARRIER : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
let EncoderMethod = "getRotImmOpValue";
}
+def ShifterAsmOperand : AsmOperandClass {
+ let Name = "Shifter";
+ let SuperClasses = [];
+}
+
// shift_imm: An integer that encodes a shift amount and the type of shift
// (currently either asr or lsl) using the same encoding used for the
// immediates in so_reg operands.
def shift_imm : Operand<i32> {
let PrintMethod = "printShiftImmOperand";
+ let ParserMatchClass = ShifterAsmOperand;
}
// shifter_operand operands: so_reg and so_imm.
[shl,srl,sra,rotr]> {
let EncoderMethod = "getSORegOpValue";
let PrintMethod = "printSORegOperand";
- let MIOperandInfo = (ops GPR, GPR, i32imm);
+ let MIOperandInfo = (ops GPR, GPR, shift_imm);
}
def shift_so_reg : Operand<i32>, // reg reg imm
ComplexPattern<i32, 3, "SelectShiftShifterOperandReg",
[shl,srl,sra,rotr]> {
let EncoderMethod = "getSORegOpValue";
let PrintMethod = "printSORegOperand";
- let MIOperandInfo = (ops GPR, GPR, i32imm);
+ let MIOperandInfo = (ops GPR, GPR, shift_imm);
}
// so_imm - Match a 32-bit shifter_operand immediate operand, which is an
// Define ARM specific addressing modes.
+def MemMode2AsmOperand : AsmOperandClass {
+ let Name = "MemMode2";
+ let SuperClasses = [];
+ let ParserMethod = "tryParseMemMode2Operand";
+}
+
+def MemMode3AsmOperand : AsmOperandClass {
+ let Name = "MemMode3";
+ let SuperClasses = [];
+ let ParserMethod = "tryParseMemMode3Operand";
+}
// addrmode_imm12 := reg +/- imm12
//
ComplexPattern<i32, 3, "SelectAddrMode2", []> {
let EncoderMethod = "getAddrMode2OpValue";
let PrintMethod = "printAddrMode2Operand";
+ let ParserMatchClass = MemMode2AsmOperand;
let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
}
ComplexPattern<i32, 3, "SelectAddrMode3", []> {
let EncoderMethod = "getAddrMode3OpValue";
let PrintMethod = "printAddrMode3Operand";
+ let ParserMatchClass = MemMode3AsmOperand;
let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
}
let MIOperandInfo = (ops GPR, i32imm);
}
+def MemMode7AsmOperand : AsmOperandClass {
+ let Name = "MemMode7";
+ let SuperClasses = [];
+}
+
+// addrmode7 := reg
+// Used by load/store exclusive instructions. Useful to enable right assembly
+// parsing and printing. Not used for any codegen matching.
+//
+def addrmode7 : Operand<i32> {
+ let PrintMethod = "printAddrMode7Operand";
+ let MIOperandInfo = (ops GPR);
+ let ParserMatchClass = MemMode7AsmOperand;
+}
+
def nohash_imm : Operand<i32> {
let PrintMethod = "printNoHashImmediate";
}
let Inst{19-16} = Rn;
}
}
+}
+
// Carry setting variants
-let isCodeGenOnly = 1, Defs = [CPSR] in {
-multiclass AI1_adde_sube_s_irs<bits<4> opcod, string opc, PatFrag opnode,
- bit Commutable = 0> {
- def Sri : AXI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
- DPFrm, IIC_iALUi, !strconcat(opc, "\t$Rd, $Rn, $imm"),
- [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>,
- Requires<[IsARM]> {
- bits<4> Rd;
- bits<4> Rn;
- bits<12> imm;
- let Inst{15-12} = Rd;
- let Inst{19-16} = Rn;
- let Inst{11-0} = imm;
- let Inst{20} = 1;
- let Inst{25} = 1;
- }
- def Srr : AXI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
- DPFrm, IIC_iALUr, !strconcat(opc, "\t$Rd, $Rn, $Rm"),
- [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]>,
- Requires<[IsARM]> {
- bits<4> Rd;
- bits<4> Rn;
- bits<4> Rm;
- let Inst{11-4} = 0b00000000;
+// NOTE: CPSR def omitted because it will be handled by the custom inserter.
+let usesCustomInserter = 1 in {
+multiclass AI1_adde_sube_s_irs<PatFrag opnode, bit Commutable = 0> {
+ def Sri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
+ Size4Bytes, IIC_iALUi,
+ [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>;
+ def Srr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
+ Size4Bytes, IIC_iALUr,
+ [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]> {
let isCommutable = Commutable;
- let Inst{3-0} = Rm;
- let Inst{15-12} = Rd;
- let Inst{19-16} = Rn;
- let Inst{20} = 1;
- let Inst{25} = 0;
- }
- def Srs : AXI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
- DPSoRegFrm, IIC_iALUsr, !strconcat(opc, "\t$Rd, $Rn, $shift"),
- [(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]>,
- Requires<[IsARM]> {
- bits<4> Rd;
- bits<4> Rn;
- bits<12> shift;
- let Inst{11-0} = shift;
- let Inst{15-12} = Rd;
- let Inst{19-16} = Rn;
- let Inst{20} = 1;
- let Inst{25} = 0;
}
-}
+ def Srs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
+ Size4Bytes, IIC_iALUsr,
+ [(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]>;
}
}
[(set GPR:$Rt, (opnode ldst_so_reg:$shift))]> {
bits<4> Rt;
bits<17> shift;
+ let shift{4} = 0; // Inst{4} = 0
let Inst{23} = shift{12}; // U (add = ('U' == 1))
let Inst{19-16} = shift{16-13}; // Rn
let Inst{15-12} = Rt;
[(opnode GPR:$Rt, ldst_so_reg:$shift)]> {
bits<4> Rt;
bits<17> shift;
+ let shift{4} = 0; // Inst{4} = 0
let Inst{23} = shift{12}; // U (add = ('U' == 1))
let Inst{19-16} = shift{16-13}; // Rn
let Inst{15-12} = Rt;
// The 'adr' mnemonic encodes differently if the label is before or after
// the instruction. The {24-21} opcode bits are set by the fixup, as we don't
// know until then which form of the instruction will be used.
-def ADR : AI1<0, (outs GPR:$Rd), (ins adrlabel:$label),
+def ADR : AI1<{0,?,?,0}, (outs GPR:$Rd), (ins adrlabel:$label),
MiscFrm, IIC_iALUi, "adr", "\t$Rd, #$label", []> {
bits<4> Rd;
bits<12> label;
}
}
+// BLX (immediate) -- for disassembly only
+def BLXi : AXI<(outs), (ins br_target:$target), BrMiscFrm, NoItinerary,
+ "blx\t$target", [/* pattern left blank */]>,
+ Requires<[IsARM, HasV5T]> {
+ let Inst{31-25} = 0b1111101;
+ bits<25> target;
+ let Inst{23-0} = target{24-1};
+ let Inst{24} = target{0};
+}
+
// Branch and Exchange Jazelle -- for disassembly only
def BXJ : ABI<0b0001, (outs), (ins GPR:$func), NoItinerary, "bxj", "\t$func",
[/* For disassembly only; pattern left blank */]> {
[/* For disassembly only; pattern left blank */]> {
let Inst{31-28} = 0b1111;
let Inst{22-20} = 0b110; // W = 1
+ let Inst{19-8} = 0xd05;
+ let Inst{7-5} = 0b000;
}
def SRS : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, i32imm:$mode),
[/* For disassembly only; pattern left blank */]> {
let Inst{31-28} = 0b1111;
let Inst{22-20} = 0b100; // W = 0
+ let Inst{19-8} = 0xd05;
+ let Inst{7-5} = 0b000;
}
// Return From Exception is a system instruction -- for disassembly only
[/* For disassembly only; pattern left blank */]> {
let Inst{31-28} = 0b1111;
let Inst{22-20} = 0b011; // W = 1
+ let Inst{15-0} = 0x0a00;
}
def RFE : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, GPR:$base),
[/* For disassembly only; pattern left blank */]> {
let Inst{31-28} = 0b1111;
let Inst{22-20} = 0b001; // W = 0
+ let Inst{15-0} = 0x0a00;
}
} // isCodeGenOnly = 1
IIC_iLoad_bh_r, "ldrsb", "\t$Rt, $addr",
[(set GPR:$Rt, (sextloadi8 addrmode3:$addr))]>;
-let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1,
- isCodeGenOnly = 1 in { // $dst2 doesn't exist in asmstring?
-// FIXME: $dst2 isn't in the asm string as it's implied by $Rd (dst2 = Rd+1)
-// how to represent that such that tblgen is happy and we don't
-// mark this codegen only?
+let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in {
// Load doubleword
def LDRD : AI3ld<0b1101, 0, (outs GPR:$Rd, GPR:$dst2),
(ins addrmode3:$addr), LdMiscFrm,
- IIC_iLoad_d_r, "ldrd", "\t$Rd, $addr",
+ IIC_iLoad_d_r, "ldrd", "\t$Rd, $dst2, $addr",
[]>, Requires<[IsARM, HasV5TE]>;
}
let Inst{23} = addr{12};
let Inst{19-16} = addr{17-14};
let Inst{11-0} = addr{11-0};
+ let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";
}
def _POST : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),
(ins GPR:$Rn, am2offset:$offset),
defm LDRH : AI3_ldridx<0b1011, 1, "ldrh", IIC_iLoad_bh_ru>;
defm LDRSH : AI3_ldridx<0b1111, 1, "ldrsh", IIC_iLoad_bh_ru>;
defm LDRSB : AI3_ldridx<0b1101, 1, "ldrsb", IIC_iLoad_bh_ru>;
-let hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in
-defm LDRD : AI3_ldridx<0b1101, 0, "ldrd", IIC_iLoad_d_ru>;
+let hasExtraDefRegAllocReq = 1 in {
+def LDRD_PRE : AI3ldstidx<0b1101, 0, 1, 1, (outs GPR:$Rt, GPR:$Rt2, GPR:$Rn_wb),
+ (ins addrmode3:$addr), IndexModePre,
+ LdMiscFrm, IIC_iLoad_d_ru,
+ "ldrd", "\t$Rt, $Rt2, $addr!",
+ "$addr.base = $Rn_wb", []> {
+ bits<14> addr;
+ let Inst{23} = addr{8}; // U bit
+ let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm
+ let Inst{19-16} = addr{12-9}; // Rn
+ let Inst{11-8} = addr{7-4}; // imm7_4/zero
+ let Inst{3-0} = addr{3-0}; // imm3_0/Rm
+}
+def LDRD_POST: AI3ldstidx<0b1101, 0, 1, 0, (outs GPR:$Rt, GPR:$Rt2, GPR:$Rn_wb),
+ (ins GPR:$Rn, am3offset:$offset), IndexModePost,
+ LdMiscFrm, IIC_iLoad_d_ru,
+ "ldrd", "\t$Rt, $Rt2, [$Rn], $offset",
+ "$Rn = $Rn_wb", []> {
+ bits<10> offset;
+ bits<4> Rn;
+ let Inst{23} = offset{8}; // U bit
+ let Inst{22} = offset{9}; // 1 == imm8, 0 == Rm
+ let Inst{19-16} = Rn;
+ let Inst{11-8} = offset{7-4}; // imm7_4/zero
+ let Inst{3-0} = offset{3-0}; // imm3_0/Rm
+}
+} // hasExtraDefRegAllocReq = 1
} // mayLoad = 1, neverHasSideEffects = 1
// LDRT, LDRBT, LDRSBT, LDRHT, LDRSHT are for disassembly only.
let mayLoad = 1, neverHasSideEffects = 1 in {
-def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$dst, GPR:$base_wb),
- (ins GPR:$base, am2offset:$offset), IndexModeNone,
- LdFrm, IIC_iLoad_ru,
- "ldrt", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
+def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb),
+ (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_ru,
+ "ldrt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
+ // {17-14} Rn
+ // {13} 1 == Rm, 0 == imm12
+ // {12} isAdd
+ // {11-0} imm12/Rm
+ bits<18> addr;
+ let Inst{25} = addr{13};
+ let Inst{23} = addr{12};
let Inst{21} = 1; // overwrite
-}
-def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$dst, GPR:$base_wb),
- (ins GPR:$base, am2offset:$offset), IndexModeNone,
- LdFrm, IIC_iLoad_bh_ru,
- "ldrbt", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
+ let Inst{19-16} = addr{17-14};
+ let Inst{11-0} = addr{11-0};
+ let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";
+}
+def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),
+ (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_bh_ru,
+ "ldrbt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
+ // {17-14} Rn
+ // {13} 1 == Rm, 0 == imm12
+ // {12} isAdd
+ // {11-0} imm12/Rm
+ bits<18> addr;
+ let Inst{25} = addr{13};
+ let Inst{23} = addr{12};
let Inst{21} = 1; // overwrite
+ let Inst{19-16} = addr{17-14};
+ let Inst{11-0} = addr{11-0};
+ let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";
}
-def LDRSBT : AI3ldstidx<0b1101, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb),
- (ins GPR:$base, am3offset:$offset), IndexModePost,
- LdMiscFrm, IIC_iLoad_bh_ru,
- "ldrsbt", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
+def LDRSBT : AI3ldstidxT<0b1101, 1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),
+ (ins addrmode3:$addr), IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru,
+ "ldrsbt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
let Inst{21} = 1; // overwrite
}
-def LDRHT : AI3ldstidx<0b1011, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb),
- (ins GPR:$base, am3offset:$offset), IndexModePost,
- LdMiscFrm, IIC_iLoad_bh_ru,
- "ldrht", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
+def LDRHT : AI3ldstidxT<0b1011, 1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),
+ (ins addrmode3:$addr), IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru,
+ "ldrht", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
let Inst{21} = 1; // overwrite
}
-def LDRSHT : AI3ldstidx<0b1111, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb),
- (ins GPR:$base, am3offset:$offset), IndexModePost,
- LdMiscFrm, IIC_iLoad_bh_ru,
- "ldrsht", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
+def LDRSHT : AI3ldstidxT<0b1111, 1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),
+ (ins addrmode3:$addr), IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru,
+ "ldrsht", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
let Inst{21} = 1; // overwrite
}
}
[(truncstorei16 GPR:$Rt, addrmode3:$addr)]>;
// Store doubleword
-let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1,
- isCodeGenOnly = 1 in // $src2 doesn't exist in asm string
-def STRD : AI3str<0b1111, (outs), (ins GPR:$src1, GPR:$src2, addrmode3:$addr),
+let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in
+def STRD : AI3str<0b1111, (outs), (ins GPR:$Rt, GPR:$src2, addrmode3:$addr),
StMiscFrm, IIC_iStore_d_r,
- "strd", "\t$src1, $addr", []>, Requires<[IsARM, HasV5TE]>;
+ "strd", "\t$Rt, $src2, $addr", []>, Requires<[IsARM, HasV5TE]>;
// Indexed stores
def STR_PRE : AI2stridx<0, 1, (outs GPR:$Rn_wb),
GPR:$Rn, am3offset:$offset))]>;
// For disassembly only
+let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in {
def STRD_PRE : AI3stdpr<(outs GPR:$base_wb),
(ins GPR:$src1, GPR:$src2, GPR:$base, am3offset:$offset),
StMiscFrm, IIC_iStore_d_ru,
StMiscFrm, IIC_iStore_d_ru,
"strd", "\t$src1, $src2, [$base], $offset",
"$base = $base_wb", []>;
+} // mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1
// STRT, STRBT, and STRHT are for disassembly only.
-def STRT : AI2stridx<0, 0, (outs GPR:$Rn_wb),
- (ins GPR:$Rt, GPR:$Rn,am2offset:$offset),
- IndexModeNone, StFrm, IIC_iStore_ru,
- "strt", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb",
- [/* For disassembly only; pattern left blank */]> {
+def STRT : AI2stridxT<0, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode2:$addr),
+ IndexModePost, StFrm, IIC_iStore_ru,
+ "strt", "\t$Rt, $addr", "$addr.base = $Rn_wb",
+ [/* For disassembly only; pattern left blank */]> {
let Inst{21} = 1; // overwrite
+ let AsmMatchConverter = "CvtStWriteBackRegAddrMode2";
}
-def STRBT : AI2stridx<1, 0, (outs GPR:$Rn_wb),
- (ins GPR:$Rt, GPR:$Rn, am2offset:$offset),
- IndexModeNone, StFrm, IIC_iStore_bh_ru,
- "strbt", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb",
- [/* For disassembly only; pattern left blank */]> {
+def STRBT : AI2stridxT<1, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode2:$addr),
+ IndexModePost, StFrm, IIC_iStore_bh_ru,
+ "strbt", "\t$Rt, $addr", "$addr.base = $Rn_wb",
+ [/* For disassembly only; pattern left blank */]> {
let Inst{21} = 1; // overwrite
+ let AsmMatchConverter = "CvtStWriteBackRegAddrMode2";
}
-def STRHT: AI3sthpo<(outs GPR:$base_wb),
- (ins GPR:$src, GPR:$base,am3offset:$offset),
+def STRHT: AI3sthpo<(outs GPR:$base_wb), (ins GPR:$Rt, addrmode3:$addr),
StMiscFrm, IIC_iStore_bh_ru,
- "strht", "\t$src, [$base], $offset", "$base = $base_wb",
+ "strht", "\t$Rt, $addr", "$addr.base = $base_wb",
[/* For disassembly only; pattern left blank */]> {
let Inst{21} = 1; // overwrite
+ let AsmMatchConverter = "CvtStWriteBackRegAddrMode3";
}
//===----------------------------------------------------------------------===//
bits<4> Rd;
bits<4> Rm;
+ let Inst{19-16} = 0b0000;
let Inst{11-4} = 0b00000000;
let Inst{25} = 0;
let Inst{3-0} = Rm;
bits<4> Rd;
bits<12> src;
let Inst{15-12} = Rd;
+ let Inst{19-16} = 0b0000;
let Inst{11-0} = src;
let Inst{25} = 0;
}
BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>>;
// ADC and SUBC with 's' bit set.
-defm ADCS : AI1_adde_sube_s_irs<0b0101, "adcs",
- BinOpFrag<(adde_live_carry node:$LHS, node:$RHS)>, 1>;
-defm SBCS : AI1_adde_sube_s_irs<0b0110, "sbcs",
- BinOpFrag<(sube_live_carry node:$LHS, node:$RHS) >>;
+let usesCustomInserter = 1 in {
+defm ADCS : AI1_adde_sube_s_irs<
+ BinOpFrag<(adde_live_carry node:$LHS, node:$RHS)>, 1>;
+defm SBCS : AI1_adde_sube_s_irs<
+ BinOpFrag<(sube_live_carry node:$LHS, node:$RHS) >>;
+}
def RSBri : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
IIC_iALUi, "rsb", "\t$Rd, $Rn, $imm",
}
// RSB with 's' bit set.
-let isCodeGenOnly = 1, Defs = [CPSR] in {
-def RSBSri : AI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
- IIC_iALUi, "rsbs", "\t$Rd, $Rn, $imm",
- [(set GPR:$Rd, (subc so_imm:$imm, GPR:$Rn))]> {
- bits<4> Rd;
- bits<4> Rn;
- bits<12> imm;
- let Inst{25} = 1;
- let Inst{20} = 1;
- let Inst{15-12} = Rd;
- let Inst{19-16} = Rn;
- let Inst{11-0} = imm;
-}
-def RSBSrr : AI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm,
- IIC_iALUr, "rsbs", "\t$Rd, $Rn, $Rm",
- [/* For disassembly only; pattern left blank */]> {
- bits<4> Rd;
- bits<4> Rn;
- bits<4> Rm;
- let Inst{11-4} = 0b00000000;
- let Inst{25} = 0;
- let Inst{20} = 1;
- let Inst{3-0} = Rm;
- let Inst{15-12} = Rd;
- let Inst{19-16} = Rn;
-}
-def RSBSrs : AI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
- DPSoRegFrm, IIC_iALUsr, "rsbs", "\t$Rd, $Rn, $shift",
- [(set GPR:$Rd, (subc so_reg:$shift, GPR:$Rn))]> {
- bits<4> Rd;
- bits<4> Rn;
- bits<12> shift;
- let Inst{25} = 0;
- let Inst{20} = 1;
- let Inst{11-0} = shift;
- let Inst{15-12} = Rd;
- let Inst{19-16} = Rn;
-}
+// NOTE: CPSR def omitted because it will be handled by the custom inserter.
+let usesCustomInserter = 1 in {
+def RSBSri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
+ Size4Bytes, IIC_iALUi,
+ [(set GPR:$Rd, (subc so_imm:$imm, GPR:$Rn))]>;
+def RSBSrr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
+ Size4Bytes, IIC_iALUr,
+ [/* For disassembly only; pattern left blank */]>;
+def RSBSrs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
+ Size4Bytes, IIC_iALUsr,
+ [(set GPR:$Rd, (subc so_reg:$shift, GPR:$Rn))]>;
}
let Uses = [CPSR] in {
}
}
-// FIXME: Allow these to be predicated.
-let isCodeGenOnly = 1, Defs = [CPSR], Uses = [CPSR] in {
-def RSCSri : AXI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
- DPFrm, IIC_iALUi, "rscs\t$Rd, $Rn, $imm",
- [(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>,
- Requires<[IsARM]> {
- bits<4> Rd;
- bits<4> Rn;
- bits<12> imm;
- let Inst{25} = 1;
- let Inst{20} = 1;
- let Inst{15-12} = Rd;
- let Inst{19-16} = Rn;
- let Inst{11-0} = imm;
-}
-def RSCSrs : AXI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
- DPSoRegFrm, IIC_iALUsr, "rscs\t$Rd, $Rn, $shift",
- [(set GPR:$Rd, (sube_dead_carry so_reg:$shift, GPR:$Rn))]>,
- Requires<[IsARM]> {
- bits<4> Rd;
- bits<4> Rn;
- bits<12> shift;
- let Inst{25} = 0;
- let Inst{20} = 1;
- let Inst{11-0} = shift;
- let Inst{15-12} = Rd;
- let Inst{19-16} = Rn;
-}
+// NOTE: CPSR def omitted because it will be handled by the custom inserter.
+let usesCustomInserter = 1, Uses = [CPSR] in {
+def RSCSri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
+ Size4Bytes, IIC_iALUi,
+ [(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>;
+def RSCSrs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
+ Size4Bytes, IIC_iALUsr,
+ [(set GPR:$Rd, (sube_dead_carry so_reg:$shift, GPR:$Rn))]>;
}
// (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
def MUL : AsMul1I32<0b0000000, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
IIC_iMUL32, "mul", "\t$Rd, $Rn, $Rm",
[(set GPR:$Rd, (mul GPR:$Rn, GPR:$Rm))]>,
- Requires<[IsARM, HasV6]>;
+ Requires<[IsARM, HasV6]> {
+ let Inst{15-12} = 0b0000;
+}
}
let Constraints = "@earlyclobber $Rd" in
IIC_iUNAr, "revsh", "\t$Rd, $Rm",
[(set GPR:$Rd,
(sext_inreg
- (or (srl (and GPR:$Rm, 0xFF00), (i32 8)),
+ (or (srl GPR:$Rm, (i32 8)),
(shl GPR:$Rm, (i32 8))), i16))]>,
Requires<[IsARM, HasV6]>;
+def : ARMV6Pat<(sext_inreg (or (srl (and GPR:$Rm, 0xFF00), (i32 8)),
+ (shl GPR:$Rm, (i32 8))), i16),
+ (REVSH GPR:$Rm)>;
+
+// Need the AddedComplexity or else MOVs + REV would be chosen.
+let AddedComplexity = 5 in
+def : ARMV6Pat<(sra (bswap GPR:$Rm), (i32 16)), (REVSH GPR:$Rm)>;
+
def lsl_shift_imm : SDNodeXForm<imm, [{
unsigned Sh = ARM_AM::getSORegOpc(ARM_AM::lsl, N->getZExtValue());
return CurDAG->getTargetConstant(Sh, MVT::i32);
}
let mayLoad = 1 in {
-def LDREXB : AIldrex<0b10, (outs GPR:$Rt), (ins GPR:$Rn), NoItinerary,
- "ldrexb", "\t$Rt, [$Rn]",
- []>;
-def LDREXH : AIldrex<0b11, (outs GPR:$Rt), (ins GPR:$Rn), NoItinerary,
- "ldrexh", "\t$Rt, [$Rn]",
- []>;
-def LDREX : AIldrex<0b00, (outs GPR:$Rt), (ins GPR:$Rn), NoItinerary,
- "ldrex", "\t$Rt, [$Rn]",
- []>;
-def LDREXD : AIldrex<0b01, (outs GPR:$Rt, GPR:$Rt2), (ins GPR:$Rn),
- NoItinerary,
- "ldrexd", "\t$Rt, $Rt2, [$Rn]",
- []>;
+def LDREXB : AIldrex<0b10, (outs GPR:$Rt), (ins addrmode7:$addr), NoItinerary,
+ "ldrexb", "\t$Rt, $addr", []>;
+def LDREXH : AIldrex<0b11, (outs GPR:$Rt), (ins addrmode7:$addr), NoItinerary,
+ "ldrexh", "\t$Rt, $addr", []>;
+def LDREX : AIldrex<0b00, (outs GPR:$Rt), (ins addrmode7:$addr), NoItinerary,
+ "ldrex", "\t$Rt, $addr", []>;
+def LDREXD : AIldrex<0b01, (outs GPR:$Rt, GPR:$Rt2), (ins addrmode7:$addr),
+ NoItinerary, "ldrexd", "\t$Rt, $Rt2, $addr", []>;
}
let mayStore = 1, Constraints = "@earlyclobber $Rd" in {
-def STREXB : AIstrex<0b10, (outs GPR:$Rd), (ins GPR:$src, GPR:$Rn),
- NoItinerary,
- "strexb", "\t$Rd, $src, [$Rn]",
- []>;
-def STREXH : AIstrex<0b11, (outs GPR:$Rd), (ins GPR:$Rt, GPR:$Rn),
- NoItinerary,
- "strexh", "\t$Rd, $Rt, [$Rn]",
- []>;
-def STREX : AIstrex<0b00, (outs GPR:$Rd), (ins GPR:$Rt, GPR:$Rn),
- NoItinerary,
- "strex", "\t$Rd, $Rt, [$Rn]",
- []>;
+def STREXB : AIstrex<0b10, (outs GPR:$Rd), (ins GPR:$Rt, addrmode7:$addr),
+ NoItinerary, "strexb", "\t$Rd, $Rt, $addr", []>;
+def STREXH : AIstrex<0b11, (outs GPR:$Rd), (ins GPR:$Rt, addrmode7:$addr),
+ NoItinerary, "strexh", "\t$Rd, $Rt, $addr", []>;
+def STREX : AIstrex<0b00, (outs GPR:$Rd), (ins GPR:$Rt, addrmode7:$addr),
+ NoItinerary, "strex", "\t$Rd, $Rt, $addr", []>;
def STREXD : AIstrex<0b01, (outs GPR:$Rd),
- (ins GPR:$Rt, GPR:$Rt2, GPR:$Rn),
- NoItinerary,
- "strexd", "\t$Rd, $Rt, $Rt2, [$Rn]",
- []>;
+ (ins GPR:$Rt, GPR:$Rt2, addrmode7:$addr),
+ NoItinerary, "strexd", "\t$Rd, $Rt, $Rt2, $addr", []>;
}
// Clear-Exclusive is for disassembly only.
let Inst{23-20} = opc1;
}
-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 */]> {
+class ACI<dag oops, dag iops, string opc, string asm,
+ IndexMode im = IndexModeNone>
+ : InoP<oops, iops, AddrModeNone, Size4Bytes, im, 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> {
+multiclass LdStCop<bits<4> op31_28, bit load, dag ops, string opc, string cond>{
def _OFFSET : ACI<(outs),
- (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
- opc, "\tp$cop, cr$CRd, $addr"> {
+ !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops),
+ !strconcat(opc, cond), "\tp$cop, cr$CRd, $addr"> {
let Inst{31-28} = op31_28;
let Inst{24} = 1; // P = 1
let Inst{21} = 0; // W = 0
}
def _PRE : ACI<(outs),
- (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
- opc, "\tp$cop, cr$CRd, $addr!"> {
+ !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops),
+ !strconcat(opc, cond), "\tp$cop, cr$CRd, $addr!", IndexModePre> {
let Inst{31-28} = op31_28;
let Inst{24} = 1; // P = 1
let Inst{21} = 1; // W = 1
}
def _POST : ACI<(outs),
- (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset),
- opc, "\tp$cop, cr$CRd, [$base], $offset"> {
+ !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops),
+ !strconcat(opc, cond), "\tp$cop, cr$CRd, $addr", IndexModePost> {
let Inst{31-28} = op31_28;
let Inst{24} = 0; // P = 0
let Inst{21} = 1; // W = 1
}
def _OPTION : ACI<(outs),
- (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, i32imm:$option),
- opc, "\tp$cop, cr$CRd, [$base], $option"> {
+ !con((ins nohash_imm:$cop,nohash_imm:$CRd,GPR:$base, nohash_imm:$option),
+ ops),
+ !strconcat(opc, cond), "\tp$cop, cr$CRd, [$base], \\{$option\\}"> {
let Inst{31-28} = op31_28;
let Inst{24} = 0; // P = 0
let Inst{23} = 1; // U = 1
}
def L_OFFSET : ACI<(outs),
- (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
- !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr"> {
+ !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops),
+ !strconcat(!strconcat(opc, "l"), cond), "\tp$cop, cr$CRd, $addr"> {
let Inst{31-28} = op31_28;
let Inst{24} = 1; // P = 1
let Inst{21} = 0; // W = 0
}
def L_PRE : ACI<(outs),
- (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
- !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr!"> {
+ !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops),
+ !strconcat(!strconcat(opc, "l"), cond), "\tp$cop, cr$CRd, $addr!",
+ IndexModePre> {
let Inst{31-28} = op31_28;
let Inst{24} = 1; // P = 1
let Inst{21} = 1; // W = 1
}
def L_POST : ACI<(outs),
- (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset),
- !strconcat(opc, "l"), "\tp$cop, cr$CRd, [$base], $offset"> {
+ !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops),
+ !strconcat(!strconcat(opc, "l"), cond), "\tp$cop, cr$CRd, $addr",
+ IndexModePost> {
let Inst{31-28} = op31_28;
let Inst{24} = 0; // P = 0
let Inst{21} = 1; // W = 1
}
def L_OPTION : ACI<(outs),
- (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, nohash_imm:$option),
- !strconcat(opc, "l"), "\tp$cop, cr$CRd, [$base], $option"> {
+ !con((ins nohash_imm:$cop, nohash_imm:$CRd,GPR:$base,nohash_imm:$option),
+ ops),
+ !strconcat(!strconcat(opc, "l"), cond),
+ "\tp$cop, cr$CRd, [$base], \\{$option\\}"> {
let Inst{31-28} = op31_28;
let Inst{24} = 0; // P = 0
let Inst{23} = 1; // U = 1
}
}
-defm LDC : LdStCop<{?,?,?,?}, 1, "ldc">;
-defm LDC2 : LdStCop<0b1111, 1, "ldc2">;
-defm STC : LdStCop<{?,?,?,?}, 0, "stc">;
-defm STC2 : LdStCop<0b1111, 0, "stc2">;
+defm LDC : LdStCop<{?,?,?,?}, 1, (ins pred:$p), "ldc", "${p}">;
+defm LDC2 : LdStCop<0b1111, 1, (ins), "ldc2", "">;
+defm STC : LdStCop<{?,?,?,?}, 0, (ins pred:$p), "stc", "${p}">;
+defm STC2 : LdStCop<0b1111, 0, (ins), "stc2", "">;
//===----------------------------------------------------------------------===//
// Move between coprocessor and ARM core register -- for disassembly only
//
-class MovRCopro<string opc, bit direction>
- : ABI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1,
- GPR:$Rt, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2),
- NoItinerary, opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2",
+class MovRCopro<string opc, bit direction, dag oops, dag iops>
+ : ABI<0b1110, oops, iops, NoItinerary, opc,
+ "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2",
[/* For disassembly only; pattern left blank */]> {
let Inst{20} = direction;
let Inst{4} = 1;
let Inst{19-16} = CRn;
}
-def MCR : MovRCopro<"mcr", 0 /* from ARM core register to coprocessor */>;
-def MRC : MovRCopro<"mrc", 1 /* from coprocessor to ARM core register */>;
+def MCR : MovRCopro<"mcr", 0 /* from ARM core register to coprocessor */,
+ (outs), (ins p_imm:$cop, i32imm:$opc1,
+ GPR:$Rt, c_imm:$CRn, c_imm:$CRm,
+ i32imm:$opc2)>;
+def MRC : MovRCopro<"mrc", 1 /* from coprocessor to ARM core register */,
+ (outs GPR:$Rt), (ins p_imm:$cop, i32imm:$opc1,
+ c_imm:$CRn, c_imm:$CRm, i32imm:$opc2)>;
-class MovRCopro2<string opc, bit direction>
- : ABXI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1,
- GPR:$Rt, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2),
- NoItinerary, !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"),
+class MovRCopro2<string opc, bit direction, dag oops, dag iops>
+ : ABXI<0b1110, oops, iops, NoItinerary,
+ !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"),
[/* For disassembly only; pattern left blank */]> {
let Inst{31-28} = 0b1111;
let Inst{20} = direction;
let Inst{19-16} = CRn;
}
-def MCR2 : MovRCopro2<"mcr2", 0 /* from ARM core register to coprocessor */>;
-def MRC2 : MovRCopro2<"mrc2", 1 /* from coprocessor to ARM core register */>;
+def MCR2 : MovRCopro2<"mcr2", 0 /* from ARM core register to coprocessor */,
+ (outs), (ins p_imm:$cop, i32imm:$opc1,
+ GPR:$Rt, c_imm:$CRn, c_imm:$CRm,
+ i32imm:$opc2)>;
+def MRC2 : MovRCopro2<"mrc2", 1 /* from coprocessor to ARM core register */,
+ (outs GPR:$Rt), (ins p_imm:$cop, i32imm:$opc1,
+ c_imm:$CRn, c_imm:$CRm,
+ i32imm:$opc2)>;
class MovRRCopro<string opc, bit direction>
: ABI<0b1100, (outs), (ins p_imm:$cop, i32imm:$opc1,
// 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)]>,
+ PseudoInst<(outs), (ins), NoItinerary,
+ [(ARMeh_sjlj_dispatchsetup)]>,
Requires<[IsDarwin]>;
//===----------------------------------------------------------------------===//