1//=- HexagonInstrInfoV4.td - Target Desc. for Hexagon Target -*- tablegen -*-=//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file describes the Hexagon V4 instructions in TableGen format.
11//
12//===----------------------------------------------------------------------===//
13
14def DuplexIClass0:  InstDuplex < 0 >;
15def DuplexIClass1:  InstDuplex < 1 >;
16def DuplexIClass2:  InstDuplex < 2 >;
17let isExtendable = 1 in {
18  def DuplexIClass3:  InstDuplex < 3 >;
19  def DuplexIClass4:  InstDuplex < 4 >;
20  def DuplexIClass5:  InstDuplex < 5 >;
21  def DuplexIClass6:  InstDuplex < 6 >;
22  def DuplexIClass7:  InstDuplex < 7 >;
23}
24def DuplexIClass8:  InstDuplex < 8 >;
25def DuplexIClass9:  InstDuplex < 9 >;
26def DuplexIClassA:  InstDuplex < 0xA >;
27def DuplexIClassB:  InstDuplex < 0xB >;
28def DuplexIClassC:  InstDuplex < 0xC >;
29def DuplexIClassD:  InstDuplex < 0xD >;
30def DuplexIClassE:  InstDuplex < 0xE >;
31def DuplexIClassF:  InstDuplex < 0xF >;
32
33def addrga: PatLeaf<(i32 AddrGA:$Addr)>;
34def addrgp: PatLeaf<(i32 AddrGP:$Addr)>;
35
36let hasSideEffects = 0 in
37class T_Immext<Operand ImmType>
38  : EXTENDERInst<(outs), (ins ImmType:$imm),
39                 "immext(#$imm)", []> {
40    bits<32> imm;
41    let IClass = 0b0000;
42
43    let Inst{27-16} = imm{31-20};
44    let Inst{13-0} = imm{19-6};
45  }
46
47def A4_ext : T_Immext<u26_6Imm>;
48let isCodeGenOnly = 1 in {
49  let isBranch = 1 in
50    def A4_ext_b : T_Immext<brtarget>;
51  let isCall = 1 in
52    def A4_ext_c : T_Immext<calltarget>;
53  def A4_ext_g : T_Immext<globaladdress>;
54}
55
56def BITPOS32 : SDNodeXForm<imm, [{
57   // Return the bit position we will set [0-31].
58   // As an SDNode.
59   int32_t imm = N->getSExtValue();
60   return XformMskToBitPosU5Imm(imm);
61}]>;
62
63// Hexagon V4 Architecture spec defines 8 instruction classes:
64// LD ST ALU32 XTYPE J JR MEMOP NV CR SYSTEM(system is not implemented in the
65// compiler)
66
67// LD Instructions:
68// ========================================
69// Loads (8/16/32/64 bit)
70// Deallocframe
71
72// ST Instructions:
73// ========================================
74// Stores (8/16/32/64 bit)
75// Allocframe
76
77// ALU32 Instructions:
78// ========================================
79// Arithmetic / Logical (32 bit)
80// Vector Halfword
81
82// XTYPE Instructions (32/64 bit):
83// ========================================
84// Arithmetic, Logical, Bit Manipulation
85// Multiply (Integer, Fractional, Complex)
86// Permute / Vector Permute Operations
87// Predicate Operations
88// Shift / Shift with Add/Sub/Logical
89// Vector Byte ALU
90// Vector Halfword (ALU, Shift, Multiply)
91// Vector Word (ALU, Shift)
92
93// J Instructions:
94// ========================================
95// Jump/Call PC-relative
96
97// JR Instructions:
98// ========================================
99// Jump/Call Register
100
101// MEMOP Instructions:
102// ========================================
103// Operation on memory (8/16/32 bit)
104
105// NV Instructions:
106// ========================================
107// New-value Jumps
108// New-value Stores
109
110// CR Instructions:
111// ========================================
112// Control-Register Transfers
113// Hardware Loop Setup
114// Predicate Logicals & Reductions
115
116// SYSTEM Instructions (not implemented in the compiler):
117// ========================================
118// Prefetch
119// Cache Maintenance
120// Bus Operations
121
122
123//===----------------------------------------------------------------------===//
124// ALU32 +
125//===----------------------------------------------------------------------===//
126
127class T_ALU32_3op_not<string mnemonic, bits<3> MajOp, bits<3> MinOp,
128                      bit OpsRev>
129  : T_ALU32_3op<mnemonic, MajOp, MinOp, OpsRev, 0> {
130  let AsmString = "$Rd = "#mnemonic#"($Rs, ~$Rt)";
131}
132
133let BaseOpcode = "andn_rr", CextOpcode = "andn" in
134def A4_andn    : T_ALU32_3op_not<"and", 0b001, 0b100, 1>;
135let BaseOpcode = "orn_rr", CextOpcode = "orn" in
136def A4_orn     : T_ALU32_3op_not<"or",  0b001, 0b101, 1>;
137
138let CextOpcode = "rcmp.eq" in
139def A4_rcmpeq  : T_ALU32_3op<"cmp.eq",  0b011, 0b010, 0, 1>;
140let CextOpcode = "!rcmp.eq" in
141def A4_rcmpneq : T_ALU32_3op<"!cmp.eq", 0b011, 0b011, 0, 1>;
142
143def C4_cmpneq  : T_ALU32_3op_cmp<"!cmp.eq",  0b00, 1, 1>;
144def C4_cmplte  : T_ALU32_3op_cmp<"!cmp.gt",  0b10, 1, 0>;
145def C4_cmplteu : T_ALU32_3op_cmp<"!cmp.gtu", 0b11, 1, 0>;
146
147// Pats for instruction selection.
148
149// A class to embed the usual comparison patfrags within a zext to i32.
150// The seteq/setne frags use "lhs" and "rhs" as operands, so use the same
151// names, or else the frag's "body" won't match the operands.
152class CmpInReg<PatFrag Op>
153  : PatFrag<(ops node:$lhs, node:$rhs),(i32 (zext (i1 Op.Fragment)))>;
154
155def: T_cmp32_rr_pat<A4_rcmpeq,  CmpInReg<seteq>, i32>;
156def: T_cmp32_rr_pat<A4_rcmpneq, CmpInReg<setne>, i32>;
157
158def: T_cmp32_rr_pat<C4_cmpneq,  setne,  i1>;
159def: T_cmp32_rr_pat<C4_cmplteu, setule, i1>;
160
161def: T_cmp32_rr_pat<C4_cmplteu, RevCmp<setuge>, i1>;
162
163class T_CMP_rrbh<string mnemonic, bits<3> MinOp, bit IsComm>
164  : SInst<(outs PredRegs:$Pd), (ins IntRegs:$Rs, IntRegs:$Rt),
165    "$Pd = "#mnemonic#"($Rs, $Rt)", [], "", S_3op_tc_2early_SLOT23>,
166    ImmRegRel {
167  let InputType = "reg";
168  let CextOpcode = mnemonic;
169  let isCompare = 1;
170  let isCommutable = IsComm;
171  let hasSideEffects = 0;
172
173  bits<2> Pd;
174  bits<5> Rs;
175  bits<5> Rt;
176
177  let IClass = 0b1100;
178  let Inst{27-21} = 0b0111110;
179  let Inst{20-16} = Rs;
180  let Inst{12-8} = Rt;
181  let Inst{7-5} = MinOp;
182  let Inst{1-0} = Pd;
183}
184
185def A4_cmpbeq  : T_CMP_rrbh<"cmpb.eq",  0b110, 1>;
186def A4_cmpbgt  : T_CMP_rrbh<"cmpb.gt",  0b010, 0>;
187def A4_cmpbgtu : T_CMP_rrbh<"cmpb.gtu", 0b111, 0>;
188def A4_cmpheq  : T_CMP_rrbh<"cmph.eq",  0b011, 1>;
189def A4_cmphgt  : T_CMP_rrbh<"cmph.gt",  0b100, 0>;
190def A4_cmphgtu : T_CMP_rrbh<"cmph.gtu", 0b101, 0>;
191
192let AddedComplexity = 100 in {
193  def: Pat<(i1 (seteq (and (xor (i32 IntRegs:$Rs), (i32 IntRegs:$Rt)),
194                       255), 0)),
195           (A4_cmpbeq IntRegs:$Rs, IntRegs:$Rt)>;
196  def: Pat<(i1 (setne (and (xor (i32 IntRegs:$Rs), (i32 IntRegs:$Rt)),
197                       255), 0)),
198           (C2_not (A4_cmpbeq IntRegs:$Rs, IntRegs:$Rt))>;
199  def: Pat<(i1 (seteq (and (xor (i32 IntRegs:$Rs), (i32 IntRegs:$Rt)),
200                           65535), 0)),
201           (A4_cmpheq IntRegs:$Rs, IntRegs:$Rt)>;
202  def: Pat<(i1 (setne (and (xor (i32 IntRegs:$Rs), (i32 IntRegs:$Rt)),
203                           65535), 0)),
204           (C2_not (A4_cmpheq IntRegs:$Rs, IntRegs:$Rt))>;
205}
206
207class T_CMP_ribh<string mnemonic, bits<2> MajOp, bit IsHalf, bit IsComm,
208                 Operand ImmType, bit IsImmExt, bit IsImmSigned, int ImmBits>
209  : ALU64Inst<(outs PredRegs:$Pd), (ins IntRegs:$Rs, ImmType:$Imm),
210    "$Pd = "#mnemonic#"($Rs, #$Imm)", [], "", ALU64_tc_2early_SLOT23>,
211    ImmRegRel {
212  let InputType = "imm";
213  let CextOpcode = mnemonic;
214  let isCompare = 1;
215  let isCommutable = IsComm;
216  let hasSideEffects = 0;
217  let isExtendable = IsImmExt;
218  let opExtendable = !if (IsImmExt, 2, 0);
219  let isExtentSigned = IsImmSigned;
220  let opExtentBits = ImmBits;
221
222  bits<2> Pd;
223  bits<5> Rs;
224  bits<8> Imm;
225
226  let IClass = 0b1101;
227  let Inst{27-24} = 0b1101;
228  let Inst{22-21} = MajOp;
229  let Inst{20-16} = Rs;
230  let Inst{12-5} = Imm;
231  let Inst{4} = 0b0;
232  let Inst{3} = IsHalf;
233  let Inst{1-0} = Pd;
234}
235
236def A4_cmpbeqi  : T_CMP_ribh<"cmpb.eq",  0b00, 0, 1, u8Imm, 0, 0, 8>;
237def A4_cmpbgti  : T_CMP_ribh<"cmpb.gt",  0b01, 0, 0, s8Imm, 0, 1, 8>;
238def A4_cmpbgtui : T_CMP_ribh<"cmpb.gtu", 0b10, 0, 0, u7Ext, 1, 0, 7>;
239def A4_cmpheqi  : T_CMP_ribh<"cmph.eq",  0b00, 1, 1, s8Ext, 1, 1, 8>;
240def A4_cmphgti  : T_CMP_ribh<"cmph.gt",  0b01, 1, 0, s8Ext, 1, 1, 8>;
241def A4_cmphgtui : T_CMP_ribh<"cmph.gtu", 0b10, 1, 0, u7Ext, 1, 0, 7>;
242
243class T_RCMP_EQ_ri<string mnemonic, bit IsNeg>
244  : ALU32_ri<(outs IntRegs:$Rd), (ins IntRegs:$Rs, s8Ext:$s8),
245    "$Rd = "#mnemonic#"($Rs, #$s8)", [], "", ALU32_2op_tc_1_SLOT0123>,
246    ImmRegRel {
247  let InputType = "imm";
248  let CextOpcode = !if (IsNeg, "!rcmp.eq", "rcmp.eq");
249  let isExtendable = 1;
250  let opExtendable = 2;
251  let isExtentSigned = 1;
252  let opExtentBits = 8;
253  let hasNewValue = 1;
254
255  bits<5> Rd;
256  bits<5> Rs;
257  bits<8> s8;
258
259  let IClass = 0b0111;
260  let Inst{27-24} = 0b0011;
261  let Inst{22} = 0b1;
262  let Inst{21} = IsNeg;
263  let Inst{20-16} = Rs;
264  let Inst{13} = 0b1;
265  let Inst{12-5} = s8;
266  let Inst{4-0} = Rd;
267}
268
269def A4_rcmpeqi  : T_RCMP_EQ_ri<"cmp.eq",  0>;
270def A4_rcmpneqi : T_RCMP_EQ_ri<"!cmp.eq", 1>;
271
272def: Pat<(i32 (zext (i1 (seteq (i32 IntRegs:$Rs), s32ImmPred:$s8)))),
273         (A4_rcmpeqi IntRegs:$Rs, s32ImmPred:$s8)>;
274def: Pat<(i32 (zext (i1 (setne (i32 IntRegs:$Rs), s32ImmPred:$s8)))),
275         (A4_rcmpneqi IntRegs:$Rs, s32ImmPred:$s8)>;
276
277// Preserve the S2_tstbit_r generation
278def: Pat<(i32 (zext (i1 (setne (i32 (and (i32 (shl 1, (i32 IntRegs:$src2))),
279                                         (i32 IntRegs:$src1))), 0)))),
280         (C2_muxii (S2_tstbit_r IntRegs:$src1, IntRegs:$src2), 1, 0)>;
281
282//===----------------------------------------------------------------------===//
283// ALU32 -
284//===----------------------------------------------------------------------===//
285
286
287//===----------------------------------------------------------------------===//
288// ALU32/PERM +
289//===----------------------------------------------------------------------===//
290
291// Combine a word and an immediate into a register pair.
292let hasSideEffects = 0, isExtentSigned = 1, isExtendable = 1,
293    opExtentBits = 8 in
294class T_Combine1 <bits<2> MajOp, dag ins, string AsmStr>
295  : ALU32Inst <(outs DoubleRegs:$Rdd), ins, AsmStr> {
296    bits<5> Rdd;
297    bits<5> Rs;
298    bits<8> s8;
299
300    let IClass      = 0b0111;
301    let Inst{27-24} = 0b0011;
302    let Inst{22-21} = MajOp;
303    let Inst{20-16} = Rs;
304    let Inst{13}    = 0b1;
305    let Inst{12-5}  = s8;
306    let Inst{4-0}   = Rdd;
307  }
308
309let opExtendable = 2 in
310def A4_combineri : T_Combine1<0b00, (ins IntRegs:$Rs, s8Ext:$s8),
311                                    "$Rdd = combine($Rs, #$s8)">;
312
313let opExtendable = 1 in
314def A4_combineir : T_Combine1<0b01, (ins s8Ext:$s8, IntRegs:$Rs),
315                                    "$Rdd = combine(#$s8, $Rs)">;
316
317// The complexity of the combines involving immediates should be greater
318// than the complexity of the combine with two registers.
319let AddedComplexity = 50 in {
320def: Pat<(HexagonCOMBINE IntRegs:$r, s32ImmPred:$i),
321         (A4_combineri IntRegs:$r, s32ImmPred:$i)>;
322
323def: Pat<(HexagonCOMBINE s32ImmPred:$i, IntRegs:$r),
324         (A4_combineir s32ImmPred:$i, IntRegs:$r)>;
325}
326
327// A4_combineii: Set two small immediates.
328let hasSideEffects = 0, isExtendable = 1, opExtentBits = 6, opExtendable = 2 in
329def A4_combineii: ALU32Inst<(outs DoubleRegs:$Rdd), (ins s8Imm:$s8, u6Ext:$U6),
330  "$Rdd = combine(#$s8, #$U6)"> {
331    bits<5> Rdd;
332    bits<8> s8;
333    bits<6> U6;
334
335    let IClass = 0b0111;
336    let Inst{27-23} = 0b11001;
337    let Inst{20-16} = U6{5-1};
338    let Inst{13}    = U6{0};
339    let Inst{12-5}  = s8;
340    let Inst{4-0}   = Rdd;
341  }
342
343// The complexity of the combine with two immediates should be greater than
344// the complexity of a combine involving a register.
345let AddedComplexity = 75 in
346def: Pat<(HexagonCOMBINE s8ImmPred:$s8, u32ImmPred:$u6),
347         (A4_combineii imm:$s8, imm:$u6)>;
348
349//===----------------------------------------------------------------------===//
350// ALU32/PERM -
351//===----------------------------------------------------------------------===//
352
353//===----------------------------------------------------------------------===//
354// LD +
355//===----------------------------------------------------------------------===//
356
357def Zext64: OutPatFrag<(ops node:$Rs),
358  (i64 (A4_combineir 0, (i32 $Rs)))>;
359def Sext64: OutPatFrag<(ops node:$Rs),
360  (i64 (A2_sxtw (i32 $Rs)))>;
361
362// Patterns to generate indexed loads with different forms of the address:
363// - frameindex,
364// - base + offset,
365// - base (without offset).
366multiclass Loadxm_pat<PatFrag Load, ValueType VT, PatFrag ValueMod,
367                      PatLeaf ImmPred, InstHexagon MI> {
368  def: Pat<(VT (Load AddrFI:$fi)),
369           (VT (ValueMod (MI AddrFI:$fi, 0)))>;
370  def: Pat<(VT (Load (add AddrFI:$fi, ImmPred:$Off))),
371           (VT (ValueMod (MI AddrFI:$fi, imm:$Off)))>;
372  def: Pat<(VT (Load (add IntRegs:$Rs, ImmPred:$Off))),
373           (VT (ValueMod (MI IntRegs:$Rs, imm:$Off)))>;
374  def: Pat<(VT (Load (i32 IntRegs:$Rs))),
375           (VT (ValueMod (MI IntRegs:$Rs, 0)))>;
376}
377
378defm: Loadxm_pat<extloadi1,   i64, Zext64, s32_0ImmPred, L2_loadrub_io>;
379defm: Loadxm_pat<extloadi8,   i64, Zext64, s32_0ImmPred, L2_loadrub_io>;
380defm: Loadxm_pat<extloadi16,  i64, Zext64, s31_1ImmPred, L2_loadruh_io>;
381defm: Loadxm_pat<zextloadi1,  i64, Zext64, s32_0ImmPred, L2_loadrub_io>;
382defm: Loadxm_pat<zextloadi8,  i64, Zext64, s32_0ImmPred, L2_loadrub_io>;
383defm: Loadxm_pat<zextloadi16, i64, Zext64, s31_1ImmPred, L2_loadruh_io>;
384defm: Loadxm_pat<sextloadi8,  i64, Sext64, s32_0ImmPred, L2_loadrb_io>;
385defm: Loadxm_pat<sextloadi16, i64, Sext64, s31_1ImmPred, L2_loadrh_io>;
386
387// Map Rdd = anyext(Rs) -> Rdd = combine(#0, Rs).
388def: Pat<(i64 (anyext (i32 IntRegs:$src1))), (Zext64 IntRegs:$src1)>;
389
390//===----------------------------------------------------------------------===//
391// Template class for load instructions with Absolute set addressing mode.
392//===----------------------------------------------------------------------===//
393let isExtended = 1, opExtendable = 2, opExtentBits = 6, addrMode = AbsoluteSet,
394    hasSideEffects = 0 in
395class T_LD_abs_set<string mnemonic, RegisterClass RC, bits<4>MajOp>:
396            LDInst<(outs RC:$dst1, IntRegs:$dst2),
397            (ins u6Ext:$addr),
398            "$dst1 = "#mnemonic#"($dst2 = #$addr)",
399            []> {
400  bits<7> name;
401  bits<5> dst1;
402  bits<5> dst2;
403  bits<6> addr;
404
405  let IClass = 0b1001;
406  let Inst{27-25} = 0b101;
407  let Inst{24-21} = MajOp;
408  let Inst{13-12} = 0b01;
409  let Inst{4-0}   = dst1;
410  let Inst{20-16} = dst2;
411  let Inst{11-8}  = addr{5-2};
412  let Inst{6-5}   = addr{1-0};
413}
414
415let accessSize = ByteAccess, hasNewValue = 1 in {
416  def L4_loadrb_ap   : T_LD_abs_set <"memb",   IntRegs, 0b1000>;
417  def L4_loadrub_ap  : T_LD_abs_set <"memub",  IntRegs, 0b1001>;
418}
419
420let accessSize = HalfWordAccess, hasNewValue = 1 in {
421  def L4_loadrh_ap  : T_LD_abs_set <"memh",  IntRegs, 0b1010>;
422  def L4_loadruh_ap : T_LD_abs_set <"memuh", IntRegs, 0b1011>;
423  def L4_loadbsw2_ap : T_LD_abs_set <"membh",  IntRegs, 0b0001>;
424  def L4_loadbzw2_ap : T_LD_abs_set <"memubh", IntRegs, 0b0011>;
425}
426
427let accessSize = WordAccess, hasNewValue = 1 in
428  def L4_loadri_ap : T_LD_abs_set <"memw", IntRegs, 0b1100>;
429
430let accessSize = WordAccess in {
431  def L4_loadbzw4_ap : T_LD_abs_set <"memubh", DoubleRegs, 0b0101>;
432  def L4_loadbsw4_ap : T_LD_abs_set <"membh",  DoubleRegs, 0b0111>;
433}
434
435let accessSize = DoubleWordAccess in
436def L4_loadrd_ap : T_LD_abs_set <"memd", DoubleRegs, 0b1110>;
437
438let accessSize = ByteAccess in
439  def L4_loadalignb_ap : T_LD_abs_set <"memb_fifo", DoubleRegs, 0b0100>;
440
441let accessSize = HalfWordAccess in
442def L4_loadalignh_ap : T_LD_abs_set <"memh_fifo", DoubleRegs, 0b0010>;
443
444// Load - Indirect with long offset
445let InputType = "imm", addrMode = BaseLongOffset, isExtended = 1,
446opExtentBits = 6, opExtendable = 3 in
447class T_LoadAbsReg <string mnemonic, string CextOp, RegisterClass RC,
448                    bits<4> MajOp>
449  : LDInst <(outs RC:$dst), (ins IntRegs:$src1, u2Imm:$src2, u6Ext:$src3),
450  "$dst = "#mnemonic#"($src1<<#$src2 + #$src3)",
451  [] >, ImmRegShl {
452    bits<5> dst;
453    bits<5> src1;
454    bits<2> src2;
455    bits<6> src3;
456    let CextOpcode = CextOp;
457    let hasNewValue = !if (!eq(!cast<string>(RC), "DoubleRegs"), 0, 1);
458
459    let IClass = 0b1001;
460    let Inst{27-25} = 0b110;
461    let Inst{24-21} = MajOp;
462    let Inst{20-16} = src1;
463    let Inst{13}    = src2{1};
464    let Inst{12}    = 0b1;
465    let Inst{11-8}  = src3{5-2};
466    let Inst{7}     = src2{0};
467    let Inst{6-5}   = src3{1-0};
468    let Inst{4-0}   = dst;
469  }
470
471let accessSize = ByteAccess in {
472  def L4_loadrb_ur  : T_LoadAbsReg<"memb",  "LDrib", IntRegs, 0b1000>;
473  def L4_loadrub_ur : T_LoadAbsReg<"memub", "LDriub", IntRegs, 0b1001>;
474  def L4_loadalignb_ur : T_LoadAbsReg<"memb_fifo", "LDrib_fifo",
475                                      DoubleRegs, 0b0100>;
476}
477
478let accessSize = HalfWordAccess in {
479  def L4_loadrh_ur   : T_LoadAbsReg<"memh",   "LDrih",    IntRegs, 0b1010>;
480  def L4_loadruh_ur  : T_LoadAbsReg<"memuh",  "LDriuh",   IntRegs, 0b1011>;
481  def L4_loadbsw2_ur : T_LoadAbsReg<"membh",  "LDribh2",  IntRegs, 0b0001>;
482  def L4_loadbzw2_ur : T_LoadAbsReg<"memubh", "LDriubh2", IntRegs, 0b0011>;
483  def L4_loadalignh_ur : T_LoadAbsReg<"memh_fifo", "LDrih_fifo",
484                                      DoubleRegs, 0b0010>;
485}
486
487let accessSize = WordAccess in {
488  def L4_loadri_ur   : T_LoadAbsReg<"memw", "LDriw", IntRegs, 0b1100>;
489  def L4_loadbsw4_ur : T_LoadAbsReg<"membh", "LDribh4", DoubleRegs, 0b0111>;
490  def L4_loadbzw4_ur : T_LoadAbsReg<"memubh", "LDriubh4", DoubleRegs, 0b0101>;
491}
492
493let accessSize = DoubleWordAccess in
494def L4_loadrd_ur  : T_LoadAbsReg<"memd", "LDrid", DoubleRegs, 0b1110>;
495
496
497multiclass T_LoadAbsReg_Pat <PatFrag ldOp, InstHexagon MI, ValueType VT = i32> {
498  def  : Pat <(VT (ldOp (add (shl IntRegs:$src1, u2ImmPred:$src2),
499                             (HexagonCONST32 tglobaladdr:$src3)))),
500              (MI IntRegs:$src1, u2ImmPred:$src2, tglobaladdr:$src3)>;
501
502  def  : Pat <(VT (ldOp (add IntRegs:$src1,
503                             (HexagonCONST32 tglobaladdr:$src2)))),
504              (MI IntRegs:$src1, 0, tglobaladdr:$src2)>;
505}
506
507let AddedComplexity  = 60 in {
508defm : T_LoadAbsReg_Pat <sextloadi8, L4_loadrb_ur>;
509defm : T_LoadAbsReg_Pat <zextloadi8, L4_loadrub_ur>;
510defm : T_LoadAbsReg_Pat <extloadi8,  L4_loadrub_ur>;
511
512defm : T_LoadAbsReg_Pat <sextloadi16, L4_loadrh_ur>;
513defm : T_LoadAbsReg_Pat <zextloadi16, L4_loadruh_ur>;
514defm : T_LoadAbsReg_Pat <extloadi16,  L4_loadruh_ur>;
515
516defm : T_LoadAbsReg_Pat <load, L4_loadri_ur>;
517defm : T_LoadAbsReg_Pat <load, L4_loadrd_ur, i64>;
518}
519
520//===----------------------------------------------------------------------===//
521// Template classes for the non-predicated load instructions with
522// base + register offset addressing mode
523//===----------------------------------------------------------------------===//
524class T_load_rr <string mnemonic, RegisterClass RC, bits<3> MajOp>:
525   LDInst<(outs RC:$dst), (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$u2),
526  "$dst = "#mnemonic#"($src1 + $src2<<#$u2)",
527  [], "", V4LDST_tc_ld_SLOT01>, ImmRegShl, AddrModeRel {
528    bits<5> dst;
529    bits<5> src1;
530    bits<5> src2;
531    bits<2> u2;
532
533    let IClass = 0b0011;
534
535    let Inst{27-24} = 0b1010;
536    let Inst{23-21} = MajOp;
537    let Inst{20-16} = src1;
538    let Inst{12-8}  = src2;
539    let Inst{13}    = u2{1};
540    let Inst{7}     = u2{0};
541    let Inst{4-0}   = dst;
542  }
543
544//===----------------------------------------------------------------------===//
545// Template classes for the predicated load instructions with
546// base + register offset addressing mode
547//===----------------------------------------------------------------------===//
548let isPredicated =  1 in
549class T_pload_rr <string mnemonic, RegisterClass RC, bits<3> MajOp,
550                  bit isNot, bit isPredNew>:
551   LDInst <(outs RC:$dst),
552           (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$u2),
553  !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
554  ") ")#"$dst = "#mnemonic#"($src2+$src3<<#$u2)",
555  [], "", V4LDST_tc_ld_SLOT01>, AddrModeRel {
556    bits<5> dst;
557    bits<2> src1;
558    bits<5> src2;
559    bits<5> src3;
560    bits<2> u2;
561
562    let isPredicatedFalse = isNot;
563    let isPredicatedNew = isPredNew;
564
565    let IClass = 0b0011;
566
567    let Inst{27-26} = 0b00;
568    let Inst{25}    = isPredNew;
569    let Inst{24}    = isNot;
570    let Inst{23-21} = MajOp;
571    let Inst{20-16} = src2;
572    let Inst{12-8}  = src3;
573    let Inst{13}    = u2{1};
574    let Inst{7}     = u2{0};
575    let Inst{6-5}   = src1;
576    let Inst{4-0}   = dst;
577  }
578
579//===----------------------------------------------------------------------===//
580// multiclass for load instructions with base + register offset
581// addressing mode
582//===----------------------------------------------------------------------===//
583let hasSideEffects = 0, addrMode = BaseRegOffset in
584multiclass ld_idxd_shl <string mnemonic, string CextOp, RegisterClass RC,
585                        bits<3> MajOp > {
586  let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed_shl,
587      InputType = "reg" in {
588    let isPredicable = 1 in
589    def L4_#NAME#_rr : T_load_rr <mnemonic, RC, MajOp>;
590
591    // Predicated
592    def L4_p#NAME#t_rr : T_pload_rr <mnemonic, RC, MajOp, 0, 0>;
593    def L4_p#NAME#f_rr : T_pload_rr <mnemonic, RC, MajOp, 1, 0>;
594
595    // Predicated new
596    def L4_p#NAME#tnew_rr : T_pload_rr <mnemonic, RC, MajOp, 0, 1>;
597    def L4_p#NAME#fnew_rr : T_pload_rr <mnemonic, RC, MajOp, 1, 1>;
598  }
599}
600
601let hasNewValue = 1, accessSize = ByteAccess in {
602  defm loadrb  : ld_idxd_shl<"memb", "LDrib", IntRegs, 0b000>;
603  defm loadrub : ld_idxd_shl<"memub", "LDriub", IntRegs, 0b001>;
604}
605
606let hasNewValue = 1, accessSize = HalfWordAccess in {
607  defm loadrh  : ld_idxd_shl<"memh", "LDrih", IntRegs, 0b010>;
608  defm loadruh : ld_idxd_shl<"memuh", "LDriuh", IntRegs, 0b011>;
609}
610
611let hasNewValue = 1, accessSize = WordAccess in
612defm loadri : ld_idxd_shl<"memw", "LDriw", IntRegs, 0b100>;
613
614let accessSize = DoubleWordAccess in
615defm loadrd  : ld_idxd_shl<"memd", "LDrid", DoubleRegs, 0b110>;
616
617// 'def pats' for load instructions with base + register offset and non-zero
618// immediate value. Immediate value is used to left-shift the second
619// register operand.
620class Loadxs_pat<PatFrag Load, ValueType VT, InstHexagon MI>
621  : Pat<(VT (Load (add (i32 IntRegs:$Rs),
622                       (i32 (shl (i32 IntRegs:$Rt), u2ImmPred:$u2))))),
623        (VT (MI IntRegs:$Rs, IntRegs:$Rt, imm:$u2))>;
624
625let AddedComplexity = 40 in {
626  def: Loadxs_pat<extloadi8,   i32, L4_loadrub_rr>;
627  def: Loadxs_pat<zextloadi8,  i32, L4_loadrub_rr>;
628  def: Loadxs_pat<sextloadi8,  i32, L4_loadrb_rr>;
629  def: Loadxs_pat<extloadi16,  i32, L4_loadruh_rr>;
630  def: Loadxs_pat<zextloadi16, i32, L4_loadruh_rr>;
631  def: Loadxs_pat<sextloadi16, i32, L4_loadrh_rr>;
632  def: Loadxs_pat<load,        i32, L4_loadri_rr>;
633  def: Loadxs_pat<load,        i64, L4_loadrd_rr>;
634}
635
636// 'def pats' for load instruction base + register offset and
637// zero immediate value.
638class Loadxs_simple_pat<PatFrag Load, ValueType VT, InstHexagon MI>
639  : Pat<(VT (Load (add (i32 IntRegs:$Rs), (i32 IntRegs:$Rt)))),
640        (VT (MI IntRegs:$Rs, IntRegs:$Rt, 0))>;
641
642let AddedComplexity = 20 in {
643  def: Loadxs_simple_pat<extloadi8,   i32, L4_loadrub_rr>;
644  def: Loadxs_simple_pat<zextloadi8,  i32, L4_loadrub_rr>;
645  def: Loadxs_simple_pat<sextloadi8,  i32, L4_loadrb_rr>;
646  def: Loadxs_simple_pat<extloadi16,  i32, L4_loadruh_rr>;
647  def: Loadxs_simple_pat<zextloadi16, i32, L4_loadruh_rr>;
648  def: Loadxs_simple_pat<sextloadi16, i32, L4_loadrh_rr>;
649  def: Loadxs_simple_pat<load,        i32, L4_loadri_rr>;
650  def: Loadxs_simple_pat<load,        i64, L4_loadrd_rr>;
651}
652
653// zext i1->i64
654def: Pat<(i64 (zext (i1 PredRegs:$src1))),
655         (Zext64 (C2_muxii PredRegs:$src1, 1, 0))>;
656
657// zext i32->i64
658def: Pat<(i64 (zext (i32 IntRegs:$src1))),
659         (Zext64 IntRegs:$src1)>;
660
661//===----------------------------------------------------------------------===//
662// LD -
663//===----------------------------------------------------------------------===//
664
665//===----------------------------------------------------------------------===//
666// ST +
667//===----------------------------------------------------------------------===//
668///
669//===----------------------------------------------------------------------===//
670// Template class for store instructions with Absolute set addressing mode.
671//===----------------------------------------------------------------------===//
672let isExtended = 1, opExtendable = 1, opExtentBits = 6,
673    addrMode = AbsoluteSet, isNVStorable = 1 in
674class T_ST_absset <string mnemonic, string BaseOp, RegisterClass RC,
675                   bits<3> MajOp, MemAccessSize AccessSz, bit isHalf = 0>
676  : STInst<(outs IntRegs:$dst),
677           (ins u6Ext:$addr, RC:$src),
678    mnemonic#"($dst = #$addr) = $src"#!if(isHalf, ".h","")>, NewValueRel {
679    bits<5> dst;
680    bits<6> addr;
681    bits<5> src;
682    let accessSize = AccessSz;
683    let BaseOpcode = BaseOp#"_AbsSet";
684
685    let IClass = 0b1010;
686
687    let Inst{27-24} = 0b1011;
688    let Inst{23-21} = MajOp;
689    let Inst{20-16} = dst;
690    let Inst{13}    = 0b0;
691    let Inst{12-8}  = src;
692    let Inst{7}     = 0b1;
693    let Inst{5-0}   = addr;
694  }
695
696def S4_storerb_ap : T_ST_absset <"memb", "STrib", IntRegs, 0b000, ByteAccess>;
697def S4_storerh_ap : T_ST_absset <"memh", "STrih", IntRegs, 0b010,
698                                 HalfWordAccess>;
699def S4_storeri_ap : T_ST_absset <"memw", "STriw", IntRegs, 0b100, WordAccess>;
700
701let isNVStorable = 0 in {
702  def S4_storerf_ap : T_ST_absset <"memh", "STrif", IntRegs,
703                                   0b011, HalfWordAccess, 1>;
704  def S4_storerd_ap : T_ST_absset <"memd", "STrid", DoubleRegs,
705                                   0b110, DoubleWordAccess>;
706}
707
708let opExtendable = 1, isNewValue = 1, isNVStore = 1, opNewValue = 2,
709isExtended = 1, opExtentBits= 6 in
710class T_ST_absset_nv <string mnemonic, string BaseOp, bits<2> MajOp,
711                      MemAccessSize AccessSz >
712  : NVInst <(outs IntRegs:$dst),
713            (ins u6Ext:$addr, IntRegs:$src),
714    mnemonic#"($dst = #$addr) = $src.new">, NewValueRel {
715    bits<5> dst;
716    bits<6> addr;
717    bits<3> src;
718    let accessSize = AccessSz;
719    let BaseOpcode = BaseOp#"_AbsSet";
720
721    let IClass = 0b1010;
722
723    let Inst{27-21} = 0b1011101;
724    let Inst{20-16} = dst;
725    let Inst{13-11} = 0b000;
726    let Inst{12-11} = MajOp;
727    let Inst{10-8}  = src;
728    let Inst{7}     = 0b1;
729    let Inst{5-0}   = addr;
730  }
731
732let mayStore = 1, addrMode = AbsoluteSet in {
733  def S4_storerbnew_ap : T_ST_absset_nv <"memb", "STrib", 0b00, ByteAccess>;
734  def S4_storerhnew_ap : T_ST_absset_nv <"memh", "STrih", 0b01, HalfWordAccess>;
735  def S4_storerinew_ap : T_ST_absset_nv <"memw", "STriw", 0b10, WordAccess>;
736}
737
738let isExtended = 1, opExtendable = 2, opExtentBits = 6, InputType = "imm",
739addrMode = BaseLongOffset, AddedComplexity = 40 in
740class T_StoreAbsReg <string mnemonic, string CextOp, RegisterClass RC,
741                     bits<3> MajOp, MemAccessSize AccessSz, bit isHalf = 0>
742  : STInst<(outs),
743           (ins IntRegs:$src1, u2Imm:$src2, u6Ext:$src3, RC:$src4),
744   mnemonic#"($src1<<#$src2 + #$src3) = $src4"#!if(isHalf, ".h",""),
745   []>, ImmRegShl, NewValueRel {
746
747    bits<5> src1;
748    bits<2> src2;
749    bits<6> src3;
750    bits<5> src4;
751
752    let accessSize = AccessSz;
753    let CextOpcode = CextOp;
754    let BaseOpcode = CextOp#"_shl";
755    let IClass = 0b1010;
756
757    let Inst{27-24} =0b1101;
758    let Inst{23-21} = MajOp;
759    let Inst{20-16} = src1;
760    let Inst{13}    = src2{1};
761    let Inst{12-8}  = src4;
762    let Inst{7}     = 0b1;
763    let Inst{6}     = src2{0};
764    let Inst{5-0}   = src3;
765}
766
767def S4_storerb_ur : T_StoreAbsReg <"memb", "STrib", IntRegs, 0b000, ByteAccess>;
768def S4_storerh_ur : T_StoreAbsReg <"memh", "STrih", IntRegs, 0b010,
769                                   HalfWordAccess>;
770def S4_storerf_ur : T_StoreAbsReg <"memh", "STrif", IntRegs, 0b011,
771                                   HalfWordAccess, 1>;
772def S4_storeri_ur : T_StoreAbsReg <"memw", "STriw", IntRegs, 0b100, WordAccess>;
773def S4_storerd_ur : T_StoreAbsReg <"memd", "STrid", DoubleRegs, 0b110,
774                                   DoubleWordAccess>;
775
776let AddedComplexity = 40 in
777multiclass T_StoreAbsReg_Pats <InstHexagon MI, RegisterClass RC, ValueType VT,
778                           PatFrag stOp> {
779 def : Pat<(stOp (VT RC:$src4),
780                 (add (shl (i32 IntRegs:$src1), u2ImmPred:$src2),
781                      u32ImmPred:$src3)),
782          (MI IntRegs:$src1, u2ImmPred:$src2, u32ImmPred:$src3, RC:$src4)>;
783
784 def : Pat<(stOp (VT RC:$src4),
785                 (add (shl IntRegs:$src1, u2ImmPred:$src2),
786                      (HexagonCONST32 tglobaladdr:$src3))),
787           (MI IntRegs:$src1, u2ImmPred:$src2, tglobaladdr:$src3, RC:$src4)>;
788
789 def : Pat<(stOp (VT RC:$src4),
790                 (add IntRegs:$src1, (HexagonCONST32 tglobaladdr:$src3))),
791           (MI IntRegs:$src1, 0, tglobaladdr:$src3, RC:$src4)>;
792}
793
794defm : T_StoreAbsReg_Pats <S4_storerd_ur, DoubleRegs, i64, store>;
795defm : T_StoreAbsReg_Pats <S4_storeri_ur, IntRegs, i32, store>;
796defm : T_StoreAbsReg_Pats <S4_storerb_ur, IntRegs, i32, truncstorei8>;
797defm : T_StoreAbsReg_Pats <S4_storerh_ur, IntRegs, i32, truncstorei16>;
798
799let mayStore = 1, isNVStore = 1, isExtended = 1, addrMode = BaseLongOffset,
800    opExtentBits = 6, isNewValue = 1, opNewValue = 3, opExtendable = 2 in
801class T_StoreAbsRegNV <string mnemonic, string CextOp, bits<2> MajOp,
802                       MemAccessSize AccessSz>
803  : NVInst <(outs ),
804            (ins IntRegs:$src1, u2Imm:$src2, u6Ext:$src3, IntRegs:$src4),
805  mnemonic#"($src1<<#$src2 + #$src3) = $src4.new">, NewValueRel {
806    bits<5> src1;
807    bits<2> src2;
808    bits<6> src3;
809    bits<3> src4;
810
811    let CextOpcode  = CextOp;
812    let BaseOpcode  = CextOp#"_shl";
813    let IClass      = 0b1010;
814
815    let Inst{27-21} = 0b1101101;
816    let Inst{12-11} = 0b00;
817    let Inst{7}     = 0b1;
818    let Inst{20-16} = src1;
819    let Inst{13}    = src2{1};
820    let Inst{12-11} = MajOp;
821    let Inst{10-8}  = src4;
822    let Inst{6}     = src2{0};
823    let Inst{5-0}   = src3;
824  }
825
826def S4_storerbnew_ur : T_StoreAbsRegNV <"memb", "STrib", 0b00, ByteAccess>;
827def S4_storerhnew_ur : T_StoreAbsRegNV <"memh", "STrih", 0b01, HalfWordAccess>;
828def S4_storerinew_ur : T_StoreAbsRegNV <"memw", "STriw", 0b10, WordAccess>;
829
830//===----------------------------------------------------------------------===//
831// Template classes for the non-predicated store instructions with
832// base + register offset addressing mode
833//===----------------------------------------------------------------------===//
834let isPredicable = 1 in
835class T_store_rr <string mnemonic, RegisterClass RC, bits<3> MajOp, bit isH>
836  : STInst < (outs ), (ins IntRegs:$Rs, IntRegs:$Ru, u2Imm:$u2, RC:$Rt),
837  mnemonic#"($Rs + $Ru<<#$u2) = $Rt"#!if(isH, ".h",""),
838  [],"",V4LDST_tc_st_SLOT01>, ImmRegShl, AddrModeRel {
839
840    bits<5> Rs;
841    bits<5> Ru;
842    bits<2> u2;
843    bits<5> Rt;
844
845    let IClass = 0b0011;
846
847    let Inst{27-24} = 0b1011;
848    let Inst{23-21} = MajOp;
849    let Inst{20-16} = Rs;
850    let Inst{12-8}  = Ru;
851    let Inst{13}    = u2{1};
852    let Inst{7}     = u2{0};
853    let Inst{4-0}   = Rt;
854  }
855
856//===----------------------------------------------------------------------===//
857// Template classes for the predicated store instructions with
858// base + register offset addressing mode
859//===----------------------------------------------------------------------===//
860let isPredicated = 1 in
861class T_pstore_rr <string mnemonic, RegisterClass RC, bits<3> MajOp,
862                   bit isNot, bit isPredNew, bit isH>
863  : STInst <(outs),
864            (ins PredRegs:$Pv, IntRegs:$Rs, IntRegs:$Ru, u2Imm:$u2, RC:$Rt),
865
866  !if(isNot, "if (!$Pv", "if ($Pv")#!if(isPredNew, ".new) ",
867  ") ")#mnemonic#"($Rs+$Ru<<#$u2) = $Rt"#!if(isH, ".h",""),
868  [], "", V4LDST_tc_st_SLOT01> , AddrModeRel{
869    bits<2> Pv;
870    bits<5> Rs;
871    bits<5> Ru;
872    bits<2> u2;
873    bits<5> Rt;
874
875    let isPredicatedFalse = isNot;
876    let isPredicatedNew = isPredNew;
877
878    let IClass = 0b0011;
879
880    let Inst{27-26} = 0b01;
881    let Inst{25}    = isPredNew;
882    let Inst{24}    = isNot;
883    let Inst{23-21} = MajOp;
884    let Inst{20-16} = Rs;
885    let Inst{12-8}  = Ru;
886    let Inst{13}    = u2{1};
887    let Inst{7}     = u2{0};
888    let Inst{6-5}   = Pv;
889    let Inst{4-0}   = Rt;
890  }
891
892//===----------------------------------------------------------------------===//
893// Template classes for the new-value store instructions with
894// base + register offset addressing mode
895//===----------------------------------------------------------------------===//
896let isPredicable = 1, isNewValue = 1, opNewValue = 3 in
897class T_store_new_rr <string mnemonic, bits<2> MajOp> :
898  NVInst < (outs ), (ins IntRegs:$Rs, IntRegs:$Ru, u2Imm:$u2, IntRegs:$Nt),
899  mnemonic#"($Rs + $Ru<<#$u2) = $Nt.new",
900  [],"",V4LDST_tc_st_SLOT0>, ImmRegShl, AddrModeRel {
901
902    bits<5> Rs;
903    bits<5> Ru;
904    bits<2> u2;
905    bits<3> Nt;
906
907    let IClass = 0b0011;
908
909    let Inst{27-21} = 0b1011101;
910    let Inst{20-16} = Rs;
911    let Inst{12-8}  = Ru;
912    let Inst{13}    = u2{1};
913    let Inst{7}     = u2{0};
914    let Inst{4-3}   = MajOp;
915    let Inst{2-0}   = Nt;
916  }
917
918//===----------------------------------------------------------------------===//
919// Template classes for the predicated new-value store instructions with
920// base + register offset addressing mode
921//===----------------------------------------------------------------------===//
922let isPredicated = 1, isNewValue = 1, opNewValue = 4 in
923class T_pstore_new_rr <string mnemonic, bits<2> MajOp, bit isNot, bit isPredNew>
924  : NVInst<(outs),
925           (ins PredRegs:$Pv, IntRegs:$Rs, IntRegs:$Ru, u2Imm:$u2, IntRegs:$Nt),
926   !if(isNot, "if (!$Pv", "if ($Pv")#!if(isPredNew, ".new) ",
927   ") ")#mnemonic#"($Rs+$Ru<<#$u2) = $Nt.new",
928   [], "", V4LDST_tc_st_SLOT0>, AddrModeRel {
929    bits<2> Pv;
930    bits<5> Rs;
931    bits<5> Ru;
932    bits<2> u2;
933    bits<3> Nt;
934
935    let isPredicatedFalse = isNot;
936    let isPredicatedNew = isPredNew;
937
938    let IClass = 0b0011;
939    let Inst{27-26} = 0b01;
940    let Inst{25}    = isPredNew;
941    let Inst{24}    = isNot;
942    let Inst{23-21} = 0b101;
943    let Inst{20-16} = Rs;
944    let Inst{12-8}  = Ru;
945    let Inst{13}    = u2{1};
946    let Inst{7}     = u2{0};
947    let Inst{6-5}   = Pv;
948    let Inst{4-3}   = MajOp;
949    let Inst{2-0}   = Nt;
950  }
951
952//===----------------------------------------------------------------------===//
953// multiclass for store instructions with base + register offset addressing
954// mode
955//===----------------------------------------------------------------------===//
956let isNVStorable = 1 in
957multiclass ST_Idxd_shl<string mnemonic, string CextOp, RegisterClass RC,
958                       bits<3> MajOp, bit isH = 0> {
959  let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed_shl in {
960    def S4_#NAME#_rr : T_store_rr <mnemonic, RC, MajOp, isH>;
961
962    // Predicated
963    def S4_p#NAME#t_rr : T_pstore_rr <mnemonic, RC, MajOp, 0, 0, isH>;
964    def S4_p#NAME#f_rr : T_pstore_rr <mnemonic, RC, MajOp, 1, 0, isH>;
965
966    // Predicated new
967    def S4_p#NAME#tnew_rr : T_pstore_rr <mnemonic, RC, MajOp, 0, 1, isH>;
968    def S4_p#NAME#fnew_rr : T_pstore_rr <mnemonic, RC, MajOp, 1, 1, isH>;
969  }
970}
971
972//===----------------------------------------------------------------------===//
973// multiclass for new-value store instructions with base + register offset
974// addressing mode.
975//===----------------------------------------------------------------------===//
976let mayStore = 1, isNVStore = 1 in
977multiclass ST_Idxd_shl_nv <string mnemonic, string CextOp, RegisterClass RC,
978                           bits<2> MajOp> {
979  let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed_shl in {
980    def S4_#NAME#new_rr : T_store_new_rr<mnemonic, MajOp>;
981
982    // Predicated
983    def S4_p#NAME#newt_rr : T_pstore_new_rr <mnemonic, MajOp, 0, 0>;
984    def S4_p#NAME#newf_rr : T_pstore_new_rr <mnemonic, MajOp, 1, 0>;
985
986    // Predicated new
987    def S4_p#NAME#newtnew_rr : T_pstore_new_rr <mnemonic, MajOp, 0, 1>;
988    def S4_p#NAME#newfnew_rr : T_pstore_new_rr <mnemonic, MajOp, 1, 1>;
989  }
990}
991
992let addrMode = BaseRegOffset, InputType = "reg", hasSideEffects = 0 in {
993  let accessSize = ByteAccess in
994  defm storerb: ST_Idxd_shl<"memb", "STrib", IntRegs, 0b000>,
995                ST_Idxd_shl_nv<"memb", "STrib", IntRegs, 0b00>;
996
997  let accessSize = HalfWordAccess in
998  defm storerh: ST_Idxd_shl<"memh", "STrih", IntRegs, 0b010>,
999                ST_Idxd_shl_nv<"memh", "STrih", IntRegs, 0b01>;
1000
1001  let accessSize = WordAccess in
1002  defm storeri: ST_Idxd_shl<"memw", "STriw", IntRegs, 0b100>,
1003                ST_Idxd_shl_nv<"memw", "STriw", IntRegs, 0b10>;
1004
1005  let isNVStorable = 0, accessSize = DoubleWordAccess in
1006  defm storerd: ST_Idxd_shl<"memd", "STrid", DoubleRegs, 0b110>;
1007
1008  let isNVStorable = 0, accessSize = HalfWordAccess in
1009  defm storerf: ST_Idxd_shl<"memh", "STrif", IntRegs, 0b011, 1>;
1010}
1011
1012class Storexs_pat<PatFrag Store, PatFrag Value, InstHexagon MI>
1013  : Pat<(Store Value:$Ru, (add (i32 IntRegs:$Rs),
1014                               (i32 (shl (i32 IntRegs:$Rt), u2ImmPred:$u2)))),
1015        (MI IntRegs:$Rs, IntRegs:$Rt, imm:$u2, Value:$Ru)>;
1016
1017let AddedComplexity = 40 in {
1018  def: Storexs_pat<truncstorei8,  I32, S4_storerb_rr>;
1019  def: Storexs_pat<truncstorei16, I32, S4_storerh_rr>;
1020  def: Storexs_pat<store,         I32, S4_storeri_rr>;
1021  def: Storexs_pat<store,         I64, S4_storerd_rr>;
1022}
1023
1024// memd(Rx++#s4:3)=Rtt
1025// memd(Rx++#s4:3:circ(Mu))=Rtt
1026// memd(Rx++I:circ(Mu))=Rtt
1027// memd(Rx++Mu)=Rtt
1028// memd(Rx++Mu:brev)=Rtt
1029// memd(gp+#u16:3)=Rtt
1030
1031// Store doubleword conditionally.
1032// if ([!]Pv[.new]) memd(#u6)=Rtt
1033// TODO: needs to be implemented.
1034
1035//===----------------------------------------------------------------------===//
1036// Template class
1037//===----------------------------------------------------------------------===//
1038let isPredicable = 1, isExtendable = 1, isExtentSigned = 1, opExtentBits = 8,
1039    opExtendable = 2 in
1040class T_StoreImm <string mnemonic, Operand OffsetOp, bits<2> MajOp >
1041  : STInst <(outs ), (ins IntRegs:$Rs, OffsetOp:$offset, s8Ext:$S8),
1042  mnemonic#"($Rs+#$offset)=#$S8",
1043  [], "", V4LDST_tc_st_SLOT01>,
1044  ImmRegRel, PredNewRel {
1045    bits<5> Rs;
1046    bits<8> S8;
1047    bits<8> offset;
1048    bits<6> offsetBits;
1049
1050    string OffsetOpStr = !cast<string>(OffsetOp);
1051    let offsetBits = !if (!eq(OffsetOpStr, "u6_2Imm"), offset{7-2},
1052                     !if (!eq(OffsetOpStr, "u6_1Imm"), offset{6-1},
1053                                         /* u6_0Imm */ offset{5-0}));
1054
1055    let IClass = 0b0011;
1056
1057    let Inst{27-25} = 0b110;
1058    let Inst{22-21} = MajOp;
1059    let Inst{20-16} = Rs;
1060    let Inst{12-7}  = offsetBits;
1061    let Inst{13}    = S8{7};
1062    let Inst{6-0}   = S8{6-0};
1063  }
1064
1065let isPredicated = 1, isExtendable = 1, isExtentSigned = 1, opExtentBits = 6,
1066    opExtendable = 3 in
1067class T_StoreImm_pred <string mnemonic, Operand OffsetOp, bits<2> MajOp,
1068                       bit isPredNot, bit isPredNew >
1069  : STInst <(outs ),
1070            (ins PredRegs:$Pv, IntRegs:$Rs, OffsetOp:$offset, s6Ext:$S6),
1071  !if(isPredNot, "if (!$Pv", "if ($Pv")#!if(isPredNew, ".new) ",
1072  ") ")#mnemonic#"($Rs+#$offset)=#$S6",
1073  [], "", V4LDST_tc_st_SLOT01>,
1074  ImmRegRel, PredNewRel {
1075    bits<2> Pv;
1076    bits<5> Rs;
1077    bits<6> S6;
1078    bits<8> offset;
1079    bits<6> offsetBits;
1080
1081    string OffsetOpStr = !cast<string>(OffsetOp);
1082    let offsetBits = !if (!eq(OffsetOpStr, "u6_2Imm"), offset{7-2},
1083                     !if (!eq(OffsetOpStr, "u6_1Imm"), offset{6-1},
1084                                         /* u6_0Imm */ offset{5-0}));
1085    let isPredicatedNew = isPredNew;
1086    let isPredicatedFalse = isPredNot;
1087
1088    let IClass = 0b0011;
1089
1090    let Inst{27-25} = 0b100;
1091    let Inst{24}    = isPredNew;
1092    let Inst{23}    = isPredNot;
1093    let Inst{22-21} = MajOp;
1094    let Inst{20-16} = Rs;
1095    let Inst{13}    = S6{5};
1096    let Inst{12-7}  = offsetBits;
1097    let Inst{6-5}   = Pv;
1098    let Inst{4-0}   = S6{4-0};
1099  }
1100
1101
1102//===----------------------------------------------------------------------===//
1103// multiclass for store instructions with base + immediate offset
1104// addressing mode and immediate stored value.
1105// mem[bhw](Rx++#s4:3)=#s8
1106// if ([!]Pv[.new]) mem[bhw](Rx++#s4:3)=#s6
1107//===----------------------------------------------------------------------===//
1108
1109multiclass ST_Imm_Pred <string mnemonic, Operand OffsetOp, bits<2> MajOp,
1110                        bit PredNot> {
1111  def _io    : T_StoreImm_pred <mnemonic, OffsetOp, MajOp, PredNot, 0>;
1112  // Predicate new
1113  def new_io : T_StoreImm_pred <mnemonic, OffsetOp, MajOp, PredNot, 1>;
1114}
1115
1116multiclass ST_Imm <string mnemonic, string CextOp, Operand OffsetOp,
1117                   bits<2> MajOp> {
1118  let CextOpcode = CextOp, BaseOpcode = CextOp#_imm in {
1119    def _io : T_StoreImm <mnemonic, OffsetOp, MajOp>;
1120
1121    defm t : ST_Imm_Pred <mnemonic, OffsetOp, MajOp, 0>;
1122    defm f : ST_Imm_Pred <mnemonic, OffsetOp, MajOp, 1>;
1123  }
1124}
1125
1126let hasSideEffects = 0, addrMode = BaseImmOffset,
1127    InputType = "imm" in {
1128  let accessSize = ByteAccess in
1129  defm S4_storeirb : ST_Imm<"memb", "STrib", u6_0Imm, 0b00>;
1130
1131  let accessSize = HalfWordAccess in
1132  defm S4_storeirh : ST_Imm<"memh", "STrih", u6_1Imm, 0b01>;
1133
1134  let accessSize = WordAccess in
1135  defm S4_storeiri : ST_Imm<"memw", "STriw", u6_2Imm, 0b10>;
1136}
1137
1138def IMM_BYTE : SDNodeXForm<imm, [{
1139  // -1 etc is  represented as 255 etc
1140  // assigning to a byte restores our desired signed value.
1141  int8_t imm = N->getSExtValue();
1142  return CurDAG->getTargetConstant(imm, MVT::i32);
1143}]>;
1144
1145def IMM_HALF : SDNodeXForm<imm, [{
1146  // -1 etc is  represented as 65535 etc
1147  // assigning to a short restores our desired signed value.
1148  int16_t imm = N->getSExtValue();
1149  return CurDAG->getTargetConstant(imm, MVT::i32);
1150}]>;
1151
1152def IMM_WORD : SDNodeXForm<imm, [{
1153  // -1 etc can be represented as 4294967295 etc
1154  // Currently, it's not doing this. But some optimization
1155  // might convert -1 to a large +ve number.
1156  // assigning to a word restores our desired signed value.
1157  int32_t imm = N->getSExtValue();
1158  return CurDAG->getTargetConstant(imm, MVT::i32);
1159}]>;
1160
1161def ToImmByte : OutPatFrag<(ops node:$R), (IMM_BYTE $R)>;
1162def ToImmHalf : OutPatFrag<(ops node:$R), (IMM_HALF $R)>;
1163def ToImmWord : OutPatFrag<(ops node:$R), (IMM_WORD $R)>;
1164
1165let AddedComplexity = 40 in {
1166  // Not using frameindex patterns for these stores, because the offset
1167  // is not extendable. This could cause problems during removing the frame
1168  // indices, since the offset with respect to R29/R30 may not fit in the
1169  // u6 field.
1170  def: Storexm_add_pat<truncstorei8, s32ImmPred, u6_0ImmPred, ToImmByte,
1171                       S4_storeirb_io>;
1172  def: Storexm_add_pat<truncstorei16, s32ImmPred, u6_1ImmPred, ToImmHalf,
1173                       S4_storeirh_io>;
1174  def: Storexm_add_pat<store, s32ImmPred, u6_2ImmPred, ToImmWord,
1175                       S4_storeiri_io>;
1176}
1177
1178def: Storexm_simple_pat<truncstorei8,  s32ImmPred, ToImmByte, S4_storeirb_io>;
1179def: Storexm_simple_pat<truncstorei16, s32ImmPred, ToImmHalf, S4_storeirh_io>;
1180def: Storexm_simple_pat<store,         s32ImmPred, ToImmWord, S4_storeiri_io>;
1181
1182// memb(Rx++#s4:0:circ(Mu))=Rt
1183// memb(Rx++I:circ(Mu))=Rt
1184// memb(Rx++Mu)=Rt
1185// memb(Rx++Mu:brev)=Rt
1186// memb(gp+#u16:0)=Rt
1187
1188// Store halfword.
1189// TODO: needs to be implemented
1190// memh(Re=#U6)=Rt.H
1191// memh(Rs+#s11:1)=Rt.H
1192// memh(Rs+Ru<<#u2)=Rt.H
1193// TODO: needs to be implemented.
1194
1195// memh(Ru<<#u2+#U6)=Rt.H
1196// memh(Rx++#s4:1:circ(Mu))=Rt.H
1197// memh(Rx++#s4:1:circ(Mu))=Rt
1198// memh(Rx++I:circ(Mu))=Rt.H
1199// memh(Rx++I:circ(Mu))=Rt
1200// memh(Rx++Mu)=Rt.H
1201// memh(Rx++Mu)=Rt
1202// memh(Rx++Mu:brev)=Rt.H
1203// memh(Rx++Mu:brev)=Rt
1204// memh(gp+#u16:1)=Rt
1205// if ([!]Pv[.new]) memh(#u6)=Rt.H
1206// if ([!]Pv[.new]) memh(#u6)=Rt
1207
1208// if ([!]Pv[.new]) memh(Rs+#u6:1)=Rt.H
1209// TODO: needs to be implemented.
1210
1211// if ([!]Pv[.new]) memh(Rx++#s4:1)=Rt.H
1212// TODO: Needs to be implemented.
1213
1214// Store word.
1215// memw(Re=#U6)=Rt
1216// TODO: Needs to be implemented.
1217// memw(Rx++#s4:2)=Rt
1218// memw(Rx++#s4:2:circ(Mu))=Rt
1219// memw(Rx++I:circ(Mu))=Rt
1220// memw(Rx++Mu)=Rt
1221// memw(Rx++Mu:brev)=Rt
1222
1223//===----------------------------------------------------------------------===
1224// ST -
1225//===----------------------------------------------------------------------===
1226
1227
1228//===----------------------------------------------------------------------===//
1229// NV/ST +
1230//===----------------------------------------------------------------------===//
1231
1232let opNewValue = 2, opExtendable = 1, isExtentSigned = 1, isPredicable = 1 in
1233class T_store_io_nv <string mnemonic, RegisterClass RC,
1234                    Operand ImmOp, bits<2>MajOp>
1235  : NVInst_V4 <(outs),
1236               (ins IntRegs:$src1, ImmOp:$src2, RC:$src3),
1237  mnemonic#"($src1+#$src2) = $src3.new",
1238  [],"",ST_tc_st_SLOT0> {
1239    bits<5> src1;
1240    bits<13> src2; // Actual address offset
1241    bits<3> src3;
1242    bits<11> offsetBits; // Represents offset encoding
1243
1244    let opExtentBits = !if (!eq(mnemonic, "memb"), 11,
1245                       !if (!eq(mnemonic, "memh"), 12,
1246                       !if (!eq(mnemonic, "memw"), 13, 0)));
1247
1248    let opExtentAlign = !if (!eq(mnemonic, "memb"), 0,
1249                        !if (!eq(mnemonic, "memh"), 1,
1250                        !if (!eq(mnemonic, "memw"), 2, 0)));
1251
1252    let offsetBits = !if (!eq(mnemonic, "memb"),  src2{10-0},
1253                     !if (!eq(mnemonic, "memh"),  src2{11-1},
1254                     !if (!eq(mnemonic, "memw"),  src2{12-2}, 0)));
1255
1256    let IClass = 0b1010;
1257
1258    let Inst{27} = 0b0;
1259    let Inst{26-25} = offsetBits{10-9};
1260    let Inst{24-21} = 0b1101;
1261    let Inst{20-16} = src1;
1262    let Inst{13} = offsetBits{8};
1263    let Inst{12-11} = MajOp;
1264    let Inst{10-8} = src3;
1265    let Inst{7-0} = offsetBits{7-0};
1266  }
1267
1268let opExtendable = 2, opNewValue = 3, isPredicated = 1 in
1269class T_pstore_io_nv <string mnemonic, RegisterClass RC, Operand predImmOp,
1270                         bits<2>MajOp, bit PredNot, bit isPredNew>
1271  : NVInst_V4 <(outs),
1272               (ins PredRegs:$src1, IntRegs:$src2, predImmOp:$src3, RC:$src4),
1273  !if(PredNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
1274  ") ")#mnemonic#"($src2+#$src3) = $src4.new",
1275  [],"",V2LDST_tc_st_SLOT0> {
1276    bits<2> src1;
1277    bits<5> src2;
1278    bits<9> src3;
1279    bits<3> src4;
1280    bits<6> offsetBits; // Represents offset encoding
1281
1282    let isPredicatedNew = isPredNew;
1283    let isPredicatedFalse = PredNot;
1284    let opExtentBits = !if (!eq(mnemonic, "memb"), 6,
1285                       !if (!eq(mnemonic, "memh"), 7,
1286                       !if (!eq(mnemonic, "memw"), 8, 0)));
1287
1288    let opExtentAlign = !if (!eq(mnemonic, "memb"), 0,
1289                        !if (!eq(mnemonic, "memh"), 1,
1290                        !if (!eq(mnemonic, "memw"), 2, 0)));
1291
1292    let offsetBits = !if (!eq(mnemonic, "memb"), src3{5-0},
1293                     !if (!eq(mnemonic, "memh"), src3{6-1},
1294                     !if (!eq(mnemonic, "memw"), src3{7-2}, 0)));
1295
1296    let IClass = 0b0100;
1297
1298    let Inst{27}    = 0b0;
1299    let Inst{26}    = PredNot;
1300    let Inst{25}    = isPredNew;
1301    let Inst{24-21} = 0b0101;
1302    let Inst{20-16} = src2;
1303    let Inst{13}    = offsetBits{5};
1304    let Inst{12-11} = MajOp;
1305    let Inst{10-8}  = src4;
1306    let Inst{7-3}   = offsetBits{4-0};
1307    let Inst{2}     = 0b0;
1308    let Inst{1-0}   = src1;
1309  }
1310
1311// multiclass for new-value store instructions with base + immediate offset.
1312//
1313let mayStore = 1, isNVStore = 1, isNewValue = 1, hasSideEffects = 0,
1314    isExtendable = 1 in
1315multiclass ST_Idxd_nv<string mnemonic, string CextOp, RegisterClass RC,
1316                   Operand ImmOp, Operand predImmOp, bits<2> MajOp> {
1317
1318  let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed in {
1319    def S2_#NAME#new_io : T_store_io_nv <mnemonic, RC, ImmOp, MajOp>;
1320    // Predicated
1321    def S2_p#NAME#newt_io :T_pstore_io_nv <mnemonic, RC, predImmOp, MajOp, 0, 0>;
1322    def S2_p#NAME#newf_io :T_pstore_io_nv <mnemonic, RC, predImmOp, MajOp, 1, 0>;
1323    // Predicated new
1324    def S4_p#NAME#newtnew_io :T_pstore_io_nv <mnemonic, RC, predImmOp,
1325                                              MajOp, 0, 1>;
1326    def S4_p#NAME#newfnew_io :T_pstore_io_nv <mnemonic, RC, predImmOp,
1327                                              MajOp, 1, 1>;
1328  }
1329}
1330
1331let addrMode = BaseImmOffset, InputType = "imm" in {
1332  let accessSize = ByteAccess in
1333  defm storerb: ST_Idxd_nv<"memb", "STrib", IntRegs, s11_0Ext,
1334                           u6_0Ext, 0b00>, AddrModeRel;
1335
1336  let accessSize = HalfWordAccess, opExtentAlign = 1 in
1337  defm storerh: ST_Idxd_nv<"memh", "STrih", IntRegs, s11_1Ext,
1338                           u6_1Ext, 0b01>, AddrModeRel;
1339
1340  let accessSize = WordAccess, opExtentAlign = 2 in
1341  defm storeri: ST_Idxd_nv<"memw", "STriw", IntRegs, s11_2Ext,
1342                           u6_2Ext, 0b10>, AddrModeRel;
1343}
1344
1345//===----------------------------------------------------------------------===//
1346// Post increment loads with register offset.
1347//===----------------------------------------------------------------------===//
1348
1349let hasNewValue = 1 in
1350def L2_loadbsw2_pr : T_load_pr <"membh", IntRegs, 0b0001, HalfWordAccess>;
1351
1352def L2_loadbsw4_pr : T_load_pr <"membh", DoubleRegs, 0b0111, WordAccess>;
1353
1354let hasSideEffects = 0, addrMode = PostInc in
1355class T_loadalign_pr <string mnemonic, bits<4> MajOp, MemAccessSize AccessSz>
1356  : LDInstPI <(outs DoubleRegs:$dst, IntRegs:$_dst_),
1357              (ins DoubleRegs:$src1, IntRegs:$src2, ModRegs:$src3),
1358  "$dst = "#mnemonic#"($src2++$src3)", [],
1359  "$src1 = $dst, $src2 = $_dst_"> {
1360    bits<5> dst;
1361    bits<5> src2;
1362    bits<1> src3;
1363
1364    let accessSize = AccessSz;
1365    let IClass = 0b1001;
1366
1367    let Inst{27-25} = 0b110;
1368    let Inst{24-21} = MajOp;
1369    let Inst{20-16} = src2;
1370    let Inst{13}    = src3;
1371    let Inst{12}    = 0b0;
1372    let Inst{7}     = 0b0;
1373    let Inst{4-0}   = dst;
1374  }
1375
1376def L2_loadalignb_pr : T_loadalign_pr <"memb_fifo", 0b0100, ByteAccess>;
1377def L2_loadalignh_pr : T_loadalign_pr <"memh_fifo", 0b0010, HalfWordAccess>;
1378
1379//===----------------------------------------------------------------------===//
1380// Template class for non-predicated post increment .new stores
1381// mem[bhwd](Rx++#s4:[0123])=Nt.new
1382//===----------------------------------------------------------------------===//
1383let isPredicable = 1, hasSideEffects = 0, addrMode = PostInc, isNVStore = 1,
1384    isNewValue = 1, opNewValue = 3 in
1385class T_StorePI_nv <string mnemonic, Operand ImmOp, bits<2> MajOp >
1386  : NVInstPI_V4 <(outs IntRegs:$_dst_),
1387                 (ins IntRegs:$src1, ImmOp:$offset, IntRegs:$src2),
1388  mnemonic#"($src1++#$offset) = $src2.new",
1389  [], "$src1 = $_dst_">,
1390  AddrModeRel {
1391    bits<5> src1;
1392    bits<3> src2;
1393    bits<7> offset;
1394    bits<4> offsetBits;
1395
1396    string ImmOpStr = !cast<string>(ImmOp);
1397    let offsetBits = !if (!eq(ImmOpStr, "s4_2Imm"), offset{5-2},
1398                     !if (!eq(ImmOpStr, "s4_1Imm"), offset{4-1},
1399                                      /* s4_0Imm */ offset{3-0}));
1400    let IClass = 0b1010;
1401
1402    let Inst{27-21} = 0b1011101;
1403    let Inst{20-16} = src1;
1404    let Inst{13} = 0b0;
1405    let Inst{12-11} = MajOp;
1406    let Inst{10-8} = src2;
1407    let Inst{7} = 0b0;
1408    let Inst{6-3} = offsetBits;
1409    let Inst{1} = 0b0;
1410  }
1411
1412//===----------------------------------------------------------------------===//
1413// Template class for predicated post increment .new stores
1414// if([!]Pv[.new]) mem[bhwd](Rx++#s4:[0123])=Nt.new
1415//===----------------------------------------------------------------------===//
1416let isPredicated = 1, hasSideEffects = 0, addrMode = PostInc, isNVStore = 1,
1417    isNewValue = 1, opNewValue = 4 in
1418class T_StorePI_nv_pred <string mnemonic, Operand ImmOp,
1419                         bits<2> MajOp, bit isPredNot, bit isPredNew >
1420  : NVInstPI_V4 <(outs IntRegs:$_dst_),
1421                 (ins PredRegs:$src1, IntRegs:$src2,
1422                      ImmOp:$offset, IntRegs:$src3),
1423  !if(isPredNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
1424  ") ")#mnemonic#"($src2++#$offset) = $src3.new",
1425  [], "$src2 = $_dst_">,
1426  AddrModeRel {
1427    bits<2> src1;
1428    bits<5> src2;
1429    bits<3> src3;
1430    bits<7> offset;
1431    bits<4> offsetBits;
1432
1433    string ImmOpStr = !cast<string>(ImmOp);
1434    let offsetBits = !if (!eq(ImmOpStr, "s4_2Imm"), offset{5-2},
1435                     !if (!eq(ImmOpStr, "s4_1Imm"), offset{4-1},
1436                                      /* s4_0Imm */ offset{3-0}));
1437    let isPredicatedNew = isPredNew;
1438    let isPredicatedFalse = isPredNot;
1439
1440    let IClass = 0b1010;
1441
1442    let Inst{27-21} = 0b1011101;
1443    let Inst{20-16} = src2;
1444    let Inst{13} = 0b1;
1445    let Inst{12-11} = MajOp;
1446    let Inst{10-8} = src3;
1447    let Inst{7} = isPredNew;
1448    let Inst{6-3} = offsetBits;
1449    let Inst{2} = isPredNot;
1450    let Inst{1-0} = src1;
1451  }
1452
1453multiclass ST_PostInc_Pred_nv<string mnemonic, Operand ImmOp,
1454                              bits<2> MajOp, bit PredNot> {
1455  def _pi : T_StorePI_nv_pred <mnemonic, ImmOp, MajOp, PredNot, 0>;
1456
1457  // Predicate new
1458  def new_pi : T_StorePI_nv_pred <mnemonic, ImmOp, MajOp, PredNot, 1>;
1459}
1460
1461multiclass ST_PostInc_nv<string mnemonic, string BaseOp, Operand ImmOp,
1462                         bits<2> MajOp> {
1463  let BaseOpcode = "POST_"#BaseOp in {
1464    def S2_#NAME#_pi : T_StorePI_nv <mnemonic, ImmOp, MajOp>;
1465
1466    // Predicated
1467    defm S2_p#NAME#t : ST_PostInc_Pred_nv <mnemonic, ImmOp, MajOp, 0>;
1468    defm S2_p#NAME#f : ST_PostInc_Pred_nv <mnemonic, ImmOp, MajOp, 1>;
1469  }
1470}
1471
1472let accessSize = ByteAccess in
1473defm storerbnew: ST_PostInc_nv <"memb", "STrib", s4_0Imm, 0b00>;
1474
1475let accessSize = HalfWordAccess in
1476defm storerhnew: ST_PostInc_nv <"memh", "STrih", s4_1Imm, 0b01>;
1477
1478let accessSize = WordAccess in
1479defm storerinew: ST_PostInc_nv <"memw", "STriw", s4_2Imm, 0b10>;
1480
1481//===----------------------------------------------------------------------===//
1482// Template class for post increment .new stores with register offset
1483//===----------------------------------------------------------------------===//
1484let isNewValue = 1, mayStore = 1, isNVStore = 1, opNewValue = 3 in
1485class T_StorePI_RegNV <string mnemonic, bits<2> MajOp, MemAccessSize AccessSz>
1486  : NVInstPI_V4 <(outs IntRegs:$_dst_),
1487                 (ins IntRegs:$src1, ModRegs:$src2, IntRegs:$src3),
1488  #mnemonic#"($src1++$src2) = $src3.new",
1489  [], "$src1 = $_dst_"> {
1490    bits<5> src1;
1491    bits<1> src2;
1492    bits<3> src3;
1493    let accessSize = AccessSz;
1494
1495    let IClass = 0b1010;
1496
1497    let Inst{27-21} = 0b1101101;
1498    let Inst{20-16} = src1;
1499    let Inst{13}    = src2;
1500    let Inst{12-11} = MajOp;
1501    let Inst{10-8}  = src3;
1502    let Inst{7}     = 0b0;
1503  }
1504
1505def S2_storerbnew_pr : T_StorePI_RegNV<"memb", 0b00, ByteAccess>;
1506def S2_storerhnew_pr : T_StorePI_RegNV<"memh", 0b01, HalfWordAccess>;
1507def S2_storerinew_pr : T_StorePI_RegNV<"memw", 0b10, WordAccess>;
1508
1509// memb(Rx++#s4:0:circ(Mu))=Nt.new
1510// memb(Rx++I:circ(Mu))=Nt.new
1511// memb(Rx++Mu:brev)=Nt.new
1512// memh(Rx++#s4:1:circ(Mu))=Nt.new
1513// memh(Rx++I:circ(Mu))=Nt.new
1514// memh(Rx++Mu)=Nt.new
1515// memh(Rx++Mu:brev)=Nt.new
1516
1517// memw(Rx++#s4:2:circ(Mu))=Nt.new
1518// memw(Rx++I:circ(Mu))=Nt.new
1519// memw(Rx++Mu)=Nt.new
1520// memw(Rx++Mu:brev)=Nt.new
1521
1522//===----------------------------------------------------------------------===//
1523// NV/ST -
1524//===----------------------------------------------------------------------===//
1525
1526//===----------------------------------------------------------------------===//
1527// NV/J +
1528//===----------------------------------------------------------------------===//
1529
1530//===----------------------------------------------------------------------===//
1531// multiclass/template class for the new-value compare jumps with the register
1532// operands.
1533//===----------------------------------------------------------------------===//
1534
1535let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 11,
1536    opExtentAlign = 2 in
1537class NVJrr_template<string mnemonic, bits<3> majOp, bit NvOpNum,
1538                      bit isNegCond, bit isTak>
1539  : NVInst_V4<(outs),
1540    (ins IntRegs:$src1, IntRegs:$src2, brtarget:$offset),
1541    "if ("#!if(isNegCond, "!","")#mnemonic#
1542    "($src1"#!if(!eq(NvOpNum, 0),".new, ",", ")#
1543    "$src2"#!if(!eq(NvOpNum, 1),".new))","))")#" jump:"
1544    #!if(isTak, "t","nt")#" $offset", []> {
1545
1546      bits<5> src1;
1547      bits<5> src2;
1548      bits<3> Ns;    // New-Value Operand
1549      bits<5> RegOp; // Non-New-Value Operand
1550      bits<11> offset;
1551
1552      let isTaken = isTak;
1553      let isPredicatedFalse = isNegCond;
1554      let opNewValue{0} = NvOpNum;
1555
1556      let Ns = !if(!eq(NvOpNum, 0), src1{2-0}, src2{2-0});
1557      let RegOp = !if(!eq(NvOpNum, 0), src2, src1);
1558
1559      let IClass = 0b0010;
1560      let Inst{27-26} = 0b00;
1561      let Inst{25-23} = majOp;
1562      let Inst{22} = isNegCond;
1563      let Inst{18-16} = Ns;
1564      let Inst{13} = isTak;
1565      let Inst{12-8} = RegOp;
1566      let Inst{21-20} = offset{10-9};
1567      let Inst{7-1} = offset{8-2};
1568}
1569
1570
1571multiclass NVJrr_cond<string mnemonic, bits<3> majOp, bit NvOpNum,
1572                       bit isNegCond> {
1573  // Branch not taken:
1574  def _nt: NVJrr_template<mnemonic, majOp, NvOpNum, isNegCond, 0>;
1575  // Branch taken:
1576  def _t : NVJrr_template<mnemonic, majOp, NvOpNum, isNegCond, 1>;
1577}
1578
1579// NvOpNum = 0 -> First Operand is a new-value Register
1580// NvOpNum = 1 -> Second Operand is a new-value Register
1581
1582multiclass NVJrr_base<string mnemonic, string BaseOp, bits<3> majOp,
1583                       bit NvOpNum> {
1584  let BaseOpcode = BaseOp#_NVJ in {
1585    defm _t_jumpnv : NVJrr_cond<mnemonic, majOp, NvOpNum, 0>; // True cond
1586    defm _f_jumpnv : NVJrr_cond<mnemonic, majOp, NvOpNum, 1>; // False cond
1587  }
1588}
1589
1590// if ([!]cmp.eq(Ns.new,Rt)) jump:[n]t #r9:2
1591// if ([!]cmp.gt(Ns.new,Rt)) jump:[n]t #r9:2
1592// if ([!]cmp.gtu(Ns.new,Rt)) jump:[n]t #r9:2
1593// if ([!]cmp.gt(Rt,Ns.new)) jump:[n]t #r9:2
1594// if ([!]cmp.gtu(Rt,Ns.new)) jump:[n]t #r9:2
1595
1596let isPredicated = 1, isBranch = 1, isNewValue = 1, isTerminator = 1,
1597    Defs = [PC], hasSideEffects = 0 in {
1598  defm J4_cmpeq  : NVJrr_base<"cmp.eq",  "CMPEQ",  0b000, 0>, PredRel;
1599  defm J4_cmpgt  : NVJrr_base<"cmp.gt",  "CMPGT",  0b001, 0>, PredRel;
1600  defm J4_cmpgtu : NVJrr_base<"cmp.gtu", "CMPGTU", 0b010, 0>, PredRel;
1601  defm J4_cmplt  : NVJrr_base<"cmp.gt",  "CMPLT",  0b011, 1>, PredRel;
1602  defm J4_cmpltu : NVJrr_base<"cmp.gtu", "CMPLTU", 0b100, 1>, PredRel;
1603}
1604
1605//===----------------------------------------------------------------------===//
1606// multiclass/template class for the new-value compare jumps instruction
1607// with a register and an unsigned immediate (U5) operand.
1608//===----------------------------------------------------------------------===//
1609
1610let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 11,
1611    opExtentAlign = 2 in
1612class NVJri_template<string mnemonic, bits<3> majOp, bit isNegCond,
1613                         bit isTak>
1614  : NVInst_V4<(outs),
1615    (ins IntRegs:$src1, u5Imm:$src2, brtarget:$offset),
1616    "if ("#!if(isNegCond, "!","")#mnemonic#"($src1.new, #$src2)) jump:"
1617    #!if(isTak, "t","nt")#" $offset", []> {
1618
1619      let isTaken = isTak;
1620      let isPredicatedFalse = isNegCond;
1621      let isTaken = isTak;
1622
1623      bits<3> src1;
1624      bits<5> src2;
1625      bits<11> offset;
1626
1627      let IClass = 0b0010;
1628      let Inst{26} = 0b1;
1629      let Inst{25-23} = majOp;
1630      let Inst{22} = isNegCond;
1631      let Inst{18-16} = src1;
1632      let Inst{13} = isTak;
1633      let Inst{12-8} = src2;
1634      let Inst{21-20} = offset{10-9};
1635      let Inst{7-1} = offset{8-2};
1636}
1637
1638multiclass NVJri_cond<string mnemonic, bits<3> majOp, bit isNegCond> {
1639  // Branch not taken:
1640  def _nt: NVJri_template<mnemonic, majOp, isNegCond, 0>;
1641  // Branch taken:
1642  def _t : NVJri_template<mnemonic, majOp, isNegCond, 1>;
1643}
1644
1645multiclass NVJri_base<string mnemonic, string BaseOp, bits<3> majOp> {
1646  let BaseOpcode = BaseOp#_NVJri in {
1647    defm _t_jumpnv : NVJri_cond<mnemonic, majOp, 0>; // True Cond
1648    defm _f_jumpnv : NVJri_cond<mnemonic, majOp, 1>; // False cond
1649  }
1650}
1651
1652// if ([!]cmp.eq(Ns.new,#U5)) jump:[n]t #r9:2
1653// if ([!]cmp.gt(Ns.new,#U5)) jump:[n]t #r9:2
1654// if ([!]cmp.gtu(Ns.new,#U5)) jump:[n]t #r9:2
1655
1656let isPredicated = 1, isBranch = 1, isNewValue = 1, isTerminator = 1,
1657    Defs = [PC], hasSideEffects = 0 in {
1658  defm J4_cmpeqi  : NVJri_base<"cmp.eq", "CMPEQ", 0b000>, PredRel;
1659  defm J4_cmpgti  : NVJri_base<"cmp.gt", "CMPGT", 0b001>, PredRel;
1660  defm J4_cmpgtui : NVJri_base<"cmp.gtu", "CMPGTU", 0b010>, PredRel;
1661}
1662
1663//===----------------------------------------------------------------------===//
1664// multiclass/template class for the new-value compare jumps instruction
1665// with a register and an hardcoded 0/-1 immediate value.
1666//===----------------------------------------------------------------------===//
1667
1668let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 11,
1669    opExtentAlign = 2 in
1670class NVJ_ConstImm_template<string mnemonic, bits<3> majOp, string ImmVal,
1671                            bit isNegCond, bit isTak>
1672  : NVInst_V4<(outs),
1673    (ins IntRegs:$src1, brtarget:$offset),
1674    "if ("#!if(isNegCond, "!","")#mnemonic
1675    #"($src1.new, #"#ImmVal#")) jump:"
1676    #!if(isTak, "t","nt")#" $offset", []> {
1677
1678      let isTaken = isTak;
1679      let isPredicatedFalse = isNegCond;
1680      let isTaken = isTak;
1681
1682      bits<3> src1;
1683      bits<11> offset;
1684      let IClass = 0b0010;
1685      let Inst{26} = 0b1;
1686      let Inst{25-23} = majOp;
1687      let Inst{22} = isNegCond;
1688      let Inst{18-16} = src1;
1689      let Inst{13} = isTak;
1690      let Inst{21-20} = offset{10-9};
1691      let Inst{7-1} = offset{8-2};
1692}
1693
1694multiclass NVJ_ConstImm_cond<string mnemonic, bits<3> majOp, string ImmVal,
1695                             bit isNegCond> {
1696  // Branch not taken:
1697  def _nt: NVJ_ConstImm_template<mnemonic, majOp, ImmVal, isNegCond, 0>;
1698  // Branch taken:
1699  def _t : NVJ_ConstImm_template<mnemonic, majOp, ImmVal, isNegCond, 1>;
1700}
1701
1702multiclass NVJ_ConstImm_base<string mnemonic, string BaseOp, bits<3> majOp,
1703                             string ImmVal> {
1704  let BaseOpcode = BaseOp#_NVJ_ConstImm in {
1705    defm _t_jumpnv : NVJ_ConstImm_cond<mnemonic, majOp, ImmVal, 0>; // True
1706    defm _f_jumpnv : NVJ_ConstImm_cond<mnemonic, majOp, ImmVal, 1>; // False
1707  }
1708}
1709
1710// if ([!]tstbit(Ns.new,#0)) jump:[n]t #r9:2
1711// if ([!]cmp.eq(Ns.new,#-1)) jump:[n]t #r9:2
1712// if ([!]cmp.gt(Ns.new,#-1)) jump:[n]t #r9:2
1713
1714let isPredicated = 1, isBranch = 1, isNewValue = 1, isTerminator=1,
1715    Defs = [PC], hasSideEffects = 0 in {
1716  defm J4_tstbit0 : NVJ_ConstImm_base<"tstbit", "TSTBIT", 0b011, "0">, PredRel;
1717  defm J4_cmpeqn1 : NVJ_ConstImm_base<"cmp.eq", "CMPEQ",  0b100, "-1">, PredRel;
1718  defm J4_cmpgtn1 : NVJ_ConstImm_base<"cmp.gt", "CMPGT",  0b101, "-1">, PredRel;
1719}
1720
1721// J4_hintjumpr: Hint indirect conditional jump.
1722let isBranch = 1, isIndirectBranch = 1, hasSideEffects = 0 in
1723def J4_hintjumpr: JRInst <
1724  (outs),
1725  (ins IntRegs:$Rs),
1726  "hintjr($Rs)"> {
1727    bits<5> Rs;
1728    let IClass = 0b0101;
1729    let Inst{27-21} = 0b0010101;
1730    let Inst{20-16} = Rs;
1731  }
1732
1733//===----------------------------------------------------------------------===//
1734// NV/J -
1735//===----------------------------------------------------------------------===//
1736
1737//===----------------------------------------------------------------------===//
1738// CR +
1739//===----------------------------------------------------------------------===//
1740
1741// PC-relative add
1742let hasNewValue = 1, isExtendable = 1, opExtendable = 1,
1743    isExtentSigned = 0, opExtentBits = 6, hasSideEffects = 0, Uses = [PC] in
1744def C4_addipc : CRInst <(outs IntRegs:$Rd), (ins u6Ext:$u6),
1745  "$Rd = add(pc, #$u6)", [], "", CR_tc_2_SLOT3 > {
1746    bits<5> Rd;
1747    bits<6> u6;
1748
1749    let IClass = 0b0110;
1750    let Inst{27-16} = 0b101001001001;
1751    let Inst{12-7} = u6;
1752    let Inst{4-0} = Rd;
1753  }
1754
1755
1756
1757let hasSideEffects = 0 in
1758class T_LOGICAL_3OP<string MnOp1, string MnOp2, bits<2> OpBits, bit IsNeg>
1759    : CRInst<(outs PredRegs:$Pd),
1760             (ins PredRegs:$Ps, PredRegs:$Pt, PredRegs:$Pu),
1761             "$Pd = " # MnOp1 # "($Ps, " # MnOp2 # "($Pt, " #
1762                   !if (IsNeg,"!","") # "$Pu))",
1763             [], "", CR_tc_2early_SLOT23> {
1764  bits<2> Pd;
1765  bits<2> Ps;
1766  bits<2> Pt;
1767  bits<2> Pu;
1768
1769  let IClass = 0b0110;
1770  let Inst{27-24} = 0b1011;
1771  let Inst{23} = IsNeg;
1772  let Inst{22-21} = OpBits;
1773  let Inst{20} = 0b1;
1774  let Inst{17-16} = Ps;
1775  let Inst{13} = 0b0;
1776  let Inst{9-8} = Pt;
1777  let Inst{7-6} = Pu;
1778  let Inst{1-0} = Pd;
1779}
1780
1781def C4_and_and  : T_LOGICAL_3OP<"and", "and", 0b00, 0>;
1782def C4_and_or   : T_LOGICAL_3OP<"and", "or",  0b01, 0>;
1783def C4_or_and   : T_LOGICAL_3OP<"or",  "and", 0b10, 0>;
1784def C4_or_or    : T_LOGICAL_3OP<"or",  "or",  0b11, 0>;
1785def C4_and_andn : T_LOGICAL_3OP<"and", "and", 0b00, 1>;
1786def C4_and_orn  : T_LOGICAL_3OP<"and", "or",  0b01, 1>;
1787def C4_or_andn  : T_LOGICAL_3OP<"or",  "and", 0b10, 1>;
1788def C4_or_orn   : T_LOGICAL_3OP<"or",  "or",  0b11, 1>;
1789
1790// op(Ps, op(Pt, Pu))
1791class LogLog_pat<SDNode Op1, SDNode Op2, InstHexagon MI>
1792  : Pat<(i1 (Op1 I1:$Ps, (Op2 I1:$Pt, I1:$Pu))),
1793        (MI I1:$Ps, I1:$Pt, I1:$Pu)>;
1794
1795// op(Ps, op(Pt, ~Pu))
1796class LogLogNot_pat<SDNode Op1, SDNode Op2, InstHexagon MI>
1797  : Pat<(i1 (Op1 I1:$Ps, (Op2 I1:$Pt, (not I1:$Pu)))),
1798        (MI I1:$Ps, I1:$Pt, I1:$Pu)>;
1799
1800def: LogLog_pat<and, and, C4_and_and>;
1801def: LogLog_pat<and, or,  C4_and_or>;
1802def: LogLog_pat<or,  and, C4_or_and>;
1803def: LogLog_pat<or,  or,  C4_or_or>;
1804
1805def: LogLogNot_pat<and, and, C4_and_andn>;
1806def: LogLogNot_pat<and, or,  C4_and_orn>;
1807def: LogLogNot_pat<or,  and, C4_or_andn>;
1808def: LogLogNot_pat<or,  or,  C4_or_orn>;
1809
1810//===----------------------------------------------------------------------===//
1811// PIC: Support for PIC compilations. The patterns and SD nodes defined
1812// below are needed to support code generation for PIC
1813//===----------------------------------------------------------------------===//
1814
1815def SDT_HexagonPICAdd
1816  : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
1817def SDT_HexagonGOTAdd
1818  : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
1819
1820def SDT_HexagonGOTAddInternal   : SDTypeProfile<1, 1, [SDTCisVT<0, i32>]>;
1821def SDT_HexagonGOTAddInternalJT : SDTypeProfile<1, 1, [SDTCisVT<0, i32>]>;
1822def SDT_HexagonGOTAddInternalBA : SDTypeProfile<1, 1, [SDTCisVT<0, i32>]>;
1823
1824def Hexagonpic_add      : SDNode<"HexagonISD::PIC_ADD", SDT_HexagonPICAdd>;
1825def Hexagonat_got       : SDNode<"HexagonISD::AT_GOT", SDT_HexagonGOTAdd>;
1826def Hexagongat_pcrel    : SDNode<"HexagonISD::AT_PCREL",
1827                                 SDT_HexagonGOTAddInternal>;
1828def Hexagongat_pcrel_jt : SDNode<"HexagonISD::AT_PCREL",
1829                                 SDT_HexagonGOTAddInternalJT>;
1830def Hexagongat_pcrel_ba : SDNode<"HexagonISD::AT_PCREL",
1831                                 SDT_HexagonGOTAddInternalBA>;
1832
1833// PIC: Map from a block address computation to a PC-relative add
1834def: Pat<(Hexagongat_pcrel_ba tblockaddress:$src1),
1835         (C4_addipc u32ImmPred:$src1)>;
1836
1837// PIC: Map from the computation to generate a GOT pointer to a PC-relative add
1838def: Pat<(Hexagonpic_add texternalsym:$src1),
1839         (C4_addipc u32ImmPred:$src1)>;
1840
1841// PIC: Map from a jump table address computation to a PC-relative add
1842def: Pat<(Hexagongat_pcrel_jt tjumptable:$src1),
1843         (C4_addipc u32ImmPred:$src1)>;
1844
1845// PIC: Map from a GOT-relative symbol reference to a load
1846def: Pat<(Hexagonat_got (i32 IntRegs:$src1), tglobaladdr:$src2),
1847         (L2_loadri_io IntRegs:$src1, s30_2ImmPred:$src2)>;
1848
1849// PIC: Map from a static symbol reference to a PC-relative add
1850def: Pat<(Hexagongat_pcrel tglobaladdr:$src1),
1851         (C4_addipc u32ImmPred:$src1)>;
1852
1853//===----------------------------------------------------------------------===//
1854// CR -
1855//===----------------------------------------------------------------------===//
1856
1857//===----------------------------------------------------------------------===//
1858// XTYPE/ALU +
1859//===----------------------------------------------------------------------===//
1860
1861// Logical with-not instructions.
1862def A4_andnp : T_ALU64_logical<"and", 0b001, 1, 0, 1>;
1863def A4_ornp  : T_ALU64_logical<"or",  0b011, 1, 0, 1>;
1864
1865def: Pat<(i64 (and (i64 DoubleRegs:$Rs), (i64 (not (i64 DoubleRegs:$Rt))))),
1866         (A4_andnp DoubleRegs:$Rs, DoubleRegs:$Rt)>;
1867def: Pat<(i64 (or  (i64 DoubleRegs:$Rs), (i64 (not (i64 DoubleRegs:$Rt))))),
1868         (A4_ornp DoubleRegs:$Rs, DoubleRegs:$Rt)>;
1869
1870let hasNewValue = 1, hasSideEffects = 0 in
1871def S4_parity: ALU64Inst<(outs IntRegs:$Rd), (ins IntRegs:$Rs, IntRegs:$Rt),
1872      "$Rd = parity($Rs, $Rt)", [], "", ALU64_tc_2_SLOT23> {
1873  bits<5> Rd;
1874  bits<5> Rs;
1875  bits<5> Rt;
1876
1877  let IClass = 0b1101;
1878  let Inst{27-21} = 0b0101111;
1879  let Inst{20-16} = Rs;
1880  let Inst{12-8} = Rt;
1881  let Inst{4-0} = Rd;
1882}
1883
1884//  Add and accumulate.
1885//  Rd=add(Rs,add(Ru,#s6))
1886let isExtentSigned = 1, hasNewValue = 1, isExtendable = 1, opExtentBits = 6,
1887    opExtendable = 3 in
1888def S4_addaddi : ALU64Inst <(outs IntRegs:$Rd),
1889                            (ins IntRegs:$Rs, IntRegs:$Ru, s6Ext:$s6),
1890  "$Rd = add($Rs, add($Ru, #$s6))" ,
1891  [(set (i32 IntRegs:$Rd), (add (i32 IntRegs:$Rs),
1892                           (add (i32 IntRegs:$Ru), s16_16ImmPred:$s6)))],
1893  "", ALU64_tc_2_SLOT23> {
1894    bits<5> Rd;
1895    bits<5> Rs;
1896    bits<5> Ru;
1897    bits<6> s6;
1898
1899    let IClass = 0b1101;
1900
1901    let Inst{27-23} = 0b10110;
1902    let Inst{22-21} = s6{5-4};
1903    let Inst{20-16} = Rs;
1904    let Inst{13}    = s6{3};
1905    let Inst{12-8}  = Rd;
1906    let Inst{7-5}   = s6{2-0};
1907    let Inst{4-0}   = Ru;
1908  }
1909
1910let isExtentSigned = 1, hasSideEffects = 0, hasNewValue = 1, isExtendable = 1,
1911    opExtentBits = 6, opExtendable = 2 in
1912def S4_subaddi: ALU64Inst <(outs IntRegs:$Rd),
1913                           (ins IntRegs:$Rs, s6Ext:$s6, IntRegs:$Ru),
1914  "$Rd = add($Rs, sub(#$s6, $Ru))",
1915  [], "", ALU64_tc_2_SLOT23> {
1916    bits<5> Rd;
1917    bits<5> Rs;
1918    bits<6> s6;
1919    bits<5> Ru;
1920
1921    let IClass = 0b1101;
1922
1923    let Inst{27-23} = 0b10111;
1924    let Inst{22-21} = s6{5-4};
1925    let Inst{20-16} = Rs;
1926    let Inst{13}    = s6{3};
1927    let Inst{12-8}  = Rd;
1928    let Inst{7-5}   = s6{2-0};
1929    let Inst{4-0}   = Ru;
1930  }
1931
1932// Rd=add(Rs,sub(#s6,Ru))
1933def: Pat<(add (i32 IntRegs:$src1), (sub s32ImmPred:$src2,
1934                                        (i32 IntRegs:$src3))),
1935         (S4_subaddi IntRegs:$src1, s32ImmPred:$src2, IntRegs:$src3)>;
1936
1937// Rd=sub(add(Rs,#s6),Ru)
1938def: Pat<(sub (add (i32 IntRegs:$src1), s32ImmPred:$src2),
1939                   (i32 IntRegs:$src3)),
1940         (S4_subaddi IntRegs:$src1, s32ImmPred:$src2, IntRegs:$src3)>;
1941
1942// Rd=add(sub(Rs,Ru),#s6)
1943def: Pat<(add (sub (i32 IntRegs:$src1), (i32 IntRegs:$src3)),
1944                   (s32ImmPred:$src2)),
1945         (S4_subaddi IntRegs:$src1, s32ImmPred:$src2, IntRegs:$src3)>;
1946
1947
1948//  Add or subtract doublewords with carry.
1949//TODO:
1950//  Rdd=add(Rss,Rtt,Px):carry
1951//TODO:
1952//  Rdd=sub(Rss,Rtt,Px):carry
1953
1954// Extract bitfield
1955// Rdd=extract(Rss,#u6,#U6)
1956// Rdd=extract(Rss,Rtt)
1957// Rd=extract(Rs,Rtt)
1958// Rd=extract(Rs,#u5,#U5)
1959
1960def S4_extractp_rp : T_S3op_64 < "extract",  0b11, 0b100, 0>;
1961def S4_extractp    : T_S2op_extract <"extract",  0b1010, DoubleRegs, u6Imm>;
1962
1963let hasNewValue = 1 in {
1964  def S4_extract_rp : T_S3op_extract<"extract",  0b01>;
1965  def S4_extract    : T_S2op_extract <"extract",  0b1101, IntRegs, u5Imm>;
1966}
1967
1968// Complex add/sub halfwords/words
1969let Defs = [USR_OVF] in {
1970  def S4_vxaddsubh : T_S3op_64 < "vxaddsubh", 0b01, 0b100, 0, 1>;
1971  def S4_vxaddsubw : T_S3op_64 < "vxaddsubw", 0b01, 0b000, 0, 1>;
1972  def S4_vxsubaddh : T_S3op_64 < "vxsubaddh", 0b01, 0b110, 0, 1>;
1973  def S4_vxsubaddw : T_S3op_64 < "vxsubaddw", 0b01, 0b010, 0, 1>;
1974}
1975
1976let Defs = [USR_OVF] in {
1977  def S4_vxaddsubhr : T_S3op_64 < "vxaddsubh", 0b11, 0b000, 0, 1, 1, 1>;
1978  def S4_vxsubaddhr : T_S3op_64 < "vxsubaddh", 0b11, 0b010, 0, 1, 1, 1>;
1979}
1980
1981let Itinerary = M_tc_3x_SLOT23, Defs = [USR_OVF] in {
1982  def M4_mac_up_s1_sat: T_MType_acc_rr<"+= mpy", 0b011, 0b000, 0, [], 0, 1, 1>;
1983  def M4_nac_up_s1_sat: T_MType_acc_rr<"-= mpy", 0b011, 0b001, 0, [], 0, 1, 1>;
1984}
1985
1986// Logical xor with xor accumulation.
1987// Rxx^=xor(Rss,Rtt)
1988let hasSideEffects = 0 in
1989def M4_xor_xacc
1990  : SInst <(outs DoubleRegs:$Rxx),
1991           (ins DoubleRegs:$dst2, DoubleRegs:$Rss, DoubleRegs:$Rtt),
1992  "$Rxx ^= xor($Rss, $Rtt)",
1993  [(set (i64 DoubleRegs:$Rxx),
1994   (xor (i64 DoubleRegs:$dst2), (xor (i64 DoubleRegs:$Rss),
1995                                     (i64 DoubleRegs:$Rtt))))],
1996  "$dst2 = $Rxx", S_3op_tc_1_SLOT23> {
1997    bits<5> Rxx;
1998    bits<5> Rss;
1999    bits<5> Rtt;
2000
2001    let IClass = 0b1100;
2002
2003    let Inst{27-22} = 0b101010;
2004    let Inst{20-16} = Rss;
2005    let Inst{12-8}  = Rtt;
2006    let Inst{7-5}   = 0b000;
2007    let Inst{4-0}   = Rxx;
2008  }
2009
2010// Rotate and reduce bytes
2011// Rdd=vrcrotate(Rss,Rt,#u2)
2012let hasSideEffects = 0 in
2013def S4_vrcrotate
2014  : SInst <(outs DoubleRegs:$Rdd),
2015           (ins DoubleRegs:$Rss, IntRegs:$Rt, u2Imm:$u2),
2016  "$Rdd = vrcrotate($Rss, $Rt, #$u2)",
2017  [], "", S_3op_tc_3x_SLOT23> {
2018    bits<5> Rdd;
2019    bits<5> Rss;
2020    bits<5> Rt;
2021    bits<2> u2;
2022
2023    let IClass = 0b1100;
2024
2025    let Inst{27-22} = 0b001111;
2026    let Inst{20-16} = Rss;
2027    let Inst{13}    = u2{1};
2028    let Inst{12-8}  = Rt;
2029    let Inst{7-6}   = 0b11;
2030    let Inst{5}     = u2{0};
2031    let Inst{4-0}   = Rdd;
2032  }
2033
2034// Rotate and reduce bytes with accumulation
2035// Rxx+=vrcrotate(Rss,Rt,#u2)
2036let hasSideEffects = 0 in
2037def S4_vrcrotate_acc
2038  : SInst <(outs DoubleRegs:$Rxx),
2039           (ins DoubleRegs:$dst2, DoubleRegs:$Rss, IntRegs:$Rt, u2Imm:$u2),
2040  "$Rxx += vrcrotate($Rss, $Rt, #$u2)", [],
2041  "$dst2 = $Rxx", S_3op_tc_3x_SLOT23> {
2042    bits<5> Rxx;
2043    bits<5> Rss;
2044    bits<5> Rt;
2045    bits<2> u2;
2046
2047    let IClass = 0b1100;
2048
2049    let Inst{27-21} = 0b1011101;
2050    let Inst{20-16} = Rss;
2051    let Inst{13}    = u2{1};
2052    let Inst{12-8}  = Rt;
2053    let Inst{5}     = u2{0};
2054    let Inst{4-0}   = Rxx;
2055  }
2056
2057// Vector reduce conditional negate halfwords
2058let hasSideEffects = 0 in
2059def S2_vrcnegh
2060  : SInst <(outs DoubleRegs:$Rxx),
2061           (ins DoubleRegs:$dst2, DoubleRegs:$Rss, IntRegs:$Rt),
2062  "$Rxx += vrcnegh($Rss, $Rt)", [],
2063  "$dst2 = $Rxx", S_3op_tc_3x_SLOT23> {
2064    bits<5> Rxx;
2065    bits<5> Rss;
2066    bits<5> Rt;
2067
2068    let IClass = 0b1100;
2069
2070    let Inst{27-21} = 0b1011001;
2071    let Inst{20-16} = Rss;
2072    let Inst{13}    = 0b1;
2073    let Inst{12-8}  = Rt;
2074    let Inst{7-5}   = 0b111;
2075    let Inst{4-0}   = Rxx;
2076  }
2077
2078// Split bitfield
2079def A4_bitspliti : T_S2op_2_di <"bitsplit", 0b110, 0b100>;
2080
2081// Arithmetic/Convergent round
2082def A4_cround_ri : T_S2op_2_ii <"cround", 0b111, 0b000>;
2083
2084def A4_round_ri  : T_S2op_2_ii <"round", 0b111, 0b100>;
2085
2086let Defs = [USR_OVF] in
2087def A4_round_ri_sat : T_S2op_2_ii <"round", 0b111, 0b110, 1>;
2088
2089// Logical-logical words.
2090// Compound or-and -- Rx=or(Ru,and(Rx,#s10))
2091let isExtentSigned = 1, hasNewValue = 1, isExtendable = 1, opExtentBits = 10,
2092    opExtendable = 3 in
2093def S4_or_andix:
2094  ALU64Inst<(outs IntRegs:$Rx),
2095            (ins IntRegs:$Ru, IntRegs:$_src_, s10Ext:$s10),
2096  "$Rx = or($Ru, and($_src_, #$s10))" ,
2097  [(set (i32 IntRegs:$Rx),
2098        (or (i32 IntRegs:$Ru), (and (i32 IntRegs:$_src_), s32ImmPred:$s10)))] ,
2099  "$_src_ = $Rx", ALU64_tc_2_SLOT23> {
2100    bits<5> Rx;
2101    bits<5> Ru;
2102    bits<10> s10;
2103
2104    let IClass = 0b1101;
2105
2106    let Inst{27-22} = 0b101001;
2107    let Inst{20-16} = Rx;
2108    let Inst{21}    = s10{9};
2109    let Inst{13-5}  = s10{8-0};
2110    let Inst{4-0}   = Ru;
2111  }
2112
2113// Miscellaneous ALU64 instructions.
2114//
2115let hasNewValue = 1, hasSideEffects = 0 in
2116def A4_modwrapu: ALU64Inst<(outs IntRegs:$Rd), (ins IntRegs:$Rs, IntRegs:$Rt),
2117      "$Rd = modwrap($Rs, $Rt)", [], "", ALU64_tc_2_SLOT23> {
2118  bits<5> Rd;
2119  bits<5> Rs;
2120  bits<5> Rt;
2121
2122  let IClass = 0b1101;
2123  let Inst{27-21} = 0b0011111;
2124  let Inst{20-16} = Rs;
2125  let Inst{12-8} = Rt;
2126  let Inst{7-5} = 0b111;
2127  let Inst{4-0} = Rd;
2128}
2129
2130let hasSideEffects = 0 in
2131def A4_bitsplit: ALU64Inst<(outs DoubleRegs:$Rd),
2132      (ins IntRegs:$Rs, IntRegs:$Rt),
2133      "$Rd = bitsplit($Rs, $Rt)", [], "", ALU64_tc_1_SLOT23> {
2134  bits<5> Rd;
2135  bits<5> Rs;
2136  bits<5> Rt;
2137
2138  let IClass = 0b1101;
2139  let Inst{27-24} = 0b0100;
2140  let Inst{21} = 0b1;
2141  let Inst{20-16} = Rs;
2142  let Inst{12-8} = Rt;
2143  let Inst{4-0} = Rd;
2144}
2145
2146let hasSideEffects = 0 in
2147def dep_S2_packhl: ALU64Inst<(outs DoubleRegs:$Rd),
2148      (ins IntRegs:$Rs, IntRegs:$Rt),
2149      "$Rd = packhl($Rs, $Rt):deprecated", [], "", ALU64_tc_1_SLOT23> {
2150  bits<5> Rd;
2151  bits<5> Rs;
2152  bits<5> Rt;
2153
2154  let IClass = 0b1101;
2155  let Inst{27-24} = 0b0100;
2156  let Inst{21} = 0b0;
2157  let Inst{20-16} = Rs;
2158  let Inst{12-8} = Rt;
2159  let Inst{4-0} = Rd;
2160}
2161
2162let hasNewValue = 1, hasSideEffects = 0 in
2163def dep_A2_addsat: ALU64Inst<(outs IntRegs:$Rd),
2164      (ins IntRegs:$Rs, IntRegs:$Rt),
2165      "$Rd = add($Rs, $Rt):sat:deprecated", [], "", ALU64_tc_2_SLOT23> {
2166  bits<5> Rd;
2167  bits<5> Rs;
2168  bits<5> Rt;
2169
2170  let IClass = 0b1101;
2171  let Inst{27-21} = 0b0101100;
2172  let Inst{20-16} = Rs;
2173  let Inst{12-8} = Rt;
2174  let Inst{7} = 0b0;
2175  let Inst{4-0} = Rd;
2176}
2177
2178let hasNewValue = 1, hasSideEffects = 0 in
2179def dep_A2_subsat: ALU64Inst<(outs IntRegs:$Rd),
2180      (ins IntRegs:$Rs, IntRegs:$Rt),
2181      "$Rd = sub($Rs, $Rt):sat:deprecated", [], "", ALU64_tc_2_SLOT23> {
2182  bits<5> Rd;
2183  bits<5> Rs;
2184  bits<5> Rt;
2185
2186  let IClass = 0b1101;
2187  let Inst{27-21} = 0b0101100;
2188  let Inst{20-16} = Rt;
2189  let Inst{12-8} = Rs;
2190  let Inst{7} = 0b1;
2191  let Inst{4-0} = Rd;
2192}
2193
2194// Rx[&|]=xor(Rs,Rt)
2195def M4_or_xor   : T_MType_acc_rr < "|= xor", 0b110, 0b001, 0>;
2196def M4_and_xor  : T_MType_acc_rr < "&= xor", 0b010, 0b010, 0>;
2197
2198// Rx[&|^]=or(Rs,Rt)
2199def M4_xor_or   : T_MType_acc_rr < "^= or",  0b110, 0b011, 0>;
2200
2201let CextOpcode = "ORr_ORr" in
2202def M4_or_or    : T_MType_acc_rr < "|= or",  0b110, 0b000, 0>;
2203def M4_and_or   : T_MType_acc_rr < "&= or",  0b010, 0b001, 0>;
2204
2205// Rx[&|^]=and(Rs,Rt)
2206def M4_xor_and  : T_MType_acc_rr < "^= and", 0b110, 0b010, 0>;
2207
2208let CextOpcode = "ORr_ANDr" in
2209def M4_or_and   : T_MType_acc_rr < "|= and", 0b010, 0b011, 0>;
2210def M4_and_and  : T_MType_acc_rr < "&= and", 0b010, 0b000, 0>;
2211
2212// Rx[&|^]=and(Rs,~Rt)
2213def M4_xor_andn : T_MType_acc_rr < "^= and", 0b001, 0b010, 0, [], 1>;
2214def M4_or_andn  : T_MType_acc_rr < "|= and", 0b001, 0b000, 0, [], 1>;
2215def M4_and_andn : T_MType_acc_rr < "&= and", 0b001, 0b001, 0, [], 1>;
2216
2217def: T_MType_acc_pat2 <M4_or_xor, xor, or>;
2218def: T_MType_acc_pat2 <M4_and_xor, xor, and>;
2219def: T_MType_acc_pat2 <M4_or_and, and, or>;
2220def: T_MType_acc_pat2 <M4_and_and, and, and>;
2221def: T_MType_acc_pat2 <M4_xor_and, and, xor>;
2222def: T_MType_acc_pat2 <M4_or_or, or, or>;
2223def: T_MType_acc_pat2 <M4_and_or, or, and>;
2224def: T_MType_acc_pat2 <M4_xor_or, or, xor>;
2225
2226class T_MType_acc_pat3 <InstHexagon MI, SDNode firstOp, SDNode secOp>
2227  : Pat <(i32 (secOp IntRegs:$src1, (firstOp IntRegs:$src2,
2228                                              (not IntRegs:$src3)))),
2229         (i32 (MI IntRegs:$src1, IntRegs:$src2, IntRegs:$src3))>;
2230
2231def: T_MType_acc_pat3 <M4_or_andn, and, or>;
2232def: T_MType_acc_pat3 <M4_and_andn, and, and>;
2233def: T_MType_acc_pat3 <M4_xor_andn, and, xor>;
2234
2235// Compound or-or and or-and
2236let isExtentSigned = 1, InputType = "imm", hasNewValue = 1, isExtendable = 1,
2237    opExtentBits = 10, opExtendable = 3 in
2238class T_CompOR <string mnemonic, bits<2> MajOp, SDNode OpNode>
2239  : MInst_acc <(outs IntRegs:$Rx),
2240               (ins IntRegs:$src1, IntRegs:$Rs, s10Ext:$s10),
2241  "$Rx |= "#mnemonic#"($Rs, #$s10)",
2242  [(set (i32 IntRegs:$Rx), (or (i32 IntRegs:$src1),
2243                           (OpNode (i32 IntRegs:$Rs), s32ImmPred:$s10)))],
2244  "$src1 = $Rx", ALU64_tc_2_SLOT23>, ImmRegRel {
2245    bits<5> Rx;
2246    bits<5> Rs;
2247    bits<10> s10;
2248
2249    let IClass = 0b1101;
2250
2251    let Inst{27-24} = 0b1010;
2252    let Inst{23-22} = MajOp;
2253    let Inst{20-16} = Rs;
2254    let Inst{21}    = s10{9};
2255    let Inst{13-5}  = s10{8-0};
2256    let Inst{4-0}   = Rx;
2257  }
2258
2259let CextOpcode = "ORr_ANDr" in
2260def S4_or_andi : T_CompOR <"and", 0b00, and>;
2261
2262let CextOpcode = "ORr_ORr" in
2263def S4_or_ori : T_CompOR <"or", 0b10, or>;
2264
2265//    Modulo wrap
2266//        Rd=modwrap(Rs,Rt)
2267//    Round
2268//        Rd=cround(Rs,#u5)
2269//        Rd=cround(Rs,Rt)
2270//        Rd=round(Rs,#u5)[:sat]
2271//        Rd=round(Rs,Rt)[:sat]
2272//    Vector reduce add unsigned halfwords
2273//        Rd=vraddh(Rss,Rtt)
2274//    Vector add bytes
2275//        Rdd=vaddb(Rss,Rtt)
2276//    Vector conditional negate
2277//        Rdd=vcnegh(Rss,Rt)
2278//        Rxx+=vrcnegh(Rss,Rt)
2279//    Vector maximum bytes
2280//        Rdd=vmaxb(Rtt,Rss)
2281//    Vector reduce maximum halfwords
2282//        Rxx=vrmaxh(Rss,Ru)
2283//        Rxx=vrmaxuh(Rss,Ru)
2284//    Vector reduce maximum words
2285//        Rxx=vrmaxuw(Rss,Ru)
2286//        Rxx=vrmaxw(Rss,Ru)
2287//    Vector minimum bytes
2288//        Rdd=vminb(Rtt,Rss)
2289//    Vector reduce minimum halfwords
2290//        Rxx=vrminh(Rss,Ru)
2291//        Rxx=vrminuh(Rss,Ru)
2292//    Vector reduce minimum words
2293//        Rxx=vrminuw(Rss,Ru)
2294//        Rxx=vrminw(Rss,Ru)
2295//    Vector subtract bytes
2296//        Rdd=vsubb(Rss,Rtt)
2297
2298//===----------------------------------------------------------------------===//
2299// XTYPE/ALU -
2300//===----------------------------------------------------------------------===//
2301
2302//===----------------------------------------------------------------------===//
2303// XTYPE/BIT +
2304//===----------------------------------------------------------------------===//
2305
2306// Bit reverse
2307def S2_brevp : T_S2op_3 <"brev", 0b11, 0b110>;
2308
2309// Bit count
2310def S2_ct0p : T_COUNT_LEADING_64<"ct0", 0b111, 0b010>;
2311def S2_ct1p : T_COUNT_LEADING_64<"ct1", 0b111, 0b100>;
2312def S4_clbpnorm : T_COUNT_LEADING_64<"normamt", 0b011, 0b000>;
2313
2314def: Pat<(i32 (trunc (cttz (i64 DoubleRegs:$Rss)))),
2315         (S2_ct0p (i64 DoubleRegs:$Rss))>;
2316def: Pat<(i32 (trunc (cttz (not (i64 DoubleRegs:$Rss))))),
2317         (S2_ct1p (i64 DoubleRegs:$Rss))>;
2318
2319let hasSideEffects = 0, hasNewValue = 1 in
2320def S4_clbaddi : SInst<(outs IntRegs:$Rd), (ins IntRegs:$Rs, s6Imm:$s6),
2321    "$Rd = add(clb($Rs), #$s6)", [], "", S_2op_tc_2_SLOT23> {
2322  bits<5> Rs;
2323  bits<5> Rd;
2324  bits<6> s6;
2325  let IClass = 0b1000;
2326  let Inst{27-24} = 0b1100;
2327  let Inst{23-21} = 0b001;
2328  let Inst{20-16} = Rs;
2329  let Inst{13-8} = s6;
2330  let Inst{7-5} = 0b000;
2331  let Inst{4-0} = Rd;
2332}
2333
2334let hasSideEffects = 0, hasNewValue = 1 in
2335def S4_clbpaddi : SInst<(outs IntRegs:$Rd), (ins DoubleRegs:$Rs, s6Imm:$s6),
2336    "$Rd = add(clb($Rs), #$s6)", [], "", S_2op_tc_2_SLOT23> {
2337  bits<5> Rs;
2338  bits<5> Rd;
2339  bits<6> s6;
2340  let IClass = 0b1000;
2341  let Inst{27-24} = 0b1000;
2342  let Inst{23-21} = 0b011;
2343  let Inst{20-16} = Rs;
2344  let Inst{13-8} = s6;
2345  let Inst{7-5} = 0b010;
2346  let Inst{4-0} = Rd;
2347}
2348
2349
2350// Bit test/set/clear
2351def S4_ntstbit_i : T_TEST_BIT_IMM<"!tstbit", 0b001>;
2352def S4_ntstbit_r : T_TEST_BIT_REG<"!tstbit", 1>;
2353
2354let AddedComplexity = 20 in {   // Complexity greater than cmp reg-imm.
2355  def: Pat<(i1 (seteq (and (shl 1, u5ImmPred:$u5), (i32 IntRegs:$Rs)), 0)),
2356           (S4_ntstbit_i (i32 IntRegs:$Rs), u5ImmPred:$u5)>;
2357  def: Pat<(i1 (seteq (and (shl 1, (i32 IntRegs:$Rt)), (i32 IntRegs:$Rs)), 0)),
2358           (S4_ntstbit_r (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))>;
2359}
2360
2361// Add extra complexity to prefer these instructions over bitsset/bitsclr.
2362// The reason is that tstbit/ntstbit can be folded into a compound instruction:
2363//   if ([!]tstbit(...)) jump ...
2364let AddedComplexity = 100 in
2365def: Pat<(i1 (setne (and (i32 IntRegs:$Rs), (i32 Set5ImmPred:$u5)), (i32 0))),
2366         (S2_tstbit_i (i32 IntRegs:$Rs), (BITPOS32 Set5ImmPred:$u5))>;
2367
2368let AddedComplexity = 100 in
2369def: Pat<(i1 (seteq (and (i32 IntRegs:$Rs), (i32 Set5ImmPred:$u5)), (i32 0))),
2370         (S4_ntstbit_i (i32 IntRegs:$Rs), (BITPOS32 Set5ImmPred:$u5))>;
2371
2372def C4_nbitsset  : T_TEST_BITS_REG<"!bitsset", 0b01, 1>;
2373def C4_nbitsclr  : T_TEST_BITS_REG<"!bitsclr", 0b10, 1>;
2374def C4_nbitsclri : T_TEST_BITS_IMM<"!bitsclr", 0b10, 1>;
2375
2376// Do not increase complexity of these patterns. In the DAG, "cmp i8" may be
2377// represented as a compare against "value & 0xFF", which is an exact match
2378// for cmpb (same for cmph). The patterns below do not contain any additional
2379// complexity that would make them preferable, and if they were actually used
2380// instead of cmpb/cmph, they would result in a compare against register that
2381// is loaded with the byte/half mask (i.e. 0xFF or 0xFFFF).
2382def: Pat<(i1 (setne (and I32:$Rs, u6ImmPred:$u6), 0)),
2383         (C4_nbitsclri I32:$Rs, u6ImmPred:$u6)>;
2384def: Pat<(i1 (setne (and I32:$Rs, I32:$Rt), 0)),
2385         (C4_nbitsclr I32:$Rs, I32:$Rt)>;
2386def: Pat<(i1 (setne (and I32:$Rs, I32:$Rt), I32:$Rt)),
2387         (C4_nbitsset I32:$Rs, I32:$Rt)>;
2388
2389//===----------------------------------------------------------------------===//
2390// XTYPE/BIT -
2391//===----------------------------------------------------------------------===//
2392
2393//===----------------------------------------------------------------------===//
2394// XTYPE/MPY +
2395//===----------------------------------------------------------------------===//
2396
2397// Rd=add(#u6,mpyi(Rs,#U6)) -- Multiply by immed and add immed.
2398
2399let hasNewValue = 1, isExtendable = 1, opExtentBits = 6, opExtendable = 1 in
2400def M4_mpyri_addi : MInst<(outs IntRegs:$Rd),
2401  (ins u6Ext:$u6, IntRegs:$Rs, u6Imm:$U6),
2402  "$Rd = add(#$u6, mpyi($Rs, #$U6))" ,
2403  [(set (i32 IntRegs:$Rd),
2404        (add (mul (i32 IntRegs:$Rs), u6ImmPred:$U6),
2405             u32ImmPred:$u6))] ,"",ALU64_tc_3x_SLOT23> {
2406    bits<5> Rd;
2407    bits<6> u6;
2408    bits<5> Rs;
2409    bits<6> U6;
2410
2411    let IClass = 0b1101;
2412
2413    let Inst{27-24} = 0b1000;
2414    let Inst{23}    = U6{5};
2415    let Inst{22-21} = u6{5-4};
2416    let Inst{20-16} = Rs;
2417    let Inst{13}    = u6{3};
2418    let Inst{12-8}  = Rd;
2419    let Inst{7-5}   = u6{2-0};
2420    let Inst{4-0}   = U6{4-0};
2421  }
2422
2423// Rd=add(#u6,mpyi(Rs,Rt))
2424let CextOpcode = "ADD_MPY", InputType = "imm", hasNewValue = 1,
2425    isExtendable = 1, opExtentBits = 6, opExtendable = 1 in
2426def M4_mpyrr_addi : MInst <(outs IntRegs:$Rd),
2427  (ins u6Ext:$u6, IntRegs:$Rs, IntRegs:$Rt),
2428  "$Rd = add(#$u6, mpyi($Rs, $Rt))" ,
2429  [(set (i32 IntRegs:$Rd),
2430        (add (mul (i32 IntRegs:$Rs), (i32 IntRegs:$Rt)), u32ImmPred:$u6))],
2431  "", ALU64_tc_3x_SLOT23>, ImmRegRel {
2432    bits<5> Rd;
2433    bits<6> u6;
2434    bits<5> Rs;
2435    bits<5> Rt;
2436
2437    let IClass = 0b1101;
2438
2439    let Inst{27-23} = 0b01110;
2440    let Inst{22-21} = u6{5-4};
2441    let Inst{20-16} = Rs;
2442    let Inst{13}    = u6{3};
2443    let Inst{12-8}  = Rt;
2444    let Inst{7-5}   = u6{2-0};
2445    let Inst{4-0}   = Rd;
2446  }
2447
2448let hasNewValue = 1 in
2449class T_AddMpy <bit MajOp, PatLeaf ImmPred, dag ins>
2450  : ALU64Inst <(outs IntRegs:$dst), ins,
2451  "$dst = add($src1, mpyi("#!if(MajOp,"$src3, #$src2))",
2452                                      "#$src2, $src3))"),
2453  [(set (i32 IntRegs:$dst),
2454        (add (i32 IntRegs:$src1), (mul (i32 IntRegs:$src3), ImmPred:$src2)))],
2455  "", ALU64_tc_3x_SLOT23> {
2456    bits<5> dst;
2457    bits<5> src1;
2458    bits<8> src2;
2459    bits<5> src3;
2460
2461    let IClass = 0b1101;
2462
2463    bits<6> ImmValue = !if(MajOp, src2{5-0}, src2{7-2});
2464
2465    let Inst{27-24} = 0b1111;
2466    let Inst{23}    = MajOp;
2467    let Inst{22-21} = ImmValue{5-4};
2468    let Inst{20-16} = src3;
2469    let Inst{13}    = ImmValue{3};
2470    let Inst{12-8}  = dst;
2471    let Inst{7-5}   = ImmValue{2-0};
2472    let Inst{4-0}   = src1;
2473  }
2474
2475def M4_mpyri_addr_u2 : T_AddMpy<0b0, u6_2ImmPred,
2476                       (ins IntRegs:$src1, u6_2Imm:$src2, IntRegs:$src3)>;
2477
2478let isExtendable = 1, opExtentBits = 6, opExtendable = 3,
2479    CextOpcode = "ADD_MPY", InputType = "imm" in
2480def M4_mpyri_addr : T_AddMpy<0b1, u32ImmPred,
2481                    (ins IntRegs:$src1, IntRegs:$src3, u6Ext:$src2)>, ImmRegRel;
2482
2483// Rx=add(Ru,mpyi(Rx,Rs))
2484let CextOpcode = "ADD_MPY", InputType = "reg", hasNewValue = 1 in
2485def M4_mpyrr_addr: MInst_acc <(outs IntRegs:$Rx),
2486                              (ins IntRegs:$Ru, IntRegs:$_src_, IntRegs:$Rs),
2487  "$Rx = add($Ru, mpyi($_src_, $Rs))",
2488  [(set (i32 IntRegs:$Rx), (add (i32 IntRegs:$Ru),
2489                           (mul (i32 IntRegs:$_src_), (i32 IntRegs:$Rs))))],
2490  "$_src_ = $Rx", M_tc_3x_SLOT23>, ImmRegRel {
2491    bits<5> Rx;
2492    bits<5> Ru;
2493    bits<5> Rs;
2494
2495    let IClass = 0b1110;
2496
2497    let Inst{27-21} = 0b0011000;
2498    let Inst{12-8} = Rx;
2499    let Inst{4-0} = Ru;
2500    let Inst{20-16} = Rs;
2501  }
2502
2503
2504// Vector reduce multiply word by signed half (32x16)
2505//Rdd=vrmpyweh(Rss,Rtt)[:<<1]
2506def M4_vrmpyeh_s0 : T_M2_vmpy<"vrmpyweh", 0b010, 0b100, 0, 0, 0>;
2507def M4_vrmpyeh_s1 : T_M2_vmpy<"vrmpyweh", 0b110, 0b100, 1, 0, 0>;
2508
2509//Rdd=vrmpywoh(Rss,Rtt)[:<<1]
2510def M4_vrmpyoh_s0 : T_M2_vmpy<"vrmpywoh", 0b001, 0b010, 0, 0, 0>;
2511def M4_vrmpyoh_s1 : T_M2_vmpy<"vrmpywoh", 0b101, 0b010, 1, 0, 0>;
2512
2513//Rdd+=vrmpyweh(Rss,Rtt)[:<<1]
2514def M4_vrmpyeh_acc_s0: T_M2_vmpy_acc<"vrmpyweh", 0b001, 0b110, 0, 0>;
2515def M4_vrmpyeh_acc_s1: T_M2_vmpy_acc<"vrmpyweh", 0b101, 0b110, 1, 0>;
2516
2517//Rdd=vrmpywoh(Rss,Rtt)[:<<1]
2518def M4_vrmpyoh_acc_s0: T_M2_vmpy_acc<"vrmpywoh", 0b011, 0b110, 0, 0>;
2519def M4_vrmpyoh_acc_s1: T_M2_vmpy_acc<"vrmpywoh", 0b111, 0b110, 1, 0>;
2520
2521// Vector multiply halfwords, signed by unsigned
2522// Rdd=vmpyhsu(Rs,Rt)[:<<]:sat
2523def M2_vmpy2su_s0 : T_XTYPE_mpy64 < "vmpyhsu", 0b000, 0b111, 1, 0, 0>;
2524def M2_vmpy2su_s1 : T_XTYPE_mpy64 < "vmpyhsu", 0b100, 0b111, 1, 1, 0>;
2525
2526// Rxx+=vmpyhsu(Rs,Rt)[:<<1]:sat
2527def M2_vmac2su_s0 : T_XTYPE_mpy64_acc < "vmpyhsu", "+", 0b011, 0b101, 1, 0, 0>;
2528def M2_vmac2su_s1 : T_XTYPE_mpy64_acc < "vmpyhsu", "+", 0b111, 0b101, 1, 1, 0>;
2529
2530// Vector polynomial multiply halfwords
2531// Rdd=vpmpyh(Rs,Rt)
2532def M4_vpmpyh : T_XTYPE_mpy64 < "vpmpyh", 0b110, 0b111, 0, 0, 0>;
2533
2534// Rxx^=vpmpyh(Rs,Rt)
2535def M4_vpmpyh_acc : T_XTYPE_mpy64_acc < "vpmpyh", "^", 0b101, 0b111, 0, 0, 0>;
2536
2537// Polynomial multiply words
2538// Rdd=pmpyw(Rs,Rt)
2539def M4_pmpyw : T_XTYPE_mpy64 < "pmpyw", 0b010, 0b111, 0, 0, 0>;
2540
2541// Rxx^=pmpyw(Rs,Rt)
2542def M4_pmpyw_acc  : T_XTYPE_mpy64_acc < "pmpyw", "^", 0b001, 0b111, 0, 0, 0>;
2543
2544//===----------------------------------------------------------------------===//
2545// XTYPE/MPY -
2546//===----------------------------------------------------------------------===//
2547
2548//===----------------------------------------------------------------------===//
2549// ALU64/Vector compare
2550//===----------------------------------------------------------------------===//
2551//===----------------------------------------------------------------------===//
2552// Template class for vector compare
2553//===----------------------------------------------------------------------===//
2554
2555let hasSideEffects = 0 in
2556class T_vcmpImm <string Str, bits<2> cmpOp, bits<2> minOp, Operand ImmOprnd>
2557  : ALU64_rr <(outs PredRegs:$Pd),
2558              (ins DoubleRegs:$Rss, ImmOprnd:$Imm),
2559  "$Pd = "#Str#"($Rss, #$Imm)",
2560  [], "", ALU64_tc_2early_SLOT23> {
2561    bits<2> Pd;
2562    bits<5> Rss;
2563    bits<32> Imm;
2564    bits<8> ImmBits;
2565    let ImmBits{6-0} = Imm{6-0};
2566    let ImmBits{7} = !if (!eq(cmpOp,0b10), 0b0, Imm{7}); // 0 for vcmp[bhw].gtu
2567
2568    let IClass = 0b1101;
2569
2570    let Inst{27-24} = 0b1100;
2571    let Inst{22-21} = cmpOp;
2572    let Inst{20-16} = Rss;
2573    let Inst{12-5} = ImmBits;
2574    let Inst{4-3} = minOp;
2575    let Inst{1-0} = Pd;
2576  }
2577
2578// Vector compare bytes
2579def A4_vcmpbgt   : T_vcmp <"vcmpb.gt", 0b1010>;
2580def: T_vcmp_pat<A4_vcmpbgt, setgt, v8i8>;
2581
2582let AsmString = "$Pd = any8(vcmpb.eq($Rss, $Rtt))" in
2583def A4_vcmpbeq_any : T_vcmp <"any8(vcmpb.gt", 0b1000>;
2584
2585def A4_vcmpbeqi  : T_vcmpImm <"vcmpb.eq",  0b00, 0b00, u8Imm>;
2586def A4_vcmpbgti  : T_vcmpImm <"vcmpb.gt",  0b01, 0b00, s8Imm>;
2587def A4_vcmpbgtui : T_vcmpImm <"vcmpb.gtu", 0b10, 0b00, u7Imm>;
2588
2589// Vector compare halfwords
2590def A4_vcmpheqi  : T_vcmpImm <"vcmph.eq",  0b00, 0b01, s8Imm>;
2591def A4_vcmphgti  : T_vcmpImm <"vcmph.gt",  0b01, 0b01, s8Imm>;
2592def A4_vcmphgtui : T_vcmpImm <"vcmph.gtu", 0b10, 0b01, u7Imm>;
2593
2594// Vector compare words
2595def A4_vcmpweqi  : T_vcmpImm <"vcmpw.eq",  0b00, 0b10, s8Imm>;
2596def A4_vcmpwgti  : T_vcmpImm <"vcmpw.gt",  0b01, 0b10, s8Imm>;
2597def A4_vcmpwgtui : T_vcmpImm <"vcmpw.gtu", 0b10, 0b10, u7Imm>;
2598
2599//===----------------------------------------------------------------------===//
2600// XTYPE/SHIFT +
2601//===----------------------------------------------------------------------===//
2602// Shift by immediate and accumulate/logical.
2603// Rx=add(#u8,asl(Rx,#U5))  Rx=add(#u8,lsr(Rx,#U5))
2604// Rx=sub(#u8,asl(Rx,#U5))  Rx=sub(#u8,lsr(Rx,#U5))
2605// Rx=and(#u8,asl(Rx,#U5))  Rx=and(#u8,lsr(Rx,#U5))
2606// Rx=or(#u8,asl(Rx,#U5))   Rx=or(#u8,lsr(Rx,#U5))
2607let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8,
2608    hasNewValue = 1, opNewValue = 0 in
2609class T_S4_ShiftOperate<string MnOp, string MnSh, SDNode Op, SDNode Sh,
2610                        bit asl_lsr, bits<2> MajOp, InstrItinClass Itin>
2611  : MInst_acc<(outs IntRegs:$Rd), (ins u8Ext:$u8, IntRegs:$Rx, u5Imm:$U5),
2612      "$Rd = "#MnOp#"(#$u8, "#MnSh#"($Rx, #$U5))",
2613      [(set (i32 IntRegs:$Rd),
2614            (Op (Sh I32:$Rx, u5ImmPred:$U5), u32ImmPred:$u8))],
2615      "$Rd = $Rx", Itin> {
2616
2617  bits<5> Rd;
2618  bits<8> u8;
2619  bits<5> Rx;
2620  bits<5> U5;
2621
2622  let IClass = 0b1101;
2623  let Inst{27-24} = 0b1110;
2624  let Inst{23-21} = u8{7-5};
2625  let Inst{20-16} = Rd;
2626  let Inst{13} = u8{4};
2627  let Inst{12-8} = U5;
2628  let Inst{7-5} = u8{3-1};
2629  let Inst{4} = asl_lsr;
2630  let Inst{3} = u8{0};
2631  let Inst{2-1} = MajOp;
2632}
2633
2634multiclass T_ShiftOperate<string mnemonic, SDNode Op, bits<2> MajOp,
2635                          InstrItinClass Itin> {
2636  def _asl_ri : T_S4_ShiftOperate<mnemonic, "asl", Op, shl, 0, MajOp, Itin>;
2637  def _lsr_ri : T_S4_ShiftOperate<mnemonic, "lsr", Op, srl, 1, MajOp, Itin>;
2638}
2639
2640let AddedComplexity = 200 in {
2641  defm S4_addi : T_ShiftOperate<"add", add, 0b10, ALU64_tc_2_SLOT23>;
2642  defm S4_andi : T_ShiftOperate<"and", and, 0b00, ALU64_tc_2_SLOT23>;
2643}
2644
2645let AddedComplexity = 30 in
2646defm S4_ori  : T_ShiftOperate<"or",  or,  0b01, ALU64_tc_1_SLOT23>;
2647
2648defm S4_subi : T_ShiftOperate<"sub", sub, 0b11, ALU64_tc_1_SLOT23>;
2649
2650let AddedComplexity = 200 in {
2651  def: Pat<(add addrga:$addr, (shl I32:$src2, u5ImmPred:$src3)),
2652           (S4_addi_asl_ri addrga:$addr, IntRegs:$src2, u5ImmPred:$src3)>;
2653  def: Pat<(add addrga:$addr, (srl I32:$src2, u5ImmPred:$src3)),
2654           (S4_addi_lsr_ri addrga:$addr, IntRegs:$src2, u5ImmPred:$src3)>;
2655  def: Pat<(sub addrga:$addr, (shl I32:$src2, u5ImmPred:$src3)),
2656           (S4_subi_asl_ri addrga:$addr, IntRegs:$src2, u5ImmPred:$src3)>;
2657  def: Pat<(sub addrga:$addr, (srl I32:$src2, u5ImmPred:$src3)),
2658           (S4_subi_lsr_ri addrga:$addr, IntRegs:$src2, u5ImmPred:$src3)>;
2659}
2660
2661// Vector conditional negate
2662// Rdd=vcnegh(Rss,Rt)
2663let Defs = [USR_OVF], Itinerary = S_3op_tc_2_SLOT23 in
2664def S2_vcnegh   : T_S3op_shiftVect < "vcnegh",   0b11, 0b01>;
2665
2666// Rd=[cround|round](Rs,Rt)
2667let hasNewValue = 1, Itinerary = S_3op_tc_2_SLOT23 in {
2668  def A4_cround_rr    : T_S3op_3 < "cround", IntRegs, 0b11, 0b00>;
2669  def A4_round_rr     : T_S3op_3 < "round", IntRegs, 0b11, 0b10>;
2670}
2671
2672// Rd=round(Rs,Rt):sat
2673let hasNewValue = 1, Defs = [USR_OVF], Itinerary = S_3op_tc_2_SLOT23 in
2674def A4_round_rr_sat : T_S3op_3 < "round", IntRegs, 0b11, 0b11, 1>;
2675
2676// Rd=[cmpyiwh|cmpyrwh](Rss,Rt):<<1:rnd:sat
2677let Defs = [USR_OVF], Itinerary = S_3op_tc_3x_SLOT23 in {
2678  def M4_cmpyi_wh     : T_S3op_8<"cmpyiwh", 0b100, 1, 1, 1>;
2679  def M4_cmpyr_wh     : T_S3op_8<"cmpyrwh", 0b110, 1, 1, 1>;
2680}
2681
2682// Rdd=[add|sub](Rss,Rtt,Px):carry
2683let isPredicateLate = 1, hasSideEffects = 0 in
2684class T_S3op_carry <string mnemonic, bits<3> MajOp>
2685  : SInst < (outs DoubleRegs:$Rdd, PredRegs:$Px),
2686            (ins DoubleRegs:$Rss, DoubleRegs:$Rtt, PredRegs:$Pu),
2687  "$Rdd = "#mnemonic#"($Rss, $Rtt, $Pu):carry",
2688  [], "$Px = $Pu", S_3op_tc_1_SLOT23 > {
2689    bits<5> Rdd;
2690    bits<5> Rss;
2691    bits<5> Rtt;
2692    bits<2> Pu;
2693
2694    let IClass = 0b1100;
2695
2696    let Inst{27-24} = 0b0010;
2697    let Inst{23-21} = MajOp;
2698    let Inst{20-16} = Rss;
2699    let Inst{12-8}  = Rtt;
2700    let Inst{6-5}   = Pu;
2701    let Inst{4-0}   = Rdd;
2702  }
2703
2704def A4_addp_c : T_S3op_carry < "add", 0b110 >;
2705def A4_subp_c : T_S3op_carry < "sub", 0b111 >;
2706
2707let Itinerary = S_3op_tc_3_SLOT23, hasSideEffects = 0 in
2708class T_S3op_6 <string mnemonic, bits<3> MinOp, bit isUnsigned>
2709  : SInst <(outs DoubleRegs:$Rxx),
2710           (ins DoubleRegs:$dst2, DoubleRegs:$Rss, IntRegs:$Ru),
2711  "$Rxx = "#mnemonic#"($Rss, $Ru)" ,
2712  [] , "$dst2 = $Rxx"> {
2713    bits<5> Rxx;
2714    bits<5> Rss;
2715    bits<5> Ru;
2716
2717    let IClass = 0b1100;
2718
2719    let Inst{27-21} = 0b1011001;
2720    let Inst{20-16} = Rss;
2721    let Inst{13}    = isUnsigned;
2722    let Inst{12-8}  = Rxx;
2723    let Inst{7-5}   = MinOp;
2724    let Inst{4-0}   = Ru;
2725  }
2726
2727// Vector reduce maximum halfwords
2728// Rxx=vrmax[u]h(Rss,Ru)
2729def A4_vrmaxh  : T_S3op_6 < "vrmaxh",  0b001, 0>;
2730def A4_vrmaxuh : T_S3op_6 < "vrmaxuh", 0b001, 1>;
2731
2732// Vector reduce maximum words
2733// Rxx=vrmax[u]w(Rss,Ru)
2734def A4_vrmaxw  : T_S3op_6 < "vrmaxw",  0b010, 0>;
2735def A4_vrmaxuw : T_S3op_6 < "vrmaxuw", 0b010, 1>;
2736
2737// Vector reduce minimum halfwords
2738// Rxx=vrmin[u]h(Rss,Ru)
2739def A4_vrminh  : T_S3op_6 < "vrminh",  0b101, 0>;
2740def A4_vrminuh : T_S3op_6 < "vrminuh", 0b101, 1>;
2741
2742// Vector reduce minimum words
2743// Rxx=vrmin[u]w(Rss,Ru)
2744def A4_vrminw  : T_S3op_6 < "vrminw",  0b110, 0>;
2745def A4_vrminuw : T_S3op_6 < "vrminuw", 0b110, 1>;
2746
2747// Shift an immediate left by register amount.
2748let hasNewValue = 1, hasSideEffects = 0 in
2749def S4_lsli: SInst <(outs IntRegs:$Rd), (ins s6Imm:$s6, IntRegs:$Rt),
2750  "$Rd = lsl(#$s6, $Rt)" ,
2751  [(set (i32 IntRegs:$Rd), (shl s6ImmPred:$s6,
2752                                 (i32 IntRegs:$Rt)))],
2753  "", S_3op_tc_1_SLOT23> {
2754    bits<5> Rd;
2755    bits<6> s6;
2756    bits<5> Rt;
2757
2758    let IClass = 0b1100;
2759
2760    let Inst{27-22} = 0b011010;
2761    let Inst{20-16} = s6{5-1};
2762    let Inst{12-8}  = Rt;
2763    let Inst{7-6}   = 0b11;
2764    let Inst{4-0}   = Rd;
2765    let Inst{5}     = s6{0};
2766  }
2767
2768//===----------------------------------------------------------------------===//
2769// XTYPE/SHIFT -
2770//===----------------------------------------------------------------------===//
2771
2772//===----------------------------------------------------------------------===//
2773// MEMOP: Word, Half, Byte
2774//===----------------------------------------------------------------------===//
2775
2776def MEMOPIMM : SDNodeXForm<imm, [{
2777  // Call the transformation function XformM5ToU5Imm to get the negative
2778  // immediate's positive counterpart.
2779  int32_t imm = N->getSExtValue();
2780  return XformM5ToU5Imm(imm);
2781}]>;
2782
2783def MEMOPIMM_HALF : SDNodeXForm<imm, [{
2784  // -1 .. -31 represented as 65535..65515
2785  // assigning to a short restores our desired signed value.
2786  // Call the transformation function XformM5ToU5Imm to get the negative
2787  // immediate's positive counterpart.
2788  int16_t imm = N->getSExtValue();
2789  return XformM5ToU5Imm(imm);
2790}]>;
2791
2792def MEMOPIMM_BYTE : SDNodeXForm<imm, [{
2793  // -1 .. -31 represented as 255..235
2794  // assigning to a char restores our desired signed value.
2795  // Call the transformation function XformM5ToU5Imm to get the negative
2796  // immediate's positive counterpart.
2797  int8_t imm = N->getSExtValue();
2798  return XformM5ToU5Imm(imm);
2799}]>;
2800
2801def SETMEMIMM : SDNodeXForm<imm, [{
2802   // Return the bit position we will set [0-31].
2803   // As an SDNode.
2804   int32_t imm = N->getSExtValue();
2805   return XformMskToBitPosU5Imm(imm);
2806}]>;
2807
2808def CLRMEMIMM : SDNodeXForm<imm, [{
2809   // Return the bit position we will clear [0-31].
2810   // As an SDNode.
2811   // we bit negate the value first
2812   int32_t imm = ~(N->getSExtValue());
2813   return XformMskToBitPosU5Imm(imm);
2814}]>;
2815
2816def SETMEMIMM_SHORT : SDNodeXForm<imm, [{
2817   // Return the bit position we will set [0-15].
2818   // As an SDNode.
2819   int16_t imm = N->getSExtValue();
2820   return XformMskToBitPosU4Imm(imm);
2821}]>;
2822
2823def CLRMEMIMM_SHORT : SDNodeXForm<imm, [{
2824   // Return the bit position we will clear [0-15].
2825   // As an SDNode.
2826   // we bit negate the value first
2827   int16_t imm = ~(N->getSExtValue());
2828   return XformMskToBitPosU4Imm(imm);
2829}]>;
2830
2831def SETMEMIMM_BYTE : SDNodeXForm<imm, [{
2832   // Return the bit position we will set [0-7].
2833   // As an SDNode.
2834   int8_t imm =  N->getSExtValue();
2835   return XformMskToBitPosU3Imm(imm);
2836}]>;
2837
2838def CLRMEMIMM_BYTE : SDNodeXForm<imm, [{
2839   // Return the bit position we will clear [0-7].
2840   // As an SDNode.
2841   // we bit negate the value first
2842   int8_t imm = ~(N->getSExtValue());
2843   return XformMskToBitPosU3Imm(imm);
2844}]>;
2845
2846//===----------------------------------------------------------------------===//
2847// Template class for MemOp instructions with the register value.
2848//===----------------------------------------------------------------------===//
2849class MemOp_rr_base <string opc, bits<2> opcBits, Operand ImmOp,
2850                     string memOp, bits<2> memOpBits> :
2851      MEMInst_V4<(outs),
2852                 (ins IntRegs:$base, ImmOp:$offset, IntRegs:$delta),
2853                 opc#"($base+#$offset)"#memOp#"$delta",
2854                 []>,
2855                 Requires<[UseMEMOP]> {
2856
2857    bits<5> base;
2858    bits<5> delta;
2859    bits<32> offset;
2860    bits<6> offsetBits; // memb - u6:0 , memh - u6:1, memw - u6:2
2861
2862    let offsetBits = !if (!eq(opcBits, 0b00), offset{5-0},
2863                     !if (!eq(opcBits, 0b01), offset{6-1},
2864                     !if (!eq(opcBits, 0b10), offset{7-2},0)));
2865
2866    let opExtentAlign = opcBits;
2867    let IClass = 0b0011;
2868    let Inst{27-24} = 0b1110;
2869    let Inst{22-21} = opcBits;
2870    let Inst{20-16} = base;
2871    let Inst{13} = 0b0;
2872    let Inst{12-7} = offsetBits;
2873    let Inst{6-5} = memOpBits;
2874    let Inst{4-0} = delta;
2875}
2876
2877//===----------------------------------------------------------------------===//
2878// Template class for MemOp instructions with the immediate value.
2879//===----------------------------------------------------------------------===//
2880class MemOp_ri_base <string opc, bits<2> opcBits, Operand ImmOp,
2881                     string memOp, bits<2> memOpBits> :
2882      MEMInst_V4 <(outs),
2883                  (ins IntRegs:$base, ImmOp:$offset, u5Imm:$delta),
2884                  opc#"($base+#$offset)"#memOp#"#$delta"
2885                  #!if(memOpBits{1},")", ""), // clrbit, setbit - include ')'
2886                  []>,
2887                  Requires<[UseMEMOP]> {
2888
2889    bits<5> base;
2890    bits<5> delta;
2891    bits<32> offset;
2892    bits<6> offsetBits; // memb - u6:0 , memh - u6:1, memw - u6:2
2893
2894    let offsetBits = !if (!eq(opcBits, 0b00), offset{5-0},
2895                     !if (!eq(opcBits, 0b01), offset{6-1},
2896                     !if (!eq(opcBits, 0b10), offset{7-2},0)));
2897
2898    let opExtentAlign = opcBits;
2899    let IClass = 0b0011;
2900    let Inst{27-24} = 0b1111;
2901    let Inst{22-21} = opcBits;
2902    let Inst{20-16} = base;
2903    let Inst{13} = 0b0;
2904    let Inst{12-7} = offsetBits;
2905    let Inst{6-5} = memOpBits;
2906    let Inst{4-0} = delta;
2907}
2908
2909// multiclass to define MemOp instructions with register operand.
2910multiclass MemOp_rr<string opc, bits<2> opcBits, Operand ImmOp> {
2911  def L4_add#NAME : MemOp_rr_base <opc, opcBits, ImmOp, " += ", 0b00>; // add
2912  def L4_sub#NAME : MemOp_rr_base <opc, opcBits, ImmOp, " -= ", 0b01>; // sub
2913  def L4_and#NAME : MemOp_rr_base <opc, opcBits, ImmOp, " &= ", 0b10>; // and
2914  def L4_or#NAME  : MemOp_rr_base <opc, opcBits, ImmOp, " |= ", 0b11>; // or
2915}
2916
2917// multiclass to define MemOp instructions with immediate Operand.
2918multiclass MemOp_ri<string opc, bits<2> opcBits, Operand ImmOp> {
2919  def L4_iadd#NAME : MemOp_ri_base <opc, opcBits, ImmOp, " += ", 0b00 >;
2920  def L4_isub#NAME : MemOp_ri_base <opc, opcBits, ImmOp, " -= ", 0b01 >;
2921  def L4_iand#NAME : MemOp_ri_base<opc, opcBits, ImmOp, " = clrbit(", 0b10>;
2922  def L4_ior#NAME : MemOp_ri_base<opc, opcBits, ImmOp, " = setbit(", 0b11>;
2923}
2924
2925multiclass MemOp_base <string opc, bits<2> opcBits, Operand ImmOp> {
2926  defm _#NAME : MemOp_rr <opc, opcBits, ImmOp>;
2927  defm _#NAME : MemOp_ri <opc, opcBits, ImmOp>;
2928}
2929
2930// Define MemOp instructions.
2931let isExtendable = 1, opExtendable = 1, isExtentSigned = 0 in {
2932  let opExtentBits = 6, accessSize = ByteAccess in
2933  defm memopb_io : MemOp_base <"memb", 0b00, u6_0Ext>;
2934
2935  let opExtentBits = 7, accessSize = HalfWordAccess in
2936  defm memoph_io : MemOp_base <"memh", 0b01, u6_1Ext>;
2937
2938  let opExtentBits = 8, accessSize = WordAccess in
2939  defm memopw_io : MemOp_base <"memw", 0b10, u6_2Ext>;
2940}
2941
2942//===----------------------------------------------------------------------===//
2943// Multiclass to define 'Def Pats' for ALU operations on the memory
2944// Here value used for the ALU operation is an immediate value.
2945// mem[bh](Rs+#0) += #U5
2946// mem[bh](Rs+#u6) += #U5
2947//===----------------------------------------------------------------------===//
2948
2949multiclass MemOpi_u5Pats <PatFrag ldOp, PatFrag stOp, PatLeaf ImmPred,
2950                          InstHexagon MI, SDNode OpNode> {
2951  let AddedComplexity = 180 in
2952  def: Pat<(stOp (OpNode (ldOp IntRegs:$addr), u5ImmPred:$addend),
2953                  IntRegs:$addr),
2954            (MI IntRegs:$addr, 0, u5ImmPred:$addend)>;
2955
2956  let AddedComplexity = 190 in
2957  def: Pat<(stOp (OpNode (ldOp (add IntRegs:$base, ImmPred:$offset)),
2958                  u5ImmPred:$addend),
2959            (add IntRegs:$base, ImmPred:$offset)),
2960            (MI IntRegs:$base, ImmPred:$offset, u5ImmPred:$addend)>;
2961}
2962
2963multiclass MemOpi_u5ALUOp<PatFrag ldOp, PatFrag stOp, PatLeaf ImmPred,
2964                          InstHexagon addMI, InstHexagon subMI> {
2965  defm: MemOpi_u5Pats<ldOp, stOp, ImmPred, addMI, add>;
2966  defm: MemOpi_u5Pats<ldOp, stOp, ImmPred, subMI, sub>;
2967}
2968
2969multiclass MemOpi_u5ExtType<PatFrag ldOpByte, PatFrag ldOpHalf > {
2970  // Half Word
2971  defm: MemOpi_u5ALUOp <ldOpHalf, truncstorei16, u31_1ImmPred,
2972                        L4_iadd_memoph_io, L4_isub_memoph_io>;
2973  // Byte
2974  defm: MemOpi_u5ALUOp <ldOpByte, truncstorei8, u32ImmPred,
2975                        L4_iadd_memopb_io, L4_isub_memopb_io>;
2976}
2977
2978let Predicates = [UseMEMOP] in {
2979  defm: MemOpi_u5ExtType<zextloadi8, zextloadi16>; // zero extend
2980  defm: MemOpi_u5ExtType<sextloadi8, sextloadi16>; // sign extend
2981  defm: MemOpi_u5ExtType<extloadi8,  extloadi16>;  // any extend
2982
2983  // Word
2984  defm: MemOpi_u5ALUOp <load, store, u30_2ImmPred, L4_iadd_memopw_io,
2985                        L4_isub_memopw_io>;
2986}
2987
2988//===----------------------------------------------------------------------===//
2989// multiclass to define 'Def Pats' for ALU operations on the memory.
2990// Here value used for the ALU operation is a negative value.
2991// mem[bh](Rs+#0) += #m5
2992// mem[bh](Rs+#u6) += #m5
2993//===----------------------------------------------------------------------===//
2994
2995multiclass MemOpi_m5Pats <PatFrag ldOp, PatFrag stOp, PatLeaf ImmPred,
2996                          PatLeaf immPred, SDNodeXForm xformFunc,
2997                          InstHexagon MI> {
2998  let AddedComplexity = 190 in
2999  def: Pat<(stOp (add (ldOp IntRegs:$addr), immPred:$subend), IntRegs:$addr),
3000           (MI IntRegs:$addr, 0, (xformFunc immPred:$subend))>;
3001
3002  let AddedComplexity = 195 in
3003  def: Pat<(stOp (add (ldOp (add IntRegs:$base, ImmPred:$offset)),
3004                  immPred:$subend),
3005           (add IntRegs:$base, ImmPred:$offset)),
3006           (MI IntRegs:$base, ImmPred:$offset, (xformFunc immPred:$subend))>;
3007}
3008
3009multiclass MemOpi_m5ExtType<PatFrag ldOpByte, PatFrag ldOpHalf > {
3010  // Half Word
3011  defm: MemOpi_m5Pats <ldOpHalf, truncstorei16, u31_1ImmPred, m5HImmPred,
3012                       MEMOPIMM_HALF, L4_isub_memoph_io>;
3013  // Byte
3014  defm: MemOpi_m5Pats <ldOpByte, truncstorei8, u32ImmPred, m5BImmPred,
3015                       MEMOPIMM_BYTE, L4_isub_memopb_io>;
3016}
3017
3018let Predicates = [UseMEMOP] in {
3019  defm: MemOpi_m5ExtType<zextloadi8, zextloadi16>; // zero extend
3020  defm: MemOpi_m5ExtType<sextloadi8, sextloadi16>; // sign extend
3021  defm: MemOpi_m5ExtType<extloadi8,  extloadi16>;  // any extend
3022
3023  // Word
3024  defm: MemOpi_m5Pats <load, store, u30_2ImmPred, m5ImmPred,
3025                       MEMOPIMM, L4_isub_memopw_io>;
3026}
3027
3028//===----------------------------------------------------------------------===//
3029// Multiclass to define 'def Pats' for bit operations on the memory.
3030// mem[bhw](Rs+#0) = [clrbit|setbit](#U5)
3031// mem[bhw](Rs+#u6) = [clrbit|setbit](#U5)
3032//===----------------------------------------------------------------------===//
3033
3034multiclass MemOpi_bitPats <PatFrag ldOp, PatFrag stOp, PatLeaf immPred,
3035                     PatLeaf extPred, SDNodeXForm xformFunc, InstHexagon MI,
3036                     SDNode OpNode> {
3037
3038  // mem[bhw](Rs+#u6:[012]) = [clrbit|setbit](#U5)
3039  let AddedComplexity = 250 in
3040  def: Pat<(stOp (OpNode (ldOp (add IntRegs:$base, extPred:$offset)),
3041                  immPred:$bitend),
3042           (add IntRegs:$base, extPred:$offset)),
3043           (MI IntRegs:$base, extPred:$offset, (xformFunc immPred:$bitend))>;
3044
3045  // mem[bhw](Rs+#0) = [clrbit|setbit](#U5)
3046  let AddedComplexity = 225 in
3047  def: Pat<(stOp (OpNode (ldOp IntRegs:$addr), immPred:$bitend), IntRegs:$addr),
3048           (MI IntRegs:$addr, 0, (xformFunc immPred:$bitend))>;
3049}
3050
3051multiclass MemOpi_bitExtType<PatFrag ldOpByte, PatFrag ldOpHalf> {
3052  // Byte - clrbit
3053  defm: MemOpi_bitPats<ldOpByte, truncstorei8, Clr3ImmPred, u32ImmPred,
3054                       CLRMEMIMM_BYTE, L4_iand_memopb_io, and>;
3055  // Byte - setbit
3056  defm: MemOpi_bitPats<ldOpByte, truncstorei8, Set3ImmPred, u32ImmPred,
3057                       SETMEMIMM_BYTE, L4_ior_memopb_io, or>;
3058  // Half Word - clrbit
3059  defm: MemOpi_bitPats<ldOpHalf, truncstorei16, Clr4ImmPred, u31_1ImmPred,
3060                       CLRMEMIMM_SHORT, L4_iand_memoph_io, and>;
3061  // Half Word - setbit
3062  defm: MemOpi_bitPats<ldOpHalf, truncstorei16, Set4ImmPred, u31_1ImmPred,
3063                       SETMEMIMM_SHORT, L4_ior_memoph_io, or>;
3064}
3065
3066let Predicates = [UseMEMOP] in {
3067  // mem[bh](Rs+#0) = [clrbit|setbit](#U5)
3068  // mem[bh](Rs+#u6:[01]) = [clrbit|setbit](#U5)
3069  defm: MemOpi_bitExtType<zextloadi8, zextloadi16>; // zero extend
3070  defm: MemOpi_bitExtType<sextloadi8, sextloadi16>; // sign extend
3071  defm: MemOpi_bitExtType<extloadi8,  extloadi16>;  // any extend
3072
3073  // memw(Rs+#0) = [clrbit|setbit](#U5)
3074  // memw(Rs+#u6:2) = [clrbit|setbit](#U5)
3075  defm: MemOpi_bitPats<load, store, Clr5ImmPred, u30_2ImmPred, CLRMEMIMM,
3076                       L4_iand_memopw_io, and>;
3077  defm: MemOpi_bitPats<load, store, Set5ImmPred, u30_2ImmPred, SETMEMIMM,
3078                       L4_ior_memopw_io, or>;
3079}
3080
3081//===----------------------------------------------------------------------===//
3082// Multiclass to define 'def Pats' for ALU operations on the memory
3083// where addend is a register.
3084// mem[bhw](Rs+#0) [+-&|]= Rt
3085// mem[bhw](Rs+#U6:[012]) [+-&|]= Rt
3086//===----------------------------------------------------------------------===//
3087
3088multiclass MemOpr_Pats <PatFrag ldOp, PatFrag stOp, PatLeaf extPred,
3089                        InstHexagon MI, SDNode OpNode> {
3090  let AddedComplexity = 141 in
3091  // mem[bhw](Rs+#0) [+-&|]= Rt
3092  def: Pat<(stOp (OpNode (ldOp IntRegs:$addr), (i32 IntRegs:$addend)),
3093                 IntRegs:$addr),
3094           (MI IntRegs:$addr, 0, (i32 IntRegs:$addend))>;
3095
3096  // mem[bhw](Rs+#U6:[012]) [+-&|]= Rt
3097  let AddedComplexity = 150 in
3098  def: Pat<(stOp (OpNode (ldOp (add IntRegs:$base, extPred:$offset)),
3099                  (i32 IntRegs:$orend)),
3100           (add IntRegs:$base, extPred:$offset)),
3101           (MI IntRegs:$base, extPred:$offset, (i32 IntRegs:$orend))>;
3102}
3103
3104multiclass MemOPr_ALUOp<PatFrag ldOp, PatFrag stOp, PatLeaf extPred,
3105                        InstHexagon addMI, InstHexagon subMI,
3106                        InstHexagon andMI, InstHexagon orMI> {
3107  defm: MemOpr_Pats <ldOp, stOp, extPred, addMI, add>;
3108  defm: MemOpr_Pats <ldOp, stOp, extPred, subMI, sub>;
3109  defm: MemOpr_Pats <ldOp, stOp, extPred, andMI, and>;
3110  defm: MemOpr_Pats <ldOp, stOp, extPred, orMI,  or>;
3111}
3112
3113multiclass MemOPr_ExtType<PatFrag ldOpByte, PatFrag ldOpHalf > {
3114  // Half Word
3115  defm: MemOPr_ALUOp <ldOpHalf, truncstorei16, u31_1ImmPred,
3116                      L4_add_memoph_io, L4_sub_memoph_io,
3117                      L4_and_memoph_io, L4_or_memoph_io>;
3118  // Byte
3119  defm: MemOPr_ALUOp <ldOpByte, truncstorei8, u32ImmPred,
3120                      L4_add_memopb_io, L4_sub_memopb_io,
3121                      L4_and_memopb_io, L4_or_memopb_io>;
3122}
3123
3124// Define 'def Pats' for MemOps with register addend.
3125let Predicates = [UseMEMOP] in {
3126  // Byte, Half Word
3127  defm: MemOPr_ExtType<zextloadi8, zextloadi16>; // zero extend
3128  defm: MemOPr_ExtType<sextloadi8, sextloadi16>; // sign extend
3129  defm: MemOPr_ExtType<extloadi8,  extloadi16>;  // any extend
3130  // Word
3131  defm: MemOPr_ALUOp <load, store, u30_2ImmPred, L4_add_memopw_io,
3132                      L4_sub_memopw_io, L4_and_memopw_io, L4_or_memopw_io>;
3133}
3134
3135//===----------------------------------------------------------------------===//
3136// XTYPE/PRED +
3137//===----------------------------------------------------------------------===//
3138
3139// Hexagon V4 only supports these flavors of byte/half compare instructions:
3140// EQ/GT/GTU. Other flavors like GE/GEU/LT/LTU/LE/LEU are not supported by
3141// hardware. However, compiler can still implement these patterns through
3142// appropriate patterns combinations based on current implemented patterns.
3143// The implemented patterns are: EQ/GT/GTU.
3144// Missing patterns are: GE/GEU/LT/LTU/LE/LEU.
3145
3146// Following instruction is not being extended as it results into the
3147// incorrect code for negative numbers.
3148// Pd=cmpb.eq(Rs,#u8)
3149
3150// p=!cmp.eq(r1,#s10)
3151def C4_cmpneqi  : T_CMP <"cmp.eq",  0b00, 1, s10Ext>;
3152def C4_cmpltei  : T_CMP <"cmp.gt",  0b01, 1, s10Ext>;
3153def C4_cmplteui : T_CMP <"cmp.gtu", 0b10, 1, u9Ext>;
3154
3155def : T_CMP_pat <C4_cmpneqi,  setne,  s32ImmPred>;
3156def : T_CMP_pat <C4_cmpltei,  setle,  s32ImmPred>;
3157def : T_CMP_pat <C4_cmplteui, setule, u9ImmPred>;
3158
3159// rs <= rt -> !(rs > rt).
3160/*
3161def: Pat<(i1 (setle (i32 IntRegs:$src1), s32ImmPred:$src2)),
3162         (C2_not (C2_cmpgti IntRegs:$src1, s32ImmPred:$src2))>;
3163//         (C4_cmpltei IntRegs:$src1, s32ImmPred:$src2)>;
3164*/
3165// Map cmplt(Rs, Imm) -> !cmpgt(Rs, Imm-1).
3166def: Pat<(i1 (setlt (i32 IntRegs:$src1), s32ImmPred:$src2)),
3167         (C4_cmpltei IntRegs:$src1, (DEC_CONST_SIGNED s32ImmPred:$src2))>;
3168
3169// rs != rt -> !(rs == rt).
3170def: Pat<(i1 (setne (i32 IntRegs:$src1), s32ImmPred:$src2)),
3171         (C4_cmpneqi IntRegs:$src1, s32ImmPred:$src2)>;
3172
3173// SDNode for converting immediate C to C-1.
3174def DEC_CONST_BYTE : SDNodeXForm<imm, [{
3175   // Return the byte immediate const-1 as an SDNode.
3176   int32_t imm = N->getSExtValue();
3177   return XformU7ToU7M1Imm(imm);
3178}]>;
3179
3180// For the sequence
3181//   zext( setult ( and(Rs, 255), u8))
3182// Use the isdigit transformation below
3183
3184// Generate code of the form 'C2_muxii(cmpbgtui(Rdd, C-1),0,1)'
3185// for C code of the form r = ((c>='0') & (c<='9')) ? 1 : 0;.
3186// The isdigit transformation relies on two 'clever' aspects:
3187// 1) The data type is unsigned which allows us to eliminate a zero test after
3188//    biasing the expression by 48. We are depending on the representation of
3189//    the unsigned types, and semantics.
3190// 2) The front end has converted <= 9 into < 10 on entry to LLVM
3191//
3192// For the C code:
3193//   retval = ((c>='0') & (c<='9')) ? 1 : 0;
3194// The code is transformed upstream of llvm into
3195//   retval = (c-48) < 10 ? 1 : 0;
3196let AddedComplexity = 139 in
3197def: Pat<(i32 (zext (i1 (setult (i32 (and (i32 IntRegs:$src1), 255)),
3198                         u7StrictPosImmPred:$src2)))),
3199         (C2_muxii (A4_cmpbgtui IntRegs:$src1,
3200                    (DEC_CONST_BYTE u7StrictPosImmPred:$src2)),
3201          0, 1)>;
3202
3203//===----------------------------------------------------------------------===//
3204// XTYPE/PRED -
3205//===----------------------------------------------------------------------===//
3206
3207//===----------------------------------------------------------------------===//
3208// Multiclass for DeallocReturn
3209//===----------------------------------------------------------------------===//
3210class L4_RETURN<string mnemonic, bit isNot, bit isPredNew, bit isTak>
3211  : LD0Inst<(outs), (ins PredRegs:$src),
3212  !if(isNot, "if (!$src", "if ($src")#
3213  !if(isPredNew, ".new) ", ") ")#mnemonic#
3214  !if(isPredNew, #!if(isTak,":t", ":nt"),""),
3215  [], "", LD_tc_3or4stall_SLOT0> {
3216
3217    bits<2> src;
3218    let BaseOpcode = "L4_RETURN";
3219    let isPredicatedFalse = isNot;
3220    let isPredicatedNew = isPredNew;
3221    let isTaken = isTak;
3222    let IClass = 0b1001;
3223
3224    let Inst{27-16} = 0b011000011110;
3225
3226    let Inst{13} = isNot;
3227    let Inst{12} = isTak;
3228    let Inst{11} = isPredNew;
3229    let Inst{10} = 0b0;
3230    let Inst{9-8} = src;
3231    let Inst{4-0} = 0b11110;
3232  }
3233
3234// Produce all predicated forms, p, !p, p.new, !p.new, :t, :nt
3235multiclass L4_RETURN_PRED<string mnemonic, bit PredNot> {
3236  let isPredicated = 1 in {
3237    def _#NAME# : L4_RETURN <mnemonic, PredNot, 0, 1>;
3238    def _#NAME#new_pnt : L4_RETURN <mnemonic, PredNot, 1, 0>;
3239    def _#NAME#new_pt : L4_RETURN <mnemonic, PredNot, 1, 1>;
3240  }
3241}
3242
3243multiclass LD_MISC_L4_RETURN<string mnemonic> {
3244  let isBarrier = 1, isPredicable = 1 in
3245    def NAME : LD0Inst <(outs), (ins), mnemonic, [], "",
3246                        LD_tc_3or4stall_SLOT0> {
3247      let BaseOpcode = "L4_RETURN";
3248      let IClass = 0b1001;
3249      let Inst{27-16} = 0b011000011110;
3250      let Inst{13-10} = 0b0000;
3251      let Inst{4-0} = 0b11110;
3252    }
3253  defm t : L4_RETURN_PRED<mnemonic, 0 >;
3254  defm f : L4_RETURN_PRED<mnemonic, 1 >;
3255}
3256
3257let isReturn = 1, isTerminator = 1,
3258    Defs = [R29, R30, R31, PC], Uses = [R30], hasSideEffects = 0 in
3259defm L4_return: LD_MISC_L4_RETURN <"dealloc_return">, PredNewRel;
3260
3261// Restore registers and dealloc return function call.
3262let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1,
3263    Defs = [R29, R30, R31, PC], isPredicable = 0, isAsmParserOnly = 1 in {
3264  def RESTORE_DEALLOC_RET_JMP_V4 : T_JMP<"">;
3265}
3266
3267// Restore registers and dealloc frame before a tail call.
3268let isCall = 1, Defs = [R29, R30, R31, PC], isAsmParserOnly = 1 in {
3269  def RESTORE_DEALLOC_BEFORE_TAILCALL_V4 : T_Call<"">, PredRel;
3270}
3271
3272// Save registers function call.
3273let isCall = 1, Uses = [R29, R31], isAsmParserOnly = 1 in {
3274  def SAVE_REGISTERS_CALL_V4 : T_Call<"">, PredRel;
3275}
3276
3277//===----------------------------------------------------------------------===//
3278// Template class for non predicated store instructions with
3279// GP-Relative or absolute addressing.
3280//===----------------------------------------------------------------------===//
3281let hasSideEffects = 0, isPredicable = 1, isNVStorable = 1 in
3282class T_StoreAbsGP <string mnemonic, RegisterClass RC, Operand ImmOp,
3283                    bits<2>MajOp, Operand AddrOp, bit isAbs, bit isHalf>
3284  : STInst<(outs), (ins AddrOp:$addr, RC:$src),
3285  mnemonic # !if(isAbs, "(##", "(#")#"$addr) = $src"#!if(isHalf, ".h",""),
3286  [], "", V2LDST_tc_st_SLOT01> {
3287    bits<19> addr;
3288    bits<5> src;
3289    bits<16> offsetBits;
3290
3291    string ImmOpStr = !cast<string>(ImmOp);
3292    let offsetBits = !if (!eq(ImmOpStr, "u16_3Imm"), addr{18-3},
3293                     !if (!eq(ImmOpStr, "u16_2Imm"), addr{17-2},
3294                     !if (!eq(ImmOpStr, "u16_1Imm"), addr{16-1},
3295                                      /* u16_0Imm */ addr{15-0})));
3296    let IClass = 0b0100;
3297    let Inst{27} = 1;
3298    let Inst{26-25} = offsetBits{15-14};
3299    let Inst{24}    = 0b0;
3300    let Inst{23-22} = MajOp;
3301    let Inst{21}    = isHalf;
3302    let Inst{20-16} = offsetBits{13-9};
3303    let Inst{13}    = offsetBits{8};
3304    let Inst{12-8}  = src;
3305    let Inst{7-0}   = offsetBits{7-0};
3306  }
3307
3308//===----------------------------------------------------------------------===//
3309// Template class for predicated store instructions with
3310// GP-Relative or absolute addressing.
3311//===----------------------------------------------------------------------===//
3312let hasSideEffects = 0, isPredicated = 1, isNVStorable = 1, opExtentBits = 6,
3313    opExtendable = 1 in
3314class T_StoreAbs_Pred <string mnemonic, RegisterClass RC, bits<2> MajOp,
3315                       bit isHalf, bit isNot, bit isNew>
3316  : STInst<(outs), (ins PredRegs:$src1, u6Ext:$absaddr, RC: $src2),
3317  !if(isNot, "if (!$src1", "if ($src1")#!if(isNew, ".new) ",
3318  ") ")#mnemonic#"(#$absaddr) = $src2"#!if(isHalf, ".h",""),
3319  [], "", ST_tc_st_SLOT01>, AddrModeRel {
3320    bits<2> src1;
3321    bits<6> absaddr;
3322    bits<5> src2;
3323
3324    let isPredicatedNew = isNew;
3325    let isPredicatedFalse = isNot;
3326
3327    let IClass = 0b1010;
3328
3329    let Inst{27-24} = 0b1111;
3330    let Inst{23-22} = MajOp;
3331    let Inst{21}    = isHalf;
3332    let Inst{17-16} = absaddr{5-4};
3333    let Inst{13}    = isNew;
3334    let Inst{12-8}  = src2;
3335    let Inst{7}     = 0b1;
3336    let Inst{6-3}   = absaddr{3-0};
3337    let Inst{2}     = isNot;
3338    let Inst{1-0}   = src1;
3339  }
3340
3341//===----------------------------------------------------------------------===//
3342// Template class for predicated store instructions with absolute addressing.
3343//===----------------------------------------------------------------------===//
3344class T_StoreAbs <string mnemonic, RegisterClass RC, Operand ImmOp,
3345                 bits<2> MajOp, bit isHalf>
3346  : T_StoreAbsGP <mnemonic, RC, ImmOp, MajOp, u32Imm, 1, isHalf>,
3347                  AddrModeRel {
3348  string ImmOpStr = !cast<string>(ImmOp);
3349  let opExtentBits = !if (!eq(ImmOpStr, "u16_3Imm"), 19,
3350                     !if (!eq(ImmOpStr, "u16_2Imm"), 18,
3351                     !if (!eq(ImmOpStr, "u16_1Imm"), 17,
3352                                      /* u16_0Imm */ 16)));
3353
3354  let opExtentAlign = !if (!eq(ImmOpStr, "u16_3Imm"), 3,
3355                      !if (!eq(ImmOpStr, "u16_2Imm"), 2,
3356                      !if (!eq(ImmOpStr, "u16_1Imm"), 1,
3357                                       /* u16_0Imm */ 0)));
3358}
3359
3360//===----------------------------------------------------------------------===//
3361// Multiclass for store instructions with absolute addressing.
3362//===----------------------------------------------------------------------===//
3363let addrMode = Absolute, isExtended = 1 in
3364multiclass ST_Abs<string mnemonic, string CextOp, RegisterClass RC,
3365                  Operand ImmOp, bits<2> MajOp, bit isHalf = 0> {
3366  let CextOpcode = CextOp, BaseOpcode = CextOp#_abs in {
3367    let opExtendable = 0, isPredicable = 1 in
3368    def S2_#NAME#abs : T_StoreAbs <mnemonic, RC, ImmOp, MajOp, isHalf>;
3369
3370    // Predicated
3371    def S4_p#NAME#t_abs : T_StoreAbs_Pred<mnemonic, RC, MajOp, isHalf, 0, 0>;
3372    def S4_p#NAME#f_abs : T_StoreAbs_Pred<mnemonic, RC, MajOp, isHalf, 1, 0>;
3373
3374    // .new Predicated
3375    def S4_p#NAME#tnew_abs : T_StoreAbs_Pred<mnemonic, RC, MajOp, isHalf, 0, 1>;
3376    def S4_p#NAME#fnew_abs : T_StoreAbs_Pred<mnemonic, RC, MajOp, isHalf, 1, 1>;
3377  }
3378}
3379
3380//===----------------------------------------------------------------------===//
3381// Template class for non predicated new-value store instructions with
3382// GP-Relative or absolute addressing.
3383//===----------------------------------------------------------------------===//
3384let hasSideEffects = 0, isPredicable = 1, mayStore = 1, isNVStore = 1,
3385    isNewValue = 1, opNewValue = 1 in
3386class T_StoreAbsGP_NV <string mnemonic, Operand ImmOp, bits<2>MajOp, bit isAbs>
3387  : NVInst_V4<(outs), (ins u32Imm:$addr, IntRegs:$src),
3388  mnemonic # !if(isAbs, "(##", "(#")#"$addr) = $src.new",
3389  [], "", V2LDST_tc_st_SLOT0> {
3390    bits<19> addr;
3391    bits<3> src;
3392    bits<16> offsetBits;
3393
3394    string ImmOpStr = !cast<string>(ImmOp);
3395    let offsetBits = !if (!eq(ImmOpStr, "u16_3Imm"), addr{18-3},
3396                     !if (!eq(ImmOpStr, "u16_2Imm"), addr{17-2},
3397                     !if (!eq(ImmOpStr, "u16_1Imm"), addr{16-1},
3398                                      /* u16_0Imm */ addr{15-0})));
3399    let IClass = 0b0100;
3400
3401    let Inst{27} = 1;
3402    let Inst{26-25} = offsetBits{15-14};
3403    let Inst{24-21} = 0b0101;
3404    let Inst{20-16} = offsetBits{13-9};
3405    let Inst{13}    = offsetBits{8};
3406    let Inst{12-11} = MajOp;
3407    let Inst{10-8}  = src;
3408    let Inst{7-0}   = offsetBits{7-0};
3409  }
3410
3411//===----------------------------------------------------------------------===//
3412// Template class for predicated new-value store instructions with
3413// absolute addressing.
3414//===----------------------------------------------------------------------===//
3415let hasSideEffects = 0, isPredicated = 1, mayStore = 1, isNVStore = 1,
3416    isNewValue = 1, opNewValue = 2, opExtentBits = 6, opExtendable = 1 in
3417class T_StoreAbs_NV_Pred <string mnemonic, bits<2> MajOp, bit isNot, bit isNew>
3418  : NVInst_V4<(outs), (ins PredRegs:$src1, u6Ext:$absaddr, IntRegs:$src2),
3419  !if(isNot, "if (!$src1", "if ($src1")#!if(isNew, ".new) ",
3420  ") ")#mnemonic#"(#$absaddr) = $src2.new",
3421  [], "", ST_tc_st_SLOT0>, AddrModeRel {
3422    bits<2> src1;
3423    bits<6> absaddr;
3424    bits<3> src2;
3425
3426    let isPredicatedNew = isNew;
3427    let isPredicatedFalse = isNot;
3428
3429    let IClass = 0b1010;
3430
3431    let Inst{27-24} = 0b1111;
3432    let Inst{23-21} = 0b101;
3433    let Inst{17-16} = absaddr{5-4};
3434    let Inst{13}    = isNew;
3435    let Inst{12-11} = MajOp;
3436    let Inst{10-8}  = src2;
3437    let Inst{7}     = 0b1;
3438    let Inst{6-3}   = absaddr{3-0};
3439    let Inst{2}     = isNot;
3440    let Inst{1-0}   = src1;
3441}
3442
3443//===----------------------------------------------------------------------===//
3444// Template class for non-predicated new-value store instructions with
3445// absolute addressing.
3446//===----------------------------------------------------------------------===//
3447class T_StoreAbs_NV <string mnemonic, Operand ImmOp, bits<2> MajOp>
3448  : T_StoreAbsGP_NV <mnemonic, ImmOp, MajOp, 1>, AddrModeRel {
3449
3450  string ImmOpStr = !cast<string>(ImmOp);
3451  let opExtentBits = !if (!eq(ImmOpStr, "u16_3Imm"), 19,
3452                     !if (!eq(ImmOpStr, "u16_2Imm"), 18,
3453                     !if (!eq(ImmOpStr, "u16_1Imm"), 17,
3454                                      /* u16_0Imm */ 16)));
3455
3456  let opExtentAlign = !if (!eq(ImmOpStr, "u16_3Imm"), 3,
3457                      !if (!eq(ImmOpStr, "u16_2Imm"), 2,
3458                      !if (!eq(ImmOpStr, "u16_1Imm"), 1,
3459                                       /* u16_0Imm */ 0)));
3460}
3461
3462//===----------------------------------------------------------------------===//
3463// Multiclass for new-value store instructions with absolute addressing.
3464//===----------------------------------------------------------------------===//
3465let addrMode = Absolute, isExtended = 1  in
3466multiclass ST_Abs_NV <string mnemonic, string CextOp, Operand ImmOp,
3467                   bits<2> MajOp> {
3468  let CextOpcode = CextOp, BaseOpcode = CextOp#_abs in {
3469    let opExtendable = 0, isPredicable = 1 in
3470    def S2_#NAME#newabs : T_StoreAbs_NV <mnemonic, ImmOp, MajOp>;
3471
3472    // Predicated
3473    def S4_p#NAME#newt_abs  : T_StoreAbs_NV_Pred <mnemonic, MajOp, 0, 0>;
3474    def S4_p#NAME#newf_abs  : T_StoreAbs_NV_Pred <mnemonic, MajOp, 1, 0>;
3475
3476    // .new Predicated
3477    def S4_p#NAME#newtnew_abs : T_StoreAbs_NV_Pred <mnemonic, MajOp, 0, 1>;
3478    def S4_p#NAME#newfnew_abs : T_StoreAbs_NV_Pred <mnemonic, MajOp, 1, 1>;
3479  }
3480}
3481
3482//===----------------------------------------------------------------------===//
3483// Stores with absolute addressing
3484//===----------------------------------------------------------------------===//
3485let accessSize = ByteAccess in
3486defm storerb : ST_Abs    <"memb", "STrib", IntRegs, u16_0Imm, 0b00>,
3487               ST_Abs_NV <"memb", "STrib", u16_0Imm, 0b00>;
3488
3489let accessSize = HalfWordAccess in
3490defm storerh : ST_Abs    <"memh", "STrih", IntRegs, u16_1Imm, 0b01>,
3491               ST_Abs_NV <"memh", "STrih", u16_1Imm, 0b01>;
3492
3493let accessSize = WordAccess in
3494defm storeri : ST_Abs    <"memw", "STriw", IntRegs, u16_2Imm, 0b10>,
3495               ST_Abs_NV <"memw", "STriw", u16_2Imm, 0b10>;
3496
3497let isNVStorable = 0, accessSize = DoubleWordAccess in
3498defm storerd : ST_Abs <"memd", "STrid", DoubleRegs, u16_3Imm, 0b11>;
3499
3500let isNVStorable = 0, accessSize = HalfWordAccess in
3501defm storerf : ST_Abs <"memh", "STrif", IntRegs, u16_1Imm, 0b01, 1>;
3502
3503//===----------------------------------------------------------------------===//
3504// GP-relative stores.
3505// mem[bhwd](#global)=Rt
3506// Once predicated, these instructions map to absolute addressing mode.
3507// if ([!]Pv[.new]) mem[bhwd](##global)=Rt
3508//===----------------------------------------------------------------------===//
3509
3510let isAsmParserOnly = 1 in
3511class T_StoreGP <string mnemonic, string BaseOp, RegisterClass RC,
3512                 Operand ImmOp, bits<2> MajOp, bit isHalf = 0>
3513  : T_StoreAbsGP <mnemonic, RC, ImmOp, MajOp, globaladdress, 0, isHalf> {
3514    // Set BaseOpcode same as absolute addressing instructions so that
3515    // non-predicated GP-Rel instructions can have relate with predicated
3516    // Absolute instruction.
3517    let BaseOpcode = BaseOp#_abs;
3518  }
3519
3520let isAsmParserOnly = 1 in
3521multiclass ST_GP <string mnemonic, string BaseOp, Operand ImmOp,
3522                  bits<2> MajOp, bit isHalf = 0> {
3523  // Set BaseOpcode same as absolute addressing instructions so that
3524  // non-predicated GP-Rel instructions can have relate with predicated
3525  // Absolute instruction.
3526  let BaseOpcode = BaseOp#_abs in {
3527    def NAME#gp : T_StoreAbsGP <mnemonic, IntRegs, ImmOp, MajOp,
3528                                globaladdress, 0, isHalf>;
3529    // New-value store
3530    def NAME#newgp : T_StoreAbsGP_NV <mnemonic, ImmOp, MajOp, 0> ;
3531  }
3532}
3533
3534let accessSize = ByteAccess in
3535defm S2_storerb : ST_GP<"memb", "STrib", u16_0Imm, 0b00>, NewValueRel;
3536
3537let accessSize = HalfWordAccess in
3538defm S2_storerh : ST_GP<"memh", "STrih", u16_1Imm, 0b01>, NewValueRel;
3539
3540let accessSize = WordAccess in
3541defm S2_storeri : ST_GP<"memw", "STriw", u16_2Imm, 0b10>, NewValueRel;
3542
3543let isNVStorable = 0, accessSize = DoubleWordAccess in
3544def S2_storerdgp : T_StoreGP <"memd", "STrid", DoubleRegs,
3545                              u16_3Imm, 0b11>, PredNewRel;
3546
3547let isNVStorable = 0, accessSize = HalfWordAccess in
3548def S2_storerfgp : T_StoreGP <"memh", "STrif", IntRegs,
3549                              u16_1Imm, 0b01, 1>, PredNewRel;
3550
3551class Loada_pat<PatFrag Load, ValueType VT, PatFrag Addr, InstHexagon MI>
3552  : Pat<(VT (Load Addr:$addr)), (MI Addr:$addr)>;
3553
3554class Loadam_pat<PatFrag Load, ValueType VT, PatFrag Addr, PatFrag ValueMod,
3555                 InstHexagon MI>
3556  : Pat<(VT (Load Addr:$addr)), (ValueMod (MI Addr:$addr))>;
3557
3558class Storea_pat<PatFrag Store, PatFrag Value, PatFrag Addr, InstHexagon MI>
3559  : Pat<(Store Value:$val, Addr:$addr), (MI Addr:$addr, Value:$val)>;
3560
3561class Stoream_pat<PatFrag Store, PatFrag Value, PatFrag Addr, PatFrag ValueMod,
3562                  InstHexagon MI>
3563  : Pat<(Store Value:$val, Addr:$addr),
3564        (MI Addr:$addr, (ValueMod Value:$val))>;
3565
3566def: Storea_pat<SwapSt<atomic_store_8>,  I32, addrgp, S2_storerbgp>;
3567def: Storea_pat<SwapSt<atomic_store_16>, I32, addrgp, S2_storerhgp>;
3568def: Storea_pat<SwapSt<atomic_store_32>, I32, addrgp, S2_storerigp>;
3569def: Storea_pat<SwapSt<atomic_store_64>, I64, addrgp, S2_storerdgp>;
3570
3571let AddedComplexity = 100 in {
3572  def: Storea_pat<truncstorei8,  I32, addrgp, S2_storerbgp>;
3573  def: Storea_pat<truncstorei16, I32, addrgp, S2_storerhgp>;
3574  def: Storea_pat<store,         I32, addrgp, S2_storerigp>;
3575  def: Storea_pat<store,         I64, addrgp, S2_storerdgp>;
3576
3577  // Map from "i1 = constant<-1>; memw(CONST32(#foo)) = i1"
3578  //       to "r0 = 1; memw(#foo) = r0"
3579  let AddedComplexity = 100 in
3580  def: Pat<(store (i1 -1), (HexagonCONST32_GP tglobaladdr:$global)),
3581           (S2_storerbgp tglobaladdr:$global, (A2_tfrsi 1))>;
3582}
3583
3584//===----------------------------------------------------------------------===//
3585// Template class for non predicated load instructions with
3586// absolute addressing mode.
3587//===----------------------------------------------------------------------===//
3588let isPredicable = 1, hasSideEffects = 0 in
3589class T_LoadAbsGP <string mnemonic, RegisterClass RC, Operand ImmOp,
3590                   bits<3> MajOp, Operand AddrOp, bit isAbs>
3591  : LDInst <(outs RC:$dst), (ins AddrOp:$addr),
3592  "$dst = "#mnemonic# !if(isAbs, "(##", "(#")#"$addr)",
3593  [], "", V2LDST_tc_ld_SLOT01> {
3594    bits<5> dst;
3595    bits<19> addr;
3596    bits<16> offsetBits;
3597
3598    string ImmOpStr = !cast<string>(ImmOp);
3599    let offsetBits = !if (!eq(ImmOpStr, "u16_3Imm"), addr{18-3},
3600                     !if (!eq(ImmOpStr, "u16_2Imm"), addr{17-2},
3601                     !if (!eq(ImmOpStr, "u16_1Imm"), addr{16-1},
3602                                      /* u16_0Imm */ addr{15-0})));
3603
3604    let IClass = 0b0100;
3605
3606    let Inst{27}    = 0b1;
3607    let Inst{26-25} = offsetBits{15-14};
3608    let Inst{24}    = 0b1;
3609    let Inst{23-21} = MajOp;
3610    let Inst{20-16} = offsetBits{13-9};
3611    let Inst{13-5}  = offsetBits{8-0};
3612    let Inst{4-0}   = dst;
3613  }
3614
3615class T_LoadAbs <string mnemonic, RegisterClass RC, Operand ImmOp,
3616                 bits<3> MajOp>
3617  : T_LoadAbsGP <mnemonic, RC, ImmOp, MajOp, u32Imm, 1>, AddrModeRel {
3618
3619    string ImmOpStr = !cast<string>(ImmOp);
3620    let opExtentBits = !if (!eq(ImmOpStr, "u16_3Imm"), 19,
3621                       !if (!eq(ImmOpStr, "u16_2Imm"), 18,
3622                       !if (!eq(ImmOpStr, "u16_1Imm"), 17,
3623                                        /* u16_0Imm */ 16)));
3624
3625    let opExtentAlign = !if (!eq(ImmOpStr, "u16_3Imm"), 3,
3626                        !if (!eq(ImmOpStr, "u16_2Imm"), 2,
3627                        !if (!eq(ImmOpStr, "u16_1Imm"), 1,
3628                                        /* u16_0Imm */ 0)));
3629  }
3630
3631//===----------------------------------------------------------------------===//
3632// Template class for predicated load instructions with
3633// absolute addressing mode.
3634//===----------------------------------------------------------------------===//
3635let isPredicated = 1, opExtentBits = 6, opExtendable = 2 in
3636class T_LoadAbs_Pred <string mnemonic, RegisterClass RC, bits<3> MajOp,
3637                      bit isPredNot, bit isPredNew>
3638  : LDInst <(outs RC:$dst), (ins PredRegs:$src1, u6Ext:$absaddr),
3639  !if(isPredNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
3640  ") ")#"$dst = "#mnemonic#"(#$absaddr)">, AddrModeRel {
3641    bits<5> dst;
3642    bits<2> src1;
3643    bits<6> absaddr;
3644
3645    let isPredicatedNew = isPredNew;
3646    let isPredicatedFalse = isPredNot;
3647    let hasNewValue = !if (!eq(!cast<string>(RC), "DoubleRegs"), 0, 1);
3648
3649    let IClass = 0b1001;
3650
3651    let Inst{27-24} = 0b1111;
3652    let Inst{23-21} = MajOp;
3653    let Inst{20-16} = absaddr{5-1};
3654    let Inst{13} = 0b1;
3655    let Inst{12} = isPredNew;
3656    let Inst{11} = isPredNot;
3657    let Inst{10-9} = src1;
3658    let Inst{8} = absaddr{0};
3659    let Inst{7} = 0b1;
3660    let Inst{4-0} = dst;
3661  }
3662
3663//===----------------------------------------------------------------------===//
3664// Multiclass for the load instructions with absolute addressing mode.
3665//===----------------------------------------------------------------------===//
3666multiclass LD_Abs_Pred<string mnemonic, RegisterClass RC, bits<3> MajOp,
3667                       bit PredNot> {
3668  def _abs : T_LoadAbs_Pred <mnemonic, RC, MajOp, PredNot, 0>;
3669  // Predicate new
3670  def new_abs : T_LoadAbs_Pred <mnemonic, RC, MajOp, PredNot, 1>;
3671}
3672
3673let addrMode = Absolute, isExtended = 1 in
3674multiclass LD_Abs<string mnemonic, string CextOp, RegisterClass RC,
3675                  Operand ImmOp, bits<3> MajOp> {
3676  let CextOpcode = CextOp, BaseOpcode = CextOp#_abs in {
3677    let opExtendable = 1, isPredicable = 1 in
3678    def L4_#NAME#_abs: T_LoadAbs <mnemonic, RC, ImmOp, MajOp>;
3679
3680    // Predicated
3681    defm L4_p#NAME#t : LD_Abs_Pred<mnemonic, RC, MajOp, 0>;
3682    defm L4_p#NAME#f : LD_Abs_Pred<mnemonic, RC, MajOp, 1>;
3683  }
3684}
3685
3686let accessSize = ByteAccess, hasNewValue = 1 in {
3687  defm loadrb  : LD_Abs<"memb",  "LDrib",  IntRegs, u16_0Imm, 0b000>;
3688  defm loadrub : LD_Abs<"memub", "LDriub", IntRegs, u16_0Imm, 0b001>;
3689}
3690
3691let accessSize = HalfWordAccess, hasNewValue = 1 in {
3692  defm loadrh  : LD_Abs<"memh",  "LDrih",  IntRegs, u16_1Imm, 0b010>;
3693  defm loadruh : LD_Abs<"memuh", "LDriuh", IntRegs, u16_1Imm, 0b011>;
3694}
3695
3696let accessSize = WordAccess, hasNewValue = 1 in
3697defm loadri  : LD_Abs<"memw",  "LDriw",  IntRegs, u16_2Imm, 0b100>;
3698
3699let accessSize = DoubleWordAccess in
3700defm loadrd  : LD_Abs<"memd",  "LDrid", DoubleRegs, u16_3Imm, 0b110>;
3701
3702//===----------------------------------------------------------------------===//
3703// multiclass for load instructions with GP-relative addressing mode.
3704// Rx=mem[bhwd](##global)
3705// Once predicated, these instructions map to absolute addressing mode.
3706// if ([!]Pv[.new]) Rx=mem[bhwd](##global)
3707//===----------------------------------------------------------------------===//
3708
3709let isAsmParserOnly = 1 in
3710class T_LoadGP <string mnemonic, string BaseOp, RegisterClass RC, Operand ImmOp,
3711                bits<3> MajOp>
3712  : T_LoadAbsGP <mnemonic, RC, ImmOp, MajOp, globaladdress, 0>, PredNewRel {
3713    let BaseOpcode = BaseOp#_abs;
3714  }
3715
3716let accessSize = ByteAccess, hasNewValue = 1 in {
3717  def L2_loadrbgp  : T_LoadGP<"memb",  "LDrib",  IntRegs, u16_0Imm, 0b000>;
3718  def L2_loadrubgp : T_LoadGP<"memub", "LDriub", IntRegs, u16_0Imm, 0b001>;
3719}
3720
3721let accessSize = HalfWordAccess, hasNewValue = 1 in {
3722  def L2_loadrhgp  : T_LoadGP<"memh",  "LDrih",  IntRegs, u16_1Imm, 0b010>;
3723  def L2_loadruhgp : T_LoadGP<"memuh", "LDriuh", IntRegs, u16_1Imm, 0b011>;
3724}
3725
3726let accessSize = WordAccess, hasNewValue = 1 in
3727def L2_loadrigp  : T_LoadGP<"memw",  "LDriw",  IntRegs, u16_2Imm, 0b100>;
3728
3729let accessSize = DoubleWordAccess in
3730def L2_loadrdgp  : T_LoadGP<"memd", "LDrid", DoubleRegs, u16_3Imm, 0b110>;
3731
3732def: Loada_pat<atomic_load_8,  i32, addrgp, L2_loadrubgp>;
3733def: Loada_pat<atomic_load_16, i32, addrgp, L2_loadruhgp>;
3734def: Loada_pat<atomic_load_32, i32, addrgp, L2_loadrigp>;
3735def: Loada_pat<atomic_load_64, i64, addrgp, L2_loadrdgp>;
3736
3737// Map from Pd = load(globaladdress) -> Rd = memb(globaladdress), Pd = Rd
3738def: Loadam_pat<load, i1, addrga, I32toI1, L4_loadrub_abs>;
3739def: Loadam_pat<load, i1, addrgp, I32toI1, L2_loadrubgp>;
3740
3741def: Stoream_pat<store, I1, addrga, I1toI32, S2_storerbabs>;
3742def: Stoream_pat<store, I1, addrgp, I1toI32, S2_storerbgp>;
3743
3744// Map from load(globaladdress) -> mem[u][bhwd](#foo)
3745class LoadGP_pats <PatFrag ldOp, InstHexagon MI, ValueType VT = i32>
3746  : Pat <(VT (ldOp (HexagonCONST32_GP tglobaladdr:$global))),
3747         (VT (MI tglobaladdr:$global))>;
3748
3749let AddedComplexity = 100 in {
3750  def: LoadGP_pats <extloadi8, L2_loadrbgp>;
3751  def: LoadGP_pats <sextloadi8, L2_loadrbgp>;
3752  def: LoadGP_pats <zextloadi8, L2_loadrubgp>;
3753  def: LoadGP_pats <extloadi16, L2_loadrhgp>;
3754  def: LoadGP_pats <sextloadi16, L2_loadrhgp>;
3755  def: LoadGP_pats <zextloadi16, L2_loadruhgp>;
3756  def: LoadGP_pats <load, L2_loadrigp>;
3757  def: LoadGP_pats <load, L2_loadrdgp, i64>;
3758}
3759
3760// When the Interprocedural Global Variable optimizer realizes that a certain
3761// global variable takes only two constant values, it shrinks the global to
3762// a boolean. Catch those loads here in the following 3 patterns.
3763let AddedComplexity = 100 in {
3764  def: LoadGP_pats <extloadi1, L2_loadrubgp>;
3765  def: LoadGP_pats <zextloadi1, L2_loadrubgp>;
3766}
3767
3768// Transfer global address into a register
3769def: Pat<(HexagonCONST32 tglobaladdr:$Rs),      (A2_tfrsi s16Ext:$Rs)>;
3770def: Pat<(HexagonCONST32_GP tblockaddress:$Rs), (A2_tfrsi s16Ext:$Rs)>;
3771def: Pat<(HexagonCONST32_GP tglobaladdr:$Rs),   (A2_tfrsi s16Ext:$Rs)>;
3772
3773def: Pat<(i64 (ctlz I64:$src1)), (Zext64 (S2_cl0p I64:$src1))>;
3774def: Pat<(i64 (cttz I64:$src1)), (Zext64 (S2_ct0p I64:$src1))>;
3775
3776let AddedComplexity  = 30 in {
3777  def: Storea_pat<truncstorei8,  I32, u32ImmPred, S2_storerbabs>;
3778  def: Storea_pat<truncstorei16, I32, u32ImmPred, S2_storerhabs>;
3779  def: Storea_pat<store,         I32, u32ImmPred, S2_storeriabs>;
3780}
3781
3782let AddedComplexity  = 30 in {
3783  def: Loada_pat<load,        i32, u32ImmPred, L4_loadri_abs>;
3784  def: Loada_pat<sextloadi8,  i32, u32ImmPred, L4_loadrb_abs>;
3785  def: Loada_pat<zextloadi8,  i32, u32ImmPred, L4_loadrub_abs>;
3786  def: Loada_pat<sextloadi16, i32, u32ImmPred, L4_loadrh_abs>;
3787  def: Loada_pat<zextloadi16, i32, u32ImmPred, L4_loadruh_abs>;
3788}
3789
3790// Indexed store word - global address.
3791// memw(Rs+#u6:2)=#S8
3792let AddedComplexity = 100 in
3793def: Storex_add_pat<store, addrga, u6_2ImmPred, S4_storeiri_io>;
3794
3795// Load from a global address that has only one use in the current basic block.
3796let AddedComplexity = 100 in {
3797  def: Loada_pat<extloadi8,   i32, addrga, L4_loadrub_abs>;
3798  def: Loada_pat<sextloadi8,  i32, addrga, L4_loadrb_abs>;
3799  def: Loada_pat<zextloadi8,  i32, addrga, L4_loadrub_abs>;
3800
3801  def: Loada_pat<extloadi16,  i32, addrga, L4_loadruh_abs>;
3802  def: Loada_pat<sextloadi16, i32, addrga, L4_loadrh_abs>;
3803  def: Loada_pat<zextloadi16, i32, addrga, L4_loadruh_abs>;
3804
3805  def: Loada_pat<load,        i32, addrga, L4_loadri_abs>;
3806  def: Loada_pat<load,        i64, addrga, L4_loadrd_abs>;
3807}
3808
3809// Store to a global address that has only one use in the current basic block.
3810let AddedComplexity = 100 in {
3811  def: Storea_pat<truncstorei8,  I32, addrga, S2_storerbabs>;
3812  def: Storea_pat<truncstorei16, I32, addrga, S2_storerhabs>;
3813  def: Storea_pat<store,         I32, addrga, S2_storeriabs>;
3814  def: Storea_pat<store,         I64, addrga, S2_storerdabs>;
3815
3816  def: Stoream_pat<truncstorei32, I64, addrga, LoReg, S2_storeriabs>;
3817}
3818
3819// Map from Pd = load(globaladdress) -> Rd = memb(globaladdress), Pd = Rd
3820let AddedComplexity = 100 in
3821def : Pat <(i1 (load (HexagonCONST32_GP tglobaladdr:$global))),
3822           (i1 (C2_tfrrp (i32 (L2_loadrbgp tglobaladdr:$global))))>;
3823
3824// Transfer global address into a register
3825let isExtended = 1, opExtendable = 1, AddedComplexity=50, isMoveImm = 1,
3826isAsCheapAsAMove = 1, isReMaterializable = 1, isCodeGenOnly = 1 in
3827def TFRI_V4 : ALU32_ri<(outs IntRegs:$dst), (ins s16Ext:$src1),
3828           "$dst = #$src1",
3829           [(set IntRegs:$dst, (HexagonCONST32 tglobaladdr:$src1))]>;
3830
3831// Transfer a block address into a register
3832def : Pat<(HexagonCONST32_GP tblockaddress:$src1),
3833          (TFRI_V4 tblockaddress:$src1)>;
3834
3835let AddedComplexity = 50 in
3836def : Pat<(HexagonCONST32_GP tglobaladdr:$src1),
3837           (TFRI_V4 tglobaladdr:$src1)>;
3838
3839// i8/i16/i32 -> i64 loads
3840// We need a complexity of 120 here to override preceding handling of
3841// zextload.
3842let AddedComplexity = 120 in {
3843  def: Loadam_pat<extloadi8,   i64, addrga, Zext64, L4_loadrub_abs>;
3844  def: Loadam_pat<sextloadi8,  i64, addrga, Sext64, L4_loadrb_abs>;
3845  def: Loadam_pat<zextloadi8,  i64, addrga, Zext64, L4_loadrub_abs>;
3846
3847  def: Loadam_pat<extloadi16,  i64, addrga, Zext64, L4_loadruh_abs>;
3848  def: Loadam_pat<sextloadi16, i64, addrga, Sext64, L4_loadrh_abs>;
3849  def: Loadam_pat<zextloadi16, i64, addrga, Zext64, L4_loadruh_abs>;
3850
3851  def: Loadam_pat<extloadi32,  i64, addrga, Zext64, L4_loadri_abs>;
3852  def: Loadam_pat<sextloadi32, i64, addrga, Sext64, L4_loadri_abs>;
3853  def: Loadam_pat<zextloadi32, i64, addrga, Zext64, L4_loadri_abs>;
3854}
3855
3856let AddedComplexity = 100 in {
3857  def: Loada_pat<extloadi8,   i32, addrgp, L4_loadrub_abs>;
3858  def: Loada_pat<sextloadi8,  i32, addrgp, L4_loadrb_abs>;
3859  def: Loada_pat<zextloadi8,  i32, addrgp, L4_loadrub_abs>;
3860
3861  def: Loada_pat<extloadi16,  i32, addrgp, L4_loadruh_abs>;
3862  def: Loada_pat<sextloadi16, i32, addrgp, L4_loadrh_abs>;
3863  def: Loada_pat<zextloadi16, i32, addrgp, L4_loadruh_abs>;
3864
3865  def: Loada_pat<load,        i32, addrgp, L4_loadri_abs>;
3866  def: Loada_pat<load,        i64, addrgp, L4_loadrd_abs>;
3867}
3868
3869let AddedComplexity = 100 in {
3870  def: Storea_pat<truncstorei8,  I32, addrgp, S2_storerbabs>;
3871  def: Storea_pat<truncstorei16, I32, addrgp, S2_storerhabs>;
3872  def: Storea_pat<store,         I32, addrgp, S2_storeriabs>;
3873  def: Storea_pat<store,         I64, addrgp, S2_storerdabs>;
3874}
3875
3876def: Loada_pat<atomic_load_8,  i32, addrgp, L4_loadrub_abs>;
3877def: Loada_pat<atomic_load_16, i32, addrgp, L4_loadruh_abs>;
3878def: Loada_pat<atomic_load_32, i32, addrgp, L4_loadri_abs>;
3879def: Loada_pat<atomic_load_64, i64, addrgp, L4_loadrd_abs>;
3880
3881def: Storea_pat<SwapSt<atomic_store_8>,  I32, addrgp, S2_storerbabs>;
3882def: Storea_pat<SwapSt<atomic_store_16>, I32, addrgp, S2_storerhabs>;
3883def: Storea_pat<SwapSt<atomic_store_32>, I32, addrgp, S2_storeriabs>;
3884def: Storea_pat<SwapSt<atomic_store_64>, I64, addrgp, S2_storerdabs>;
3885
3886let Constraints = "@earlyclobber $dst" in
3887def Insert4 : PseudoM<(outs DoubleRegs:$dst), (ins IntRegs:$a, IntRegs:$b,
3888                                                   IntRegs:$c, IntRegs:$d),
3889  ".error \"Should never try to emit Insert4\"",
3890  [(set (i64 DoubleRegs:$dst),
3891        (or (or (or (shl (i64 (zext (i32 (and (i32 IntRegs:$b), (i32 65535))))),
3892                         (i32 16)),
3893                    (i64 (zext (i32 (and (i32 IntRegs:$a), (i32 65535)))))),
3894                (shl (i64 (anyext (i32 (and (i32 IntRegs:$c), (i32 65535))))),
3895                     (i32 32))),
3896            (shl (i64 (anyext (i32 IntRegs:$d))), (i32 48))))]>;
3897
3898//===----------------------------------------------------------------------===//
3899// :raw for of boundscheck:hi:lo insns
3900//===----------------------------------------------------------------------===//
3901
3902// A4_boundscheck_lo: Detect if a register is within bounds.
3903let hasSideEffects = 0 in
3904def A4_boundscheck_lo: ALU64Inst <
3905  (outs PredRegs:$Pd),
3906  (ins DoubleRegs:$Rss, DoubleRegs:$Rtt),
3907  "$Pd = boundscheck($Rss, $Rtt):raw:lo"> {
3908    bits<2> Pd;
3909    bits<5> Rss;
3910    bits<5> Rtt;
3911
3912    let IClass = 0b1101;
3913
3914    let Inst{27-23} = 0b00100;
3915    let Inst{13} = 0b1;
3916    let Inst{7-5} = 0b100;
3917    let Inst{1-0} = Pd;
3918    let Inst{20-16} = Rss;
3919    let Inst{12-8} = Rtt;
3920  }
3921
3922// A4_boundscheck_hi: Detect if a register is within bounds.
3923let hasSideEffects = 0 in
3924def A4_boundscheck_hi: ALU64Inst <
3925  (outs PredRegs:$Pd),
3926  (ins DoubleRegs:$Rss, DoubleRegs:$Rtt),
3927  "$Pd = boundscheck($Rss, $Rtt):raw:hi"> {
3928    bits<2> Pd;
3929    bits<5> Rss;
3930    bits<5> Rtt;
3931
3932    let IClass = 0b1101;
3933
3934    let Inst{27-23} = 0b00100;
3935    let Inst{13} = 0b1;
3936    let Inst{7-5} = 0b101;
3937    let Inst{1-0} = Pd;
3938    let Inst{20-16} = Rss;
3939    let Inst{12-8} = Rtt;
3940  }
3941
3942let hasSideEffects = 0, isAsmParserOnly = 1 in
3943def A4_boundscheck : MInst <
3944  (outs PredRegs:$Pd), (ins IntRegs:$Rs, DoubleRegs:$Rtt),
3945  "$Pd=boundscheck($Rs,$Rtt)">;
3946
3947// A4_tlbmatch: Detect if a VA/ASID matches a TLB entry.
3948let isPredicateLate = 1, hasSideEffects = 0 in
3949def A4_tlbmatch : ALU64Inst<(outs PredRegs:$Pd),
3950  (ins DoubleRegs:$Rs, IntRegs:$Rt),
3951  "$Pd = tlbmatch($Rs, $Rt)",
3952  [], "", ALU64_tc_2early_SLOT23> {
3953    bits<2> Pd;
3954    bits<5> Rs;
3955    bits<5> Rt;
3956
3957    let IClass = 0b1101;
3958    let Inst{27-23} = 0b00100;
3959    let Inst{20-16} = Rs;
3960    let Inst{13} = 0b1;
3961    let Inst{12-8} = Rt;
3962    let Inst{7-5} = 0b011;
3963    let Inst{1-0} = Pd;
3964  }
3965
3966// We need custom lowering of ISD::PREFETCH into HexagonISD::DCFETCH
3967// because the SDNode ISD::PREFETCH has properties MayLoad and MayStore.
3968// We don't really want either one here.
3969def SDTHexagonDCFETCH : SDTypeProfile<0, 2, [SDTCisPtrTy<0>,SDTCisInt<1>]>;
3970def HexagonDCFETCH : SDNode<"HexagonISD::DCFETCH", SDTHexagonDCFETCH,
3971                            [SDNPHasChain]>;
3972
3973// Use LD0Inst for dcfetch, but set "mayLoad" to 0 because this doesn't
3974// really do a load.
3975let hasSideEffects = 1, mayLoad = 0 in
3976def Y2_dcfetchbo : LD0Inst<(outs), (ins IntRegs:$Rs, u11_3Imm:$u11_3),
3977      "dcfetch($Rs + #$u11_3)",
3978      [(HexagonDCFETCH IntRegs:$Rs, u11_3ImmPred:$u11_3)],
3979      "", LD_tc_ld_SLOT0> {
3980  bits<5> Rs;
3981  bits<14> u11_3;
3982
3983  let IClass = 0b1001;
3984  let Inst{27-21} = 0b0100000;
3985  let Inst{20-16} = Rs;
3986  let Inst{13} = 0b0;
3987  let Inst{10-0} = u11_3{13-3};
3988}
3989
3990//===----------------------------------------------------------------------===//
3991// Compound instructions
3992//===----------------------------------------------------------------------===//
3993
3994let isBranch = 1, hasSideEffects = 0, isExtentSigned = 1,
3995    isPredicated = 1, isPredicatedNew = 1, isExtendable = 1,
3996    opExtentBits = 11, opExtentAlign = 2, opExtendable = 1,
3997    isTerminator = 1 in
3998class CJInst_tstbit_R0<string px, bit np, string tnt>
3999  : InstHexagon<(outs), (ins IntRegs:$Rs, brtarget:$r9_2),
4000  ""#px#" = tstbit($Rs, #0); if ("
4001    #!if(np, "!","")#""#px#".new) jump:"#tnt#" $r9_2",
4002  [], "", COMPOUND, TypeCOMPOUND>, OpcodeHexagon {
4003  bits<4> Rs;
4004  bits<11> r9_2;
4005
4006  // np: !p[01]
4007  let isPredicatedFalse = np;
4008  // tnt: Taken/Not Taken
4009  let isBrTaken = !if (!eq(tnt, "t"), "true", "false");
4010  let isTaken   = !if (!eq(tnt, "t"), 1, 0);
4011
4012  let IClass = 0b0001;
4013  let Inst{27-26} = 0b00;
4014  let Inst{25} = !if (!eq(px, "!p1"), 1,
4015                 !if (!eq(px,  "p1"), 1, 0));
4016  let Inst{24-23} = 0b11;
4017  let Inst{22} = np;
4018  let Inst{21-20} = r9_2{10-9};
4019  let Inst{19-16} = Rs;
4020  let Inst{13} = !if (!eq(tnt, "t"), 1, 0);
4021  let Inst{9-8} = 0b11;
4022  let Inst{7-1} = r9_2{8-2};
4023}
4024
4025let Defs = [PC, P0], Uses = [P0] in {
4026  def J4_tstbit0_tp0_jump_nt : CJInst_tstbit_R0<"p0", 0, "nt">;
4027  def J4_tstbit0_tp0_jump_t : CJInst_tstbit_R0<"p0", 0, "t">;
4028  def J4_tstbit0_fp0_jump_nt : CJInst_tstbit_R0<"p0", 1, "nt">;
4029  def J4_tstbit0_fp0_jump_t : CJInst_tstbit_R0<"p0", 1, "t">;
4030}
4031
4032let Defs = [PC, P1], Uses = [P1] in {
4033  def J4_tstbit0_tp1_jump_nt : CJInst_tstbit_R0<"p1", 0, "nt">;
4034  def J4_tstbit0_tp1_jump_t : CJInst_tstbit_R0<"p1", 0, "t">;
4035  def J4_tstbit0_fp1_jump_nt : CJInst_tstbit_R0<"p1", 1, "nt">;
4036  def J4_tstbit0_fp1_jump_t : CJInst_tstbit_R0<"p1", 1, "t">;
4037}
4038
4039
4040let isBranch = 1, hasSideEffects = 0,
4041    isExtentSigned = 1, isPredicated = 1, isPredicatedNew = 1,
4042    isExtendable = 1, opExtentBits = 11, opExtentAlign = 2,
4043    opExtendable = 2, isTerminator = 1 in
4044class CJInst_RR<string px, string op, bit np, string tnt>
4045  : InstHexagon<(outs), (ins IntRegs:$Rs, IntRegs:$Rt, brtarget:$r9_2),
4046  ""#px#" = cmp."#op#"($Rs, $Rt); if ("
4047   #!if(np, "!","")#""#px#".new) jump:"#tnt#" $r9_2",
4048  [], "", COMPOUND, TypeCOMPOUND>, OpcodeHexagon {
4049  bits<4> Rs;
4050  bits<4> Rt;
4051  bits<11> r9_2;
4052
4053  // np: !p[01]
4054  let isPredicatedFalse = np;
4055  // tnt: Taken/Not Taken
4056  let isBrTaken = !if (!eq(tnt, "t"), "true", "false");
4057  let isTaken   = !if (!eq(tnt, "t"), 1, 0);
4058
4059  let IClass = 0b0001;
4060  let Inst{27-23} = !if (!eq(op, "eq"),  0b01000,
4061                    !if (!eq(op, "gt"),  0b01001,
4062                    !if (!eq(op, "gtu"), 0b01010, 0)));
4063  let Inst{22} = np;
4064  let Inst{21-20} = r9_2{10-9};
4065  let Inst{19-16} = Rs;
4066  let Inst{13} = !if (!eq(tnt, "t"), 1, 0);
4067  // px: Predicate reg 0/1
4068  let Inst{12} = !if (!eq(px, "!p1"), 1,
4069                 !if (!eq(px,  "p1"), 1, 0));
4070  let Inst{11-8} = Rt;
4071  let Inst{7-1} = r9_2{8-2};
4072}
4073
4074// P[10] taken/not taken.
4075multiclass T_tnt_CJInst_RR<string op, bit np> {
4076  let Defs = [PC, P0], Uses = [P0] in {
4077    def NAME#p0_jump_nt : CJInst_RR<"p0", op, np, "nt">;
4078    def NAME#p0_jump_t : CJInst_RR<"p0", op, np, "t">;
4079  }
4080  let Defs = [PC, P1], Uses = [P1] in {
4081    def NAME#p1_jump_nt : CJInst_RR<"p1", op, np, "nt">;
4082    def NAME#p1_jump_t : CJInst_RR<"p1", op, np, "t">;
4083  }
4084}
4085// Predicate / !Predicate
4086multiclass T_pnp_CJInst_RR<string op>{
4087  defm J4_cmp#NAME#_t : T_tnt_CJInst_RR<op, 0>;
4088  defm J4_cmp#NAME#_f : T_tnt_CJInst_RR<op, 1>;
4089}
4090// TypeCJ Instructions compare RR and jump
4091defm eq : T_pnp_CJInst_RR<"eq">;
4092defm gt : T_pnp_CJInst_RR<"gt">;
4093defm gtu : T_pnp_CJInst_RR<"gtu">;
4094
4095let isBranch = 1, hasSideEffects = 0, isExtentSigned = 1,
4096    isPredicated = 1, isPredicatedNew = 1, isExtendable = 1, opExtentBits = 11,
4097    opExtentAlign = 2, opExtendable = 2, isTerminator = 1 in
4098class CJInst_RU5<string px, string op, bit np, string tnt>
4099  : InstHexagon<(outs), (ins IntRegs:$Rs, u5Imm:$U5, brtarget:$r9_2),
4100  ""#px#" = cmp."#op#"($Rs, #$U5); if ("
4101    #!if(np, "!","")#""#px#".new) jump:"#tnt#" $r9_2",
4102  [], "", COMPOUND, TypeCOMPOUND>, OpcodeHexagon {
4103  bits<4> Rs;
4104  bits<5> U5;
4105  bits<11> r9_2;
4106
4107  // np: !p[01]
4108  let isPredicatedFalse = np;
4109  // tnt: Taken/Not Taken
4110  let isBrTaken = !if (!eq(tnt, "t"), "true", "false");
4111  let isTaken   = !if (!eq(tnt, "t"), 1, 0);
4112
4113  let IClass = 0b0001;
4114  let Inst{27-26} = 0b00;
4115  // px: Predicate reg 0/1
4116  let Inst{25} = !if (!eq(px, "!p1"), 1,
4117                 !if (!eq(px,  "p1"), 1, 0));
4118  let Inst{24-23} = !if (!eq(op, "eq"),  0b00,
4119                    !if (!eq(op, "gt"),  0b01,
4120                    !if (!eq(op, "gtu"), 0b10, 0)));
4121  let Inst{22} = np;
4122  let Inst{21-20} = r9_2{10-9};
4123  let Inst{19-16} = Rs;
4124  let Inst{13} = !if (!eq(tnt, "t"), 1, 0);
4125  let Inst{12-8} = U5;
4126  let Inst{7-1} = r9_2{8-2};
4127}
4128// P[10] taken/not taken.
4129multiclass T_tnt_CJInst_RU5<string op, bit np> {
4130  let Defs = [PC, P0], Uses = [P0] in {
4131    def NAME#p0_jump_nt : CJInst_RU5<"p0", op, np, "nt">;
4132    def NAME#p0_jump_t : CJInst_RU5<"p0", op, np, "t">;
4133  }
4134  let Defs = [PC, P1], Uses = [P1] in {
4135    def NAME#p1_jump_nt : CJInst_RU5<"p1", op, np, "nt">;
4136    def NAME#p1_jump_t : CJInst_RU5<"p1", op, np, "t">;
4137  }
4138}
4139// Predicate / !Predicate
4140multiclass T_pnp_CJInst_RU5<string op>{
4141  defm J4_cmp#NAME#i_t : T_tnt_CJInst_RU5<op, 0>;
4142  defm J4_cmp#NAME#i_f : T_tnt_CJInst_RU5<op, 1>;
4143}
4144// TypeCJ Instructions compare RI and jump
4145defm eq : T_pnp_CJInst_RU5<"eq">;
4146defm gt : T_pnp_CJInst_RU5<"gt">;
4147defm gtu : T_pnp_CJInst_RU5<"gtu">;
4148
4149let isBranch = 1, hasSideEffects = 0, isExtentSigned = 1,
4150    isPredicated = 1, isPredicatedFalse = 1, isPredicatedNew = 1,
4151    isExtendable = 1, opExtentBits = 11, opExtentAlign = 2, opExtendable = 1,
4152    isTerminator = 1 in
4153class CJInst_Rn1<string px, string op, bit np, string tnt>
4154  : InstHexagon<(outs), (ins IntRegs:$Rs, brtarget:$r9_2),
4155  ""#px#" = cmp."#op#"($Rs,#-1); if ("
4156  #!if(np, "!","")#""#px#".new) jump:"#tnt#" $r9_2",
4157  [], "", COMPOUND, TypeCOMPOUND>, OpcodeHexagon {
4158  bits<4> Rs;
4159  bits<11> r9_2;
4160
4161  // np: !p[01]
4162  let isPredicatedFalse = np;
4163  // tnt: Taken/Not Taken
4164  let isBrTaken = !if (!eq(tnt, "t"), "true", "false");
4165  let isTaken   = !if (!eq(tnt, "t"), 1, 0);
4166
4167  let IClass = 0b0001;
4168  let Inst{27-26} = 0b00;
4169  let Inst{25} = !if (!eq(px, "!p1"), 1,
4170                 !if (!eq(px,  "p1"), 1, 0));
4171
4172  let Inst{24-23} = 0b11;
4173  let Inst{22} = np;
4174  let Inst{21-20} = r9_2{10-9};
4175  let Inst{19-16} = Rs;
4176  let Inst{13} = !if (!eq(tnt, "t"), 1, 0);
4177  let Inst{9-8} = !if (!eq(op, "eq"),  0b00,
4178                  !if (!eq(op, "gt"),  0b01, 0));
4179  let Inst{7-1} = r9_2{8-2};
4180}
4181
4182// P[10] taken/not taken.
4183multiclass T_tnt_CJInst_Rn1<string op, bit np> {
4184  let Defs = [PC, P0], Uses = [P0] in {
4185    def NAME#p0_jump_nt : CJInst_Rn1<"p0", op, np, "nt">;
4186    def NAME#p0_jump_t : CJInst_Rn1<"p0", op, np, "t">;
4187  }
4188  let Defs = [PC, P1], Uses = [P1] in {
4189    def NAME#p1_jump_nt : CJInst_Rn1<"p1", op, np, "nt">;
4190    def NAME#p1_jump_t : CJInst_Rn1<"p1", op, np, "t">;
4191  }
4192}
4193// Predicate / !Predicate
4194multiclass T_pnp_CJInst_Rn1<string op>{
4195  defm J4_cmp#NAME#n1_t : T_tnt_CJInst_Rn1<op, 0>;
4196  defm J4_cmp#NAME#n1_f : T_tnt_CJInst_Rn1<op, 1>;
4197}
4198// TypeCJ Instructions compare -1 and jump
4199defm eq : T_pnp_CJInst_Rn1<"eq">;
4200defm gt : T_pnp_CJInst_Rn1<"gt">;
4201
4202// J4_jumpseti: Direct unconditional jump and set register to immediate.
4203let Defs = [PC], isBranch = 1, hasSideEffects = 0, hasNewValue = 1,
4204    isExtentSigned = 1, opNewValue = 0, isExtendable = 1, opExtentBits = 11,
4205    opExtentAlign = 2, opExtendable = 2 in
4206def J4_jumpseti: CJInst <
4207  (outs IntRegs:$Rd),
4208  (ins u6Imm:$U6, brtarget:$r9_2),
4209  "$Rd = #$U6 ; jump $r9_2"> {
4210    bits<4> Rd;
4211    bits<6> U6;
4212    bits<11> r9_2;
4213
4214    let IClass = 0b0001;
4215    let Inst{27-24} = 0b0110;
4216    let Inst{21-20} = r9_2{10-9};
4217    let Inst{19-16} = Rd;
4218    let Inst{13-8} = U6;
4219    let Inst{7-1} = r9_2{8-2};
4220  }
4221
4222// J4_jumpsetr: Direct unconditional jump and transfer register.
4223let Defs = [PC], isBranch = 1, hasSideEffects = 0, hasNewValue = 1,
4224    isExtentSigned = 1, opNewValue = 0, isExtendable = 1, opExtentBits = 11,
4225    opExtentAlign = 2, opExtendable = 2 in
4226def J4_jumpsetr: CJInst <
4227  (outs IntRegs:$Rd),
4228  (ins IntRegs:$Rs, brtarget:$r9_2),
4229  "$Rd = $Rs ; jump $r9_2"> {
4230    bits<4> Rd;
4231    bits<4> Rs;
4232    bits<11> r9_2;
4233
4234    let IClass = 0b0001;
4235    let Inst{27-24} = 0b0111;
4236    let Inst{21-20} = r9_2{10-9};
4237    let Inst{11-8} = Rd;
4238    let Inst{19-16} = Rs;
4239    let Inst{7-1} = r9_2{8-2};
4240  }
4241