X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FARMInstrThumb2.td;h=25b39ba9752bb5a76170be1a04387822d9e63b61;hb=61512ba251097888963a8f07a35605564bcfc537;hp=d32052399158ec426b9c4008d445c0e30b3c8a46;hpb=612fb5b9a6472f8e1cea8a4f771238840f4eaa1c;p=oota-llvm.git diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index d3205239915..25b39ba9752 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -21,11 +21,6 @@ def it_mask : Operand { let PrintMethod = "printThumbITMask"; } -// Table branch address -def tb_addrmode : Operand { - let PrintMethod = "printTBAddrMode"; -} - // Shifted operands. No register controlled shifts for Thumb2. // Note: We do not support rrx shifted operands yet. def t2_so_reg : Operand, // reg imm @@ -48,11 +43,10 @@ def t2_so_imm_neg_XFORM : SDNodeXForm, PatLeaf<(imm), [{ return Pred_t2_so_imm(N); }]> { +// immediate splatted into multiple bytes of the word. +def t2_so_imm : Operand, ImmLeaf { let EncoderMethod = "getT2SOImmOpValue"; } @@ -69,49 +63,15 @@ def t2_so_imm_neg : Operand, return ARM_AM::getT2SOImmVal(-((uint32_t)N->getZExtValue())) != -1; }], t2_so_imm_neg_XFORM>; -// Break t2_so_imm's up into two pieces. This handles immediates with up to 16 -// bits set in them. This uses t2_so_imm2part to match and t2_so_imm2part_[12] -// to get the first/second pieces. -def t2_so_imm2part : Operand, - PatLeaf<(imm), [{ - return ARM_AM::isT2SOImmTwoPartVal((unsigned)N->getZExtValue()); - }]> { -} - -def t2_so_imm2part_1 : SDNodeXFormgetZExtValue()); - return CurDAG->getTargetConstant(V, MVT::i32); -}]>; - -def t2_so_imm2part_2 : SDNodeXFormgetZExtValue()); - return CurDAG->getTargetConstant(V, MVT::i32); -}]>; - -def t2_so_neg_imm2part : Operand, PatLeaf<(imm), [{ - return ARM_AM::isT2SOImmTwoPartVal(-(int)N->getZExtValue()); - }]> { -} - -def t2_so_neg_imm2part_1 : SDNodeXFormgetZExtValue()); - return CurDAG->getTargetConstant(V, MVT::i32); -}]>; - -def t2_so_neg_imm2part_2 : SDNodeXFormgetZExtValue()); - return CurDAG->getTargetConstant(V, MVT::i32); -}]>; - /// imm1_31 predicate - True if the 32-bit immediate is in the range [1,31]. -def imm1_31 : PatLeaf<(i32 imm), [{ - return (int32_t)N->getZExtValue() >= 1 && (int32_t)N->getZExtValue() < 32; +def imm1_31 : ImmLeaf= 1 && (int32_t)Imm < 32; }]>; /// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095]. def imm0_4095 : Operand, - PatLeaf<(i32 imm), [{ - return (uint32_t)N->getZExtValue() < 4096; + ImmLeaf= 0 && Imm < 4096; }]>; def imm0_4095_neg : PatLeaf<(i32 imm), [{ @@ -126,32 +86,57 @@ def imm0_255_not : PatLeaf<(i32 imm), [{ return (uint32_t)(~N->getZExtValue()) < 255; }], imm_comp_XFORM>; +def lo5AllOne : PatLeaf<(i32 imm), [{ + // Returns true if all low 5-bits are 1. + return (((uint32_t)N->getZExtValue()) & 0x1FUL) == 0x1FUL; +}]>; + // Define Thumb2 specific addressing modes. // t2addrmode_imm12 := reg + imm12 def t2addrmode_imm12 : Operand, ComplexPattern { let PrintMethod = "printAddrModeImm12Operand"; + let EncoderMethod = "getAddrModeImm12OpValue"; let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); + let ParserMatchClass = MemMode5AsmOperand; +} + +// t2ldrlabel := imm12 +def t2ldrlabel : Operand { + let EncoderMethod = "getAddrModeImm12OpValue"; } + +// ADR instruction labels. +def t2adrlabel : Operand { + let EncoderMethod = "getT2AdrLabelOpValue"; +} + + // t2addrmode_imm8 := reg +/- imm8 def t2addrmode_imm8 : Operand, ComplexPattern { let PrintMethod = "printT2AddrModeImm8Operand"; + let EncoderMethod = "getT2AddrModeImm8OpValue"; let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); + let ParserMatchClass = MemMode5AsmOperand; } def t2am_imm8_offset : Operand, ComplexPattern { let PrintMethod = "printT2AddrModeImm8OffsetOperand"; + let EncoderMethod = "getT2AddrModeImm8OffsetOpValue"; + let ParserMatchClass = MemMode5AsmOperand; } // t2addrmode_imm8s4 := reg +/- (imm8 << 2) def t2addrmode_imm8s4 : Operand { let PrintMethod = "printT2AddrModeImm8s4Operand"; + let EncoderMethod = "getT2AddrModeImm8s4OpValue"; let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); + let ParserMatchClass = MemMode5AsmOperand; } def t2am_imm8s4_offset : Operand { @@ -162,9 +147,20 @@ def t2am_imm8s4_offset : Operand { def t2addrmode_so_reg : Operand, ComplexPattern { let PrintMethod = "printT2AddrModeSoRegOperand"; + let EncoderMethod = "getT2AddrModeSORegOpValue"; let MIOperandInfo = (ops GPR:$base, rGPR:$offsreg, i32imm:$offsimm); + let ParserMatchClass = MemMode5AsmOperand; } +// t2addrmode_reg := reg +// Used by load/store exclusive instructions. Useful to enable right assembly +// parsing and printing. Not used for any codegen matching. +// +def t2addrmode_reg : Operand { + let PrintMethod = "printAddrMode7Operand"; + let MIOperandInfo = (ops tGPR); + let ParserMatchClass = MemMode7AsmOperand; +} //===----------------------------------------------------------------------===// // Multiclass helpers... @@ -176,8 +172,8 @@ class T2OneRegImm { bits<4> Rd; bits<12> imm; - - let Inst{11-8} = Rd{3-0}; + + let Inst{11-8} = Rd; let Inst{26} = imm{11}; let Inst{14-12} = imm{10-8}; let Inst{7-0} = imm{7-0}; @@ -190,8 +186,8 @@ class T2sOneRegImm Rd; bits<4> Rn; bits<12> imm; - - let Inst{11-8} = Rd{3-0}; + + let Inst{11-8} = Rd; let Inst{26} = imm{11}; let Inst{14-12} = imm{10-8}; let Inst{7-0} = imm{7-0}; @@ -202,8 +198,8 @@ class T2OneRegCmpImm { bits<4> Rn; bits<12> imm; - - let Inst{19-16} = Rn{3-0}; + + let Inst{19-16} = Rn; let Inst{26} = imm{11}; let Inst{14-12} = imm{10-8}; let Inst{7-0} = imm{7-0}; @@ -215,8 +211,8 @@ class T2OneRegShiftedReg { bits<4> Rd; bits<12> ShiftedRm; - - let Inst{11-8} = Rd{3-0}; + + let Inst{11-8} = Rd; let Inst{3-0} = ShiftedRm{3-0}; let Inst{5-4} = ShiftedRm{6-5}; let Inst{14-12} = ShiftedRm{11-9}; @@ -225,11 +221,11 @@ class T2OneRegShiftedReg pattern> - : T2I { + : T2sI { bits<4> Rd; bits<12> ShiftedRm; - - let Inst{11-8} = Rd{3-0}; + + let Inst{11-8} = Rd; let Inst{3-0} = ShiftedRm{3-0}; let Inst{5-4} = ShiftedRm{6-5}; let Inst{14-12} = ShiftedRm{11-9}; @@ -241,8 +237,8 @@ class T2OneRegCmpShiftedReg { bits<4> Rn; bits<12> ShiftedRm; - - let Inst{19-16} = Rn{3-0}; + + let Inst{19-16} = Rn; let Inst{3-0} = ShiftedRm{3-0}; let Inst{5-4} = ShiftedRm{6-5}; let Inst{14-12} = ShiftedRm{11-9}; @@ -251,32 +247,32 @@ class T2OneRegCmpShiftedReg pattern> - : T2I { + : T2I { bits<4> Rd; bits<4> Rm; - - let Inst{11-8} = Rd{3-0}; - let Inst{3-0} = Rm{3-0}; + + let Inst{11-8} = Rd; + let Inst{3-0} = Rm; } class T2sTwoReg pattern> - : T2sI { + : T2sI { bits<4> Rd; bits<4> Rm; - - let Inst{11-8} = Rd{3-0}; - let Inst{3-0} = Rm{3-0}; + + let Inst{11-8} = Rd; + let Inst{3-0} = Rm; } class T2TwoRegCmp pattern> - : T2I { + : T2I { bits<4> Rn; bits<4> Rm; - - let Inst{19-16} = Rn{3-0}; - let Inst{3-0} = Rm{3-0}; + + let Inst{19-16} = Rn; + let Inst{3-0} = Rm; } @@ -284,10 +280,14 @@ class T2TwoRegImm pattern> : T2I { bits<4> Rd; - bits<4> Rm; - - let Inst{11-8} = Rd{3-0}; - let Inst{3-0} = Rm{3-0}; + bits<4> Rn; + bits<12> imm; + + let Inst{11-8} = Rd; + let Inst{19-16} = Rn; + let Inst{26} = imm{11}; + let Inst{14-12} = imm{10-8}; + let Inst{7-0} = imm{7-0}; } class T2sTwoRegImm Rd; bits<4> Rn; bits<12> imm; - - let Inst{11-8} = Rd{3-0}; - let Inst{19-16} = Rn{3-0}; + + let Inst{11-8} = Rd; + let Inst{19-16} = Rn; let Inst{26} = imm{11}; let Inst{14-12} = imm{10-8}; let Inst{7-0} = imm{7-0}; @@ -310,9 +310,9 @@ class T2TwoRegShiftImm Rd; bits<4> Rm; bits<5> imm; - - let Inst{11-8} = Rd{3-0}; - let Inst{3-0} = Rm{3-0}; + + let Inst{11-8} = Rd; + let Inst{3-0} = Rm; let Inst{14-12} = imm{4-2}; let Inst{7-6} = imm{1-0}; } @@ -323,35 +323,35 @@ class T2sTwoRegShiftImm Rd; bits<4> Rm; bits<5> imm; - - let Inst{11-8} = Rd{3-0}; - let Inst{3-0} = Rm{3-0}; + + let Inst{11-8} = Rd; + let Inst{3-0} = Rm; let Inst{14-12} = imm{4-2}; let Inst{7-6} = imm{1-0}; } class T2ThreeReg pattern> - : T2I { + : T2I { bits<4> Rd; bits<4> Rn; bits<4> Rm; - - let Inst{11-8} = Rd{3-0}; - let Inst{19-16} = Rn{3-0}; - let Inst{3-0} = Rm{3-0}; + + let Inst{11-8} = Rd; + let Inst{19-16} = Rn; + let Inst{3-0} = Rm; } class T2sThreeReg pattern> - : T2sI { + : T2sI { bits<4> Rd; bits<4> Rn; bits<4> Rm; - - let Inst{11-8} = Rd{3-0}; - let Inst{19-16} = Rn{3-0}; - let Inst{3-0} = Rm{3-0}; + + let Inst{11-8} = Rd; + let Inst{19-16} = Rn; + let Inst{3-0} = Rm; } class T2TwoRegShiftedReg Rd; bits<4> Rn; bits<12> ShiftedRm; - - let Inst{11-8} = Rd{3-0}; - let Inst{19-16} = Rn{3-0}; + + let Inst{11-8} = Rd; + let Inst{19-16} = Rn; let Inst{3-0} = ShiftedRm{3-0}; let Inst{5-4} = ShiftedRm{6-5}; let Inst{14-12} = ShiftedRm{11-9}; @@ -375,9 +375,9 @@ class T2sTwoRegShiftedReg Rd; bits<4> Rn; bits<12> ShiftedRm; - - let Inst{11-8} = Rd{3-0}; - let Inst{19-16} = Rn{3-0}; + + let Inst{11-8} = Rd; + let Inst{19-16} = Rn; let Inst{3-0} = ShiftedRm{3-0}; let Inst{5-4} = ShiftedRm{6-5}; let Inst{14-12} = ShiftedRm{11-9}; @@ -386,16 +386,34 @@ class T2sTwoRegShiftedReg pattern> - : T2I { + : T2I { bits<4> Rd; bits<4> Rn; bits<4> Rm; bits<4> Ra; - - let Inst{11-8} = Rd{3-0}; - let Inst{19-16} = Rn{3-0}; - let Inst{3-0} = Rm{3-0}; - let Inst{15-12} = Ra{3-0}; + + let Inst{19-16} = Rn; + let Inst{15-12} = Ra; + let Inst{11-8} = Rd; + let Inst{3-0} = Rm; +} + +class T2MulLong opc22_20, bits<4> opc7_4, + dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : T2I { + bits<4> RdLo; + bits<4> RdHi; + bits<4> Rn; + bits<4> Rm; + + let Inst{31-23} = 0b111110111; + let Inst{22-20} = opc22_20; + let Inst{19-16} = Rn; + let Inst{15-12} = RdLo; + let Inst{11-8} = RdHi; + let Inst{7-4} = opc7_4; + let Inst{3-0} = Rm; } @@ -414,7 +432,6 @@ multiclass T2I_un_irs opcod, string opc, let Inst{31-27} = 0b11110; let Inst{25} = 0; let Inst{24-21} = opcod; - let Inst{20} = ?; // The S bit. let Inst{19-16} = 0b1111; // Rn let Inst{15} = 0; } @@ -425,7 +442,6 @@ multiclass T2I_un_irs opcod, string opc, let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = opcod; - let Inst{20} = ?; // The S bit. let Inst{19-16} = 0b1111; // Rn let Inst{14-12} = 0b000; // imm3 let Inst{7-6} = 0b00; // imm2 @@ -438,7 +454,6 @@ multiclass T2I_un_irs opcod, string opc, let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = opcod; - let Inst{20} = ?; // The S bit. let Inst{19-16} = 0b1111; // Rn } } @@ -457,7 +472,6 @@ multiclass T2I_bin_irs opcod, string opc, let Inst{31-27} = 0b11110; let Inst{25} = 0; let Inst{24-21} = opcod; - let Inst{20} = ?; // The S bit. let Inst{15} = 0; } // register @@ -468,7 +482,6 @@ multiclass T2I_bin_irs opcod, string opc, let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = opcod; - let Inst{20} = ?; // The S bit. let Inst{14-12} = 0b000; // imm3 let Inst{7-6} = 0b00; // imm2 let Inst{5-4} = 0b00; // type @@ -481,7 +494,6 @@ multiclass T2I_bin_irs opcod, string opc, let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = opcod; - let Inst{20} = ?; // The S bit. } } @@ -504,7 +516,6 @@ multiclass T2I_rbin_irs opcod, string opc, PatFrag opnode> { let Inst{31-27} = 0b11110; let Inst{25} = 0; let Inst{24-21} = opcod; - let Inst{20} = ?; // The S bit. let Inst{15} = 0; } // register @@ -515,7 +526,6 @@ multiclass T2I_rbin_irs opcod, string opc, PatFrag opnode> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = opcod; - let Inst{20} = ?; // The S bit. let Inst{14-12} = 0b000; // imm3 let Inst{7-6} = 0b00; // imm2 let Inst{5-4} = 0b00; // type @@ -528,13 +538,12 @@ multiclass T2I_rbin_irs opcod, string opc, PatFrag opnode> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = opcod; - let Inst{20} = ?; // The S bit. } } /// T2I_bin_s_irs - Similar to T2I_bin_irs except it sets the 's' bit so the /// instruction modifies the CPSR register. -let Defs = [CPSR] in { +let isCodeGenOnly = 1, Defs = [CPSR] in { multiclass T2I_bin_s_irs opcod, string opc, InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, PatFrag opnode, bit Commutable = 0> { @@ -592,21 +601,27 @@ multiclass T2I_bin_ii12rs op23_21, string opc, PatFrag opnode, let Inst{25} = 0; let Inst{24} = 1; let Inst{23-21} = op23_21; - let Inst{20} = 0; // The S bit. let Inst{15} = 0; } } // 12-bit imm - def ri12 : T2TwoRegImm< + def ri12 : T2I< (outs rGPR:$Rd), (ins GPR:$Rn, imm0_4095:$imm), IIC_iALUi, !strconcat(opc, "w"), "\t$Rd, $Rn, $imm", [(set rGPR:$Rd, (opnode GPR:$Rn, imm0_4095:$imm))]> { + bits<4> Rd; + bits<4> Rn; + bits<12> imm; let Inst{31-27} = 0b11110; - let Inst{25} = 1; - let Inst{24} = 0; + let Inst{26} = imm{11}; + let Inst{25-24} = 0b10; let Inst{23-21} = op23_21; let Inst{20} = 0; // The S bit. + let Inst{19-16} = Rn; let Inst{15} = 0; + let Inst{14-12} = imm{10-8}; + let Inst{11-8} = Rd; + let Inst{7-0} = imm{7-0}; } // register def rr : T2sThreeReg<(outs rGPR:$Rd), (ins GPR:$Rn, rGPR:$Rm), IIC_iALUr, @@ -617,21 +632,19 @@ multiclass T2I_bin_ii12rs op23_21, string opc, PatFrag opnode, let Inst{26-25} = 0b01; let Inst{24} = 1; let Inst{23-21} = op23_21; - let Inst{20} = 0; // The S bit. let Inst{14-12} = 0b000; // imm3 let Inst{7-6} = 0b00; // imm2 let Inst{5-4} = 0b00; // type } // shifted register def rs : T2sTwoRegShiftedReg< - (outs rGPR:$Rd), (ins GPR:$Rn, t2_so_reg:$ShiftedRm), + (outs rGPR:$Rd), (ins GPR:$Rn, t2_so_reg:$ShiftedRm), IIC_iALUsi, opc, ".w\t$Rd, $Rn, $ShiftedRm", [(set rGPR:$Rd, (opnode GPR:$Rn, t2_so_reg:$ShiftedRm))]> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24} = 1; let Inst{23-21} = op23_21; - let Inst{20} = 0; // The S bit. } } @@ -649,7 +662,6 @@ multiclass T2I_adde_sube_irs opcod, string opc, PatFrag opnode, let Inst{31-27} = 0b11110; let Inst{25} = 0; let Inst{24-21} = opcod; - let Inst{20} = 0; // The S bit. let Inst{15} = 0; } // register @@ -661,72 +673,48 @@ multiclass T2I_adde_sube_irs opcod, string opc, PatFrag opnode, let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = opcod; - let Inst{20} = 0; // The S bit. let Inst{14-12} = 0b000; // imm3 let Inst{7-6} = 0b00; // imm2 let Inst{5-4} = 0b00; // type } // shifted register def rs : T2sTwoRegShiftedReg< - (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm), + (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm), IIC_iALUsi, opc, ".w\t$Rd, $Rn, $ShiftedRm", [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>, Requires<[IsThumb2]> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = opcod; - let Inst{20} = 0; // The S bit. } } +} // Carry setting variants -let Defs = [CPSR] in { -multiclass T2I_adde_sube_s_irs opcod, string opc, PatFrag opnode, - bit Commutable = 0> { +// NOTE: CPSR def omitted because it will be handled by the custom inserter. +let usesCustomInserter = 1 in { +multiclass T2I_adde_sube_s_irs { // shifted imm - def ri : T2sTwoRegImm< - (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm), IIC_iALUi, - opc, "\t$Rd, $Rn, $imm", - [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>, - Requires<[IsThumb2]> { - let Inst{31-27} = 0b11110; - let Inst{25} = 0; - let Inst{24-21} = opcod; - let Inst{20} = 1; // The S bit. - let Inst{15} = 0; - } + def ri : t2PseudoInst<(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm), + Size4Bytes, IIC_iALUi, + [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>; // register - def rr : T2sThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUr, - opc, ".w\t$Rd, $Rn, $Rm", - [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]>, - Requires<[IsThumb2]> { + def rr : t2PseudoInst<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), + Size4Bytes, IIC_iALUr, + [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]> { let isCommutable = Commutable; - let Inst{31-27} = 0b11101; - let Inst{26-25} = 0b01; - let Inst{24-21} = opcod; - let Inst{20} = 1; // The S bit. - let Inst{14-12} = 0b000; // imm3 - let Inst{7-6} = 0b00; // imm2 - let Inst{5-4} = 0b00; // type } // shifted register - def rs : T2sTwoRegShiftedReg< - (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm), - IIC_iALUsi, opc, ".w\t$Rd, $Rn, $ShiftedRm", - [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>, - Requires<[IsThumb2]> { - let Inst{31-27} = 0b11101; - let Inst{26-25} = 0b01; - let Inst{24-21} = opcod; - let Inst{20} = 1; // The S bit. - } -} + def rs : t2PseudoInst< + (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm), + Size4Bytes, IIC_iALUsi, + [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>; } } /// T2I_rbin_s_is - Same as T2I_rbin_irs except sets 's' bit and the register /// version is not needed since this is only for codegen. -let Defs = [CPSR] in { +let isCodeGenOnly = 1, Defs = [CPSR] in { multiclass T2I_rbin_s_is opcod, string opc, PatFrag opnode> { // shifted imm def ri : T2TwoRegImm< @@ -828,19 +816,28 @@ multiclass T2I_cmp_irs opcod, string opc, /// T2I_ld - Defines a set of (op r, {imm12|imm8|so_reg}) load patterns. multiclass T2I_ld opcod, string opc, InstrItinClass iii, InstrItinClass iis, PatFrag opnode> { - def i12 : T2Ii12<(outs GPR:$dst), (ins t2addrmode_imm12:$addr), iii, - opc, ".w\t$dst, $addr", - [(set GPR:$dst, (opnode t2addrmode_imm12:$addr))]> { + def i12 : T2Ii12<(outs GPR:$Rt), (ins t2addrmode_imm12:$addr), iii, + opc, ".w\t$Rt, $addr", + [(set GPR:$Rt, (opnode t2addrmode_imm12:$addr))]> { let Inst{31-27} = 0b11111; let Inst{26-25} = 0b00; let Inst{24} = signed; let Inst{23} = 1; let Inst{22-21} = opcod; let Inst{20} = 1; // load + + bits<4> Rt; + let Inst{15-12} = Rt; + + bits<17> addr; + let addr{12} = 1; // add = TRUE + let Inst{19-16} = addr{16-13}; // Rn + let Inst{23} = addr{12}; // U + let Inst{11-0} = addr{11-0}; // imm } - def i8 : T2Ii8 <(outs GPR:$dst), (ins t2addrmode_imm8:$addr), iii, - opc, "\t$dst, $addr", - [(set GPR:$dst, (opnode t2addrmode_imm8:$addr))]> { + def i8 : T2Ii8 <(outs GPR:$Rt), (ins t2addrmode_imm8:$addr), iii, + opc, "\t$Rt, $addr", + [(set GPR:$Rt, (opnode t2addrmode_imm8:$addr))]> { let Inst{31-27} = 0b11111; let Inst{26-25} = 0b00; let Inst{24} = signed; @@ -851,10 +848,18 @@ multiclass T2I_ld opcod, string opc, // Offset: index==TRUE, wback==FALSE let Inst{10} = 1; // The P bit. let Inst{8} = 0; // The W bit. + + bits<4> Rt; + let Inst{15-12} = Rt; + + bits<13> addr; + let Inst{19-16} = addr{12-9}; // Rn + let Inst{9} = addr{8}; // U + let Inst{7-0} = addr{7-0}; // imm } - def s : T2Iso <(outs GPR:$dst), (ins t2addrmode_so_reg:$addr), iis, - opc, ".w\t$dst, $addr", - [(set GPR:$dst, (opnode t2addrmode_so_reg:$addr))]> { + def s : T2Iso <(outs GPR:$Rt), (ins t2addrmode_so_reg:$addr), iis, + opc, ".w\t$Rt, $addr", + [(set GPR:$Rt, (opnode t2addrmode_so_reg:$addr))]> { let Inst{31-27} = 0b11111; let Inst{26-25} = 0b00; let Inst{24} = signed; @@ -862,12 +867,20 @@ multiclass T2I_ld opcod, string opc, let Inst{22-21} = opcod; let Inst{20} = 1; // load let Inst{11-6} = 0b000000; + + bits<4> Rt; + let Inst{15-12} = Rt; + + bits<10> addr; + let Inst{19-16} = addr{9-6}; // Rn + let Inst{3-0} = addr{5-2}; // Rm + let Inst{5-4} = addr{1-0}; // imm } // FIXME: Is the pci variant actually needed? - def pci : T2Ipc <(outs GPR:$dst), (ins i32imm:$addr), iii, - opc, ".w\t$dst, $addr", - [(set GPR:$dst, (opnode (ARMWrapper tconstpool:$addr)))]> { + def pci : T2Ipc <(outs GPR:$Rt), (ins t2ldrlabel:$addr), iii, + opc, ".w\t$Rt, $addr", + [(set GPR:$Rt, (opnode (ARMWrapper tconstpool:$addr)))]> { let isReMaterializable = 1; let Inst{31-27} = 0b11111; let Inst{26-25} = 0b00; @@ -876,23 +889,36 @@ multiclass T2I_ld opcod, string opc, let Inst{22-21} = opcod; let Inst{20} = 1; // load let Inst{19-16} = 0b1111; // Rn + bits<4> Rt; + bits<12> addr; + let Inst{15-12} = Rt{3-0}; + let Inst{11-0} = addr{11-0}; } } /// T2I_st - Defines a set of (op r, {imm12|imm8|so_reg}) store patterns. multiclass T2I_st opcod, string opc, InstrItinClass iii, InstrItinClass iis, PatFrag opnode> { - def i12 : T2Ii12<(outs), (ins GPR:$src, t2addrmode_imm12:$addr), iii, - opc, ".w\t$src, $addr", - [(opnode GPR:$src, t2addrmode_imm12:$addr)]> { + def i12 : T2Ii12<(outs), (ins GPR:$Rt, t2addrmode_imm12:$addr), iii, + opc, ".w\t$Rt, $addr", + [(opnode GPR:$Rt, t2addrmode_imm12:$addr)]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0001; let Inst{22-21} = opcod; let Inst{20} = 0; // !load + + bits<4> Rt; + let Inst{15-12} = Rt; + + bits<17> addr; + let addr{12} = 1; // add = TRUE + let Inst{19-16} = addr{16-13}; // Rn + let Inst{23} = addr{12}; // U + let Inst{11-0} = addr{11-0}; // imm } - def i8 : T2Ii8 <(outs), (ins GPR:$src, t2addrmode_imm8:$addr), iii, - opc, "\t$src, $addr", - [(opnode GPR:$src, t2addrmode_imm8:$addr)]> { + def i8 : T2Ii8 <(outs), (ins GPR:$Rt, t2addrmode_imm8:$addr), iii, + opc, "\t$Rt, $addr", + [(opnode GPR:$Rt, t2addrmode_imm8:$addr)]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0000; let Inst{22-21} = opcod; @@ -901,15 +927,31 @@ multiclass T2I_st opcod, string opc, // Offset: index==TRUE, wback==FALSE let Inst{10} = 1; // The P bit. let Inst{8} = 0; // The W bit. + + bits<4> Rt; + let Inst{15-12} = Rt; + + bits<13> addr; + let Inst{19-16} = addr{12-9}; // Rn + let Inst{9} = addr{8}; // U + let Inst{7-0} = addr{7-0}; // imm } - def s : T2Iso <(outs), (ins GPR:$src, t2addrmode_so_reg:$addr), iis, - opc, ".w\t$src, $addr", - [(opnode GPR:$src, t2addrmode_so_reg:$addr)]> { + def s : T2Iso <(outs), (ins GPR:$Rt, t2addrmode_so_reg:$addr), iis, + opc, ".w\t$Rt, $addr", + [(opnode GPR:$Rt, t2addrmode_so_reg:$addr)]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0000; let Inst{22-21} = opcod; let Inst{20} = 0; // !load let Inst{11-6} = 0b000000; + + bits<4> Rt; + let Inst{15-12} = Rt; + + bits<10> addr; + let Inst{19-16} = addr{9-6}; // Rn + let Inst{3-0} = addr{5-2}; // Rm + let Inst{5-4} = addr{1-0}; // imm } } @@ -927,7 +969,7 @@ multiclass T2I_ext_rrot opcod, string opc, PatFrag opnode> { let Inst{7} = 1; let Inst{5-4} = 0b00; // rotate } - def r_rot : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, i32imm:$rot), IIC_iEXTr, + def r_rot : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, rot_imm:$rot), IIC_iEXTr, opc, ".w\t$Rd, $Rm, ror $rot", [(set rGPR:$Rd, (opnode (rotr rGPR:$Rm, rot_imm:$rot)))]> { let Inst{31-27} = 0b11111; @@ -936,7 +978,7 @@ multiclass T2I_ext_rrot opcod, string opc, PatFrag opnode> { let Inst{19-16} = 0b1111; // Rn let Inst{15-12} = 0b1111; let Inst{7} = 1; - + bits<2> rot; let Inst{5-4} = rot{1-0}; // rotate } @@ -956,8 +998,8 @@ multiclass T2I_ext_rrot_uxtb16 opcod, string opc, PatFrag opnode> { let Inst{7} = 1; let Inst{5-4} = 0b00; // rotate } - def r_rot : T2TwoReg<(outs rGPR:$dst), (ins rGPR:$Rm, i32imm:$rot), IIC_iEXTr, - opc, "\t$dst, $Rm, ror $rot", + def r_rot : T2TwoReg<(outs rGPR:$dst), (ins rGPR:$Rm, rot_imm:$rot), + IIC_iEXTr, opc, "\t$dst, $Rm, ror $rot", [(set rGPR:$dst, (opnode (rotr rGPR:$Rm, rot_imm:$rot)))]>, Requires<[HasT2ExtractPack, IsThumb2]> { let Inst{31-27} = 0b11111; @@ -966,7 +1008,7 @@ multiclass T2I_ext_rrot_uxtb16 opcod, string opc, PatFrag opnode> { let Inst{19-16} = 0b1111; // Rn let Inst{15-12} = 0b1111; let Inst{7} = 1; - + bits<2> rot; let Inst{5-4} = rot{1-0}; // rotate } @@ -993,7 +1035,7 @@ multiclass T2I_ext_rrot_sxtb16 opcod, string opc> { let Inst{19-16} = 0b1111; // Rn let Inst{15-12} = 0b1111; let Inst{7} = 1; - + bits<2> rot; let Inst{5-4} = rot{1-0}; // rotate } @@ -1013,7 +1055,8 @@ multiclass T2I_exta_rrot opcod, string opc, PatFrag opnode> { let Inst{7} = 1; let Inst{5-4} = 0b00; // rotate } - def rr_rot : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, i32imm:$rot), + def rr_rot : T2ThreeReg<(outs rGPR:$Rd), + (ins rGPR:$Rn, rGPR:$Rm, rot_imm:$rot), IIC_iEXTAsr, opc, "\t$Rd, $Rn, $Rm, ror $rot", [(set rGPR:$Rd, (opnode rGPR:$Rn, (rotr rGPR:$Rm, rot_imm:$rot)))]>, @@ -1023,7 +1066,7 @@ multiclass T2I_exta_rrot opcod, string opc, PatFrag opnode> { let Inst{22-20} = opcod; let Inst{15-12} = 0b1111; let Inst{7} = 1; - + bits<2> rot; let Inst{5-4} = rot{1-0}; // rotate } @@ -1048,7 +1091,7 @@ multiclass T2I_exta_rrot_DO opcod, string opc> { let Inst{22-20} = opcod; let Inst{15-12} = 0b1111; let Inst{7} = 1; - + bits<2> rot; let Inst{5-4} = rot{1-0}; // rotate } @@ -1067,8 +1110,8 @@ class T2PCOneRegImm { bits<4> Rd; bits<12> label; - - let Inst{11-8} = Rd{3-0}; + + let Inst{11-8} = Rd; let Inst{26} = label{11}; let Inst{14-12} = label{10-8}; let Inst{7-0} = label{7-0}; @@ -1076,10 +1119,9 @@ class T2PCOneRegImm { +def t2ADR : T2PCOneRegImm<(outs rGPR:$Rd), + (ins t2adrlabel:$addr, pred:$p), + IIC_iALUi, "adr{$p}.w\t$Rd, #$addr", []> { let Inst{31-27} = 0b11110; let Inst{25-24} = 0b10; // Inst{23:21} = '11' (add = FALSE) or '00' (add = TRUE) @@ -1087,91 +1129,88 @@ def t2LEApcrel : T2PCOneRegImm<(outs rGPR:$Rd), (ins i32imm:$label, pred:$p), II let Inst{20} = 0; let Inst{19-16} = 0b1111; // Rn let Inst{15} = 0; - - -} -} // neverHasSideEffects -def t2LEApcrelJT : T2PCOneRegImm<(outs rGPR:$Rd), - (ins i32imm:$label, nohash_imm:$id, pred:$p), IIC_iALUi, - "adr${p}.w\t$Rd, #${label}_${id}", []> { - let Inst{31-27} = 0b11110; - let Inst{25-24} = 0b10; - // Inst{23:21} = '11' (add = FALSE) or '00' (add = TRUE) - let Inst{22} = 0; - let Inst{20} = 0; - let Inst{19-16} = 0b1111; // Rn - let Inst{15} = 0; -} + bits<4> Rd; + bits<13> addr; + let Inst{11-8} = Rd; + let Inst{23} = addr{12}; + let Inst{21} = addr{12}; + let Inst{26} = addr{11}; + let Inst{14-12} = addr{10-8}; + let Inst{7-0} = addr{7-0}; +} + +let neverHasSideEffects = 1, isReMaterializable = 1 in +def t2LEApcrel : t2PseudoInst<(outs rGPR:$Rd), (ins i32imm:$label, pred:$p), + Size4Bytes, IIC_iALUi, []>; +def t2LEApcrelJT : t2PseudoInst<(outs rGPR:$Rd), + (ins i32imm:$label, nohash_imm:$id, pred:$p), + Size4Bytes, IIC_iALUi, + []>; + + +// FIXME: None of these add/sub SP special instructions should be necessary +// at all for thumb2 since they use the same encodings as the generic +// add/sub instructions. In thumb1 we need them since they have dedicated +// encodings. At the least, they should be pseudo instructions. // ADD r, sp, {so_imm|i12} -def t2ADDrSPi : T2sTwoRegImm<(outs GPR:$Rd), (ins GPR:$sp, t2_so_imm:$imm), - IIC_iALUi, "add", ".w\t$Rd, $sp, $imm", []> { +let isCodeGenOnly = 1 in { +def t2ADDrSPi : T2sTwoRegImm<(outs GPR:$Rd), (ins GPR:$Rn, t2_so_imm:$imm), + IIC_iALUi, "add", ".w\t$Rd, $Rn, $imm", []> { let Inst{31-27} = 0b11110; let Inst{25} = 0; let Inst{24-21} = 0b1000; - let Inst{20} = ?; // The S bit. - let Inst{19-16} = 0b1101; // Rn = sp let Inst{15} = 0; } -def t2ADDrSPi12 : T2TwoRegImm<(outs GPR:$Rd), (ins GPR:$sp, imm0_4095:$imm), - IIC_iALUi, "addw", "\t$Rd, $sp, $imm", []> { +def t2ADDrSPi12 : T2TwoRegImm<(outs GPR:$Rd), (ins GPR:$Rn, imm0_4095:$imm), + IIC_iALUi, "addw", "\t$Rd, $Rn, $imm", []> { let Inst{31-27} = 0b11110; - let Inst{25} = 1; - let Inst{24-21} = 0b0000; - let Inst{20} = 0; // The S bit. - let Inst{19-16} = 0b1101; // Rn = sp + let Inst{25-20} = 0b100000; let Inst{15} = 0; } // ADD r, sp, so_reg def t2ADDrSPs : T2sTwoRegShiftedReg< - (outs GPR:$Rd), (ins GPR:$sp, t2_so_reg:$ShiftedRm), - IIC_iALUsi, "add", ".w\t$Rd, $sp, $ShiftedRm", []> { + (outs GPR:$Rd), (ins GPR:$Rn, t2_so_reg:$ShiftedRm), + IIC_iALUsi, "add", ".w\t$Rd, $Rn, $ShiftedRm", []> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = 0b1000; - let Inst{20} = ?; // The S bit. - let Inst{19-16} = 0b1101; // Rn = sp let Inst{15} = 0; } // SUB r, sp, {so_imm|i12} -def t2SUBrSPi : T2sTwoRegImm<(outs GPR:$Rd), (ins GPR:$sp, t2_so_imm:$imm), - IIC_iALUi, "sub", ".w\t$Rd, $sp, $imm", []> { +def t2SUBrSPi : T2sTwoRegImm<(outs GPR:$Rd), (ins GPR:$Rn, t2_so_imm:$imm), + IIC_iALUi, "sub", ".w\t$Rd, $Rn, $imm", []> { let Inst{31-27} = 0b11110; let Inst{25} = 0; let Inst{24-21} = 0b1101; - let Inst{20} = ?; // The S bit. - let Inst{19-16} = 0b1101; // Rn = sp let Inst{15} = 0; } -def t2SUBrSPi12 : T2TwoRegImm<(outs GPR:$Rd), (ins GPR:$sp, imm0_4095:$imm), - IIC_iALUi, "subw", "\t$Rd, $sp, $imm", []> { +def t2SUBrSPi12 : T2TwoRegImm<(outs GPR:$Rd), (ins GPR:$Rn, imm0_4095:$imm), + IIC_iALUi, "subw", "\t$Rd, $Rn, $imm", []> { let Inst{31-27} = 0b11110; - let Inst{25} = 1; - let Inst{24-21} = 0b0101; - let Inst{20} = 0; // The S bit. - let Inst{19-16} = 0b1101; // Rn = sp + let Inst{25-20} = 0b101010; let Inst{15} = 0; } // SUB r, sp, so_reg -def t2SUBrSPs : T2sTwoRegImm<(outs GPR:$Rd), (ins GPR:$sp, t2_so_reg:$imm), +def t2SUBrSPs : T2sTwoRegImm<(outs GPR:$Rd), (ins GPR:$Rn, t2_so_reg:$imm), IIC_iALUsi, - "sub", "\t$Rd, $sp, $imm", []> { + "sub", "\t$Rd, $Rn, $imm", []> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = 0b1101; - let Inst{20} = ?; // The S bit. let Inst{19-16} = 0b1101; // Rn = sp let Inst{15} = 0; } +} // end isCodeGenOnly = 1 // Signed and unsigned division on v7-M -def t2SDIV : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUi, +def t2SDIV : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUi, "sdiv", "\t$Rd, $Rn, $Rm", [(set rGPR:$Rd, (sdiv rGPR:$Rn, rGPR:$Rm))]>, - Requires<[HasDivide]> { + Requires<[HasDivide, IsThumb2]> { let Inst{31-27} = 0b11111; let Inst{26-21} = 0b011100; let Inst{20} = 0b1; @@ -1179,10 +1218,10 @@ def t2SDIV : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUi, let Inst{7-4} = 0b1111; } -def t2UDIV : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUi, +def t2UDIV : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUi, "udiv", "\t$Rd, $Rn, $Rm", [(set rGPR:$Rd, (udiv rGPR:$Rn, rGPR:$Rm))]>, - Requires<[HasDivide]> { + Requires<[HasDivide, IsThumb2]> { let Inst{31-27} = 0b11111; let Inst{26-21} = 0b011101; let Inst{20} = 0b1; @@ -1211,17 +1250,11 @@ defm t2LDRSH : T2I_ld<1, 0b01, "ldrsh", IIC_iLoad_bh_i, IIC_iLoad_bh_si, defm t2LDRSB : T2I_ld<1, 0b00, "ldrsb", IIC_iLoad_bh_i, IIC_iLoad_bh_si, UnOpFrag<(sextloadi8 node:$Src)>>; -let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1, - isCodeGenOnly = 1 in { // $dst doesn't exist in asmstring? +let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in { // Load doubleword -def t2LDRDi8 : T2Ii8s4<1, 0, 1, (outs rGPR:$dst1, rGPR:$dst2), +def t2LDRDi8 : T2Ii8s4<1, 0, 1, (outs rGPR:$Rt, rGPR:$Rt2), (ins t2addrmode_imm8s4:$addr), - IIC_iLoad_d_i, "ldrd", "\t$dst1, $addr", []>; -def t2LDRDpci : T2Ii8s4<1, 0, 1, (outs rGPR:$dst1, rGPR:$dst2), - (ins i32imm:$addr), IIC_iLoad_d_i, - "ldrd", "\t$dst1, $addr", []> { - let Inst{19-16} = 0b1111; // Rn -} + IIC_iLoad_d_i, "ldrd", "\t$Rt, $Rt2, $addr", []>; } // mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 // zextload i1 -> zextload i8 @@ -1270,70 +1303,71 @@ def : T2Pat<(extloadi16 (ARMWrapper tconstpool:$addr)), // not via pattern. // Indexed loads + let mayLoad = 1, neverHasSideEffects = 1 in { -def t2LDR_PRE : T2Iidxldst<0, 0b10, 1, 1, (outs GPR:$dst, GPR:$base_wb), +def t2LDR_PRE : T2Iidxldst<0, 0b10, 1, 1, (outs GPR:$Rt, GPR:$Rn), (ins t2addrmode_imm8:$addr), AddrModeT2_i8, IndexModePre, IIC_iLoad_iu, - "ldr", "\t$dst, $addr!", "$addr.base = $base_wb", + "ldr", "\t$Rt, $addr!", "$addr.base = $Rn", []>; -def t2LDR_POST : T2Iidxldst<0, 0b10, 1, 0, (outs GPR:$dst, GPR:$base_wb), - (ins GPR:$base, t2am_imm8_offset:$offset), +def t2LDR_POST : T2Iidxldst<0, 0b10, 1, 0, (outs GPR:$Rt, GPR:$Rn), + (ins GPR:$base, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePost, IIC_iLoad_iu, - "ldr", "\t$dst, [$base], $offset", "$base = $base_wb", + "ldr", "\t$Rt, [$Rn], $addr", "$base = $Rn", []>; -def t2LDRB_PRE : T2Iidxldst<0, 0b00, 1, 1, (outs GPR:$dst, GPR:$base_wb), +def t2LDRB_PRE : T2Iidxldst<0, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn), (ins t2addrmode_imm8:$addr), AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu, - "ldrb", "\t$dst, $addr!", "$addr.base = $base_wb", + "ldrb", "\t$Rt, $addr!", "$addr.base = $Rn", []>; -def t2LDRB_POST : T2Iidxldst<0, 0b00, 1, 0, (outs GPR:$dst, GPR:$base_wb), - (ins GPR:$base, t2am_imm8_offset:$offset), +def t2LDRB_POST : T2Iidxldst<0, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn), + (ins GPR:$base, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu, - "ldrb", "\t$dst, [$base], $offset", "$base = $base_wb", + "ldrb", "\t$Rt, [$Rn], $addr", "$base = $Rn", []>; -def t2LDRH_PRE : T2Iidxldst<0, 0b01, 1, 1, (outs GPR:$dst, GPR:$base_wb), +def t2LDRH_PRE : T2Iidxldst<0, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn), (ins t2addrmode_imm8:$addr), AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu, - "ldrh", "\t$dst, $addr!", "$addr.base = $base_wb", + "ldrh", "\t$Rt, $addr!", "$addr.base = $Rn", []>; -def t2LDRH_POST : T2Iidxldst<0, 0b01, 1, 0, (outs GPR:$dst, GPR:$base_wb), - (ins GPR:$base, t2am_imm8_offset:$offset), +def t2LDRH_POST : T2Iidxldst<0, 0b01, 1, 0, (outs GPR:$Rt, GPR:$Rn), + (ins GPR:$base, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu, - "ldrh", "\t$dst, [$base], $offset", "$base = $base_wb", + "ldrh", "\t$Rt, [$Rn], $addr", "$base = $Rn", []>; -def t2LDRSB_PRE : T2Iidxldst<1, 0b00, 1, 1, (outs GPR:$dst, GPR:$base_wb), +def t2LDRSB_PRE : T2Iidxldst<1, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn), (ins t2addrmode_imm8:$addr), AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu, - "ldrsb", "\t$dst, $addr!", "$addr.base = $base_wb", + "ldrsb", "\t$Rt, $addr!", "$addr.base = $Rn", []>; -def t2LDRSB_POST : T2Iidxldst<1, 0b00, 1, 0, (outs GPR:$dst, GPR:$base_wb), - (ins GPR:$base, t2am_imm8_offset:$offset), +def t2LDRSB_POST : T2Iidxldst<1, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn), + (ins GPR:$base, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu, - "ldrsb", "\t$dst, [$base], $offset", "$base = $base_wb", + "ldrsb", "\t$Rt, [$Rn], $addr", "$base = $Rn", []>; -def t2LDRSH_PRE : T2Iidxldst<1, 0b01, 1, 1, (outs GPR:$dst, GPR:$base_wb), +def t2LDRSH_PRE : T2Iidxldst<1, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn), (ins t2addrmode_imm8:$addr), AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu, - "ldrsh", "\t$dst, $addr!", "$addr.base = $base_wb", + "ldrsh", "\t$Rt, $addr!", "$addr.base = $Rn", []>; -def t2LDRSH_POST : T2Iidxldst<1, 0b01, 1, 0, (outs GPR:$dst, GPR:$base_wb), - (ins GPR:$base, t2am_imm8_offset:$offset), +def t2LDRSH_POST : T2Iidxldst<1, 0b01, 1, 0, (outs GPR:$dst, GPR:$Rn), + (ins GPR:$base, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu, - "ldrsh", "\t$dst, [$base], $offset", "$base = $base_wb", + "ldrsh", "\t$dst, [$Rn], $addr", "$base = $Rn", []>; -} // mayLoad = 1, neverHasSideEffects = 1 +} // mayLoad = 1, neverHasSideEffects = 1 // LDRT, LDRBT, LDRHT, LDRSBT, LDRSHT all have offset mode (PUW=0b110) and are // for disassembly only. // Ref: A8.6.57 LDR (immediate, Thumb) Encoding T4 class T2IldT type, string opc, InstrItinClass ii> - : T2Ii8<(outs GPR:$dst), (ins t2addrmode_imm8:$addr), ii, opc, - "\t$dst, $addr", []> { + : T2Ii8<(outs rGPR:$Rt), (ins t2addrmode_imm8:$addr), ii, opc, + "\t$Rt, $addr", []> { let Inst{31-27} = 0b11111; let Inst{26-25} = 0b00; let Inst{24} = signed; @@ -1342,6 +1376,12 @@ class T2IldT type, string opc, InstrItinClass ii> let Inst{20} = 1; // load let Inst{11} = 1; let Inst{10-8} = 0b110; // PUW. + + bits<4> Rt; + bits<13> addr; + let Inst{15-12} = Rt; + let Inst{19-16} = addr{12-9}; + let Inst{7-0} = addr{7-0}; } def t2LDRT : T2IldT<0, 0b10, "ldrt", IIC_iLoad_i>; @@ -1359,61 +1399,66 @@ defm t2STRH:T2I_st<0b01,"strh", IIC_iStore_bh_i, IIC_iStore_bh_si, BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>; // Store doubleword -let mayLoad = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1, - isCodeGenOnly = 1 in // $src2 doesn't exist in asm string +let mayLoad = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in def t2STRDi8 : T2Ii8s4<1, 0, 0, (outs), - (ins GPR:$src1, GPR:$src2, t2addrmode_imm8s4:$addr), - IIC_iStore_d_r, "strd", "\t$src1, $addr", []>; + (ins GPR:$Rt, GPR:$Rt2, t2addrmode_imm8s4:$addr), + IIC_iStore_d_r, "strd", "\t$Rt, $Rt2, $addr", []>; // Indexed stores def t2STR_PRE : T2Iidxldst<0, 0b10, 0, 1, (outs GPR:$base_wb), - (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), + (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePre, IIC_iStore_iu, - "str", "\t$src, [$base, $offset]!", "$base = $base_wb", + "str", "\t$Rt, [$Rn, $addr]!", + "$Rn = $base_wb,@earlyclobber $base_wb", [(set GPR:$base_wb, - (pre_store GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; + (pre_store GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; def t2STR_POST : T2Iidxldst<0, 0b10, 0, 0, (outs GPR:$base_wb), - (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), + (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePost, IIC_iStore_iu, - "str", "\t$src, [$base], $offset", "$base = $base_wb", + "str", "\t$Rt, [$Rn], $addr", + "$Rn = $base_wb,@earlyclobber $base_wb", [(set GPR:$base_wb, - (post_store GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; + (post_store GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; def t2STRH_PRE : T2Iidxldst<0, 0b01, 0, 1, (outs GPR:$base_wb), - (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), + (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePre, IIC_iStore_iu, - "strh", "\t$src, [$base, $offset]!", "$base = $base_wb", + "strh", "\t$Rt, [$Rn, $addr]!", + "$Rn = $base_wb,@earlyclobber $base_wb", [(set GPR:$base_wb, - (pre_truncsti16 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; + (pre_truncsti16 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; def t2STRH_POST : T2Iidxldst<0, 0b01, 0, 0, (outs GPR:$base_wb), - (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), + (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu, - "strh", "\t$src, [$base], $offset", "$base = $base_wb", + "strh", "\t$Rt, [$Rn], $addr", + "$Rn = $base_wb,@earlyclobber $base_wb", [(set GPR:$base_wb, - (post_truncsti16 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; + (post_truncsti16 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; def t2STRB_PRE : T2Iidxldst<0, 0b00, 0, 1, (outs GPR:$base_wb), - (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), + (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePre, IIC_iStore_bh_iu, - "strb", "\t$src, [$base, $offset]!", "$base = $base_wb", + "strb", "\t$Rt, [$Rn, $addr]!", + "$Rn = $base_wb,@earlyclobber $base_wb", [(set GPR:$base_wb, - (pre_truncsti8 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; + (pre_truncsti8 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; def t2STRB_POST : T2Iidxldst<0, 0b00, 0, 0, (outs GPR:$base_wb), - (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), + (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu, - "strb", "\t$src, [$base], $offset", "$base = $base_wb", + "strb", "\t$Rt, [$Rn], $addr", + "$Rn = $base_wb,@earlyclobber $base_wb", [(set GPR:$base_wb, - (post_truncsti8 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; + (post_truncsti8 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; // STRT, STRBT, STRHT all have offset mode (PUW=0b110) and are for disassembly // only. // Ref: A8.6.193 STR (immediate, Thumb) Encoding T4 class T2IstT type, string opc, InstrItinClass ii> - : T2Ii8<(outs GPR:$src), (ins t2addrmode_imm8:$addr), ii, opc, - "\t$src, $addr", []> { + : T2Ii8<(outs rGPR:$Rt), (ins t2addrmode_imm8:$addr), ii, opc, + "\t$Rt, $addr", []> { let Inst{31-27} = 0b11111; let Inst{26-25} = 0b00; let Inst{24} = 0; // not signed @@ -1422,6 +1467,12 @@ class T2IstT type, string opc, InstrItinClass ii> let Inst{20} = 0; // store let Inst{11} = 1; let Inst{10-8} = 0b110; // PUW + + bits<4> Rt; + bits<13> addr; + let Inst{15-12} = Rt; + let Inst{19-16} = addr{12-9}; + let Inst{7-0} = addr{7-0}; } def t2STRT : T2IstT<0b10, "strt", IIC_iStore_i>; @@ -1431,21 +1482,21 @@ def t2STRHT : T2IstT<0b01, "strht", IIC_iStore_bh_i>; // ldrd / strd pre / post variants // For disassembly only. -def t2LDRD_PRE : T2Ii8s4<1, 1, 1, (outs GPR:$dst1, GPR:$dst2), +def t2LDRD_PRE : T2Ii8s4<1, 1, 1, (outs rGPR:$Rt, rGPR:$Rt2), (ins GPR:$base, t2am_imm8s4_offset:$imm), IIC_iLoad_d_ru, - "ldrd", "\t$dst1, $dst2, [$base, $imm]!", []>; + "ldrd", "\t$Rt, $Rt2, [$base, $imm]!", []>; -def t2LDRD_POST : T2Ii8s4<0, 1, 1, (outs GPR:$dst1, GPR:$dst2), +def t2LDRD_POST : T2Ii8s4<0, 1, 1, (outs rGPR:$Rt, rGPR:$Rt2), (ins GPR:$base, t2am_imm8s4_offset:$imm), IIC_iLoad_d_ru, - "ldrd", "\t$dst1, $dst2, [$base], $imm", []>; + "ldrd", "\t$Rt, $Rt2, [$base], $imm", []>; def t2STRD_PRE : T2Ii8s4<1, 1, 0, (outs), - (ins GPR:$src1, GPR:$src2, GPR:$base, t2am_imm8s4_offset:$imm), - IIC_iStore_d_ru, "strd", "\t$src1, $src2, [$base, $imm]!", []>; + (ins rGPR:$Rt, rGPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm), + IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, [$base, $imm]!", []>; def t2STRD_POST : T2Ii8s4<0, 1, 0, (outs), - (ins GPR:$src1, GPR:$src2, GPR:$base, t2am_imm8s4_offset:$imm), - IIC_iStore_d_ru, "strd", "\t$src1, $src2, [$base], $imm", []>; + (ins rGPR:$Rt, rGPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm), + IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, [$base], $imm", []>; // T2Ipl (Preload Data/Instruction) signals the memory system of possible future // data/instruction access. These are for disassembly only. @@ -1458,11 +1509,16 @@ multiclass T2Ipl write, bits<1> instr, string opc> { [(ARMPreload t2addrmode_imm12:$addr, (i32 write), (i32 instr))]> { let Inst{31-25} = 0b1111100; let Inst{24} = instr; - let Inst{23} = 1; // U = 1 let Inst{22} = 0; let Inst{21} = write; let Inst{20} = 1; let Inst{15-12} = 0b1111; + + bits<17> addr; + let addr{12} = 1; // add = TRUE + let Inst{19-16} = addr{16-13}; // Rn + let Inst{23} = addr{12}; // U + let Inst{11-0} = addr{11-0}; // imm12 } def i8 : T2Ii8<(outs), (ins t2addrmode_imm8:$addr), IIC_Preload, opc, @@ -1476,6 +1532,10 @@ multiclass T2Ipl write, bits<1> instr, string opc> { let Inst{20} = 1; let Inst{15-12} = 0b1111; let Inst{11-8} = 0b1100; + + bits<13> addr; + let Inst{19-16} = addr{12-9}; // Rn + let Inst{7-0} = addr{7-0}; // imm8 } def s : T2Iso<(outs), (ins t2addrmode_so_reg:$addr), IIC_Preload, opc, @@ -1489,20 +1549,11 @@ multiclass T2Ipl write, bits<1> instr, string opc> { let Inst{20} = 1; let Inst{15-12} = 0b1111; let Inst{11-6} = 0000000; - } - let isCodeGenOnly = 1 in - def pci : T2Ipc<(outs), (ins i32imm:$addr), IIC_Preload, opc, - "\t$addr", - []> { - let Inst{31-25} = 0b1111100; - let Inst{24} = write; - let Inst{23} = ?; // add = (U == 1) - let Inst{22} = 0; - let Inst{21} = instr; - let Inst{20} = 1; - let Inst{19-16} = 0b1111; // Rn = 0b1111 - let Inst{15-12} = 0b1111; + bits<10> addr; + let Inst{19-16} = addr{9-6}; // Rn + let Inst{3-0} = addr{5-2}; // Rm + let Inst{5-4} = addr{1-0}; // imm2 } } @@ -1521,7 +1572,7 @@ multiclass thumb2_ldst_mult { bits<4> Rn; bits<16> regs; - + let Inst{31-27} = 0b11101; let Inst{26-25} = 0b00; let Inst{24-23} = 0b01; // Increment After @@ -1536,7 +1587,7 @@ multiclass thumb2_ldst_mult { bits<4> Rn; bits<16> regs; - + let Inst{31-27} = 0b11101; let Inst{26-25} = 0b00; let Inst{24-23} = 0b01; // Increment After @@ -1599,7 +1650,6 @@ def t2MOVr : T2sTwoReg<(outs GPR:$Rd), (ins GPR:$Rm), IIC_iMOVr, let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = 0b0010; - let Inst{20} = ?; // The S bit. let Inst{19-16} = 0b1111; // Rn let Inst{14-12} = 0b000; let Inst{7-4} = 0b0000; @@ -1614,13 +1664,12 @@ def t2MOVi : T2sOneRegImm<(outs rGPR:$Rd), (ins t2_so_imm:$imm), IIC_iMOVi, let Inst{31-27} = 0b11110; let Inst{25} = 0; let Inst{24-21} = 0b0010; - let Inst{20} = ?; // The S bit. let Inst{19-16} = 0b1111; // Rn let Inst{15} = 0; } let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in -def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins i32imm:$imm), IIC_iMOVi, +def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins i32imm_hilo16:$imm), IIC_iMOVi, "movw", "\t$Rd, $imm", [(set rGPR:$Rd, imm0_65535:$imm)]> { let Inst{31-27} = 0b11110; @@ -1628,19 +1677,23 @@ def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins i32imm:$imm), IIC_iMOVi, let Inst{24-21} = 0b0010; let Inst{20} = 0; // The S bit. let Inst{15} = 0; - + bits<4> Rd; bits<16> imm; - - let Inst{11-8} = Rd{3-0}; + + let Inst{11-8} = Rd; let Inst{19-16} = imm{15-12}; let Inst{26} = imm{11}; let Inst{14-12} = imm{10-8}; let Inst{7-0} = imm{7-0}; } -let Constraints = "$src = $Rd" in -def t2MOVTi16 : T2I<(outs rGPR:$Rd), (ins rGPR:$src, i32imm:$imm), IIC_iMOVi, +def t2MOVi16_ga_pcrel : PseudoInst<(outs rGPR:$Rd), + (ins i32imm:$addr, pclabel:$id), IIC_iMOVi, []>; + +let Constraints = "$src = $Rd" in { +def t2MOVTi16 : T2I<(outs rGPR:$Rd), + (ins rGPR:$src, i32imm_hilo16:$imm), IIC_iMOVi, "movt", "\t$Rd, $imm", [(set rGPR:$Rd, (or (and rGPR:$src, 0xffff), lo16AllZero:$imm))]> { @@ -1649,17 +1702,21 @@ def t2MOVTi16 : T2I<(outs rGPR:$Rd), (ins rGPR:$src, i32imm:$imm), IIC_iMOVi, let Inst{24-21} = 0b0110; let Inst{20} = 0; // The S bit. let Inst{15} = 0; - + bits<4> Rd; bits<16> imm; - - let Inst{11-8} = Rd{3-0}; + + let Inst{11-8} = Rd; let Inst{19-16} = imm{15-12}; let Inst{26} = imm{11}; let Inst{14-12} = imm{10-8}; let Inst{7-0} = imm{7-0}; } +def t2MOVTi16_ga_pcrel : PseudoInst<(outs rGPR:$Rd), + (ins rGPR:$src, i32imm:$addr, pclabel:$id), IIC_iMOVi, []>; +} // Constraints + def : T2Pat<(or rGPR:$src, 0xffff0000), (t2MOVTi16 rGPR:$src, 0xffff)>; //===----------------------------------------------------------------------===// @@ -1731,10 +1788,8 @@ defm t2ADC : T2I_adde_sube_irs<0b1010, "adc", BinOpFrag<(adde_dead_carry node:$LHS, node:$RHS)>, 1>; defm t2SBC : T2I_adde_sube_irs<0b1011, "sbc", BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>>; -defm t2ADCS : T2I_adde_sube_s_irs<0b1010, "adc", - BinOpFrag<(adde_live_carry node:$LHS, node:$RHS)>, 1>; -defm t2SBCS : T2I_adde_sube_s_irs<0b1011, "sbc", - BinOpFrag<(sube_live_carry node:$LHS, node:$RHS)>>; +defm t2ADCS : T2I_adde_sube_s_irs, 1>; +defm t2SBCS : T2I_adde_sube_s_irs>; // RSB defm t2RSB : T2I_rbin_irs <0b1110, "rsb", @@ -1765,15 +1820,20 @@ def : T2Pat<(addc rGPR:$src, t2_so_imm_neg:$imm), // Effectively, the inverse interpretation of the carry flag already accounts // for part of the negation. let AddedComplexity = 1 in -def : T2Pat<(adde rGPR:$src, imm0_255_not:$imm), +def : T2Pat<(adde_dead_carry rGPR:$src, imm0_255_not:$imm), + (t2SBCri rGPR:$src, imm0_255_not:$imm)>; +def : T2Pat<(adde_dead_carry rGPR:$src, t2_so_imm_not:$imm), + (t2SBCri rGPR:$src, t2_so_imm_not:$imm)>; +let AddedComplexity = 1 in +def : T2Pat<(adde_live_carry rGPR:$src, imm0_255_not:$imm), (t2SBCSri rGPR:$src, imm0_255_not:$imm)>; -def : T2Pat<(adde rGPR:$src, t2_so_imm_not:$imm), +def : T2Pat<(adde_live_carry rGPR:$src, t2_so_imm_not:$imm), (t2SBCSri rGPR:$src, t2_so_imm_not:$imm)>; // Select Bytes -- for disassembly only -def t2SEL : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), NoItinerary, "sel", - "\t$dst, $a, $b", []> { +def t2SEL : T2ThreeReg<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), + NoItinerary, "sel", "\t$Rd, $Rn, $Rm", []> { let Inst{31-27} = 0b11111; let Inst{26-24} = 0b010; let Inst{23} = 0b1; @@ -1786,36 +1846,41 @@ def t2SEL : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), NoItinerary, "sel", // A6.3.13, A6.3.14, A6.3.15 Parallel addition and subtraction (signed/unsigned) // And Miscellaneous operations -- for disassembly only class T2I_pam op22_20, bits<4> op7_4, string opc, - list pat = [/* For disassembly only; pattern left blank */]> - : T2I<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), NoItinerary, opc, - "\t$Rd, $Rn, $Rm", pat> { + list pat = [/* For disassembly only; pattern left blank */], + dag iops = (ins rGPR:$Rn, rGPR:$Rm), + string asm = "\t$Rd, $Rn, $Rm"> + : T2I<(outs rGPR:$Rd), iops, NoItinerary, opc, asm, pat> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0101; let Inst{22-20} = op22_20; let Inst{15-12} = 0b1111; let Inst{7-4} = op7_4; - + bits<4> Rd; bits<4> Rn; bits<4> Rm; - - let Inst{11-8} = Rd{3-0}; - let Inst{19-16} = Rn{3-0}; - let Inst{3-0} = Rm{3-0}; + + let Inst{11-8} = Rd; + let Inst{19-16} = Rn; + let Inst{3-0} = Rm; } // Saturating add/subtract -- for disassembly only def t2QADD : T2I_pam<0b000, 0b1000, "qadd", - [(set rGPR:$Rd, (int_arm_qadd rGPR:$Rn, rGPR:$Rm))]>; + [(set rGPR:$Rd, (int_arm_qadd rGPR:$Rn, rGPR:$Rm))], + (ins rGPR:$Rm, rGPR:$Rn), "\t$Rd, $Rm, $Rn">; def t2QADD16 : T2I_pam<0b001, 0b0001, "qadd16">; def t2QADD8 : T2I_pam<0b000, 0b0001, "qadd8">; def t2QASX : T2I_pam<0b010, 0b0001, "qasx">; -def t2QDADD : T2I_pam<0b000, 0b1001, "qdadd">; -def t2QDSUB : T2I_pam<0b000, 0b1011, "qdsub">; +def t2QDADD : T2I_pam<0b000, 0b1001, "qdadd", [], + (ins rGPR:$Rm, rGPR:$Rn), "\t$Rd, $Rm, $Rn">; +def t2QDSUB : T2I_pam<0b000, 0b1011, "qdsub", [], + (ins rGPR:$Rm, rGPR:$Rn), "\t$Rd, $Rm, $Rn">; def t2QSAX : T2I_pam<0b110, 0b0001, "qsax">; def t2QSUB : T2I_pam<0b000, 0b1010, "qsub", - [(set rGPR:$Rd, (int_arm_qsub rGPR:$Rn, rGPR:$Rm))]>; + [(set rGPR:$Rd, (int_arm_qsub rGPR:$Rn, rGPR:$Rm))], + (ins rGPR:$Rm, rGPR:$Rn), "\t$Rd, $Rm, $Rn">; def t2QSUB16 : T2I_pam<0b101, 0b0001, "qsub16">; def t2QSUB8 : T2I_pam<0b100, 0b0001, "qsub8">; def t2UQADD16 : T2I_pam<0b001, 0b0101, "uqadd16">; @@ -1886,28 +1951,29 @@ def t2USAD8 : T2ThreeReg_mac<0, 0b111, 0b0000, (outs rGPR:$Rd), let Inst{15-12} = 0b1111; } def t2USADA8 : T2FourReg_mac<0, 0b111, 0b0000, (outs rGPR:$Rd), - (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), NoItinerary, + (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), NoItinerary, "usada8", "\t$Rd, $Rn, $Rm, $Ra", []>; // Signed/Unsigned saturate -- for disassembly only class T2SatI pattern> - : T2I { + : T2I { bits<4> Rd; bits<4> Rn; bits<5> sat_imm; bits<7> sh; - - let Inst{11-8} = Rd{3-0}; - let Inst{19-16} = Rn{3-0}; + + let Inst{11-8} = Rd; + let Inst{19-16} = Rn; let Inst{4-0} = sat_imm{4-0}; let Inst{21} = sh{6}; let Inst{14-12} = sh{4-2}; let Inst{7-6} = sh{1-0}; } -def t2SSAT: T2I<(outs rGPR:$Rd), (ins i32imm:$sat_imm, rGPR:$Rn, shift_imm:$sh), +def t2SSAT: T2SatI< + (outs rGPR:$Rd), (ins i32imm:$sat_imm, rGPR:$Rn, shift_imm:$sh), NoItinerary, "ssat", "\t$Rd, $sat_imm, $Rn$sh", [/* For disassembly only; pattern left blank */]> { let Inst{31-27} = 0b11110; @@ -1916,7 +1982,8 @@ def t2SSAT: T2I<(outs rGPR:$Rd), (ins i32imm:$sat_imm, rGPR:$Rn, shift_imm:$sh), let Inst{15} = 0; } -def t2SSAT16: T2I<(outs rGPR:$Rd), (ins i32imm:$sat_imm, rGPR:$Rn), NoItinerary, +def t2SSAT16: T2SatI< + (outs rGPR:$Rd), (ins i32imm:$sat_imm, rGPR:$Rn), NoItinerary, "ssat16", "\t$Rd, $sat_imm, $Rn", [/* For disassembly only; pattern left blank */]> { let Inst{31-27} = 0b11110; @@ -1928,8 +1995,9 @@ def t2SSAT16: T2I<(outs rGPR:$Rd), (ins i32imm:$sat_imm, rGPR:$Rn), NoItinerary, let Inst{7-6} = 0b00; // imm2 = '00' } -def t2USAT: T2I<(outs rGPR:$dst), (ins i32imm:$bit_pos, rGPR:$a, shift_imm:$sh), - NoItinerary, "usat", "\t$dst, $bit_pos, $a$sh", +def t2USAT: T2SatI< + (outs rGPR:$Rd), (ins i32imm:$sat_imm, rGPR:$Rn, shift_imm:$sh), + NoItinerary, "usat", "\t$Rd, $sat_imm, $Rn$sh", [/* For disassembly only; pattern left blank */]> { let Inst{31-27} = 0b11110; let Inst{25-22} = 0b1110; @@ -1937,8 +2005,9 @@ def t2USAT: T2I<(outs rGPR:$dst), (ins i32imm:$bit_pos, rGPR:$a, shift_imm:$sh), let Inst{15} = 0; } -def t2USAT16: T2I<(outs rGPR:$dst), (ins i32imm:$bit_pos, rGPR:$a), NoItinerary, - "usat16", "\t$dst, $bit_pos, $a", +def t2USAT16: T2SatI< + (outs rGPR:$dst), (ins i32imm:$sat_imm, rGPR:$Rn), NoItinerary, + "usat16", "\t$dst, $sat_imm, $Rn", [/* For disassembly only; pattern left blank */]> { let Inst{31-27} = 0b11110; let Inst{25-22} = 0b1110; @@ -1961,6 +2030,10 @@ defm t2LSR : T2I_sh_ir<0b01, "lsr", BinOpFrag<(srl node:$LHS, node:$RHS)>>; defm t2ASR : T2I_sh_ir<0b10, "asr", BinOpFrag<(sra node:$LHS, node:$RHS)>>; defm t2ROR : T2I_sh_ir<0b11, "ror", BinOpFrag<(rotr node:$LHS, node:$RHS)>>; +// (rotr x, (and y, 0x...1f)) ==> (ROR x, y) +def : Pat<(rotr rGPR:$lhs, (and rGPR:$rhs, lo5AllOne)), + (t2RORrr rGPR:$lhs, rGPR:$rhs)>; + let Uses = [CPSR] in { def t2RRX : T2sTwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iMOVsi, "rrx", "\t$Rd, $Rm", @@ -1968,14 +2041,13 @@ def t2RRX : T2sTwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iMOVsi, let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = 0b0010; - let Inst{20} = ?; // The S bit. let Inst{19-16} = 0b1111; // Rn let Inst{14-12} = 0b000; let Inst{7-4} = 0b0011; } } -let Defs = [CPSR] in { +let isCodeGenOnly = 1, Defs = [CPSR] in { def t2MOVsrl_flag : T2TwoRegShiftImm< (outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iMOVsi, "lsrs", ".w\t$Rd, $Rm, #1", @@ -2026,12 +2098,12 @@ defm t2BIC : T2I_bin_w_irs<0b0001, "bic", class T2BitFI pattern> - : T2I { + : T2I { bits<4> Rd; bits<5> msb; bits<5> lsb; - - let Inst{11-8} = Rd{3-0}; + + let Inst{11-8} = Rd; let Inst{4-0} = msb{4-0}; let Inst{14-12} = lsb{4-2}; let Inst{7-6} = lsb{1-0}; @@ -2041,8 +2113,8 @@ class T2TwoRegBitFI pattern> : T2BitFI { bits<4> Rn; - - let Inst{19-16} = Rn{3-0}; + + let Inst{19-16} = Rn; } let Constraints = "$src = $Rd" in @@ -2050,11 +2122,13 @@ def t2BFC : T2BitFI<(outs rGPR:$Rd), (ins rGPR:$src, bf_inv_mask_imm:$imm), IIC_iUNAsi, "bfc", "\t$Rd, $imm", [(set rGPR:$Rd, (and rGPR:$src, bf_inv_mask_imm:$imm))]> { let Inst{31-27} = 0b11110; + let Inst{26} = 0; // should be 0. let Inst{25} = 1; let Inst{24-20} = 0b10110; let Inst{19-16} = 0b1111; // Rn let Inst{15} = 0; - + let Inst{5} = 0; // should be 0. + bits<10> imm; let msb{4-0} = imm{9-5}; let lsb{4-0} = imm{4-0}; @@ -2079,20 +2153,43 @@ def t2UBFX: T2TwoRegBitFI< } // A8.6.18 BFI - Bitfield insert (Encoding T1) -let Constraints = "$src = $Rd" in -def t2BFI : T2TwoRegBitFI<(outs rGPR:$Rd), - (ins rGPR:$src, rGPR:$Rn, bf_inv_mask_imm:$imm), - IIC_iBITi, "bfi", "\t$Rd, $Rn, $imm", - [(set rGPR:$Rd, (ARMbfi rGPR:$src, rGPR:$Rn, - bf_inv_mask_imm:$imm))]> { - let Inst{31-27} = 0b11110; - let Inst{25} = 1; - let Inst{24-20} = 0b10110; - let Inst{15} = 0; - - bits<10> imm; - let msb{4-0} = imm{9-5}; - let lsb{4-0} = imm{4-0}; +let Constraints = "$src = $Rd" in { + def t2BFI : T2TwoRegBitFI<(outs rGPR:$Rd), + (ins rGPR:$src, rGPR:$Rn, bf_inv_mask_imm:$imm), + IIC_iBITi, "bfi", "\t$Rd, $Rn, $imm", + [(set rGPR:$Rd, (ARMbfi rGPR:$src, rGPR:$Rn, + bf_inv_mask_imm:$imm))]> { + let Inst{31-27} = 0b11110; + let Inst{26} = 0; // should be 0. + let Inst{25} = 1; + let Inst{24-20} = 0b10110; + let Inst{15} = 0; + let Inst{5} = 0; // should be 0. + + bits<10> imm; + let msb{4-0} = imm{9-5}; + let lsb{4-0} = imm{4-0}; + } + + // GNU as only supports this form of bfi (w/ 4 arguments) + let isAsmParserOnly = 1 in + def t2BFI4p : T2TwoRegBitFI<(outs rGPR:$Rd), + (ins rGPR:$src, rGPR:$Rn, lsb_pos_imm:$lsbit, + width_imm:$width), + IIC_iBITi, "bfi", "\t$Rd, $Rn, $lsbit, $width", + []> { + let Inst{31-27} = 0b11110; + let Inst{26} = 0; // should be 0. + let Inst{25} = 1; + let Inst{24-20} = 0b10110; + let Inst{15} = 0; + let Inst{5} = 0; // should be 0. + + bits<5> lsbit; + bits<5> width; + let msb{4-0} = width; // Custom encoder => lsb+width-1 + let lsb{4-0} = lsbit; + } } defm t2ORN : T2I_bin_irs<0b0011, "orn", @@ -2155,54 +2252,32 @@ def t2MLS: T2FourReg< // Extra precision multiplies with low / high results let neverHasSideEffects = 1 in { let isCommutable = 1 in { -def t2SMULL : T2FourReg< +def t2SMULL : T2MulLong<0b000, 0b0000, (outs rGPR:$Rd, rGPR:$Ra), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL64, - "smull", "\t$Rd, $Ra, $Rn, $Rm", []> { - let Inst{31-27} = 0b11111; - let Inst{26-23} = 0b0111; - let Inst{22-20} = 0b000; - let Inst{7-4} = 0b0000; -} + "smull", "\t$Rd, $Ra, $Rn, $Rm", []>; -def t2UMULL : T2FourReg< - (outs rGPR:$Rd, rGPR:$Ra), +def t2UMULL : T2MulLong<0b010, 0b0000, + (outs rGPR:$RdLo, rGPR:$RdHi), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL64, - "umull", "\t$Rd, $Ra, $Rn, $Rm", []> { - let Inst{31-27} = 0b11111; - let Inst{26-23} = 0b0111; - let Inst{22-20} = 0b010; - let Inst{7-4} = 0b0000; -} + "umull", "\t$RdLo, $RdHi, $Rn, $Rm", []>; } // isCommutable // Multiply + accumulate -def t2SMLAL : T2FourReg<(outs rGPR:$Ra, rGPR:$Rd), +def t2SMLAL : T2MulLong<0b100, 0b0000, + (outs rGPR:$RdLo, rGPR:$RdHi), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMAC64, - "smlal", "\t$Ra, $Rd, $Rn, $Rm", []>{ - let Inst{31-27} = 0b11111; - let Inst{26-23} = 0b0111; - let Inst{22-20} = 0b100; - let Inst{7-4} = 0b0000; -} + "smlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>; -def t2UMLAL : T2FourReg<(outs rGPR:$Ra, rGPR:$Rd), +def t2UMLAL : T2MulLong<0b110, 0b0000, + (outs rGPR:$RdLo, rGPR:$RdHi), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMAC64, - "umlal", "\t$Ra, $Rd, $Rn, $Rm", []>{ - let Inst{31-27} = 0b11111; - let Inst{26-23} = 0b0111; - let Inst{22-20} = 0b110; - let Inst{7-4} = 0b0000; -} + "umlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>; -def t2UMAAL : T2FourReg<(outs rGPR:$Ra, rGPR:$Rd), +def t2UMAAL : T2MulLong<0b110, 0b0110, + (outs rGPR:$RdLo, rGPR:$RdHi), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMAC64, - "umaal", "\t$Ra, $Rd, $Rn, $Rm", []>{ - let Inst{31-27} = 0b11111; - let Inst{26-23} = 0b0111; - let Inst{22-20} = 0b110; - let Inst{7-4} = 0b0110; -} + "umaal", "\t$RdLo, $RdHi, $Rn, $Rm", []>; } // neverHasSideEffects // Rounding variants of the below included for disassembly only @@ -2434,7 +2509,7 @@ def t2SMLALTT : T2FourReg_mac<1, 0b100, 0b1011, (outs rGPR:$Ra,rGPR:$Rd), // Dual halfword multiple: SMUAD, SMUSD, SMLAD, SMLSD, SMLALD, SMLSLD // These are for disassembly only. - + def t2SMUAD: T2ThreeReg_mac< 0, 0b010, 0b0000, (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMAC32, "smuad", "\t$Rd, $Rn, $Rm", []> { @@ -2495,7 +2570,7 @@ class T2I_misc op1, bits<2> op2, dag oops, dag iops, let Inst{15-12} = 0b1111; let Inst{7-6} = 0b10; let Inst{5-4} = op2; - let Rn{3-0} = Rm{3-0}; + let Rn{3-0} = Rm; } def t2CLZ : T2I_misc<0b11, 0b00, (outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iUNAr, @@ -2520,9 +2595,15 @@ def t2REVSH : T2I_misc<0b01, 0b11, (outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iUNAr, "revsh", ".w\t$Rd, $Rm", [(set rGPR:$Rd, (sext_inreg - (or (srl (and rGPR:$Rm, 0xFF00), (i32 8)), + (or (srl rGPR:$Rm, (i32 8)), (shl rGPR:$Rm, (i32 8))), i16))]>; +def : T2Pat<(sext_inreg (or (srl (and rGPR:$Rm, 0xFF00), (i32 8)), + (shl rGPR:$Rm, (i32 8))), i16), + (t2REVSH rGPR:$Rm)>; + +def : T2Pat<(sra (bswap rGPR:$Rm), (i32 16)), (t2REVSH rGPR:$Rm)>; + def t2PKHBT : T2ThreeReg< (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, shift_imm:$sh), IIC_iBITsi, "pkhbt", "\t$Rd, $Rn, $Rm$sh", @@ -2535,10 +2616,10 @@ def t2PKHBT : T2ThreeReg< let Inst{24-20} = 0b01100; let Inst{5} = 0; // BT form let Inst{4} = 0; - - bits<5> sh; - let Inst{14-12} = sh{4-2}; - let Inst{7-6} = sh{1-0}; + + bits<8> sh; + let Inst{14-12} = sh{7-5}; + let Inst{7-6} = sh{4-3}; } // Alternate cases for PKHBT where identities eliminate some nodes. @@ -2563,10 +2644,10 @@ def t2PKHTB : T2ThreeReg< let Inst{24-20} = 0b01100; let Inst{5} = 1; // TB form let Inst{4} = 0; - - bits<5> sh; - let Inst{14-12} = sh{4-2}; - let Inst{7-6} = sh{1-0}; + + bits<8> sh; + let Inst{14-12} = sh{7-5}; + let Inst{7-6} = sh{4-3}; } // Alternate cases for PKHTB where identities eliminate some nodes. Note that @@ -2585,9 +2666,13 @@ def : T2Pat<(or (and rGPR:$src1, 0xFFFF0000), defm t2CMP : T2I_cmp_irs<0b1101, "cmp", IIC_iCMPi, IIC_iCMPr, IIC_iCMPsi, BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>; -defm t2CMPz : T2I_cmp_irs<0b1101, "cmp", - IIC_iCMPi, IIC_iCMPr, IIC_iCMPsi, - BinOpFrag<(ARMcmpZ node:$LHS, node:$RHS)>>; + +def : T2Pat<(ARMcmpZ GPR:$lhs, t2_so_imm:$imm), + (t2CMPri GPR:$lhs, t2_so_imm:$imm)>; +def : T2Pat<(ARMcmpZ GPR:$lhs, rGPR:$rhs), + (t2CMPrr GPR:$lhs, rGPR:$rhs)>; +def : T2Pat<(ARMcmpZ GPR:$lhs, t2_so_reg:$rhs), + (t2CMPrs GPR:$lhs, t2_so_reg:$rhs)>; //FIXME: Disable CMN, as CCodes are backwards from compare expectations // Compare-to-zero still works out, just not the relationals @@ -2614,10 +2699,11 @@ defm t2TEQ : T2I_cmp_irs<0b0100, "teq", // FIXME: should be able to write a pattern for ARMcmov, but can't use // a two-value operand where a dag node expects two operands. :( let neverHasSideEffects = 1 in { -def t2MOVCCr : T2I<(outs rGPR:$dst), (ins rGPR:$false, rGPR:$true), IIC_iCMOVr, - "mov", ".w\t$dst, $true", - [/*(set rGPR:$dst, (ARMcmov rGPR:$false, rGPR:$true, imm:$cc, CCR:$ccr))*/]>, - RegConstraint<"$false = $dst"> { +def t2MOVCCr : T2TwoReg< + (outs rGPR:$Rd), (ins rGPR:$false, rGPR:$Rm), IIC_iCMOVr, + "mov", ".w\t$Rd, $Rm", + [/*(set rGPR:$Rd, (ARMcmov rGPR:$false, rGPR:$Rm, imm:$cc, CCR:$ccr))*/]>, + RegConstraint<"$false = $Rd"> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = 0b0010; @@ -2628,10 +2714,10 @@ def t2MOVCCr : T2I<(outs rGPR:$dst), (ins rGPR:$false, rGPR:$true), IIC_iCMOVr, } let isMoveImm = 1 in -def t2MOVCCi : T2I<(outs rGPR:$dst), (ins rGPR:$false, t2_so_imm:$true), - IIC_iCMOVi, "mov", ".w\t$dst, $true", -[/*(set rGPR:$dst,(ARMcmov rGPR:$false,t2_so_imm:$true, imm:$cc, CCR:$ccr))*/]>, - RegConstraint<"$false = $dst"> { +def t2MOVCCi : T2OneRegImm<(outs rGPR:$Rd), (ins rGPR:$false, t2_so_imm:$imm), + IIC_iCMOVi, "mov", ".w\t$Rd, $imm", +[/*(set rGPR:$Rd,(ARMcmov rGPR:$false,t2_so_imm:$imm, imm:$cc, CCR:$ccr))*/]>, + RegConstraint<"$false = $Rd"> { let Inst{31-27} = 0b11110; let Inst{25} = 0; let Inst{24-21} = 0b0010; @@ -2641,7 +2727,7 @@ def t2MOVCCi : T2I<(outs rGPR:$dst), (ins rGPR:$false, t2_so_imm:$true), } let isMoveImm = 1 in -def t2MOVCCi16 : T2I<(outs rGPR:$Rd), (ins rGPR:$false, i32imm:$imm), +def t2MOVCCi16 : T2I<(outs rGPR:$Rd), (ins rGPR:$false, i32imm_hilo16:$imm), IIC_iCMOVi, "movw", "\t$Rd, $imm", []>, RegConstraint<"$false = $Rd"> { @@ -2650,11 +2736,11 @@ def t2MOVCCi16 : T2I<(outs rGPR:$Rd), (ins rGPR:$false, i32imm:$imm), let Inst{24-21} = 0b0010; let Inst{20} = 0; // The S bit. let Inst{15} = 0; - + bits<4> Rd; bits<16> imm; - - let Inst{11-8} = Rd{3-0}; + + let Inst{11-8} = Rd; let Inst{19-16} = imm{15-12}; let Inst{26} = imm{11}; let Inst{14-12} = imm{10-8}; @@ -2667,11 +2753,11 @@ def t2MOVCCi32imm : PseudoInst<(outs rGPR:$dst), IIC_iCMOVix2, []>, RegConstraint<"$false = $dst">; let isMoveImm = 1 in -def t2MVNCCi : T2I<(outs rGPR:$dst), (ins rGPR:$false, t2_so_imm:$true), - IIC_iCMOVi, "mvn", ".w\t$dst, $true", -[/*(set rGPR:$dst,(ARMcmov rGPR:$false,t2_so_imm_not:$true, +def t2MVNCCi : T2OneRegImm<(outs rGPR:$Rd), (ins rGPR:$false, t2_so_imm:$imm), + IIC_iCMOVi, "mvn", ".w\t$Rd, $imm", +[/*(set rGPR:$Rd,(ARMcmov rGPR:$false,t2_so_imm_not:$imm, imm:$cc, CCR:$ccr))*/]>, - RegConstraint<"$false = $dst"> { + RegConstraint<"$false = $Rd"> { let Inst{31-27} = 0b11110; let Inst{25} = 0; let Inst{24-21} = 0b0011; @@ -2733,7 +2819,7 @@ def t2DSB : AInoP<(outs), (ins memb_opt:$opt), ThumbFrm, NoItinerary, } // ISB has only full system option -- for disassembly only -def t2ISB : T2I<(outs), (ins), NoItinerary, "isb", "", +def t2ISB : AInoP<(outs), (ins), ThumbFrm, NoItinerary, "isb", "", [/* For disassembly only; pattern left blank */]>, Requires<[IsThumb2, HasV7]> { let Inst{31-4} = 0xf3bf8f6; @@ -2750,6 +2836,11 @@ class T2I_ldrex opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz, let Inst{7-6} = 0b01; let Inst{5-4} = opcod; let Inst{3-0} = 0b1111; + + bits<4> addr; + bits<4> Rt; + let Inst{19-16} = addr; + let Inst{15-12} = Rt; } class T2I_strex opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz, InstrItinClass itin, string opc, string asm, string cstr, @@ -2760,60 +2851,88 @@ class T2I_strex opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz, let Inst{11-8} = rt2; let Inst{7-6} = 0b01; let Inst{5-4} = opcod; + + bits<4> Rd; + bits<4> addr; + bits<4> Rt; + let Inst{3-0} = Rd; + let Inst{19-16} = addr; + let Inst{15-12} = Rt; } let mayLoad = 1 in { -def t2LDREXB : T2I_ldrex<0b00, (outs rGPR:$dest), (ins rGPR:$ptr), AddrModeNone, - Size4Bytes, NoItinerary, "ldrexb", "\t$dest, [$ptr]", +def t2LDREXB : T2I_ldrex<0b00, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr), AddrModeNone, + Size4Bytes, NoItinerary, "ldrexb", "\t$Rt, $addr", "", []>; -def t2LDREXH : T2I_ldrex<0b01, (outs rGPR:$dest), (ins rGPR:$ptr), AddrModeNone, - Size4Bytes, NoItinerary, "ldrexh", "\t$dest, [$ptr]", +def t2LDREXH : T2I_ldrex<0b01, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr), AddrModeNone, + Size4Bytes, NoItinerary, "ldrexh", "\t$Rt, $addr", "", []>; -def t2LDREX : Thumb2I<(outs rGPR:$dest), (ins rGPR:$ptr), AddrModeNone, +def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_reg:$addr), AddrModeNone, Size4Bytes, NoItinerary, - "ldrex", "\t$dest, [$ptr]", "", + "ldrex", "\t$Rt, $addr", "", []> { let Inst{31-27} = 0b11101; let Inst{26-20} = 0b0000101; let Inst{11-8} = 0b1111; let Inst{7-0} = 0b00000000; // imm8 = 0 -} -def t2LDREXD : T2I_ldrex<0b11, (outs rGPR:$dest, rGPR:$dest2), (ins rGPR:$ptr), - AddrModeNone, Size4Bytes, NoItinerary, - "ldrexd", "\t$dest, $dest2, [$ptr]", "", - [], {?, ?, ?, ?}>; -} -let mayStore = 1, Constraints = "@earlyclobber $success" in { -def t2STREXB : T2I_strex<0b00, (outs rGPR:$success), (ins rGPR:$src, rGPR:$ptr), - AddrModeNone, Size4Bytes, NoItinerary, - "strexb", "\t$success, $src, [$ptr]", "", []>; -def t2STREXH : T2I_strex<0b01, (outs rGPR:$success), (ins rGPR:$src, rGPR:$ptr), + bits<4> Rt; + bits<4> addr; + let Inst{19-16} = addr; + let Inst{15-12} = Rt; +} +def t2LDREXD : T2I_ldrex<0b11, (outs rGPR:$Rt, rGPR:$Rt2), (ins t2addrmode_reg:$addr), AddrModeNone, Size4Bytes, NoItinerary, - "strexh", "\t$success, $src, [$ptr]", "", []>; -def t2STREX : Thumb2I<(outs rGPR:$success), (ins rGPR:$src, rGPR:$ptr), - AddrModeNone, Size4Bytes, NoItinerary, - "strex", "\t$success, $src, [$ptr]", "", - []> { + "ldrexd", "\t$Rt, $Rt2, $addr", "", + [], {?, ?, ?, ?}> { + bits<4> Rt2; + let Inst{11-8} = Rt2; +} +} + +let mayStore = 1, Constraints = "@earlyclobber $Rd" in { +def t2STREXB : T2I_strex<0b00, (outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr), + AddrModeNone, Size4Bytes, NoItinerary, + "strexb", "\t$Rd, $Rt, $addr", "", []>; +def t2STREXH : T2I_strex<0b01, (outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr), + AddrModeNone, Size4Bytes, NoItinerary, + "strexh", "\t$Rd, $Rt, $addr", "", []>; +def t2STREX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr), + AddrModeNone, Size4Bytes, NoItinerary, + "strex", "\t$Rd, $Rt, $addr", "", + []> { let Inst{31-27} = 0b11101; let Inst{26-20} = 0b0000100; let Inst{7-0} = 0b00000000; // imm8 = 0 -} -def t2STREXD : T2I_strex<0b11, (outs rGPR:$success), - (ins rGPR:$src, rGPR:$src2, rGPR:$ptr), + + bits<4> Rd; + bits<4> addr; + bits<4> Rt; + let Inst{11-8} = Rd; + let Inst{19-16} = addr; + let Inst{15-12} = Rt; +} +def t2STREXD : T2I_strex<0b11, (outs rGPR:$Rd), + (ins rGPR:$Rt, rGPR:$Rt2, t2addrmode_reg:$addr), AddrModeNone, Size4Bytes, NoItinerary, - "strexd", "\t$success, $src, $src2, [$ptr]", "", [], - {?, ?, ?, ?}>; + "strexd", "\t$Rd, $Rt, $Rt2, $addr", "", [], + {?, ?, ?, ?}> { + bits<4> Rt2; + let Inst{11-8} = Rt2; +} } // Clear-Exclusive is for disassembly only. -def t2CLREX : T2I<(outs), (ins), NoItinerary, "clrex", "", - [/* For disassembly only; pattern left blank */]>, - Requires<[IsARM, HasV7]> { - let Inst{31-20} = 0xf3b; +def t2CLREX : T2XI<(outs), (ins), NoItinerary, "clrex", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsThumb2, HasV7]> { + let Inst{31-16} = 0xf3bf; let Inst{15-14} = 0b10; + let Inst{13} = 0; let Inst{12} = 0; + let Inst{11-8} = 0b1111; let Inst{7-4} = 0b0010; + let Inst{3-0} = 0b1111; } //===----------------------------------------------------------------------===// @@ -2822,7 +2941,7 @@ def t2CLREX : T2I<(outs), (ins), NoItinerary, "clrex", "", // __aeabi_read_tp preserves the registers r1-r3. let isCall = 1, - Defs = [R0, R12, LR, CPSR] in { + Defs = [R0, R12, LR, CPSR], Uses = [SP] in { def t2TPsoft : T2XI<(outs), (ins), IIC_Br, "bl\t__aeabi_read_tp", [(set R0, ARMthread_pointer)]> { @@ -2840,16 +2959,15 @@ let isCall = 1, // 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 +// when we get here from a longjmp(). We force everything 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, 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, isCodeGenOnly = 1 in { + [ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR, + QQQQ0, QQQQ1, QQQQ2, QQQQ3 ], + hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1 in { def t2Int_eh_sjlj_setjmp : Thumb2XI<(outs), (ins tGPR:$src, tGPR:$val), AddrModeNone, SizeSpecial, NoItinerary, "", "", [(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>, @@ -2883,7 +3001,7 @@ def t2LDMIA_RET: T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, "$Rn = $wb", []> { bits<4> Rn; bits<16> regs; - + let Inst{31-27} = 0b11101; let Inst{26-25} = 0b00; let Inst{24-23} = 0b01; // Increment After @@ -2896,70 +3014,56 @@ def t2LDMIA_RET: T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, let isBranch = 1, isTerminator = 1, isBarrier = 1 in { let isPredicable = 1 in -def t2B : T2XI<(outs), (ins brtarget:$target), IIC_Br, +def t2B : T2XI<(outs), (ins uncondbrtarget:$target), IIC_Br, "b.w\t$target", [(br bb:$target)]> { let Inst{31-27} = 0b11110; let Inst{15-14} = 0b10; let Inst{12} = 1; -} -let isNotDuplicable = 1, isIndirectBranch = 1, - isCodeGenOnly = 1 in { // $id doesn't exist in asmstring, should be lowered. -def t2BR_JT : - T2JTI<(outs), - (ins GPR:$target, GPR:$index, jt2block_operand:$jt, i32imm:$id), - IIC_Br, "mov\tpc, $target$jt", - [(ARMbr2jt GPR:$target, GPR:$index, tjumptable:$jt, imm:$id)]> { - let Inst{31-27} = 0b11101; - let Inst{26-20} = 0b0100100; - let Inst{19-16} = 0b1111; - let Inst{14-12} = 0b000; - let Inst{11-8} = 0b1111; // Rd = pc - let Inst{7-4} = 0b0000; + bits<20> target; + let Inst{26} = target{19}; + let Inst{11} = target{18}; + let Inst{13} = target{17}; + let Inst{21-16} = target{16-11}; + let Inst{10-0} = target{10-0}; } -// FIXME: Add a non-pc based case that can be predicated. -let isCodeGenOnly = 1 in // $id doesn't exist in asm string, should be lowered. -def t2TBB : - T2JTI<(outs), - (ins tb_addrmode:$index, jt2block_operand:$jt, i32imm:$id), - IIC_Br, "tbb\t$index$jt", []> { - let Inst{31-27} = 0b11101; - let Inst{26-20} = 0b0001101; - let Inst{19-16} = 0b1111; // Rn = pc (table follows this instruction) - let Inst{15-8} = 0b11110000; - let Inst{7-4} = 0b0000; // B form -} +let isNotDuplicable = 1, isIndirectBranch = 1 in { +def t2BR_JT : t2PseudoInst<(outs), + (ins GPR:$target, GPR:$index, i32imm:$jt, i32imm:$id), + SizeSpecial, IIC_Br, + [(ARMbr2jt GPR:$target, GPR:$index, tjumptable:$jt, imm:$id)]>; -let isCodeGenOnly = 1 in // $id doesn't exist in asm string, should be lowered. -def t2TBH : - T2JTI<(outs), - (ins tb_addrmode:$index, jt2block_operand:$jt, i32imm:$id), - IIC_Br, "tbh\t$index$jt", []> { - let Inst{31-27} = 0b11101; - let Inst{26-20} = 0b0001101; - let Inst{19-16} = 0b1111; // Rn = pc (table follows this instruction) - let Inst{15-8} = 0b11110000; - let Inst{7-4} = 0b0001; // H form -} +// FIXME: Add a non-pc based case that can be predicated. +def t2TBB_JT : t2PseudoInst<(outs), + (ins GPR:$index, i32imm:$jt, i32imm:$id), + SizeSpecial, IIC_Br, []>; -// Generic versions of the above two instructions, for disassembly only +def t2TBH_JT : t2PseudoInst<(outs), + (ins GPR:$index, i32imm:$jt, i32imm:$id), + SizeSpecial, IIC_Br, []>; -def t2TBBgen : T2I<(outs), (ins GPR:$a, GPR:$b), IIC_Br, - "tbb", "\t[$a, $b]", []>{ - let Inst{31-27} = 0b11101; - let Inst{26-20} = 0b0001101; - let Inst{15-8} = 0b11110000; - let Inst{7-4} = 0b0000; // B form +def t2TBB : T2I<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_Br, + "tbb", "\t[$Rn, $Rm]", []> { + bits<4> Rn; + bits<4> Rm; + let Inst{31-20} = 0b111010001101; + let Inst{19-16} = Rn; + let Inst{15-5} = 0b11110000000; + let Inst{4} = 0; // B form + let Inst{3-0} = Rm; } -def t2TBHgen : T2I<(outs), (ins GPR:$a, GPR:$b), IIC_Br, - "tbh", "\t[$a, $b, lsl #1]", []> { - let Inst{31-27} = 0b11101; - let Inst{26-20} = 0b0001101; - let Inst{15-8} = 0b11110000; - let Inst{7-4} = 0b0001; // H form +def t2TBH : T2I<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_Br, + "tbh", "\t[$Rn, $Rm, lsl #1]", []> { + bits<4> Rn; + bits<4> Rm; + let Inst{31-20} = 0b111010001101; + let Inst{19-16} = Rn; + let Inst{15-5} = 0b11110000000; + let Inst{4} = 1; // H form + let Inst{3-0} = Rm; } } // isNotDuplicable, isIndirectBranch @@ -2974,6 +3078,16 @@ def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br, let Inst{31-27} = 0b11110; let Inst{15-14} = 0b10; let Inst{12} = 0; + + bits<4> p; + let Inst{25-22} = p; + + bits<21> target; + let Inst{26} = target{20}; + let Inst{11} = target{19}; + let Inst{13} = target{18}; + let Inst{21-16} = target{17-12}; + let Inst{10-0} = target{11-1}; } @@ -2985,6 +3099,11 @@ def t2IT : Thumb2XI<(outs), (ins it_pred:$cc, it_mask:$mask), // 16-bit instruction. let Inst{31-16} = 0x0000; let Inst{15-8} = 0b10111111; + + bits<4> cc; + bits<4> mask; + let Inst{7-4} = cc; + let Inst{3-0} = mask; } // Branch and Exchange Jazelle -- for disassembly only @@ -2996,22 +3115,44 @@ def t2BXJ : T2I<(outs), (ins rGPR:$func), NoItinerary, "bxj", "\t$func", let Inst{25-20} = 0b111100; let Inst{15-14} = 0b10; let Inst{12} = 0; + + bits<4> func; + let Inst{19-16} = func; } -// Change Processor State is a system instruction -- for disassembly only. -// The singleton $opt operand contains the following information: -// opt{4-0} = mode from Inst{4-0} -// opt{5} = changemode from Inst{17} -// opt{8-6} = AIF from Inst{8-6} -// opt{10-9} = imod from Inst{19-18} with 0b10 as enable and 0b11 as disable -def t2CPS : T2XI<(outs),(ins cps_opt:$opt), NoItinerary, "cps$opt", - [/* For disassembly only; pattern left blank */]> { +// Change Processor State is a system instruction -- for disassembly and +// parsing only. +// FIXME: Since the asm parser has currently no clean way to handle optional +// operands, create 3 versions of the same instruction. Once there's a clean +// framework to represent optional operands, change this behavior. +class t2CPS : T2XI<(outs), iops, NoItinerary, + !strconcat("cps", asm_op), + [/* For disassembly only; pattern left blank */]> { + bits<2> imod; + bits<3> iflags; + bits<5> mode; + bit M; + let Inst{31-27} = 0b11110; - let Inst{26} = 0; + let Inst{26} = 0; let Inst{25-20} = 0b111010; + let Inst{19-16} = 0b1111; let Inst{15-14} = 0b10; - let Inst{12} = 0; -} + let Inst{12} = 0; + let Inst{10-9} = imod; + let Inst{8} = M; + let Inst{7-5} = iflags; + let Inst{4-0} = mode; +} + +let M = 1 in + def t2CPS3p : t2CPS<(ins imod_op:$imod, iflags_op:$iflags, i32imm:$mode), + "$imod.w\t$iflags, $mode">; +let mode = 0, M = 0 in + def t2CPS2p : t2CPS<(ins imod_op:$imod, iflags_op:$iflags), + "$imod.w\t$iflags">; +let imod = 0, iflags = 0, M = 1 in + def t2CPS1p : t2CPS<(ins i32imm:$mode), "\t$mode">; // A6.3.4 Branches and miscellaneous control // Table A6-14 Change Processor State, and hint instructions @@ -3020,6 +3161,7 @@ class T2I_hint op7_0, string opc, string asm> : T2I<(outs), (ins), NoItinerary, opc, asm, [/* For disassembly only; pattern left blank */]> { let Inst{31-20} = 0xf3a; + let Inst{19-16} = 0b1111; let Inst{15-14} = 0b10; let Inst{12} = 0; let Inst{10-8} = 0b000; @@ -3039,6 +3181,9 @@ def t2DBG : T2I<(outs),(ins i32imm:$opt), NoItinerary, "dbg", "\t$opt", let Inst{12} = 0; let Inst{10-8} = 0b000; let Inst{7-4} = 0b1111; + + bits<4> opt; + let Inst{3-0} = opt; } // Secure Monitor Call is a system instruction -- for disassembly only @@ -3048,57 +3193,59 @@ def t2SMC : T2I<(outs), (ins i32imm:$opt), NoItinerary, "smc", "\t$opt", let Inst{31-27} = 0b11110; let Inst{26-20} = 0b1111111; let Inst{15-12} = 0b1000; -} -// Store Return State is a system instruction -- for disassembly only -def t2SRSDBW : T2I<(outs),(ins i32imm:$mode),NoItinerary,"srsdb","\tsp!, $mode", - [/* For disassembly only; pattern left blank */]> { - let Inst{31-27} = 0b11101; - let Inst{26-20} = 0b0000010; // W = 1 + bits<4> opt; + let Inst{19-16} = opt; } -def t2SRSDB : T2I<(outs),(ins i32imm:$mode),NoItinerary,"srsdb","\tsp, $mode", - [/* For disassembly only; pattern left blank */]> { - let Inst{31-27} = 0b11101; - let Inst{26-20} = 0b0000000; // W = 0 -} +class T2SRS op31_20, + dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : T2I { + let Inst{31-20} = op31_20{11-0}; -def t2SRSIAW : T2I<(outs),(ins i32imm:$mode),NoItinerary,"srsia","\tsp!, $mode", - [/* For disassembly only; pattern left blank */]> { - let Inst{31-27} = 0b11101; - let Inst{26-20} = 0b0011010; // W = 1 + bits<5> mode; + let Inst{4-0} = mode{4-0}; } -def t2SRSIA : T2I<(outs), (ins i32imm:$mode),NoItinerary,"srsia","\tsp, $mode", - [/* For disassembly only; pattern left blank */]> { - let Inst{31-27} = 0b11101; - let Inst{26-20} = 0b0011000; // W = 0 -} +// Store Return State is a system instruction -- for disassembly only +def t2SRSDBW : T2SRS<0b111010000010, + (outs),(ins i32imm:$mode),NoItinerary,"srsdb","\tsp!, $mode", + [/* For disassembly only; pattern left blank */]>; +def t2SRSDB : T2SRS<0b111010000000, + (outs),(ins i32imm:$mode),NoItinerary,"srsdb","\tsp, $mode", + [/* For disassembly only; pattern left blank */]>; +def t2SRSIAW : T2SRS<0b111010011010, + (outs),(ins i32imm:$mode),NoItinerary,"srsia","\tsp!, $mode", + [/* For disassembly only; pattern left blank */]>; +def t2SRSIA : T2SRS<0b111010011000, + (outs), (ins i32imm:$mode),NoItinerary,"srsia","\tsp, $mode", + [/* For disassembly only; pattern left blank */]>; // Return From Exception is a system instruction -- for disassembly only -def t2RFEDBW : T2I<(outs), (ins rGPR:$base), NoItinerary, "rfedb", "\t$base!", - [/* For disassembly only; pattern left blank */]> { - let Inst{31-27} = 0b11101; - let Inst{26-20} = 0b0000011; // W = 1 -} -def t2RFEDB : T2I<(outs), (ins rGPR:$base), NoItinerary, "rfeab", "\t$base", - [/* For disassembly only; pattern left blank */]> { - let Inst{31-27} = 0b11101; - let Inst{26-20} = 0b0000001; // W = 0 -} - -def t2RFEIAW : T2I<(outs), (ins rGPR:$base), NoItinerary, "rfeia", "\t$base!", - [/* For disassembly only; pattern left blank */]> { - let Inst{31-27} = 0b11101; - let Inst{26-20} = 0b0011011; // W = 1 -} +class T2RFE op31_20, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : T2I { + let Inst{31-20} = op31_20{11-0}; -def t2RFEIA : T2I<(outs), (ins rGPR:$base), NoItinerary, "rfeia", "\t$base", - [/* For disassembly only; pattern left blank */]> { - let Inst{31-27} = 0b11101; - let Inst{26-20} = 0b0011001; // W = 0 -} + bits<4> Rn; + let Inst{19-16} = Rn; + let Inst{15-0} = 0xc000; +} + +def t2RFEDBW : T2RFE<0b111010000011, + (outs), (ins GPR:$Rn), NoItinerary, "rfedb", "\t$Rn!", + [/* For disassembly only; pattern left blank */]>; +def t2RFEDB : T2RFE<0b111010000001, + (outs), (ins GPR:$Rn), NoItinerary, "rfedb", "\t$Rn", + [/* For disassembly only; pattern left blank */]>; +def t2RFEIAW : T2RFE<0b111010011011, + (outs), (ins GPR:$Rn), NoItinerary, "rfeia", "\t$Rn!", + [/* For disassembly only; pattern left blank */]>; +def t2RFEIA : T2RFE<0b111010011001, + (outs), (ins GPR:$Rn), NoItinerary, "rfeia", "\t$Rn", + [/* For disassembly only; pattern left blank */]>; //===----------------------------------------------------------------------===// // Non-Instruction Patterns @@ -3112,6 +3259,22 @@ def t2MOVi32imm : PseudoInst<(outs rGPR:$dst), (ins i32imm:$src), IIC_iMOVix2, [(set rGPR:$dst, (i32 imm:$src))]>, Requires<[IsThumb, HasV6T2]>; +// Pseudo instruction that combines movw + movt + add pc (if pic). +// It also makes it possible to rematerialize the instructions. +// FIXME: Remove this when we can do generalized remat and when machine licm +// can properly the instructions. +let isReMaterializable = 1 in { +def t2MOV_ga_pcrel : PseudoInst<(outs rGPR:$dst), (ins i32imm:$addr), + IIC_iMOVix2addpc, + [(set rGPR:$dst, (ARMWrapperPIC tglobaladdr:$addr))]>, + Requires<[IsThumb2, UseMovt]>; + +def t2MOV_ga_dyn : PseudoInst<(outs rGPR:$dst), (ins i32imm:$addr), + IIC_iMOVix2, + [(set rGPR:$dst, (ARMWrapperDYN tglobaladdr:$addr))]>, + Requires<[IsThumb2, UseMovt]>; +} + // ConstantPool, GlobalAddress, and JumpTable def : T2Pat<(ARMWrapper tglobaladdr :$dst), (t2LEApcrel tglobaladdr :$dst)>, Requires<[IsThumb2, DontUseMovt]>; @@ -3126,9 +3289,9 @@ def : T2Pat<(ARMWrapperJT tjumptable:$dst, imm:$id), // be expanded into two instructions late to allow if-conversion and // scheduling. let canFoldAsLoad = 1, isReMaterializable = 1 in -def t2LDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp), +def t2LDRpci_pic : PseudoInst<(outs rGPR:$dst), (ins i32imm:$addr, pclabel:$cp), IIC_iLoadiALU, - [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)), + [(set rGPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)), imm:$cp))]>, Requires<[IsThumb2]>; @@ -3136,48 +3299,140 @@ def t2LDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp), // Move between special register and ARM core register -- for disassembly only // -// Rd = Instr{11-8} -def t2MRS : T2I<(outs rGPR:$dst), (ins), NoItinerary, "mrs", "\t$dst, cpsr", - [/* For disassembly only; pattern left blank */]> { - let Inst{31-27} = 0b11110; - let Inst{26} = 0; - let Inst{25-21} = 0b11111; - let Inst{20} = 0; // The R bit. - let Inst{15-14} = 0b10; - let Inst{12} = 0; +class T2SpecialReg op31_20, bits<2> op15_14, bits<1> op12, + dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : T2I { + let Inst{31-20} = op31_20{11-0}; + let Inst{15-14} = op15_14{1-0}; + let Inst{12} = op12{0}; } -// Rd = Instr{11-8} -def t2MRSsys : T2I<(outs rGPR:$dst), (ins), NoItinerary, "mrs", "\t$dst, spsr", - [/* For disassembly only; pattern left blank */]> { - let Inst{31-27} = 0b11110; - let Inst{26} = 0; - let Inst{25-21} = 0b11111; - let Inst{20} = 1; // The R bit. - let Inst{15-14} = 0b10; - let Inst{12} = 0; +class T2MRS op31_20, bits<2> op15_14, bits<1> op12, + dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : T2SpecialReg { + bits<4> Rd; + let Inst{11-8} = Rd; + let Inst{19-16} = 0b1111; } -// Rn = Inst{19-16} -def t2MSR : T2I<(outs), (ins rGPR:$src, msr_mask:$mask), NoItinerary, "msr", - "\tcpsr$mask, $src", - [/* For disassembly only; pattern left blank */]> { - let Inst{31-27} = 0b11110; - let Inst{26} = 0; - let Inst{25-21} = 0b11100; - let Inst{20} = 0; // The R bit. - let Inst{15-14} = 0b10; - let Inst{12} = 0; +def t2MRS : T2MRS<0b111100111110, 0b10, 0, + (outs rGPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, cpsr", + [/* For disassembly only; pattern left blank */]>; +def t2MRSsys : T2MRS<0b111100111111, 0b10, 0, + (outs rGPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, spsr", + [/* For disassembly only; pattern left blank */]>; + +// Move from ARM core register to Special Register +// +// No need to have both system and application versions, the encodings are the +// same and the assembly parser has no way to distinguish between them. The mask +// operand contains the special register (R Bit) in bit 4 and bits 3-0 contains +// the mask with the fields to be accessed in the special register. +def t2MSR : T2SpecialReg<0b111100111000 /* op31-20 */, 0b10 /* op15-14 */, + 0 /* op12 */, (outs), (ins msr_mask:$mask, rGPR:$Rn), + NoItinerary, "msr", "\t$mask, $Rn", + [/* For disassembly only; pattern left blank */]> { + bits<5> mask; + bits<4> Rn; + let Inst{19-16} = Rn; + let Inst{20} = mask{4}; // R Bit + let Inst{13} = 0b0; + let Inst{11-8} = mask{3-0}; } -// Rn = Inst{19-16} -def t2MSRsys : T2I<(outs), (ins rGPR:$src, msr_mask:$mask), NoItinerary, "msr", - "\tspsr$mask, $src", - [/* For disassembly only; pattern left blank */]> { - let Inst{31-27} = 0b11110; - let Inst{26} = 0; - let Inst{25-21} = 0b11100; - let Inst{20} = 1; // The R bit. - let Inst{15-14} = 0b10; - let Inst{12} = 0; +//===----------------------------------------------------------------------===// +// Move between coprocessor and ARM core register -- for disassembly only +// + +class t2MovRCopro pattern> + : T2Cop { + let Inst{27-24} = 0b1110; + let Inst{20} = direction; + let Inst{4} = 1; + + bits<4> Rt; + bits<4> cop; + bits<3> opc1; + bits<3> opc2; + bits<4> CRm; + bits<4> CRn; + + let Inst{15-12} = Rt; + let Inst{11-8} = cop; + let Inst{23-21} = opc1; + let Inst{7-5} = opc2; + let Inst{3-0} = CRm; + let Inst{19-16} = CRn; +} + +def t2MCR2 : t2MovRCopro<"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), + [(int_arm_mcr2 imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn, + imm:$CRm, imm:$opc2)]>; +def t2MRC2 : t2MovRCopro<"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), []>; + +def : T2v6Pat<(int_arm_mrc2 imm:$cop, imm:$opc1, imm:$CRn, + imm:$CRm, imm:$opc2), + (t2MRC2 imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>; + +class t2MovRRCopro pattern = [/* For disassembly only */]> + : T2Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm), + !strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), pattern> { + let Inst{27-24} = 0b1100; + let Inst{23-21} = 0b010; + let Inst{20} = direction; + + bits<4> Rt; + bits<4> Rt2; + bits<4> cop; + bits<4> opc1; + bits<4> CRm; + + let Inst{15-12} = Rt; + let Inst{19-16} = Rt2; + let Inst{11-8} = cop; + let Inst{7-4} = opc1; + let Inst{3-0} = CRm; +} + +def t2MCRR2 : t2MovRRCopro<"mcrr2", + 0 /* from ARM core register to coprocessor */, + [(int_arm_mcrr2 imm:$cop, imm:$opc1, GPR:$Rt, + GPR:$Rt2, imm:$CRm)]>; +def t2MRRC2 : t2MovRRCopro<"mrrc2", + 1 /* from coprocessor to ARM core register */>; + +//===----------------------------------------------------------------------===// +// Other Coprocessor Instructions. For disassembly only. +// + +def t2CDP2 : T2Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, + c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), + "cdp2\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", + [(int_arm_cdp2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, + imm:$CRm, imm:$opc2)]> { + let Inst{27-24} = 0b1110; + + bits<4> opc1; + bits<4> CRn; + bits<4> CRd; + bits<4> cop; + bits<3> opc2; + bits<4> CRm; + + let Inst{3-0} = CRm; + let Inst{4} = 0; + let Inst{7-5} = opc2; + let Inst{11-8} = cop; + let Inst{15-12} = CRd; + let Inst{19-16} = CRn; + let Inst{23-20} = opc1; }