106f32e7eSjoerg//===--- HexagonPseudo.td -------------------------------------------------===//
206f32e7eSjoerg//
306f32e7eSjoerg// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg// See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg//
706f32e7eSjoerg//===----------------------------------------------------------------------===//
806f32e7eSjoerg
906f32e7eSjoerg// The pat frags in the definitions below need to have a named register,
1006f32e7eSjoerg// otherwise i32 will be assumed regardless of the register class. The
1106f32e7eSjoerg// name of the register does not matter.
1206f32e7eSjoergdef I1  : PatLeaf<(i1 PredRegs:$R)>;
1306f32e7eSjoergdef I32 : PatLeaf<(i32 IntRegs:$R)>;
1406f32e7eSjoergdef I64 : PatLeaf<(i64 DoubleRegs:$R)>;
1506f32e7eSjoergdef F32 : PatLeaf<(f32 IntRegs:$R)>;
1606f32e7eSjoergdef F64 : PatLeaf<(f64 DoubleRegs:$R)>;
1706f32e7eSjoerg
1806f32e7eSjoerglet PrintMethod = "printGlobalOperand" in {
1906f32e7eSjoerg  def globaladdress : Operand<i32>;
2006f32e7eSjoerg  def globaladdressExt : Operand<i32>;
2106f32e7eSjoerg}
2206f32e7eSjoerg
2306f32e7eSjoerglet isPseudo = 1 in {
2406f32e7eSjoerglet isCodeGenOnly = 0 in
2506f32e7eSjoergdef A2_iconst : Pseudo<(outs IntRegs:$Rd32),
2606f32e7eSjoerg    (ins s27_2Imm:$Ii), "${Rd32} = iconst(#${Ii})">;
2706f32e7eSjoerg
2806f32e7eSjoergdef DUPLEX_Pseudo : InstHexagon<(outs),
2906f32e7eSjoerg    (ins s32_0Imm:$offset), "DUPLEX", [], "", DUPLEX, TypePSEUDO>;
3006f32e7eSjoerg}
3106f32e7eSjoerg
3206f32e7eSjoerglet isExtendable = 1, opExtendable = 1, opExtentBits = 6,
3306f32e7eSjoerg    isAsmParserOnly = 1 in
3406f32e7eSjoergdef TFRI64_V2_ext : InstHexagon<(outs DoubleRegs:$dst),
3506f32e7eSjoerg    (ins s32_0Imm:$src1, s8_0Imm:$src2),
3606f32e7eSjoerg    "$dst = combine(#$src1,#$src2)", [], "",
3706f32e7eSjoerg    A2_combineii.Itinerary, TypeALU32_2op>, OpcodeHexagon;
3806f32e7eSjoerg
3906f32e7eSjoerg// HI/LO Instructions
4006f32e7eSjoerglet isReMaterializable = 1, isMoveImm = 1, hasSideEffects = 0,
4106f32e7eSjoerg    hasNewValue = 1, opNewValue = 0 in
4206f32e7eSjoergclass REG_IMMED<string RegHalf, bit Rs, bits<3> MajOp, bit MinOp,
4306f32e7eSjoerg                InstHexagon rootInst>
4406f32e7eSjoerg  : InstHexagon<(outs IntRegs:$dst),
4506f32e7eSjoerg                (ins u16_0Imm:$imm_value),
4606f32e7eSjoerg                "$dst"#RegHalf#" = #$imm_value", [], "",
4706f32e7eSjoerg                rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {
4806f32e7eSjoerg    bits<5> dst;
4906f32e7eSjoerg    bits<32> imm_value;
5006f32e7eSjoerg
5106f32e7eSjoerg    let Inst{27} = Rs;
5206f32e7eSjoerg    let Inst{26-24} = MajOp;
5306f32e7eSjoerg    let Inst{21} = MinOp;
5406f32e7eSjoerg    let Inst{20-16} = dst;
5506f32e7eSjoerg    let Inst{23-22} = imm_value{15-14};
5606f32e7eSjoerg    let Inst{13-0} = imm_value{13-0};
5706f32e7eSjoerg}
5806f32e7eSjoerg
5906f32e7eSjoerglet isAsmParserOnly = 1 in {
6006f32e7eSjoerg  def LO : REG_IMMED<".l", 0b0, 0b001, 0b1, A2_tfril>;
6106f32e7eSjoerg  def HI : REG_IMMED<".h", 0b0, 0b010, 0b1, A2_tfrih>;
6206f32e7eSjoerg}
6306f32e7eSjoerg
6406f32e7eSjoerglet isReMaterializable = 1, isMoveImm = 1, isAsmParserOnly = 1 in {
6506f32e7eSjoerg  def CONST32 : CONSTLDInst<(outs IntRegs:$Rd), (ins i32imm:$v),
6606f32e7eSjoerg                "$Rd = CONST32(#$v)", []>;
6706f32e7eSjoerg  def CONST64 : CONSTLDInst<(outs DoubleRegs:$Rd), (ins i64imm:$v),
6806f32e7eSjoerg                "$Rd = CONST64(#$v)", []>;
6906f32e7eSjoerg}
7006f32e7eSjoerg
7106f32e7eSjoerglet hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,
7206f32e7eSjoerg    isCodeGenOnly = 1 in
7306f32e7eSjoergdef PS_true : InstHexagon<(outs PredRegs:$dst), (ins), "",
7406f32e7eSjoerg              [(set I1:$dst, 1)], "", C2_orn.Itinerary, TypeCR>;
7506f32e7eSjoerg
7606f32e7eSjoerglet hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,
7706f32e7eSjoerg    isCodeGenOnly = 1 in
7806f32e7eSjoergdef PS_false : InstHexagon<(outs PredRegs:$dst), (ins), "",
7906f32e7eSjoerg               [(set I1:$dst, 0)], "", C2_andn.Itinerary, TypeCR>;
8006f32e7eSjoerg
8106f32e7eSjoerglet Defs = [R29, R30], Uses = [R31, R30, R29], isPseudo = 1 in
8206f32e7eSjoergdef ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
8306f32e7eSjoerg                              ".error \"should not emit\" ", []>;
8406f32e7eSjoerg
8506f32e7eSjoerglet Defs = [R29, R30, R31], Uses = [R29], isPseudo = 1 in
8606f32e7eSjoergdef ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
8706f32e7eSjoerg                             ".error \"should not emit\" ", []>;
8806f32e7eSjoerg
8906f32e7eSjoerg
9006f32e7eSjoerglet isBranch = 1, isTerminator = 1, hasSideEffects = 0,
9106f32e7eSjoerg    Defs = [PC, LC0], Uses = [SA0, LC0] in {
9206f32e7eSjoergdef ENDLOOP0 : Endloop<(outs), (ins b30_2Imm:$offset),
9306f32e7eSjoerg                       ":endloop0",
9406f32e7eSjoerg                       []>;
9506f32e7eSjoerg}
9606f32e7eSjoerg
9706f32e7eSjoerglet isBranch = 1, isTerminator = 1, hasSideEffects = 0,
9806f32e7eSjoerg    Defs = [PC, LC1], Uses = [SA1, LC1] in {
9906f32e7eSjoergdef ENDLOOP1 : Endloop<(outs), (ins b30_2Imm:$offset),
10006f32e7eSjoerg                       ":endloop1",
10106f32e7eSjoerg                       []>;
10206f32e7eSjoerg}
10306f32e7eSjoerg
10406f32e7eSjoerglet isBranch = 1, isTerminator = 1, hasSideEffects = 0,
10506f32e7eSjoerg    Defs = [PC, LC0, LC1], Uses = [SA0, SA1, LC0, LC1] in {
10606f32e7eSjoergdef ENDLOOP01 : Endloop<(outs), (ins b30_2Imm:$offset),
10706f32e7eSjoerg                        ":endloop01",
10806f32e7eSjoerg                        []>;
10906f32e7eSjoerg}
11006f32e7eSjoerg
11106f32e7eSjoerglet isExtendable = 1, isExtentSigned = 1, opExtentBits = 9, opExtentAlign = 2,
11206f32e7eSjoerg    opExtendable = 0, hasSideEffects = 0 in
11306f32e7eSjoergclass LOOP_iBase<string mnemonic, InstHexagon rootInst>
11406f32e7eSjoerg         : InstHexagon <(outs), (ins b30_2Imm:$offset, u10_0Imm:$src2),
115*da58b97aSjoerg           mnemonic#"($offset,#$src2)",
11606f32e7eSjoerg           [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {
11706f32e7eSjoerg    bits<9> offset;
11806f32e7eSjoerg    bits<10> src2;
11906f32e7eSjoerg
12006f32e7eSjoerg    let IClass = 0b0110;
12106f32e7eSjoerg
12206f32e7eSjoerg    let Inst{27-22} = 0b100100;
12306f32e7eSjoerg    let Inst{21} = !if (!eq(mnemonic, "loop0"), 0b0, 0b1);
12406f32e7eSjoerg    let Inst{20-16} = src2{9-5};
12506f32e7eSjoerg    let Inst{12-8} = offset{8-4};
12606f32e7eSjoerg    let Inst{7-5} = src2{4-2};
12706f32e7eSjoerg    let Inst{4-3} = offset{3-2};
12806f32e7eSjoerg    let Inst{1-0} = src2{1-0};
12906f32e7eSjoerg}
13006f32e7eSjoerg
13106f32e7eSjoerglet isExtendable = 1, isExtentSigned = 1, opExtentBits = 9, opExtentAlign = 2,
13206f32e7eSjoerg    opExtendable = 0, hasSideEffects = 0 in
13306f32e7eSjoergclass LOOP_rBase<string mnemonic, InstHexagon rootInst>
13406f32e7eSjoerg         : InstHexagon<(outs), (ins b30_2Imm:$offset, IntRegs:$src2),
135*da58b97aSjoerg           mnemonic#"($offset,$src2)",
13606f32e7eSjoerg           [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {
13706f32e7eSjoerg    bits<9> offset;
13806f32e7eSjoerg    bits<5> src2;
13906f32e7eSjoerg
14006f32e7eSjoerg    let IClass = 0b0110;
14106f32e7eSjoerg
14206f32e7eSjoerg    let Inst{27-22} = 0b000000;
14306f32e7eSjoerg    let Inst{21} = !if (!eq(mnemonic, "loop0"), 0b0, 0b1);
14406f32e7eSjoerg    let Inst{20-16} = src2;
14506f32e7eSjoerg    let Inst{12-8} = offset{8-4};
14606f32e7eSjoerg    let Inst{4-3} = offset{3-2};
14706f32e7eSjoerg  }
14806f32e7eSjoerg
14906f32e7eSjoerglet Defs = [SA0, LC0, USR], isCodeGenOnly = 1, isExtended = 1,
15006f32e7eSjoerg    opExtendable = 0 in {
15106f32e7eSjoerg  def J2_loop0iext : LOOP_iBase<"loop0", J2_loop0i>;
15206f32e7eSjoerg  def J2_loop1iext : LOOP_iBase<"loop1", J2_loop1i>;
15306f32e7eSjoerg}
15406f32e7eSjoerg
15506f32e7eSjoerg// Interestingly only loop0's appear to set usr.lpcfg
15606f32e7eSjoerglet Defs = [SA1, LC1], isCodeGenOnly = 1, isExtended = 1, opExtendable = 0 in {
15706f32e7eSjoerg  def J2_loop0rext : LOOP_rBase<"loop0", J2_loop0r>;
15806f32e7eSjoerg  def J2_loop1rext : LOOP_rBase<"loop1", J2_loop1r>;
15906f32e7eSjoerg}
16006f32e7eSjoerg
16106f32e7eSjoerglet isCall = 1, hasSideEffects = 1, isPredicable = 0,
16206f32e7eSjoerg    isExtended = 0, isExtendable = 1, opExtendable = 0,
16306f32e7eSjoerg    isExtentSigned = 1, opExtentBits = 24, opExtentAlign = 2 in
16406f32e7eSjoergclass T_Call<string ExtStr>
16506f32e7eSjoerg  : InstHexagon<(outs), (ins a30_2Imm:$dst),
16606f32e7eSjoerg      "call " # ExtStr # "$dst", [], "", J2_call.Itinerary, TypeJ>,
16706f32e7eSjoerg    OpcodeHexagon {
16806f32e7eSjoerg  let BaseOpcode = "call";
16906f32e7eSjoerg  bits<24> dst;
17006f32e7eSjoerg
17106f32e7eSjoerg  let IClass = 0b0101;
17206f32e7eSjoerg  let Inst{27-25} = 0b101;
17306f32e7eSjoerg  let Inst{24-16,13-1} = dst{23-2};
17406f32e7eSjoerg  let Inst{0} = 0b0;
17506f32e7eSjoerg}
17606f32e7eSjoerg
17706f32e7eSjoerglet isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1, Defs = [R16],
17806f32e7eSjoerg    isPredicable = 0 in
17906f32e7eSjoergdef CALLProfile :  T_Call<"">;
18006f32e7eSjoerg
18106f32e7eSjoerglet isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1,
18206f32e7eSjoerg    Defs = [PC, R31, R6, R7, P0] in
18306f32e7eSjoergdef PS_call_stk : T_Call<"">;
18406f32e7eSjoerg
18506f32e7eSjoerg// Call, no return.
18606f32e7eSjoerglet isCall = 1, hasSideEffects = 1, cofMax1 = 1, isCodeGenOnly = 1 in
18706f32e7eSjoergdef PS_callr_nr: InstHexagon<(outs), (ins IntRegs:$Rs),
18806f32e7eSjoerg    "callr $Rs", [], "", J2_callr.Itinerary, TypeJ>, OpcodeHexagon {
18906f32e7eSjoerg    bits<5> Rs;
19006f32e7eSjoerg    bits<2> Pu;
19106f32e7eSjoerg    let isPredicatedFalse = 1;
19206f32e7eSjoerg
19306f32e7eSjoerg    let IClass = 0b0101;
19406f32e7eSjoerg    let Inst{27-21} = 0b0000101;
19506f32e7eSjoerg    let Inst{20-16} = Rs;
19606f32e7eSjoerg  }
19706f32e7eSjoerg
19806f32e7eSjoerglet isCall = 1, hasSideEffects = 1,
19906f32e7eSjoerg    isExtended = 0, isExtendable = 1, opExtendable = 0, isCodeGenOnly = 1,
20006f32e7eSjoerg    BaseOpcode = "PS_call_nr", isExtentSigned = 1, opExtentAlign = 2 in
20106f32e7eSjoergclass Call_nr<bits<5> nbits, bit isPred, bit isFalse, dag iops,
20206f32e7eSjoerg              InstrItinClass itin>
20306f32e7eSjoerg  : Pseudo<(outs), iops, "">, PredRel {
20406f32e7eSjoerg    bits<2> Pu;
20506f32e7eSjoerg    bits<17> dst;
20606f32e7eSjoerg    let opExtentBits = nbits;
20706f32e7eSjoerg    let isPredicable = 0;  // !if(isPred, 0, 1);
20806f32e7eSjoerg    let isPredicated = 0;  // isPred;
20906f32e7eSjoerg    let isPredicatedFalse = isFalse;
21006f32e7eSjoerg    let Itinerary = itin;
21106f32e7eSjoerg}
21206f32e7eSjoerg
21306f32e7eSjoergdef PS_call_nr : Call_nr<24, 0, 0, (ins s32_0Imm:$Ii), J2_call.Itinerary>;
21406f32e7eSjoerg//def PS_call_nrt: Call_nr<17, 1, 0, (ins PredRegs:$Pu, s32_0Imm:$dst),
21506f32e7eSjoerg//                         J2_callt.Itinerary>;
21606f32e7eSjoerg//def PS_call_nrf: Call_nr<17, 1, 1, (ins PredRegs:$Pu, s32_0Imm:$dst),
21706f32e7eSjoerg//                         J2_callf.Itinerary>;
21806f32e7eSjoerg
21906f32e7eSjoerglet isBranch = 1, isIndirectBranch = 1, isBarrier = 1, Defs = [PC],
22006f32e7eSjoerg    isPredicable = 1, hasSideEffects = 0, InputType = "reg",
22106f32e7eSjoerg    cofMax1 = 1 in
22206f32e7eSjoergclass T_JMPr <InstHexagon rootInst>
22306f32e7eSjoerg  :  InstHexagon<(outs), (ins IntRegs:$dst), "jumpr $dst", [],
22406f32e7eSjoerg                 "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {
22506f32e7eSjoerg    bits<5> dst;
22606f32e7eSjoerg
22706f32e7eSjoerg    let IClass = 0b0101;
22806f32e7eSjoerg    let Inst{27-21} = 0b0010100;
22906f32e7eSjoerg    let Inst{20-16} = dst;
23006f32e7eSjoerg}
23106f32e7eSjoerg
23206f32e7eSjoerg// A return through builtin_eh_return.
23306f32e7eSjoerglet isReturn = 1, isTerminator = 1, isBarrier = 1, hasSideEffects = 0,
23406f32e7eSjoerg    isCodeGenOnly = 1, Defs = [PC], Uses = [R28], isPredicable = 0 in
23506f32e7eSjoergdef EH_RETURN_JMPR : T_JMPr<J2_jumpr>;
23606f32e7eSjoerg
23706f32e7eSjoerg// Indirect tail-call.
23806f32e7eSjoerglet isPseudo = 1, isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0,
23906f32e7eSjoerg    isTerminator = 1, isCodeGenOnly = 1 in
24006f32e7eSjoergdef PS_tailcall_r : T_JMPr<J2_jumpr>;
24106f32e7eSjoerg
24206f32e7eSjoerg//
24306f32e7eSjoerg// Direct tail-calls.
24406f32e7eSjoerglet isPseudo = 1, isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0,
24506f32e7eSjoerg    isTerminator = 1, isCodeGenOnly = 1 in
24606f32e7eSjoergdef PS_tailcall_i : Pseudo<(outs), (ins a30_2Imm:$dst), "", []>;
24706f32e7eSjoerg
24806f32e7eSjoerglet isCodeGenOnly = 1, isPseudo = 1, Uses = [R30], hasSideEffects = 0 in
24906f32e7eSjoergdef PS_aligna : Pseudo<(outs IntRegs:$Rd), (ins u32_0Imm:$A), "", []>;
25006f32e7eSjoerg
25106f32e7eSjoerg// Generate frameindex addresses. The main reason for the offset operand is
25206f32e7eSjoerg// that every instruction that is allowed to have frame index as an operand
25306f32e7eSjoerg// will then have that operand followed by an immediate operand (the offset).
25406f32e7eSjoerg// This simplifies the frame-index elimination code.
25506f32e7eSjoerg//
25606f32e7eSjoerglet isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1,
25706f32e7eSjoerg    isPseudo = 1, isCodeGenOnly = 1, hasSideEffects = 0, isExtendable = 1,
25806f32e7eSjoerg    isExtentSigned = 1, opExtentBits = 16, opExtentAlign = 0 in {
25906f32e7eSjoerg  let opExtendable = 2 in
26006f32e7eSjoerg  def PS_fi  : Pseudo<(outs IntRegs:$Rd),
26106f32e7eSjoerg                      (ins IntRegs:$fi, s32_0Imm:$off), "">;
26206f32e7eSjoerg  let opExtendable = 3 in
26306f32e7eSjoerg  def PS_fia : Pseudo<(outs IntRegs:$Rd),
26406f32e7eSjoerg                      (ins IntRegs:$Rs, IntRegs:$fi, s32_0Imm:$off), "">;
26506f32e7eSjoerg}
26606f32e7eSjoerg
26706f32e7eSjoergclass CondStr<string CReg, bit True, bit New> {
26806f32e7eSjoerg  string S = "if (" # !if(True,"","!") # CReg # !if(New,".new","") # ") ";
26906f32e7eSjoerg}
27006f32e7eSjoergclass JumpOpcStr<string Mnemonic, bit New, bit Taken> {
27106f32e7eSjoerg  string S = Mnemonic # !if(Taken, ":t", ":nt");
27206f32e7eSjoerg}
27306f32e7eSjoerglet isBranch = 1, isIndirectBranch = 1, Defs = [PC], isPredicated = 1,
27406f32e7eSjoerg    hasSideEffects = 0, InputType = "reg", cofMax1 = 1 in
27506f32e7eSjoergclass T_JMPr_c <bit PredNot, bit isPredNew, bit isTak, InstHexagon rootInst>
27606f32e7eSjoerg  :  InstHexagon<(outs), (ins PredRegs:$src, IntRegs:$dst),
27706f32e7eSjoerg                 CondStr<"$src", !if(PredNot,0,1), isPredNew>.S #
27806f32e7eSjoerg                 JumpOpcStr<"jumpr", isPredNew, isTak>.S # " $dst",
27906f32e7eSjoerg                 [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {
28006f32e7eSjoerg
28106f32e7eSjoerg    let isTaken = isTak;
28206f32e7eSjoerg    let isPredicatedFalse = PredNot;
28306f32e7eSjoerg    let isPredicatedNew = isPredNew;
28406f32e7eSjoerg    bits<2> src;
28506f32e7eSjoerg    bits<5> dst;
28606f32e7eSjoerg
28706f32e7eSjoerg    let IClass = 0b0101;
28806f32e7eSjoerg
28906f32e7eSjoerg    let Inst{27-22} = 0b001101;
29006f32e7eSjoerg    let Inst{21} = PredNot;
29106f32e7eSjoerg    let Inst{20-16} = dst;
29206f32e7eSjoerg    let Inst{12} = isTak;
29306f32e7eSjoerg    let Inst{11} = isPredNew;
29406f32e7eSjoerg    let Inst{9-8} = src;
29506f32e7eSjoerg}
29606f32e7eSjoerg
29706f32e7eSjoerglet isTerminator = 1, hasSideEffects = 0, isReturn = 1, isCodeGenOnly = 1,
29806f32e7eSjoerg    isBarrier = 1, BaseOpcode = "JMPret" in {
29906f32e7eSjoerg  def PS_jmpret : T_JMPr<J2_jumpr>, PredNewRel;
30006f32e7eSjoerg  def PS_jmprett : T_JMPr_c<0, 0, 0, J2_jumprt>, PredNewRel;
30106f32e7eSjoerg  def PS_jmpretf : T_JMPr_c<1, 0, 0, J2_jumprf>, PredNewRel;
30206f32e7eSjoerg  def PS_jmprettnew : T_JMPr_c<0, 1, 0, J2_jumprtnew>, PredNewRel;
30306f32e7eSjoerg  def PS_jmpretfnew : T_JMPr_c<1, 1, 0, J2_jumprfnew>, PredNewRel;
30406f32e7eSjoerg  def PS_jmprettnewpt : T_JMPr_c<0, 1, 1, J2_jumprtnewpt>, PredNewRel;
30506f32e7eSjoerg  def PS_jmpretfnewpt : T_JMPr_c<1, 1, 1, J2_jumprfnewpt>, PredNewRel;
30606f32e7eSjoerg}
30706f32e7eSjoerg
30806f32e7eSjoerg//defm V6_vtran2x2_map : HexagonMapping<(outs HvxVR:$Vy32, HvxVR:$Vx32), (ins HvxVR:$Vx32in, IntRegs:$Rt32), "vtrans2x2(${Vy32},${Vx32},${Rt32})", (V6_vshuff HvxVR:$Vy32, HvxVR:$Vx32, HvxVR:$Vx32in, IntRegs:$Rt32)>;
30906f32e7eSjoerg
31006f32e7eSjoerg// The reason for the custom inserter is to record all ALLOCA instructions
31106f32e7eSjoerg// in MachineFunctionInfo.
31206f32e7eSjoerglet Defs = [R29], hasSideEffects = 1 in
31306f32e7eSjoergdef PS_alloca: Pseudo <(outs IntRegs:$Rd),
31406f32e7eSjoerg                       (ins IntRegs:$Rs, u32_0Imm:$A), "", []>;
31506f32e7eSjoerg
31606f32e7eSjoerg// Load predicate.
31706f32e7eSjoerglet isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13,
31806f32e7eSjoerg    isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
31906f32e7eSjoergdef LDriw_pred : LDInst<(outs PredRegs:$dst),
32006f32e7eSjoerg                        (ins IntRegs:$addr, s32_0Imm:$off),
32106f32e7eSjoerg                        ".error \"should not emit\"", []>;
32206f32e7eSjoerg
32306f32e7eSjoerg// Load modifier.
32406f32e7eSjoerglet isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13,
32506f32e7eSjoerg    isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
32606f32e7eSjoergdef LDriw_ctr : LDInst<(outs CtrRegs:$dst),
32706f32e7eSjoerg                        (ins IntRegs:$addr, s32_0Imm:$off),
32806f32e7eSjoerg                        ".error \"should not emit\"", []>;
32906f32e7eSjoerg
33006f32e7eSjoerg
33106f32e7eSjoerglet isCodeGenOnly = 1, isPseudo = 1 in
33206f32e7eSjoergdef PS_pselect: InstHexagon<(outs DoubleRegs:$Rd),
33306f32e7eSjoerg      (ins PredRegs:$Pu, DoubleRegs:$Rs, DoubleRegs:$Rt),
33406f32e7eSjoerg      ".error \"should not emit\" ", [], "", A2_tfrpt.Itinerary, TypeALU32_2op>;
33506f32e7eSjoerg
33606f32e7eSjoerglet isBranch = 1, isBarrier = 1, Defs = [PC], hasSideEffects = 0,
33706f32e7eSjoerg    isPredicable = 1,
33806f32e7eSjoerg    isExtendable = 1, opExtendable = 0, isExtentSigned = 1,
33906f32e7eSjoerg    opExtentBits = 24, opExtentAlign = 2, InputType = "imm" in
34006f32e7eSjoergclass T_JMP: InstHexagon<(outs), (ins b30_2Imm:$dst),
34106f32e7eSjoerg      "jump $dst",
34206f32e7eSjoerg      [], "", J2_jump.Itinerary, TypeJ>, OpcodeHexagon {
34306f32e7eSjoerg    bits<24> dst;
34406f32e7eSjoerg    let IClass = 0b0101;
34506f32e7eSjoerg
34606f32e7eSjoerg    let Inst{27-25} = 0b100;
34706f32e7eSjoerg    let Inst{24-16} = dst{23-15};
34806f32e7eSjoerg    let Inst{13-1} = dst{14-2};
34906f32e7eSjoerg}
35006f32e7eSjoerg
35106f32e7eSjoerg// Restore registers and dealloc return function call.
35206f32e7eSjoerglet isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1,
35306f32e7eSjoerg    Defs = [R29, R30, R31, PC], isPredicable = 0, isAsmParserOnly = 1 in {
35406f32e7eSjoerg  def RESTORE_DEALLOC_RET_JMP_V4 : T_JMP;
35506f32e7eSjoerg
35606f32e7eSjoerg  let isExtended = 1, opExtendable = 0 in
35706f32e7eSjoerg  def RESTORE_DEALLOC_RET_JMP_V4_EXT : T_JMP;
35806f32e7eSjoerg
35906f32e7eSjoerg  let Defs = [R14, R15, R28, R29, R30, R31, PC] in {
36006f32e7eSjoerg    def RESTORE_DEALLOC_RET_JMP_V4_PIC : T_JMP;
36106f32e7eSjoerg
36206f32e7eSjoerg    let isExtended = 1, opExtendable = 0 in
36306f32e7eSjoerg    def RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC : T_JMP;
36406f32e7eSjoerg  }
36506f32e7eSjoerg}
36606f32e7eSjoerg
36706f32e7eSjoerg// Restore registers and dealloc frame before a tail call.
36806f32e7eSjoerglet isCall = 1, Defs = [R29, R30, R31, PC], isAsmParserOnly = 1 in {
36906f32e7eSjoerg  def RESTORE_DEALLOC_BEFORE_TAILCALL_V4 : T_Call<"">, PredRel;
37006f32e7eSjoerg
37106f32e7eSjoerg  let isExtended = 1, opExtendable = 0 in
37206f32e7eSjoerg  def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT : T_Call<"">, PredRel;
37306f32e7eSjoerg
37406f32e7eSjoerg  let Defs = [R14, R15, R28, R29, R30, R31, PC] in {
37506f32e7eSjoerg    def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC : T_Call<"">, PredRel;
37606f32e7eSjoerg
37706f32e7eSjoerg    let isExtended = 1, opExtendable = 0 in
37806f32e7eSjoerg    def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC : T_Call<"">, PredRel;
37906f32e7eSjoerg  }
38006f32e7eSjoerg}
38106f32e7eSjoerg
38206f32e7eSjoerg// Save registers function call.
38306f32e7eSjoerglet isCall = 1, Uses = [R29, R31], isAsmParserOnly = 1 in {
38406f32e7eSjoerg  def SAVE_REGISTERS_CALL_V4 : T_Call<"">, PredRel;
38506f32e7eSjoerg
38606f32e7eSjoerg  let isExtended = 1, opExtendable = 0 in
38706f32e7eSjoerg  def SAVE_REGISTERS_CALL_V4_EXT : T_Call<"">, PredRel;
38806f32e7eSjoerg
38906f32e7eSjoerg  let Defs = [P0] in
39006f32e7eSjoerg  def SAVE_REGISTERS_CALL_V4STK : T_Call<"">, PredRel;
39106f32e7eSjoerg
39206f32e7eSjoerg  let Defs = [P0], isExtended = 1, opExtendable = 0 in
39306f32e7eSjoerg  def SAVE_REGISTERS_CALL_V4STK_EXT : T_Call<"">, PredRel;
39406f32e7eSjoerg
39506f32e7eSjoerg  let Defs = [R14, R15, R28] in
39606f32e7eSjoerg  def SAVE_REGISTERS_CALL_V4_PIC : T_Call<"">, PredRel;
39706f32e7eSjoerg
39806f32e7eSjoerg  let Defs = [R14, R15, R28], isExtended = 1, opExtendable = 0 in
39906f32e7eSjoerg  def SAVE_REGISTERS_CALL_V4_EXT_PIC : T_Call<"">, PredRel;
40006f32e7eSjoerg
40106f32e7eSjoerg  let Defs = [R14, R15, R28, P0] in
40206f32e7eSjoerg  def SAVE_REGISTERS_CALL_V4STK_PIC : T_Call<"">, PredRel;
40306f32e7eSjoerg
40406f32e7eSjoerg  let Defs = [R14, R15, R28, P0], isExtended = 1, opExtendable = 0 in
40506f32e7eSjoerg  def SAVE_REGISTERS_CALL_V4STK_EXT_PIC : T_Call<"">, PredRel;
40606f32e7eSjoerg}
40706f32e7eSjoerg
40806f32e7eSjoerg// Vector store pseudos
40906f32e7eSjoerglet Predicates = [HasV60,UseHVX], isPseudo = 1, isCodeGenOnly = 1,
41006f32e7eSjoerg    mayStore = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in
411*da58b97aSjoergclass STriv_template<RegisterClass RC, InstHexagon rootInst>
41206f32e7eSjoerg  : InstHexagon<(outs), (ins IntRegs:$addr, s32_0Imm:$off, RC:$src),
41306f32e7eSjoerg    "", [], "", rootInst.Itinerary, rootInst.Type>;
41406f32e7eSjoerg
415*da58b97aSjoergdef PS_vstorerv_ai: STriv_template<HvxVR, V6_vS32b_ai>,
41606f32e7eSjoerg      Requires<[HasV60,UseHVX]>;
417*da58b97aSjoergdef PS_vstorerv_nt_ai: STriv_template<HvxVR, V6_vS32b_nt_ai>,
41806f32e7eSjoerg      Requires<[HasV60,UseHVX]>;
419*da58b97aSjoergdef PS_vstorerw_ai: STriv_template<HvxWR, V6_vS32b_ai>,
420*da58b97aSjoerg      Requires<[HasV60,UseHVX]>;
421*da58b97aSjoergdef PS_vstorerw_nt_ai: STriv_template<HvxWR, V6_vS32b_nt_ai>,
42206f32e7eSjoerg      Requires<[HasV60,UseHVX]>;
42306f32e7eSjoerg
42406f32e7eSjoerglet isPseudo = 1, isCodeGenOnly = 1, mayStore = 1, hasSideEffects = 0 in
42506f32e7eSjoergdef PS_vstorerq_ai: Pseudo<(outs),
42606f32e7eSjoerg      (ins IntRegs:$Rs, s32_0Imm:$Off, HvxQR:$Qt), "", []>,
42706f32e7eSjoerg      Requires<[HasV60,UseHVX]>;
42806f32e7eSjoerg
42906f32e7eSjoerg// Vector load pseudos
43006f32e7eSjoerglet Predicates = [HasV60, UseHVX], isPseudo = 1, isCodeGenOnly = 1,
43106f32e7eSjoerg    mayLoad = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in
432*da58b97aSjoergclass LDriv_template<RegisterClass RC, InstHexagon rootInst>
43306f32e7eSjoerg  : InstHexagon<(outs RC:$dst), (ins IntRegs:$addr, s32_0Imm:$off),
43406f32e7eSjoerg    "", [], "", rootInst.Itinerary, rootInst.Type>;
43506f32e7eSjoerg
436*da58b97aSjoergdef PS_vloadrv_ai: LDriv_template<HvxVR, V6_vL32b_ai>,
43706f32e7eSjoerg      Requires<[HasV60,UseHVX]>;
438*da58b97aSjoergdef PS_vloadrv_nt_ai: LDriv_template<HvxVR, V6_vL32b_nt_ai>,
43906f32e7eSjoerg      Requires<[HasV60,UseHVX]>;
440*da58b97aSjoergdef PS_vloadrw_ai: LDriv_template<HvxWR, V6_vL32b_ai>,
441*da58b97aSjoerg      Requires<[HasV60,UseHVX]>;
442*da58b97aSjoergdef PS_vloadrw_nt_ai: LDriv_template<HvxWR, V6_vL32b_nt_ai>,
44306f32e7eSjoerg      Requires<[HasV60,UseHVX]>;
44406f32e7eSjoerg
44506f32e7eSjoerglet isPseudo = 1, isCodeGenOnly = 1, mayLoad = 1, hasSideEffects = 0 in
44606f32e7eSjoergdef PS_vloadrq_ai: Pseudo<(outs HvxQR:$Qd),
44706f32e7eSjoerg      (ins IntRegs:$Rs, s32_0Imm:$Off), "", []>,
44806f32e7eSjoerg      Requires<[HasV60,UseHVX]>;
44906f32e7eSjoerg
45006f32e7eSjoerg
45106f32e7eSjoerglet isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
45206f32e7eSjoergclass VSELInst<dag outs, dag ins, InstHexagon rootInst>
45306f32e7eSjoerg  : InstHexagon<outs, ins, "", [], "", rootInst.Itinerary, rootInst.Type>;
45406f32e7eSjoerg
45506f32e7eSjoergdef PS_vselect: VSELInst<(outs HvxVR:$dst),
45606f32e7eSjoerg      (ins PredRegs:$src1, HvxVR:$src2, HvxVR:$src3), V6_vcmov>,
45706f32e7eSjoerg      Requires<[HasV60,UseHVX]>;
45806f32e7eSjoergdef PS_wselect: VSELInst<(outs HvxWR:$dst),
45906f32e7eSjoerg      (ins PredRegs:$src1, HvxWR:$src2, HvxWR:$src3), V6_vccombine>,
46006f32e7eSjoerg      Requires<[HasV60,UseHVX]>;
46106f32e7eSjoerg
46206f32e7eSjoerglet hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,
46306f32e7eSjoerg    isCodeGenOnly = 1 in {
46406f32e7eSjoerg  def PS_qtrue:  InstHexagon<(outs HvxQR:$Qd), (ins), "", [], "",
46506f32e7eSjoerg                 V6_veqw.Itinerary, TypeCVI_VA>;
46606f32e7eSjoerg  def PS_qfalse: InstHexagon<(outs HvxQR:$Qd), (ins), "", [], "",
46706f32e7eSjoerg                 V6_vgtw.Itinerary, TypeCVI_VA>;
46806f32e7eSjoerg  def PS_vdd0:   InstHexagon<(outs HvxWR:$Vd), (ins), "", [], "",
46906f32e7eSjoerg                 V6_vsubw_dv.Itinerary, TypeCVI_VA_DV>;
47006f32e7eSjoerg}
47106f32e7eSjoerg
47206f32e7eSjoerg// Store predicate.
47306f32e7eSjoerglet isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13,
47406f32e7eSjoerg    isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
47506f32e7eSjoergdef STriw_pred : STInst<(outs),
47606f32e7eSjoerg      (ins IntRegs:$addr, s32_0Imm:$off, PredRegs:$src1),
47706f32e7eSjoerg      ".error \"should not emit\"", []>;
47806f32e7eSjoerg// Store modifier.
47906f32e7eSjoerglet isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13,
48006f32e7eSjoerg    isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
48106f32e7eSjoergdef STriw_ctr : STInst<(outs),
48206f32e7eSjoerg      (ins IntRegs:$addr, s32_0Imm:$off, CtrRegs:$src1),
48306f32e7eSjoerg      ".error \"should not emit\"", []>;
48406f32e7eSjoerg
48506f32e7eSjoerglet isExtendable = 1, opExtendable = 1, opExtentBits = 6,
48606f32e7eSjoerg    isAsmParserOnly = 1 in
48706f32e7eSjoergdef TFRI64_V4 : InstHexagon<(outs DoubleRegs:$dst),
48806f32e7eSjoerg    (ins u64_0Imm:$src1),
48906f32e7eSjoerg    "$dst = #$src1", [], "",
49006f32e7eSjoerg    A2_combineii.Itinerary, TypeALU32_2op>, OpcodeHexagon;
49106f32e7eSjoerg
49206f32e7eSjoerg// Hexagon doesn't have a vector multiply with C semantics.
493*da58b97aSjoerg// Instead, generate a pseudo instruction that gets expanded into two
49406f32e7eSjoerg// scalar MPYI instructions.
49506f32e7eSjoerg// This is expanded by ExpandPostRAPseudos.
49606f32e7eSjoerglet isPseudo = 1 in
49706f32e7eSjoergdef PS_vmulw : PseudoM<(outs DoubleRegs:$Rd),
49806f32e7eSjoerg      (ins DoubleRegs:$Rs, DoubleRegs:$Rt), "", []>;
49906f32e7eSjoerg
50006f32e7eSjoerglet isPseudo = 1 in
50106f32e7eSjoergdef PS_vmulw_acc : PseudoM<(outs DoubleRegs:$Rd),
50206f32e7eSjoerg      (ins DoubleRegs:$Rx, DoubleRegs:$Rs, DoubleRegs:$Rt), "", [],
50306f32e7eSjoerg      "$Rd = $Rx">;
50406f32e7eSjoerg
50506f32e7eSjoergdef DuplexIClass0:  InstDuplex < 0 >;
50606f32e7eSjoergdef DuplexIClass1:  InstDuplex < 1 >;
50706f32e7eSjoergdef DuplexIClass2:  InstDuplex < 2 >;
50806f32e7eSjoerglet isExtendable = 1 in {
50906f32e7eSjoerg  def DuplexIClass3:  InstDuplex < 3 >;
51006f32e7eSjoerg  def DuplexIClass4:  InstDuplex < 4 >;
51106f32e7eSjoerg  def DuplexIClass5:  InstDuplex < 5 >;
51206f32e7eSjoerg  def DuplexIClass6:  InstDuplex < 6 >;
51306f32e7eSjoerg  def DuplexIClass7:  InstDuplex < 7 >;
51406f32e7eSjoerg}
51506f32e7eSjoergdef DuplexIClass8:  InstDuplex < 8 >;
51606f32e7eSjoergdef DuplexIClass9:  InstDuplex < 9 >;
51706f32e7eSjoergdef DuplexIClassA:  InstDuplex < 0xA >;
51806f32e7eSjoergdef DuplexIClassB:  InstDuplex < 0xB >;
51906f32e7eSjoergdef DuplexIClassC:  InstDuplex < 0xC >;
52006f32e7eSjoergdef DuplexIClassD:  InstDuplex < 0xD >;
52106f32e7eSjoergdef DuplexIClassE:  InstDuplex < 0xE >;
52206f32e7eSjoergdef DuplexIClassF:  InstDuplex < 0xF >;
52306f32e7eSjoerg
52406f32e7eSjoerg// Pseudos for circular buffer instructions. These are needed in order to
52506f32e7eSjoerg// allocate the correct pair of CSx and Mx registers.
52606f32e7eSjoergmulticlass NewCircularLoad<RegisterClass RC, MemAccessSize MS> {
52706f32e7eSjoerg
52806f32e7eSjoerglet isCodeGenOnly = 1, isPseudo = 1, Defs = [CS], Uses = [CS],
52906f32e7eSjoerg    addrMode = PostInc, accessSize = MS, hasSideEffects = 0 in {
530*da58b97aSjoerg  // Use timing class of L2_loadrb_pci.
53106f32e7eSjoerg  def NAME#_pci : LDInst<(outs RC:$Rd32, IntRegs:$Rx32),
53206f32e7eSjoerg       (ins IntRegs:$Rx32in, s4_0Imm:$Ii, ModRegs:$Mu2, IntRegs:$Cs),
533*da58b97aSjoerg       ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_5ceb2f9e>;
53406f32e7eSjoerg
535*da58b97aSjoerg  // Use timing class of L2_loadrb_pcr.
53606f32e7eSjoerg  def NAME#_pcr : LDInst<(outs RC:$Rd32, IntRegs:$Rx32),
53706f32e7eSjoerg       (ins IntRegs:$Rx32in, ModRegs:$Mu2, IntRegs:$Cs),
538*da58b97aSjoerg       ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_075c8dd8>;
53906f32e7eSjoerg}
54006f32e7eSjoerg}
54106f32e7eSjoerg
54206f32e7eSjoergdefm PS_loadrub : NewCircularLoad<IntRegs, ByteAccess>;
54306f32e7eSjoergdefm PS_loadrb : NewCircularLoad<IntRegs, ByteAccess>;
54406f32e7eSjoergdefm PS_loadruh : NewCircularLoad<IntRegs, HalfWordAccess>;
54506f32e7eSjoergdefm PS_loadrh : NewCircularLoad<IntRegs, HalfWordAccess>;
54606f32e7eSjoergdefm PS_loadri : NewCircularLoad<IntRegs, WordAccess>;
54706f32e7eSjoergdefm PS_loadrd : NewCircularLoad<DoubleRegs, DoubleWordAccess>;
54806f32e7eSjoerg
54906f32e7eSjoergmulticlass NewCircularStore<RegisterClass RC, MemAccessSize MS> {
55006f32e7eSjoerg
55106f32e7eSjoerglet isCodeGenOnly = 1, isPseudo = 1, Defs = [CS], Uses = [CS],
55206f32e7eSjoerg    addrMode = PostInc, accessSize = MS, hasSideEffects = 0 in {
553*da58b97aSjoerg  // Use timing class of S2_storerb_pci.
55406f32e7eSjoerg  def NAME#_pci : STInst<(outs IntRegs:$Rx32),
55506f32e7eSjoerg       (ins IntRegs:$Rx32in, s4_0Imm:$Ii, ModRegs:$Mu2, RC:$Rt32, IntRegs:$Cs),
556*da58b97aSjoerg       ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_b4dc7630>;
55706f32e7eSjoerg
558*da58b97aSjoerg  // Use timing class of S2_storerb_pcr.
55906f32e7eSjoerg  def NAME#_pcr : STInst<(outs IntRegs:$Rx32),
56006f32e7eSjoerg       (ins IntRegs:$Rx32in, ModRegs:$Mu2, RC:$Rt32, IntRegs:$Cs),
561*da58b97aSjoerg       ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_a2b365d2>;
56206f32e7eSjoerg}
56306f32e7eSjoerg}
56406f32e7eSjoerg
56506f32e7eSjoergdefm PS_storerb : NewCircularStore<IntRegs, ByteAccess>;
56606f32e7eSjoergdefm PS_storerh : NewCircularStore<IntRegs, HalfWordAccess>;
56706f32e7eSjoergdefm PS_storerf : NewCircularStore<IntRegs, HalfWordAccess>;
56806f32e7eSjoergdefm PS_storeri : NewCircularStore<IntRegs, WordAccess>;
56906f32e7eSjoergdefm PS_storerd : NewCircularStore<DoubleRegs, WordAccess>;
57006f32e7eSjoerg
57106f32e7eSjoerg// A pseudo that generates a runtime crash. This is used to implement
57206f32e7eSjoerg// __builtin_trap.
57306f32e7eSjoerglet hasSideEffects = 1, isPseudo = 1, isCodeGenOnly = 1, isSolo = 1 in
57406f32e7eSjoergdef PS_crash: InstHexagon<(outs), (ins), "", [], "", PSEUDO, TypePSEUDO>;
575