1234285Sdim//=- HexagonInstrInfoV4.td - Target Desc. for Hexagon Target -*- tablegen -*-=//
2234285Sdim//
3234285Sdim//                     The LLVM Compiler Infrastructure
4234285Sdim//
5234285Sdim// This file is distributed under the University of Illinois Open Source
6234285Sdim// License. See LICENSE.TXT for details.
7234285Sdim//
8234285Sdim//===----------------------------------------------------------------------===//
9234285Sdim//
10234285Sdim// This file describes the Hexagon V4 instructions in TableGen format.
11234285Sdim//
12234285Sdim//===----------------------------------------------------------------------===//
13234285Sdim
14239462Sdimlet neverHasSideEffects = 1 in
15249423Sdimclass T_Immext<dag ins> :
16249423Sdim  EXTENDERInst<(outs), ins, "immext(#$imm)", []>,
17249423Sdim  Requires<[HasV4T]>;
18239462Sdim
19249423Sdimdef IMMEXT_b : T_Immext<(ins brtarget:$imm)>;
20249423Sdimdef IMMEXT_c : T_Immext<(ins calltarget:$imm)>;
21249423Sdimdef IMMEXT_g : T_Immext<(ins globaladdress:$imm)>;
22249423Sdimdef IMMEXT_i : T_Immext<(ins u26_6Imm:$imm)>;
23249423Sdim
24249423Sdim// Fold (add (CONST32 tglobaladdr:$addr) <offset>) into a global address.
25249423Sdimdef FoldGlobalAddr : ComplexPattern<i32, 1, "foldGlobalAddress", [], []>;
26249423Sdim
27249423Sdim// Fold (add (CONST32_GP tglobaladdr:$addr) <offset>) into a global address.
28249423Sdimdef FoldGlobalAddrGP : ComplexPattern<i32, 1, "foldGlobalAddressGP", [], []>;
29249423Sdim
30249423Sdimdef NumUsesBelowThresCONST32 : PatFrag<(ops node:$addr),
31249423Sdim                                       (HexagonCONST32 node:$addr), [{
32249423Sdim  return hasNumUsesBelowThresGA(N->getOperand(0).getNode());
33249423Sdim}]>;
34249423Sdim
35234285Sdim// Hexagon V4 Architecture spec defines 8 instruction classes:
36234285Sdim// LD ST ALU32 XTYPE J JR MEMOP NV CR SYSTEM(system is not implemented in the
37234285Sdim// compiler)
38234285Sdim
39234285Sdim// LD Instructions:
40234285Sdim// ========================================
41234285Sdim// Loads (8/16/32/64 bit)
42234285Sdim// Deallocframe
43234285Sdim
44234285Sdim// ST Instructions:
45234285Sdim// ========================================
46234285Sdim// Stores (8/16/32/64 bit)
47234285Sdim// Allocframe
48234285Sdim
49234285Sdim// ALU32 Instructions:
50234285Sdim// ========================================
51234285Sdim// Arithmetic / Logical (32 bit)
52234285Sdim// Vector Halfword
53234285Sdim
54234285Sdim// XTYPE Instructions (32/64 bit):
55234285Sdim// ========================================
56234285Sdim// Arithmetic, Logical, Bit Manipulation
57234285Sdim// Multiply (Integer, Fractional, Complex)
58234285Sdim// Permute / Vector Permute Operations
59234285Sdim// Predicate Operations
60234285Sdim// Shift / Shift with Add/Sub/Logical
61234285Sdim// Vector Byte ALU
62234285Sdim// Vector Halfword (ALU, Shift, Multiply)
63234285Sdim// Vector Word (ALU, Shift)
64234285Sdim
65234285Sdim// J Instructions:
66234285Sdim// ========================================
67234285Sdim// Jump/Call PC-relative
68234285Sdim
69234285Sdim// JR Instructions:
70234285Sdim// ========================================
71234285Sdim// Jump/Call Register
72234285Sdim
73234285Sdim// MEMOP Instructions:
74234285Sdim// ========================================
75234285Sdim// Operation on memory (8/16/32 bit)
76234285Sdim
77234285Sdim// NV Instructions:
78234285Sdim// ========================================
79234285Sdim// New-value Jumps
80234285Sdim// New-value Stores
81234285Sdim
82234285Sdim// CR Instructions:
83234285Sdim// ========================================
84234285Sdim// Control-Register Transfers
85234285Sdim// Hardware Loop Setup
86234285Sdim// Predicate Logicals & Reductions
87234285Sdim
88234285Sdim// SYSTEM Instructions (not implemented in the compiler):
89234285Sdim// ========================================
90234285Sdim// Prefetch
91234285Sdim// Cache Maintenance
92234285Sdim// Bus Operations
93234285Sdim
94234285Sdim
95234285Sdim//===----------------------------------------------------------------------===//
96234285Sdim// ALU32 +
97234285Sdim//===----------------------------------------------------------------------===//
98249423Sdim// Generate frame index addresses.
99249423Sdimlet neverHasSideEffects = 1, isReMaterializable = 1,
100249423SdimisExtended = 1, opExtendable = 2, validSubTargets = HasV4SubT in
101249423Sdimdef TFR_FI_immext_V4 : ALU32_ri<(outs IntRegs:$dst),
102249423Sdim            (ins IntRegs:$src1, s32Imm:$offset),
103249423Sdim            "$dst = add($src1, ##$offset)",
104234285Sdim            []>,
105234285Sdim            Requires<[HasV4T]>;
106234285Sdim
107249423Sdim// Rd=cmp.eq(Rs,#s8)
108249423Sdimlet validSubTargets = HasV4SubT, isExtendable = 1, opExtendable = 2,
109249423SdimisExtentSigned = 1, opExtentBits = 8 in
110249423Sdimdef V4_A4_rcmpeqi : ALU32_ri<(outs IntRegs:$Rd),
111249423Sdim                    (ins IntRegs:$Rs, s8Ext:$s8),
112249423Sdim                    "$Rd = cmp.eq($Rs, #$s8)",
113249423Sdim                    [(set (i32 IntRegs:$Rd),
114249423Sdim                          (i32 (zext (i1 (seteq (i32 IntRegs:$Rs),
115249423Sdim                                                s8ExtPred:$s8)))))]>,
116249423Sdim                    Requires<[HasV4T]>;
117234285Sdim
118249423Sdim// Preserve the TSTBIT generation
119249423Sdimdef : Pat <(i32 (zext (i1 (setne (i32 (and (i32 (shl 1, (i32 IntRegs:$src2))),
120249423Sdim                                           (i32 IntRegs:$src1))), 0)))),
121249423Sdim      (i32 (MUX_ii (i1 (TSTBIT_rr (i32 IntRegs:$src1), (i32 IntRegs:$src2))),
122249423Sdim                   1, 0))>;
123234285Sdim
124249423Sdim// Interfered with tstbit generation, above pattern preserves, see : tstbit.ll
125249423Sdim// Rd=cmp.ne(Rs,#s8)
126249423Sdimlet validSubTargets = HasV4SubT, isExtendable = 1, opExtendable = 2,
127249423SdimisExtentSigned = 1, opExtentBits = 8 in
128249423Sdimdef V4_A4_rcmpneqi : ALU32_ri<(outs IntRegs:$Rd),
129249423Sdim                     (ins IntRegs:$Rs, s8Ext:$s8),
130249423Sdim                     "$Rd = !cmp.eq($Rs, #$s8)",
131249423Sdim                     [(set (i32 IntRegs:$Rd),
132249423Sdim                           (i32 (zext (i1 (setne (i32 IntRegs:$Rs),
133249423Sdim                                                 s8ExtPred:$s8)))))]>,
134249423Sdim                     Requires<[HasV4T]>;
135234285Sdim
136249423Sdim// Rd=cmp.eq(Rs,Rt)
137249423Sdimlet validSubTargets = HasV4SubT in
138249423Sdimdef V4_A4_rcmpeq : ALU32_ri<(outs IntRegs:$Rd),
139249423Sdim                   (ins IntRegs:$Rs, IntRegs:$Rt),
140249423Sdim                   "$Rd = cmp.eq($Rs, $Rt)",
141249423Sdim                   [(set (i32 IntRegs:$Rd),
142249423Sdim                         (i32 (zext (i1 (seteq (i32 IntRegs:$Rs),
143249423Sdim                                               IntRegs:$Rt)))))]>,
144249423Sdim                   Requires<[HasV4T]>;
145234285Sdim
146249423Sdim// Rd=cmp.ne(Rs,Rt)
147249423Sdimlet validSubTargets = HasV4SubT in
148249423Sdimdef V4_A4_rcmpneq : ALU32_ri<(outs IntRegs:$Rd),
149249423Sdim                    (ins IntRegs:$Rs, IntRegs:$Rt),
150249423Sdim                    "$Rd = !cmp.eq($Rs, $Rt)",
151249423Sdim                    [(set (i32 IntRegs:$Rd),
152249423Sdim                          (i32 (zext (i1 (setne (i32 IntRegs:$Rs),
153249423Sdim                                               IntRegs:$Rt)))))]>,
154249423Sdim                    Requires<[HasV4T]>;
155234285Sdim
156234285Sdim//===----------------------------------------------------------------------===//
157234285Sdim// ALU32 -
158234285Sdim//===----------------------------------------------------------------------===//
159234285Sdim
160234285Sdim
161239462Sdim//===----------------------------------------------------------------------===//
162239462Sdim// ALU32/PERM +
163239462Sdim//===----------------------------------------------------------------------===//
164234285Sdim
165239462Sdim// Combine
166239462Sdim// Rdd=combine(Rs, #s8)
167249423Sdimlet isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8,
168249423Sdim    neverHasSideEffects = 1, validSubTargets = HasV4SubT in
169249423Sdimdef COMBINE_rI_V4 : ALU32_ri<(outs DoubleRegs:$dst),
170249423Sdim            (ins IntRegs:$src1, s8Ext:$src2),
171239462Sdim            "$dst = combine($src1, #$src2)",
172239462Sdim            []>,
173239462Sdim            Requires<[HasV4T]>;
174249423Sdim
175239462Sdim// Rdd=combine(#s8, Rs)
176249423Sdimlet isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 8,
177249423Sdim    neverHasSideEffects = 1, validSubTargets = HasV4SubT in
178249423Sdimdef COMBINE_Ir_V4 : ALU32_ir<(outs DoubleRegs:$dst),
179249423Sdim            (ins s8Ext:$src1, IntRegs:$src2),
180239462Sdim            "$dst = combine(#$src1, $src2)",
181239462Sdim            []>,
182239462Sdim            Requires<[HasV4T]>;
183249423Sdim
184249423Sdimdef HexagonWrapperCombineRI_V4 :
185249423Sdim  SDNode<"HexagonISD::WrapperCombineRI_V4", SDTHexagonI64I32I32>;
186249423Sdimdef HexagonWrapperCombineIR_V4 :
187249423Sdim  SDNode<"HexagonISD::WrapperCombineIR_V4", SDTHexagonI64I32I32>;
188249423Sdim
189249423Sdimdef : Pat <(HexagonWrapperCombineRI_V4 IntRegs:$r, s8ExtPred:$i),
190249423Sdim           (COMBINE_rI_V4 IntRegs:$r, s8ExtPred:$i)>,
191249423Sdim          Requires<[HasV4T]>;
192249423Sdim
193249423Sdimdef : Pat <(HexagonWrapperCombineIR_V4 s8ExtPred:$i, IntRegs:$r),
194249423Sdim           (COMBINE_Ir_V4 s8ExtPred:$i, IntRegs:$r)>,
195249423Sdim          Requires<[HasV4T]>;
196249423Sdim
197249423Sdimlet isExtendable = 1, opExtendable = 2, isExtentSigned = 0, opExtentBits = 6,
198249423Sdim    neverHasSideEffects = 1, validSubTargets = HasV4SubT in
199249423Sdimdef COMBINE_iI_V4 : ALU32_ii<(outs DoubleRegs:$dst),
200249423Sdim            (ins s8Imm:$src1, u6Ext:$src2),
201249423Sdim            "$dst = combine(#$src1, #$src2)",
202249423Sdim            []>,
203249423Sdim            Requires<[HasV4T]>;
204249423Sdim
205234285Sdim//===----------------------------------------------------------------------===//
206239462Sdim// ALU32/PERM +
207239462Sdim//===----------------------------------------------------------------------===//
208239462Sdim
209239462Sdim//===----------------------------------------------------------------------===//
210234285Sdim// LD +
211234285Sdim//===----------------------------------------------------------------------===//
212251662Sdim//===----------------------------------------------------------------------===//
213251662Sdim// Template class for load instructions with Absolute set addressing mode.
214251662Sdim//===----------------------------------------------------------------------===//
215249423Sdimlet isExtended = 1, opExtendable = 2, neverHasSideEffects = 1,
216263508SdimvalidSubTargets = HasV4SubT, addrMode = AbsoluteSet in
217251662Sdimclass T_LD_abs_set<string mnemonic, RegisterClass RC>:
218251662Sdim            LDInst2<(outs RC:$dst1, IntRegs:$dst2),
219249423Sdim            (ins u0AlwaysExt:$addr),
220251662Sdim            "$dst1 = "#mnemonic#"($dst2=##$addr)",
221239462Sdim            []>,
222239462Sdim            Requires<[HasV4T]>;
223239462Sdim
224251662Sdimdef LDrid_abs_set_V4  : T_LD_abs_set <"memd", DoubleRegs>;
225251662Sdimdef LDrib_abs_set_V4  : T_LD_abs_set <"memb", IntRegs>;
226251662Sdimdef LDriub_abs_set_V4 : T_LD_abs_set <"memub", IntRegs>;
227251662Sdimdef LDrih_abs_set_V4  : T_LD_abs_set <"memh", IntRegs>;
228251662Sdimdef LDriw_abs_set_V4  : T_LD_abs_set <"memw", IntRegs>;
229251662Sdimdef LDriuh_abs_set_V4 : T_LD_abs_set <"memuh", IntRegs>;
230239462Sdim
231239462Sdim
232249423Sdim// multiclass for load instructions with base + register offset
233249423Sdim// addressing mode
234249423Sdimmulticlass ld_idxd_shl_pbase<string mnemonic, RegisterClass RC, bit isNot,
235249423Sdim                             bit isPredNew> {
236251662Sdim  let isPredicatedNew = isPredNew in
237249423Sdim  def NAME : LDInst2<(outs RC:$dst),
238249423Sdim            (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$offset),
239249423Sdim            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
240249423Sdim            ") ")#"$dst = "#mnemonic#"($src2+$src3<<#$offset)",
241249423Sdim            []>, Requires<[HasV4T]>;
242249423Sdim}
243234285Sdim
244249423Sdimmulticlass ld_idxd_shl_pred<string mnemonic, RegisterClass RC, bit PredNot> {
245251662Sdim  let isPredicatedFalse = PredNot in {
246249423Sdim    defm _c#NAME : ld_idxd_shl_pbase<mnemonic, RC, PredNot, 0>;
247249423Sdim    // Predicate new
248249423Sdim    defm _cdn#NAME : ld_idxd_shl_pbase<mnemonic, RC, PredNot, 1>;
249249423Sdim  }
250249423Sdim}
251234285Sdim
252249423Sdimlet neverHasSideEffects  = 1 in
253249423Sdimmulticlass ld_idxd_shl<string mnemonic, string CextOp, RegisterClass RC> {
254249423Sdim  let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed_shl in {
255249423Sdim    let isPredicable = 1 in
256249423Sdim    def NAME#_V4 : LDInst2<(outs RC:$dst),
257249423Sdim            (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset),
258249423Sdim            "$dst = "#mnemonic#"($src1+$src2<<#$offset)",
259249423Sdim            []>, Requires<[HasV4T]>;
260234285Sdim
261249423Sdim    let isPredicated = 1 in {
262249423Sdim      defm Pt_V4 : ld_idxd_shl_pred<mnemonic, RC, 0 >;
263249423Sdim      defm NotPt_V4 : ld_idxd_shl_pred<mnemonic, RC, 1>;
264249423Sdim    }
265249423Sdim  }
266249423Sdim}
267234285Sdim
268249423Sdimlet addrMode = BaseRegOffset in {
269263508Sdim  let accessSize = ByteAccess in {
270263508Sdim    defm LDrib_indexed_shl: ld_idxd_shl<"memb", "LDrib", IntRegs>,
271263508Sdim                                        AddrModeRel;
272263508Sdim    defm LDriub_indexed_shl: ld_idxd_shl<"memub", "LDriub", IntRegs>,
273263508Sdim                                        AddrModeRel;
274263508Sdim  }
275263508Sdim  let accessSize = HalfWordAccess in {
276263508Sdim    defm LDrih_indexed_shl: ld_idxd_shl<"memh", "LDrih", IntRegs>, AddrModeRel;
277263508Sdim    defm LDriuh_indexed_shl: ld_idxd_shl<"memuh", "LDriuh", IntRegs>,
278263508Sdim                             AddrModeRel;
279263508Sdim  }
280263508Sdim  let accessSize = WordAccess in
281263508Sdim     defm LDriw_indexed_shl: ld_idxd_shl<"memw", "LDriw", IntRegs>, AddrModeRel;
282263508Sdim
283263508Sdim  let accessSize = DoubleWordAccess in
284263508Sdim    defm LDrid_indexed_shl: ld_idxd_shl<"memd", "LDrid", DoubleRegs>,
285263508Sdim                             AddrModeRel;
286249423Sdim}
287234285Sdim
288249423Sdim// 'def pats' for load instructions with base + register offset and non-zero
289249423Sdim// immediate value. Immediate value is used to left-shift the second
290249423Sdim// register operand.
291249423Sdimlet AddedComplexity = 40 in {
292249423Sdimdef : Pat <(i32 (sextloadi8 (add IntRegs:$src1,
293249423Sdim                                 (shl IntRegs:$src2, u2ImmPred:$offset)))),
294249423Sdim           (LDrib_indexed_shl_V4 IntRegs:$src1,
295249423Sdim            IntRegs:$src2, u2ImmPred:$offset)>,
296239462Sdim            Requires<[HasV4T]>;
297239462Sdim
298249423Sdimdef : Pat <(i32 (zextloadi8 (add IntRegs:$src1,
299249423Sdim                                 (shl IntRegs:$src2, u2ImmPred:$offset)))),
300249423Sdim           (LDriub_indexed_shl_V4 IntRegs:$src1,
301249423Sdim            IntRegs:$src2, u2ImmPred:$offset)>,
302234285Sdim            Requires<[HasV4T]>;
303234285Sdim
304249423Sdimdef : Pat <(i32 (extloadi8 (add IntRegs:$src1,
305249423Sdim                                (shl IntRegs:$src2, u2ImmPred:$offset)))),
306249423Sdim           (LDriub_indexed_shl_V4 IntRegs:$src1,
307249423Sdim            IntRegs:$src2, u2ImmPred:$offset)>,
308234285Sdim            Requires<[HasV4T]>;
309234285Sdim
310249423Sdimdef : Pat <(i32 (sextloadi16 (add IntRegs:$src1,
311249423Sdim                                  (shl IntRegs:$src2, u2ImmPred:$offset)))),
312249423Sdim           (LDrih_indexed_shl_V4 IntRegs:$src1,
313249423Sdim            IntRegs:$src2, u2ImmPred:$offset)>,
314234285Sdim            Requires<[HasV4T]>;
315234285Sdim
316249423Sdimdef : Pat <(i32 (zextloadi16 (add IntRegs:$src1,
317249423Sdim                                  (shl IntRegs:$src2, u2ImmPred:$offset)))),
318249423Sdim           (LDriuh_indexed_shl_V4 IntRegs:$src1,
319249423Sdim            IntRegs:$src2, u2ImmPred:$offset)>,
320234285Sdim            Requires<[HasV4T]>;
321234285Sdim
322249423Sdimdef : Pat <(i32 (extloadi16 (add IntRegs:$src1,
323249423Sdim                                 (shl IntRegs:$src2, u2ImmPred:$offset)))),
324249423Sdim           (LDriuh_indexed_shl_V4 IntRegs:$src1,
325249423Sdim            IntRegs:$src2, u2ImmPred:$offset)>,
326234285Sdim            Requires<[HasV4T]>;
327234285Sdim
328249423Sdimdef : Pat <(i32 (load (add IntRegs:$src1,
329249423Sdim                           (shl IntRegs:$src2, u2ImmPred:$offset)))),
330249423Sdim           (LDriw_indexed_shl_V4 IntRegs:$src1,
331249423Sdim            IntRegs:$src2, u2ImmPred:$offset)>,
332234285Sdim            Requires<[HasV4T]>;
333234285Sdim
334249423Sdimdef : Pat <(i64 (load (add IntRegs:$src1,
335249423Sdim                           (shl IntRegs:$src2, u2ImmPred:$offset)))),
336249423Sdim           (LDrid_indexed_shl_V4 IntRegs:$src1,
337249423Sdim            IntRegs:$src2, u2ImmPred:$offset)>,
338234285Sdim            Requires<[HasV4T]>;
339249423Sdim}
340234285Sdim
341234285Sdim
342249423Sdim// 'def pats' for load instruction base + register offset and
343249423Sdim// zero immediate value.
344249423Sdimlet AddedComplexity = 10 in {
345249423Sdimdef : Pat <(i64 (load (add IntRegs:$src1, IntRegs:$src2))),
346249423Sdim           (LDrid_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>,
347234285Sdim            Requires<[HasV4T]>;
348234285Sdim
349249423Sdimdef : Pat <(i32 (sextloadi8 (add IntRegs:$src1, IntRegs:$src2))),
350249423Sdim           (LDrib_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>,
351234285Sdim            Requires<[HasV4T]>;
352234285Sdim
353249423Sdimdef : Pat <(i32 (zextloadi8 (add IntRegs:$src1, IntRegs:$src2))),
354249423Sdim           (LDriub_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>,
355234285Sdim            Requires<[HasV4T]>;
356234285Sdim
357249423Sdimdef : Pat <(i32 (extloadi8 (add IntRegs:$src1, IntRegs:$src2))),
358249423Sdim           (LDriub_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>,
359234285Sdim            Requires<[HasV4T]>;
360234285Sdim
361249423Sdimdef : Pat <(i32 (sextloadi16 (add IntRegs:$src1, IntRegs:$src2))),
362249423Sdim           (LDrih_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>,
363239462Sdim            Requires<[HasV4T]>;
364239462Sdim
365249423Sdimdef : Pat <(i32 (zextloadi16 (add IntRegs:$src1, IntRegs:$src2))),
366249423Sdim           (LDriuh_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>,
367239462Sdim            Requires<[HasV4T]>;
368239462Sdim
369249423Sdimdef : Pat <(i32 (extloadi16 (add IntRegs:$src1, IntRegs:$src2))),
370249423Sdim           (LDriuh_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>,
371239462Sdim            Requires<[HasV4T]>;
372239462Sdim
373249423Sdimdef : Pat <(i32 (load (add IntRegs:$src1, IntRegs:$src2))),
374249423Sdim           (LDriw_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>,
375239462Sdim            Requires<[HasV4T]>;
376249423Sdim}
377239462Sdim
378249423Sdim// zext i1->i64
379249423Sdimdef : Pat <(i64 (zext (i1 PredRegs:$src1))),
380249423Sdim      (i64 (COMBINE_Ir_V4 0, (MUX_ii (i1 PredRegs:$src1), 1, 0)))>,
381249423Sdim      Requires<[HasV4T]>;
382239462Sdim
383249423Sdim// zext i32->i64
384249423Sdimdef : Pat <(i64 (zext (i32 IntRegs:$src1))),
385249423Sdim      (i64 (COMBINE_Ir_V4 0, (i32 IntRegs:$src1)))>,
386249423Sdim      Requires<[HasV4T]>;
387249423Sdim// zext i8->i64
388249423Sdimdef:  Pat <(i64 (zextloadi8 ADDRriS11_0:$src1)),
389249423Sdim      (i64 (COMBINE_Ir_V4 0, (LDriub ADDRriS11_0:$src1)))>,
390249423Sdim      Requires<[HasV4T]>;
391239462Sdim
392249423Sdimlet AddedComplexity = 20 in
393249423Sdimdef:  Pat <(i64 (zextloadi8 (add (i32 IntRegs:$src1),
394249423Sdim                                s11_0ExtPred:$offset))),
395249423Sdim      (i64 (COMBINE_Ir_V4 0, (LDriub_indexed IntRegs:$src1,
396249423Sdim                                  s11_0ExtPred:$offset)))>,
397249423Sdim      Requires<[HasV4T]>;
398239462Sdim
399249423Sdim// zext i1->i64
400249423Sdimdef:  Pat <(i64 (zextloadi1 ADDRriS11_0:$src1)),
401249423Sdim      (i64 (COMBINE_Ir_V4 0, (LDriub ADDRriS11_0:$src1)))>,
402249423Sdim      Requires<[HasV4T]>;
403239462Sdim
404249423Sdimlet AddedComplexity = 20 in
405249423Sdimdef:  Pat <(i64 (zextloadi1 (add (i32 IntRegs:$src1),
406249423Sdim                                s11_0ExtPred:$offset))),
407249423Sdim      (i64 (COMBINE_Ir_V4 0, (LDriub_indexed IntRegs:$src1,
408249423Sdim                                  s11_0ExtPred:$offset)))>,
409249423Sdim      Requires<[HasV4T]>;
410239462Sdim
411249423Sdim// zext i16->i64
412249423Sdimdef:  Pat <(i64 (zextloadi16 ADDRriS11_1:$src1)),
413249423Sdim      (i64 (COMBINE_Ir_V4 0, (LDriuh ADDRriS11_1:$src1)))>,
414249423Sdim      Requires<[HasV4T]>;
415239462Sdim
416249423Sdimlet AddedComplexity = 20 in
417249423Sdimdef:  Pat <(i64 (zextloadi16 (add (i32 IntRegs:$src1),
418249423Sdim                                  s11_1ExtPred:$offset))),
419249423Sdim      (i64 (COMBINE_Ir_V4 0, (LDriuh_indexed IntRegs:$src1,
420249423Sdim                                  s11_1ExtPred:$offset)))>,
421249423Sdim      Requires<[HasV4T]>;
422239462Sdim
423249423Sdim// anyext i16->i64
424249423Sdimdef:  Pat <(i64 (extloadi16 ADDRriS11_2:$src1)),
425249423Sdim      (i64 (COMBINE_Ir_V4 0, (LDrih ADDRriS11_2:$src1)))>,
426249423Sdim      Requires<[HasV4T]>;
427239462Sdim
428249423Sdimlet AddedComplexity = 20 in
429249423Sdimdef:  Pat <(i64 (extloadi16 (add (i32 IntRegs:$src1),
430249423Sdim                                  s11_1ExtPred:$offset))),
431249423Sdim      (i64 (COMBINE_Ir_V4 0, (LDrih_indexed IntRegs:$src1,
432249423Sdim                                  s11_1ExtPred:$offset)))>,
433249423Sdim      Requires<[HasV4T]>;
434239462Sdim
435249423Sdim// zext i32->i64
436249423Sdimdef:  Pat <(i64 (zextloadi32 ADDRriS11_2:$src1)),
437249423Sdim      (i64 (COMBINE_Ir_V4 0, (LDriw ADDRriS11_2:$src1)))>,
438249423Sdim      Requires<[HasV4T]>;
439239462Sdim
440239462Sdimlet AddedComplexity = 100 in
441249423Sdimdef:  Pat <(i64 (zextloadi32 (i32 (add IntRegs:$src1, s11_2ExtPred:$offset)))),
442249423Sdim      (i64 (COMBINE_Ir_V4 0, (LDriw_indexed IntRegs:$src1,
443249423Sdim                                  s11_2ExtPred:$offset)))>,
444249423Sdim      Requires<[HasV4T]>;
445239462Sdim
446249423Sdim// anyext i32->i64
447249423Sdimdef:  Pat <(i64 (extloadi32 ADDRriS11_2:$src1)),
448249423Sdim      (i64 (COMBINE_Ir_V4 0, (LDriw ADDRriS11_2:$src1)))>,
449249423Sdim      Requires<[HasV4T]>;
450239462Sdim
451239462Sdimlet AddedComplexity = 100 in
452249423Sdimdef:  Pat <(i64 (extloadi32 (i32 (add IntRegs:$src1, s11_2ExtPred:$offset)))),
453249423Sdim      (i64 (COMBINE_Ir_V4 0, (LDriw_indexed IntRegs:$src1,
454249423Sdim                                  s11_2ExtPred:$offset)))>,
455249423Sdim      Requires<[HasV4T]>;
456239462Sdim
457239462Sdim
458239462Sdim
459234285Sdim//===----------------------------------------------------------------------===//
460234285Sdim// LD -
461234285Sdim//===----------------------------------------------------------------------===//
462234285Sdim
463234285Sdim//===----------------------------------------------------------------------===//
464234285Sdim// ST +
465234285Sdim//===----------------------------------------------------------------------===//
466234285Sdim///
467251662Sdim//===----------------------------------------------------------------------===//
468251662Sdim// Template class for store instructions with Absolute set addressing mode.
469251662Sdim//===----------------------------------------------------------------------===//
470263508Sdimlet isExtended = 1, opExtendable = 2, validSubTargets = HasV4SubT,
471263508SdimaddrMode = AbsoluteSet in
472251662Sdimclass T_ST_abs_set<string mnemonic, RegisterClass RC>:
473251662Sdim            STInst2<(outs IntRegs:$dst1),
474251662Sdim            (ins RC:$src1, u0AlwaysExt:$src2),
475251662Sdim            mnemonic#"($dst1=##$src2) = $src1",
476239462Sdim            []>,
477239462Sdim            Requires<[HasV4T]>;
478234285Sdim
479251662Sdimdef STrid_abs_set_V4 : T_ST_abs_set <"memd", DoubleRegs>;
480251662Sdimdef STrib_abs_set_V4 : T_ST_abs_set <"memb", IntRegs>;
481251662Sdimdef STrih_abs_set_V4 : T_ST_abs_set <"memh", IntRegs>;
482251662Sdimdef STriw_abs_set_V4 : T_ST_abs_set <"memw", IntRegs>;
483239462Sdim
484251662Sdim//===----------------------------------------------------------------------===//
485249423Sdim// multiclass for store instructions with base + register offset addressing
486249423Sdim// mode
487251662Sdim//===----------------------------------------------------------------------===//
488249423Sdimmulticlass ST_Idxd_shl_Pbase<string mnemonic, RegisterClass RC, bit isNot,
489249423Sdim                             bit isPredNew> {
490251662Sdim  let isPredicatedNew = isPredNew in
491249423Sdim  def NAME : STInst2<(outs),
492249423Sdim            (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4,
493249423Sdim                 RC:$src5),
494249423Sdim            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
495249423Sdim            ") ")#mnemonic#"($src2+$src3<<#$src4) = $src5",
496249423Sdim            []>,
497234285Sdim            Requires<[HasV4T]>;
498249423Sdim}
499234285Sdim
500249423Sdimmulticlass ST_Idxd_shl_Pred<string mnemonic, RegisterClass RC, bit PredNot> {
501251662Sdim  let isPredicatedFalse = PredNot in {
502249423Sdim    defm _c#NAME : ST_Idxd_shl_Pbase<mnemonic, RC, PredNot, 0>;
503249423Sdim    // Predicate new
504249423Sdim    defm _cdn#NAME : ST_Idxd_shl_Pbase<mnemonic, RC, PredNot, 1>;
505249423Sdim  }
506249423Sdim}
507249423Sdim
508249423Sdimlet isNVStorable = 1 in
509249423Sdimmulticlass ST_Idxd_shl<string mnemonic, string CextOp, RegisterClass RC> {
510249423Sdim  let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed_shl in {
511249423Sdim    let isPredicable = 1 in
512249423Sdim    def NAME#_V4 : STInst2<(outs),
513249423Sdim            (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, RC:$src4),
514249423Sdim            mnemonic#"($src1+$src2<<#$src3) = $src4",
515249423Sdim            []>,
516249423Sdim            Requires<[HasV4T]>;
517249423Sdim
518249423Sdim    let isPredicated = 1 in {
519249423Sdim      defm Pt_V4 : ST_Idxd_shl_Pred<mnemonic, RC, 0 >;
520249423Sdim      defm NotPt_V4 : ST_Idxd_shl_Pred<mnemonic, RC, 1>;
521249423Sdim    }
522249423Sdim  }
523249423Sdim}
524249423Sdim
525249423Sdim// multiclass for new-value store instructions with base + register offset
526249423Sdim// addressing mode.
527249423Sdimmulticlass ST_Idxd_shl_Pbase_nv<string mnemonic, RegisterClass RC, bit isNot,
528249423Sdim                             bit isPredNew> {
529251662Sdim  let isPredicatedNew = isPredNew in
530249423Sdim  def NAME#_nv_V4 : NVInst_V4<(outs),
531249423Sdim            (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4,
532249423Sdim                 RC:$src5),
533249423Sdim            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
534249423Sdim            ") ")#mnemonic#"($src2+$src3<<#$src4) = $src5.new",
535249423Sdim            []>,
536249423Sdim            Requires<[HasV4T]>;
537249423Sdim}
538249423Sdim
539249423Sdimmulticlass ST_Idxd_shl_Pred_nv<string mnemonic, RegisterClass RC, bit PredNot> {
540251662Sdim  let isPredicatedFalse = PredNot in {
541249423Sdim    defm _c#NAME : ST_Idxd_shl_Pbase_nv<mnemonic, RC, PredNot, 0>;
542249423Sdim    // Predicate new
543249423Sdim    defm _cdn#NAME : ST_Idxd_shl_Pbase_nv<mnemonic, RC, PredNot, 1>;
544249423Sdim  }
545249423Sdim}
546249423Sdim
547249423Sdimlet mayStore = 1, isNVStore = 1 in
548249423Sdimmulticlass ST_Idxd_shl_nv<string mnemonic, string CextOp, RegisterClass RC> {
549249423Sdim  let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed_shl in {
550249423Sdim    let isPredicable = 1 in
551249423Sdim    def NAME#_nv_V4 : NVInst_V4<(outs),
552249423Sdim            (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, RC:$src4),
553249423Sdim            mnemonic#"($src1+$src2<<#$src3) = $src4.new",
554249423Sdim            []>,
555249423Sdim            Requires<[HasV4T]>;
556249423Sdim
557249423Sdim    let isPredicated = 1 in {
558249423Sdim      defm Pt : ST_Idxd_shl_Pred_nv<mnemonic, RC, 0 >;
559249423Sdim      defm NotPt : ST_Idxd_shl_Pred_nv<mnemonic, RC, 1>;
560249423Sdim    }
561249423Sdim  }
562249423Sdim}
563249423Sdim
564249423Sdimlet addrMode = BaseRegOffset, neverHasSideEffects = 1,
565249423SdimvalidSubTargets = HasV4SubT in {
566263508Sdim  let accessSize = ByteAccess in
567263508Sdim    defm STrib_indexed_shl: ST_Idxd_shl<"memb", "STrib", IntRegs>,
568263508Sdim                            ST_Idxd_shl_nv<"memb", "STrib", IntRegs>, AddrModeRel;
569249423Sdim
570263508Sdim  let accessSize = HalfWordAccess in
571263508Sdim    defm STrih_indexed_shl: ST_Idxd_shl<"memh", "STrih", IntRegs>,
572263508Sdim                            ST_Idxd_shl_nv<"memh", "STrih", IntRegs>, AddrModeRel;
573249423Sdim
574263508Sdim  let accessSize = WordAccess in
575263508Sdim    defm STriw_indexed_shl: ST_Idxd_shl<"memw", "STriw", IntRegs>,
576263508Sdim                            ST_Idxd_shl_nv<"memw", "STriw", IntRegs>, AddrModeRel;
577249423Sdim
578263508Sdim  let isNVStorable = 0, accessSize = DoubleWordAccess in
579263508Sdim    defm STrid_indexed_shl: ST_Idxd_shl<"memd", "STrid", DoubleRegs>, AddrModeRel;
580249423Sdim}
581249423Sdim
582249423Sdimlet Predicates = [HasV4T], AddedComplexity = 10 in {
583249423Sdimdef : Pat<(truncstorei8 (i32 IntRegs:$src4),
584249423Sdim                       (add IntRegs:$src1, (shl IntRegs:$src2,
585249423Sdim                                                u2ImmPred:$src3))),
586249423Sdim          (STrib_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2,
587249423Sdim                                u2ImmPred:$src3, IntRegs:$src4)>;
588249423Sdim
589249423Sdimdef : Pat<(truncstorei16 (i32 IntRegs:$src4),
590249423Sdim                        (add IntRegs:$src1, (shl IntRegs:$src2,
591249423Sdim                                                 u2ImmPred:$src3))),
592249423Sdim          (STrih_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2,
593249423Sdim                                u2ImmPred:$src3, IntRegs:$src4)>;
594249423Sdim
595249423Sdimdef : Pat<(store (i32 IntRegs:$src4),
596249423Sdim                 (add IntRegs:$src1, (shl IntRegs:$src2, u2ImmPred:$src3))),
597249423Sdim          (STriw_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2,
598249423Sdim                                u2ImmPred:$src3, IntRegs:$src4)>;
599249423Sdim
600249423Sdimdef : Pat<(store (i64 DoubleRegs:$src4),
601249423Sdim                (add IntRegs:$src1, (shl IntRegs:$src2, u2ImmPred:$src3))),
602249423Sdim          (STrid_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2,
603249423Sdim                                u2ImmPred:$src3, DoubleRegs:$src4)>;
604249423Sdim}
605249423Sdim
606251662Sdimlet isExtended = 1, opExtendable = 2 in
607251662Sdimclass T_ST_LongOff <string mnemonic, PatFrag stOp, RegisterClass RC, ValueType VT> :
608251662Sdim            STInst<(outs),
609251662Sdim            (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, RC:$src4),
610251662Sdim            mnemonic#"($src1<<#$src2+##$src3) = $src4",
611251662Sdim            [(stOp (VT RC:$src4),
612239462Sdim                    (add (shl (i32 IntRegs:$src1), u2ImmPred:$src2),
613249423Sdim                         u0AlwaysExtPred:$src3))]>,
614234285Sdim            Requires<[HasV4T]>;
615234285Sdim
616251662Sdimlet isExtended = 1, opExtendable = 2, mayStore = 1, isNVStore = 1 in
617251662Sdimclass T_ST_LongOff_nv <string mnemonic> :
618251662Sdim            NVInst_V4<(outs),
619251662Sdim            (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, IntRegs:$src4),
620251662Sdim            mnemonic#"($src1<<#$src2+##$src3) = $src4.new",
621251662Sdim            []>,
622251662Sdim            Requires<[HasV4T]>;
623251662Sdim
624251662Sdimmulticlass ST_LongOff <string mnemonic, string BaseOp, PatFrag stOp> {
625251662Sdim  let  BaseOpcode = BaseOp#"_shl" in {
626251662Sdim    let isNVStorable = 1 in
627251662Sdim    def NAME#_V4 : T_ST_LongOff<mnemonic, stOp, IntRegs, i32>;
628251662Sdim
629251662Sdim    def NAME#_nv_V4 : T_ST_LongOff_nv<mnemonic>;
630251662Sdim  }
631251662Sdim}
632251662Sdim
633251662Sdimlet AddedComplexity = 10, validSubTargets = HasV4SubT in {
634251662Sdim  def STrid_shl_V4 : T_ST_LongOff<"memd", store, DoubleRegs, i64>;
635251662Sdim  defm STrib_shl   : ST_LongOff <"memb", "STrib", truncstorei8>, NewValueRel;
636251662Sdim  defm STrih_shl   : ST_LongOff <"memh", "Strih", truncstorei16>, NewValueRel;
637251662Sdim  defm STriw_shl   : ST_LongOff <"memw", "STriw", store>, NewValueRel;
638251662Sdim}
639251662Sdim
640251662Sdimlet AddedComplexity = 40 in
641251662Sdimmulticlass T_ST_LOff_Pats <InstHexagon I, RegisterClass RC, ValueType VT,
642251662Sdim                           PatFrag stOp> {
643251662Sdim def : Pat<(stOp (VT RC:$src4),
644251662Sdim           (add (shl IntRegs:$src1, u2ImmPred:$src2),
645251662Sdim               (NumUsesBelowThresCONST32 tglobaladdr:$src3))),
646251662Sdim           (I IntRegs:$src1, u2ImmPred:$src2, tglobaladdr:$src3, RC:$src4)>;
647251662Sdim
648251662Sdim def : Pat<(stOp (VT RC:$src4),
649251662Sdim           (add IntRegs:$src1,
650251662Sdim               (NumUsesBelowThresCONST32 tglobaladdr:$src3))),
651251662Sdim           (I IntRegs:$src1, 0, tglobaladdr:$src3, RC:$src4)>;
652251662Sdim}
653251662Sdim
654251662Sdimdefm : T_ST_LOff_Pats<STrid_shl_V4, DoubleRegs, i64, store>;
655251662Sdimdefm : T_ST_LOff_Pats<STriw_shl_V4, IntRegs, i32, store>;
656251662Sdimdefm : T_ST_LOff_Pats<STrib_shl_V4, IntRegs, i32, truncstorei8>;
657251662Sdimdefm : T_ST_LOff_Pats<STrih_shl_V4, IntRegs, i32, truncstorei16>;
658251662Sdim
659234285Sdim// memd(Rx++#s4:3)=Rtt
660234285Sdim// memd(Rx++#s4:3:circ(Mu))=Rtt
661234285Sdim// memd(Rx++I:circ(Mu))=Rtt
662234285Sdim// memd(Rx++Mu)=Rtt
663234285Sdim// memd(Rx++Mu:brev)=Rtt
664234285Sdim// memd(gp+#u16:3)=Rtt
665234285Sdim
666234285Sdim// Store doubleword conditionally.
667234285Sdim// if ([!]Pv[.new]) memd(#u6)=Rtt
668234285Sdim// TODO: needs to be implemented.
669234285Sdim
670249423Sdim//===----------------------------------------------------------------------===//
671249423Sdim// multiclass for store instructions with base + immediate offset
672249423Sdim// addressing mode and immediate stored value.
673249423Sdim// mem[bhw](Rx++#s4:3)=#s8
674249423Sdim// if ([!]Pv[.new]) mem[bhw](Rx++#s4:3)=#s6
675249423Sdim//===----------------------------------------------------------------------===//
676249423Sdimmulticlass ST_Imm_Pbase<string mnemonic, Operand OffsetOp, bit isNot,
677249423Sdim                        bit isPredNew> {
678251662Sdim  let isPredicatedNew = isPredNew in
679249423Sdim  def NAME : STInst2<(outs),
680249423Sdim            (ins PredRegs:$src1, IntRegs:$src2, OffsetOp:$src3, s6Ext:$src4),
681249423Sdim            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
682249423Sdim            ") ")#mnemonic#"($src2+#$src3) = #$src4",
683234285Sdim            []>,
684234285Sdim            Requires<[HasV4T]>;
685249423Sdim}
686234285Sdim
687249423Sdimmulticlass ST_Imm_Pred<string mnemonic, Operand OffsetOp, bit PredNot> {
688251662Sdim  let isPredicatedFalse = PredNot in {
689249423Sdim    defm _c#NAME : ST_Imm_Pbase<mnemonic, OffsetOp, PredNot, 0>;
690249423Sdim    // Predicate new
691249423Sdim    defm _cdn#NAME : ST_Imm_Pbase<mnemonic, OffsetOp, PredNot, 1>;
692249423Sdim  }
693249423Sdim}
694234285Sdim
695249423Sdimlet isExtendable = 1, isExtentSigned = 1, neverHasSideEffects = 1 in
696249423Sdimmulticlass ST_Imm<string mnemonic, string CextOp, Operand OffsetOp> {
697249423Sdim  let CextOpcode = CextOp, BaseOpcode = CextOp#_imm in {
698249423Sdim    let opExtendable = 2, opExtentBits = 8, isPredicable = 1 in
699249423Sdim    def NAME#_V4 : STInst2<(outs),
700249423Sdim            (ins IntRegs:$src1, OffsetOp:$src2, s8Ext:$src3),
701249423Sdim            mnemonic#"($src1+#$src2) = #$src3",
702234285Sdim            []>,
703234285Sdim            Requires<[HasV4T]>;
704234285Sdim
705249423Sdim    let opExtendable = 3, opExtentBits = 6, isPredicated = 1 in {
706249423Sdim      defm Pt_V4 : ST_Imm_Pred<mnemonic, OffsetOp, 0>;
707249423Sdim      defm NotPt_V4 : ST_Imm_Pred<mnemonic, OffsetOp, 1 >;
708249423Sdim    }
709249423Sdim  }
710249423Sdim}
711234285Sdim
712249423Sdimlet addrMode = BaseImmOffset, InputType = "imm",
713263508SdimvalidSubTargets = HasV4SubT in {
714263508Sdim  let accessSize = ByteAccess in
715263508Sdim    defm STrib_imm : ST_Imm<"memb", "STrib", u6_0Imm>, ImmRegRel, PredNewRel;
716263508Sdim
717263508Sdim  let accessSize = HalfWordAccess in
718263508Sdim    defm STrih_imm : ST_Imm<"memh", "STrih", u6_1Imm>, ImmRegRel, PredNewRel;
719263508Sdim
720263508Sdim  let accessSize = WordAccess in
721263508Sdim    defm STriw_imm : ST_Imm<"memw", "STriw", u6_2Imm>, ImmRegRel, PredNewRel;
722249423Sdim}
723234285Sdim
724249423Sdimlet Predicates = [HasV4T], AddedComplexity = 10 in {
725249423Sdimdef: Pat<(truncstorei8 s8ExtPred:$src3, (add IntRegs:$src1, u6_0ImmPred:$src2)),
726249423Sdim            (STrib_imm_V4 IntRegs:$src1, u6_0ImmPred:$src2, s8ExtPred:$src3)>;
727234285Sdim
728249423Sdimdef: Pat<(truncstorei16 s8ExtPred:$src3, (add IntRegs:$src1,
729249423Sdim                                              u6_1ImmPred:$src2)),
730249423Sdim            (STrih_imm_V4 IntRegs:$src1, u6_1ImmPred:$src2, s8ExtPred:$src3)>;
731234285Sdim
732249423Sdimdef: Pat<(store s8ExtPred:$src3, (add IntRegs:$src1, u6_2ImmPred:$src2)),
733249423Sdim            (STriw_imm_V4 IntRegs:$src1, u6_2ImmPred:$src2, s8ExtPred:$src3)>;
734249423Sdim}
735234285Sdim
736249423Sdimlet AddedComplexity = 6 in
737249423Sdimdef : Pat <(truncstorei8 s8ExtPred:$src2, (i32 IntRegs:$src1)),
738249423Sdim           (STrib_imm_V4 IntRegs:$src1, 0, s8ExtPred:$src2)>,
739249423Sdim           Requires<[HasV4T]>;
740234285Sdim
741234285Sdim// memb(Rx++#s4:0:circ(Mu))=Rt
742234285Sdim// memb(Rx++I:circ(Mu))=Rt
743234285Sdim// memb(Rx++Mu)=Rt
744234285Sdim// memb(Rx++Mu:brev)=Rt
745234285Sdim// memb(gp+#u16:0)=Rt
746234285Sdim
747234285Sdim
748234285Sdim// Store halfword.
749239462Sdim// TODO: needs to be implemented
750234982Sdim// memh(Re=#U6)=Rt.H
751234285Sdim// memh(Rs+#s11:1)=Rt.H
752249423Sdimlet AddedComplexity = 6 in
753249423Sdimdef : Pat <(truncstorei16 s8ExtPred:$src2, (i32 IntRegs:$src1)),
754249423Sdim           (STrih_imm_V4 IntRegs:$src1, 0, s8ExtPred:$src2)>,
755249423Sdim           Requires<[HasV4T]>;
756234285Sdim
757234285Sdim// memh(Rs+Ru<<#u2)=Rt.H
758234285Sdim// TODO: needs to be implemented.
759234285Sdim
760234285Sdim// memh(Ru<<#u2+#U6)=Rt.H
761234285Sdim// memh(Rx++#s4:1:circ(Mu))=Rt.H
762234285Sdim// memh(Rx++#s4:1:circ(Mu))=Rt
763234285Sdim// memh(Rx++I:circ(Mu))=Rt.H
764234285Sdim// memh(Rx++I:circ(Mu))=Rt
765234285Sdim// memh(Rx++Mu)=Rt.H
766234285Sdim// memh(Rx++Mu)=Rt
767234285Sdim// memh(Rx++Mu:brev)=Rt.H
768234285Sdim// memh(Rx++Mu:brev)=Rt
769234285Sdim// memh(gp+#u16:1)=Rt
770234285Sdim// if ([!]Pv[.new]) memh(#u6)=Rt.H
771234285Sdim// if ([!]Pv[.new]) memh(#u6)=Rt
772234285Sdim
773234285Sdim
774234285Sdim// if ([!]Pv[.new]) memh(Rs+#u6:1)=Rt.H
775234285Sdim// TODO: needs to be implemented.
776234285Sdim
777234285Sdim// if ([!]Pv[.new]) memh(Rx++#s4:1)=Rt.H
778234285Sdim// TODO: Needs to be implemented.
779234285Sdim
780234285Sdim// Store word.
781234285Sdim// memw(Re=#U6)=Rt
782234285Sdim// TODO: Needs to be implemented.
783234285Sdim
784239462Sdim// Store predicate:
785239462Sdimlet neverHasSideEffects = 1 in
786239462Sdimdef STriw_pred_V4 : STInst2<(outs),
787239462Sdim            (ins MEMri:$addr, PredRegs:$src1),
788239462Sdim            "Error; should not emit",
789239462Sdim            []>,
790239462Sdim            Requires<[HasV4T]>;
791239462Sdim
792249423Sdimlet AddedComplexity = 6 in
793249423Sdimdef : Pat <(store s8ExtPred:$src2, (i32 IntRegs:$src1)),
794249423Sdim           (STriw_imm_V4 IntRegs:$src1, 0, s8ExtPred:$src2)>,
795249423Sdim           Requires<[HasV4T]>;
796239462Sdim
797234285Sdim// memw(Rx++#s4:2)=Rt
798234285Sdim// memw(Rx++#s4:2:circ(Mu))=Rt
799234285Sdim// memw(Rx++I:circ(Mu))=Rt
800234285Sdim// memw(Rx++Mu)=Rt
801234285Sdim// memw(Rx++Mu:brev)=Rt
802234285Sdim
803234285Sdim//===----------------------------------------------------------------------===
804234285Sdim// ST -
805234285Sdim//===----------------------------------------------------------------------===
806234285Sdim
807234285Sdim
808234285Sdim//===----------------------------------------------------------------------===//
809234285Sdim// NV/ST +
810234285Sdim//===----------------------------------------------------------------------===//
811234285Sdim
812249423Sdim// multiclass for new-value store instructions with base + immediate offset.
813249423Sdim//
814249423Sdimmulticlass ST_Idxd_Pbase_nv<string mnemonic, RegisterClass RC,
815249423Sdim                            Operand predImmOp, bit isNot, bit isPredNew> {
816251662Sdim  let isPredicatedNew = isPredNew in
817249423Sdim  def NAME#_nv_V4 : NVInst_V4<(outs),
818249423Sdim            (ins PredRegs:$src1, IntRegs:$src2, predImmOp:$src3, RC: $src4),
819249423Sdim            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
820249423Sdim            ") ")#mnemonic#"($src2+#$src3) = $src4.new",
821234285Sdim            []>,
822234285Sdim            Requires<[HasV4T]>;
823249423Sdim}
824234285Sdim
825249423Sdimmulticlass ST_Idxd_Pred_nv<string mnemonic, RegisterClass RC, Operand predImmOp,
826249423Sdim                           bit PredNot> {
827251662Sdim  let isPredicatedFalse = PredNot in {
828249423Sdim    defm _c#NAME : ST_Idxd_Pbase_nv<mnemonic, RC, predImmOp, PredNot, 0>;
829249423Sdim    // Predicate new
830249423Sdim    defm _cdn#NAME : ST_Idxd_Pbase_nv<mnemonic, RC, predImmOp, PredNot, 1>;
831249423Sdim  }
832249423Sdim}
833234285Sdim
834249423Sdimlet mayStore = 1, isNVStore = 1, neverHasSideEffects = 1, isExtendable = 1 in
835249423Sdimmulticlass ST_Idxd_nv<string mnemonic, string CextOp, RegisterClass RC,
836249423Sdim                   Operand ImmOp, Operand predImmOp, bits<5> ImmBits,
837249423Sdim                   bits<5> PredImmBits> {
838234285Sdim
839249423Sdim  let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed in {
840249423Sdim    let opExtendable = 1, isExtentSigned = 1, opExtentBits = ImmBits,
841249423Sdim    isPredicable = 1 in
842249423Sdim    def NAME#_nv_V4 : NVInst_V4<(outs),
843249423Sdim            (ins IntRegs:$src1, ImmOp:$src2, RC:$src3),
844249423Sdim            mnemonic#"($src1+#$src2) = $src3.new",
845234285Sdim            []>,
846234285Sdim            Requires<[HasV4T]>;
847234285Sdim
848249423Sdim    let opExtendable = 2, isExtentSigned = 0, opExtentBits = PredImmBits,
849249423Sdim    isPredicated = 1 in {
850249423Sdim      defm Pt : ST_Idxd_Pred_nv<mnemonic, RC, predImmOp, 0>;
851249423Sdim      defm NotPt : ST_Idxd_Pred_nv<mnemonic, RC, predImmOp, 1>;
852249423Sdim    }
853249423Sdim  }
854249423Sdim}
855234285Sdim
856249423Sdimlet addrMode = BaseImmOffset, validSubTargets = HasV4SubT in {
857263508Sdim  let accessSize = ByteAccess in
858263508Sdim    defm STrib_indexed: ST_Idxd_nv<"memb", "STrib", IntRegs, s11_0Ext,
859263508Sdim                                   u6_0Ext, 11, 6>, AddrModeRel;
860263508Sdim
861263508Sdim  let accessSize = HalfWordAccess in
862263508Sdim    defm STrih_indexed: ST_Idxd_nv<"memh", "STrih", IntRegs, s11_1Ext,
863263508Sdim                                   u6_1Ext, 12, 7>, AddrModeRel;
864263508Sdim
865263508Sdim  let accessSize = WordAccess in
866263508Sdim    defm STriw_indexed: ST_Idxd_nv<"memw", "STriw", IntRegs, s11_2Ext,
867263508Sdim                                   u6_2Ext, 13, 8>, AddrModeRel;
868249423Sdim}
869234285Sdim
870249423Sdim// multiclass for new-value store instructions with base + immediate offset.
871249423Sdim// and MEMri operand.
872249423Sdimmulticlass ST_MEMri_Pbase_nv<string mnemonic, RegisterClass RC, bit isNot,
873249423Sdim                          bit isPredNew> {
874251662Sdim  let isPredicatedNew = isPredNew in
875249423Sdim  def NAME#_nv_V4 : NVInst_V4<(outs),
876249423Sdim            (ins PredRegs:$src1, MEMri:$addr, RC: $src2),
877249423Sdim            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
878249423Sdim            ") ")#mnemonic#"($addr) = $src2.new",
879234285Sdim            []>,
880234285Sdim            Requires<[HasV4T]>;
881249423Sdim}
882234285Sdim
883249423Sdimmulticlass ST_MEMri_Pred_nv<string mnemonic, RegisterClass RC, bit PredNot> {
884251662Sdim  let isPredicatedFalse = PredNot in {
885249423Sdim    defm _c#NAME : ST_MEMri_Pbase_nv<mnemonic, RC, PredNot, 0>;
886234285Sdim
887249423Sdim    // Predicate new
888249423Sdim    defm _cdn#NAME : ST_MEMri_Pbase_nv<mnemonic, RC, PredNot, 1>;
889249423Sdim  }
890249423Sdim}
891234285Sdim
892249423Sdimlet mayStore = 1, isNVStore = 1, isExtendable = 1, neverHasSideEffects = 1 in
893249423Sdimmulticlass ST_MEMri_nv<string mnemonic, string CextOp, RegisterClass RC,
894249423Sdim                    bits<5> ImmBits, bits<5> PredImmBits> {
895234285Sdim
896249423Sdim  let CextOpcode = CextOp, BaseOpcode = CextOp in {
897249423Sdim    let opExtendable = 1, isExtentSigned = 1, opExtentBits = ImmBits,
898249423Sdim         isPredicable = 1 in
899249423Sdim    def NAME#_nv_V4 : NVInst_V4<(outs),
900249423Sdim            (ins MEMri:$addr, RC:$src),
901249423Sdim            mnemonic#"($addr) = $src.new",
902234285Sdim            []>,
903234285Sdim            Requires<[HasV4T]>;
904234285Sdim
905249423Sdim    let opExtendable = 2, isExtentSigned = 0, opExtentBits = PredImmBits,
906249423Sdim        neverHasSideEffects = 1, isPredicated = 1 in {
907249423Sdim      defm Pt : ST_MEMri_Pred_nv<mnemonic, RC, 0>;
908249423Sdim      defm NotPt : ST_MEMri_Pred_nv<mnemonic, RC, 1>;
909249423Sdim    }
910249423Sdim  }
911249423Sdim}
912234285Sdim
913249423Sdimlet addrMode = BaseImmOffset, isMEMri = "true", validSubTargets = HasV4SubT,
914249423SdimmayStore = 1 in {
915263508Sdim  let accessSize = ByteAccess in
916263508Sdim    defm STrib: ST_MEMri_nv<"memb", "STrib", IntRegs, 11, 6>, AddrModeRel;
917263508Sdim
918263508Sdim  let accessSize = HalfWordAccess in
919263508Sdim    defm STrih: ST_MEMri_nv<"memh", "STrih", IntRegs, 12, 7>, AddrModeRel;
920263508Sdim
921263508Sdim  let accessSize = WordAccess in
922263508Sdim    defm STriw: ST_MEMri_nv<"memw", "STriw", IntRegs, 13, 8>, AddrModeRel;
923249423Sdim}
924234285Sdim
925249423Sdim//===----------------------------------------------------------------------===//
926249423Sdim// Post increment store
927249423Sdim// mem[bhwd](Rx++#s4:[0123])=Nt.new
928249423Sdim//===----------------------------------------------------------------------===//
929234285Sdim
930249423Sdimmulticlass ST_PostInc_Pbase_nv<string mnemonic, RegisterClass RC, Operand ImmOp,
931249423Sdim                            bit isNot, bit isPredNew> {
932251662Sdim  let isPredicatedNew = isPredNew in
933249423Sdim  def NAME#_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst),
934249423Sdim            (ins PredRegs:$src1, IntRegs:$src2, ImmOp:$offset, RC:$src3),
935249423Sdim            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
936249423Sdim            ") ")#mnemonic#"($src2++#$offset) = $src3.new",
937249423Sdim            [],
938249423Sdim            "$src2 = $dst">,
939234285Sdim            Requires<[HasV4T]>;
940249423Sdim}
941234285Sdim
942249423Sdimmulticlass ST_PostInc_Pred_nv<string mnemonic, RegisterClass RC,
943249423Sdim                           Operand ImmOp, bit PredNot> {
944251662Sdim  let isPredicatedFalse = PredNot in {
945249423Sdim    defm _c#NAME : ST_PostInc_Pbase_nv<mnemonic, RC, ImmOp, PredNot, 0>;
946249423Sdim    // Predicate new
947249423Sdim    let Predicates = [HasV4T], validSubTargets = HasV4SubT in
948249423Sdim    defm _cdn#NAME : ST_PostInc_Pbase_nv<mnemonic, RC, ImmOp, PredNot, 1>;
949249423Sdim  }
950249423Sdim}
951234285Sdim
952249423Sdimlet hasCtrlDep = 1, isNVStore = 1, neverHasSideEffects = 1 in
953249423Sdimmulticlass ST_PostInc_nv<string mnemonic, string BaseOp, RegisterClass RC,
954249423Sdim                      Operand ImmOp> {
955234285Sdim
956249423Sdim  let BaseOpcode = "POST_"#BaseOp in {
957249423Sdim    let isPredicable = 1 in
958249423Sdim    def NAME#_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst),
959249423Sdim                (ins IntRegs:$src1, ImmOp:$offset, RC:$src2),
960249423Sdim                mnemonic#"($src1++#$offset) = $src2.new",
961249423Sdim                [],
962249423Sdim                "$src1 = $dst">,
963249423Sdim                Requires<[HasV4T]>;
964234285Sdim
965249423Sdim    let isPredicated = 1 in {
966249423Sdim      defm Pt : ST_PostInc_Pred_nv<mnemonic, RC, ImmOp, 0 >;
967249423Sdim      defm NotPt : ST_PostInc_Pred_nv<mnemonic, RC, ImmOp, 1 >;
968249423Sdim    }
969249423Sdim  }
970249423Sdim}
971234285Sdim
972263508Sdimlet addrMode = PostInc, validSubTargets = HasV4SubT in {
973249423Sdimdefm POST_STbri: ST_PostInc_nv <"memb", "STrib", IntRegs, s4_0Imm>, AddrModeRel;
974249423Sdimdefm POST_SThri: ST_PostInc_nv <"memh", "STrih", IntRegs, s4_1Imm>, AddrModeRel;
975249423Sdimdefm POST_STwri: ST_PostInc_nv <"memw", "STriw", IntRegs, s4_2Imm>, AddrModeRel;
976249423Sdim}
977234285Sdim
978249423Sdim// memb(Rx++#s4:0:circ(Mu))=Nt.new
979249423Sdim// memb(Rx++I:circ(Mu))=Nt.new
980249423Sdim// memb(Rx++Mu)=Nt.new
981249423Sdim// memb(Rx++Mu:brev)=Nt.new
982234285Sdim// memh(Rx++#s4:1:circ(Mu))=Nt.new
983234285Sdim// memh(Rx++I:circ(Mu))=Nt.new
984234285Sdim// memh(Rx++Mu)=Nt.new
985234285Sdim// memh(Rx++Mu:brev)=Nt.new
986234285Sdim
987234285Sdim// memw(Rx++#s4:2:circ(Mu))=Nt.new
988234285Sdim// memw(Rx++I:circ(Mu))=Nt.new
989234285Sdim// memw(Rx++Mu)=Nt.new
990234285Sdim// memw(Rx++Mu:brev)=Nt.new
991234285Sdim
992234285Sdim//===----------------------------------------------------------------------===//
993234285Sdim// NV/ST -
994234285Sdim//===----------------------------------------------------------------------===//
995234285Sdim
996234285Sdim//===----------------------------------------------------------------------===//
997234285Sdim// NV/J +
998234285Sdim//===----------------------------------------------------------------------===//
999234285Sdim
1000251662Sdim//===----------------------------------------------------------------------===//
1001251662Sdim// multiclass/template class for the new-value compare jumps with the register
1002251662Sdim// operands.
1003251662Sdim//===----------------------------------------------------------------------===//
1004234285Sdim
1005251662Sdimlet isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 11 in
1006251662Sdimclass NVJrr_template<string mnemonic, bits<3> majOp, bit NvOpNum,
1007251662Sdim                      bit isNegCond, bit isTaken>
1008251662Sdim  : NVInst_V4<(outs),
1009251662Sdim    (ins IntRegs:$src1, IntRegs:$src2, brtarget:$offset),
1010251662Sdim    "if ("#!if(isNegCond, "!","")#mnemonic#
1011251662Sdim    "($src1"#!if(!eq(NvOpNum, 0),".new, ",", ")#
1012251662Sdim    "$src2"#!if(!eq(NvOpNum, 1),".new))","))")#" jump:"
1013251662Sdim    #!if(isTaken, "t","nt")#" $offset",
1014251662Sdim    []>, Requires<[HasV4T]> {
1015234285Sdim
1016251662Sdim      bits<5> src1;
1017251662Sdim      bits<5> src2;
1018251662Sdim      bits<3> Ns;    // New-Value Operand
1019251662Sdim      bits<5> RegOp; // Non New-Value Operand
1020251662Sdim      bits<11> offset;
1021234285Sdim
1022251662Sdim      let isBrTaken = !if(isTaken, "true", "false");
1023251662Sdim      let isPredicatedFalse = isNegCond;
1024234285Sdim
1025251662Sdim      let Ns = !if(!eq(NvOpNum, 0), src1{2-0}, src2{2-0});
1026251662Sdim      let RegOp = !if(!eq(NvOpNum, 0), src2, src1);
1027234285Sdim
1028251662Sdim      let IClass = 0b0010;
1029251662Sdim      let Inst{26} = 0b0;
1030251662Sdim      let Inst{25-23} = majOp;
1031251662Sdim      let Inst{22} = isNegCond;
1032251662Sdim      let Inst{18-16} = Ns;
1033251662Sdim      let Inst{13} = isTaken;
1034251662Sdim      let Inst{12-8} = RegOp;
1035251662Sdim      let Inst{21-20} = offset{10-9};
1036251662Sdim      let Inst{7-1} = offset{8-2};
1037234285Sdim}
1038234285Sdim
1039234285Sdim
1040251662Sdimmulticlass NVJrr_cond<string mnemonic, bits<3> majOp, bit NvOpNum,
1041251662Sdim                       bit isNegCond> {
1042251662Sdim  // Branch not taken:
1043251662Sdim  def _nt_V4: NVJrr_template<mnemonic, majOp, NvOpNum, isNegCond, 0>;
1044251662Sdim  // Branch taken:
1045251662Sdim  def _t_V4: NVJrr_template<mnemonic, majOp, NvOpNum, isNegCond, 1>;
1046234285Sdim}
1047234285Sdim
1048251662Sdim// NvOpNum = 0 -> First Operand is a new-value Register
1049251662Sdim// NvOpNum = 1 -> Second Operand is a new-value Register
1050234285Sdim
1051251662Sdimmulticlass NVJrr_base<string mnemonic, string BaseOp, bits<3> majOp,
1052251662Sdim                       bit NvOpNum> {
1053251662Sdim  let BaseOpcode = BaseOp#_NVJ in {
1054251662Sdim    defm _t_Jumpnv : NVJrr_cond<mnemonic, majOp, NvOpNum, 0>; // True cond
1055251662Sdim    defm _f_Jumpnv : NVJrr_cond<mnemonic, majOp, NvOpNum, 1>; // False cond
1056251662Sdim  }
1057234285Sdim}
1058234285Sdim
1059251662Sdim// if ([!]cmp.eq(Ns.new,Rt)) jump:[n]t #r9:2
1060251662Sdim// if ([!]cmp.gt(Ns.new,Rt)) jump:[n]t #r9:2
1061251662Sdim// if ([!]cmp.gtu(Ns.new,Rt)) jump:[n]t #r9:2
1062251662Sdim// if ([!]cmp.gt(Rt,Ns.new)) jump:[n]t #r9:2
1063251662Sdim// if ([!]cmp.gtu(Rt,Ns.new)) jump:[n]t #r9:2
1064251662Sdim
1065251662Sdimlet isPredicated = 1, isBranch = 1, isNewValue = 1, isTerminator = 1,
1066251662Sdim  Defs = [PC], neverHasSideEffects = 1, validSubTargets = HasV4SubT in {
1067251662Sdim  defm CMPEQrr  : NVJrr_base<"cmp.eq",  "CMPEQ",  0b000, 0>, PredRel;
1068251662Sdim  defm CMPGTrr  : NVJrr_base<"cmp.gt",  "CMPGT",  0b001, 0>, PredRel;
1069251662Sdim  defm CMPGTUrr : NVJrr_base<"cmp.gtu", "CMPGTU", 0b010, 0>, PredRel;
1070251662Sdim  defm CMPLTrr  : NVJrr_base<"cmp.gt",  "CMPLT",  0b011, 1>, PredRel;
1071251662Sdim  defm CMPLTUrr : NVJrr_base<"cmp.gtu", "CMPLTU", 0b100, 1>, PredRel;
1072234285Sdim}
1073234285Sdim
1074251662Sdim//===----------------------------------------------------------------------===//
1075251662Sdim// multiclass/template class for the new-value compare jumps instruction
1076251662Sdim// with a register and an unsigned immediate (U5) operand.
1077251662Sdim//===----------------------------------------------------------------------===//
1078251662Sdim
1079251662Sdimlet isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 11 in
1080251662Sdimclass NVJri_template<string mnemonic, bits<3> majOp, bit isNegCond,
1081251662Sdim                         bit isTaken>
1082251662Sdim  : NVInst_V4<(outs),
1083251662Sdim    (ins IntRegs:$src1, u5Imm:$src2, brtarget:$offset),
1084251662Sdim    "if ("#!if(isNegCond, "!","")#mnemonic#"($src1.new, #$src2)) jump:"
1085251662Sdim    #!if(isTaken, "t","nt")#" $offset",
1086251662Sdim    []>, Requires<[HasV4T]> {
1087251662Sdim
1088251662Sdim      let isPredicatedFalse = isNegCond;
1089251662Sdim      let isBrTaken = !if(isTaken, "true", "false");
1090251662Sdim
1091251662Sdim      bits<3> src1;
1092251662Sdim      bits<5> src2;
1093251662Sdim      bits<11> offset;
1094251662Sdim
1095251662Sdim      let IClass = 0b0010;
1096251662Sdim      let Inst{26} = 0b1;
1097251662Sdim      let Inst{25-23} = majOp;
1098251662Sdim      let Inst{22} = isNegCond;
1099251662Sdim      let Inst{18-16} = src1;
1100251662Sdim      let Inst{13} = isTaken;
1101251662Sdim      let Inst{12-8} = src2;
1102251662Sdim      let Inst{21-20} = offset{10-9};
1103251662Sdim      let Inst{7-1} = offset{8-2};
1104234285Sdim}
1105234285Sdim
1106251662Sdimmulticlass NVJri_cond<string mnemonic, bits<3> majOp, bit isNegCond> {
1107251662Sdim  // Branch not taken:
1108251662Sdim  def _nt_V4: NVJri_template<mnemonic, majOp, isNegCond, 0>;
1109251662Sdim  // Branch taken:
1110251662Sdim  def _t_V4: NVJri_template<mnemonic, majOp, isNegCond, 1>;
1111234285Sdim}
1112234285Sdim
1113251662Sdimmulticlass NVJri_base<string mnemonic, string BaseOp, bits<3> majOp> {
1114251662Sdim  let BaseOpcode = BaseOp#_NVJri in {
1115251662Sdim    defm _t_Jumpnv : NVJri_cond<mnemonic, majOp, 0>; // True Cond
1116251662Sdim    defm _f_Jumpnv : NVJri_cond<mnemonic, majOp, 1>; // False cond
1117251662Sdim  }
1118234285Sdim}
1119234285Sdim
1120251662Sdim// if ([!]cmp.eq(Ns.new,#U5)) jump:[n]t #r9:2
1121251662Sdim// if ([!]cmp.gt(Ns.new,#U5)) jump:[n]t #r9:2
1122251662Sdim// if ([!]cmp.gtu(Ns.new,#U5)) jump:[n]t #r9:2
1123251662Sdim
1124251662Sdimlet isPredicated = 1, isBranch = 1, isNewValue = 1, isTerminator = 1,
1125251662Sdim  Defs = [PC], neverHasSideEffects = 1, validSubTargets = HasV4SubT in {
1126251662Sdim  defm CMPEQri  : NVJri_base<"cmp.eq", "CMPEQ", 0b000>, PredRel;
1127251662Sdim  defm CMPGTri  : NVJri_base<"cmp.gt", "CMPGT", 0b001>, PredRel;
1128251662Sdim  defm CMPGTUri : NVJri_base<"cmp.gtu", "CMPGTU", 0b010>, PredRel;
1129234285Sdim}
1130234285Sdim
1131251662Sdim//===----------------------------------------------------------------------===//
1132251662Sdim// multiclass/template class for the new-value compare jumps instruction
1133251662Sdim// with a register and an hardcoded 0/-1 immediate value.
1134251662Sdim//===----------------------------------------------------------------------===//
1135251662Sdim
1136251662Sdimlet isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 11 in
1137251662Sdimclass NVJ_ConstImm_template<string mnemonic, bits<3> majOp, string ImmVal,
1138251662Sdim                            bit isNegCond, bit isTaken>
1139251662Sdim  : NVInst_V4<(outs),
1140251662Sdim    (ins IntRegs:$src1, brtarget:$offset),
1141251662Sdim    "if ("#!if(isNegCond, "!","")#mnemonic
1142251662Sdim    #"($src1.new, #"#ImmVal#")) jump:"
1143251662Sdim    #!if(isTaken, "t","nt")#" $offset",
1144251662Sdim    []>, Requires<[HasV4T]> {
1145251662Sdim
1146251662Sdim      let isPredicatedFalse = isNegCond;
1147251662Sdim      let isBrTaken = !if(isTaken, "true", "false");
1148251662Sdim
1149251662Sdim      bits<3> src1;
1150251662Sdim      bits<11> offset;
1151251662Sdim      let IClass = 0b0010;
1152251662Sdim      let Inst{26} = 0b1;
1153251662Sdim      let Inst{25-23} = majOp;
1154251662Sdim      let Inst{22} = isNegCond;
1155251662Sdim      let Inst{18-16} = src1;
1156251662Sdim      let Inst{13} = isTaken;
1157251662Sdim      let Inst{21-20} = offset{10-9};
1158251662Sdim      let Inst{7-1} = offset{8-2};
1159234285Sdim}
1160234285Sdim
1161251662Sdimmulticlass NVJ_ConstImm_cond<string mnemonic, bits<3> majOp, string ImmVal,
1162251662Sdim                             bit isNegCond> {
1163251662Sdim  // Branch not taken:
1164251662Sdim  def _nt_V4: NVJ_ConstImm_template<mnemonic, majOp, ImmVal, isNegCond, 0>;
1165251662Sdim  // Branch taken:
1166251662Sdim  def _t_V4: NVJ_ConstImm_template<mnemonic, majOp, ImmVal, isNegCond, 1>;
1167234285Sdim}
1168234285Sdim
1169251662Sdimmulticlass NVJ_ConstImm_base<string mnemonic, string BaseOp, bits<3> majOp,
1170251662Sdim                             string ImmVal> {
1171251662Sdim  let BaseOpcode = BaseOp#_NVJ_ConstImm in {
1172251662Sdim  defm _t_Jumpnv : NVJ_ConstImm_cond<mnemonic, majOp, ImmVal, 0>; // True cond
1173251662Sdim  defm _f_Jumpnv : NVJ_ConstImm_cond<mnemonic, majOp, ImmVal, 1>; // False Cond
1174251662Sdim  }
1175234285Sdim}
1176234285Sdim
1177251662Sdim// if ([!]tstbit(Ns.new,#0)) jump:[n]t #r9:2
1178251662Sdim// if ([!]cmp.eq(Ns.new,#-1)) jump:[n]t #r9:2
1179251662Sdim// if ([!]cmp.gt(Ns.new,#-1)) jump:[n]t #r9:2
1180234285Sdim
1181251662Sdimlet isPredicated = 1, isBranch = 1, isNewValue = 1, isTerminator=1,
1182251662Sdim  Defs = [PC], neverHasSideEffects = 1 in {
1183251662Sdim  defm TSTBIT0  : NVJ_ConstImm_base<"tstbit", "TSTBIT", 0b011, "0">, PredRel;
1184251662Sdim  defm CMPEQn1  : NVJ_ConstImm_base<"cmp.eq", "CMPEQ",  0b100, "-1">, PredRel;
1185251662Sdim  defm CMPGTn1  : NVJ_ConstImm_base<"cmp.gt", "CMPGT",  0b101, "-1">, PredRel;
1186234285Sdim}
1187234285Sdim
1188234285Sdim//===----------------------------------------------------------------------===//
1189234285Sdim// XTYPE/ALU +
1190234285Sdim//===----------------------------------------------------------------------===//
1191234285Sdim
1192234285Sdim//  Add and accumulate.
1193234285Sdim//  Rd=add(Rs,add(Ru,#s6))
1194249423Sdimlet isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 6,
1195249423SdimvalidSubTargets = HasV4SubT in
1196234285Sdimdef ADDr_ADDri_V4 : MInst<(outs IntRegs:$dst),
1197249423Sdim          (ins IntRegs:$src1, IntRegs:$src2, s6Ext:$src3),
1198234285Sdim          "$dst = add($src1, add($src2, #$src3))",
1199239462Sdim          [(set (i32 IntRegs:$dst),
1200239462Sdim           (add (i32 IntRegs:$src1), (add (i32 IntRegs:$src2),
1201249423Sdim                                          s6_16ExtPred:$src3)))]>,
1202234285Sdim          Requires<[HasV4T]>;
1203234285Sdim
1204234285Sdim//  Rd=add(Rs,sub(#s6,Ru))
1205249423Sdimlet isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 6,
1206249423SdimvalidSubTargets = HasV4SubT in
1207234285Sdimdef ADDr_SUBri_V4 : MInst<(outs IntRegs:$dst),
1208249423Sdim          (ins IntRegs:$src1, s6Ext:$src2, IntRegs:$src3),
1209234285Sdim          "$dst = add($src1, sub(#$src2, $src3))",
1210239462Sdim          [(set (i32 IntRegs:$dst),
1211249423Sdim           (add (i32 IntRegs:$src1), (sub s6_10ExtPred:$src2,
1212239462Sdim                                          (i32 IntRegs:$src3))))]>,
1213234285Sdim          Requires<[HasV4T]>;
1214234285Sdim
1215234285Sdim// Generates the same instruction as ADDr_SUBri_V4 but matches different
1216234285Sdim// pattern.
1217234285Sdim//  Rd=add(Rs,sub(#s6,Ru))
1218249423Sdimlet isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 6,
1219249423SdimvalidSubTargets = HasV4SubT in
1220234285Sdimdef ADDri_SUBr_V4 : MInst<(outs IntRegs:$dst),
1221249423Sdim          (ins IntRegs:$src1, s6Ext:$src2, IntRegs:$src3),
1222234285Sdim          "$dst = add($src1, sub(#$src2, $src3))",
1223239462Sdim          [(set (i32 IntRegs:$dst),
1224249423Sdim                (sub (add (i32 IntRegs:$src1), s6_10ExtPred:$src2),
1225239462Sdim                     (i32 IntRegs:$src3)))]>,
1226234285Sdim          Requires<[HasV4T]>;
1227234285Sdim
1228234285Sdim
1229234285Sdim//  Add or subtract doublewords with carry.
1230234285Sdim//TODO:
1231234285Sdim//  Rdd=add(Rss,Rtt,Px):carry
1232234285Sdim//TODO:
1233234285Sdim//  Rdd=sub(Rss,Rtt,Px):carry
1234234285Sdim
1235234285Sdim
1236234285Sdim//  Logical doublewords.
1237234285Sdim//  Rdd=and(Rtt,~Rss)
1238249423Sdimlet validSubTargets = HasV4SubT in
1239234285Sdimdef ANDd_NOTd_V4 : MInst<(outs DoubleRegs:$dst),
1240234285Sdim          (ins DoubleRegs:$src1, DoubleRegs:$src2),
1241234285Sdim          "$dst = and($src1, ~$src2)",
1242239462Sdim          [(set (i64 DoubleRegs:$dst), (and (i64 DoubleRegs:$src1),
1243239462Sdim                                      (not (i64 DoubleRegs:$src2))))]>,
1244234285Sdim          Requires<[HasV4T]>;
1245234285Sdim
1246234285Sdim//  Rdd=or(Rtt,~Rss)
1247249423Sdimlet validSubTargets = HasV4SubT in
1248234285Sdimdef ORd_NOTd_V4 : MInst<(outs DoubleRegs:$dst),
1249234285Sdim          (ins DoubleRegs:$src1, DoubleRegs:$src2),
1250234285Sdim          "$dst = or($src1, ~$src2)",
1251239462Sdim          [(set (i64 DoubleRegs:$dst),
1252239462Sdim           (or (i64 DoubleRegs:$src1), (not (i64 DoubleRegs:$src2))))]>,
1253234285Sdim          Requires<[HasV4T]>;
1254234285Sdim
1255234285Sdim
1256234285Sdim//  Logical-logical doublewords.
1257234285Sdim//  Rxx^=xor(Rss,Rtt)
1258249423Sdimlet validSubTargets = HasV4SubT in
1259234285Sdimdef XORd_XORdd: MInst_acc<(outs DoubleRegs:$dst),
1260234285Sdim          (ins DoubleRegs:$src1, DoubleRegs:$src2, DoubleRegs:$src3),
1261234285Sdim          "$dst ^= xor($src2, $src3)",
1262239462Sdim          [(set (i64 DoubleRegs:$dst),
1263239462Sdim           (xor (i64 DoubleRegs:$src1), (xor (i64 DoubleRegs:$src2),
1264239462Sdim                                             (i64 DoubleRegs:$src3))))],
1265234285Sdim          "$src1 = $dst">,
1266234285Sdim          Requires<[HasV4T]>;
1267234285Sdim
1268234285Sdim
1269234285Sdim// Logical-logical words.
1270234285Sdim// Rx=or(Ru,and(Rx,#s10))
1271249423Sdimlet isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 10,
1272249423SdimvalidSubTargets = HasV4SubT in
1273234285Sdimdef ORr_ANDri_V4 : MInst_acc<(outs IntRegs:$dst),
1274249423Sdim            (ins IntRegs:$src1, IntRegs: $src2, s10Ext:$src3),
1275234285Sdim            "$dst = or($src1, and($src2, #$src3))",
1276239462Sdim            [(set (i32 IntRegs:$dst),
1277239462Sdim                  (or (i32 IntRegs:$src1), (and (i32 IntRegs:$src2),
1278249423Sdim                                                s10ExtPred:$src3)))],
1279234285Sdim            "$src2 = $dst">,
1280234285Sdim            Requires<[HasV4T]>;
1281234285Sdim
1282234285Sdim// Rx[&|^]=and(Rs,Rt)
1283234285Sdim// Rx&=and(Rs,Rt)
1284249423Sdimlet validSubTargets = HasV4SubT in
1285234285Sdimdef ANDr_ANDrr_V4 : MInst_acc<(outs IntRegs:$dst),
1286234285Sdim            (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3),
1287234285Sdim            "$dst &= and($src2, $src3)",
1288239462Sdim            [(set (i32 IntRegs:$dst),
1289239462Sdim                  (and (i32 IntRegs:$src1), (and (i32 IntRegs:$src2),
1290239462Sdim                                                 (i32 IntRegs:$src3))))],
1291234285Sdim            "$src1 = $dst">,
1292234285Sdim            Requires<[HasV4T]>;
1293234285Sdim
1294234285Sdim// Rx|=and(Rs,Rt)
1295249423Sdimlet validSubTargets = HasV4SubT, CextOpcode = "ORr_ANDr", InputType = "reg" in
1296234285Sdimdef ORr_ANDrr_V4 : MInst_acc<(outs IntRegs:$dst),
1297234285Sdim            (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3),
1298234285Sdim            "$dst |= and($src2, $src3)",
1299239462Sdim            [(set (i32 IntRegs:$dst),
1300239462Sdim                  (or (i32 IntRegs:$src1), (and (i32 IntRegs:$src2),
1301239462Sdim                                                (i32 IntRegs:$src3))))],
1302234285Sdim            "$src1 = $dst">,
1303249423Sdim            Requires<[HasV4T]>, ImmRegRel;
1304234285Sdim
1305234285Sdim// Rx^=and(Rs,Rt)
1306249423Sdimlet validSubTargets = HasV4SubT in
1307234285Sdimdef XORr_ANDrr_V4 : MInst_acc<(outs IntRegs:$dst),
1308234285Sdim            (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3),
1309234285Sdim            "$dst ^= and($src2, $src3)",
1310239462Sdim            [(set (i32 IntRegs:$dst),
1311239462Sdim             (xor (i32 IntRegs:$src1), (and (i32 IntRegs:$src2),
1312239462Sdim                                            (i32 IntRegs:$src3))))],
1313234285Sdim            "$src1 = $dst">,
1314234285Sdim            Requires<[HasV4T]>;
1315234285Sdim
1316234285Sdim// Rx[&|^]=and(Rs,~Rt)
1317234285Sdim// Rx&=and(Rs,~Rt)
1318249423Sdimlet validSubTargets = HasV4SubT in
1319234285Sdimdef ANDr_ANDr_NOTr_V4 : MInst_acc<(outs IntRegs:$dst),
1320234285Sdim            (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3),
1321234285Sdim            "$dst &= and($src2, ~$src3)",
1322239462Sdim            [(set (i32 IntRegs:$dst),
1323239462Sdim                  (and (i32 IntRegs:$src1), (and (i32 IntRegs:$src2),
1324239462Sdim                                                 (not (i32 IntRegs:$src3)))))],
1325234285Sdim            "$src1 = $dst">,
1326234285Sdim            Requires<[HasV4T]>;
1327234285Sdim
1328234285Sdim// Rx|=and(Rs,~Rt)
1329249423Sdimlet validSubTargets = HasV4SubT in
1330234285Sdimdef ORr_ANDr_NOTr_V4 : MInst_acc<(outs IntRegs:$dst),
1331234285Sdim            (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3),
1332234285Sdim            "$dst |= and($src2, ~$src3)",
1333239462Sdim            [(set (i32 IntRegs:$dst),
1334239462Sdim             (or (i32 IntRegs:$src1), (and (i32 IntRegs:$src2),
1335239462Sdim                                           (not (i32 IntRegs:$src3)))))],
1336234285Sdim            "$src1 = $dst">,
1337234285Sdim            Requires<[HasV4T]>;
1338234285Sdim
1339234285Sdim// Rx^=and(Rs,~Rt)
1340249423Sdimlet validSubTargets = HasV4SubT in
1341234285Sdimdef XORr_ANDr_NOTr_V4 : MInst_acc<(outs IntRegs:$dst),
1342234285Sdim            (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3),
1343234285Sdim            "$dst ^= and($src2, ~$src3)",
1344239462Sdim            [(set (i32 IntRegs:$dst),
1345239462Sdim             (xor (i32 IntRegs:$src1), (and (i32 IntRegs:$src2),
1346239462Sdim                                            (not (i32 IntRegs:$src3)))))],
1347234285Sdim            "$src1 = $dst">,
1348234285Sdim            Requires<[HasV4T]>;
1349234285Sdim
1350234285Sdim// Rx[&|^]=or(Rs,Rt)
1351234285Sdim// Rx&=or(Rs,Rt)
1352249423Sdimlet validSubTargets = HasV4SubT in
1353234285Sdimdef ANDr_ORrr_V4 : MInst_acc<(outs IntRegs:$dst),
1354234285Sdim            (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3),
1355234285Sdim            "$dst &= or($src2, $src3)",
1356239462Sdim            [(set (i32 IntRegs:$dst),
1357239462Sdim                  (and (i32 IntRegs:$src1), (or (i32 IntRegs:$src2),
1358239462Sdim                                                (i32 IntRegs:$src3))))],
1359234285Sdim            "$src1 = $dst">,
1360234285Sdim            Requires<[HasV4T]>;
1361234285Sdim
1362234285Sdim// Rx|=or(Rs,Rt)
1363249423Sdimlet validSubTargets = HasV4SubT, CextOpcode = "ORr_ORr", InputType = "reg" in
1364234285Sdimdef ORr_ORrr_V4 : MInst_acc<(outs IntRegs:$dst),
1365234285Sdim            (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3),
1366234285Sdim            "$dst |= or($src2, $src3)",
1367239462Sdim            [(set (i32 IntRegs:$dst),
1368239462Sdim                  (or (i32 IntRegs:$src1), (or (i32 IntRegs:$src2),
1369239462Sdim                                               (i32 IntRegs:$src3))))],
1370234285Sdim            "$src1 = $dst">,
1371249423Sdim            Requires<[HasV4T]>, ImmRegRel;
1372234285Sdim
1373234285Sdim// Rx^=or(Rs,Rt)
1374249423Sdimlet validSubTargets = HasV4SubT in
1375234285Sdimdef XORr_ORrr_V4 : MInst_acc<(outs IntRegs:$dst),
1376234285Sdim            (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3),
1377234285Sdim            "$dst ^= or($src2, $src3)",
1378239462Sdim            [(set (i32 IntRegs:$dst),
1379239462Sdim             (xor (i32 IntRegs:$src1), (or (i32 IntRegs:$src2),
1380239462Sdim                                           (i32 IntRegs:$src3))))],
1381234285Sdim            "$src1 = $dst">,
1382234285Sdim            Requires<[HasV4T]>;
1383234285Sdim
1384234285Sdim// Rx[&|^]=xor(Rs,Rt)
1385234285Sdim// Rx&=xor(Rs,Rt)
1386249423Sdimlet validSubTargets = HasV4SubT in
1387234285Sdimdef ANDr_XORrr_V4 : MInst_acc<(outs IntRegs:$dst),
1388234285Sdim            (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3),
1389234285Sdim            "$dst &= xor($src2, $src3)",
1390239462Sdim            [(set (i32 IntRegs:$dst),
1391239462Sdim                  (and (i32 IntRegs:$src1), (xor (i32 IntRegs:$src2),
1392239462Sdim                                                 (i32 IntRegs:$src3))))],
1393234285Sdim            "$src1 = $dst">,
1394234285Sdim            Requires<[HasV4T]>;
1395234285Sdim
1396234285Sdim// Rx|=xor(Rs,Rt)
1397249423Sdimlet validSubTargets = HasV4SubT in
1398234285Sdimdef ORr_XORrr_V4 : MInst_acc<(outs IntRegs:$dst),
1399234285Sdim            (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3),
1400234285Sdim            "$dst |= xor($src2, $src3)",
1401239462Sdim            [(set (i32 IntRegs:$dst),
1402239462Sdim                  (and (i32 IntRegs:$src1), (xor (i32 IntRegs:$src2),
1403239462Sdim                                                 (i32 IntRegs:$src3))))],
1404234285Sdim            "$src1 = $dst">,
1405234285Sdim            Requires<[HasV4T]>;
1406234285Sdim
1407234285Sdim// Rx^=xor(Rs,Rt)
1408249423Sdimlet validSubTargets = HasV4SubT in
1409234285Sdimdef XORr_XORrr_V4 : MInst_acc<(outs IntRegs:$dst),
1410234285Sdim            (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3),
1411234285Sdim            "$dst ^= xor($src2, $src3)",
1412239462Sdim            [(set (i32 IntRegs:$dst),
1413239462Sdim             (and (i32 IntRegs:$src1), (xor (i32 IntRegs:$src2),
1414239462Sdim                                            (i32 IntRegs:$src3))))],
1415234285Sdim            "$src1 = $dst">,
1416234285Sdim            Requires<[HasV4T]>;
1417234285Sdim
1418234285Sdim// Rx|=and(Rs,#s10)
1419249423Sdimlet isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 10,
1420249423SdimvalidSubTargets = HasV4SubT, CextOpcode = "ORr_ANDr", InputType = "imm" in
1421234285Sdimdef ORr_ANDri2_V4 : MInst_acc<(outs IntRegs:$dst),
1422249423Sdim            (ins IntRegs:$src1, IntRegs: $src2, s10Ext:$src3),
1423234285Sdim            "$dst |= and($src2, #$src3)",
1424239462Sdim            [(set (i32 IntRegs:$dst),
1425239462Sdim                  (or (i32 IntRegs:$src1), (and (i32 IntRegs:$src2),
1426249423Sdim                                                s10ExtPred:$src3)))],
1427234285Sdim            "$src1 = $dst">,
1428249423Sdim            Requires<[HasV4T]>, ImmRegRel;
1429234285Sdim
1430234285Sdim// Rx|=or(Rs,#s10)
1431249423Sdimlet isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 10,
1432249423SdimvalidSubTargets = HasV4SubT, CextOpcode = "ORr_ORr", InputType = "imm" in
1433234285Sdimdef ORr_ORri_V4 : MInst_acc<(outs IntRegs:$dst),
1434249423Sdim            (ins IntRegs:$src1, IntRegs: $src2, s10Ext:$src3),
1435234285Sdim            "$dst |= or($src2, #$src3)",
1436239462Sdim            [(set (i32 IntRegs:$dst),
1437239462Sdim                  (or (i32 IntRegs:$src1), (and (i32 IntRegs:$src2),
1438249423Sdim                                                s10ExtPred:$src3)))],
1439234285Sdim            "$src1 = $dst">,
1440249423Sdim            Requires<[HasV4T]>, ImmRegRel;
1441234285Sdim
1442234285Sdim
1443234285Sdim//    Modulo wrap
1444234285Sdim//        Rd=modwrap(Rs,Rt)
1445234285Sdim//    Round
1446234285Sdim//        Rd=cround(Rs,#u5)
1447234285Sdim//        Rd=cround(Rs,Rt)
1448234285Sdim//        Rd=round(Rs,#u5)[:sat]
1449234285Sdim//        Rd=round(Rs,Rt)[:sat]
1450234285Sdim//    Vector reduce add unsigned halfwords
1451234285Sdim//        Rd=vraddh(Rss,Rtt)
1452234285Sdim//    Vector add bytes
1453234285Sdim//        Rdd=vaddb(Rss,Rtt)
1454234285Sdim//    Vector conditional negate
1455234285Sdim//        Rdd=vcnegh(Rss,Rt)
1456234285Sdim//        Rxx+=vrcnegh(Rss,Rt)
1457234285Sdim//    Vector maximum bytes
1458234285Sdim//        Rdd=vmaxb(Rtt,Rss)
1459234285Sdim//    Vector reduce maximum halfwords
1460234285Sdim//        Rxx=vrmaxh(Rss,Ru)
1461234285Sdim//        Rxx=vrmaxuh(Rss,Ru)
1462234285Sdim//    Vector reduce maximum words
1463234285Sdim//        Rxx=vrmaxuw(Rss,Ru)
1464234285Sdim//        Rxx=vrmaxw(Rss,Ru)
1465234285Sdim//    Vector minimum bytes
1466234285Sdim//        Rdd=vminb(Rtt,Rss)
1467234285Sdim//    Vector reduce minimum halfwords
1468234285Sdim//        Rxx=vrminh(Rss,Ru)
1469234285Sdim//        Rxx=vrminuh(Rss,Ru)
1470234285Sdim//    Vector reduce minimum words
1471234285Sdim//        Rxx=vrminuw(Rss,Ru)
1472234285Sdim//        Rxx=vrminw(Rss,Ru)
1473234285Sdim//    Vector subtract bytes
1474234285Sdim//        Rdd=vsubb(Rss,Rtt)
1475234285Sdim
1476234285Sdim//===----------------------------------------------------------------------===//
1477234285Sdim// XTYPE/ALU -
1478234285Sdim//===----------------------------------------------------------------------===//
1479234285Sdim
1480234285Sdim
1481234285Sdim//===----------------------------------------------------------------------===//
1482234285Sdim// XTYPE/MPY +
1483234285Sdim//===----------------------------------------------------------------------===//
1484234285Sdim
1485234285Sdim// Multiply and user lower result.
1486234285Sdim// Rd=add(#u6,mpyi(Rs,#U6))
1487249423Sdimlet isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 6,
1488249423SdimvalidSubTargets = HasV4SubT in
1489234285Sdimdef ADDi_MPYri_V4 : MInst<(outs IntRegs:$dst),
1490249423Sdim            (ins u6Ext:$src1, IntRegs:$src2, u6Imm:$src3),
1491234285Sdim            "$dst = add(#$src1, mpyi($src2, #$src3))",
1492239462Sdim            [(set (i32 IntRegs:$dst),
1493239462Sdim                  (add (mul (i32 IntRegs:$src2), u6ImmPred:$src3),
1494249423Sdim                       u6ExtPred:$src1))]>,
1495234285Sdim            Requires<[HasV4T]>;
1496234285Sdim
1497249423Sdim// Rd=add(##,mpyi(Rs,#U6))
1498249423Sdimdef : Pat <(add (mul (i32 IntRegs:$src2), u6ImmPred:$src3),
1499249423Sdim                     (HexagonCONST32 tglobaladdr:$src1)),
1500249423Sdim           (i32 (ADDi_MPYri_V4 tglobaladdr:$src1, IntRegs:$src2,
1501249423Sdim                               u6ImmPred:$src3))>;
1502249423Sdim
1503234285Sdim// Rd=add(#u6,mpyi(Rs,Rt))
1504249423Sdimlet isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 6,
1505249423SdimvalidSubTargets = HasV4SubT, InputType = "imm", CextOpcode = "ADD_MPY" in
1506234285Sdimdef ADDi_MPYrr_V4 : MInst<(outs IntRegs:$dst),
1507249423Sdim            (ins u6Ext:$src1, IntRegs:$src2, IntRegs:$src3),
1508234285Sdim            "$dst = add(#$src1, mpyi($src2, $src3))",
1509239462Sdim            [(set (i32 IntRegs:$dst),
1510239462Sdim                  (add (mul (i32 IntRegs:$src2), (i32 IntRegs:$src3)),
1511249423Sdim                       u6ExtPred:$src1))]>,
1512249423Sdim            Requires<[HasV4T]>, ImmRegRel;
1513234285Sdim
1514249423Sdim// Rd=add(##,mpyi(Rs,Rt))
1515249423Sdimdef : Pat <(add (mul (i32 IntRegs:$src2), (i32 IntRegs:$src3)),
1516249423Sdim                     (HexagonCONST32 tglobaladdr:$src1)),
1517249423Sdim           (i32 (ADDi_MPYrr_V4 tglobaladdr:$src1, IntRegs:$src2,
1518249423Sdim                               IntRegs:$src3))>;
1519249423Sdim
1520234285Sdim// Rd=add(Ru,mpyi(#u6:2,Rs))
1521249423Sdimlet validSubTargets = HasV4SubT in
1522234285Sdimdef ADDr_MPYir_V4 : MInst<(outs IntRegs:$dst),
1523234285Sdim            (ins IntRegs:$src1, u6Imm:$src2, IntRegs:$src3),
1524234285Sdim            "$dst = add($src1, mpyi(#$src2, $src3))",
1525239462Sdim            [(set (i32 IntRegs:$dst),
1526239462Sdim             (add (i32 IntRegs:$src1), (mul (i32 IntRegs:$src3),
1527239462Sdim                                            u6_2ImmPred:$src2)))]>,
1528234285Sdim            Requires<[HasV4T]>;
1529234285Sdim
1530234285Sdim// Rd=add(Ru,mpyi(Rs,#u6))
1531249423Sdimlet isExtendable = 1, opExtendable = 3, isExtentSigned = 0, opExtentBits = 6,
1532249423SdimvalidSubTargets = HasV4SubT, InputType = "imm", CextOpcode = "ADD_MPY" in
1533234285Sdimdef ADDr_MPYri_V4 : MInst<(outs IntRegs:$dst),
1534249423Sdim            (ins IntRegs:$src1, IntRegs:$src2, u6Ext:$src3),
1535234285Sdim            "$dst = add($src1, mpyi($src2, #$src3))",
1536239462Sdim            [(set (i32 IntRegs:$dst),
1537239462Sdim                  (add (i32 IntRegs:$src1), (mul (i32 IntRegs:$src2),
1538249423Sdim                                                 u6ExtPred:$src3)))]>,
1539249423Sdim            Requires<[HasV4T]>, ImmRegRel;
1540234285Sdim
1541234285Sdim// Rx=add(Ru,mpyi(Rx,Rs))
1542249423Sdimlet validSubTargets = HasV4SubT, InputType = "reg", CextOpcode = "ADD_MPY" in
1543234285Sdimdef ADDr_MPYrr_V4 : MInst_acc<(outs IntRegs:$dst),
1544234285Sdim            (ins IntRegs:$src1, IntRegs:$src2, IntRegs:$src3),
1545234285Sdim            "$dst = add($src1, mpyi($src2, $src3))",
1546239462Sdim            [(set (i32 IntRegs:$dst),
1547239462Sdim             (add (i32 IntRegs:$src1), (mul (i32 IntRegs:$src2),
1548239462Sdim                                            (i32 IntRegs:$src3))))],
1549234285Sdim            "$src2 = $dst">,
1550249423Sdim            Requires<[HasV4T]>, ImmRegRel;
1551234285Sdim
1552234285Sdim
1553234285Sdim// Polynomial multiply words
1554234285Sdim// Rdd=pmpyw(Rs,Rt)
1555234285Sdim// Rxx^=pmpyw(Rs,Rt)
1556234285Sdim
1557234285Sdim// Vector reduce multiply word by signed half (32x16)
1558234285Sdim// Rdd=vrmpyweh(Rss,Rtt)[:<<1]
1559234285Sdim// Rdd=vrmpywoh(Rss,Rtt)[:<<1]
1560234285Sdim// Rxx+=vrmpyweh(Rss,Rtt)[:<<1]
1561234285Sdim// Rxx+=vrmpywoh(Rss,Rtt)[:<<1]
1562234285Sdim
1563234285Sdim// Multiply and use upper result
1564234285Sdim// Rd=mpy(Rs,Rt.H):<<1:sat
1565234285Sdim// Rd=mpy(Rs,Rt.L):<<1:sat
1566234285Sdim// Rd=mpy(Rs,Rt):<<1
1567234285Sdim// Rd=mpy(Rs,Rt):<<1:sat
1568234285Sdim// Rd=mpysu(Rs,Rt)
1569234285Sdim// Rx+=mpy(Rs,Rt):<<1:sat
1570234285Sdim// Rx-=mpy(Rs,Rt):<<1:sat
1571234285Sdim
1572234285Sdim// Vector multiply bytes
1573234285Sdim// Rdd=vmpybsu(Rs,Rt)
1574234285Sdim// Rdd=vmpybu(Rs,Rt)
1575234285Sdim// Rxx+=vmpybsu(Rs,Rt)
1576234285Sdim// Rxx+=vmpybu(Rs,Rt)
1577234285Sdim
1578234285Sdim// Vector polynomial multiply halfwords
1579234285Sdim// Rdd=vpmpyh(Rs,Rt)
1580234285Sdim// Rxx^=vpmpyh(Rs,Rt)
1581234285Sdim
1582234285Sdim//===----------------------------------------------------------------------===//
1583234285Sdim// XTYPE/MPY -
1584234285Sdim//===----------------------------------------------------------------------===//
1585234285Sdim
1586234285Sdim
1587234285Sdim//===----------------------------------------------------------------------===//
1588234285Sdim// XTYPE/SHIFT +
1589234285Sdim//===----------------------------------------------------------------------===//
1590234285Sdim
1591234285Sdim// Shift by immediate and accumulate.
1592234285Sdim// Rx=add(#u8,asl(Rx,#U5))
1593249423Sdimlet isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8,
1594249423SdimvalidSubTargets = HasV4SubT in
1595234285Sdimdef ADDi_ASLri_V4 : MInst_acc<(outs IntRegs:$dst),
1596249423Sdim            (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3),
1597234285Sdim            "$dst = add(#$src1, asl($src2, #$src3))",
1598239462Sdim            [(set (i32 IntRegs:$dst),
1599239462Sdim                  (add (shl (i32 IntRegs:$src2), u5ImmPred:$src3),
1600249423Sdim                       u8ExtPred:$src1))],
1601234285Sdim            "$src2 = $dst">,
1602234285Sdim            Requires<[HasV4T]>;
1603234285Sdim
1604234285Sdim// Rx=add(#u8,lsr(Rx,#U5))
1605249423Sdimlet isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8,
1606249423SdimvalidSubTargets = HasV4SubT in
1607234285Sdimdef ADDi_LSRri_V4 : MInst_acc<(outs IntRegs:$dst),
1608249423Sdim            (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3),
1609234285Sdim            "$dst = add(#$src1, lsr($src2, #$src3))",
1610239462Sdim            [(set (i32 IntRegs:$dst),
1611239462Sdim                  (add (srl (i32 IntRegs:$src2), u5ImmPred:$src3),
1612249423Sdim                       u8ExtPred:$src1))],
1613234285Sdim            "$src2 = $dst">,
1614234285Sdim            Requires<[HasV4T]>;
1615234285Sdim
1616234285Sdim// Rx=sub(#u8,asl(Rx,#U5))
1617249423Sdimlet isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8,
1618249423SdimvalidSubTargets = HasV4SubT in
1619234285Sdimdef SUBi_ASLri_V4 : MInst_acc<(outs IntRegs:$dst),
1620249423Sdim            (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3),
1621234285Sdim            "$dst = sub(#$src1, asl($src2, #$src3))",
1622239462Sdim            [(set (i32 IntRegs:$dst),
1623239462Sdim                  (sub (shl (i32 IntRegs:$src2), u5ImmPred:$src3),
1624249423Sdim                       u8ExtPred:$src1))],
1625234285Sdim            "$src2 = $dst">,
1626234285Sdim            Requires<[HasV4T]>;
1627234285Sdim
1628234285Sdim// Rx=sub(#u8,lsr(Rx,#U5))
1629249423Sdimlet isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8,
1630249423SdimvalidSubTargets = HasV4SubT in
1631234285Sdimdef SUBi_LSRri_V4 : MInst_acc<(outs IntRegs:$dst),
1632249423Sdim            (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3),
1633234285Sdim            "$dst = sub(#$src1, lsr($src2, #$src3))",
1634239462Sdim            [(set (i32 IntRegs:$dst),
1635239462Sdim                  (sub (srl (i32 IntRegs:$src2), u5ImmPred:$src3),
1636249423Sdim                       u8ExtPred:$src1))],
1637234285Sdim            "$src2 = $dst">,
1638234285Sdim            Requires<[HasV4T]>;
1639234285Sdim
1640234285Sdim
1641234285Sdim//Shift by immediate and logical.
1642234285Sdim//Rx=and(#u8,asl(Rx,#U5))
1643249423Sdimlet isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8,
1644249423SdimvalidSubTargets = HasV4SubT in
1645234285Sdimdef ANDi_ASLri_V4 : MInst_acc<(outs IntRegs:$dst),
1646249423Sdim            (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3),
1647234285Sdim            "$dst = and(#$src1, asl($src2, #$src3))",
1648239462Sdim            [(set (i32 IntRegs:$dst),
1649239462Sdim                  (and (shl (i32 IntRegs:$src2), u5ImmPred:$src3),
1650249423Sdim                       u8ExtPred:$src1))],
1651234285Sdim            "$src2 = $dst">,
1652234285Sdim            Requires<[HasV4T]>;
1653234285Sdim
1654234285Sdim//Rx=and(#u8,lsr(Rx,#U5))
1655249423Sdimlet isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8,
1656249423SdimvalidSubTargets = HasV4SubT in
1657234285Sdimdef ANDi_LSRri_V4 : MInst_acc<(outs IntRegs:$dst),
1658249423Sdim            (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3),
1659234285Sdim            "$dst = and(#$src1, lsr($src2, #$src3))",
1660239462Sdim            [(set (i32 IntRegs:$dst),
1661239462Sdim                  (and (srl (i32 IntRegs:$src2), u5ImmPred:$src3),
1662249423Sdim                       u8ExtPred:$src1))],
1663234285Sdim            "$src2 = $dst">,
1664234285Sdim            Requires<[HasV4T]>;
1665234285Sdim
1666234285Sdim//Rx=or(#u8,asl(Rx,#U5))
1667249423Sdimlet isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8,
1668249423SdimAddedComplexity = 30, validSubTargets = HasV4SubT in
1669234285Sdimdef ORi_ASLri_V4 : MInst_acc<(outs IntRegs:$dst),
1670249423Sdim            (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3),
1671234285Sdim            "$dst = or(#$src1, asl($src2, #$src3))",
1672239462Sdim            [(set (i32 IntRegs:$dst),
1673239462Sdim                  (or (shl (i32 IntRegs:$src2), u5ImmPred:$src3),
1674249423Sdim                      u8ExtPred:$src1))],
1675234285Sdim            "$src2 = $dst">,
1676234285Sdim            Requires<[HasV4T]>;
1677234285Sdim
1678234285Sdim//Rx=or(#u8,lsr(Rx,#U5))
1679249423Sdimlet isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8,
1680249423SdimAddedComplexity = 30, validSubTargets = HasV4SubT in
1681234285Sdimdef ORi_LSRri_V4 : MInst_acc<(outs IntRegs:$dst),
1682249423Sdim            (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3),
1683234285Sdim            "$dst = or(#$src1, lsr($src2, #$src3))",
1684239462Sdim            [(set (i32 IntRegs:$dst),
1685239462Sdim                  (or (srl (i32 IntRegs:$src2), u5ImmPred:$src3),
1686249423Sdim                      u8ExtPred:$src1))],
1687234285Sdim            "$src2 = $dst">,
1688234285Sdim            Requires<[HasV4T]>;
1689234285Sdim
1690234285Sdim
1691234285Sdim//Shift by register.
1692234285Sdim//Rd=lsl(#s6,Rt)
1693249423Sdimlet validSubTargets = HasV4SubT in {
1694234285Sdimdef LSLi_V4 : MInst<(outs IntRegs:$dst), (ins s6Imm:$src1, IntRegs:$src2),
1695234285Sdim            "$dst = lsl(#$src1, $src2)",
1696239462Sdim            [(set (i32 IntRegs:$dst), (shl s6ImmPred:$src1,
1697239462Sdim                                           (i32 IntRegs:$src2)))]>,
1698234285Sdim            Requires<[HasV4T]>;
1699234285Sdim
1700234285Sdim
1701234285Sdim//Shift by register and logical.
1702234285Sdim//Rxx^=asl(Rss,Rt)
1703234285Sdimdef ASLd_rr_xor_V4 : MInst_acc<(outs DoubleRegs:$dst),
1704234285Sdim            (ins DoubleRegs:$src1, DoubleRegs:$src2, IntRegs:$src3),
1705234285Sdim            "$dst ^= asl($src2, $src3)",
1706239462Sdim            [(set (i64 DoubleRegs:$dst),
1707239462Sdim                  (xor (i64 DoubleRegs:$src1), (shl (i64 DoubleRegs:$src2),
1708239462Sdim                                                    (i32 IntRegs:$src3))))],
1709234285Sdim            "$src1 = $dst">,
1710234285Sdim            Requires<[HasV4T]>;
1711234285Sdim
1712234285Sdim//Rxx^=asr(Rss,Rt)
1713234285Sdimdef ASRd_rr_xor_V4 : MInst_acc<(outs DoubleRegs:$dst),
1714234285Sdim            (ins DoubleRegs:$src1, DoubleRegs:$src2, IntRegs:$src3),
1715234285Sdim            "$dst ^= asr($src2, $src3)",
1716239462Sdim            [(set (i64 DoubleRegs:$dst),
1717239462Sdim                  (xor (i64 DoubleRegs:$src1), (sra (i64 DoubleRegs:$src2),
1718239462Sdim                                                    (i32 IntRegs:$src3))))],
1719234285Sdim            "$src1 = $dst">,
1720234285Sdim            Requires<[HasV4T]>;
1721234285Sdim
1722234285Sdim//Rxx^=lsl(Rss,Rt)
1723234285Sdimdef LSLd_rr_xor_V4 : MInst_acc<(outs DoubleRegs:$dst),
1724234285Sdim            (ins DoubleRegs:$src1, DoubleRegs:$src2, IntRegs:$src3),
1725234285Sdim            "$dst ^= lsl($src2, $src3)",
1726239462Sdim            [(set (i64 DoubleRegs:$dst), (xor (i64 DoubleRegs:$src1),
1727239462Sdim                                              (shl (i64 DoubleRegs:$src2),
1728239462Sdim                                                   (i32 IntRegs:$src3))))],
1729234285Sdim            "$src1 = $dst">,
1730234285Sdim            Requires<[HasV4T]>;
1731234285Sdim
1732234285Sdim//Rxx^=lsr(Rss,Rt)
1733234285Sdimdef LSRd_rr_xor_V4 : MInst_acc<(outs DoubleRegs:$dst),
1734234285Sdim            (ins DoubleRegs:$src1, DoubleRegs:$src2, IntRegs:$src3),
1735234285Sdim            "$dst ^= lsr($src2, $src3)",
1736239462Sdim            [(set (i64 DoubleRegs:$dst),
1737239462Sdim                  (xor (i64 DoubleRegs:$src1), (srl (i64 DoubleRegs:$src2),
1738239462Sdim                                                    (i32 IntRegs:$src3))))],
1739234285Sdim            "$src1 = $dst">,
1740234285Sdim            Requires<[HasV4T]>;
1741249423Sdim}
1742234285Sdim
1743234285Sdim//===----------------------------------------------------------------------===//
1744234285Sdim// XTYPE/SHIFT -
1745234285Sdim//===----------------------------------------------------------------------===//
1746234285Sdim
1747234285Sdim//===----------------------------------------------------------------------===//
1748234285Sdim// MEMOP: Word, Half, Byte
1749234285Sdim//===----------------------------------------------------------------------===//
1750234285Sdim
1751249423Sdimdef MEMOPIMM : SDNodeXForm<imm, [{
1752249423Sdim  // Call the transformation function XformM5ToU5Imm to get the negative
1753249423Sdim  // immediate's positive counterpart.
1754249423Sdim  int32_t imm = N->getSExtValue();
1755249423Sdim  return XformM5ToU5Imm(imm);
1756249423Sdim}]>;
1757234285Sdim
1758249423Sdimdef MEMOPIMM_HALF : SDNodeXForm<imm, [{
1759249423Sdim  // -1 .. -31 represented as 65535..65515
1760249423Sdim  // assigning to a short restores our desired signed value.
1761249423Sdim  // Call the transformation function XformM5ToU5Imm to get the negative
1762249423Sdim  // immediate's positive counterpart.
1763249423Sdim  int16_t imm = N->getSExtValue();
1764249423Sdim  return XformM5ToU5Imm(imm);
1765249423Sdim}]>;
1766234285Sdim
1767249423Sdimdef MEMOPIMM_BYTE : SDNodeXForm<imm, [{
1768249423Sdim  // -1 .. -31 represented as 255..235
1769249423Sdim  // assigning to a char restores our desired signed value.
1770249423Sdim  // Call the transformation function XformM5ToU5Imm to get the negative
1771249423Sdim  // immediate's positive counterpart.
1772249423Sdim  int8_t imm = N->getSExtValue();
1773249423Sdim  return XformM5ToU5Imm(imm);
1774249423Sdim}]>;
1775234285Sdim
1776249423Sdimdef SETMEMIMM : SDNodeXForm<imm, [{
1777249423Sdim   // Return the bit position we will set [0-31].
1778249423Sdim   // As an SDNode.
1779249423Sdim   int32_t imm = N->getSExtValue();
1780249423Sdim   return XformMskToBitPosU5Imm(imm);
1781249423Sdim}]>;
1782234285Sdim
1783249423Sdimdef CLRMEMIMM : SDNodeXForm<imm, [{
1784249423Sdim   // Return the bit position we will clear [0-31].
1785249423Sdim   // As an SDNode.
1786249423Sdim   // we bit negate the value first
1787249423Sdim   int32_t imm = ~(N->getSExtValue());
1788249423Sdim   return XformMskToBitPosU5Imm(imm);
1789249423Sdim}]>;
1790234285Sdim
1791249423Sdimdef SETMEMIMM_SHORT : SDNodeXForm<imm, [{
1792249423Sdim   // Return the bit position we will set [0-15].
1793249423Sdim   // As an SDNode.
1794249423Sdim   int16_t imm = N->getSExtValue();
1795249423Sdim   return XformMskToBitPosU4Imm(imm);
1796249423Sdim}]>;
1797234285Sdim
1798249423Sdimdef CLRMEMIMM_SHORT : SDNodeXForm<imm, [{
1799249423Sdim   // Return the bit position we will clear [0-15].
1800249423Sdim   // As an SDNode.
1801249423Sdim   // we bit negate the value first
1802249423Sdim   int16_t imm = ~(N->getSExtValue());
1803249423Sdim   return XformMskToBitPosU4Imm(imm);
1804249423Sdim}]>;
1805234285Sdim
1806249423Sdimdef SETMEMIMM_BYTE : SDNodeXForm<imm, [{
1807249423Sdim   // Return the bit position we will set [0-7].
1808249423Sdim   // As an SDNode.
1809249423Sdim   int8_t imm =  N->getSExtValue();
1810249423Sdim   return XformMskToBitPosU3Imm(imm);
1811249423Sdim}]>;
1812234285Sdim
1813249423Sdimdef CLRMEMIMM_BYTE : SDNodeXForm<imm, [{
1814249423Sdim   // Return the bit position we will clear [0-7].
1815249423Sdim   // As an SDNode.
1816249423Sdim   // we bit negate the value first
1817249423Sdim   int8_t imm = ~(N->getSExtValue());
1818249423Sdim   return XformMskToBitPosU3Imm(imm);
1819249423Sdim}]>;
1820234285Sdim
1821249423Sdim//===----------------------------------------------------------------------===//
1822249423Sdim// Template class for MemOp instructions with the register value.
1823249423Sdim//===----------------------------------------------------------------------===//
1824249423Sdimclass MemOp_rr_base <string opc, bits<2> opcBits, Operand ImmOp,
1825249423Sdim                     string memOp, bits<2> memOpBits> :
1826249423Sdim      MEMInst_V4<(outs),
1827249423Sdim                 (ins IntRegs:$base, ImmOp:$offset, IntRegs:$delta),
1828249423Sdim                 opc#"($base+#$offset)"#memOp#"$delta",
1829249423Sdim                 []>,
1830249423Sdim                 Requires<[HasV4T, UseMEMOP]> {
1831234285Sdim
1832249423Sdim    bits<5> base;
1833249423Sdim    bits<5> delta;
1834249423Sdim    bits<32> offset;
1835249423Sdim    bits<6> offsetBits; // memb - u6:0 , memh - u6:1, memw - u6:2
1836234285Sdim
1837249423Sdim    let offsetBits = !if (!eq(opcBits, 0b00), offset{5-0},
1838249423Sdim                     !if (!eq(opcBits, 0b01), offset{6-1},
1839249423Sdim                     !if (!eq(opcBits, 0b10), offset{7-2},0)));
1840234285Sdim
1841249423Sdim    let IClass = 0b0011;
1842249423Sdim    let Inst{27-24} = 0b1110;
1843249423Sdim    let Inst{22-21} = opcBits;
1844249423Sdim    let Inst{20-16} = base;
1845249423Sdim    let Inst{13} = 0b0;
1846249423Sdim    let Inst{12-7} = offsetBits;
1847249423Sdim    let Inst{6-5} = memOpBits;
1848249423Sdim    let Inst{4-0} = delta;
1849249423Sdim}
1850234285Sdim
1851234285Sdim//===----------------------------------------------------------------------===//
1852249423Sdim// Template class for MemOp instructions with the immediate value.
1853234285Sdim//===----------------------------------------------------------------------===//
1854249423Sdimclass MemOp_ri_base <string opc, bits<2> opcBits, Operand ImmOp,
1855249423Sdim                     string memOp, bits<2> memOpBits> :
1856249423Sdim      MEMInst_V4 <(outs),
1857249423Sdim                  (ins IntRegs:$base, ImmOp:$offset, u5Imm:$delta),
1858249423Sdim                  opc#"($base+#$offset)"#memOp#"#$delta"
1859249423Sdim                  #!if(memOpBits{1},")", ""), // clrbit, setbit - include ')'
1860249423Sdim                  []>,
1861249423Sdim                  Requires<[HasV4T, UseMEMOP]> {
1862234285Sdim
1863249423Sdim    bits<5> base;
1864249423Sdim    bits<5> delta;
1865249423Sdim    bits<32> offset;
1866249423Sdim    bits<6> offsetBits; // memb - u6:0 , memh - u6:1, memw - u6:2
1867234285Sdim
1868249423Sdim    let offsetBits = !if (!eq(opcBits, 0b00), offset{5-0},
1869249423Sdim                     !if (!eq(opcBits, 0b01), offset{6-1},
1870249423Sdim                     !if (!eq(opcBits, 0b10), offset{7-2},0)));
1871234285Sdim
1872249423Sdim    let IClass = 0b0011;
1873249423Sdim    let Inst{27-24} = 0b1111;
1874249423Sdim    let Inst{22-21} = opcBits;
1875249423Sdim    let Inst{20-16} = base;
1876249423Sdim    let Inst{13} = 0b0;
1877249423Sdim    let Inst{12-7} = offsetBits;
1878249423Sdim    let Inst{6-5} = memOpBits;
1879249423Sdim    let Inst{4-0} = delta;
1880249423Sdim}
1881234285Sdim
1882249423Sdim// multiclass to define MemOp instructions with register operand.
1883249423Sdimmulticlass MemOp_rr<string opc, bits<2> opcBits, Operand ImmOp> {
1884249423Sdim  def _ADD#NAME#_V4 : MemOp_rr_base <opc, opcBits, ImmOp, " += ", 0b00>; // add
1885249423Sdim  def _SUB#NAME#_V4 : MemOp_rr_base <opc, opcBits, ImmOp, " -= ", 0b01>; // sub
1886249423Sdim  def _AND#NAME#_V4 : MemOp_rr_base <opc, opcBits, ImmOp, " &= ", 0b10>; // and
1887249423Sdim  def _OR#NAME#_V4  : MemOp_rr_base <opc, opcBits, ImmOp, " |= ", 0b11>; // or
1888249423Sdim}
1889234285Sdim
1890249423Sdim// multiclass to define MemOp instructions with immediate Operand.
1891249423Sdimmulticlass MemOp_ri<string opc, bits<2> opcBits, Operand ImmOp> {
1892249423Sdim  def _ADD#NAME#_V4 : MemOp_ri_base <opc, opcBits, ImmOp, " += ", 0b00 >;
1893249423Sdim  def _SUB#NAME#_V4 : MemOp_ri_base <opc, opcBits, ImmOp, " -= ", 0b01 >;
1894249423Sdim  def _CLRBIT#NAME#_V4 : MemOp_ri_base<opc, opcBits, ImmOp, " =clrbit(", 0b10>;
1895249423Sdim  def _SETBIT#NAME#_V4 : MemOp_ri_base<opc, opcBits, ImmOp, " =setbit(", 0b11>;
1896249423Sdim}
1897234285Sdim
1898249423Sdimmulticlass MemOp_base <string opc, bits<2> opcBits, Operand ImmOp> {
1899249423Sdim  defm r : MemOp_rr <opc, opcBits, ImmOp>;
1900249423Sdim  defm i : MemOp_ri <opc, opcBits, ImmOp>;
1901249423Sdim}
1902234285Sdim
1903249423Sdim// Define MemOp instructions.
1904249423Sdimlet isExtendable = 1, opExtendable = 1, isExtentSigned = 0,
1905249423SdimvalidSubTargets =HasV4SubT in {
1906249423Sdim  let opExtentBits = 6, accessSize = ByteAccess in
1907249423Sdim  defm MemOPb : MemOp_base <"memb", 0b00, u6_0Ext>;
1908234285Sdim
1909249423Sdim  let opExtentBits = 7, accessSize = HalfWordAccess in
1910249423Sdim  defm MemOPh : MemOp_base <"memh", 0b01, u6_1Ext>;
1911234285Sdim
1912249423Sdim  let opExtentBits = 8, accessSize = WordAccess in
1913249423Sdim  defm MemOPw : MemOp_base <"memw", 0b10, u6_2Ext>;
1914249423Sdim}
1915234285Sdim
1916249423Sdim//===----------------------------------------------------------------------===//
1917249423Sdim// Multiclass to define 'Def Pats' for ALU operations on the memory
1918249423Sdim// Here value used for the ALU operation is an immediate value.
1919249423Sdim// mem[bh](Rs+#0) += #U5
1920249423Sdim// mem[bh](Rs+#u6) += #U5
1921249423Sdim//===----------------------------------------------------------------------===//
1922234285Sdim
1923249423Sdimmulticlass MemOpi_u5Pats <PatFrag ldOp, PatFrag stOp, PatLeaf ExtPred,
1924249423Sdim                          InstHexagon MI, SDNode OpNode> {
1925249423Sdim  let AddedComplexity = 180 in
1926249423Sdim  def : Pat < (stOp (OpNode (ldOp IntRegs:$addr), u5ImmPred:$addend),
1927249423Sdim                    IntRegs:$addr),
1928249423Sdim              (MI IntRegs:$addr, #0, u5ImmPred:$addend )>;
1929234285Sdim
1930249423Sdim  let AddedComplexity = 190 in
1931249423Sdim  def : Pat <(stOp (OpNode (ldOp (add IntRegs:$base, ExtPred:$offset)),
1932249423Sdim                     u5ImmPred:$addend),
1933249423Sdim             (add IntRegs:$base, ExtPred:$offset)),
1934249423Sdim       (MI IntRegs:$base, ExtPred:$offset, u5ImmPred:$addend)>;
1935249423Sdim}
1936234285Sdim
1937249423Sdimmulticlass MemOpi_u5ALUOp<PatFrag ldOp, PatFrag stOp, PatLeaf ExtPred,
1938249423Sdim                          InstHexagon addMI, InstHexagon subMI> {
1939249423Sdim  defm : MemOpi_u5Pats<ldOp, stOp, ExtPred, addMI, add>;
1940249423Sdim  defm : MemOpi_u5Pats<ldOp, stOp, ExtPred, subMI, sub>;
1941249423Sdim}
1942234285Sdim
1943249423Sdimmulticlass MemOpi_u5ExtType<PatFrag ldOpByte, PatFrag ldOpHalf > {
1944249423Sdim  // Half Word
1945249423Sdim  defm : MemOpi_u5ALUOp <ldOpHalf, truncstorei16, u6_1ExtPred,
1946249423Sdim                         MemOPh_ADDi_V4, MemOPh_SUBi_V4>;
1947249423Sdim  // Byte
1948249423Sdim  defm : MemOpi_u5ALUOp <ldOpByte, truncstorei8, u6ExtPred,
1949249423Sdim                         MemOPb_ADDi_V4, MemOPb_SUBi_V4>;
1950249423Sdim}
1951234285Sdim
1952249423Sdimlet Predicates = [HasV4T, UseMEMOP] in {
1953249423Sdim  defm : MemOpi_u5ExtType<zextloadi8, zextloadi16>; // zero extend
1954249423Sdim  defm : MemOpi_u5ExtType<sextloadi8, sextloadi16>; // sign extend
1955249423Sdim  defm : MemOpi_u5ExtType<extloadi8,  extloadi16>;  // any extend
1956234285Sdim
1957249423Sdim  // Word
1958249423Sdim  defm : MemOpi_u5ALUOp <load, store, u6_2ExtPred, MemOPw_ADDi_V4,
1959249423Sdim                         MemOPw_SUBi_V4>;
1960249423Sdim}
1961234285Sdim
1962234285Sdim//===----------------------------------------------------------------------===//
1963249423Sdim// multiclass to define 'Def Pats' for ALU operations on the memory.
1964249423Sdim// Here value used for the ALU operation is a negative value.
1965249423Sdim// mem[bh](Rs+#0) += #m5
1966249423Sdim// mem[bh](Rs+#u6) += #m5
1967234285Sdim//===----------------------------------------------------------------------===//
1968234285Sdim
1969249423Sdimmulticlass MemOpi_m5Pats <PatFrag ldOp, PatFrag stOp, PatLeaf extPred,
1970249423Sdim                          PatLeaf immPred, ComplexPattern addrPred,
1971249423Sdim                          SDNodeXForm xformFunc, InstHexagon MI> {
1972249423Sdim  let AddedComplexity = 190 in
1973249423Sdim  def : Pat <(stOp (add (ldOp IntRegs:$addr), immPred:$subend),
1974249423Sdim                   IntRegs:$addr),
1975249423Sdim             (MI IntRegs:$addr, #0, (xformFunc immPred:$subend) )>;
1976234285Sdim
1977249423Sdim  let AddedComplexity = 195 in
1978249423Sdim  def : Pat<(stOp (add (ldOp (add IntRegs:$base, extPred:$offset)),
1979249423Sdim                       immPred:$subend),
1980249423Sdim                  (add IntRegs:$base, extPred:$offset)),
1981249423Sdim            (MI IntRegs:$base, extPred:$offset, (xformFunc immPred:$subend))>;
1982249423Sdim}
1983234285Sdim
1984249423Sdimmulticlass MemOpi_m5ExtType<PatFrag ldOpByte, PatFrag ldOpHalf > {
1985249423Sdim  // Half Word
1986249423Sdim  defm : MemOpi_m5Pats <ldOpHalf, truncstorei16, u6_1ExtPred, m5HImmPred,
1987249423Sdim                        ADDRriU6_1, MEMOPIMM_HALF, MemOPh_SUBi_V4>;
1988249423Sdim  // Byte
1989249423Sdim  defm : MemOpi_m5Pats <ldOpByte, truncstorei8, u6ExtPred, m5BImmPred,
1990249423Sdim                        ADDRriU6_0, MEMOPIMM_BYTE, MemOPb_SUBi_V4>;
1991249423Sdim}
1992234285Sdim
1993249423Sdimlet Predicates = [HasV4T, UseMEMOP] in {
1994249423Sdim  defm : MemOpi_m5ExtType<zextloadi8, zextloadi16>; // zero extend
1995249423Sdim  defm : MemOpi_m5ExtType<sextloadi8, sextloadi16>; // sign extend
1996249423Sdim  defm : MemOpi_m5ExtType<extloadi8,  extloadi16>;  // any extend
1997234285Sdim
1998249423Sdim  // Word
1999249423Sdim  defm : MemOpi_m5Pats <load, store, u6_2ExtPred, m5ImmPred,
2000249423Sdim                          ADDRriU6_2, MEMOPIMM, MemOPw_SUBi_V4>;
2001249423Sdim}
2002234285Sdim
2003249423Sdim//===----------------------------------------------------------------------===//
2004249423Sdim// Multiclass to define 'def Pats' for bit operations on the memory.
2005249423Sdim// mem[bhw](Rs+#0) = [clrbit|setbit](#U5)
2006249423Sdim// mem[bhw](Rs+#u6) = [clrbit|setbit](#U5)
2007249423Sdim//===----------------------------------------------------------------------===//
2008234285Sdim
2009249423Sdimmulticlass MemOpi_bitPats <PatFrag ldOp, PatFrag stOp, PatLeaf immPred,
2010249423Sdim                     PatLeaf extPred, ComplexPattern addrPred,
2011249423Sdim                     SDNodeXForm xformFunc, InstHexagon MI, SDNode OpNode> {
2012234285Sdim
2013249423Sdim  // mem[bhw](Rs+#u6:[012]) = [clrbit|setbit](#U5)
2014249423Sdim  let AddedComplexity = 250 in
2015249423Sdim  def : Pat<(stOp (OpNode (ldOp (add IntRegs:$base, extPred:$offset)),
2016249423Sdim                          immPred:$bitend),
2017249423Sdim                  (add IntRegs:$base, extPred:$offset)),
2018249423Sdim            (MI IntRegs:$base, extPred:$offset, (xformFunc immPred:$bitend))>;
2019234285Sdim
2020249423Sdim  // mem[bhw](Rs+#0) = [clrbit|setbit](#U5)
2021249423Sdim  let AddedComplexity = 225 in
2022249423Sdim  def : Pat <(stOp (OpNode (ldOp addrPred:$addr), immPred:$bitend),
2023249423Sdim                   addrPred:$addr),
2024249423Sdim             (MI IntRegs:$addr, #0, (xformFunc immPred:$bitend))>;
2025249423Sdim}
2026234285Sdim
2027249423Sdimmulticlass MemOpi_bitExtType<PatFrag ldOpByte, PatFrag ldOpHalf > {
2028249423Sdim  // Byte - clrbit
2029249423Sdim  defm : MemOpi_bitPats<ldOpByte, truncstorei8, Clr3ImmPred, u6ExtPred,
2030249423Sdim                       ADDRriU6_0, CLRMEMIMM_BYTE, MemOPb_CLRBITi_V4, and>;
2031249423Sdim  // Byte - setbit
2032249423Sdim  defm : MemOpi_bitPats<ldOpByte, truncstorei8, Set3ImmPred,  u6ExtPred,
2033249423Sdim                       ADDRriU6_0, SETMEMIMM_BYTE, MemOPb_SETBITi_V4, or>;
2034249423Sdim  // Half Word - clrbit
2035249423Sdim  defm : MemOpi_bitPats<ldOpHalf, truncstorei16, Clr4ImmPred, u6_1ExtPred,
2036249423Sdim                       ADDRriU6_1, CLRMEMIMM_SHORT, MemOPh_CLRBITi_V4, and>;
2037249423Sdim  // Half Word - setbit
2038249423Sdim  defm : MemOpi_bitPats<ldOpHalf, truncstorei16, Set4ImmPred, u6_1ExtPred,
2039249423Sdim                       ADDRriU6_1, SETMEMIMM_SHORT, MemOPh_SETBITi_V4, or>;
2040249423Sdim}
2041234285Sdim
2042249423Sdimlet Predicates = [HasV4T, UseMEMOP] in {
2043249423Sdim  // mem[bh](Rs+#0) = [clrbit|setbit](#U5)
2044249423Sdim  // mem[bh](Rs+#u6:[01]) = [clrbit|setbit](#U5)
2045249423Sdim  defm : MemOpi_bitExtType<zextloadi8, zextloadi16>; // zero extend
2046249423Sdim  defm : MemOpi_bitExtType<sextloadi8, sextloadi16>; // sign extend
2047249423Sdim  defm : MemOpi_bitExtType<extloadi8,  extloadi16>;  // any extend
2048234285Sdim
2049249423Sdim  // memw(Rs+#0) = [clrbit|setbit](#U5)
2050249423Sdim  // memw(Rs+#u6:2) = [clrbit|setbit](#U5)
2051249423Sdim  defm : MemOpi_bitPats<load, store, Clr5ImmPred, u6_2ExtPred, ADDRriU6_2,
2052249423Sdim                       CLRMEMIMM, MemOPw_CLRBITi_V4, and>;
2053249423Sdim  defm : MemOpi_bitPats<load, store, Set5ImmPred, u6_2ExtPred, ADDRriU6_2,
2054249423Sdim                       SETMEMIMM, MemOPw_SETBITi_V4, or>;
2055249423Sdim}
2056234285Sdim
2057249423Sdim//===----------------------------------------------------------------------===//
2058249423Sdim// Multiclass to define 'def Pats' for ALU operations on the memory
2059249423Sdim// where addend is a register.
2060249423Sdim// mem[bhw](Rs+#0) [+-&|]= Rt
2061249423Sdim// mem[bhw](Rs+#U6:[012]) [+-&|]= Rt
2062249423Sdim//===----------------------------------------------------------------------===//
2063234285Sdim
2064249423Sdimmulticlass MemOpr_Pats <PatFrag ldOp, PatFrag stOp, ComplexPattern addrPred,
2065249423Sdim                     PatLeaf extPred, InstHexagon MI, SDNode OpNode> {
2066249423Sdim  let AddedComplexity = 141 in
2067249423Sdim  // mem[bhw](Rs+#0) [+-&|]= Rt
2068249423Sdim  def : Pat <(stOp (OpNode (ldOp addrPred:$addr), (i32 IntRegs:$addend)),
2069249423Sdim                   addrPred:$addr),
2070249423Sdim             (MI IntRegs:$addr, #0, (i32 IntRegs:$addend) )>;
2071234285Sdim
2072249423Sdim  // mem[bhw](Rs+#U6:[012]) [+-&|]= Rt
2073249423Sdim  let AddedComplexity = 150 in
2074249423Sdim  def : Pat <(stOp (OpNode (ldOp (add IntRegs:$base, extPred:$offset)),
2075249423Sdim                           (i32 IntRegs:$orend)),
2076249423Sdim                   (add IntRegs:$base, extPred:$offset)),
2077249423Sdim             (MI IntRegs:$base, extPred:$offset, (i32 IntRegs:$orend) )>;
2078249423Sdim}
2079234285Sdim
2080249423Sdimmulticlass MemOPr_ALUOp<PatFrag ldOp, PatFrag stOp,
2081249423Sdim                        ComplexPattern addrPred, PatLeaf extPred,
2082249423Sdim                        InstHexagon addMI, InstHexagon subMI,
2083249423Sdim                        InstHexagon andMI, InstHexagon orMI > {
2084234285Sdim
2085249423Sdim  defm : MemOpr_Pats <ldOp, stOp, addrPred, extPred, addMI, add>;
2086249423Sdim  defm : MemOpr_Pats <ldOp, stOp, addrPred, extPred, subMI, sub>;
2087249423Sdim  defm : MemOpr_Pats <ldOp, stOp, addrPred, extPred, andMI, and>;
2088249423Sdim  defm : MemOpr_Pats <ldOp, stOp, addrPred, extPred, orMI,  or>;
2089249423Sdim}
2090249423Sdim
2091249423Sdimmulticlass MemOPr_ExtType<PatFrag ldOpByte, PatFrag ldOpHalf > {
2092249423Sdim  // Half Word
2093249423Sdim  defm : MemOPr_ALUOp <ldOpHalf, truncstorei16, ADDRriU6_1, u6_1ExtPred,
2094249423Sdim                       MemOPh_ADDr_V4, MemOPh_SUBr_V4,
2095249423Sdim                       MemOPh_ANDr_V4, MemOPh_ORr_V4>;
2096249423Sdim  // Byte
2097249423Sdim  defm : MemOPr_ALUOp <ldOpByte, truncstorei8, ADDRriU6_0, u6ExtPred,
2098249423Sdim                       MemOPb_ADDr_V4, MemOPb_SUBr_V4,
2099249423Sdim                       MemOPb_ANDr_V4, MemOPb_ORr_V4>;
2100249423Sdim}
2101249423Sdim
2102249423Sdim// Define 'def Pats' for MemOps with register addend.
2103249423Sdimlet Predicates = [HasV4T, UseMEMOP] in {
2104249423Sdim  // Byte, Half Word
2105249423Sdim  defm : MemOPr_ExtType<zextloadi8, zextloadi16>; // zero extend
2106249423Sdim  defm : MemOPr_ExtType<sextloadi8, sextloadi16>; // sign extend
2107249423Sdim  defm : MemOPr_ExtType<extloadi8,  extloadi16>;  // any extend
2108249423Sdim  // Word
2109249423Sdim  defm : MemOPr_ALUOp <load, store, ADDRriU6_2, u6_2ExtPred, MemOPw_ADDr_V4,
2110249423Sdim                       MemOPw_SUBr_V4, MemOPw_ANDr_V4, MemOPw_ORr_V4 >;
2111249423Sdim}
2112249423Sdim
2113234285Sdim//===----------------------------------------------------------------------===//
2114234285Sdim// XTYPE/PRED +
2115234285Sdim//===----------------------------------------------------------------------===//
2116234285Sdim
2117234285Sdim// Hexagon V4 only supports these flavors of byte/half compare instructions:
2118234285Sdim// EQ/GT/GTU. Other flavors like GE/GEU/LT/LTU/LE/LEU are not supported by
2119234285Sdim// hardware. However, compiler can still implement these patterns through
2120234285Sdim// appropriate patterns combinations based on current implemented patterns.
2121234285Sdim// The implemented patterns are: EQ/GT/GTU.
2122234285Sdim// Missing patterns are: GE/GEU/LT/LTU/LE/LEU.
2123234285Sdim
2124239462Sdim// Following instruction is not being extended as it results into the
2125239462Sdim// incorrect code for negative numbers.
2126234285Sdim// Pd=cmpb.eq(Rs,#u8)
2127239462Sdim
2128249423Sdim// p=!cmp.eq(r1,r2)
2129249423Sdimlet isCompare = 1, validSubTargets = HasV4SubT in
2130249423Sdimdef CMPnotEQ_rr : ALU32_rr<(outs PredRegs:$dst),
2131249423Sdim                           (ins IntRegs:$src1, IntRegs:$src2),
2132249423Sdim      "$dst = !cmp.eq($src1, $src2)",
2133249423Sdim      [(set (i1 PredRegs:$dst),
2134249423Sdim            (setne (i32 IntRegs:$src1), (i32 IntRegs:$src2)))]>,
2135249423Sdim      Requires<[HasV4T]>;
2136249423Sdim
2137249423Sdim// p=!cmp.eq(r1,#s10)
2138249423Sdimlet isCompare = 1, validSubTargets = HasV4SubT in
2139249423Sdimdef CMPnotEQ_ri : ALU32_ri<(outs PredRegs:$dst),
2140249423Sdim                           (ins IntRegs:$src1, s10Ext:$src2),
2141249423Sdim      "$dst = !cmp.eq($src1, #$src2)",
2142249423Sdim      [(set (i1 PredRegs:$dst),
2143249423Sdim            (setne (i32 IntRegs:$src1), s10ImmPred:$src2))]>,
2144249423Sdim      Requires<[HasV4T]>;
2145249423Sdim
2146249423Sdim// p=!cmp.gt(r1,r2)
2147249423Sdimlet isCompare = 1, validSubTargets = HasV4SubT in
2148249423Sdimdef CMPnotGT_rr : ALU32_rr<(outs PredRegs:$dst),
2149249423Sdim                           (ins IntRegs:$src1, IntRegs:$src2),
2150249423Sdim      "$dst = !cmp.gt($src1, $src2)",
2151249423Sdim      [(set (i1 PredRegs:$dst),
2152249423Sdim            (not (setgt (i32 IntRegs:$src1), (i32 IntRegs:$src2))))]>,
2153249423Sdim      Requires<[HasV4T]>;
2154249423Sdim
2155249423Sdim// p=!cmp.gt(r1,#s10)
2156249423Sdimlet isCompare = 1, validSubTargets = HasV4SubT in
2157249423Sdimdef CMPnotGT_ri : ALU32_ri<(outs PredRegs:$dst),
2158249423Sdim                           (ins IntRegs:$src1, s10Ext:$src2),
2159249423Sdim      "$dst = !cmp.gt($src1, #$src2)",
2160249423Sdim      [(set (i1 PredRegs:$dst),
2161249423Sdim            (not (setgt (i32 IntRegs:$src1), s10ImmPred:$src2)))]>,
2162249423Sdim      Requires<[HasV4T]>;
2163249423Sdim
2164249423Sdim// p=!cmp.gtu(r1,r2)
2165249423Sdimlet isCompare = 1, validSubTargets = HasV4SubT in
2166249423Sdimdef CMPnotGTU_rr : ALU32_rr<(outs PredRegs:$dst),
2167249423Sdim                            (ins IntRegs:$src1, IntRegs:$src2),
2168249423Sdim      "$dst = !cmp.gtu($src1, $src2)",
2169249423Sdim      [(set (i1 PredRegs:$dst),
2170249423Sdim            (not (setugt (i32 IntRegs:$src1), (i32 IntRegs:$src2))))]>,
2171249423Sdim      Requires<[HasV4T]>;
2172249423Sdim
2173249423Sdim// p=!cmp.gtu(r1,#u9)
2174249423Sdimlet isCompare = 1, validSubTargets = HasV4SubT in
2175249423Sdimdef CMPnotGTU_ri : ALU32_ri<(outs PredRegs:$dst),
2176249423Sdim                            (ins IntRegs:$src1, u9Ext:$src2),
2177249423Sdim      "$dst = !cmp.gtu($src1, #$src2)",
2178249423Sdim      [(set (i1 PredRegs:$dst),
2179249423Sdim            (not (setugt (i32 IntRegs:$src1), u9ImmPred:$src2)))]>,
2180249423Sdim      Requires<[HasV4T]>;
2181249423Sdim
2182249423Sdimlet isCompare = 1, validSubTargets = HasV4SubT in
2183234285Sdimdef CMPbEQri_V4 : MInst<(outs PredRegs:$dst),
2184234285Sdim            (ins IntRegs:$src1, u8Imm:$src2),
2185234285Sdim            "$dst = cmpb.eq($src1, #$src2)",
2186239462Sdim            [(set (i1 PredRegs:$dst),
2187239462Sdim                  (seteq (and (i32 IntRegs:$src1), 255), u8ImmPred:$src2))]>,
2188234285Sdim            Requires<[HasV4T]>;
2189234285Sdim
2190249423Sdimdef : Pat <(brcond (i1 (setne (and (i32 IntRegs:$src1), 255), u8ImmPred:$src2)),
2191249423Sdim                       bb:$offset),
2192251662Sdim      (JMP_f (CMPbEQri_V4 (i32 IntRegs:$src1), u8ImmPred:$src2),
2193249423Sdim                bb:$offset)>,
2194249423Sdim      Requires<[HasV4T]>;
2195249423Sdim
2196234285Sdim// Pd=cmpb.eq(Rs,Rt)
2197249423Sdimlet isCompare = 1, validSubTargets = HasV4SubT in
2198234285Sdimdef CMPbEQrr_ubub_V4 : MInst<(outs PredRegs:$dst),
2199234285Sdim            (ins IntRegs:$src1, IntRegs:$src2),
2200234285Sdim            "$dst = cmpb.eq($src1, $src2)",
2201239462Sdim            [(set (i1 PredRegs:$dst),
2202239462Sdim                  (seteq (and (xor (i32 IntRegs:$src1),
2203239462Sdim                                   (i32 IntRegs:$src2)), 255), 0))]>,
2204234285Sdim            Requires<[HasV4T]>;
2205234285Sdim
2206234285Sdim// Pd=cmpb.eq(Rs,Rt)
2207249423Sdimlet isCompare = 1, validSubTargets = HasV4SubT in
2208234285Sdimdef CMPbEQrr_sbsb_V4 : MInst<(outs PredRegs:$dst),
2209234285Sdim            (ins IntRegs:$src1, IntRegs:$src2),
2210234285Sdim            "$dst = cmpb.eq($src1, $src2)",
2211239462Sdim            [(set (i1 PredRegs:$dst),
2212239462Sdim                  (seteq (shl (i32 IntRegs:$src1), (i32 24)),
2213239462Sdim                         (shl (i32 IntRegs:$src2), (i32 24))))]>,
2214234285Sdim            Requires<[HasV4T]>;
2215234285Sdim
2216234285Sdim// Pd=cmpb.gt(Rs,Rt)
2217249423Sdimlet isCompare = 1, validSubTargets = HasV4SubT in
2218234285Sdimdef CMPbGTrr_V4 : MInst<(outs PredRegs:$dst),
2219234285Sdim            (ins IntRegs:$src1, IntRegs:$src2),
2220234285Sdim            "$dst = cmpb.gt($src1, $src2)",
2221239462Sdim            [(set (i1 PredRegs:$dst),
2222239462Sdim                  (setgt (shl (i32 IntRegs:$src1), (i32 24)),
2223239462Sdim                         (shl (i32 IntRegs:$src2), (i32 24))))]>,
2224234285Sdim            Requires<[HasV4T]>;
2225234285Sdim
2226234285Sdim// Pd=cmpb.gtu(Rs,#u7)
2227249423Sdimlet isExtendable = 1, opExtendable = 2, isExtentSigned = 0, opExtentBits = 7,
2228249423SdimisCompare = 1, validSubTargets = HasV4SubT, CextOpcode = "CMPbGTU", InputType = "imm" in
2229234285Sdimdef CMPbGTUri_V4 : MInst<(outs PredRegs:$dst),
2230249423Sdim            (ins IntRegs:$src1, u7Ext:$src2),
2231234285Sdim            "$dst = cmpb.gtu($src1, #$src2)",
2232239462Sdim            [(set (i1 PredRegs:$dst), (setugt (and (i32 IntRegs:$src1), 255),
2233249423Sdim                                              u7ExtPred:$src2))]>,
2234249423Sdim            Requires<[HasV4T]>, ImmRegRel;
2235234285Sdim
2236249423Sdim// SDNode for converting immediate C to C-1.
2237249423Sdimdef DEC_CONST_BYTE : SDNodeXForm<imm, [{
2238249423Sdim   // Return the byte immediate const-1 as an SDNode.
2239249423Sdim   int32_t imm = N->getSExtValue();
2240249423Sdim   return XformU7ToU7M1Imm(imm);
2241249423Sdim}]>;
2242249423Sdim
2243249423Sdim// For the sequence
2244249423Sdim//   zext( seteq ( and(Rs, 255), u8))
2245249423Sdim// Generate
2246249423Sdim//   Pd=cmpb.eq(Rs, #u8)
2247249423Sdim//   if (Pd.new) Rd=#1
2248249423Sdim//   if (!Pd.new) Rd=#0
2249249423Sdimdef : Pat <(i32 (zext (i1 (seteq (i32 (and (i32 IntRegs:$Rs), 255)),
2250249423Sdim                                           u8ExtPred:$u8)))),
2251249423Sdim           (i32 (TFR_condset_ii (i1 (CMPbEQri_V4 (i32 IntRegs:$Rs),
2252249423Sdim                                                 (u8ExtPred:$u8))),
2253249423Sdim                                1, 0))>,
2254249423Sdim           Requires<[HasV4T]>;
2255249423Sdim
2256249423Sdim// For the sequence
2257249423Sdim//   zext( setne ( and(Rs, 255), u8))
2258249423Sdim// Generate
2259249423Sdim//   Pd=cmpb.eq(Rs, #u8)
2260249423Sdim//   if (Pd.new) Rd=#0
2261249423Sdim//   if (!Pd.new) Rd=#1
2262249423Sdimdef : Pat <(i32 (zext (i1 (setne (i32 (and (i32 IntRegs:$Rs), 255)),
2263249423Sdim                                           u8ExtPred:$u8)))),
2264249423Sdim           (i32 (TFR_condset_ii (i1 (CMPbEQri_V4 (i32 IntRegs:$Rs),
2265249423Sdim                                                 (u8ExtPred:$u8))),
2266249423Sdim                                0, 1))>,
2267249423Sdim           Requires<[HasV4T]>;
2268249423Sdim
2269249423Sdim// For the sequence
2270249423Sdim//   zext( seteq (Rs, and(Rt, 255)))
2271249423Sdim// Generate
2272249423Sdim//   Pd=cmpb.eq(Rs, Rt)
2273249423Sdim//   if (Pd.new) Rd=#1
2274249423Sdim//   if (!Pd.new) Rd=#0
2275249423Sdimdef : Pat <(i32 (zext (i1 (seteq (i32 IntRegs:$Rt),
2276249423Sdim                                 (i32 (and (i32 IntRegs:$Rs), 255)))))),
2277249423Sdim           (i32 (TFR_condset_ii (i1 (CMPbEQrr_ubub_V4 (i32 IntRegs:$Rs),
2278249423Sdim                                                      (i32 IntRegs:$Rt))),
2279249423Sdim                                1, 0))>,
2280249423Sdim           Requires<[HasV4T]>;
2281249423Sdim
2282249423Sdim// For the sequence
2283249423Sdim//   zext( setne (Rs, and(Rt, 255)))
2284249423Sdim// Generate
2285249423Sdim//   Pd=cmpb.eq(Rs, Rt)
2286249423Sdim//   if (Pd.new) Rd=#0
2287249423Sdim//   if (!Pd.new) Rd=#1
2288249423Sdimdef : Pat <(i32 (zext (i1 (setne (i32 IntRegs:$Rt),
2289249423Sdim                                 (i32 (and (i32 IntRegs:$Rs), 255)))))),
2290249423Sdim           (i32 (TFR_condset_ii (i1 (CMPbEQrr_ubub_V4 (i32 IntRegs:$Rs),
2291249423Sdim                                                      (i32 IntRegs:$Rt))),
2292249423Sdim                                0, 1))>,
2293249423Sdim           Requires<[HasV4T]>;
2294249423Sdim
2295249423Sdim// For the sequence
2296249423Sdim//   zext( setugt ( and(Rs, 255), u8))
2297249423Sdim// Generate
2298249423Sdim//   Pd=cmpb.gtu(Rs, #u8)
2299249423Sdim//   if (Pd.new) Rd=#1
2300249423Sdim//   if (!Pd.new) Rd=#0
2301249423Sdimdef : Pat <(i32 (zext (i1 (setugt (i32 (and (i32 IntRegs:$Rs), 255)),
2302249423Sdim                                            u8ExtPred:$u8)))),
2303249423Sdim           (i32 (TFR_condset_ii (i1 (CMPbGTUri_V4 (i32 IntRegs:$Rs),
2304249423Sdim                                                  (u8ExtPred:$u8))),
2305249423Sdim                                1, 0))>,
2306249423Sdim           Requires<[HasV4T]>;
2307249423Sdim
2308249423Sdim// For the sequence
2309249423Sdim//   zext( setugt ( and(Rs, 254), u8))
2310249423Sdim// Generate
2311249423Sdim//   Pd=cmpb.gtu(Rs, #u8)
2312249423Sdim//   if (Pd.new) Rd=#1
2313249423Sdim//   if (!Pd.new) Rd=#0
2314249423Sdimdef : Pat <(i32 (zext (i1 (setugt (i32 (and (i32 IntRegs:$Rs), 254)),
2315249423Sdim                                            u8ExtPred:$u8)))),
2316249423Sdim           (i32 (TFR_condset_ii (i1 (CMPbGTUri_V4 (i32 IntRegs:$Rs),
2317249423Sdim                                                  (u8ExtPred:$u8))),
2318249423Sdim                                1, 0))>,
2319249423Sdim           Requires<[HasV4T]>;
2320249423Sdim
2321249423Sdim// For the sequence
2322249423Sdim//   zext( setult ( Rs, Rt))
2323249423Sdim// Generate
2324249423Sdim//   Pd=cmp.ltu(Rs, Rt)
2325249423Sdim//   if (Pd.new) Rd=#1
2326249423Sdim//   if (!Pd.new) Rd=#0
2327249423Sdim// cmp.ltu(Rs, Rt) -> cmp.gtu(Rt, Rs)
2328249423Sdimdef : Pat <(i32 (zext (i1 (setult (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))),
2329249423Sdim           (i32 (TFR_condset_ii (i1 (CMPGTUrr (i32 IntRegs:$Rt),
2330249423Sdim                                              (i32 IntRegs:$Rs))),
2331249423Sdim                                1, 0))>,
2332249423Sdim           Requires<[HasV4T]>;
2333249423Sdim
2334249423Sdim// For the sequence
2335249423Sdim//   zext( setlt ( Rs, Rt))
2336249423Sdim// Generate
2337249423Sdim//   Pd=cmp.lt(Rs, Rt)
2338249423Sdim//   if (Pd.new) Rd=#1
2339249423Sdim//   if (!Pd.new) Rd=#0
2340249423Sdim// cmp.lt(Rs, Rt) -> cmp.gt(Rt, Rs)
2341249423Sdimdef : Pat <(i32 (zext (i1 (setlt (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))),
2342249423Sdim           (i32 (TFR_condset_ii (i1 (CMPGTrr (i32 IntRegs:$Rt),
2343249423Sdim                                             (i32 IntRegs:$Rs))),
2344249423Sdim                                1, 0))>,
2345249423Sdim           Requires<[HasV4T]>;
2346249423Sdim
2347249423Sdim// For the sequence
2348249423Sdim//   zext( setugt ( Rs, Rt))
2349249423Sdim// Generate
2350249423Sdim//   Pd=cmp.gtu(Rs, Rt)
2351249423Sdim//   if (Pd.new) Rd=#1
2352249423Sdim//   if (!Pd.new) Rd=#0
2353249423Sdimdef : Pat <(i32 (zext (i1 (setugt (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))),
2354249423Sdim           (i32 (TFR_condset_ii (i1 (CMPGTUrr (i32 IntRegs:$Rs),
2355249423Sdim                                              (i32 IntRegs:$Rt))),
2356249423Sdim                                1, 0))>,
2357249423Sdim           Requires<[HasV4T]>;
2358249423Sdim
2359249423Sdim// This pattern interefers with coremark performance, not implementing at this
2360249423Sdim// time.
2361249423Sdim// For the sequence
2362249423Sdim//   zext( setgt ( Rs, Rt))
2363249423Sdim// Generate
2364249423Sdim//   Pd=cmp.gt(Rs, Rt)
2365249423Sdim//   if (Pd.new) Rd=#1
2366249423Sdim//   if (!Pd.new) Rd=#0
2367249423Sdim
2368249423Sdim// For the sequence
2369249423Sdim//   zext( setuge ( Rs, Rt))
2370249423Sdim// Generate
2371249423Sdim//   Pd=cmp.ltu(Rs, Rt)
2372249423Sdim//   if (Pd.new) Rd=#0
2373249423Sdim//   if (!Pd.new) Rd=#1
2374249423Sdim// cmp.ltu(Rs, Rt) -> cmp.gtu(Rt, Rs)
2375249423Sdimdef : Pat <(i32 (zext (i1 (setuge (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))),
2376249423Sdim           (i32 (TFR_condset_ii (i1 (CMPGTUrr (i32 IntRegs:$Rt),
2377249423Sdim                                              (i32 IntRegs:$Rs))),
2378249423Sdim                                0, 1))>,
2379249423Sdim           Requires<[HasV4T]>;
2380249423Sdim
2381249423Sdim// For the sequence
2382249423Sdim//   zext( setge ( Rs, Rt))
2383249423Sdim// Generate
2384249423Sdim//   Pd=cmp.lt(Rs, Rt)
2385249423Sdim//   if (Pd.new) Rd=#0
2386249423Sdim//   if (!Pd.new) Rd=#1
2387249423Sdim// cmp.lt(Rs, Rt) -> cmp.gt(Rt, Rs)
2388249423Sdimdef : Pat <(i32 (zext (i1 (setge (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))),
2389249423Sdim           (i32 (TFR_condset_ii (i1 (CMPGTrr (i32 IntRegs:$Rt),
2390249423Sdim                                             (i32 IntRegs:$Rs))),
2391249423Sdim                                0, 1))>,
2392249423Sdim           Requires<[HasV4T]>;
2393249423Sdim
2394249423Sdim// For the sequence
2395249423Sdim//   zext( setule ( Rs, Rt))
2396249423Sdim// Generate
2397249423Sdim//   Pd=cmp.gtu(Rs, Rt)
2398249423Sdim//   if (Pd.new) Rd=#0
2399249423Sdim//   if (!Pd.new) Rd=#1
2400249423Sdimdef : Pat <(i32 (zext (i1 (setule (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))),
2401249423Sdim           (i32 (TFR_condset_ii (i1 (CMPGTUrr (i32 IntRegs:$Rs),
2402249423Sdim                                              (i32 IntRegs:$Rt))),
2403249423Sdim                                0, 1))>,
2404249423Sdim           Requires<[HasV4T]>;
2405249423Sdim
2406249423Sdim// For the sequence
2407249423Sdim//   zext( setle ( Rs, Rt))
2408249423Sdim// Generate
2409249423Sdim//   Pd=cmp.gt(Rs, Rt)
2410249423Sdim//   if (Pd.new) Rd=#0
2411249423Sdim//   if (!Pd.new) Rd=#1
2412249423Sdimdef : Pat <(i32 (zext (i1 (setle (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))),
2413249423Sdim           (i32 (TFR_condset_ii (i1 (CMPGTrr (i32 IntRegs:$Rs),
2414249423Sdim                                             (i32 IntRegs:$Rt))),
2415249423Sdim                                0, 1))>,
2416249423Sdim           Requires<[HasV4T]>;
2417249423Sdim
2418249423Sdim// For the sequence
2419249423Sdim//   zext( setult ( and(Rs, 255), u8))
2420249423Sdim// Use the isdigit transformation below
2421249423Sdim
2422249423Sdim// Generate code of the form 'mux_ii(cmpbgtu(Rdd, C-1),0,1)'
2423249423Sdim// for C code of the form r = ((c>='0') & (c<='9')) ? 1 : 0;.
2424249423Sdim// The isdigit transformation relies on two 'clever' aspects:
2425249423Sdim// 1) The data type is unsigned which allows us to eliminate a zero test after
2426249423Sdim//    biasing the expression by 48. We are depending on the representation of
2427249423Sdim//    the unsigned types, and semantics.
2428249423Sdim// 2) The front end has converted <= 9 into < 10 on entry to LLVM
2429249423Sdim//
2430249423Sdim// For the C code:
2431249423Sdim//   retval = ((c>='0') & (c<='9')) ? 1 : 0;
2432249423Sdim// The code is transformed upstream of llvm into
2433249423Sdim//   retval = (c-48) < 10 ? 1 : 0;
2434249423Sdimlet AddedComplexity = 139 in
2435249423Sdimdef : Pat <(i32 (zext (i1 (setult (i32 (and (i32 IntRegs:$src1), 255)),
2436249423Sdim                                  u7StrictPosImmPred:$src2)))),
2437249423Sdim  (i32 (MUX_ii (i1 (CMPbGTUri_V4 (i32 IntRegs:$src1),
2438249423Sdim                                 (DEC_CONST_BYTE u7StrictPosImmPred:$src2))),
2439249423Sdim                   0, 1))>,
2440249423Sdim                   Requires<[HasV4T]>;
2441249423Sdim
2442234285Sdim// Pd=cmpb.gtu(Rs,Rt)
2443249423Sdimlet isCompare = 1, validSubTargets = HasV4SubT, CextOpcode = "CMPbGTU",
2444249423SdimInputType = "reg" in
2445234285Sdimdef CMPbGTUrr_V4 : MInst<(outs PredRegs:$dst),
2446234285Sdim            (ins IntRegs:$src1, IntRegs:$src2),
2447234285Sdim            "$dst = cmpb.gtu($src1, $src2)",
2448239462Sdim            [(set (i1 PredRegs:$dst), (setugt (and (i32 IntRegs:$src1), 255),
2449239462Sdim                                             (and (i32 IntRegs:$src2), 255)))]>,
2450249423Sdim            Requires<[HasV4T]>, ImmRegRel;
2451234285Sdim
2452239462Sdim// Following instruction is not being extended as it results into the incorrect
2453239462Sdim// code for negative numbers.
2454239462Sdim
2455234285Sdim// Signed half compare(.eq) ri.
2456234285Sdim// Pd=cmph.eq(Rs,#s8)
2457249423Sdimlet isCompare = 1, validSubTargets = HasV4SubT in
2458234285Sdimdef CMPhEQri_V4 : MInst<(outs PredRegs:$dst),
2459239462Sdim            (ins IntRegs:$src1, s8Imm:$src2),
2460234285Sdim            "$dst = cmph.eq($src1, #$src2)",
2461239462Sdim            [(set (i1 PredRegs:$dst), (seteq (and (i32 IntRegs:$src1), 65535),
2462239462Sdim                                             s8ImmPred:$src2))]>,
2463234285Sdim            Requires<[HasV4T]>;
2464234285Sdim
2465234285Sdim// Signed half compare(.eq) rr.
2466234285Sdim// Case 1: xor + and, then compare:
2467234285Sdim//   r0=xor(r0,r1)
2468234285Sdim//   r0=and(r0,#0xffff)
2469234285Sdim//   p0=cmp.eq(r0,#0)
2470234285Sdim// Pd=cmph.eq(Rs,Rt)
2471249423Sdimlet isCompare = 1, validSubTargets = HasV4SubT in
2472234285Sdimdef CMPhEQrr_xor_V4 : MInst<(outs PredRegs:$dst),
2473234285Sdim            (ins IntRegs:$src1, IntRegs:$src2),
2474234285Sdim            "$dst = cmph.eq($src1, $src2)",
2475239462Sdim            [(set (i1 PredRegs:$dst), (seteq (and (xor (i32 IntRegs:$src1),
2476239462Sdim                                                       (i32 IntRegs:$src2)),
2477239462Sdim                                                  65535), 0))]>,
2478234285Sdim            Requires<[HasV4T]>;
2479234285Sdim
2480234285Sdim// Signed half compare(.eq) rr.
2481234285Sdim// Case 2: shift left 16 bits then compare:
2482234285Sdim//   r0=asl(r0,16)
2483234285Sdim//   r1=asl(r1,16)
2484234285Sdim//   p0=cmp.eq(r0,r1)
2485234285Sdim// Pd=cmph.eq(Rs,Rt)
2486249423Sdimlet isCompare = 1, validSubTargets = HasV4SubT in
2487234285Sdimdef CMPhEQrr_shl_V4 : MInst<(outs PredRegs:$dst),
2488234285Sdim            (ins IntRegs:$src1, IntRegs:$src2),
2489234285Sdim            "$dst = cmph.eq($src1, $src2)",
2490239462Sdim            [(set (i1 PredRegs:$dst),
2491239462Sdim                  (seteq (shl (i32 IntRegs:$src1), (i32 16)),
2492239462Sdim                         (shl (i32 IntRegs:$src2), (i32 16))))]>,
2493234285Sdim            Requires<[HasV4T]>;
2494234285Sdim
2495239462Sdim/* Incorrect Pattern -- immediate should be right shifted before being
2496239462Sdimused in the cmph.gt instruction.
2497234285Sdim// Signed half compare(.gt) ri.
2498234285Sdim// Pd=cmph.gt(Rs,#s8)
2499239462Sdim
2500249423Sdimlet isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8,
2501249423SdimisCompare = 1, validSubTargets = HasV4SubT in
2502234285Sdimdef CMPhGTri_V4 : MInst<(outs PredRegs:$dst),
2503249423Sdim            (ins IntRegs:$src1, s8Ext:$src2),
2504234285Sdim            "$dst = cmph.gt($src1, #$src2)",
2505239462Sdim            [(set (i1 PredRegs:$dst),
2506239462Sdim                  (setgt (shl (i32 IntRegs:$src1), (i32 16)),
2507249423Sdim                         s8ExtPred:$src2))]>,
2508234285Sdim            Requires<[HasV4T]>;
2509239462Sdim*/
2510234285Sdim
2511234285Sdim// Signed half compare(.gt) rr.
2512234285Sdim// Pd=cmph.gt(Rs,Rt)
2513249423Sdimlet isCompare = 1, validSubTargets = HasV4SubT in
2514234285Sdimdef CMPhGTrr_shl_V4 : MInst<(outs PredRegs:$dst),
2515234285Sdim            (ins IntRegs:$src1, IntRegs:$src2),
2516234285Sdim            "$dst = cmph.gt($src1, $src2)",
2517239462Sdim            [(set (i1 PredRegs:$dst),
2518239462Sdim                  (setgt (shl (i32 IntRegs:$src1), (i32 16)),
2519239462Sdim                         (shl (i32 IntRegs:$src2), (i32 16))))]>,
2520234285Sdim            Requires<[HasV4T]>;
2521234285Sdim
2522234285Sdim// Unsigned half compare rr (.gtu).
2523234285Sdim// Pd=cmph.gtu(Rs,Rt)
2524249423Sdimlet isCompare = 1, validSubTargets = HasV4SubT, CextOpcode = "CMPhGTU",
2525249423SdimInputType = "reg" in
2526234285Sdimdef CMPhGTUrr_V4 : MInst<(outs PredRegs:$dst),
2527234285Sdim            (ins IntRegs:$src1, IntRegs:$src2),
2528234285Sdim            "$dst = cmph.gtu($src1, $src2)",
2529239462Sdim            [(set (i1 PredRegs:$dst),
2530239462Sdim                  (setugt (and (i32 IntRegs:$src1), 65535),
2531239462Sdim                          (and (i32 IntRegs:$src2), 65535)))]>,
2532249423Sdim            Requires<[HasV4T]>, ImmRegRel;
2533234285Sdim
2534234285Sdim// Unsigned half compare ri (.gtu).
2535234285Sdim// Pd=cmph.gtu(Rs,#u7)
2536249423Sdimlet isExtendable = 1, opExtendable = 2, isExtentSigned = 0, opExtentBits = 7,
2537249423SdimisCompare = 1, validSubTargets = HasV4SubT, CextOpcode = "CMPhGTU",
2538249423SdimInputType = "imm" in
2539234285Sdimdef CMPhGTUri_V4 : MInst<(outs PredRegs:$dst),
2540249423Sdim            (ins IntRegs:$src1, u7Ext:$src2),
2541234285Sdim            "$dst = cmph.gtu($src1, #$src2)",
2542239462Sdim            [(set (i1 PredRegs:$dst), (setugt (and (i32 IntRegs:$src1), 65535),
2543249423Sdim                                              u7ExtPred:$src2))]>,
2544249423Sdim            Requires<[HasV4T]>, ImmRegRel;
2545234285Sdim
2546249423Sdimlet validSubTargets = HasV4SubT in
2547249423Sdimdef NTSTBIT_rr : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
2548249423Sdim    "$dst = !tstbit($src1, $src2)",
2549249423Sdim    [(set (i1 PredRegs:$dst),
2550249423Sdim          (seteq (and (shl 1, (i32 IntRegs:$src2)), (i32 IntRegs:$src1)), 0))]>,
2551249423Sdim    Requires<[HasV4T]>;
2552249423Sdim
2553249423Sdimlet validSubTargets = HasV4SubT in
2554249423Sdimdef NTSTBIT_ri : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2),
2555249423Sdim    "$dst = !tstbit($src1, $src2)",
2556249423Sdim    [(set (i1 PredRegs:$dst),
2557249423Sdim          (seteq (and (shl 1, u5ImmPred:$src2), (i32 IntRegs:$src1)), 0))]>,
2558249423Sdim    Requires<[HasV4T]>;
2559249423Sdim
2560234285Sdim//===----------------------------------------------------------------------===//
2561234285Sdim// XTYPE/PRED -
2562234285Sdim//===----------------------------------------------------------------------===//
2563234285Sdim
2564234285Sdim//Deallocate frame and return.
2565234285Sdim//    dealloc_return
2566234285Sdimlet isReturn = 1, isTerminator = 1, isBarrier = 1, isPredicable = 1,
2567263508Sdim  Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1 in {
2568263508Sdimlet validSubTargets = HasV4SubT in
2569263508Sdim  def DEALLOC_RET_V4 : LD0Inst<(outs), (ins),
2570234285Sdim            "dealloc_return",
2571234285Sdim            []>,
2572234285Sdim            Requires<[HasV4T]>;
2573234285Sdim}
2574234285Sdim
2575239462Sdim// Restore registers and dealloc return function call.
2576239462Sdimlet isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1,
2577239462Sdim  Defs = [R29, R30, R31, PC] in {
2578263508Sdimlet validSubTargets = HasV4SubT in
2579239462Sdim  def RESTORE_DEALLOC_RET_JMP_V4 : JInst<(outs),
2580239462Sdim                                   (ins calltarget:$dst),
2581263508Sdim             "jump $dst",
2582239462Sdim             []>,
2583239462Sdim             Requires<[HasV4T]>;
2584239462Sdim}
2585239462Sdim
2586239462Sdim// Restore registers and dealloc frame before a tail call.
2587239462Sdimlet isCall = 1, isBarrier = 1,
2588239462Sdim  Defs = [R29, R30, R31, PC] in {
2589263508Sdimlet validSubTargets = HasV4SubT in
2590239462Sdim  def RESTORE_DEALLOC_BEFORE_TAILCALL_V4 : JInst<(outs),
2591239462Sdim                                           (ins calltarget:$dst),
2592263508Sdim             "call $dst",
2593239462Sdim             []>,
2594239462Sdim             Requires<[HasV4T]>;
2595239462Sdim}
2596239462Sdim
2597239462Sdim// Save registers function call.
2598239462Sdimlet isCall = 1, isBarrier = 1,
2599239462Sdim  Uses = [R29, R31] in {
2600239462Sdim  def SAVE_REGISTERS_CALL_V4 : JInst<(outs),
2601239462Sdim                               (ins calltarget:$dst),
2602239462Sdim             "call $dst // Save_calle_saved_registers",
2603239462Sdim             []>,
2604239462Sdim             Requires<[HasV4T]>;
2605239462Sdim}
2606239462Sdim
2607234285Sdim//    if (Ps) dealloc_return
2608234285Sdimlet isReturn = 1, isTerminator = 1,
2609263508Sdim    Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1,
2610239462Sdim    isPredicated = 1 in {
2611263508Sdimlet validSubTargets = HasV4SubT in
2612263508Sdim  def DEALLOC_RET_cPt_V4 : LD0Inst<(outs),
2613263508Sdim                           (ins PredRegs:$src1),
2614234285Sdim            "if ($src1) dealloc_return",
2615234285Sdim            []>,
2616234285Sdim            Requires<[HasV4T]>;
2617234285Sdim}
2618234285Sdim
2619234285Sdim//    if (!Ps) dealloc_return
2620234285Sdimlet isReturn = 1, isTerminator = 1,
2621263508Sdim    Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1,
2622263508Sdim    isPredicated = 1, isPredicatedFalse = 1 in {
2623263508Sdimlet validSubTargets = HasV4SubT in
2624263508Sdim  def DEALLOC_RET_cNotPt_V4 : LD0Inst<(outs), (ins PredRegs:$src1),
2625234285Sdim            "if (!$src1) dealloc_return",
2626234285Sdim            []>,
2627234285Sdim            Requires<[HasV4T]>;
2628234285Sdim}
2629234285Sdim
2630234285Sdim//    if (Ps.new) dealloc_return:nt
2631234285Sdimlet isReturn = 1, isTerminator = 1,
2632263508Sdim    Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1,
2633239462Sdim    isPredicated = 1 in {
2634263508Sdimlet validSubTargets = HasV4SubT in
2635263508Sdim  def DEALLOC_RET_cdnPnt_V4 : LD0Inst<(outs), (ins PredRegs:$src1),
2636234285Sdim            "if ($src1.new) dealloc_return:nt",
2637234285Sdim            []>,
2638234285Sdim            Requires<[HasV4T]>;
2639234285Sdim}
2640234285Sdim
2641234285Sdim//    if (!Ps.new) dealloc_return:nt
2642234285Sdimlet isReturn = 1, isTerminator = 1,
2643263508Sdim    Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1,
2644263508Sdim    isPredicated = 1, isPredicatedFalse = 1 in {
2645263508Sdimlet validSubTargets = HasV4SubT in
2646263508Sdim  def DEALLOC_RET_cNotdnPnt_V4 : LD0Inst<(outs), (ins PredRegs:$src1),
2647234285Sdim            "if (!$src1.new) dealloc_return:nt",
2648234285Sdim            []>,
2649234285Sdim            Requires<[HasV4T]>;
2650234285Sdim}
2651234285Sdim
2652234285Sdim//    if (Ps.new) dealloc_return:t
2653234285Sdimlet isReturn = 1, isTerminator = 1,
2654263508Sdim    Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1,
2655239462Sdim    isPredicated = 1 in {
2656263508Sdimlet validSubTargets = HasV4SubT in
2657263508Sdim  def DEALLOC_RET_cdnPt_V4 : LD0Inst<(outs), (ins PredRegs:$src1),
2658234285Sdim            "if ($src1.new) dealloc_return:t",
2659234285Sdim            []>,
2660234285Sdim            Requires<[HasV4T]>;
2661234285Sdim}
2662234285Sdim
2663263508Sdim// if (!Ps.new) dealloc_return:nt
2664234285Sdimlet isReturn = 1, isTerminator = 1,
2665263508Sdim    Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1,
2666263508Sdim    isPredicated = 1, isPredicatedFalse = 1 in {
2667263508Sdimlet validSubTargets = HasV4SubT in
2668263508Sdim  def DEALLOC_RET_cNotdnPt_V4 : LD0Inst<(outs), (ins PredRegs:$src1),
2669234285Sdim            "if (!$src1.new) dealloc_return:t",
2670234285Sdim            []>,
2671234285Sdim            Requires<[HasV4T]>;
2672234285Sdim}
2673239462Sdim
2674239462Sdim// Load/Store with absolute addressing mode
2675239462Sdim// memw(#u6)=Rt
2676239462Sdim
2677249423Sdimmulticlass ST_Abs_Predbase<string mnemonic, RegisterClass RC, bit isNot,
2678249423Sdim                           bit isPredNew> {
2679251662Sdim  let isPredicatedNew = isPredNew in
2680249423Sdim  def NAME#_V4 : STInst2<(outs),
2681251662Sdim            (ins PredRegs:$src1, u0AlwaysExt:$absaddr, RC: $src2),
2682249423Sdim            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
2683249423Sdim            ") ")#mnemonic#"(##$absaddr) = $src2",
2684239462Sdim            []>,
2685239462Sdim            Requires<[HasV4T]>;
2686249423Sdim}
2687239462Sdim
2688249423Sdimmulticlass ST_Abs_Pred<string mnemonic, RegisterClass RC, bit PredNot> {
2689251662Sdim  let isPredicatedFalse = PredNot in {
2690249423Sdim    defm _c#NAME : ST_Abs_Predbase<mnemonic, RC, PredNot, 0>;
2691249423Sdim    // Predicate new
2692249423Sdim    defm _cdn#NAME : ST_Abs_Predbase<mnemonic, RC, PredNot, 1>;
2693249423Sdim  }
2694249423Sdim}
2695239462Sdim
2696249423Sdimlet isNVStorable = 1, isExtended = 1, neverHasSideEffects = 1 in
2697249423Sdimmulticlass ST_Abs<string mnemonic, string CextOp, RegisterClass RC> {
2698249423Sdim  let CextOpcode = CextOp, BaseOpcode = CextOp#_abs in {
2699249423Sdim    let opExtendable = 0, isPredicable = 1 in
2700249423Sdim    def NAME#_V4 : STInst2<(outs),
2701251662Sdim            (ins u0AlwaysExt:$absaddr, RC:$src),
2702249423Sdim            mnemonic#"(##$absaddr) = $src",
2703239462Sdim            []>,
2704239462Sdim            Requires<[HasV4T]>;
2705239462Sdim
2706249423Sdim    let opExtendable = 1, isPredicated = 1 in {
2707249423Sdim      defm Pt : ST_Abs_Pred<mnemonic, RC, 0>;
2708249423Sdim      defm NotPt : ST_Abs_Pred<mnemonic, RC, 1>;
2709249423Sdim    }
2710249423Sdim  }
2711249423Sdim}
2712239462Sdim
2713249423Sdimmulticlass ST_Abs_Predbase_nv<string mnemonic, RegisterClass RC, bit isNot,
2714249423Sdim                           bit isPredNew> {
2715251662Sdim  let isPredicatedNew = isPredNew in
2716249423Sdim  def NAME#_nv_V4 : NVInst_V4<(outs),
2717251662Sdim            (ins PredRegs:$src1, u0AlwaysExt:$absaddr, RC: $src2),
2718249423Sdim            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
2719249423Sdim            ") ")#mnemonic#"(##$absaddr) = $src2.new",
2720239462Sdim            []>,
2721239462Sdim            Requires<[HasV4T]>;
2722249423Sdim}
2723239462Sdim
2724249423Sdimmulticlass ST_Abs_Pred_nv<string mnemonic, RegisterClass RC, bit PredNot> {
2725251662Sdim  let isPredicatedFalse = PredNot in {
2726249423Sdim    defm _c#NAME : ST_Abs_Predbase_nv<mnemonic, RC, PredNot, 0>;
2727249423Sdim    // Predicate new
2728249423Sdim    defm _cdn#NAME : ST_Abs_Predbase_nv<mnemonic, RC, PredNot, 1>;
2729249423Sdim  }
2730249423Sdim}
2731239462Sdim
2732249423Sdimlet mayStore = 1, isNVStore = 1, isExtended = 1, neverHasSideEffects = 1 in
2733249423Sdimmulticlass ST_Abs_nv<string mnemonic, string CextOp, RegisterClass RC> {
2734249423Sdim  let CextOpcode = CextOp, BaseOpcode = CextOp#_abs in {
2735249423Sdim    let opExtendable = 0, isPredicable = 1 in
2736249423Sdim    def NAME#_nv_V4 : NVInst_V4<(outs),
2737251662Sdim            (ins u0AlwaysExt:$absaddr, RC:$src),
2738249423Sdim            mnemonic#"(##$absaddr) = $src.new",
2739239462Sdim            []>,
2740239462Sdim            Requires<[HasV4T]>;
2741239462Sdim
2742249423Sdim    let opExtendable = 1, isPredicated = 1 in {
2743249423Sdim      defm Pt : ST_Abs_Pred_nv<mnemonic, RC, 0>;
2744249423Sdim      defm NotPt : ST_Abs_Pred_nv<mnemonic, RC, 1>;
2745249423Sdim    }
2746249423Sdim  }
2747239462Sdim}
2748239462Sdim
2749249423Sdimlet addrMode = Absolute in {
2750251662Sdim  let accessSize = ByteAccess in
2751249423Sdim    defm STrib_abs : ST_Abs<"memb", "STrib", IntRegs>,
2752249423Sdim                     ST_Abs_nv<"memb", "STrib", IntRegs>, AddrModeRel;
2753239462Sdim
2754251662Sdim  let accessSize = HalfWordAccess in
2755249423Sdim    defm STrih_abs : ST_Abs<"memh", "STrih", IntRegs>,
2756249423Sdim                     ST_Abs_nv<"memh", "STrih", IntRegs>, AddrModeRel;
2757239462Sdim
2758251662Sdim  let accessSize = WordAccess in
2759249423Sdim    defm STriw_abs : ST_Abs<"memw", "STriw", IntRegs>,
2760249423Sdim                     ST_Abs_nv<"memw", "STriw", IntRegs>, AddrModeRel;
2761239462Sdim
2762251662Sdim  let accessSize = DoubleWordAccess, isNVStorable = 0 in
2763249423Sdim    defm STrid_abs : ST_Abs<"memd", "STrid", DoubleRegs>, AddrModeRel;
2764249423Sdim}
2765239462Sdim
2766249423Sdimlet Predicates = [HasV4T], AddedComplexity = 30 in {
2767239462Sdimdef : Pat<(truncstorei8 (i32 IntRegs:$src1),
2768239462Sdim                        (HexagonCONST32 tglobaladdr:$absaddr)),
2769239462Sdim          (STrib_abs_V4 tglobaladdr: $absaddr, IntRegs: $src1)>;
2770239462Sdim
2771239462Sdimdef : Pat<(truncstorei16 (i32 IntRegs:$src1),
2772239462Sdim                          (HexagonCONST32 tglobaladdr:$absaddr)),
2773239462Sdim          (STrih_abs_V4 tglobaladdr: $absaddr, IntRegs: $src1)>;
2774239462Sdim
2775239462Sdimdef : Pat<(store (i32 IntRegs:$src1), (HexagonCONST32 tglobaladdr:$absaddr)),
2776239462Sdim          (STriw_abs_V4 tglobaladdr: $absaddr, IntRegs: $src1)>;
2777239462Sdim
2778249423Sdimdef : Pat<(store (i64 DoubleRegs:$src1),
2779249423Sdim                 (HexagonCONST32 tglobaladdr:$absaddr)),
2780249423Sdim          (STrid_abs_V4 tglobaladdr: $absaddr, DoubleRegs: $src1)>;
2781249423Sdim}
2782239462Sdim
2783249423Sdim//===----------------------------------------------------------------------===//
2784249423Sdim// multiclass for store instructions with GP-relative addressing mode.
2785249423Sdim// mem[bhwd](#global)=Rt
2786249423Sdim// if ([!]Pv[.new]) mem[bhwd](##global) = Rt
2787249423Sdim//===----------------------------------------------------------------------===//
2788251662Sdimlet mayStore = 1, isNVStorable = 1 in
2789249423Sdimmulticlass ST_GP<string mnemonic, string BaseOp, RegisterClass RC> {
2790249423Sdim  let BaseOpcode = BaseOp, isPredicable = 1 in
2791249423Sdim  def NAME#_V4 : STInst2<(outs),
2792249423Sdim          (ins globaladdress:$global, RC:$src),
2793249423Sdim          mnemonic#"(#$global) = $src",
2794249423Sdim          []>;
2795239462Sdim
2796249423Sdim  // When GP-relative instructions are predicated, their addressing mode is
2797249423Sdim  // changed to absolute and they are always constant extended.
2798249423Sdim  let BaseOpcode = BaseOp, isExtended = 1, opExtendable = 1,
2799249423Sdim  isPredicated = 1 in {
2800249423Sdim    defm Pt : ST_Abs_Pred <mnemonic, RC, 0>;
2801249423Sdim    defm NotPt : ST_Abs_Pred <mnemonic, RC, 1>;
2802249423Sdim  }
2803249423Sdim}
2804239462Sdim
2805249423Sdimlet mayStore = 1, isNVStore = 1 in
2806249423Sdimmulticlass ST_GP_nv<string mnemonic, string BaseOp, RegisterClass RC> {
2807249423Sdim  let BaseOpcode = BaseOp, isPredicable = 1 in
2808249423Sdim  def NAME#_nv_V4 : NVInst_V4<(outs),
2809249423Sdim          (ins u0AlwaysExt:$global, RC:$src),
2810249423Sdim          mnemonic#"(#$global) = $src.new",
2811249423Sdim          []>,
2812249423Sdim          Requires<[HasV4T]>;
2813239462Sdim
2814249423Sdim  // When GP-relative instructions are predicated, their addressing mode is
2815249423Sdim  // changed to absolute and they are always constant extended.
2816249423Sdim  let BaseOpcode = BaseOp, isExtended = 1, opExtendable = 1,
2817249423Sdim  isPredicated = 1 in {
2818249423Sdim    defm Pt : ST_Abs_Pred_nv<mnemonic, RC, 0>;
2819249423Sdim    defm NotPt : ST_Abs_Pred_nv<mnemonic, RC, 1>;
2820249423Sdim  }
2821249423Sdim}
2822239462Sdim
2823251662Sdimlet validSubTargets = HasV4SubT, neverHasSideEffects = 1 in {
2824251662Sdim  let isNVStorable = 0 in
2825251662Sdim  defm STd_GP : ST_GP <"memd", "STd_GP", DoubleRegs>, PredNewRel;
2826251662Sdim
2827251662Sdim  defm STb_GP : ST_GP<"memb",  "STb_GP", IntRegs>,
2828251662Sdim                ST_GP_nv<"memb", "STb_GP", IntRegs>, NewValueRel;
2829251662Sdim  defm STh_GP : ST_GP<"memh",  "STh_GP", IntRegs>,
2830251662Sdim                ST_GP_nv<"memh", "STh_GP", IntRegs>, NewValueRel;
2831251662Sdim  defm STw_GP : ST_GP<"memw",  "STw_GP", IntRegs>,
2832251662Sdim                ST_GP_nv<"memw", "STw_GP", IntRegs>, NewValueRel;
2833239462Sdim}
2834239462Sdim
2835249423Sdim// 64 bit atomic store
2836249423Sdimdef : Pat <(atomic_store_64 (HexagonCONST32_GP tglobaladdr:$global),
2837249423Sdim                            (i64 DoubleRegs:$src1)),
2838249423Sdim           (STd_GP_V4 tglobaladdr:$global, (i64 DoubleRegs:$src1))>,
2839249423Sdim           Requires<[HasV4T]>;
2840239462Sdim
2841249423Sdim// Map from store(globaladdress) -> memd(#foo)
2842249423Sdimlet AddedComplexity = 100 in
2843249423Sdimdef : Pat <(store (i64 DoubleRegs:$src1),
2844249423Sdim                  (HexagonCONST32_GP tglobaladdr:$global)),
2845249423Sdim           (STd_GP_V4 tglobaladdr:$global, (i64 DoubleRegs:$src1))>;
2846239462Sdim
2847249423Sdim// 8 bit atomic store
2848249423Sdimdef : Pat < (atomic_store_8 (HexagonCONST32_GP tglobaladdr:$global),
2849249423Sdim                            (i32 IntRegs:$src1)),
2850249423Sdim            (STb_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>;
2851239462Sdim
2852249423Sdim// Map from store(globaladdress) -> memb(#foo)
2853249423Sdimlet AddedComplexity = 100 in
2854249423Sdimdef : Pat<(truncstorei8 (i32 IntRegs:$src1),
2855249423Sdim          (HexagonCONST32_GP tglobaladdr:$global)),
2856249423Sdim          (STb_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>;
2857239462Sdim
2858249423Sdim// Map from "i1 = constant<-1>; memw(CONST32(#foo)) = i1"
2859249423Sdim//       to "r0 = 1; memw(#foo) = r0"
2860249423Sdimlet AddedComplexity = 100 in
2861249423Sdimdef : Pat<(store (i1 -1), (HexagonCONST32_GP tglobaladdr:$global)),
2862249423Sdim          (STb_GP_V4 tglobaladdr:$global, (TFRI 1))>;
2863239462Sdim
2864249423Sdimdef : Pat<(atomic_store_16 (HexagonCONST32_GP tglobaladdr:$global),
2865249423Sdim                           (i32 IntRegs:$src1)),
2866249423Sdim          (STh_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>;
2867239462Sdim
2868249423Sdim// Map from store(globaladdress) -> memh(#foo)
2869249423Sdimlet AddedComplexity = 100 in
2870249423Sdimdef : Pat<(truncstorei16 (i32 IntRegs:$src1),
2871249423Sdim                         (HexagonCONST32_GP tglobaladdr:$global)),
2872249423Sdim          (STh_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>;
2873239462Sdim
2874249423Sdim// 32 bit atomic store
2875249423Sdimdef : Pat<(atomic_store_32 (HexagonCONST32_GP tglobaladdr:$global),
2876249423Sdim                           (i32 IntRegs:$src1)),
2877249423Sdim          (STw_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>;
2878249423Sdim
2879249423Sdim// Map from store(globaladdress) -> memw(#foo)
2880249423Sdimlet AddedComplexity = 100 in
2881249423Sdimdef : Pat<(store (i32 IntRegs:$src1), (HexagonCONST32_GP tglobaladdr:$global)),
2882249423Sdim          (STw_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>;
2883249423Sdim
2884249423Sdim//===----------------------------------------------------------------------===//
2885249423Sdim// Multiclass for the load instructions with absolute addressing mode.
2886249423Sdim//===----------------------------------------------------------------------===//
2887249423Sdimmulticlass LD_Abs_Predbase<string mnemonic, RegisterClass RC, bit isNot,
2888249423Sdim                           bit isPredNew> {
2889251662Sdim  let isPredicatedNew = isPredNew in
2890249423Sdim  def NAME : LDInst2<(outs RC:$dst),
2891251662Sdim            (ins PredRegs:$src1, u0AlwaysExt:$absaddr),
2892249423Sdim            !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ",
2893249423Sdim            ") ")#"$dst = "#mnemonic#"(##$absaddr)",
2894249423Sdim            []>,
2895249423Sdim            Requires<[HasV4T]>;
2896249423Sdim}
2897249423Sdim
2898249423Sdimmulticlass LD_Abs_Pred<string mnemonic, RegisterClass RC, bit PredNot> {
2899251662Sdim  let isPredicatedFalse = PredNot in {
2900249423Sdim    defm _c#NAME : LD_Abs_Predbase<mnemonic, RC, PredNot, 0>;
2901249423Sdim    // Predicate new
2902249423Sdim    defm _cdn#NAME : LD_Abs_Predbase<mnemonic, RC, PredNot, 1>;
2903249423Sdim  }
2904249423Sdim}
2905249423Sdim
2906249423Sdimlet isExtended = 1, neverHasSideEffects = 1 in
2907249423Sdimmulticlass LD_Abs<string mnemonic, string CextOp, RegisterClass RC> {
2908249423Sdim  let CextOpcode = CextOp, BaseOpcode = CextOp#_abs in {
2909249423Sdim    let  opExtendable = 1, isPredicable = 1 in
2910249423Sdim    def NAME#_V4 : LDInst2<(outs RC:$dst),
2911251662Sdim            (ins u0AlwaysExt:$absaddr),
2912249423Sdim            "$dst = "#mnemonic#"(##$absaddr)",
2913249423Sdim            []>,
2914249423Sdim            Requires<[HasV4T]>;
2915249423Sdim
2916249423Sdim    let opExtendable = 2, isPredicated = 1 in {
2917249423Sdim      defm Pt_V4 : LD_Abs_Pred<mnemonic, RC, 0>;
2918249423Sdim      defm NotPt_V4 : LD_Abs_Pred<mnemonic, RC, 1>;
2919249423Sdim    }
2920249423Sdim  }
2921249423Sdim}
2922249423Sdim
2923249423Sdimlet addrMode = Absolute in {
2924251662Sdim  let accessSize = ByteAccess in {
2925249423Sdim    defm LDrib_abs  : LD_Abs<"memb", "LDrib", IntRegs>, AddrModeRel;
2926249423Sdim    defm LDriub_abs : LD_Abs<"memub", "LDriub", IntRegs>, AddrModeRel;
2927251662Sdim  }
2928251662Sdim  let accessSize = HalfWordAccess in {
2929249423Sdim    defm LDrih_abs  : LD_Abs<"memh", "LDrih", IntRegs>, AddrModeRel;
2930249423Sdim    defm LDriuh_abs : LD_Abs<"memuh", "LDriuh", IntRegs>, AddrModeRel;
2931251662Sdim  }
2932251662Sdim  let accessSize = WordAccess in
2933249423Sdim    defm LDriw_abs  : LD_Abs<"memw", "LDriw", IntRegs>, AddrModeRel;
2934251662Sdim
2935251662Sdim  let accessSize = DoubleWordAccess in
2936249423Sdim    defm LDrid_abs : LD_Abs<"memd",  "LDrid", DoubleRegs>, AddrModeRel;
2937249423Sdim}
2938249423Sdim
2939251662Sdimlet Predicates = [HasV4T], AddedComplexity  = 30 in {
2940239462Sdimdef : Pat<(i32 (load (HexagonCONST32 tglobaladdr:$absaddr))),
2941239462Sdim          (LDriw_abs_V4 tglobaladdr: $absaddr)>;
2942239462Sdim
2943239462Sdimdef : Pat<(i32 (sextloadi8 (HexagonCONST32 tglobaladdr:$absaddr))),
2944239462Sdim          (LDrib_abs_V4 tglobaladdr:$absaddr)>;
2945239462Sdim
2946239462Sdimdef : Pat<(i32 (zextloadi8 (HexagonCONST32 tglobaladdr:$absaddr))),
2947239462Sdim          (LDriub_abs_V4 tglobaladdr:$absaddr)>;
2948239462Sdim
2949239462Sdimdef : Pat<(i32 (sextloadi16 (HexagonCONST32 tglobaladdr:$absaddr))),
2950239462Sdim          (LDrih_abs_V4 tglobaladdr:$absaddr)>;
2951239462Sdim
2952239462Sdimdef : Pat<(i32 (zextloadi16 (HexagonCONST32 tglobaladdr:$absaddr))),
2953239462Sdim          (LDriuh_abs_V4 tglobaladdr:$absaddr)>;
2954251662Sdim}
2955239462Sdim
2956249423Sdim//===----------------------------------------------------------------------===//
2957249423Sdim// multiclass for load instructions with GP-relative addressing mode.
2958249423Sdim// Rx=mem[bhwd](##global)
2959249423Sdim// if ([!]Pv[.new]) Rx=mem[bhwd](##global)
2960249423Sdim//===----------------------------------------------------------------------===//
2961249423Sdimlet neverHasSideEffects = 1, validSubTargets = HasV4SubT in
2962249423Sdimmulticlass LD_GP<string mnemonic, string BaseOp, RegisterClass RC> {
2963249423Sdim  let BaseOpcode = BaseOp in {
2964249423Sdim    let isPredicable = 1 in
2965249423Sdim    def NAME#_V4 : LDInst2<(outs RC:$dst),
2966249423Sdim            (ins globaladdress:$global),
2967249423Sdim            "$dst = "#mnemonic#"(#$global)",
2968249423Sdim            []>;
2969249423Sdim
2970249423Sdim    let isExtended = 1, opExtendable = 2, isPredicated = 1 in {
2971249423Sdim      defm Pt_V4 : LD_Abs_Pred<mnemonic, RC, 0>;
2972249423Sdim      defm NotPt_V4 : LD_Abs_Pred<mnemonic, RC, 1>;
2973249423Sdim    }
2974249423Sdim  }
2975249423Sdim}
2976249423Sdim
2977251662Sdimdefm LDd_GP  : LD_GP<"memd",  "LDd_GP",  DoubleRegs>, PredNewRel;
2978251662Sdimdefm LDb_GP  : LD_GP<"memb",  "LDb_GP",  IntRegs>, PredNewRel;
2979251662Sdimdefm LDub_GP : LD_GP<"memub", "LDub_GP", IntRegs>, PredNewRel;
2980251662Sdimdefm LDh_GP  : LD_GP<"memh",  "LDh_GP",  IntRegs>, PredNewRel;
2981251662Sdimdefm LDuh_GP : LD_GP<"memuh", "LDuh_GP", IntRegs>, PredNewRel;
2982251662Sdimdefm LDw_GP  : LD_GP<"memw",  "LDw_GP",  IntRegs>, PredNewRel;
2983249423Sdim
2984249423Sdimdef : Pat <(atomic_load_64 (HexagonCONST32_GP tglobaladdr:$global)),
2985249423Sdim           (i64 (LDd_GP_V4 tglobaladdr:$global))>;
2986249423Sdim
2987249423Sdimdef : Pat <(atomic_load_32 (HexagonCONST32_GP tglobaladdr:$global)),
2988249423Sdim           (i32 (LDw_GP_V4 tglobaladdr:$global))>;
2989249423Sdim
2990249423Sdimdef : Pat <(atomic_load_16 (HexagonCONST32_GP tglobaladdr:$global)),
2991249423Sdim           (i32 (LDuh_GP_V4 tglobaladdr:$global))>;
2992249423Sdim
2993249423Sdimdef : Pat <(atomic_load_8 (HexagonCONST32_GP tglobaladdr:$global)),
2994249423Sdim           (i32 (LDub_GP_V4 tglobaladdr:$global))>;
2995249423Sdim
2996249423Sdim// Map from load(globaladdress) -> memw(#foo + 0)
2997249423Sdimlet AddedComplexity = 100 in
2998249423Sdimdef : Pat <(i64 (load (HexagonCONST32_GP tglobaladdr:$global))),
2999249423Sdim           (i64 (LDd_GP_V4 tglobaladdr:$global))>;
3000249423Sdim
3001249423Sdim// Map from Pd = load(globaladdress) -> Rd = memb(globaladdress), Pd = Rd
3002249423Sdimlet AddedComplexity = 100 in
3003249423Sdimdef : Pat <(i1 (load (HexagonCONST32_GP tglobaladdr:$global))),
3004249423Sdim           (i1 (TFR_PdRs (i32 (LDb_GP_V4 tglobaladdr:$global))))>;
3005249423Sdim
3006249423Sdim// When the Interprocedural Global Variable optimizer realizes that a certain
3007249423Sdim// global variable takes only two constant values, it shrinks the global to
3008249423Sdim// a boolean. Catch those loads here in the following 3 patterns.
3009249423Sdimlet AddedComplexity = 100 in
3010249423Sdimdef : Pat <(i32 (extloadi1 (HexagonCONST32_GP tglobaladdr:$global))),
3011249423Sdim           (i32 (LDb_GP_V4 tglobaladdr:$global))>;
3012249423Sdim
3013249423Sdimlet AddedComplexity = 100 in
3014249423Sdimdef : Pat <(i32 (sextloadi1 (HexagonCONST32_GP tglobaladdr:$global))),
3015249423Sdim           (i32 (LDb_GP_V4 tglobaladdr:$global))>;
3016249423Sdim
3017249423Sdim// Map from load(globaladdress) -> memb(#foo)
3018249423Sdimlet AddedComplexity = 100 in
3019249423Sdimdef : Pat <(i32 (extloadi8 (HexagonCONST32_GP tglobaladdr:$global))),
3020249423Sdim           (i32 (LDb_GP_V4 tglobaladdr:$global))>;
3021249423Sdim
3022249423Sdim// Map from load(globaladdress) -> memb(#foo)
3023249423Sdimlet AddedComplexity = 100 in
3024249423Sdimdef : Pat <(i32 (sextloadi8 (HexagonCONST32_GP tglobaladdr:$global))),
3025249423Sdim           (i32 (LDb_GP_V4 tglobaladdr:$global))>;
3026249423Sdim
3027249423Sdimlet AddedComplexity = 100 in
3028249423Sdimdef : Pat <(i32 (zextloadi1 (HexagonCONST32_GP tglobaladdr:$global))),
3029249423Sdim           (i32 (LDub_GP_V4 tglobaladdr:$global))>;
3030249423Sdim
3031249423Sdim// Map from load(globaladdress) -> memub(#foo)
3032249423Sdimlet AddedComplexity = 100 in
3033249423Sdimdef : Pat <(i32 (zextloadi8 (HexagonCONST32_GP tglobaladdr:$global))),
3034249423Sdim           (i32 (LDub_GP_V4 tglobaladdr:$global))>;
3035249423Sdim
3036249423Sdim// Map from load(globaladdress) -> memh(#foo)
3037249423Sdimlet AddedComplexity = 100 in
3038249423Sdimdef : Pat <(i32 (extloadi16 (HexagonCONST32_GP tglobaladdr:$global))),
3039249423Sdim           (i32 (LDh_GP_V4 tglobaladdr:$global))>;
3040249423Sdim
3041249423Sdim// Map from load(globaladdress) -> memh(#foo)
3042249423Sdimlet AddedComplexity = 100 in
3043249423Sdimdef : Pat <(i32 (sextloadi16 (HexagonCONST32_GP tglobaladdr:$global))),
3044249423Sdim           (i32 (LDh_GP_V4 tglobaladdr:$global))>;
3045249423Sdim
3046249423Sdim// Map from load(globaladdress) -> memuh(#foo)
3047249423Sdimlet AddedComplexity = 100 in
3048249423Sdimdef : Pat <(i32 (zextloadi16 (HexagonCONST32_GP tglobaladdr:$global))),
3049249423Sdim           (i32 (LDuh_GP_V4 tglobaladdr:$global))>;
3050249423Sdim
3051249423Sdim// Map from load(globaladdress) -> memw(#foo)
3052249423Sdimlet AddedComplexity = 100 in
3053249423Sdimdef : Pat <(i32 (load (HexagonCONST32_GP tglobaladdr:$global))),
3054249423Sdim           (i32 (LDw_GP_V4 tglobaladdr:$global))>;
3055249423Sdim
3056249423Sdim
3057239462Sdim// Transfer global address into a register
3058251662Sdimlet isExtended = 1, opExtendable = 1, AddedComplexity=50, isMoveImm = 1,
3059251662SdimisAsCheapAsAMove = 1, isReMaterializable = 1, validSubTargets = HasV4SubT in
3060251662Sdimdef TFRI_V4 : ALU32_ri<(outs IntRegs:$dst), (ins s16Ext:$src1),
3061251662Sdim           "$dst = #$src1",
3062239462Sdim           [(set IntRegs:$dst, (HexagonCONST32 tglobaladdr:$src1))]>,
3063239462Sdim           Requires<[HasV4T]>;
3064239462Sdim
3065249423Sdim// Transfer a block address into a register
3066249423Sdimdef : Pat<(HexagonCONST32_GP tblockaddress:$src1),
3067249423Sdim          (TFRI_V4 tblockaddress:$src1)>,
3068249423Sdim          Requires<[HasV4T]>;
3069249423Sdim
3070263508Sdimlet isExtended = 1, opExtendable = 2, AddedComplexity=50,
3071263508SdimneverHasSideEffects = 1, isPredicated = 1, validSubTargets = HasV4SubT in
3072239462Sdimdef TFRI_cPt_V4 : ALU32_ri<(outs IntRegs:$dst),
3073263508Sdim                           (ins PredRegs:$src1, s16Ext:$src2),
3074263508Sdim           "if($src1) $dst = #$src2",
3075239462Sdim           []>,
3076239462Sdim           Requires<[HasV4T]>;
3077239462Sdim
3078263508Sdimlet isExtended = 1, opExtendable = 2, AddedComplexity=50, isPredicatedFalse = 1,
3079263508SdimneverHasSideEffects = 1, isPredicated = 1, validSubTargets = HasV4SubT in
3080239462Sdimdef TFRI_cNotPt_V4 : ALU32_ri<(outs IntRegs:$dst),
3081263508Sdim                              (ins PredRegs:$src1, s16Ext:$src2),
3082263508Sdim           "if(!$src1) $dst = #$src2",
3083239462Sdim           []>,
3084239462Sdim           Requires<[HasV4T]>;
3085239462Sdim
3086263508Sdimlet isExtended = 1, opExtendable = 2, AddedComplexity=50,
3087263508SdimneverHasSideEffects = 1, isPredicated = 1, validSubTargets = HasV4SubT in
3088239462Sdimdef TFRI_cdnPt_V4 : ALU32_ri<(outs IntRegs:$dst),
3089263508Sdim                             (ins PredRegs:$src1, s16Ext:$src2),
3090263508Sdim           "if($src1.new) $dst = #$src2",
3091239462Sdim           []>,
3092239462Sdim           Requires<[HasV4T]>;
3093239462Sdim
3094263508Sdimlet isExtended = 1, opExtendable = 2, AddedComplexity=50, isPredicatedFalse = 1,
3095263508SdimneverHasSideEffects = 1, isPredicated = 1, validSubTargets = HasV4SubT in
3096239462Sdimdef TFRI_cdnNotPt_V4 : ALU32_ri<(outs IntRegs:$dst),
3097263508Sdim                                (ins PredRegs:$src1, s16Ext:$src2),
3098263508Sdim           "if(!$src1.new) $dst = #$src2",
3099239462Sdim           []>,
3100239462Sdim           Requires<[HasV4T]>;
3101239462Sdim
3102239462Sdimlet AddedComplexity = 50, Predicates = [HasV4T] in
3103239462Sdimdef : Pat<(HexagonCONST32_GP tglobaladdr:$src1),
3104263508Sdim           (TFRI_V4 tglobaladdr:$src1)>,
3105263508Sdim           Requires<[HasV4T]>;
3106239462Sdim
3107239462Sdim
3108239462Sdim// Load - Indirect with long offset: These instructions take global address
3109239462Sdim// as an operand
3110251662Sdimlet isExtended = 1, opExtendable = 3, AddedComplexity = 40,
3111251662SdimvalidSubTargets = HasV4SubT in
3112239462Sdimdef LDrid_ind_lo_V4 : LDInst<(outs DoubleRegs:$dst),
3113251662Sdim            (ins IntRegs:$src1, u2Imm:$src2, globaladdressExt:$offset),
3114239462Sdim            "$dst=memd($src1<<#$src2+##$offset)",
3115239462Sdim            [(set (i64 DoubleRegs:$dst),
3116239462Sdim                  (load (add (shl IntRegs:$src1, u2ImmPred:$src2),
3117239462Sdim                        (HexagonCONST32 tglobaladdr:$offset))))]>,
3118239462Sdim            Requires<[HasV4T]>;
3119239462Sdim
3120251662Sdimlet AddedComplexity = 40 in
3121239462Sdimmulticlass LD_indirect_lo<string OpcStr, PatFrag OpNode> {
3122251662Sdimlet isExtended = 1, opExtendable = 3, validSubTargets = HasV4SubT in
3123239462Sdim  def _lo_V4 : LDInst<(outs IntRegs:$dst),
3124251662Sdim            (ins IntRegs:$src1, u2Imm:$src2, globaladdressExt:$offset),
3125239462Sdim            !strconcat("$dst = ",
3126239462Sdim            !strconcat(OpcStr, "($src1<<#$src2+##$offset)")),
3127239462Sdim            [(set IntRegs:$dst,
3128239462Sdim                  (i32 (OpNode (add (shl IntRegs:$src1, u2ImmPred:$src2),
3129239462Sdim                          (HexagonCONST32 tglobaladdr:$offset)))))]>,
3130239462Sdim            Requires<[HasV4T]>;
3131239462Sdim}
3132239462Sdim
3133239462Sdimdefm LDrib_ind : LD_indirect_lo<"memb", sextloadi8>;
3134239462Sdimdefm LDriub_ind : LD_indirect_lo<"memub", zextloadi8>;
3135251662Sdimdefm LDriub_ind_anyext : LD_indirect_lo<"memub", extloadi8>;
3136239462Sdimdefm LDrih_ind : LD_indirect_lo<"memh", sextloadi16>;
3137239462Sdimdefm LDriuh_ind : LD_indirect_lo<"memuh", zextloadi16>;
3138251662Sdimdefm LDriuh_ind_anyext : LD_indirect_lo<"memuh", extloadi16>;
3139239462Sdimdefm LDriw_ind : LD_indirect_lo<"memw", load>;
3140239462Sdim
3141251662Sdimlet AddedComplexity = 40 in
3142251662Sdimdef : Pat <(i32 (sextloadi8 (add IntRegs:$src1,
3143251662Sdim                                 (NumUsesBelowThresCONST32 tglobaladdr:$offset)))),
3144251662Sdim           (i32 (LDrib_ind_lo_V4 IntRegs:$src1, 0, tglobaladdr:$offset))>,
3145251662Sdim           Requires<[HasV4T]>;
3146239462Sdim
3147251662Sdimlet AddedComplexity = 40 in
3148251662Sdimdef : Pat <(i32 (zextloadi8 (add IntRegs:$src1,
3149251662Sdim                                 (NumUsesBelowThresCONST32 tglobaladdr:$offset)))),
3150251662Sdim           (i32 (LDriub_ind_lo_V4 IntRegs:$src1, 0, tglobaladdr:$offset))>,
3151251662Sdim           Requires<[HasV4T]>;
3152239462Sdim
3153249423Sdimlet Predicates = [HasV4T], AddedComplexity  = 30 in {
3154249423Sdimdef : Pat<(truncstorei8 (i32 IntRegs:$src1), u0AlwaysExtPred:$src2),
3155251662Sdim          (STrib_abs_V4 u0AlwaysExtPred:$src2, IntRegs: $src1)>;
3156239462Sdim
3157249423Sdimdef : Pat<(truncstorei16 (i32 IntRegs:$src1), u0AlwaysExtPred:$src2),
3158251662Sdim          (STrih_abs_V4 u0AlwaysExtPred:$src2, IntRegs: $src1)>;
3159239462Sdim
3160249423Sdimdef : Pat<(store (i32 IntRegs:$src1), u0AlwaysExtPred:$src2),
3161251662Sdim          (STriw_abs_V4 u0AlwaysExtPred:$src2, IntRegs: $src1)>;
3162249423Sdim}
3163239462Sdim
3164249423Sdimlet Predicates = [HasV4T], AddedComplexity  = 30 in {
3165249423Sdimdef : Pat<(i32 (load u0AlwaysExtPred:$src)),
3166251662Sdim          (LDriw_abs_V4 u0AlwaysExtPred:$src)>;
3167239462Sdim
3168249423Sdimdef : Pat<(i32 (sextloadi8 u0AlwaysExtPred:$src)),
3169251662Sdim          (LDrib_abs_V4 u0AlwaysExtPred:$src)>;
3170239462Sdim
3171249423Sdimdef : Pat<(i32 (zextloadi8 u0AlwaysExtPred:$src)),
3172251662Sdim          (LDriub_abs_V4 u0AlwaysExtPred:$src)>;
3173239462Sdim
3174249423Sdimdef : Pat<(i32 (sextloadi16 u0AlwaysExtPred:$src)),
3175251662Sdim          (LDrih_abs_V4 u0AlwaysExtPred:$src)>;
3176239462Sdim
3177249423Sdimdef : Pat<(i32 (zextloadi16 u0AlwaysExtPred:$src)),
3178251662Sdim          (LDriuh_abs_V4 u0AlwaysExtPred:$src)>;
3179249423Sdim}
3180239462Sdim
3181251662Sdim// Indexed store word - global address.
3182239462Sdim// memw(Rs+#u6:2)=#S8
3183239462Sdimlet AddedComplexity = 10 in
3184239462Sdimdef STriw_offset_ext_V4 : STInst<(outs),
3185239462Sdim            (ins IntRegs:$src1, u6_2Imm:$src2, globaladdress:$src3),
3186239462Sdim            "memw($src1+#$src2) = ##$src3",
3187239462Sdim            [(store (HexagonCONST32 tglobaladdr:$src3),
3188239462Sdim                    (add IntRegs:$src1, u6_2ImmPred:$src2))]>,
3189239462Sdim            Requires<[HasV4T]>;
3190239462Sdim
3191263508Sdimdef : Pat<(i64 (ctlz (i64 DoubleRegs:$src1))),
3192263508Sdim          (i64 (COMBINE_Ir_V4 (i32 0), (i32 (CTLZ64_rr DoubleRegs:$src1))))>,
3193263508Sdim          Requires<[HasV4T]>;
3194239462Sdim
3195263508Sdimdef : Pat<(i64 (cttz (i64 DoubleRegs:$src1))),
3196263508Sdim          (i64 (COMBINE_Ir_V4 (i32 0), (i32 (CTTZ64_rr DoubleRegs:$src1))))>,
3197263508Sdim          Requires<[HasV4T]>;
3198263508Sdim
3199263508Sdim
3200263508Sdim// i8 -> i64 loads
3201263508Sdim// We need a complexity of 120 here to overide preceeding handling of
3202263508Sdim// zextloadi8.
3203263508Sdimlet Predicates = [HasV4T], AddedComplexity = 120 in {
3204263508Sdimdef:  Pat <(i64 (extloadi8 (NumUsesBelowThresCONST32 tglobaladdr:$addr))),
3205263508Sdim      (i64 (COMBINE_Ir_V4 0, (LDrib_abs_V4 tglobaladdr:$addr)))>;
3206263508Sdim
3207263508Sdimdef:  Pat <(i64 (zextloadi8 (NumUsesBelowThresCONST32 tglobaladdr:$addr))),
3208263508Sdim      (i64 (COMBINE_Ir_V4 0, (LDriub_abs_V4 tglobaladdr:$addr)))>;
3209263508Sdim
3210263508Sdimdef:  Pat <(i64 (sextloadi8 (NumUsesBelowThresCONST32 tglobaladdr:$addr))),
3211263508Sdim      (i64 (SXTW (LDrib_abs_V4 tglobaladdr:$addr)))>;
3212263508Sdim
3213263508Sdimdef:  Pat <(i64 (extloadi8 FoldGlobalAddr:$addr)),
3214263508Sdim      (i64 (COMBINE_Ir_V4 0, (LDrib_abs_V4 FoldGlobalAddr:$addr)))>;
3215263508Sdim
3216263508Sdimdef:  Pat <(i64 (zextloadi8 FoldGlobalAddr:$addr)),
3217263508Sdim      (i64 (COMBINE_Ir_V4 0, (LDriub_abs_V4 FoldGlobalAddr:$addr)))>;
3218263508Sdim
3219263508Sdimdef:  Pat <(i64 (sextloadi8 FoldGlobalAddr:$addr)),
3220263508Sdim      (i64 (SXTW (LDrib_abs_V4 FoldGlobalAddr:$addr)))>;
3221263508Sdim}
3222263508Sdim// i16 -> i64 loads
3223263508Sdim// We need a complexity of 120 here to overide preceeding handling of
3224263508Sdim// zextloadi16.
3225263508Sdimlet AddedComplexity = 120 in {
3226263508Sdimdef:  Pat <(i64 (extloadi16 (NumUsesBelowThresCONST32 tglobaladdr:$addr))),
3227263508Sdim      (i64 (COMBINE_Ir_V4 0, (LDrih_abs_V4 tglobaladdr:$addr)))>,
3228263508Sdim      Requires<[HasV4T]>;
3229263508Sdim
3230263508Sdimdef:  Pat <(i64 (zextloadi16 (NumUsesBelowThresCONST32 tglobaladdr:$addr))),
3231263508Sdim      (i64 (COMBINE_Ir_V4 0, (LDriuh_abs_V4 tglobaladdr:$addr)))>,
3232263508Sdim      Requires<[HasV4T]>;
3233263508Sdim
3234263508Sdimdef:  Pat <(i64 (sextloadi16 (NumUsesBelowThresCONST32 tglobaladdr:$addr))),
3235263508Sdim      (i64 (SXTW (LDrih_abs_V4 tglobaladdr:$addr)))>,
3236263508Sdim      Requires<[HasV4T]>;
3237263508Sdim
3238263508Sdimdef:  Pat <(i64 (extloadi16 FoldGlobalAddr:$addr)),
3239263508Sdim      (i64 (COMBINE_Ir_V4 0, (LDrih_abs_V4 FoldGlobalAddr:$addr)))>,
3240263508Sdim      Requires<[HasV4T]>;
3241263508Sdim
3242263508Sdimdef:  Pat <(i64 (zextloadi16 FoldGlobalAddr:$addr)),
3243263508Sdim      (i64 (COMBINE_Ir_V4 0, (LDriuh_abs_V4 FoldGlobalAddr:$addr)))>,
3244263508Sdim      Requires<[HasV4T]>;
3245263508Sdim
3246263508Sdimdef:  Pat <(i64 (sextloadi16 FoldGlobalAddr:$addr)),
3247263508Sdim      (i64 (SXTW (LDrih_abs_V4 FoldGlobalAddr:$addr)))>,
3248263508Sdim      Requires<[HasV4T]>;
3249263508Sdim}
3250263508Sdim// i32->i64 loads
3251263508Sdim// We need a complexity of 120 here to overide preceeding handling of
3252263508Sdim// zextloadi32.
3253263508Sdimlet AddedComplexity = 120 in {
3254263508Sdimdef:  Pat <(i64 (extloadi32 (NumUsesBelowThresCONST32 tglobaladdr:$addr))),
3255263508Sdim      (i64 (COMBINE_Ir_V4 0, (LDriw_abs_V4 tglobaladdr:$addr)))>,
3256263508Sdim      Requires<[HasV4T]>;
3257263508Sdim
3258263508Sdimdef:  Pat <(i64 (zextloadi32 (NumUsesBelowThresCONST32 tglobaladdr:$addr))),
3259263508Sdim      (i64 (COMBINE_Ir_V4 0, (LDriw_abs_V4 tglobaladdr:$addr)))>,
3260263508Sdim      Requires<[HasV4T]>;
3261263508Sdim
3262263508Sdimdef:  Pat <(i64 (sextloadi32 (NumUsesBelowThresCONST32 tglobaladdr:$addr))),
3263263508Sdim      (i64 (SXTW (LDriw_abs_V4 tglobaladdr:$addr)))>,
3264263508Sdim      Requires<[HasV4T]>;
3265263508Sdim
3266263508Sdimdef:  Pat <(i64 (extloadi32 FoldGlobalAddr:$addr)),
3267263508Sdim      (i64 (COMBINE_Ir_V4 0, (LDriw_abs_V4 FoldGlobalAddr:$addr)))>,
3268263508Sdim      Requires<[HasV4T]>;
3269263508Sdim
3270263508Sdimdef:  Pat <(i64 (zextloadi32 FoldGlobalAddr:$addr)),
3271263508Sdim      (i64 (COMBINE_Ir_V4 0, (LDriw_abs_V4 FoldGlobalAddr:$addr)))>,
3272263508Sdim      Requires<[HasV4T]>;
3273263508Sdim
3274263508Sdimdef:  Pat <(i64 (sextloadi32 FoldGlobalAddr:$addr)),
3275263508Sdim      (i64 (SXTW (LDriw_abs_V4 FoldGlobalAddr:$addr)))>,
3276263508Sdim      Requires<[HasV4T]>;
3277263508Sdim}
3278263508Sdim
3279239462Sdim// Indexed store double word - global address.
3280239462Sdim// memw(Rs+#u6:2)=#S8
3281239462Sdimlet AddedComplexity = 10 in
3282239462Sdimdef STrih_offset_ext_V4 : STInst<(outs),
3283239462Sdim            (ins IntRegs:$src1, u6_1Imm:$src2, globaladdress:$src3),
3284239462Sdim            "memh($src1+#$src2) = ##$src3",
3285239462Sdim            [(truncstorei16 (HexagonCONST32 tglobaladdr:$src3),
3286239462Sdim                    (add IntRegs:$src1, u6_1ImmPred:$src2))]>,
3287239462Sdim            Requires<[HasV4T]>;
3288249423Sdim// Map from store(globaladdress + x) -> memd(#foo + x)
3289249423Sdimlet AddedComplexity = 100 in
3290249423Sdimdef : Pat<(store (i64 DoubleRegs:$src1),
3291249423Sdim                 FoldGlobalAddrGP:$addr),
3292249423Sdim          (STrid_abs_V4 FoldGlobalAddrGP:$addr, (i64 DoubleRegs:$src1))>,
3293249423Sdim          Requires<[HasV4T]>;
3294249423Sdim
3295249423Sdimdef : Pat<(atomic_store_64 FoldGlobalAddrGP:$addr,
3296249423Sdim                           (i64 DoubleRegs:$src1)),
3297249423Sdim          (STrid_abs_V4 FoldGlobalAddrGP:$addr, (i64 DoubleRegs:$src1))>,
3298249423Sdim          Requires<[HasV4T]>;
3299249423Sdim
3300249423Sdim// Map from store(globaladdress + x) -> memb(#foo + x)
3301249423Sdimlet AddedComplexity = 100 in
3302249423Sdimdef : Pat<(truncstorei8 (i32 IntRegs:$src1), FoldGlobalAddrGP:$addr),
3303249423Sdim          (STrib_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>,
3304249423Sdim            Requires<[HasV4T]>;
3305249423Sdim
3306249423Sdimdef : Pat<(atomic_store_8 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1)),
3307249423Sdim          (STrib_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>,
3308249423Sdim            Requires<[HasV4T]>;
3309249423Sdim
3310249423Sdim// Map from store(globaladdress + x) -> memh(#foo + x)
3311249423Sdimlet AddedComplexity = 100 in
3312249423Sdimdef : Pat<(truncstorei16 (i32 IntRegs:$src1), FoldGlobalAddrGP:$addr),
3313249423Sdim          (STrih_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>,
3314249423Sdim            Requires<[HasV4T]>;
3315249423Sdim
3316249423Sdimdef : Pat<(atomic_store_16 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1)),
3317249423Sdim          (STrih_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>,
3318249423Sdim            Requires<[HasV4T]>;
3319249423Sdim
3320249423Sdim// Map from store(globaladdress + x) -> memw(#foo + x)
3321249423Sdimlet AddedComplexity = 100 in
3322249423Sdimdef : Pat<(store (i32 IntRegs:$src1), FoldGlobalAddrGP:$addr),
3323249423Sdim          (STriw_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>,
3324249423Sdim           Requires<[HasV4T]>;
3325249423Sdim
3326249423Sdimdef : Pat<(atomic_store_32 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1)),
3327249423Sdim          (STriw_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>,
3328249423Sdim            Requires<[HasV4T]>;
3329249423Sdim
3330249423Sdim// Map from load(globaladdress + x) -> memd(#foo + x)
3331249423Sdimlet AddedComplexity = 100 in
3332249423Sdimdef : Pat<(i64 (load FoldGlobalAddrGP:$addr)),
3333249423Sdim          (i64 (LDrid_abs_V4 FoldGlobalAddrGP:$addr))>,
3334249423Sdim           Requires<[HasV4T]>;
3335249423Sdim
3336249423Sdimdef : Pat<(atomic_load_64 FoldGlobalAddrGP:$addr),
3337249423Sdim          (i64 (LDrid_abs_V4 FoldGlobalAddrGP:$addr))>,
3338249423Sdim           Requires<[HasV4T]>;
3339249423Sdim
3340249423Sdim// Map from load(globaladdress + x) -> memb(#foo + x)
3341249423Sdimlet AddedComplexity = 100 in
3342249423Sdimdef : Pat<(i32 (extloadi8 FoldGlobalAddrGP:$addr)),
3343249423Sdim          (i32 (LDrib_abs_V4 FoldGlobalAddrGP:$addr))>,
3344249423Sdim           Requires<[HasV4T]>;
3345249423Sdim
3346249423Sdim// Map from load(globaladdress + x) -> memb(#foo + x)
3347249423Sdimlet AddedComplexity = 100 in
3348249423Sdimdef : Pat<(i32 (sextloadi8 FoldGlobalAddrGP:$addr)),
3349249423Sdim          (i32 (LDrib_abs_V4 FoldGlobalAddrGP:$addr))>,
3350249423Sdim           Requires<[HasV4T]>;
3351249423Sdim
3352249423Sdim//let AddedComplexity = 100 in
3353249423Sdimlet AddedComplexity = 100 in
3354249423Sdimdef : Pat<(i32 (extloadi16 FoldGlobalAddrGP:$addr)),
3355249423Sdim          (i32 (LDrih_abs_V4 FoldGlobalAddrGP:$addr))>,
3356249423Sdim           Requires<[HasV4T]>;
3357249423Sdim
3358249423Sdim// Map from load(globaladdress + x) -> memh(#foo + x)
3359249423Sdimlet AddedComplexity = 100 in
3360249423Sdimdef : Pat<(i32 (sextloadi16 FoldGlobalAddrGP:$addr)),
3361249423Sdim          (i32 (LDrih_abs_V4 FoldGlobalAddrGP:$addr))>,
3362249423Sdim           Requires<[HasV4T]>;
3363249423Sdim
3364249423Sdim// Map from load(globaladdress + x) -> memuh(#foo + x)
3365249423Sdimlet AddedComplexity = 100 in
3366249423Sdimdef : Pat<(i32 (zextloadi16 FoldGlobalAddrGP:$addr)),
3367249423Sdim          (i32 (LDriuh_abs_V4 FoldGlobalAddrGP:$addr))>,
3368249423Sdim           Requires<[HasV4T]>;
3369249423Sdim
3370249423Sdimdef : Pat<(atomic_load_16 FoldGlobalAddrGP:$addr),
3371249423Sdim          (i32 (LDriuh_abs_V4 FoldGlobalAddrGP:$addr))>,
3372249423Sdim           Requires<[HasV4T]>;
3373249423Sdim
3374249423Sdim// Map from load(globaladdress + x) -> memub(#foo + x)
3375249423Sdimlet AddedComplexity = 100 in
3376249423Sdimdef : Pat<(i32 (zextloadi8 FoldGlobalAddrGP:$addr)),
3377249423Sdim          (i32 (LDriub_abs_V4 FoldGlobalAddrGP:$addr))>,
3378249423Sdim           Requires<[HasV4T]>;
3379249423Sdim
3380249423Sdimdef : Pat<(atomic_load_8 FoldGlobalAddrGP:$addr),
3381249423Sdim          (i32 (LDriub_abs_V4 FoldGlobalAddrGP:$addr))>,
3382249423Sdim           Requires<[HasV4T]>;
3383249423Sdim
3384249423Sdim// Map from load(globaladdress + x) -> memw(#foo + x)
3385249423Sdimlet AddedComplexity = 100 in
3386249423Sdimdef : Pat<(i32 (load FoldGlobalAddrGP:$addr)),
3387249423Sdim          (i32 (LDriw_abs_V4 FoldGlobalAddrGP:$addr))>,
3388249423Sdim           Requires<[HasV4T]>;
3389249423Sdim
3390249423Sdimdef : Pat<(atomic_load_32 FoldGlobalAddrGP:$addr),
3391249423Sdim          (i32 (LDriw_abs_V4 FoldGlobalAddrGP:$addr))>,
3392249423Sdim           Requires<[HasV4T]>;
3393