HexagonInstrInfo.td revision 252723
150397Sobrien//==- HexagonInstrInfo.td - Target Description for Hexagon -*- tablegen -*-===//
250397Sobrien//
350397Sobrien//                     The LLVM Compiler Infrastructure
450397Sobrien//
550397Sobrien// This file is distributed under the University of Illinois Open Source
650397Sobrien// License. See LICENSE.TXT for details.
750397Sobrien//
850397Sobrien//===----------------------------------------------------------------------===//
950397Sobrien//
1050397Sobrien// This file describes the Hexagon instructions in TableGen format.
1150397Sobrien//
1250397Sobrien//===----------------------------------------------------------------------===//
1350397Sobrien
1450397Sobrieninclude "HexagonInstrFormats.td"
1550397Sobrieninclude "HexagonOperands.td"
1650397Sobrien
1750397Sobrien//===----------------------------------------------------------------------===//
1850397Sobrien
1950397Sobrien// Multi-class for logical operators.
2050397Sobrienmulticlass ALU32_rr_ri<string OpcStr, SDNode OpNode> {
2150397Sobrien  def rr : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
2250397Sobrien                 !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")),
2350397Sobrien                 [(set (i32 IntRegs:$dst), (OpNode (i32 IntRegs:$b),
2450397Sobrien                                                   (i32 IntRegs:$c)))]>;
2550397Sobrien  def ri : ALU32_ri<(outs IntRegs:$dst), (ins s10Imm:$b, IntRegs:$c),
2650397Sobrien                 !strconcat("$dst = ", !strconcat(OpcStr, "(#$b, $c)")),
2750397Sobrien                 [(set (i32 IntRegs:$dst), (OpNode s10Imm:$b,
2850397Sobrien                                                   (i32 IntRegs:$c)))]>;
2950397Sobrien}
3050397Sobrien
3150397Sobrien// Multi-class for compare ops.
3250397Sobrienlet isCompare = 1 in {
3350397Sobrienmulticlass CMP64_rr<string OpcStr, PatFrag OpNode> {
3450397Sobrien  def rr : ALU64_rr<(outs PredRegs:$dst), (ins DoubleRegs:$b, DoubleRegs:$c),
3550397Sobrien                 !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")),
3650397Sobrien                 [(set (i1 PredRegs:$dst),
3750397Sobrien                       (OpNode (i64 DoubleRegs:$b), (i64 DoubleRegs:$c)))]>;
3850397Sobrien}
3950397Sobrien
4050397Sobrienmulticlass CMP32_rr_ri_s10<string OpcStr, string CextOp, PatFrag OpNode> {
4150397Sobrien  let CextOpcode = CextOp in {
4250397Sobrien    let InputType = "reg" in
4350397Sobrien    def rr : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
4450397Sobrien                   !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")),
4550397Sobrien                   [(set (i1 PredRegs:$dst),
4650397Sobrien                         (OpNode (i32 IntRegs:$b), (i32 IntRegs:$c)))]>;
4750397Sobrien
4850397Sobrien    let isExtendable = 1, opExtendable = 2, isExtentSigned = 1,
4950397Sobrien    opExtentBits = 10, InputType = "imm" in
5050397Sobrien    def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, s10Ext:$c),
5150397Sobrien                   !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")),
5250397Sobrien                   [(set (i1 PredRegs:$dst),
5350397Sobrien                         (OpNode (i32 IntRegs:$b), s10ExtPred:$c))]>;
5450397Sobrien  }
5550397Sobrien}
5650397Sobrien
5750397Sobrienmulticlass CMP32_rr_ri_u9<string OpcStr, string CextOp, PatFrag OpNode> {
5850397Sobrien  let CextOpcode = CextOp in {
5950397Sobrien    let InputType = "reg" in
6050397Sobrien    def rr : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
6150397Sobrien                   !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")),
6250397Sobrien                   [(set (i1 PredRegs:$dst),
6350397Sobrien                         (OpNode (i32 IntRegs:$b), (i32 IntRegs:$c)))]>;
6450397Sobrien
6550397Sobrien    let isExtendable = 1, opExtendable = 2, isExtentSigned = 0,
6650397Sobrien    opExtentBits = 9, InputType = "imm" in
6750397Sobrien    def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, u9Ext:$c),
6850397Sobrien                   !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")),
6950397Sobrien                   [(set (i1 PredRegs:$dst),
7050397Sobrien                         (OpNode (i32 IntRegs:$b), u9ExtPred:$c))]>;
7150397Sobrien  }
7250397Sobrien}
7350397Sobrien
7450397Sobrienmulticlass CMP32_ri_s8<string OpcStr, PatFrag OpNode> {
7550397Sobrienlet isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8 in
7650397Sobrien  def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, s8Ext:$c),
7750397Sobrien                 !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")),
7850397Sobrien                 [(set (i1 PredRegs:$dst), (OpNode (i32 IntRegs:$b),
7950397Sobrien                                                   s8ExtPred:$c))]>;
8050397Sobrien}
8150397Sobrien}
8250397Sobrien
8350397Sobrien//===----------------------------------------------------------------------===//
8450397Sobrien// ALU32/ALU (Instructions with register-register form)
8550397Sobrien//===----------------------------------------------------------------------===//
8650397Sobriendef SDTHexagonI64I32I32 : SDTypeProfile<1, 2,
8750397Sobrien  [SDTCisVT<0, i64>, SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>;
8850397Sobrien
8950397Sobriendef HexagonWrapperCombineII :
9050397Sobrien  SDNode<"HexagonISD::WrapperCombineII", SDTHexagonI64I32I32>;
9150397Sobrien
9250397Sobriendef HexagonWrapperCombineRR :
9350397Sobrien  SDNode<"HexagonISD::WrapperCombineRR", SDTHexagonI64I32I32>;
9450397Sobrien
9550397Sobrienmulticlass ALU32_Pbase<string mnemonic, RegisterClass RC, bit isNot,
9650397Sobrien                       bit isPredNew> {
9750397Sobrien  let isPredicatedNew = isPredNew in
9850397Sobrien  def NAME : ALU32_rr<(outs RC:$dst),
9950397Sobrien            (ins PredRegs:$src1, IntRegs:$src2, IntRegs: $src3),
10050397Sobrien            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew,".new) $dst = ",
10150397Sobrien            ") $dst = ")#mnemonic#"($src2, $src3)",
10250397Sobrien            []>;
10350397Sobrien}
10450397Sobrien
10550397Sobrienmulticlass ALU32_Pred<string mnemonic, RegisterClass RC, bit PredNot> {
10650397Sobrien  let isPredicatedFalse = PredNot in {
10750397Sobrien    defm _c#NAME : ALU32_Pbase<mnemonic, RC, PredNot, 0>;
10850397Sobrien    // Predicate new
10950397Sobrien    defm _cdn#NAME : ALU32_Pbase<mnemonic, RC, PredNot, 1>;
11050397Sobrien  }
11150397Sobrien}
11250397Sobrien
11350397Sobrienlet InputType = "reg" in
11450397Sobrienmulticlass ALU32_base<string mnemonic, string CextOp, SDNode OpNode> {
11550397Sobrien  let CextOpcode = CextOp, BaseOpcode = CextOp#_rr in {
11650397Sobrien    let isPredicable = 1 in
11750397Sobrien    def NAME : ALU32_rr<(outs IntRegs:$dst),
11850397Sobrien            (ins IntRegs:$src1, IntRegs:$src2),
11950397Sobrien            "$dst = "#mnemonic#"($src1, $src2)",
12050397Sobrien            [(set (i32 IntRegs:$dst), (OpNode (i32 IntRegs:$src1),
12150397Sobrien                                              (i32 IntRegs:$src2)))]>;
12250397Sobrien
12350397Sobrien    let neverHasSideEffects = 1, isPredicated = 1 in {
12450397Sobrien      defm Pt : ALU32_Pred<mnemonic, IntRegs, 0>;
12550397Sobrien      defm NotPt : ALU32_Pred<mnemonic, IntRegs, 1>;
12650397Sobrien    }
12750397Sobrien  }
12850397Sobrien}
12950397Sobrien
13050397Sobrienlet isCommutable = 1 in {
13150397Sobrien  defm ADD_rr : ALU32_base<"add", "ADD", add>, ImmRegRel, PredNewRel;
13250397Sobrien  defm AND_rr : ALU32_base<"and", "AND", and>, ImmRegRel, PredNewRel;
13350397Sobrien  defm XOR_rr : ALU32_base<"xor", "XOR", xor>, ImmRegRel, PredNewRel;
13450397Sobrien  defm OR_rr  : ALU32_base<"or", "OR", or>, ImmRegRel, PredNewRel;
13550397Sobrien}
13650397Sobrien
13750397Sobriendefm SUB_rr : ALU32_base<"sub", "SUB", sub>, ImmRegRel, PredNewRel;
13850397Sobrien
13950397Sobrien// Combines the two integer registers SRC1 and SRC2 into a double register.
14050397Sobrienlet isPredicable = 1 in
14150397Sobrienclass T_Combine : ALU32_rr<(outs DoubleRegs:$dst),
14250397Sobrien                           (ins IntRegs:$src1, IntRegs:$src2),
14350397Sobrien            "$dst = combine($src1, $src2)",
14450397Sobrien            [(set (i64 DoubleRegs:$dst),
14550397Sobrien              (i64 (HexagonWrapperCombineRR (i32 IntRegs:$src1),
14650397Sobrien                                            (i32 IntRegs:$src2))))]>;
14750397Sobrien
14850397Sobrienmulticlass Combine_base {
14950397Sobrien  let BaseOpcode = "combine" in {
15050397Sobrien    def NAME : T_Combine;
15150397Sobrien    let neverHasSideEffects = 1, isPredicated = 1 in {
15250397Sobrien      defm Pt : ALU32_Pred<"combine", DoubleRegs, 0>;
15350397Sobrien      defm NotPt : ALU32_Pred<"combine", DoubleRegs, 1>;
15450397Sobrien    }
15550397Sobrien  }
15650397Sobrien}
15750397Sobrien
15850397Sobriendefm COMBINE_rr : Combine_base, PredNewRel;
15950397Sobrien
16050397Sobrien// Combines the two immediates SRC1 and SRC2 into a double register.
16150397Sobrienclass COMBINE_imm<Operand imm1, Operand imm2, PatLeaf pat1, PatLeaf pat2> :
16250397Sobrien  ALU32_ii<(outs DoubleRegs:$dst), (ins imm1:$src1, imm2:$src2),
16350397Sobrien  "$dst = combine(#$src1, #$src2)",
16450397Sobrien  [(set (i64 DoubleRegs:$dst),
16550397Sobrien        (i64 (HexagonWrapperCombineII (i32 pat1:$src1), (i32 pat2:$src2))))]>;
16650397Sobrien
16750397Sobrienlet isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 8 in
16850397Sobriendef COMBINE_Ii : COMBINE_imm<s8Ext, s8Imm, s8ExtPred, s8ImmPred>;
16950397Sobrien
17050397Sobrien//===----------------------------------------------------------------------===//
17150397Sobrien// ALU32/ALU (ADD with register-immediate form)
17250397Sobrien//===----------------------------------------------------------------------===//
17350397Sobrienmulticlass ALU32ri_Pbase<string mnemonic, bit isNot, bit isPredNew> {
17450397Sobrien  let isPredicatedNew = isPredNew in
17550397Sobrien  def NAME : ALU32_ri<(outs IntRegs:$dst),
17650397Sobrien            (ins PredRegs:$src1, IntRegs:$src2, s8Ext: $src3),
17750397Sobrien            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew,".new) $dst = ",
17850397Sobrien            ") $dst = ")#mnemonic#"($src2, #$src3)",
17950397Sobrien            []>;
18050397Sobrien}
18150397Sobrien
18250397Sobrienmulticlass ALU32ri_Pred<string mnemonic, bit PredNot> {
18350397Sobrien  let isPredicatedFalse = PredNot in {
18450397Sobrien    defm _c#NAME : ALU32ri_Pbase<mnemonic, PredNot, 0>;
18550397Sobrien    // Predicate new
18650397Sobrien    defm _cdn#NAME : ALU32ri_Pbase<mnemonic, PredNot, 1>;
18750397Sobrien  }
18850397Sobrien}
18950397Sobrien
19050397Sobrienlet isExtendable = 1, InputType = "imm" in
19150397Sobrienmulticlass ALU32ri_base<string mnemonic, string CextOp, SDNode OpNode> {
19250397Sobrien  let CextOpcode = CextOp, BaseOpcode = CextOp#_ri in {
19350397Sobrien    let opExtendable = 2, isExtentSigned = 1, opExtentBits = 16,
19450397Sobrien    isPredicable = 1 in
19550397Sobrien    def NAME : ALU32_ri<(outs IntRegs:$dst),
19650397Sobrien            (ins IntRegs:$src1, s16Ext:$src2),
19750397Sobrien            "$dst = "#mnemonic#"($src1, #$src2)",
19850397Sobrien            [(set (i32 IntRegs:$dst), (OpNode (i32 IntRegs:$src1),
19950397Sobrien                                              (s16ExtPred:$src2)))]>;
20050397Sobrien
20150397Sobrien    let opExtendable = 3, isExtentSigned = 1, opExtentBits = 8,
20250397Sobrien    neverHasSideEffects = 1, isPredicated = 1 in {
20350397Sobrien      defm Pt : ALU32ri_Pred<mnemonic, 0>;
20450397Sobrien      defm NotPt : ALU32ri_Pred<mnemonic, 1>;
20550397Sobrien    }
20650397Sobrien  }
20750397Sobrien}
20850397Sobrien
20950397Sobriendefm ADD_ri : ALU32ri_base<"add", "ADD", add>, ImmRegRel, PredNewRel;
21050397Sobrien
21150397Sobrienlet isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 10,
21250397SobrienCextOpcode = "OR", InputType = "imm" in
21350397Sobriendef OR_ri : ALU32_ri<(outs IntRegs:$dst),
21450397Sobrien            (ins IntRegs:$src1, s10Ext:$src2),
21550397Sobrien            "$dst = or($src1, #$src2)",
21650397Sobrien            [(set (i32 IntRegs:$dst), (or (i32 IntRegs:$src1),
21750397Sobrien                                          s10ExtPred:$src2))]>, ImmRegRel;
21850397Sobrien
21950397Sobrienlet isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 10,
22050397SobrienInputType = "imm", CextOpcode = "AND" in
22150397Sobriendef AND_ri : ALU32_ri<(outs IntRegs:$dst),
22250397Sobrien            (ins IntRegs:$src1, s10Ext:$src2),
22350397Sobrien            "$dst = and($src1, #$src2)",
22450397Sobrien            [(set (i32 IntRegs:$dst), (and (i32 IntRegs:$src1),
22550397Sobrien                                           s10ExtPred:$src2))]>, ImmRegRel;
22650397Sobrien
22750397Sobrien// Nop.
22850397Sobrienlet neverHasSideEffects = 1 in
22950397Sobriendef NOP : ALU32_rr<(outs), (ins),
23050397Sobrien          "nop",
23150397Sobrien          []>;
23250397Sobrien
23350397Sobrien// Rd32=sub(#s10,Rs32)
23450397Sobrienlet isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 10,
23550397SobrienCextOpcode = "SUB", InputType = "imm" in
23650397Sobriendef SUB_ri : ALU32_ri<(outs IntRegs:$dst),
23750397Sobrien            (ins s10Ext:$src1, IntRegs:$src2),
23850397Sobrien            "$dst = sub(#$src1, $src2)",
23950397Sobrien            [(set IntRegs:$dst, (sub s10ExtPred:$src1, IntRegs:$src2))]>,
24050397Sobrien            ImmRegRel;
24150397Sobrien
24250397Sobrien// Rd = not(Rs) gets mapped to Rd=sub(#-1, Rs).
24350397Sobriendef : Pat<(not (i32 IntRegs:$src1)),
24450397Sobrien          (SUB_ri -1, (i32 IntRegs:$src1))>;
24550397Sobrien
24650397Sobrien// Rd = neg(Rs) gets mapped to Rd=sub(#0, Rs).
24750397Sobrien// Pattern definition for 'neg' was not necessary.
24850397Sobrien
24950397Sobrienmulticlass TFR_Pred<bit PredNot> {
25050397Sobrien  let isPredicatedFalse = PredNot in {
25150397Sobrien    def _c#NAME : ALU32_rr<(outs IntRegs:$dst),
25250397Sobrien                           (ins PredRegs:$src1, IntRegs:$src2),
25350397Sobrien            !if(PredNot, "if (!$src1", "if ($src1")#") $dst = $src2",
25450397Sobrien            []>;
25550397Sobrien    // Predicate new
25650397Sobrien    let isPredicatedNew = 1 in
25750397Sobrien    def _cdn#NAME : ALU32_rr<(outs IntRegs:$dst),
25850397Sobrien                             (ins PredRegs:$src1, IntRegs:$src2),
25950397Sobrien            !if(PredNot, "if (!$src1", "if ($src1")#".new) $dst = $src2",
26050397Sobrien            []>;
26150397Sobrien  }
26250397Sobrien}
26350397Sobrien
26450397Sobrienlet InputType = "reg", neverHasSideEffects = 1 in
26550397Sobrienmulticlass TFR_base<string CextOp> {
26650397Sobrien  let CextOpcode = CextOp, BaseOpcode = CextOp in {
26750397Sobrien    let isPredicable = 1 in
26850397Sobrien    def NAME : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1),
26950397Sobrien            "$dst = $src1",
27050397Sobrien            []>;
27150397Sobrien
27250397Sobrien    let  isPredicated = 1 in {
27350397Sobrien      defm Pt : TFR_Pred<0>;
27450397Sobrien      defm NotPt : TFR_Pred<1>;
27550397Sobrien    }
27650397Sobrien  }
27750397Sobrien}
27850397Sobrien
27950397Sobrienclass T_TFR64_Pred<bit PredNot, bit isPredNew>
28050397Sobrien            : ALU32_rr<(outs DoubleRegs:$dst),
28150397Sobrien                       (ins PredRegs:$src1, DoubleRegs:$src2),
28250397Sobrien            !if(PredNot, "if (!$src1", "if ($src1")#
28350397Sobrien            !if(isPredNew, ".new) ", ") ")#"$dst = $src2", []>
28450397Sobrien{
28550397Sobrien    bits<5> dst;
28650397Sobrien    bits<2> src1;
28750397Sobrien    bits<5> src2;
28850397Sobrien
28950397Sobrien    let IClass = 0b1111;
29050397Sobrien    let Inst{27-24} = 0b1101;
29150397Sobrien    let Inst{13} = isPredNew;
29250397Sobrien    let Inst{7} = PredNot;
29350397Sobrien    let Inst{4-0} = dst;
29450397Sobrien    let Inst{6-5} = src1;
29550397Sobrien    let Inst{20-17} = src2{4-1};
29650397Sobrien    let Inst{16} = 0b1;
29750397Sobrien    let Inst{12-9} = src2{4-1};
29850397Sobrien    let Inst{8} = 0b0;
29950397Sobrien}
30050397Sobrien
30150397Sobrienmulticlass TFR64_Pred<bit PredNot> {
30250397Sobrien  let isPredicatedFalse = PredNot in {
30350397Sobrien    def _c#NAME : T_TFR64_Pred<PredNot, 0>;
30450397Sobrien
30550397Sobrien    let isPredicatedNew = 1 in
30650397Sobrien    def _cdn#NAME : T_TFR64_Pred<PredNot, 1>; // Predicate new
30750397Sobrien  }
30850397Sobrien}
30950397Sobrien
31050397Sobrienlet neverHasSideEffects = 1 in
31150397Sobrienmulticlass TFR64_base<string BaseName> {
31250397Sobrien  let BaseOpcode = BaseName in {
31350397Sobrien    let isPredicable = 1 in
31450397Sobrien    def NAME : ALU32Inst <(outs DoubleRegs:$dst),
31550397Sobrien                          (ins DoubleRegs:$src1),
31650397Sobrien                          "$dst = $src1" > {
31750397Sobrien        bits<5> dst;
31850397Sobrien        bits<5> src1;
31950397Sobrien
32050397Sobrien        let IClass = 0b1111;
32150397Sobrien        let Inst{27-23} = 0b01010;
32250397Sobrien        let Inst{4-0} = dst;
32350397Sobrien        let Inst{20-17} = src1{4-1};
32450397Sobrien        let Inst{16} = 0b1;
32550397Sobrien        let Inst{12-9} = src1{4-1};
32650397Sobrien        let Inst{8} = 0b0;
32750397Sobrien    }
32850397Sobrien
32950397Sobrien    let  isPredicated = 1 in {
33050397Sobrien      defm Pt : TFR64_Pred<0>;
33150397Sobrien      defm NotPt : TFR64_Pred<1>;
33250397Sobrien    }
33350397Sobrien  }
33450397Sobrien}
33550397Sobrien
33650397Sobrienmulticlass TFRI_Pred<bit PredNot> {
33750397Sobrien  let isMoveImm = 1, isPredicatedFalse = PredNot in {
338    def _c#NAME : ALU32_ri<(outs IntRegs:$dst),
339                           (ins PredRegs:$src1, s12Ext:$src2),
340            !if(PredNot, "if (!$src1", "if ($src1")#") $dst = #$src2",
341            []>;
342
343    // Predicate new
344    let isPredicatedNew = 1 in
345    def _cdn#NAME : ALU32_rr<(outs IntRegs:$dst),
346                             (ins PredRegs:$src1, s12Ext:$src2),
347            !if(PredNot, "if (!$src1", "if ($src1")#".new) $dst = #$src2",
348            []>;
349  }
350}
351
352let InputType = "imm", isExtendable = 1, isExtentSigned = 1 in
353multiclass TFRI_base<string CextOp> {
354  let CextOpcode = CextOp, BaseOpcode = CextOp#I in {
355    let isAsCheapAsAMove = 1 , opExtendable = 1, opExtentBits = 16,
356    isMoveImm = 1, isPredicable = 1, isReMaterializable = 1 in
357    def NAME : ALU32_ri<(outs IntRegs:$dst), (ins s16Ext:$src1),
358            "$dst = #$src1",
359            [(set (i32 IntRegs:$dst), s16ExtPred:$src1)]>;
360
361    let opExtendable = 2,  opExtentBits = 12, neverHasSideEffects = 1,
362    isPredicated = 1 in {
363      defm Pt    : TFRI_Pred<0>;
364      defm NotPt : TFRI_Pred<1>;
365    }
366  }
367}
368
369defm TFRI : TFRI_base<"TFR">, ImmRegRel, PredNewRel;
370defm TFR : TFR_base<"TFR">, ImmRegRel, PredNewRel;
371defm TFR64 : TFR64_base<"TFR64">, PredNewRel;
372
373// Transfer control register.
374let neverHasSideEffects = 1 in
375def TFCR : CRInst<(outs CRRegs:$dst), (ins IntRegs:$src1),
376           "$dst = $src1",
377           []>;
378//===----------------------------------------------------------------------===//
379// ALU32/ALU -
380//===----------------------------------------------------------------------===//
381
382
383//===----------------------------------------------------------------------===//
384// ALU32/PERM +
385//===----------------------------------------------------------------------===//
386
387// Mux.
388def VMUX_prr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins PredRegs:$src1,
389                                                   DoubleRegs:$src2,
390                                                   DoubleRegs:$src3),
391            "$dst = vmux($src1, $src2, $src3)",
392            []>;
393
394let CextOpcode = "MUX", InputType = "reg" in
395def MUX_rr : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1,
396                                            IntRegs:$src2, IntRegs:$src3),
397             "$dst = mux($src1, $src2, $src3)",
398             [(set (i32 IntRegs:$dst),
399                   (i32 (select (i1 PredRegs:$src1), (i32 IntRegs:$src2),
400                                (i32 IntRegs:$src3))))]>, ImmRegRel;
401
402let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8,
403CextOpcode = "MUX", InputType = "imm" in
404def MUX_ir : ALU32_ir<(outs IntRegs:$dst), (ins PredRegs:$src1, s8Ext:$src2,
405                                                IntRegs:$src3),
406             "$dst = mux($src1, #$src2, $src3)",
407             [(set (i32 IntRegs:$dst),
408                   (i32 (select (i1 PredRegs:$src1), s8ExtPred:$src2,
409                                (i32 IntRegs:$src3))))]>, ImmRegRel;
410
411let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 8,
412CextOpcode = "MUX", InputType = "imm" in
413def MUX_ri : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2,
414                                                s8Ext:$src3),
415             "$dst = mux($src1, $src2, #$src3)",
416             [(set (i32 IntRegs:$dst),
417                   (i32 (select (i1 PredRegs:$src1), (i32 IntRegs:$src2),
418                                 s8ExtPred:$src3)))]>, ImmRegRel;
419
420let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8 in
421def MUX_ii : ALU32_ii<(outs IntRegs:$dst), (ins PredRegs:$src1, s8Ext:$src2,
422                                                s8Imm:$src3),
423             "$dst = mux($src1, #$src2, #$src3)",
424             [(set (i32 IntRegs:$dst), (i32 (select (i1 PredRegs:$src1),
425                                                    s8ExtPred:$src2,
426                                                    s8ImmPred:$src3)))]>;
427
428// ALU32 - aslh, asrh, sxtb, sxth, zxtb, zxth
429multiclass ALU32_2op_Pbase<string mnemonic, bit isNot, bit isPredNew> {
430  let isPredicatedNew = isPredNew in
431  def NAME : ALU32Inst<(outs IntRegs:$dst),
432                       (ins PredRegs:$src1, IntRegs:$src2),
433            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew,".new) $dst = ",
434            ") $dst = ")#mnemonic#"($src2)">,
435            Requires<[HasV4T]>;
436}
437
438multiclass ALU32_2op_Pred<string mnemonic, bit PredNot> {
439  let isPredicatedFalse = PredNot in {
440    defm _c#NAME : ALU32_2op_Pbase<mnemonic, PredNot, 0>;
441    // Predicate new
442    defm _cdn#NAME : ALU32_2op_Pbase<mnemonic, PredNot, 1>;
443  }
444}
445
446multiclass ALU32_2op_base<string mnemonic> {
447  let BaseOpcode = mnemonic in {
448    let isPredicable = 1, neverHasSideEffects = 1 in
449    def NAME : ALU32Inst<(outs IntRegs:$dst),
450                         (ins IntRegs:$src1),
451            "$dst = "#mnemonic#"($src1)">;
452
453    let Predicates = [HasV4T], validSubTargets = HasV4SubT, isPredicated = 1,
454    neverHasSideEffects = 1 in {
455      defm Pt_V4    : ALU32_2op_Pred<mnemonic, 0>;
456      defm NotPt_V4 : ALU32_2op_Pred<mnemonic, 1>;
457    }
458  }
459}
460
461defm ASLH : ALU32_2op_base<"aslh">, PredNewRel;
462defm ASRH : ALU32_2op_base<"asrh">, PredNewRel;
463defm SXTB : ALU32_2op_base<"sxtb">, PredNewRel;
464defm SXTH : ALU32_2op_base<"sxth">,  PredNewRel;
465defm ZXTB : ALU32_2op_base<"zxtb">, PredNewRel;
466defm ZXTH : ALU32_2op_base<"zxth">,  PredNewRel;
467
468def : Pat <(shl (i32 IntRegs:$src1), (i32 16)),
469           (ASLH IntRegs:$src1)>;
470
471def : Pat <(sra (i32 IntRegs:$src1), (i32 16)),
472           (ASRH IntRegs:$src1)>;
473
474def : Pat <(sext_inreg (i32 IntRegs:$src1), i8),
475           (SXTB IntRegs:$src1)>;
476
477def : Pat <(sext_inreg (i32 IntRegs:$src1), i16),
478           (SXTH IntRegs:$src1)>;
479
480//===----------------------------------------------------------------------===//
481// ALU32/PERM -
482//===----------------------------------------------------------------------===//
483
484
485//===----------------------------------------------------------------------===//
486// ALU32/PRED +
487//===----------------------------------------------------------------------===//
488
489// Compare.
490defm CMPGTU : CMP32_rr_ri_u9<"cmp.gtu", "CMPGTU", setugt>, ImmRegRel;
491defm CMPGT : CMP32_rr_ri_s10<"cmp.gt", "CMPGT", setgt>, ImmRegRel;
492defm CMPEQ : CMP32_rr_ri_s10<"cmp.eq", "CMPEQ", seteq>, ImmRegRel;
493
494// SDNode for converting immediate C to C-1.
495def DEC_CONST_SIGNED : SDNodeXForm<imm, [{
496   // Return the byte immediate const-1 as an SDNode.
497   int32_t imm = N->getSExtValue();
498   return XformSToSM1Imm(imm);
499}]>;
500
501// SDNode for converting immediate C to C-1.
502def DEC_CONST_UNSIGNED : SDNodeXForm<imm, [{
503   // Return the byte immediate const-1 as an SDNode.
504   uint32_t imm = N->getZExtValue();
505   return XformUToUM1Imm(imm);
506}]>;
507
508def CTLZ_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1),
509    "$dst = cl0($src1)",
510    [(set (i32 IntRegs:$dst), (ctlz (i32 IntRegs:$src1)))]>;
511
512def CTTZ_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1),
513    "$dst = ct0($src1)",
514    [(set (i32 IntRegs:$dst), (cttz (i32 IntRegs:$src1)))]>;
515
516def CTLZ64_rr : SInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1),
517    "$dst = cl0($src1)",
518    [(set (i32 IntRegs:$dst), (i32 (trunc (ctlz (i64 DoubleRegs:$src1)))))]>;
519
520def CTTZ64_rr : SInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1),
521    "$dst = ct0($src1)",
522    [(set (i32 IntRegs:$dst), (i32 (trunc (cttz (i64 DoubleRegs:$src1)))))]>;
523
524def TSTBIT_rr : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
525    "$dst = tstbit($src1, $src2)",
526    [(set (i1 PredRegs:$dst),
527          (setne (and (shl 1, (i32 IntRegs:$src2)), (i32 IntRegs:$src1)), 0))]>;
528
529def TSTBIT_ri : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2),
530    "$dst = tstbit($src1, $src2)",
531    [(set (i1 PredRegs:$dst),
532          (setne (and (shl 1, (u5ImmPred:$src2)), (i32 IntRegs:$src1)), 0))]>;
533
534//===----------------------------------------------------------------------===//
535// ALU32/PRED -
536//===----------------------------------------------------------------------===//
537
538
539//===----------------------------------------------------------------------===//
540// ALU64/ALU +
541//===----------------------------------------------------------------------===//
542// Add.
543def ADD64_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
544                                                     DoubleRegs:$src2),
545               "$dst = add($src1, $src2)",
546               [(set (i64 DoubleRegs:$dst), (add (i64 DoubleRegs:$src1),
547                                                 (i64 DoubleRegs:$src2)))]>;
548
549// Add halfword.
550
551// Compare.
552defm CMPEHexagon4 : CMP64_rr<"cmp.eq", seteq>;
553defm CMPGT64 : CMP64_rr<"cmp.gt", setgt>;
554defm CMPGTU64 : CMP64_rr<"cmp.gtu", setugt>;
555
556// Logical operations.
557def AND_rr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
558                                                     DoubleRegs:$src2),
559               "$dst = and($src1, $src2)",
560               [(set (i64 DoubleRegs:$dst), (and (i64 DoubleRegs:$src1),
561                                                 (i64 DoubleRegs:$src2)))]>;
562
563def OR_rr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
564                                                    DoubleRegs:$src2),
565              "$dst = or($src1, $src2)",
566              [(set (i64 DoubleRegs:$dst), (or (i64 DoubleRegs:$src1),
567                                               (i64 DoubleRegs:$src2)))]>;
568
569def XOR_rr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
570                                                     DoubleRegs:$src2),
571               "$dst = xor($src1, $src2)",
572               [(set (i64 DoubleRegs:$dst), (xor (i64 DoubleRegs:$src1),
573                                                 (i64 DoubleRegs:$src2)))]>;
574
575// Maximum.
576def MAXw_rr : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
577              "$dst = max($src2, $src1)",
578              [(set (i32 IntRegs:$dst),
579                    (i32 (select (i1 (setlt (i32 IntRegs:$src2),
580                                            (i32 IntRegs:$src1))),
581                                 (i32 IntRegs:$src1), (i32 IntRegs:$src2))))]>;
582
583def MAXUw_rr : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
584              "$dst = maxu($src2, $src1)",
585              [(set (i32 IntRegs:$dst),
586                    (i32 (select (i1 (setult (i32 IntRegs:$src2),
587                                             (i32 IntRegs:$src1))),
588                                 (i32 IntRegs:$src1), (i32 IntRegs:$src2))))]>;
589
590def MAXd_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
591                                                    DoubleRegs:$src2),
592              "$dst = max($src2, $src1)",
593              [(set (i64 DoubleRegs:$dst),
594                    (i64 (select (i1 (setlt (i64 DoubleRegs:$src2),
595                                            (i64 DoubleRegs:$src1))),
596                                 (i64 DoubleRegs:$src1),
597                                 (i64 DoubleRegs:$src2))))]>;
598
599def MAXUd_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
600                                                     DoubleRegs:$src2),
601              "$dst = maxu($src2, $src1)",
602              [(set (i64 DoubleRegs:$dst),
603                    (i64 (select (i1 (setult (i64 DoubleRegs:$src2),
604                                             (i64 DoubleRegs:$src1))),
605                                 (i64 DoubleRegs:$src1),
606                                 (i64 DoubleRegs:$src2))))]>;
607
608// Minimum.
609def MINw_rr : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
610              "$dst = min($src2, $src1)",
611              [(set (i32 IntRegs:$dst),
612                    (i32 (select (i1 (setgt (i32 IntRegs:$src2),
613                                            (i32 IntRegs:$src1))),
614                                 (i32 IntRegs:$src1), (i32 IntRegs:$src2))))]>;
615
616def MINUw_rr : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
617              "$dst = minu($src2, $src1)",
618              [(set (i32 IntRegs:$dst),
619                    (i32 (select (i1 (setugt (i32 IntRegs:$src2),
620                                             (i32 IntRegs:$src1))),
621                                 (i32 IntRegs:$src1), (i32 IntRegs:$src2))))]>;
622
623def MINd_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
624                                                    DoubleRegs:$src2),
625              "$dst = min($src2, $src1)",
626              [(set (i64 DoubleRegs:$dst),
627                    (i64 (select (i1 (setgt (i64 DoubleRegs:$src2),
628                                            (i64 DoubleRegs:$src1))),
629                                 (i64 DoubleRegs:$src1),
630                                 (i64 DoubleRegs:$src2))))]>;
631
632def MINUd_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
633                                                     DoubleRegs:$src2),
634              "$dst = minu($src2, $src1)",
635              [(set (i64 DoubleRegs:$dst),
636                    (i64 (select (i1 (setugt (i64 DoubleRegs:$src2),
637                                             (i64 DoubleRegs:$src1))),
638                                 (i64 DoubleRegs:$src1),
639                                 (i64 DoubleRegs:$src2))))]>;
640
641// Subtract.
642def SUB64_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
643                                                     DoubleRegs:$src2),
644               "$dst = sub($src1, $src2)",
645               [(set (i64 DoubleRegs:$dst), (sub (i64 DoubleRegs:$src1),
646                                                 (i64 DoubleRegs:$src2)))]>;
647
648// Subtract halfword.
649
650//===----------------------------------------------------------------------===//
651// ALU64/ALU -
652//===----------------------------------------------------------------------===//
653
654//===----------------------------------------------------------------------===//
655// ALU64/BIT +
656//===----------------------------------------------------------------------===//
657//
658//===----------------------------------------------------------------------===//
659// ALU64/BIT -
660//===----------------------------------------------------------------------===//
661
662//===----------------------------------------------------------------------===//
663// ALU64/PERM +
664//===----------------------------------------------------------------------===//
665//
666//===----------------------------------------------------------------------===//
667// ALU64/PERM -
668//===----------------------------------------------------------------------===//
669
670//===----------------------------------------------------------------------===//
671// CR +
672//===----------------------------------------------------------------------===//
673// Logical reductions on predicates.
674
675// Looping instructions.
676
677// Pipelined looping instructions.
678
679// Logical operations on predicates.
680def AND_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1, PredRegs:$src2),
681             "$dst = and($src1, $src2)",
682             [(set (i1 PredRegs:$dst), (and (i1 PredRegs:$src1),
683                                            (i1 PredRegs:$src2)))]>;
684
685let neverHasSideEffects = 1 in
686def AND_pnotp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1,
687                                                 PredRegs:$src2),
688                "$dst = and($src1, !$src2)",
689                []>;
690
691def ANY_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1),
692             "$dst = any8($src1)",
693             []>;
694
695def ALL_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1),
696             "$dst = all8($src1)",
697             []>;
698
699def VITPACK_pp : SInst<(outs IntRegs:$dst), (ins PredRegs:$src1,
700                                                 PredRegs:$src2),
701             "$dst = vitpack($src1, $src2)",
702             []>;
703
704def VALIGN_rrp : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
705                                                    DoubleRegs:$src2,
706                                                    PredRegs:$src3),
707             "$dst = valignb($src1, $src2, $src3)",
708             []>;
709
710def VSPLICE_rrp : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
711                                                     DoubleRegs:$src2,
712                                                     PredRegs:$src3),
713             "$dst = vspliceb($src1, $src2, $src3)",
714             []>;
715
716def MASK_p : SInst<(outs DoubleRegs:$dst), (ins PredRegs:$src1),
717             "$dst = mask($src1)",
718             []>;
719
720def NOT_p : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1),
721             "$dst = not($src1)",
722             [(set (i1 PredRegs:$dst), (not (i1 PredRegs:$src1)))]>;
723
724def OR_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1, PredRegs:$src2),
725            "$dst = or($src1, $src2)",
726            [(set (i1 PredRegs:$dst), (or (i1 PredRegs:$src1),
727                                          (i1 PredRegs:$src2)))]>;
728
729def XOR_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1, PredRegs:$src2),
730             "$dst = xor($src1, $src2)",
731             [(set (i1 PredRegs:$dst), (xor (i1 PredRegs:$src1),
732                                            (i1 PredRegs:$src2)))]>;
733
734
735// User control register transfer.
736//===----------------------------------------------------------------------===//
737// CR -
738//===----------------------------------------------------------------------===//
739
740def retflag : SDNode<"HexagonISD::RET_FLAG", SDTNone,
741                               [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
742def eh_return: SDNode<"HexagonISD::EH_RETURN", SDTNone,
743                      [SDNPHasChain]>;
744
745def SDHexagonBR_JT: SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
746def HexagonBR_JT: SDNode<"HexagonISD::BR_JT", SDHexagonBR_JT, [SDNPHasChain]>;
747
748let InputType = "imm", isBarrier = 1, isPredicable = 1,
749Defs = [PC], isExtendable = 1, opExtendable = 0, isExtentSigned = 1,
750opExtentBits = 24 in
751class T_JMP <dag InsDag, list<dag> JumpList = []>
752            : JInst<(outs), InsDag,
753            "jump $dst" , JumpList> {
754    bits<24> dst;
755
756    let IClass = 0b0101;
757
758    let Inst{27-25} = 0b100;
759    let Inst{24-16} = dst{23-15};
760    let Inst{13-1} = dst{14-2};
761}
762
763let InputType = "imm", isExtendable = 1, opExtendable = 1, isExtentSigned = 1,
764Defs = [PC], isPredicated = 1, opExtentBits = 17 in
765class T_JMP_c <bit PredNot, bit isPredNew, bit isTaken>:
766            JInst<(outs ), (ins PredRegs:$src, brtarget:$dst),
767            !if(PredNot, "if (!$src", "if ($src")#
768            !if(isPredNew, ".new) ", ") ")#"jump"#
769            !if(isPredNew, !if(isTaken, ":t ", ":nt "), " ")#"$dst"> {
770
771    let isBrTaken = !if(isPredNew, !if(isTaken, "true", "false"), "");
772    let isPredicatedFalse = PredNot;
773    let isPredicatedNew = isPredNew;
774    bits<2> src;
775    bits<17> dst;
776
777    let IClass = 0b0101;
778
779    let Inst{27-24} = 0b1100;
780    let Inst{21} = PredNot;
781    let Inst{12} = !if(isPredNew, isTaken, zero);
782    let Inst{11} = isPredNew;
783    let Inst{9-8} = src;
784    let Inst{23-22} = dst{16-15};
785    let Inst{20-16} = dst{14-10};
786    let Inst{13} = dst{9};
787    let Inst{7-1} = dst{8-2};
788  }
789
790let isBarrier = 1, Defs = [PC], isPredicable = 1, InputType = "reg" in
791class T_JMPr<dag InsDag = (ins IntRegs:$dst)>
792            : JRInst<(outs ), InsDag,
793            "jumpr $dst" ,
794            []> {
795    bits<5> dst;
796
797    let IClass = 0b0101;
798    let Inst{27-21} = 0b0010100;
799    let Inst{20-16} = dst;
800}
801
802let Defs = [PC], isPredicated = 1, InputType = "reg" in
803class T_JMPr_c <bit PredNot, bit isPredNew, bit isTaken>:
804            JRInst <(outs ), (ins PredRegs:$src, IntRegs:$dst),
805            !if(PredNot, "if (!$src", "if ($src")#
806            !if(isPredNew, ".new) ", ") ")#"jumpr"#
807            !if(isPredNew, !if(isTaken, ":t ", ":nt "), " ")#"$dst"> {
808
809    let isBrTaken = !if(isPredNew, !if(isTaken, "true", "false"), "");
810    let isPredicatedFalse = PredNot;
811    let isPredicatedNew = isPredNew;
812    bits<2> src;
813    bits<5> dst;
814
815    let IClass = 0b0101;
816
817    let Inst{27-22} = 0b001101;
818    let Inst{21} = PredNot;
819    let Inst{20-16} = dst;
820    let Inst{12} = !if(isPredNew, isTaken, zero);
821    let Inst{11} = isPredNew;
822    let Inst{9-8} = src;
823    let Predicates = !if(isPredNew, [HasV3T], [HasV2T]);
824    let validSubTargets = !if(isPredNew, HasV3SubT, HasV2SubT);
825}
826
827multiclass JMP_Pred<bit PredNot> {
828  def _#NAME : T_JMP_c<PredNot, 0, 0>;
829  // Predicate new
830  def _#NAME#new_t  : T_JMP_c<PredNot, 1, 1>; // taken
831  def _#NAME#new_nt : T_JMP_c<PredNot, 1, 0>; // not taken
832}
833
834multiclass JMP_base<string BaseOp> {
835  let BaseOpcode = BaseOp in {
836    def NAME : T_JMP<(ins brtarget:$dst), [(br bb:$dst)]>;
837    defm t : JMP_Pred<0>;
838    defm f : JMP_Pred<1>;
839  }
840}
841
842multiclass JMPR_Pred<bit PredNot> {
843  def NAME: T_JMPr_c<PredNot, 0, 0>;
844  // Predicate new
845  def NAME#new_tV3  : T_JMPr_c<PredNot, 1, 1>; // taken
846  def NAME#new_ntV3 : T_JMPr_c<PredNot, 1, 0>; // not taken
847}
848
849multiclass JMPR_base<string BaseOp> {
850  let BaseOpcode = BaseOp in {
851    def NAME : T_JMPr;
852    defm _t : JMPR_Pred<0>;
853    defm _f : JMPR_Pred<1>;
854  }
855}
856
857let isTerminator = 1, neverHasSideEffects = 1 in {
858let isBranch = 1 in
859defm JMP : JMP_base<"JMP">, PredNewRel;
860
861let isBranch = 1, isIndirectBranch = 1 in
862defm JMPR : JMPR_base<"JMPr">, PredNewRel;
863
864let isReturn = 1, isCodeGenOnly = 1 in
865defm JMPret : JMPR_base<"JMPret">, PredNewRel;
866}
867
868def : Pat<(retflag),
869          (JMPret (i32 R31))>;
870
871def : Pat <(brcond (i1 PredRegs:$src1), bb:$offset),
872      (JMP_t (i1 PredRegs:$src1), bb:$offset)>;
873
874// A return through builtin_eh_return.
875let isReturn = 1, isTerminator = 1, isBarrier = 1, neverHasSideEffects = 1,
876isCodeGenOnly = 1, Defs = [PC], Uses = [R28], isPredicable = 0 in
877def EH_RETURN_JMPR : T_JMPr;
878
879def : Pat<(eh_return),
880          (EH_RETURN_JMPR (i32 R31))>;
881
882def : Pat<(HexagonBR_JT (i32 IntRegs:$dst)),
883          (JMPR (i32 IntRegs:$dst))>;
884
885def : Pat<(brind (i32 IntRegs:$dst)),
886          (JMPR (i32 IntRegs:$dst))>;
887
888//===----------------------------------------------------------------------===//
889// JR -
890//===----------------------------------------------------------------------===//
891
892//===----------------------------------------------------------------------===//
893// LD +
894//===----------------------------------------------------------------------===//
895///
896// Load -- MEMri operand
897multiclass LD_MEMri_Pbase<string mnemonic, RegisterClass RC,
898                          bit isNot, bit isPredNew> {
899  let isPredicatedNew = isPredNew in
900  def NAME : LDInst2<(outs RC:$dst),
901                       (ins PredRegs:$src1, MEMri:$addr),
902            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
903            ") ")#"$dst = "#mnemonic#"($addr)",
904            []>;
905}
906
907multiclass LD_MEMri_Pred<string mnemonic, RegisterClass RC, bit PredNot> {
908  let isPredicatedFalse = PredNot in {
909    defm _c#NAME : LD_MEMri_Pbase<mnemonic, RC, PredNot, 0>;
910    // Predicate new
911    defm _cdn#NAME : LD_MEMri_Pbase<mnemonic, RC, PredNot, 1>;
912  }
913}
914
915let isExtendable = 1, neverHasSideEffects = 1 in
916multiclass LD_MEMri<string mnemonic, string CextOp, RegisterClass RC,
917                    bits<5> ImmBits, bits<5> PredImmBits> {
918
919  let CextOpcode = CextOp, BaseOpcode = CextOp in {
920    let opExtendable = 2, isExtentSigned = 1, opExtentBits = ImmBits,
921        isPredicable = 1 in
922      def NAME : LDInst2<(outs RC:$dst), (ins MEMri:$addr),
923                   "$dst = "#mnemonic#"($addr)",
924                   []>;
925
926    let opExtendable = 3, isExtentSigned = 0, opExtentBits = PredImmBits,
927        isPredicated = 1 in {
928      defm Pt : LD_MEMri_Pred<mnemonic, RC, 0 >;
929      defm NotPt : LD_MEMri_Pred<mnemonic, RC, 1 >;
930    }
931  }
932}
933
934let addrMode = BaseImmOffset, isMEMri = "true" in {
935  defm LDrib: LD_MEMri < "memb", "LDrib", IntRegs, 11, 6>, AddrModeRel;
936  defm LDriub: LD_MEMri < "memub" , "LDriub", IntRegs, 11, 6>, AddrModeRel;
937  defm LDrih: LD_MEMri < "memh", "LDrih", IntRegs, 12, 7>, AddrModeRel;
938  defm LDriuh: LD_MEMri < "memuh", "LDriuh", IntRegs, 12, 7>, AddrModeRel;
939  defm LDriw: LD_MEMri < "memw", "LDriw", IntRegs, 13, 8>, AddrModeRel;
940  defm LDrid: LD_MEMri < "memd", "LDrid", DoubleRegs, 14, 9>, AddrModeRel;
941}
942
943def : Pat < (i32 (sextloadi8 ADDRriS11_0:$addr)),
944            (LDrib ADDRriS11_0:$addr) >;
945
946def : Pat < (i32 (zextloadi8 ADDRriS11_0:$addr)),
947            (LDriub ADDRriS11_0:$addr) >;
948
949def : Pat < (i32 (sextloadi16 ADDRriS11_1:$addr)),
950            (LDrih ADDRriS11_1:$addr) >;
951
952def : Pat < (i32 (zextloadi16 ADDRriS11_1:$addr)),
953            (LDriuh ADDRriS11_1:$addr) >;
954
955def : Pat < (i32 (load ADDRriS11_2:$addr)),
956            (LDriw ADDRriS11_2:$addr) >;
957
958def : Pat < (i64 (load ADDRriS11_3:$addr)),
959            (LDrid ADDRriS11_3:$addr) >;
960
961
962// Load - Base with Immediate offset addressing mode
963multiclass LD_Idxd_Pbase<string mnemonic, RegisterClass RC, Operand predImmOp,
964                        bit isNot, bit isPredNew> {
965  let isPredicatedNew = isPredNew in
966  def NAME : LDInst2<(outs RC:$dst),
967                     (ins PredRegs:$src1, IntRegs:$src2, predImmOp:$src3),
968            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
969            ") ")#"$dst = "#mnemonic#"($src2+#$src3)",
970            []>;
971}
972
973multiclass LD_Idxd_Pred<string mnemonic, RegisterClass RC, Operand predImmOp,
974                        bit PredNot> {
975  let isPredicatedFalse = PredNot in {
976    defm _c#NAME : LD_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 0>;
977    // Predicate new
978    defm _cdn#NAME : LD_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 1>;
979  }
980}
981
982let isExtendable = 1, neverHasSideEffects = 1 in
983multiclass LD_Idxd<string mnemonic, string CextOp, RegisterClass RC,
984                   Operand ImmOp, Operand predImmOp, bits<5> ImmBits,
985                   bits<5> PredImmBits> {
986
987  let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed in {
988    let opExtendable = 2, isExtentSigned = 1, opExtentBits = ImmBits,
989        isPredicable = 1, AddedComplexity = 20 in
990      def NAME : LDInst2<(outs RC:$dst), (ins IntRegs:$src1, ImmOp:$offset),
991                   "$dst = "#mnemonic#"($src1+#$offset)",
992                   []>;
993
994    let opExtendable = 3, isExtentSigned = 0, opExtentBits = PredImmBits,
995        isPredicated = 1 in {
996      defm Pt : LD_Idxd_Pred<mnemonic, RC, predImmOp, 0 >;
997      defm NotPt : LD_Idxd_Pred<mnemonic, RC, predImmOp, 1 >;
998    }
999  }
1000}
1001
1002let addrMode = BaseImmOffset in {
1003  defm LDrib_indexed: LD_Idxd <"memb", "LDrib", IntRegs, s11_0Ext, u6_0Ext,
1004                               11, 6>, AddrModeRel;
1005  defm LDriub_indexed: LD_Idxd <"memub" , "LDriub", IntRegs, s11_0Ext, u6_0Ext,
1006                                11, 6>, AddrModeRel;
1007  defm LDrih_indexed: LD_Idxd <"memh", "LDrih", IntRegs, s11_1Ext, u6_1Ext,
1008                               12, 7>, AddrModeRel;
1009  defm LDriuh_indexed: LD_Idxd <"memuh", "LDriuh", IntRegs, s11_1Ext, u6_1Ext,
1010                                12, 7>, AddrModeRel;
1011  defm LDriw_indexed: LD_Idxd <"memw", "LDriw", IntRegs, s11_2Ext, u6_2Ext,
1012                               13, 8>, AddrModeRel;
1013  defm LDrid_indexed: LD_Idxd <"memd", "LDrid", DoubleRegs, s11_3Ext, u6_3Ext,
1014                               14, 9>, AddrModeRel;
1015}
1016
1017let AddedComplexity = 20 in {
1018def : Pat < (i32 (sextloadi8 (add IntRegs:$src1, s11_0ExtPred:$offset))),
1019            (LDrib_indexed IntRegs:$src1, s11_0ExtPred:$offset) >;
1020
1021def : Pat < (i32 (zextloadi8 (add IntRegs:$src1, s11_0ExtPred:$offset))),
1022            (LDriub_indexed IntRegs:$src1, s11_0ExtPred:$offset) >;
1023
1024def : Pat < (i32 (sextloadi16 (add IntRegs:$src1, s11_1ExtPred:$offset))),
1025            (LDrih_indexed IntRegs:$src1, s11_1ExtPred:$offset) >;
1026
1027def : Pat < (i32 (zextloadi16 (add IntRegs:$src1, s11_1ExtPred:$offset))),
1028            (LDriuh_indexed IntRegs:$src1, s11_1ExtPred:$offset) >;
1029
1030def : Pat < (i32 (load (add IntRegs:$src1, s11_2ExtPred:$offset))),
1031            (LDriw_indexed IntRegs:$src1, s11_2ExtPred:$offset) >;
1032
1033def : Pat < (i64 (load (add IntRegs:$src1, s11_3ExtPred:$offset))),
1034            (LDrid_indexed IntRegs:$src1, s11_3ExtPred:$offset) >;
1035}
1036
1037//===----------------------------------------------------------------------===//
1038// Post increment load
1039// Make sure that in post increment load, the first operand is always the post
1040// increment operand.
1041//===----------------------------------------------------------------------===//
1042
1043multiclass LD_PostInc_Pbase<string mnemonic, RegisterClass RC, Operand ImmOp,
1044                            bit isNot, bit isPredNew> {
1045  let isPredicatedNew = isPredNew in
1046  def NAME : LDInst2PI<(outs RC:$dst, IntRegs:$dst2),
1047                       (ins PredRegs:$src1, IntRegs:$src2, ImmOp:$offset),
1048            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
1049            ") ")#"$dst = "#mnemonic#"($src2++#$offset)",
1050            [],
1051            "$src2 = $dst2">;
1052}
1053
1054multiclass LD_PostInc_Pred<string mnemonic, RegisterClass RC,
1055                           Operand ImmOp, bit PredNot> {
1056  let isPredicatedFalse = PredNot in {
1057    defm _c#NAME : LD_PostInc_Pbase<mnemonic, RC, ImmOp, PredNot, 0>;
1058    // Predicate new
1059    let Predicates = [HasV4T], validSubTargets = HasV4SubT in
1060    defm _cdn#NAME#_V4 : LD_PostInc_Pbase<mnemonic, RC, ImmOp, PredNot, 1>;
1061  }
1062}
1063
1064multiclass LD_PostInc<string mnemonic, string BaseOp, RegisterClass RC,
1065                      Operand ImmOp> {
1066
1067  let BaseOpcode = "POST_"#BaseOp in {
1068    let isPredicable = 1 in
1069    def NAME : LDInst2PI<(outs RC:$dst, IntRegs:$dst2),
1070                         (ins IntRegs:$src1, ImmOp:$offset),
1071                 "$dst = "#mnemonic#"($src1++#$offset)",
1072                 [],
1073                 "$src1 = $dst2">;
1074
1075    let isPredicated = 1 in {
1076      defm Pt : LD_PostInc_Pred<mnemonic, RC, ImmOp, 0 >;
1077      defm NotPt : LD_PostInc_Pred<mnemonic, RC, ImmOp, 1 >;
1078    }
1079  }
1080}
1081
1082let hasCtrlDep = 1, neverHasSideEffects = 1 in {
1083  defm POST_LDrib : LD_PostInc<"memb", "LDrib", IntRegs, s4_0Imm>,
1084                    PredNewRel;
1085  defm POST_LDriub : LD_PostInc<"memub", "LDriub", IntRegs, s4_0Imm>,
1086                    PredNewRel;
1087  defm POST_LDrih : LD_PostInc<"memh", "LDrih", IntRegs, s4_1Imm>,
1088                    PredNewRel;
1089  defm POST_LDriuh : LD_PostInc<"memuh", "LDriuh", IntRegs, s4_1Imm>,
1090                    PredNewRel;
1091  defm POST_LDriw : LD_PostInc<"memw", "LDriw", IntRegs, s4_2Imm>,
1092                    PredNewRel;
1093  defm POST_LDrid : LD_PostInc<"memd", "LDrid", DoubleRegs, s4_3Imm>,
1094                    PredNewRel;
1095}
1096
1097def : Pat< (i32 (extloadi1 ADDRriS11_0:$addr)),
1098           (i32 (LDrib ADDRriS11_0:$addr)) >;
1099
1100// Load byte any-extend.
1101def : Pat < (i32 (extloadi8 ADDRriS11_0:$addr)),
1102            (i32 (LDrib ADDRriS11_0:$addr)) >;
1103
1104// Indexed load byte any-extend.
1105let AddedComplexity = 20 in
1106def : Pat < (i32 (extloadi8 (add IntRegs:$src1, s11_0ImmPred:$offset))),
1107            (i32 (LDrib_indexed IntRegs:$src1, s11_0ImmPred:$offset)) >;
1108
1109def : Pat < (i32 (extloadi16 ADDRriS11_1:$addr)),
1110            (i32 (LDrih ADDRriS11_1:$addr))>;
1111
1112let AddedComplexity = 20 in
1113def : Pat < (i32 (extloadi16 (add IntRegs:$src1, s11_1ImmPred:$offset))),
1114            (i32 (LDrih_indexed IntRegs:$src1, s11_1ImmPred:$offset)) >;
1115
1116let AddedComplexity = 10 in
1117def : Pat < (i32 (zextloadi1 ADDRriS11_0:$addr)),
1118            (i32 (LDriub ADDRriS11_0:$addr))>;
1119
1120let AddedComplexity = 20 in
1121def : Pat < (i32 (zextloadi1 (add IntRegs:$src1, s11_0ImmPred:$offset))),
1122            (i32 (LDriub_indexed IntRegs:$src1, s11_0ImmPred:$offset))>;
1123
1124// Load predicate.
1125let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13,
1126isPseudo = 1, Defs = [R10,R11,D5], neverHasSideEffects = 1 in
1127def LDriw_pred : LDInst2<(outs PredRegs:$dst),
1128            (ins MEMri:$addr),
1129            "Error; should not emit",
1130            []>;
1131
1132// Deallocate stack frame.
1133let Defs = [R29, R30, R31], Uses = [R29], neverHasSideEffects = 1 in {
1134  def DEALLOCFRAME : LDInst2<(outs), (ins),
1135                     "deallocframe",
1136                     []>;
1137}
1138
1139// Load and unpack bytes to halfwords.
1140//===----------------------------------------------------------------------===//
1141// LD -
1142//===----------------------------------------------------------------------===//
1143
1144//===----------------------------------------------------------------------===//
1145// MTYPE/ALU +
1146//===----------------------------------------------------------------------===//
1147//===----------------------------------------------------------------------===//
1148// MTYPE/ALU -
1149//===----------------------------------------------------------------------===//
1150
1151//===----------------------------------------------------------------------===//
1152// MTYPE/COMPLEX +
1153//===----------------------------------------------------------------------===//
1154//===----------------------------------------------------------------------===//
1155// MTYPE/COMPLEX -
1156//===----------------------------------------------------------------------===//
1157
1158//===----------------------------------------------------------------------===//
1159// MTYPE/MPYH +
1160//===----------------------------------------------------------------------===//
1161// Multiply and use lower result.
1162// Rd=+mpyi(Rs,#u8)
1163let isExtendable = 1, opExtendable = 2, isExtentSigned = 0, opExtentBits = 8 in
1164def MPYI_riu : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u8Ext:$src2),
1165              "$dst =+ mpyi($src1, #$src2)",
1166              [(set (i32 IntRegs:$dst), (mul (i32 IntRegs:$src1),
1167                                             u8ExtPred:$src2))]>;
1168
1169// Rd=-mpyi(Rs,#u8)
1170def MPYI_rin : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u8Imm:$src2),
1171              "$dst =- mpyi($src1, #$src2)",
1172              [(set (i32 IntRegs:$dst), (ineg (mul (i32 IntRegs:$src1),
1173                                                   u8ImmPred:$src2)))]>;
1174
1175// Rd=mpyi(Rs,#m9)
1176// s9 is NOT the same as m9 - but it works.. so far.
1177// Assembler maps to either Rd=+mpyi(Rs,#u8 or Rd=-mpyi(Rs,#u8)
1178// depending on the value of m9. See Arch Spec.
1179let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 9,
1180CextOpcode = "MPYI", InputType = "imm" in
1181def MPYI_ri : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, s9Ext:$src2),
1182              "$dst = mpyi($src1, #$src2)",
1183              [(set (i32 IntRegs:$dst), (mul (i32 IntRegs:$src1),
1184                                             s9ExtPred:$src2))]>, ImmRegRel;
1185
1186// Rd=mpyi(Rs,Rt)
1187let CextOpcode = "MPYI", InputType = "reg" in
1188def MPYI : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
1189           "$dst = mpyi($src1, $src2)",
1190           [(set (i32 IntRegs:$dst), (mul (i32 IntRegs:$src1),
1191                                          (i32 IntRegs:$src2)))]>, ImmRegRel;
1192
1193// Rx+=mpyi(Rs,#u8)
1194let isExtendable = 1, opExtendable = 3, isExtentSigned = 0, opExtentBits = 8,
1195CextOpcode = "MPYI_acc", InputType = "imm" in
1196def MPYI_acc_ri : MInst_acc<(outs IntRegs:$dst),
1197            (ins IntRegs:$src1, IntRegs:$src2, u8Ext:$src3),
1198            "$dst += mpyi($src2, #$src3)",
1199            [(set (i32 IntRegs:$dst),
1200                  (add (mul (i32 IntRegs:$src2), u8ExtPred:$src3),
1201                       (i32 IntRegs:$src1)))],
1202            "$src1 = $dst">, ImmRegRel;
1203
1204// Rx+=mpyi(Rs,Rt)
1205let CextOpcode = "MPYI_acc", InputType = "reg" in
1206def MPYI_acc_rr : MInst_acc<(outs IntRegs:$dst),
1207            (ins IntRegs:$src1, IntRegs:$src2, IntRegs:$src3),
1208            "$dst += mpyi($src2, $src3)",
1209            [(set (i32 IntRegs:$dst),
1210                  (add (mul (i32 IntRegs:$src2), (i32 IntRegs:$src3)),
1211                       (i32 IntRegs:$src1)))],
1212            "$src1 = $dst">, ImmRegRel;
1213
1214// Rx-=mpyi(Rs,#u8)
1215let isExtendable = 1, opExtendable = 3, isExtentSigned = 0, opExtentBits = 8 in
1216def MPYI_sub_ri : MInst_acc<(outs IntRegs:$dst),
1217            (ins IntRegs:$src1, IntRegs:$src2, u8Ext:$src3),
1218            "$dst -= mpyi($src2, #$src3)",
1219            [(set (i32 IntRegs:$dst),
1220                  (sub (i32 IntRegs:$src1), (mul (i32 IntRegs:$src2),
1221                                                 u8ExtPred:$src3)))],
1222            "$src1 = $dst">;
1223
1224// Multiply and use upper result.
1225// Rd=mpy(Rs,Rt.H):<<1:rnd:sat
1226// Rd=mpy(Rs,Rt.L):<<1:rnd:sat
1227// Rd=mpy(Rs,Rt)
1228def MPY : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
1229          "$dst = mpy($src1, $src2)",
1230          [(set (i32 IntRegs:$dst), (mulhs (i32 IntRegs:$src1),
1231                                           (i32 IntRegs:$src2)))]>;
1232
1233// Rd=mpy(Rs,Rt):rnd
1234// Rd=mpyu(Rs,Rt)
1235def MPYU : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
1236           "$dst = mpyu($src1, $src2)",
1237           [(set (i32 IntRegs:$dst), (mulhu (i32 IntRegs:$src1),
1238                                            (i32 IntRegs:$src2)))]>;
1239
1240// Multiply and use full result.
1241// Rdd=mpyu(Rs,Rt)
1242def MPYU64 : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
1243             "$dst = mpyu($src1, $src2)",
1244             [(set (i64 DoubleRegs:$dst),
1245                   (mul (i64 (anyext (i32 IntRegs:$src1))),
1246                        (i64 (anyext (i32 IntRegs:$src2)))))]>;
1247
1248// Rdd=mpy(Rs,Rt)
1249def MPY64 : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
1250             "$dst = mpy($src1, $src2)",
1251             [(set (i64 DoubleRegs:$dst),
1252                   (mul (i64 (sext (i32 IntRegs:$src1))),
1253                        (i64 (sext (i32 IntRegs:$src2)))))]>;
1254
1255// Multiply and accumulate, use full result.
1256// Rxx[+-]=mpy(Rs,Rt)
1257// Rxx+=mpy(Rs,Rt)
1258def MPY64_acc : MInst_acc<(outs DoubleRegs:$dst),
1259            (ins DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3),
1260            "$dst += mpy($src2, $src3)",
1261            [(set (i64 DoubleRegs:$dst),
1262            (add (mul (i64 (sext (i32 IntRegs:$src2))),
1263                      (i64 (sext (i32 IntRegs:$src3)))),
1264                 (i64 DoubleRegs:$src1)))],
1265            "$src1 = $dst">;
1266
1267// Rxx-=mpy(Rs,Rt)
1268def MPY64_sub : MInst_acc<(outs DoubleRegs:$dst),
1269            (ins DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3),
1270            "$dst -= mpy($src2, $src3)",
1271            [(set (i64 DoubleRegs:$dst),
1272                  (sub (i64 DoubleRegs:$src1),
1273                       (mul (i64 (sext (i32 IntRegs:$src2))),
1274                            (i64 (sext (i32 IntRegs:$src3))))))],
1275            "$src1 = $dst">;
1276
1277// Rxx[+-]=mpyu(Rs,Rt)
1278// Rxx+=mpyu(Rs,Rt)
1279def MPYU64_acc : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
1280                            IntRegs:$src2, IntRegs:$src3),
1281             "$dst += mpyu($src2, $src3)",
1282             [(set (i64 DoubleRegs:$dst),
1283                   (add (mul (i64 (anyext (i32 IntRegs:$src2))),
1284                             (i64 (anyext (i32 IntRegs:$src3)))),
1285                        (i64 DoubleRegs:$src1)))], "$src1 = $dst">;
1286
1287// Rxx-=mpyu(Rs,Rt)
1288def MPYU64_sub : MInst_acc<(outs DoubleRegs:$dst),
1289            (ins DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3),
1290            "$dst -= mpyu($src2, $src3)",
1291            [(set (i64 DoubleRegs:$dst),
1292                  (sub (i64 DoubleRegs:$src1),
1293                       (mul (i64 (anyext (i32 IntRegs:$src2))),
1294                            (i64 (anyext (i32 IntRegs:$src3))))))],
1295            "$src1 = $dst">;
1296
1297
1298let InputType = "reg", CextOpcode = "ADD_acc" in
1299def ADDrr_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1,
1300                            IntRegs:$src2, IntRegs:$src3),
1301             "$dst += add($src2, $src3)",
1302             [(set (i32 IntRegs:$dst), (add (add (i32 IntRegs:$src2),
1303                                                 (i32 IntRegs:$src3)),
1304                                            (i32 IntRegs:$src1)))],
1305             "$src1 = $dst">, ImmRegRel;
1306
1307let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 8,
1308InputType = "imm", CextOpcode = "ADD_acc" in
1309def ADDri_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1,
1310                            IntRegs:$src2, s8Ext:$src3),
1311             "$dst += add($src2, #$src3)",
1312             [(set (i32 IntRegs:$dst), (add (add (i32 IntRegs:$src2),
1313                                                 s8_16ExtPred:$src3),
1314                                            (i32 IntRegs:$src1)))],
1315             "$src1 = $dst">, ImmRegRel;
1316
1317let CextOpcode = "SUB_acc", InputType = "reg" in
1318def SUBrr_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1,
1319                            IntRegs:$src2, IntRegs:$src3),
1320             "$dst -= add($src2, $src3)",
1321             [(set (i32 IntRegs:$dst),
1322                   (sub (i32 IntRegs:$src1), (add (i32 IntRegs:$src2),
1323                                                  (i32 IntRegs:$src3))))],
1324             "$src1 = $dst">, ImmRegRel;
1325
1326let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 8,
1327CextOpcode = "SUB_acc", InputType = "imm" in
1328def SUBri_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1,
1329                            IntRegs:$src2, s8Ext:$src3),
1330             "$dst -= add($src2, #$src3)",
1331             [(set (i32 IntRegs:$dst), (sub (i32 IntRegs:$src1),
1332                                            (add (i32 IntRegs:$src2),
1333                                                 s8_16ExtPred:$src3)))],
1334             "$src1 = $dst">, ImmRegRel;
1335
1336//===----------------------------------------------------------------------===//
1337// MTYPE/MPYH -
1338//===----------------------------------------------------------------------===//
1339
1340//===----------------------------------------------------------------------===//
1341// MTYPE/MPYS +
1342//===----------------------------------------------------------------------===//
1343//===----------------------------------------------------------------------===//
1344// MTYPE/MPYS -
1345//===----------------------------------------------------------------------===//
1346
1347//===----------------------------------------------------------------------===//
1348// MTYPE/VB +
1349//===----------------------------------------------------------------------===//
1350//===----------------------------------------------------------------------===//
1351// MTYPE/VB -
1352//===----------------------------------------------------------------------===//
1353
1354//===----------------------------------------------------------------------===//
1355// MTYPE/VH  +
1356//===----------------------------------------------------------------------===//
1357//===----------------------------------------------------------------------===//
1358// MTYPE/VH  -
1359//===----------------------------------------------------------------------===//
1360
1361//===----------------------------------------------------------------------===//
1362// ST +
1363//===----------------------------------------------------------------------===//
1364///
1365// Store doubleword.
1366
1367//===----------------------------------------------------------------------===//
1368// Post increment store
1369//===----------------------------------------------------------------------===//
1370
1371multiclass ST_PostInc_Pbase<string mnemonic, RegisterClass RC, Operand ImmOp,
1372                            bit isNot, bit isPredNew> {
1373  let isPredicatedNew = isPredNew in
1374  def NAME : STInst2PI<(outs IntRegs:$dst),
1375            (ins PredRegs:$src1, IntRegs:$src2, ImmOp:$offset, RC:$src3),
1376            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
1377            ") ")#mnemonic#"($src2++#$offset) = $src3",
1378            [],
1379            "$src2 = $dst">;
1380}
1381
1382multiclass ST_PostInc_Pred<string mnemonic, RegisterClass RC,
1383                           Operand ImmOp, bit PredNot> {
1384  let isPredicatedFalse = PredNot in {
1385    defm _c#NAME# : ST_PostInc_Pbase<mnemonic, RC, ImmOp, PredNot, 0>;
1386    // Predicate new
1387    let Predicates = [HasV4T], validSubTargets = HasV4SubT in
1388    defm _cdn#NAME#_V4 : ST_PostInc_Pbase<mnemonic, RC, ImmOp, PredNot, 1>;
1389  }
1390}
1391
1392let hasCtrlDep = 1, isNVStorable = 1, neverHasSideEffects = 1 in
1393multiclass ST_PostInc<string mnemonic, string BaseOp, RegisterClass RC,
1394                      Operand ImmOp> {
1395
1396  let hasCtrlDep = 1, BaseOpcode = "POST_"#BaseOp in {
1397    let isPredicable = 1 in
1398    def NAME : STInst2PI<(outs IntRegs:$dst),
1399                (ins IntRegs:$src1, ImmOp:$offset, RC:$src2),
1400                #mnemonic#"($src1++#$offset) = $src2",
1401                [],
1402                "$src1 = $dst">;
1403
1404    let isPredicated = 1 in {
1405      defm Pt : ST_PostInc_Pred<mnemonic, RC, ImmOp, 0 >;
1406      defm NotPt : ST_PostInc_Pred<mnemonic, RC, ImmOp, 1 >;
1407    }
1408  }
1409}
1410
1411defm POST_STbri: ST_PostInc <"memb", "STrib", IntRegs, s4_0Imm>, AddrModeRel;
1412defm POST_SThri: ST_PostInc <"memh", "STrih", IntRegs, s4_1Imm>, AddrModeRel;
1413defm POST_STwri: ST_PostInc <"memw", "STriw", IntRegs, s4_2Imm>, AddrModeRel;
1414
1415let isNVStorable = 0 in
1416defm POST_STdri: ST_PostInc <"memd", "STrid", DoubleRegs, s4_3Imm>, AddrModeRel;
1417
1418def : Pat<(post_truncsti8 (i32 IntRegs:$src1), IntRegs:$src2,
1419                           s4_3ImmPred:$offset),
1420          (POST_STbri IntRegs:$src2, s4_0ImmPred:$offset, IntRegs:$src1)>;
1421
1422def : Pat<(post_truncsti16 (i32 IntRegs:$src1), IntRegs:$src2,
1423                            s4_3ImmPred:$offset),
1424          (POST_SThri IntRegs:$src2, s4_1ImmPred:$offset, IntRegs:$src1)>;
1425
1426def : Pat<(post_store (i32 IntRegs:$src1), IntRegs:$src2, s4_2ImmPred:$offset),
1427          (POST_STwri IntRegs:$src2, s4_1ImmPred:$offset, IntRegs:$src1)>;
1428
1429def : Pat<(post_store (i64 DoubleRegs:$src1), IntRegs:$src2,
1430                       s4_3ImmPred:$offset),
1431          (POST_STdri IntRegs:$src2, s4_3ImmPred:$offset, DoubleRegs:$src1)>;
1432
1433//===----------------------------------------------------------------------===//
1434// multiclass for the store instructions with MEMri operand.
1435//===----------------------------------------------------------------------===//
1436multiclass ST_MEMri_Pbase<string mnemonic, RegisterClass RC, bit isNot,
1437                          bit isPredNew> {
1438  let isPredicatedNew = isPredNew in
1439  def NAME : STInst2<(outs),
1440            (ins PredRegs:$src1, MEMri:$addr, RC: $src2),
1441            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
1442            ") ")#mnemonic#"($addr) = $src2",
1443            []>;
1444}
1445
1446multiclass ST_MEMri_Pred<string mnemonic, RegisterClass RC, bit PredNot> {
1447  let isPredicatedFalse = PredNot in {
1448    defm _c#NAME : ST_MEMri_Pbase<mnemonic, RC, PredNot, 0>;
1449
1450    // Predicate new
1451    let validSubTargets = HasV4SubT, Predicates = [HasV4T] in
1452    defm _cdn#NAME#_V4 : ST_MEMri_Pbase<mnemonic, RC, PredNot, 1>;
1453  }
1454}
1455
1456let isExtendable = 1, isNVStorable = 1, neverHasSideEffects = 1 in
1457multiclass ST_MEMri<string mnemonic, string CextOp, RegisterClass RC,
1458                    bits<5> ImmBits, bits<5> PredImmBits> {
1459
1460  let CextOpcode = CextOp, BaseOpcode = CextOp in {
1461    let opExtendable = 1, isExtentSigned = 1, opExtentBits = ImmBits,
1462         isPredicable = 1 in
1463    def NAME : STInst2<(outs),
1464            (ins MEMri:$addr, RC:$src),
1465            mnemonic#"($addr) = $src",
1466            []>;
1467
1468    let opExtendable = 2, isExtentSigned = 0, opExtentBits = PredImmBits,
1469        isPredicated = 1 in {
1470      defm Pt : ST_MEMri_Pred<mnemonic, RC, 0>;
1471      defm NotPt : ST_MEMri_Pred<mnemonic, RC, 1>;
1472    }
1473  }
1474}
1475
1476let addrMode = BaseImmOffset, isMEMri = "true" in {
1477  defm STrib: ST_MEMri < "memb", "STrib", IntRegs, 11, 6>, AddrModeRel;
1478  defm STrih: ST_MEMri < "memh", "STrih", IntRegs, 12, 7>, AddrModeRel;
1479  defm STriw: ST_MEMri < "memw", "STriw", IntRegs, 13, 8>, AddrModeRel;
1480
1481  let isNVStorable = 0 in
1482  defm STrid: ST_MEMri < "memd", "STrid", DoubleRegs, 14, 9>, AddrModeRel;
1483}
1484
1485def : Pat<(truncstorei8 (i32 IntRegs:$src1), ADDRriS11_0:$addr),
1486          (STrib ADDRriS11_0:$addr, (i32 IntRegs:$src1))>;
1487
1488def : Pat<(truncstorei16 (i32 IntRegs:$src1), ADDRriS11_1:$addr),
1489          (STrih ADDRriS11_1:$addr, (i32 IntRegs:$src1))>;
1490
1491def : Pat<(store (i32 IntRegs:$src1), ADDRriS11_2:$addr),
1492          (STriw ADDRriS11_2:$addr, (i32 IntRegs:$src1))>;
1493
1494def : Pat<(store (i64 DoubleRegs:$src1), ADDRriS11_3:$addr),
1495          (STrid ADDRriS11_3:$addr, (i64 DoubleRegs:$src1))>;
1496
1497
1498//===----------------------------------------------------------------------===//
1499// multiclass for the store instructions with base+immediate offset
1500// addressing mode
1501//===----------------------------------------------------------------------===//
1502multiclass ST_Idxd_Pbase<string mnemonic, RegisterClass RC, Operand predImmOp,
1503                        bit isNot, bit isPredNew> {
1504  let isPredicatedNew = isPredNew in
1505  def NAME : STInst2<(outs),
1506            (ins PredRegs:$src1, IntRegs:$src2, predImmOp:$src3, RC: $src4),
1507            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
1508            ") ")#mnemonic#"($src2+#$src3) = $src4",
1509            []>;
1510}
1511
1512multiclass ST_Idxd_Pred<string mnemonic, RegisterClass RC, Operand predImmOp,
1513                        bit PredNot> {
1514  let isPredicatedFalse = PredNot, isPredicated = 1 in {
1515    defm _c#NAME : ST_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 0>;
1516
1517    // Predicate new
1518    let validSubTargets = HasV4SubT, Predicates = [HasV4T] in
1519    defm _cdn#NAME#_V4 : ST_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 1>;
1520  }
1521}
1522
1523let isExtendable = 1, isNVStorable = 1, neverHasSideEffects = 1 in
1524multiclass ST_Idxd<string mnemonic, string CextOp, RegisterClass RC,
1525                   Operand ImmOp, Operand predImmOp, bits<5> ImmBits,
1526                   bits<5> PredImmBits> {
1527
1528  let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed in {
1529    let opExtendable = 1, isExtentSigned = 1, opExtentBits = ImmBits,
1530         isPredicable = 1 in
1531    def NAME : STInst2<(outs),
1532            (ins IntRegs:$src1, ImmOp:$src2, RC:$src3),
1533            mnemonic#"($src1+#$src2) = $src3",
1534            []>;
1535
1536    let opExtendable = 2, isExtentSigned = 0, opExtentBits = PredImmBits in {
1537      defm Pt : ST_Idxd_Pred<mnemonic, RC, predImmOp, 0>;
1538      defm NotPt : ST_Idxd_Pred<mnemonic, RC, predImmOp, 1>;
1539    }
1540  }
1541}
1542
1543let addrMode = BaseImmOffset, InputType = "reg" in {
1544  defm STrib_indexed: ST_Idxd < "memb", "STrib", IntRegs, s11_0Ext,
1545                                u6_0Ext, 11, 6>, AddrModeRel, ImmRegRel;
1546  defm STrih_indexed: ST_Idxd < "memh", "STrih", IntRegs, s11_1Ext,
1547                                u6_1Ext, 12, 7>, AddrModeRel, ImmRegRel;
1548  defm STriw_indexed: ST_Idxd < "memw", "STriw", IntRegs, s11_2Ext,
1549                                u6_2Ext, 13, 8>, AddrModeRel, ImmRegRel;
1550  let isNVStorable = 0 in
1551  defm STrid_indexed: ST_Idxd < "memd", "STrid", DoubleRegs, s11_3Ext,
1552                                u6_3Ext, 14, 9>, AddrModeRel;
1553}
1554
1555let AddedComplexity = 10 in {
1556def : Pat<(truncstorei8 (i32 IntRegs:$src1), (add IntRegs:$src2,
1557                                                  s11_0ExtPred:$offset)),
1558          (STrib_indexed IntRegs:$src2, s11_0ImmPred:$offset,
1559                         (i32 IntRegs:$src1))>;
1560
1561def : Pat<(truncstorei16 (i32 IntRegs:$src1), (add IntRegs:$src2,
1562                                                   s11_1ExtPred:$offset)),
1563          (STrih_indexed IntRegs:$src2, s11_1ImmPred:$offset,
1564                         (i32 IntRegs:$src1))>;
1565
1566def : Pat<(store (i32 IntRegs:$src1), (add IntRegs:$src2,
1567                                           s11_2ExtPred:$offset)),
1568          (STriw_indexed IntRegs:$src2, s11_2ImmPred:$offset,
1569                         (i32 IntRegs:$src1))>;
1570
1571def : Pat<(store (i64 DoubleRegs:$src1), (add IntRegs:$src2,
1572                                              s11_3ExtPred:$offset)),
1573          (STrid_indexed IntRegs:$src2, s11_3ImmPred:$offset,
1574                         (i64 DoubleRegs:$src1))>;
1575}
1576
1577// memh(Rx++#s4:1)=Rt.H
1578
1579// Store word.
1580// Store predicate.
1581let Defs = [R10,R11,D5], neverHasSideEffects = 1 in
1582def STriw_pred : STInst2<(outs),
1583            (ins MEMri:$addr, PredRegs:$src1),
1584            "Error; should not emit",
1585            []>;
1586
1587// Allocate stack frame.
1588let Defs = [R29, R30], Uses = [R31, R30], neverHasSideEffects = 1 in {
1589  def ALLOCFRAME : STInst2<(outs),
1590             (ins i32imm:$amt),
1591             "allocframe(#$amt)",
1592             []>;
1593}
1594//===----------------------------------------------------------------------===//
1595// ST -
1596//===----------------------------------------------------------------------===//
1597
1598//===----------------------------------------------------------------------===//
1599// STYPE/ALU +
1600//===----------------------------------------------------------------------===//
1601// Logical NOT.
1602def NOT_rr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1),
1603               "$dst = not($src1)",
1604               [(set (i64 DoubleRegs:$dst), (not (i64 DoubleRegs:$src1)))]>;
1605
1606
1607// Sign extend word to doubleword.
1608def SXTW : ALU64_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src1),
1609           "$dst = sxtw($src1)",
1610           [(set (i64 DoubleRegs:$dst), (sext (i32 IntRegs:$src1)))]>;
1611//===----------------------------------------------------------------------===//
1612// STYPE/ALU -
1613//===----------------------------------------------------------------------===//
1614
1615//===----------------------------------------------------------------------===//
1616// STYPE/BIT +
1617//===----------------------------------------------------------------------===//
1618// clrbit.
1619def CLRBIT : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2),
1620            "$dst = clrbit($src1, #$src2)",
1621            [(set (i32 IntRegs:$dst), (and (i32 IntRegs:$src1),
1622                                           (not
1623                                              (shl 1, u5ImmPred:$src2))))]>;
1624
1625def CLRBIT_31 : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2),
1626            "$dst = clrbit($src1, #$src2)",
1627            []>;
1628
1629// Map from r0 = and(r1, 2147483647) to r0 = clrbit(r1, #31).
1630def : Pat <(and (i32 IntRegs:$src1), 2147483647),
1631      (CLRBIT_31 (i32 IntRegs:$src1), 31)>;
1632
1633// setbit.
1634def SETBIT : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2),
1635            "$dst = setbit($src1, #$src2)",
1636            [(set (i32 IntRegs:$dst), (or (i32 IntRegs:$src1),
1637                                          (shl 1, u5ImmPred:$src2)))]>;
1638
1639// Map from r0 = or(r1, -2147483648) to r0 = setbit(r1, #31).
1640def SETBIT_31 : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2),
1641            "$dst = setbit($src1, #$src2)",
1642            []>;
1643
1644def : Pat <(or (i32 IntRegs:$src1), -2147483648),
1645      (SETBIT_31 (i32 IntRegs:$src1), 31)>;
1646
1647// togglebit.
1648def TOGBIT : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2),
1649            "$dst = setbit($src1, #$src2)",
1650            [(set (i32 IntRegs:$dst), (xor (i32 IntRegs:$src1),
1651                                          (shl 1, u5ImmPred:$src2)))]>;
1652
1653// Map from r0 = xor(r1, -2147483648) to r0 = togglebit(r1, #31).
1654def TOGBIT_31 : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2),
1655            "$dst = togglebit($src1, #$src2)",
1656            []>;
1657
1658def : Pat <(xor (i32 IntRegs:$src1), -2147483648),
1659      (TOGBIT_31 (i32 IntRegs:$src1), 31)>;
1660
1661// Predicate transfer.
1662let neverHasSideEffects = 1 in
1663def TFR_RsPd : SInst<(outs IntRegs:$dst), (ins PredRegs:$src1),
1664               "$dst = $src1  /* Should almost never emit this. */",
1665               []>;
1666
1667def TFR_PdRs : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1),
1668               "$dst = $src1  /* Should almost never emit this. */",
1669               [(set (i1 PredRegs:$dst), (trunc (i32 IntRegs:$src1)))]>;
1670//===----------------------------------------------------------------------===//
1671// STYPE/PRED -
1672//===----------------------------------------------------------------------===//
1673
1674//===----------------------------------------------------------------------===//
1675// STYPE/SHIFT +
1676//===----------------------------------------------------------------------===//
1677// Shift by immediate.
1678def ASR_ri : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2),
1679             "$dst = asr($src1, #$src2)",
1680             [(set (i32 IntRegs:$dst), (sra (i32 IntRegs:$src1),
1681                                            u5ImmPred:$src2))]>;
1682
1683def ASRd_ri : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, u6Imm:$src2),
1684              "$dst = asr($src1, #$src2)",
1685              [(set (i64 DoubleRegs:$dst), (sra (i64 DoubleRegs:$src1),
1686                                                u6ImmPred:$src2))]>;
1687
1688def ASL : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2),
1689          "$dst = asl($src1, #$src2)",
1690          [(set (i32 IntRegs:$dst), (shl (i32 IntRegs:$src1),
1691                                         u5ImmPred:$src2))]>;
1692
1693def ASLd_ri : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, u6Imm:$src2),
1694              "$dst = asl($src1, #$src2)",
1695              [(set (i64 DoubleRegs:$dst), (shl (i64 DoubleRegs:$src1),
1696                                                u6ImmPred:$src2))]>;
1697
1698def LSR_ri : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2),
1699             "$dst = lsr($src1, #$src2)",
1700             [(set (i32 IntRegs:$dst), (srl (i32 IntRegs:$src1),
1701                                            u5ImmPred:$src2))]>;
1702
1703def LSRd_ri : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, u6Imm:$src2),
1704              "$dst = lsr($src1, #$src2)",
1705              [(set (i64 DoubleRegs:$dst), (srl (i64 DoubleRegs:$src1),
1706                                                u6ImmPred:$src2))]>;
1707
1708// Shift by immediate and add.
1709let AddedComplexity = 100 in
1710def ADDASL : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2,
1711                                             u3Imm:$src3),
1712             "$dst = addasl($src1, $src2, #$src3)",
1713             [(set (i32 IntRegs:$dst), (add (i32 IntRegs:$src1),
1714                                       (shl (i32 IntRegs:$src2),
1715                                            u3ImmPred:$src3)))]>;
1716
1717// Shift by register.
1718def ASL_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
1719             "$dst = asl($src1, $src2)",
1720             [(set (i32 IntRegs:$dst), (shl (i32 IntRegs:$src1),
1721                                            (i32 IntRegs:$src2)))]>;
1722
1723def ASR_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
1724             "$dst = asr($src1, $src2)",
1725             [(set (i32 IntRegs:$dst), (sra (i32 IntRegs:$src1),
1726                                            (i32 IntRegs:$src2)))]>;
1727
1728def LSL_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
1729             "$dst = lsl($src1, $src2)",
1730             [(set (i32 IntRegs:$dst), (shl (i32 IntRegs:$src1),
1731                                            (i32 IntRegs:$src2)))]>;
1732
1733def LSR_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
1734             "$dst = lsr($src1, $src2)",
1735             [(set (i32 IntRegs:$dst), (srl (i32 IntRegs:$src1),
1736                                            (i32 IntRegs:$src2)))]>;
1737
1738def ASLd : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, IntRegs:$src2),
1739           "$dst = asl($src1, $src2)",
1740           [(set (i64 DoubleRegs:$dst), (shl (i64 DoubleRegs:$src1),
1741                                             (i32 IntRegs:$src2)))]>;
1742
1743def LSLd : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, IntRegs:$src2),
1744           "$dst = lsl($src1, $src2)",
1745           [(set (i64 DoubleRegs:$dst), (shl (i64 DoubleRegs:$src1),
1746                                             (i32 IntRegs:$src2)))]>;
1747
1748def ASRd_rr : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
1749                                                 IntRegs:$src2),
1750              "$dst = asr($src1, $src2)",
1751              [(set (i64 DoubleRegs:$dst), (sra (i64 DoubleRegs:$src1),
1752                                                (i32 IntRegs:$src2)))]>;
1753
1754def LSRd_rr : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
1755                                                 IntRegs:$src2),
1756              "$dst = lsr($src1, $src2)",
1757              [(set (i64 DoubleRegs:$dst), (srl (i64 DoubleRegs:$src1),
1758                                                (i32 IntRegs:$src2)))]>;
1759
1760//===----------------------------------------------------------------------===//
1761// STYPE/SHIFT -
1762//===----------------------------------------------------------------------===//
1763
1764//===----------------------------------------------------------------------===//
1765// STYPE/VH +
1766//===----------------------------------------------------------------------===//
1767//===----------------------------------------------------------------------===//
1768// STYPE/VH -
1769//===----------------------------------------------------------------------===//
1770
1771//===----------------------------------------------------------------------===//
1772// STYPE/VW +
1773//===----------------------------------------------------------------------===//
1774//===----------------------------------------------------------------------===//
1775// STYPE/VW -
1776//===----------------------------------------------------------------------===//
1777
1778//===----------------------------------------------------------------------===//
1779// SYSTEM/SUPER +
1780//===----------------------------------------------------------------------===//
1781
1782//===----------------------------------------------------------------------===//
1783// SYSTEM/USER +
1784//===----------------------------------------------------------------------===//
1785def SDHexagonBARRIER: SDTypeProfile<0, 0, []>;
1786def HexagonBARRIER: SDNode<"HexagonISD::BARRIER", SDHexagonBARRIER,
1787                           [SDNPHasChain]>;
1788
1789let hasSideEffects = 1, isSolo = 1 in
1790def BARRIER : SYSInst<(outs), (ins),
1791                     "barrier",
1792                     [(HexagonBARRIER)]>;
1793
1794//===----------------------------------------------------------------------===//
1795// SYSTEM/SUPER -
1796//===----------------------------------------------------------------------===//
1797
1798// TFRI64 - assembly mapped.
1799let isReMaterializable = 1 in
1800def TFRI64 : ALU64_rr<(outs DoubleRegs:$dst), (ins s8Imm64:$src1),
1801             "$dst = #$src1",
1802             [(set (i64 DoubleRegs:$dst), s8Imm64Pred:$src1)]>;
1803
1804// Pseudo instruction to encode a set of conditional transfers.
1805// This instruction is used instead of a mux and trades-off codesize
1806// for performance. We conduct this transformation optimistically in
1807// the hope that these instructions get promoted to dot-new transfers.
1808let AddedComplexity = 100, isPredicated = 1 in
1809def TFR_condset_rr : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1,
1810                                                        IntRegs:$src2,
1811                                                        IntRegs:$src3),
1812                     "Error; should not emit",
1813                     [(set (i32 IntRegs:$dst),
1814                           (i32 (select (i1 PredRegs:$src1),
1815                                        (i32 IntRegs:$src2),
1816                                        (i32 IntRegs:$src3))))]>;
1817let AddedComplexity = 100, isPredicated = 1 in
1818def TFR_condset_ri : ALU32_rr<(outs IntRegs:$dst),
1819            (ins PredRegs:$src1, IntRegs:$src2, s12Imm:$src3),
1820            "Error; should not emit",
1821            [(set (i32 IntRegs:$dst),
1822             (i32 (select (i1 PredRegs:$src1), (i32 IntRegs:$src2),
1823                          s12ImmPred:$src3)))]>;
1824
1825let AddedComplexity = 100, isPredicated = 1 in
1826def TFR_condset_ir : ALU32_rr<(outs IntRegs:$dst),
1827            (ins PredRegs:$src1, s12Imm:$src2, IntRegs:$src3),
1828            "Error; should not emit",
1829            [(set (i32 IntRegs:$dst),
1830             (i32 (select (i1 PredRegs:$src1), s12ImmPred:$src2,
1831                          (i32 IntRegs:$src3))))]>;
1832
1833let AddedComplexity = 100, isPredicated = 1 in
1834def TFR_condset_ii : ALU32_rr<(outs IntRegs:$dst),
1835                              (ins PredRegs:$src1, s12Imm:$src2, s12Imm:$src3),
1836                     "Error; should not emit",
1837                     [(set (i32 IntRegs:$dst),
1838                           (i32 (select (i1 PredRegs:$src1), s12ImmPred:$src2,
1839                                        s12ImmPred:$src3)))]>;
1840
1841// Generate frameindex addresses.
1842let isReMaterializable = 1 in
1843def TFR_FI : ALU32_ri<(outs IntRegs:$dst), (ins FrameIndex:$src1),
1844             "$dst = add($src1)",
1845             [(set (i32 IntRegs:$dst), ADDRri:$src1)]>;
1846
1847//
1848// CR - Type.
1849//
1850let neverHasSideEffects = 1, Defs = [SA0, LC0] in {
1851def LOOP0_i : CRInst<(outs), (ins brtarget:$offset, u10Imm:$src2),
1852                      "loop0($offset, #$src2)",
1853                      []>;
1854}
1855
1856let neverHasSideEffects = 1, Defs = [SA0, LC0] in {
1857def LOOP0_r : CRInst<(outs), (ins brtarget:$offset, IntRegs:$src2),
1858                      "loop0($offset, $src2)",
1859                      []>;
1860}
1861
1862let isBranch = 1, isTerminator = 1, neverHasSideEffects = 1,
1863    Defs = [PC, LC0], Uses = [SA0, LC0] in {
1864def ENDLOOP0 : Endloop<(outs), (ins brtarget:$offset),
1865                       ":endloop0",
1866                       []>;
1867}
1868
1869// Support for generating global address.
1870// Taken from X86InstrInfo.td.
1871def SDTHexagonCONST32 : SDTypeProfile<1, 1, [
1872                                            SDTCisVT<0, i32>,
1873                                            SDTCisVT<1, i32>,
1874                                            SDTCisPtrTy<0>]>;
1875def HexagonCONST32 : SDNode<"HexagonISD::CONST32",     SDTHexagonCONST32>;
1876def HexagonCONST32_GP : SDNode<"HexagonISD::CONST32_GP",     SDTHexagonCONST32>;
1877
1878// HI/LO Instructions
1879let isReMaterializable = 1, isMoveImm = 1, neverHasSideEffects = 1 in
1880def LO : ALU32_ri<(outs IntRegs:$dst), (ins globaladdress:$global),
1881                  "$dst.l = #LO($global)",
1882                  []>;
1883
1884let isReMaterializable = 1, isMoveImm = 1, neverHasSideEffects = 1 in
1885def HI : ALU32_ri<(outs IntRegs:$dst), (ins globaladdress:$global),
1886                  "$dst.h = #HI($global)",
1887                  []>;
1888
1889let isReMaterializable = 1, isMoveImm = 1, neverHasSideEffects = 1 in
1890def LOi : ALU32_ri<(outs IntRegs:$dst), (ins i32imm:$imm_value),
1891                  "$dst.l = #LO($imm_value)",
1892                  []>;
1893
1894
1895let isReMaterializable = 1, isMoveImm = 1, neverHasSideEffects = 1 in
1896def HIi : ALU32_ri<(outs IntRegs:$dst), (ins i32imm:$imm_value),
1897                  "$dst.h = #HI($imm_value)",
1898                  []>;
1899
1900let isReMaterializable = 1, isMoveImm = 1, neverHasSideEffects = 1 in
1901def LO_jt : ALU32_ri<(outs IntRegs:$dst), (ins jumptablebase:$jt),
1902                  "$dst.l = #LO($jt)",
1903                  []>;
1904
1905let isReMaterializable = 1, isMoveImm = 1, neverHasSideEffects = 1 in
1906def HI_jt : ALU32_ri<(outs IntRegs:$dst), (ins jumptablebase:$jt),
1907                  "$dst.h = #HI($jt)",
1908                  []>;
1909
1910
1911let isReMaterializable = 1, isMoveImm = 1, neverHasSideEffects = 1 in
1912def LO_label : ALU32_ri<(outs IntRegs:$dst), (ins bblabel:$label),
1913                  "$dst.l = #LO($label)",
1914                  []>;
1915
1916let isReMaterializable = 1, isMoveImm = 1 , neverHasSideEffects = 1 in
1917def HI_label : ALU32_ri<(outs IntRegs:$dst), (ins bblabel:$label),
1918                  "$dst.h = #HI($label)",
1919                  []>;
1920
1921// This pattern is incorrect. When we add small data, we should change
1922// this pattern to use memw(#foo).
1923// This is for sdata.
1924let isMoveImm = 1 in
1925def CONST32 : LDInst<(outs IntRegs:$dst), (ins globaladdress:$global),
1926              "$dst = CONST32(#$global)",
1927              [(set (i32 IntRegs:$dst),
1928                    (load (HexagonCONST32 tglobaltlsaddr:$global)))]>;
1929
1930// This is for non-sdata.
1931let isReMaterializable = 1, isMoveImm = 1 in
1932def CONST32_set : LDInst2<(outs IntRegs:$dst), (ins globaladdress:$global),
1933                  "$dst = CONST32(#$global)",
1934                  [(set (i32 IntRegs:$dst),
1935                        (HexagonCONST32 tglobaladdr:$global))]>;
1936
1937let isReMaterializable = 1, isMoveImm = 1 in
1938def CONST32_set_jt : LDInst2<(outs IntRegs:$dst), (ins jumptablebase:$jt),
1939                     "$dst = CONST32(#$jt)",
1940                     [(set (i32 IntRegs:$dst),
1941                           (HexagonCONST32 tjumptable:$jt))]>;
1942
1943let isReMaterializable = 1, isMoveImm = 1 in
1944def CONST32GP_set : LDInst2<(outs IntRegs:$dst), (ins globaladdress:$global),
1945                    "$dst = CONST32(#$global)",
1946                    [(set (i32 IntRegs:$dst),
1947                          (HexagonCONST32_GP tglobaladdr:$global))]>;
1948
1949let isReMaterializable = 1, isMoveImm = 1 in
1950def CONST32_Int_Real : LDInst2<(outs IntRegs:$dst), (ins i32imm:$global),
1951                       "$dst = CONST32(#$global)",
1952                       [(set (i32 IntRegs:$dst), imm:$global) ]>;
1953
1954// Map BlockAddress lowering to CONST32_Int_Real
1955def : Pat<(HexagonCONST32_GP tblockaddress:$addr),
1956          (CONST32_Int_Real tblockaddress:$addr)>;
1957
1958let isReMaterializable = 1, isMoveImm = 1 in
1959def CONST32_Label : LDInst2<(outs IntRegs:$dst), (ins bblabel:$label),
1960                    "$dst = CONST32($label)",
1961                    [(set (i32 IntRegs:$dst), (HexagonCONST32 bbl:$label))]>;
1962
1963let isReMaterializable = 1, isMoveImm = 1 in
1964def CONST64_Int_Real : LDInst2<(outs DoubleRegs:$dst), (ins i64imm:$global),
1965                       "$dst = CONST64(#$global)",
1966                       [(set (i64 DoubleRegs:$dst), imm:$global) ]>;
1967
1968def TFR_PdFalse : SInst<(outs PredRegs:$dst), (ins),
1969                  "$dst = xor($dst, $dst)",
1970                  [(set (i1 PredRegs:$dst), 0)]>;
1971
1972def MPY_trsext : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
1973       "$dst = mpy($src1, $src2)",
1974       [(set (i32 IntRegs:$dst),
1975             (trunc (i64 (srl (i64 (mul (i64 (sext (i32 IntRegs:$src1))),
1976                                        (i64 (sext (i32 IntRegs:$src2))))),
1977                              (i32 32)))))]>;
1978
1979// Pseudo instructions.
1980def SDT_SPCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>;
1981
1982def SDT_SPCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>,
1983                                        SDTCisVT<1, i32> ]>;
1984
1985def callseq_end : SDNode<"ISD::CALLSEQ_END",   SDT_SPCallSeqEnd,
1986                  [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
1987
1988def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_SPCallSeqStart,
1989                    [SDNPHasChain, SDNPOutGlue]>;
1990
1991def SDT_SPCall : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
1992
1993def call : SDNode<"HexagonISD::CALL", SDT_SPCall,
1994           [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, SDNPVariadic]>;
1995
1996// For tailcalls a HexagonTCRet SDNode has 3 SDNode Properties - a chain,
1997// Optional Flag and Variable Arguments.
1998// Its 1 Operand has pointer type.
1999def HexagonTCRet    : SDNode<"HexagonISD::TC_RETURN", SDT_SPCall,
2000                     [SDNPHasChain,  SDNPOptInGlue, SDNPVariadic]>;
2001
2002let Defs = [R29, R30], Uses = [R31, R30, R29] in {
2003 def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt),
2004                        "Should never be emitted",
2005                        [(callseq_start timm:$amt)]>;
2006}
2007
2008let Defs = [R29, R30, R31], Uses = [R29] in {
2009 def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
2010                      "Should never be emitted",
2011                      [(callseq_end timm:$amt1, timm:$amt2)]>;
2012}
2013// Call subroutine.
2014let isCall = 1, neverHasSideEffects = 1,
2015  Defs = [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10,
2016          R22, R23, R28, R31, P0, P1, P2, P3, LC0, LC1, SA0, SA1] in {
2017  def CALL : JInst<(outs), (ins calltarget:$dst),
2018             "call $dst", []>;
2019}
2020
2021// Call subroutine from register.
2022let isCall = 1, neverHasSideEffects = 1,
2023  Defs = [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10,
2024          R22, R23, R28, R31, P0, P1, P2, P3, LC0, LC1, SA0, SA1] in {
2025  def CALLR : JRInst<(outs), (ins IntRegs:$dst),
2026              "callr $dst",
2027              []>;
2028 }
2029
2030
2031// Indirect tail-call.
2032let isCodeGenOnly = 1, isCall = 1, isReturn = 1  in
2033def TCRETURNR : T_JMPr;
2034
2035// Direct tail-calls.
2036let isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0,
2037isTerminator = 1, isCodeGenOnly = 1 in {
2038  def TCRETURNtg   : T_JMP<(ins calltarget:$dst)>;
2039  def TCRETURNtext : T_JMP<(ins calltarget:$dst)>;
2040}
2041
2042// Map call instruction.
2043def : Pat<(call (i32 IntRegs:$dst)),
2044      (CALLR (i32 IntRegs:$dst))>, Requires<[HasV2TOnly]>;
2045def : Pat<(call tglobaladdr:$dst),
2046      (CALL tglobaladdr:$dst)>, Requires<[HasV2TOnly]>;
2047def : Pat<(call texternalsym:$dst),
2048      (CALL texternalsym:$dst)>, Requires<[HasV2TOnly]>;
2049//Tail calls.
2050def : Pat<(HexagonTCRet tglobaladdr:$dst),
2051      (TCRETURNtg tglobaladdr:$dst)>;
2052def : Pat<(HexagonTCRet texternalsym:$dst),
2053      (TCRETURNtext texternalsym:$dst)>;
2054def : Pat<(HexagonTCRet (i32 IntRegs:$dst)),
2055      (TCRETURNR (i32 IntRegs:$dst))>;
2056
2057// Atomic load and store support
2058// 8 bit atomic load
2059def : Pat<(atomic_load_8 ADDRriS11_0:$src1),
2060          (i32 (LDriub ADDRriS11_0:$src1))>;
2061
2062def : Pat<(atomic_load_8 (add (i32 IntRegs:$src1), s11_0ImmPred:$offset)),
2063          (i32 (LDriub_indexed (i32 IntRegs:$src1), s11_0ImmPred:$offset))>;
2064
2065// 16 bit atomic load
2066def : Pat<(atomic_load_16 ADDRriS11_1:$src1),
2067          (i32 (LDriuh ADDRriS11_1:$src1))>;
2068
2069def : Pat<(atomic_load_16 (add (i32 IntRegs:$src1), s11_1ImmPred:$offset)),
2070          (i32 (LDriuh_indexed (i32 IntRegs:$src1), s11_1ImmPred:$offset))>;
2071
2072def : Pat<(atomic_load_32 ADDRriS11_2:$src1),
2073          (i32 (LDriw ADDRriS11_2:$src1))>;
2074
2075def : Pat<(atomic_load_32 (add (i32 IntRegs:$src1), s11_2ImmPred:$offset)),
2076          (i32 (LDriw_indexed (i32 IntRegs:$src1), s11_2ImmPred:$offset))>;
2077
2078// 64 bit atomic load
2079def : Pat<(atomic_load_64 ADDRriS11_3:$src1),
2080          (i64 (LDrid ADDRriS11_3:$src1))>;
2081
2082def : Pat<(atomic_load_64 (add (i32 IntRegs:$src1), s11_3ImmPred:$offset)),
2083          (i64 (LDrid_indexed (i32 IntRegs:$src1), s11_3ImmPred:$offset))>;
2084
2085
2086def : Pat<(atomic_store_8 ADDRriS11_0:$src2, (i32 IntRegs:$src1)),
2087          (STrib ADDRriS11_0:$src2, (i32 IntRegs:$src1))>;
2088
2089def : Pat<(atomic_store_8 (add (i32 IntRegs:$src2), s11_0ImmPred:$offset),
2090                          (i32 IntRegs:$src1)),
2091          (STrib_indexed (i32 IntRegs:$src2), s11_0ImmPred:$offset,
2092                         (i32 IntRegs:$src1))>;
2093
2094
2095def : Pat<(atomic_store_16 ADDRriS11_1:$src2, (i32 IntRegs:$src1)),
2096          (STrih ADDRriS11_1:$src2, (i32 IntRegs:$src1))>;
2097
2098def : Pat<(atomic_store_16 (i32 IntRegs:$src1),
2099                          (add (i32 IntRegs:$src2), s11_1ImmPred:$offset)),
2100          (STrih_indexed (i32 IntRegs:$src2), s11_1ImmPred:$offset,
2101                         (i32 IntRegs:$src1))>;
2102
2103def : Pat<(atomic_store_32 ADDRriS11_2:$src2, (i32 IntRegs:$src1)),
2104          (STriw ADDRriS11_2:$src2, (i32 IntRegs:$src1))>;
2105
2106def : Pat<(atomic_store_32 (add (i32 IntRegs:$src2), s11_2ImmPred:$offset),
2107                           (i32 IntRegs:$src1)),
2108          (STriw_indexed (i32 IntRegs:$src2), s11_2ImmPred:$offset,
2109                         (i32 IntRegs:$src1))>;
2110
2111
2112
2113
2114def : Pat<(atomic_store_64 ADDRriS11_3:$src2, (i64 DoubleRegs:$src1)),
2115          (STrid ADDRriS11_3:$src2, (i64 DoubleRegs:$src1))>;
2116
2117def : Pat<(atomic_store_64 (add (i32 IntRegs:$src2), s11_3ImmPred:$offset),
2118                           (i64 DoubleRegs:$src1)),
2119          (STrid_indexed (i32 IntRegs:$src2), s11_3ImmPred:$offset,
2120                         (i64 DoubleRegs:$src1))>;
2121
2122// Map from r0 = and(r1, 65535) to r0 = zxth(r1)
2123def : Pat <(and (i32 IntRegs:$src1), 65535),
2124      (ZXTH (i32 IntRegs:$src1))>;
2125
2126// Map from r0 = and(r1, 255) to r0 = zxtb(r1).
2127def : Pat <(and (i32 IntRegs:$src1), 255),
2128      (ZXTB (i32 IntRegs:$src1))>;
2129
2130// Map Add(p1, true) to p1 = not(p1).
2131//     Add(p1, false) should never be produced,
2132//     if it does, it got to be mapped to NOOP.
2133def : Pat <(add (i1 PredRegs:$src1), -1),
2134      (NOT_p (i1 PredRegs:$src1))>;
2135
2136// Map from p0 = setlt(r0, r1) r2 = mux(p0, r3, r4) =>
2137//   p0 = cmp.lt(r0, r1), r0 = mux(p0, r2, r1).
2138// cmp.lt(r0, r1) -> cmp.gt(r1, r0)
2139def : Pat <(select (i1 (setlt (i32 IntRegs:$src1), (i32 IntRegs:$src2))),
2140                   (i32 IntRegs:$src3),
2141                   (i32 IntRegs:$src4)),
2142      (i32 (TFR_condset_rr (CMPGTrr (i32 IntRegs:$src2), (i32 IntRegs:$src1)),
2143                           (i32 IntRegs:$src4), (i32 IntRegs:$src3)))>,
2144      Requires<[HasV2TOnly]>;
2145
2146// Map from p0 = pnot(p0); r0 = mux(p0, #i, #j) => r0 = mux(p0, #j, #i).
2147def : Pat <(select (not (i1 PredRegs:$src1)), s8ImmPred:$src2, s8ImmPred:$src3),
2148      (i32 (TFR_condset_ii (i1 PredRegs:$src1), s8ImmPred:$src3,
2149                           s8ImmPred:$src2))>;
2150
2151// Map from p0 = pnot(p0); r0 = select(p0, #i, r1)
2152// => r0 = TFR_condset_ri(p0, r1, #i)
2153def : Pat <(select (not (i1 PredRegs:$src1)), s12ImmPred:$src2,
2154                   (i32 IntRegs:$src3)),
2155      (i32 (TFR_condset_ri (i1 PredRegs:$src1), (i32 IntRegs:$src3),
2156                           s12ImmPred:$src2))>;
2157
2158// Map from p0 = pnot(p0); r0 = mux(p0, r1, #i)
2159// => r0 = TFR_condset_ir(p0, #i, r1)
2160def : Pat <(select (not (i1 PredRegs:$src1)), IntRegs:$src2, s12ImmPred:$src3),
2161      (i32 (TFR_condset_ir (i1 PredRegs:$src1), s12ImmPred:$src3,
2162                           (i32 IntRegs:$src2)))>;
2163
2164// Map from p0 = pnot(p0); if (p0) jump => if (!p0) jump.
2165def : Pat <(brcond (not (i1 PredRegs:$src1)), bb:$offset),
2166      (JMP_f (i1 PredRegs:$src1), bb:$offset)>;
2167
2168// Map from p2 = pnot(p2); p1 = and(p0, p2) => p1 = and(p0, !p2).
2169def : Pat <(and (i1 PredRegs:$src1), (not (i1 PredRegs:$src2))),
2170      (i1 (AND_pnotp (i1 PredRegs:$src1), (i1 PredRegs:$src2)))>;
2171
2172
2173let AddedComplexity = 100 in
2174def : Pat <(i64 (zextloadi1 (HexagonCONST32 tglobaladdr:$global))),
2175      (i64 (COMBINE_rr (TFRI 0),
2176                       (LDriub_indexed (CONST32_set tglobaladdr:$global), 0)))>,
2177      Requires<[NoV4T]>;
2178
2179// Map from i1 loads to 32 bits. This assumes that the i1* is byte aligned.
2180let AddedComplexity = 10 in
2181def : Pat <(i32 (zextloadi1 ADDRriS11_0:$addr)),
2182      (i32 (AND_rr (i32 (LDrib ADDRriS11_0:$addr)), (TFRI 0x1)))>;
2183
2184// Map from Rdd = sign_extend_inreg(Rss, i32) -> Rdd = SXTW(Rss.lo).
2185def : Pat <(i64 (sext_inreg (i64 DoubleRegs:$src1), i32)),
2186      (i64 (SXTW (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_loreg))))>;
2187
2188// Map from Rdd = sign_extend_inreg(Rss, i16) -> Rdd = SXTW(SXTH(Rss.lo)).
2189def : Pat <(i64 (sext_inreg (i64 DoubleRegs:$src1), i16)),
2190      (i64 (SXTW (i32 (SXTH (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1),
2191                                                 subreg_loreg))))))>;
2192
2193// Map from Rdd = sign_extend_inreg(Rss, i8) -> Rdd = SXTW(SXTB(Rss.lo)).
2194def : Pat <(i64 (sext_inreg (i64 DoubleRegs:$src1), i8)),
2195      (i64 (SXTW (i32 (SXTB (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1),
2196                                                 subreg_loreg))))))>;
2197
2198// We want to prevent emitting pnot's as much as possible.
2199// Map brcond with an unsupported setcc to a JMP_f.
2200def : Pat <(brcond (i1 (setne (i32 IntRegs:$src1), (i32 IntRegs:$src2))),
2201                        bb:$offset),
2202      (JMP_f (CMPEQrr (i32 IntRegs:$src1), (i32 IntRegs:$src2)),
2203                bb:$offset)>;
2204
2205def : Pat <(brcond (i1 (setne (i32 IntRegs:$src1), s10ImmPred:$src2)),
2206                        bb:$offset),
2207      (JMP_f (CMPEQri (i32 IntRegs:$src1), s10ImmPred:$src2), bb:$offset)>;
2208
2209def : Pat <(brcond (i1 (setne (i1 PredRegs:$src1), (i1 -1))), bb:$offset),
2210      (JMP_f (i1 PredRegs:$src1), bb:$offset)>;
2211
2212def : Pat <(brcond (i1 (setne (i1 PredRegs:$src1), (i1 0))), bb:$offset),
2213      (JMP_t (i1 PredRegs:$src1), bb:$offset)>;
2214
2215// cmp.lt(Rs, Imm) -> !cmp.ge(Rs, Imm) -> !cmp.gt(Rs, Imm-1)
2216def : Pat <(brcond (i1 (setlt (i32 IntRegs:$src1), s8ImmPred:$src2)),
2217                        bb:$offset),
2218      (JMP_f (CMPGTri (i32 IntRegs:$src1),
2219                (DEC_CONST_SIGNED s8ImmPred:$src2)), bb:$offset)>;
2220
2221// cmp.lt(r0, r1) -> cmp.gt(r1, r0)
2222def : Pat <(brcond (i1 (setlt (i32 IntRegs:$src1), (i32 IntRegs:$src2))),
2223                        bb:$offset),
2224      (JMP_t (CMPGTrr (i32 IntRegs:$src2), (i32 IntRegs:$src1)), bb:$offset)>;
2225
2226def : Pat <(brcond (i1 (setuge (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))),
2227                   bb:$offset),
2228      (JMP_f (CMPGTU64rr (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1)),
2229                   bb:$offset)>;
2230
2231def : Pat <(brcond (i1 (setule (i32 IntRegs:$src1), (i32 IntRegs:$src2))),
2232                        bb:$offset),
2233      (JMP_f (CMPGTUrr (i32 IntRegs:$src1), (i32 IntRegs:$src2)),
2234                bb:$offset)>;
2235
2236def : Pat <(brcond (i1 (setule (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))),
2237                   bb:$offset),
2238      (JMP_f (CMPGTU64rr (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2)),
2239                bb:$offset)>;
2240
2241// Map from a 64-bit select to an emulated 64-bit mux.
2242// Hexagon does not support 64-bit MUXes; so emulate with combines.
2243def : Pat <(select (i1 PredRegs:$src1), (i64 DoubleRegs:$src2),
2244                   (i64 DoubleRegs:$src3)),
2245      (i64 (COMBINE_rr (i32 (MUX_rr (i1 PredRegs:$src1),
2246                                    (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2),
2247                                                         subreg_hireg)),
2248                                    (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src3),
2249                                                         subreg_hireg)))),
2250                       (i32 (MUX_rr (i1 PredRegs:$src1),
2251                                    (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2),
2252                                                         subreg_loreg)),
2253                                    (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src3),
2254                                                         subreg_loreg))))))>;
2255
2256// Map from a 1-bit select to logical ops.
2257// From LegalizeDAG.cpp: (B1 ? B2 : B3) <=> (B1 & B2)|(!B1&B3).
2258def : Pat <(select (i1 PredRegs:$src1), (i1 PredRegs:$src2),
2259                   (i1 PredRegs:$src3)),
2260      (OR_pp (AND_pp (i1 PredRegs:$src1), (i1 PredRegs:$src2)),
2261             (AND_pp (NOT_p (i1 PredRegs:$src1)), (i1 PredRegs:$src3)))>;
2262
2263// Map Pd = load(addr) -> Rs = load(addr); Pd = Rs.
2264def : Pat<(i1 (load ADDRriS11_2:$addr)),
2265      (i1 (TFR_PdRs (i32 (LDrib ADDRriS11_2:$addr))))>;
2266
2267// Map for truncating from 64 immediates to 32 bit immediates.
2268def : Pat<(i32 (trunc (i64 DoubleRegs:$src))),
2269      (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src), subreg_loreg))>;
2270
2271// Map for truncating from i64 immediates to i1 bit immediates.
2272def :  Pat<(i1 (trunc (i64 DoubleRegs:$src))),
2273       (i1 (TFR_PdRs (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src),
2274                                          subreg_loreg))))>;
2275
2276// Map memb(Rs) = Rdd -> memb(Rs) = Rt.
2277def : Pat<(truncstorei8 (i64 DoubleRegs:$src), ADDRriS11_0:$addr),
2278      (STrib ADDRriS11_0:$addr, (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src),
2279                                                     subreg_loreg)))>;
2280
2281// Map memh(Rs) = Rdd -> memh(Rs) = Rt.
2282def : Pat<(truncstorei16 (i64 DoubleRegs:$src), ADDRriS11_0:$addr),
2283      (STrih ADDRriS11_0:$addr, (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src),
2284                                                     subreg_loreg)))>;
2285// Map memw(Rs) = Rdd -> memw(Rs) = Rt
2286def : Pat<(truncstorei32 (i64  DoubleRegs:$src), ADDRriS11_0:$addr),
2287      (STriw ADDRriS11_0:$addr, (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src),
2288                                                     subreg_loreg)))>;
2289
2290// Map memw(Rs) = Rdd -> memw(Rs) = Rt.
2291def : Pat<(truncstorei32 (i64 DoubleRegs:$src), ADDRriS11_0:$addr),
2292      (STriw ADDRriS11_0:$addr, (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src),
2293                                                     subreg_loreg)))>;
2294
2295// Map from i1 = constant<-1>; memw(addr) = i1 -> r0 = 1; memw(addr) = r0.
2296def : Pat<(store (i1 -1), ADDRriS11_2:$addr),
2297      (STrib ADDRriS11_2:$addr, (TFRI 1))>;
2298
2299
2300// Map from i1 = constant<-1>; store i1 -> r0 = 1; store r0.
2301def : Pat<(store (i1 -1), ADDRriS11_2:$addr),
2302      (STrib ADDRriS11_2:$addr, (TFRI 1))>;
2303
2304// Map from memb(Rs) = Pd -> Rt = mux(Pd, #0, #1); store Rt.
2305def : Pat<(store (i1 PredRegs:$src1), ADDRriS11_2:$addr),
2306      (STrib ADDRriS11_2:$addr, (i32 (MUX_ii (i1 PredRegs:$src1), 1, 0)) )>;
2307
2308// Map Rdd = anyext(Rs) -> Rdd = sxtw(Rs).
2309// Hexagon_TODO: We can probably use combine but that will cost 2 instructions.
2310// Better way to do this?
2311def : Pat<(i64 (anyext (i32 IntRegs:$src1))),
2312      (i64 (SXTW (i32 IntRegs:$src1)))>;
2313
2314// Map cmple -> cmpgt.
2315// rs <= rt -> !(rs > rt).
2316def : Pat<(i1 (setle (i32 IntRegs:$src1), s10ExtPred:$src2)),
2317      (i1 (NOT_p (CMPGTri (i32 IntRegs:$src1), s10ExtPred:$src2)))>;
2318
2319// rs <= rt -> !(rs > rt).
2320def : Pat<(i1 (setle (i32 IntRegs:$src1), (i32 IntRegs:$src2))),
2321      (i1 (NOT_p (CMPGTrr (i32 IntRegs:$src1), (i32 IntRegs:$src2))))>;
2322
2323// Rss <= Rtt -> !(Rss > Rtt).
2324def : Pat<(i1 (setle (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))),
2325      (i1 (NOT_p (CMPGT64rr (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))))>;
2326
2327// Map cmpne -> cmpeq.
2328// Hexagon_TODO: We should improve on this.
2329// rs != rt -> !(rs == rt).
2330def : Pat <(i1 (setne (i32 IntRegs:$src1), s10ExtPred:$src2)),
2331      (i1 (NOT_p(i1 (CMPEQri (i32 IntRegs:$src1), s10ExtPred:$src2))))>;
2332
2333// Map cmpne(Rs) -> !cmpeqe(Rs).
2334// rs != rt -> !(rs == rt).
2335def : Pat <(i1 (setne (i32 IntRegs:$src1), (i32 IntRegs:$src2))),
2336      (i1 (NOT_p (i1 (CMPEQrr (i32 IntRegs:$src1), (i32 IntRegs:$src2)))))>;
2337
2338// Convert setne back to xor for hexagon since we compute w/ pred registers.
2339def : Pat <(i1 (setne (i1 PredRegs:$src1), (i1 PredRegs:$src2))),
2340      (i1 (XOR_pp (i1 PredRegs:$src1), (i1 PredRegs:$src2)))>;
2341
2342// Map cmpne(Rss) -> !cmpew(Rss).
2343// rs != rt -> !(rs == rt).
2344def : Pat <(i1 (setne (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))),
2345      (i1 (NOT_p (i1 (CMPEHexagon4rr (i64 DoubleRegs:$src1),
2346                                     (i64 DoubleRegs:$src2)))))>;
2347
2348// Map cmpge(Rs, Rt) -> !(cmpgt(Rs, Rt).
2349// rs >= rt -> !(rt > rs).
2350def : Pat <(i1 (setge (i32 IntRegs:$src1), (i32 IntRegs:$src2))),
2351      (i1 (NOT_p (i1 (CMPGTrr (i32 IntRegs:$src2), (i32 IntRegs:$src1)))))>;
2352
2353// cmpge(Rs, Imm) -> cmpgt(Rs, Imm-1)
2354def : Pat <(i1 (setge (i32 IntRegs:$src1), s8ExtPred:$src2)),
2355      (i1 (CMPGTri (i32 IntRegs:$src1), (DEC_CONST_SIGNED s8ExtPred:$src2)))>;
2356
2357// Map cmpge(Rss, Rtt) -> !cmpgt(Rtt, Rss).
2358// rss >= rtt -> !(rtt > rss).
2359def : Pat <(i1 (setge (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))),
2360      (i1 (NOT_p (i1 (CMPGT64rr (i64 DoubleRegs:$src2),
2361                                (i64 DoubleRegs:$src1)))))>;
2362
2363// Map cmplt(Rs, Imm) -> !cmpge(Rs, Imm).
2364// !cmpge(Rs, Imm) -> !cmpgt(Rs, Imm-1).
2365// rs < rt -> !(rs >= rt).
2366def : Pat <(i1 (setlt (i32 IntRegs:$src1), s8ExtPred:$src2)),
2367      (i1 (NOT_p (CMPGTri (i32 IntRegs:$src1), (DEC_CONST_SIGNED s8ExtPred:$src2))))>;
2368
2369// Map cmplt(Rs, Rt) -> cmpgt(Rt, Rs).
2370// rs < rt -> rt > rs.
2371// We can let assembler map it, or we can do in the compiler itself.
2372def : Pat <(i1 (setlt (i32 IntRegs:$src1), (i32 IntRegs:$src2))),
2373      (i1 (CMPGTrr (i32 IntRegs:$src2), (i32 IntRegs:$src1)))>;
2374
2375// Map cmplt(Rss, Rtt) -> cmpgt(Rtt, Rss).
2376// rss < rtt -> (rtt > rss).
2377def : Pat <(i1 (setlt (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))),
2378      (i1 (CMPGT64rr (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1)))>;
2379
2380// Map from cmpltu(Rs, Rd) -> cmpgtu(Rd, Rs)
2381// rs < rt -> rt > rs.
2382// We can let assembler map it, or we can do in the compiler itself.
2383def : Pat <(i1 (setult (i32 IntRegs:$src1), (i32 IntRegs:$src2))),
2384      (i1 (CMPGTUrr (i32 IntRegs:$src2), (i32 IntRegs:$src1)))>;
2385
2386// Map from cmpltu(Rss, Rdd) -> cmpgtu(Rdd, Rss).
2387// rs < rt -> rt > rs.
2388def : Pat <(i1 (setult (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))),
2389      (i1 (CMPGTU64rr (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1)))>;
2390
2391// Generate cmpgeu(Rs, #0) -> cmpeq(Rs, Rs)
2392def : Pat <(i1 (setuge (i32 IntRegs:$src1), 0)),
2393      (i1 (CMPEQrr (i32 IntRegs:$src1), (i32 IntRegs:$src1)))>;
2394
2395// Generate cmpgeu(Rs, #u8) -> cmpgtu(Rs, #u8 -1)
2396def : Pat <(i1 (setuge (i32 IntRegs:$src1), u8ExtPred:$src2)),
2397      (i1 (CMPGTUri (i32 IntRegs:$src1), (DEC_CONST_UNSIGNED u8ExtPred:$src2)))>;
2398
2399// Generate cmpgtu(Rs, #u9)
2400def : Pat <(i1 (setugt (i32 IntRegs:$src1), u9ExtPred:$src2)),
2401      (i1 (CMPGTUri (i32 IntRegs:$src1), u9ExtPred:$src2))>;
2402
2403// Map from Rs >= Rt -> !(Rt > Rs).
2404// rs >= rt -> !(rt > rs).
2405def : Pat <(i1 (setuge (i32 IntRegs:$src1), (i32 IntRegs:$src2))),
2406      (i1 (NOT_p (CMPGTUrr (i32 IntRegs:$src2), (i32 IntRegs:$src1))))>;
2407
2408// Map from Rs >= Rt -> !(Rt > Rs).
2409// rs >= rt -> !(rt > rs).
2410def : Pat <(i1 (setuge (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))),
2411      (i1 (NOT_p (CMPGTU64rr (i64 DoubleRegs:$src2), (i64 DoubleRegs:$src1))))>;
2412
2413// Map from cmpleu(Rs, Rt) -> !cmpgtu(Rs, Rt).
2414// Map from (Rs <= Rt) -> !(Rs > Rt).
2415def : Pat <(i1 (setule (i32 IntRegs:$src1), (i32 IntRegs:$src2))),
2416      (i1 (NOT_p (CMPGTUrr (i32 IntRegs:$src1), (i32 IntRegs:$src2))))>;
2417
2418// Map from cmpleu(Rss, Rtt) -> !cmpgtu(Rss, Rtt-1).
2419// Map from (Rs <= Rt) -> !(Rs > Rt).
2420def : Pat <(i1 (setule (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))),
2421      (i1 (NOT_p (CMPGTU64rr (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2))))>;
2422
2423// Sign extends.
2424// i1 -> i32
2425def : Pat <(i32 (sext (i1 PredRegs:$src1))),
2426      (i32 (MUX_ii (i1 PredRegs:$src1), -1, 0))>;
2427
2428// i1 -> i64
2429def : Pat <(i64 (sext (i1 PredRegs:$src1))),
2430      (i64 (COMBINE_rr (TFRI -1), (MUX_ii (i1 PredRegs:$src1), -1, 0)))>;
2431
2432// Convert sign-extended load back to load and sign extend.
2433// i8 -> i64
2434def:  Pat <(i64 (sextloadi8 ADDRriS11_0:$src1)),
2435      (i64 (SXTW (LDrib ADDRriS11_0:$src1)))>;
2436
2437// Convert any-extended load back to load and sign extend.
2438// i8 -> i64
2439def:  Pat <(i64 (extloadi8 ADDRriS11_0:$src1)),
2440      (i64 (SXTW (LDrib ADDRriS11_0:$src1)))>;
2441
2442// Convert sign-extended load back to load and sign extend.
2443// i16 -> i64
2444def:  Pat <(i64 (sextloadi16 ADDRriS11_1:$src1)),
2445      (i64 (SXTW (LDrih ADDRriS11_1:$src1)))>;
2446
2447// Convert sign-extended load back to load and sign extend.
2448// i32 -> i64
2449def:  Pat <(i64 (sextloadi32 ADDRriS11_2:$src1)),
2450      (i64 (SXTW (LDriw ADDRriS11_2:$src1)))>;
2451
2452
2453// Zero extends.
2454// i1 -> i32
2455def : Pat <(i32 (zext (i1 PredRegs:$src1))),
2456      (i32 (MUX_ii (i1 PredRegs:$src1), 1, 0))>;
2457
2458// i1 -> i64
2459def : Pat <(i64 (zext (i1 PredRegs:$src1))),
2460      (i64 (COMBINE_rr (TFRI 0), (MUX_ii (i1 PredRegs:$src1), 1, 0)))>,
2461      Requires<[NoV4T]>;
2462
2463// i32 -> i64
2464def : Pat <(i64 (zext (i32 IntRegs:$src1))),
2465      (i64 (COMBINE_rr (TFRI 0), (i32 IntRegs:$src1)))>,
2466      Requires<[NoV4T]>;
2467
2468// i8 -> i64
2469def:  Pat <(i64 (zextloadi8 ADDRriS11_0:$src1)),
2470      (i64 (COMBINE_rr (TFRI 0), (LDriub ADDRriS11_0:$src1)))>,
2471      Requires<[NoV4T]>;
2472
2473let AddedComplexity = 20 in
2474def:  Pat <(i64 (zextloadi8 (add (i32 IntRegs:$src1),
2475                                s11_0ExtPred:$offset))),
2476      (i64 (COMBINE_rr (TFRI 0), (LDriub_indexed IntRegs:$src1,
2477                                  s11_0ExtPred:$offset)))>,
2478      Requires<[NoV4T]>;
2479
2480// i1 -> i64
2481def:  Pat <(i64 (zextloadi1 ADDRriS11_0:$src1)),
2482      (i64 (COMBINE_rr (TFRI 0), (LDriub ADDRriS11_0:$src1)))>,
2483      Requires<[NoV4T]>;
2484
2485let AddedComplexity = 20 in
2486def:  Pat <(i64 (zextloadi1 (add (i32 IntRegs:$src1),
2487                                s11_0ExtPred:$offset))),
2488      (i64 (COMBINE_rr (TFRI 0), (LDriub_indexed IntRegs:$src1,
2489                                  s11_0ExtPred:$offset)))>,
2490      Requires<[NoV4T]>;
2491
2492// i16 -> i64
2493def:  Pat <(i64 (zextloadi16 ADDRriS11_1:$src1)),
2494      (i64 (COMBINE_rr (TFRI 0), (LDriuh ADDRriS11_1:$src1)))>,
2495      Requires<[NoV4T]>;
2496
2497let AddedComplexity = 20 in
2498def:  Pat <(i64 (zextloadi16 (add (i32 IntRegs:$src1),
2499                                  s11_1ExtPred:$offset))),
2500      (i64 (COMBINE_rr (TFRI 0), (LDriuh_indexed IntRegs:$src1,
2501                                  s11_1ExtPred:$offset)))>,
2502      Requires<[NoV4T]>;
2503
2504// i32 -> i64
2505def:  Pat <(i64 (zextloadi32 ADDRriS11_2:$src1)),
2506      (i64 (COMBINE_rr (TFRI 0), (LDriw ADDRriS11_2:$src1)))>,
2507      Requires<[NoV4T]>;
2508
2509let AddedComplexity = 100 in
2510def:  Pat <(i64 (zextloadi32 (i32 (add IntRegs:$src1, s11_2ExtPred:$offset)))),
2511      (i64 (COMBINE_rr (TFRI 0), (LDriw_indexed IntRegs:$src1,
2512                                  s11_2ExtPred:$offset)))>,
2513      Requires<[NoV4T]>;
2514
2515let AddedComplexity = 10 in
2516def:  Pat <(i32 (zextloadi1 ADDRriS11_0:$src1)),
2517      (i32 (LDriw ADDRriS11_0:$src1))>;
2518
2519// Map from Rs = Pd to Pd = mux(Pd, #1, #0)
2520def : Pat <(i32 (zext (i1 PredRegs:$src1))),
2521      (i32 (MUX_ii (i1 PredRegs:$src1), 1, 0))>;
2522
2523// Map from Rs = Pd to Pd = mux(Pd, #1, #0)
2524def : Pat <(i32 (anyext (i1 PredRegs:$src1))),
2525      (i32 (MUX_ii (i1 PredRegs:$src1), 1, 0))>;
2526
2527// Map from Rss = Pd to Rdd = sxtw (mux(Pd, #1, #0))
2528def : Pat <(i64 (anyext (i1 PredRegs:$src1))),
2529      (i64 (SXTW (i32 (MUX_ii (i1 PredRegs:$src1), 1, 0))))>;
2530
2531
2532let AddedComplexity = 100 in
2533def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh),
2534                           (i32 32))),
2535               (i64 (zextloadi32 (i32 (add IntRegs:$src2,
2536                                         s11_2ExtPred:$offset2)))))),
2537        (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg),
2538                        (LDriw_indexed IntRegs:$src2,
2539                                       s11_2ExtPred:$offset2)))>;
2540
2541def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh),
2542                           (i32 32))),
2543               (i64 (zextloadi32 ADDRriS11_2:$srcLow)))),
2544        (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg),
2545                        (LDriw ADDRriS11_2:$srcLow)))>;
2546
2547def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh),
2548                           (i32 32))),
2549               (i64 (zext (i32 IntRegs:$srcLow))))),
2550        (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg),
2551                        IntRegs:$srcLow))>;
2552
2553let AddedComplexity = 100 in
2554def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh),
2555                           (i32 32))),
2556               (i64 (zextloadi32 (i32 (add IntRegs:$src2,
2557                                         s11_2ExtPred:$offset2)))))),
2558        (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg),
2559                        (LDriw_indexed IntRegs:$src2,
2560                                       s11_2ExtPred:$offset2)))>;
2561
2562def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh),
2563                           (i32 32))),
2564               (i64 (zextloadi32 ADDRriS11_2:$srcLow)))),
2565        (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg),
2566                        (LDriw ADDRriS11_2:$srcLow)))>;
2567
2568def: Pat<(i64 (or (i64 (shl (i64 DoubleRegs:$srcHigh),
2569                           (i32 32))),
2570               (i64 (zext (i32 IntRegs:$srcLow))))),
2571        (i64 (COMBINE_rr (EXTRACT_SUBREG (i64 DoubleRegs:$srcHigh), subreg_loreg),
2572                        IntRegs:$srcLow))>;
2573
2574// Any extended 64-bit load.
2575// anyext i32 -> i64
2576def:  Pat <(i64 (extloadi32 ADDRriS11_2:$src1)),
2577      (i64 (COMBINE_rr (TFRI 0), (LDriw ADDRriS11_2:$src1)))>,
2578      Requires<[NoV4T]>;
2579
2580// When there is an offset we should prefer the pattern below over the pattern above.
2581// The complexity of the above is 13 (gleaned from HexagonGenDAGIsel.inc)
2582// So this complexity below is comfortably higher to allow for choosing the below.
2583// If this is not done then we generate addresses such as
2584// ********************************************
2585//        r1 = add (r0, #4)
2586//        r1 = memw(r1 + #0)
2587//  instead of
2588//        r1 = memw(r0 + #4)
2589// ********************************************
2590let AddedComplexity = 100 in
2591def:  Pat <(i64 (extloadi32 (i32 (add IntRegs:$src1, s11_2ExtPred:$offset)))),
2592      (i64 (COMBINE_rr (TFRI 0), (LDriw_indexed IntRegs:$src1,
2593                                  s11_2ExtPred:$offset)))>,
2594      Requires<[NoV4T]>;
2595
2596// anyext i16 -> i64.
2597def:  Pat <(i64 (extloadi16 ADDRriS11_2:$src1)),
2598      (i64 (COMBINE_rr (TFRI 0), (LDrih ADDRriS11_2:$src1)))>,
2599      Requires<[NoV4T]>;
2600
2601let AddedComplexity = 20 in
2602def:  Pat <(i64 (extloadi16 (add (i32 IntRegs:$src1),
2603                                  s11_1ExtPred:$offset))),
2604      (i64 (COMBINE_rr (TFRI 0), (LDrih_indexed IntRegs:$src1,
2605                                  s11_1ExtPred:$offset)))>,
2606      Requires<[NoV4T]>;
2607
2608// Map from Rdd = zxtw(Rs) -> Rdd = combine(0, Rs).
2609def : Pat<(i64 (zext (i32 IntRegs:$src1))),
2610      (i64 (COMBINE_rr (TFRI 0), (i32 IntRegs:$src1)))>,
2611      Requires<[NoV4T]>;
2612
2613// Multiply 64-bit unsigned and use upper result.
2614def : Pat <(mulhu (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2)),
2615      (i64
2616       (MPYU64_acc
2617        (i64
2618         (COMBINE_rr
2619          (TFRI 0),
2620           (i32
2621            (EXTRACT_SUBREG
2622             (i64
2623              (LSRd_ri
2624               (i64
2625                (MPYU64_acc
2626                 (i64
2627                  (MPYU64_acc
2628                   (i64
2629                    (COMBINE_rr (TFRI 0),
2630                     (i32
2631                      (EXTRACT_SUBREG
2632                       (i64
2633                        (LSRd_ri
2634                         (i64
2635                          (MPYU64 (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1),
2636                                                       subreg_loreg)),
2637                                  (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2),
2638                                                       subreg_loreg)))), 32)),
2639                       subreg_loreg)))),
2640                  (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_hireg)),
2641                  (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2), subreg_loreg)))),
2642                 (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_loreg)),
2643                 (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2), subreg_hireg)))),
2644               32)), subreg_loreg)))),
2645        (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_hireg)),
2646        (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2), subreg_hireg))))>;
2647
2648// Multiply 64-bit signed and use upper result.
2649def : Pat <(mulhs (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2)),
2650      (i64
2651       (MPY64_acc
2652        (i64
2653         (COMBINE_rr (TFRI 0),
2654          (i32
2655           (EXTRACT_SUBREG
2656            (i64
2657             (LSRd_ri
2658              (i64
2659               (MPY64_acc
2660                (i64
2661                 (MPY64_acc
2662                  (i64
2663                   (COMBINE_rr (TFRI 0),
2664                    (i32
2665                     (EXTRACT_SUBREG
2666                      (i64
2667                       (LSRd_ri
2668                        (i64
2669                         (MPYU64 (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1),
2670                                                      subreg_loreg)),
2671                                 (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2),
2672                                                      subreg_loreg)))), 32)),
2673                      subreg_loreg)))),
2674                  (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_hireg)),
2675                  (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2), subreg_loreg)))),
2676                (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_loreg)),
2677                (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2), subreg_hireg)))),
2678              32)), subreg_loreg)))),
2679        (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_hireg)),
2680        (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2), subreg_hireg))))>;
2681
2682// Hexagon specific ISD nodes.
2683//def SDTHexagonADJDYNALLOC : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>]>;
2684def SDTHexagonADJDYNALLOC : SDTypeProfile<1, 2,
2685                                  [SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
2686def Hexagon_ADJDYNALLOC : SDNode<"HexagonISD::ADJDYNALLOC",
2687                                  SDTHexagonADJDYNALLOC>;
2688// Needed to tag these instructions for stack layout.
2689let usesCustomInserter = 1 in
2690def ADJDYNALLOC : ALU32_ri<(outs IntRegs:$dst), (ins IntRegs:$src1,
2691                                                     s16Imm:$src2),
2692                  "$dst = add($src1, #$src2)",
2693                  [(set (i32 IntRegs:$dst),
2694                        (Hexagon_ADJDYNALLOC (i32 IntRegs:$src1),
2695                                             s16ImmPred:$src2))]>;
2696
2697def SDTHexagonARGEXTEND : SDTypeProfile<1, 1, [SDTCisVT<0, i32>]>;
2698def Hexagon_ARGEXTEND : SDNode<"HexagonISD::ARGEXTEND", SDTHexagonARGEXTEND>;
2699def ARGEXTEND : ALU32_rr <(outs IntRegs:$dst), (ins IntRegs:$src1),
2700                "$dst = $src1",
2701                [(set (i32 IntRegs:$dst),
2702                      (Hexagon_ARGEXTEND (i32 IntRegs:$src1)))]>;
2703
2704let AddedComplexity = 100 in
2705def : Pat<(i32 (sext_inreg (Hexagon_ARGEXTEND (i32 IntRegs:$src1)), i16)),
2706      (COPY (i32 IntRegs:$src1))>;
2707
2708def HexagonWrapperJT: SDNode<"HexagonISD::WrapperJT", SDTIntUnaryOp>;
2709
2710def : Pat<(HexagonWrapperJT tjumptable:$dst),
2711          (i32 (CONST32_set_jt tjumptable:$dst))>;
2712
2713// XTYPE/SHIFT
2714
2715// Multi-class for logical operators :
2716// Shift by immediate/register and accumulate/logical
2717multiclass xtype_imm<string OpcStr, SDNode OpNode1, SDNode OpNode2> {
2718  def _ri : SInst_acc<(outs IntRegs:$dst),
2719            (ins IntRegs:$src1, IntRegs:$src2, u5Imm:$src3),
2720            !strconcat("$dst ", !strconcat(OpcStr, "($src2, #$src3)")),
2721            [(set (i32 IntRegs:$dst),
2722                  (OpNode2 (i32 IntRegs:$src1),
2723                           (OpNode1 (i32 IntRegs:$src2),
2724                                    u5ImmPred:$src3)))],
2725            "$src1 = $dst">;
2726
2727  def d_ri : SInst_acc<(outs DoubleRegs:$dst),
2728            (ins DoubleRegs:$src1, DoubleRegs:$src2, u6Imm:$src3),
2729            !strconcat("$dst ", !strconcat(OpcStr, "($src2, #$src3)")),
2730            [(set (i64 DoubleRegs:$dst), (OpNode2 (i64 DoubleRegs:$src1),
2731                          (OpNode1 (i64 DoubleRegs:$src2), u6ImmPred:$src3)))],
2732            "$src1 = $dst">;
2733}
2734
2735// Multi-class for logical operators :
2736// Shift by register and accumulate/logical (32/64 bits)
2737multiclass xtype_reg<string OpcStr, SDNode OpNode1, SDNode OpNode2> {
2738  def _rr : SInst_acc<(outs IntRegs:$dst),
2739            (ins IntRegs:$src1, IntRegs:$src2, IntRegs:$src3),
2740            !strconcat("$dst ", !strconcat(OpcStr, "($src2, $src3)")),
2741            [(set (i32 IntRegs:$dst),
2742                  (OpNode2 (i32 IntRegs:$src1),
2743                           (OpNode1 (i32 IntRegs:$src2),
2744                                    (i32 IntRegs:$src3))))],
2745            "$src1 = $dst">;
2746
2747  def d_rr : SInst_acc<(outs DoubleRegs:$dst),
2748            (ins DoubleRegs:$src1, DoubleRegs:$src2, IntRegs:$src3),
2749            !strconcat("$dst ", !strconcat(OpcStr, "($src2, $src3)")),
2750            [(set (i64 DoubleRegs:$dst),
2751                  (OpNode2 (i64 DoubleRegs:$src1),
2752                           (OpNode1 (i64 DoubleRegs:$src2),
2753                                    (i32 IntRegs:$src3))))],
2754            "$src1 = $dst">;
2755
2756}
2757
2758multiclass basic_xtype_imm<string OpcStr, SDNode OpNode> {
2759let AddedComplexity = 100 in
2760  defm _ADD : xtype_imm< !strconcat("+= ", OpcStr), OpNode, add>;
2761  defm _SUB : xtype_imm< !strconcat("-= ", OpcStr), OpNode, sub>;
2762  defm _AND : xtype_imm< !strconcat("&= ", OpcStr), OpNode, and>;
2763  defm _OR  : xtype_imm< !strconcat("|= ", OpcStr), OpNode, or>;
2764}
2765
2766multiclass basic_xtype_reg<string OpcStr, SDNode OpNode> {
2767let AddedComplexity = 100 in
2768  defm _ADD : xtype_reg< !strconcat("+= ", OpcStr), OpNode, add>;
2769  defm _SUB : xtype_reg< !strconcat("-= ", OpcStr), OpNode, sub>;
2770  defm _AND : xtype_reg< !strconcat("&= ", OpcStr), OpNode, and>;
2771  defm _OR  : xtype_reg< !strconcat("|= ", OpcStr), OpNode, or>;
2772}
2773
2774multiclass xtype_xor_imm<string OpcStr, SDNode OpNode> {
2775let AddedComplexity = 100 in
2776  defm _XOR : xtype_imm< !strconcat("^= ", OpcStr), OpNode, xor>;
2777}
2778
2779defm ASL : basic_xtype_imm<"asl", shl>, basic_xtype_reg<"asl", shl>,
2780           xtype_xor_imm<"asl", shl>;
2781
2782defm LSR : basic_xtype_imm<"lsr", srl>, basic_xtype_reg<"lsr", srl>,
2783           xtype_xor_imm<"lsr", srl>;
2784
2785defm ASR : basic_xtype_imm<"asr", sra>, basic_xtype_reg<"asr", sra>;
2786defm LSL : basic_xtype_reg<"lsl", shl>;
2787
2788// Change the sign of the immediate for Rd=-mpyi(Rs,#u8)
2789def : Pat <(mul (i32 IntRegs:$src1), (ineg n8ImmPred:$src2)),
2790      (i32 (MPYI_rin (i32 IntRegs:$src1), u8ImmPred:$src2))>;
2791
2792//===----------------------------------------------------------------------===//
2793// V3 Instructions +
2794//===----------------------------------------------------------------------===//
2795
2796include "HexagonInstrInfoV3.td"
2797
2798//===----------------------------------------------------------------------===//
2799// V3 Instructions -
2800//===----------------------------------------------------------------------===//
2801
2802//===----------------------------------------------------------------------===//
2803// V4 Instructions +
2804//===----------------------------------------------------------------------===//
2805
2806include "HexagonInstrInfoV4.td"
2807
2808//===----------------------------------------------------------------------===//
2809// V4 Instructions -
2810//===----------------------------------------------------------------------===//
2811
2812//===----------------------------------------------------------------------===//
2813// V5 Instructions +
2814//===----------------------------------------------------------------------===//
2815
2816include "HexagonInstrInfoV5.td"
2817
2818//===----------------------------------------------------------------------===//
2819// V5 Instructions -
2820//===----------------------------------------------------------------------===//
2821