1//===- ARCInstrInfo.td - Target Description for ARC --------*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file describes the ARC instructions in TableGen format.
10//
11//===----------------------------------------------------------------------===//
12
13include "ARCInstrFormats.td"
14
15//===----------------------------------------------------------------------===//
16// Operand Pattern Stuff.
17//===----------------------------------------------------------------------===//
18
19// Operand for printing out a condition code.
20let PrintMethod = "printCCOperand" in
21  def CCOp : PredicateOperand<i32, (ops i32imm), (ops)>;
22
23// The "u6" operand of a RRU6-type instruction
24let PrintMethod = "printU6" in {
25  def u6 : Operand<i32>, ImmLeaf<i32, [{
26    return isUInt<6>(Imm);
27  }]>;
28  def wide_u6 : Operand<i64>, ImmLeaf<i64, [{
29    return isUInt<6>(Imm);
30  }]>;
31}
32
33// ---------------------------------------------------------------------------
34// Selection DAG Nodes.
35// ---------------------------------------------------------------------------
36
37// Selection DAG types.
38def SDT_ARCcmptst : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
39def SDT_ARCcmov : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>]>;
40def SDT_ARCmov : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>]>;
41def SDT_ARCbrcc : SDTypeProfile<0, 4, []>;
42def SDT_ARCBranchLink : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
43def SDT_ARCCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32>,
44                                           SDTCisVT<1, i32> ]>;
45def SDT_ARCCallSeqEnd   : SDCallSeqEnd<[ SDTCisVT<0, i32>,
46                                         SDTCisVT<1, i32> ]>;
47
48// Global Address.
49def ARCGAWrapper : SDNode<"ARCISD::GAWRAPPER", SDT_ARCmov, []>;
50
51// Comparison
52def ARCcmp : SDNode<"ARCISD::CMP", SDT_ARCcmptst, [SDNPOutGlue]>;
53
54// Conditional mov
55def ARCcmov : SDNode<"ARCISD::CMOV", SDT_ARCcmov, [SDNPInGlue]>;
56
57// Conditional Branch
58def ARCbrcc : SDNode<"ARCISD::BRcc", SDT_ARCbrcc,
59                       [SDNPHasChain, SDNPInGlue, SDNPOutGlue]>;
60
61// Direct Call
62def ARCBranchLink     : SDNode<"ARCISD::BL",SDT_ARCBranchLink,
63                            [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
64                             SDNPVariadic]>;
65
66// Indirect Call
67def ARCJumpLink       : SDNode<"ARCISD::JL",SDT_ARCBranchLink,
68                                 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
69                                  SDNPVariadic]>;
70// Call return
71def ret      : SDNode<"ARCISD::RET", SDTNone,
72                      [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
73
74// Call sequencing nodes.
75// These are target-independent nodes, but have target-specific formats.
76def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_ARCCallSeqStart,
77                           [SDNPHasChain, SDNPOutGlue]>;
78def callseq_end   : SDNode<"ISD::CALLSEQ_END",   SDT_ARCCallSeqEnd,
79                           [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
80
81//===----------------------------------------------------------------------===//
82// Instruction predicates
83//===----------------------------------------------------------------------===//
84
85def HasNorm  :       Predicate<"Subtarget->hasNorm()">;
86
87//===----------------------------------------------------------------------===//
88// Instruction Pattern Stuff
89//===----------------------------------------------------------------------===//
90
91def imm32 : ImmLeaf<i32, [{
92  return (Imm & 0xFFFFFFFF) == Imm;
93}]>;
94
95// Addressing modes
96def FrameADDR_ri : ComplexPattern<i32, 2, "SelectFrameADDR_ri",
97                                  [add, frameindex], []>;
98def AddrModeS9 : ComplexPattern<i32, 2, "SelectAddrModeS9", []>;
99def AddrModeImm : ComplexPattern<i32, 2, "SelectAddrModeImm", []>;
100def AddrModeFar : ComplexPattern<i32, 2, "SelectAddrModeFar", []>;
101
102//===----------------------------------------------------------------------===//
103// Instruction Class Templates
104//===----------------------------------------------------------------------===//
105
106//===----------------------------------------------------------------------===//
107// Pseudo Instructions
108//===----------------------------------------------------------------------===//
109
110let Defs = [SP], Uses = [SP] in {
111def ADJCALLSTACKDOWN : PseudoInstARC<(outs), (ins i32imm:$amt, i32imm:$amt2),
112                               "# ADJCALLSTACKDOWN $amt, $amt2",
113                               [(callseq_start timm:$amt, timm:$amt2)]>;
114def ADJCALLSTACKUP : PseudoInstARC<(outs), (ins i32imm:$amt1, i32imm:$amt2),
115                            "# ADJCALLSTACKUP $amt1",
116                            [(callseq_end timm:$amt1, timm:$amt2)]>;
117}
118
119def GETFI : PseudoInstARC<(outs GPR32:$dst), (ins MEMii:$addr),
120                             "pldfi $dst, $addr",
121                             [(set GPR32:$dst, FrameADDR_ri:$addr)]>;
122
123
124def ST_FAR : PseudoInstARC<(outs), (ins GPR32:$dst, MEMrlimm:$addr),
125                             "ST_FAR $dst, $addr",
126                             [(store GPR32:$dst, AddrModeFar:$addr)]>;
127
128def STH_FAR : PseudoInstARC<(outs), (ins GPR32:$dst, MEMrlimm:$addr),
129                             "STH_FAR $dst, $addr",
130                             [(truncstorei16 GPR32:$dst, AddrModeFar:$addr)]>;
131
132def STB_FAR : PseudoInstARC<(outs), (ins GPR32:$dst, MEMrlimm:$addr),
133                             "STB_FAR $dst, $addr",
134                             [(truncstorei8 GPR32:$dst, AddrModeFar:$addr)]>;
135
136// TODO: Add `Requires<[HasBitScan]>` predicate to these when available.
137let Defs = [STATUS32] in {
138  def CTLZ : PseudoInstARC<(outs GPR32:$A),
139                           (ins GPR32:$B),
140                           "error.fls $A, $B",
141                           [(set GPR32:$A, (ctlz i32:$B))]>;
142
143  def CTTZ : PseudoInstARC<(outs GPR32:$A),
144                           (ins GPR32:$B),
145                           "error.ffs $A, $B",
146                           [(set GPR32:$A, (cttz i32:$B))]>;
147}
148
149//===----------------------------------------------------------------------===//
150// Instruction Generation multiclasses.
151// Generate many variants of a single instruction with a single defining
152// multiclass.  These classes do not contain Selection DAG patterns.
153//===----------------------------------------------------------------------===//
154
155// Generic 3 operand binary instructions (i.e., add r0, r1, r2).
156multiclass ArcBinaryInst<bits<5> major, bits<6> mincode,
157                       string opasm, bit Commutable> {
158  // 3 register variant.
159  def _rrr : F32_DOP_RR<major, mincode, 0, (outs GPR32:$A),
160                        (ins GPR32:$B, GPR32:$C),
161                        !strconcat(opasm, "\t$A, $B, $C"),
162                        []>
163  { let isCommutable = Commutable; }
164  def _f_rrr : F32_DOP_RR<major, mincode, 1, (outs GPR32:$A),
165                          (ins GPR32:$B, GPR32:$C),
166                          !strconcat(opasm, ".f\t$A, $B, $C"),
167                          []>
168  { let Defs = [STATUS32]; }
169
170  // 2 register with unsigned 6-bit immediate variant.
171  def _rru6 : F32_DOP_RU6<major, mincode, 0, (outs GPR32:$A),
172                          (ins GPR32:$B, immU6:$U6),
173                          !strconcat(opasm, "\t$A, $B, $U6"),
174                          []>;
175  def _f_rru6 : F32_DOP_RU6<major, mincode, 1, (outs GPR32:$A),
176                            (ins GPR32:$B, immU6:$U6),
177                            !strconcat(opasm, ".f\t$A, $B, $U6"),
178                            []>
179  { let Defs = [STATUS32]; }
180
181  def _cc_rru6 : F32_DOP_CC_RRU6<major, mincode, 0, (outs GPR32:$A),
182                                 (ins immU6:$U6, ccond:$cc, GPR32:$B),
183                                 !strconcat(opasm, ".$cc\t$A, $B, $U6"),
184                                 []> {
185                                   let Uses = [STATUS32];
186                                   let Constraints = "$A = $B";
187                                 }
188
189  def _cc_f_rru6 : F32_DOP_CC_RRU6<major, mincode, 1, (outs GPR32:$A),
190                                   (ins immU6:$U6, ccond:$cc, GPR32:$B),
191                                   !strconcat(opasm, ".$cc.f\t$A, $B, $U6"),
192                                   []> {
193                                     let Defs = [STATUS32];
194                                     let Uses = [STATUS32];
195                                     let Constraints = "$A = $B";
196                                   }
197
198  // 2 register with 32-bit immediate variant.
199  def _rrlimm : F32_DOP_RLIMM<major, mincode, 0,
200                              (outs GPR32:$A),
201                              (ins GPR32:$B, i32imm:$LImm),
202                              !strconcat(opasm, "\t$A, $B, $LImm"),
203                              []>;
204  def _f_rrlimm : F32_DOP_RLIMM<major, mincode, 1,
205                                (outs GPR32:$A),
206                                (ins GPR32:$B, i32imm:$LImm),
207                                !strconcat(opasm, ".f\t$A, $B, $LImm"),
208                                []>
209  { let Defs = [STATUS32]; }
210
211  // 2 matched-register with signed 12-bit immediate variant (add r0, r0, -1).
212  def _rrs12 : F32_DOP_RS12<major, mincode, 0,
213                            (outs GPR32:$B),
214                            (ins GPR32:$in, immS<12>:$S12),
215                            !strconcat(opasm, "\t$B, $in, $S12"),
216                            []>
217  { let Constraints = "$B = $in"; }
218  def _f_rrs12 : F32_DOP_RS12<major, mincode, 1,
219                              (outs GPR32:$B),
220                              (ins GPR32:$in, immS<12>:$S12),
221                              !strconcat(opasm, ".f\t$B, $in, $S12"),
222                              []>
223  { let Constraints = "$B = $in"; let Defs = [STATUS32]; }
224}
225
226// Special multivariant GEN4 DOP format instruction that take 2 registers.
227// This is the class that is used for various comparison instructions.
228multiclass ArcSpecialDOPInst<bits<6> subop, string opasm, bit F> {
229  def _rr : F32_DOP_RR<0b00100, subop, F, (outs), (ins GPR32:$B, GPR32:$C),
230               !strconcat(opasm, "\t$B, $C"),
231               []>;
232
233  def _ru6 : F32_DOP_RU6<0b00100, subop, F, (outs), (ins GPR32:$B, i32imm:$U6),
234               !strconcat(opasm, "\t$B, $U6"),
235               []>;
236
237  def _rlimm : F32_DOP_RLIMM<0b00100, subop, F, (outs),
238               (ins GPR32:$B, i32imm:$LImm),
239               !strconcat(opasm, "\t$B, $LImm"),
240               []>;
241}
242
243// Generic 2-operand unary instructions.
244multiclass ArcUnaryInst<bits<5> major, bits<6> subop,
245                        string opasm> {
246  def _rr : F32_SOP_RR<major, subop, 0, (outs GPR32:$B), (ins GPR32:$C),
247                       !strconcat(opasm, "\t$B, $C"), []>;
248
249  def _f_rr : F32_SOP_RR<major, subop, 1, (outs GPR32:$B), (ins GPR32:$C),
250                       !strconcat(opasm, ".f\t$B, $C"), []>
251  { let Defs = [STATUS32]; }
252}
253
254
255multiclass ArcBinaryGEN4Inst<bits<6> mincode, string opasm, bit Commutable = 0> :
256  ArcBinaryInst<0b00100, mincode, opasm, Commutable>;
257multiclass ArcBinaryEXT5Inst<bits<6> mincode, string opasm> :
258  ArcBinaryInst<0b00101, mincode, opasm, 0>;
259
260multiclass ArcUnaryGEN4Inst<bits<6> mincode, string opasm> :
261  ArcUnaryInst<0b00100, mincode, opasm>;
262multiclass ArcUnaryEXT5Inst<bits<6> mincode, string opasm> :
263  ArcUnaryInst<0b00101, mincode, opasm>;
264
265// Pattern generation for different instruction variants.
266multiclass MultiPat<SDPatternOperator InFrag,
267               Instruction RRR, Instruction RRU6, Instruction RRLImm> {
268  def _rrr : Pat<(InFrag i32:$B, i32:$C), (RRR i32:$B, i32:$C)>;
269  def _rru6 : Pat<(InFrag i32:$B, immU6:$U6), (RRU6 i32:$B, immU6:$U6)>;
270  def _rrlimm : Pat<(InFrag i32:$B, imm32:$LImm), (RRLImm i32:$B, imm32:$LImm)>;
271}
272
273// NOTE: This could be specialized later with a custom `PrintMethod` for
274//       displaying the aux register name. E.g. `[%count0]` instead of [33].
275def AuxReg : Operand<i32>;
276
277def LR_rs12 : F32_SOP_RS12<0b00100, 0b101010, 0,
278                           (outs GPR32:$B), (ins AuxReg:$C),
279                           "lr\t$B, [$C]", []>;
280def LR_ru6 : F32_SOP_RU6<0b00100, 0b101010, 0,
281                         (outs GPR32:$B), (ins AuxReg:$C),
282                         "lr\t$B, [$C]", []>;
283
284def: Pat<(i32 readcyclecounter), (LR_rs12 0x21) >;  // read timer
285
286// ---------------------------------------------------------------------------
287// Instruction definitions and patterns for 3 operand binary instructions.
288// ---------------------------------------------------------------------------
289
290// Definitions for 3 operand binary instructions.
291defm ADD : ArcBinaryGEN4Inst<0b000000, "add",1>;
292defm SUB : ArcBinaryGEN4Inst<0b000010, "sub">;
293defm SUB1 : ArcBinaryGEN4Inst<0b010111, "sub1">;
294defm SUB2 : ArcBinaryGEN4Inst<0b011000, "sub2">;
295defm SUB3 : ArcBinaryGEN4Inst<0b011001, "sub3">;
296defm RSUB : ArcBinaryGEN4Inst<0b001110, "rsub">;
297defm OR  : ArcBinaryGEN4Inst<0b000101, "or",1>;
298defm AND : ArcBinaryGEN4Inst<0b000100, "and",1>;
299defm XOR : ArcBinaryGEN4Inst<0b000111, "xor",1>;
300defm MAX : ArcBinaryGEN4Inst<0b001000, "max",1>;
301defm MIN : ArcBinaryGEN4Inst<0b001001, "min",1>;
302defm ASL : ArcBinaryEXT5Inst<0b000000, "asl">;
303defm LSR : ArcBinaryEXT5Inst<0b000001, "lsr">;
304defm ASR : ArcBinaryEXT5Inst<0b000010, "asr">;
305defm ROR : ArcBinaryEXT5Inst<0b000011, "ror">;
306defm MPY  : ArcBinaryGEN4Inst<0b011010, "mpy",1>;
307defm MPYM : ArcBinaryGEN4Inst<0b011011, "mpym",1>;
308defm MPYMU : ArcBinaryGEN4Inst<0b011100, "mpymu",1>;
309defm SETEQ : ArcBinaryGEN4Inst<0b111000, "seteq",1>;
310let Uses=[STATUS32], isAsCheapAsAMove=0, isReMaterializable=0 in {
311  defm ADC : ArcBinaryGEN4Inst<0b000001, "adc",1>;
312  defm SBC : ArcBinaryGEN4Inst<0b000011, "sbc">;
313}
314
315// Patterns for 3 operand binary instructions.
316defm : MultiPat<add, ADD_rrr, ADD_rru6, ADD_rrlimm>;
317defm : MultiPat<sub, SUB_rrr, SUB_rru6, SUB_rrlimm>;
318defm : MultiPat<or, OR_rrr, OR_rru6, OR_rrlimm>;
319defm : MultiPat<and, AND_rrr, AND_rru6, AND_rrlimm>;
320defm : MultiPat<xor, XOR_rrr, XOR_rru6, XOR_rrlimm>;
321defm : MultiPat<smax, MAX_rrr, MAX_rru6, MAX_rrlimm>;
322defm : MultiPat<smin, MIN_rrr, MIN_rru6, MIN_rrlimm>;
323defm : MultiPat<shl, ASL_rrr, ASL_rru6, ASL_rrlimm>;
324defm : MultiPat<srl, LSR_rrr, LSR_rru6, LSR_rrlimm>;
325defm : MultiPat<sra, ASR_rrr, ASR_rru6, ASR_rrlimm>;
326defm : MultiPat<rotr, ROR_rrr, ROR_rru6, ROR_rrlimm>;
327defm : MultiPat<mul, MPY_rrr, MPY_rru6, MPY_rrlimm>;
328defm : MultiPat<mulhs, MPYM_rrr, MPYM_rru6, MPYM_rrlimm>;
329defm : MultiPat<mulhu, MPYMU_rrr, MPYMU_rru6, MPYMU_rrlimm>;
330
331defm : MultiPat<addc, ADD_f_rrr, ADD_f_rru6, ADD_f_rrlimm>;
332defm : MultiPat<adde, ADC_f_rrr, ADC_f_rru6, ADC_f_rrlimm>;
333defm : MultiPat<subc, SUB_f_rrr, SUB_f_rru6, SUB_f_rrlimm>;
334defm : MultiPat<sube, SBC_f_rrr, SBC_f_rru6, SBC_f_rrlimm>;
335
336// ---------------------------------------------------------------------------
337// Unary Instruction definitions.
338// ---------------------------------------------------------------------------
339// General unary instruction definitions.
340defm SEXB : ArcUnaryGEN4Inst<0b000101, "sexb">;
341defm SEXH : ArcUnaryGEN4Inst<0b000110, "sexh">;
342
343// Extension unary instruction definitions.
344defm FFS : ArcUnaryEXT5Inst<0b010010, "ffs">;
345defm FLS : ArcUnaryEXT5Inst<0b010011, "fls">;
346
347let Predicates=[HasNorm] in {
348  defm NORM  : ArcUnaryEXT5Inst<0b000001,"norm">;
349  defm NORMH : ArcUnaryEXT5Inst<0b001000,"normh">;
350}
351
352// General Unary Instruction fragments.
353def : Pat<(sext_inreg i32:$a, i8), (SEXB_rr i32:$a)>;
354def : Pat<(sext_inreg i32:$a, i16), (SEXH_rr i32:$a)>;
355
356// Comparison instruction definition
357let isCompare = 1, Defs = [STATUS32] in {
358defm CMP : ArcSpecialDOPInst<0b001100, "cmp", 1>;
359}
360
361def cmp : PatFrag<(ops node:$op1, node:$op2), (ARCcmp $op1, $op2)>;
362defm : MultiPat<cmp, CMP_rr, CMP_ru6, CMP_rlimm>;
363
364// ---------------------------------------------------------------------------
365// MOV instruction and variants (conditional mov).
366// ---------------------------------------------------------------------------
367let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in {
368def MOV_rs12 : F32_DOP_RS12<0b00100, 0b001010, 0,
369                 (outs GPR32:$B), (ins immS<12>:$S12),
370                 "mov\t$B, $S12",
371                 [(set GPR32:$B, immS<12>:$S12)]>;
372}
373
374def MOV_rr : F32_DOP_RR<0b00100, 0b001010, 0,
375                (outs GPR32:$B), (ins GPR32:$C),
376                "mov\t$B, $C", []>;
377
378def MOV_rlimm : F32_DOP_RLIMM<0b00100, 0b001010, 0,
379                      (outs GPR32:$B), (ins i32imm:$LImm),
380                      "mov\t$B, $LImm", []>;
381
382def MOV_ru6 : F32_DOP_RU6<0b00100, 0b001010, 0,
383                          (outs GPR32:$B), (ins immU6:$U6),
384                          "mov\t$B, $U6", []>;
385
386def MOV_f_ru6 : F32_DOP_RU6<0b00100, 0b001010, 1,
387                          (outs GPR32:$B), (ins u6:$U6),
388                          "mov.f\t$B, $U6", []> {
389  let isAsCheapAsAMove=1;
390  let Defs = [STATUS32];
391}
392
393def cmov : PatFrag<(ops node:$op1, node:$op2, node:$cc),
394                   (ARCcmov $op1, $op2, $cc)>;
395let Uses = [STATUS32], isAsCheapAsAMove = 1, isPredicable=1,
396	  isReMaterializable = 0, Constraints = "$B = $B2" in {
397  def MOV_cc : F32_DOP_CC_RR<0b00100, 0b001010, 0,
398                 (outs GPR32:$B), (ins GPR32:$C, GPR32:$B2, cmovpred:$cc),
399                 "mov.$cc\t$B, $C",
400                 [(set GPR32:$B, (cmov i32:$C, i32:$B2, cmovpred:$cc))]>;
401
402  def MOV_cc_ru6 : F32_DOP_CC_RU6<0b00100, 0b001010, 0,
403                 (outs GPR32:$B), (ins u6:$C, CCOp:$cc, GPR32:$B2),
404                 "mov.$cc\t$B, $C", []>;
405
406  def MOV_cc_f_ru6 : F32_DOP_CC_RU6<0b00100, 0b001010, 1,
407                    (outs GPR32:$B), (ins u6:$C, CCOp:$cc, GPR32:$B2),
408                    "mov.$cc.f\t$B, $C", []> {
409    let Defs = [STATUS32];
410  }
411}
412
413def : Pat<(ARCGAWrapper tglobaladdr:$addr),
414           (MOV_rlimm tglobaladdr:$addr)>;
415
416def : Pat<(ARCGAWrapper tjumptable:$addr),
417           (MOV_rlimm tjumptable:$addr)>;
418
419
420// ---------------------------------------------------------------------------
421// Control flow instructions (branch, return, calls, etc).
422// ---------------------------------------------------------------------------
423
424// Branch instructions
425let isBranch = 1, isTerminator = 1 in {
426
427  // Unconditional branch.
428  let isBarrier = 1 in
429  def BR : F32_BR0_UCOND_FAR<(outs), (ins btargetS25:$S25),
430                             "b\t$S25", [(br bb:$S25)]>;
431
432  let Uses=[STATUS32] in
433  // Conditional branch.
434  def Bcc : F32_BR0_COND<(outs), (ins btargetS21:$S21, ccond:$cc),
435                         "b$cc\t$S21", []>;
436
437  // Compare and branch (limited range).
438  def BRcc_rr  : F32_BR1_BCC<(outs),
439                             (ins btargetS9:$S9, GPR32:$B, GPR32:$C, brccond:$cc),
440                             "br$cc\t$B, $C, $S9", 0, []>;
441  def BRcc_ru6 : F32_BR1_BCC<(outs),
442                             (ins btargetS9:$S9, GPR32:$B, immU6:$C, brccond:$cc),
443                             "br$cc\t$B, $C, $S9", 1, []>;
444
445  // Pseudo compare and branch.
446  // After register allocation, this can expand into either a limited range
447  // Compare and branch (BRcc), or into CMP + Bcc.
448  // At worst, this expands into 2 4-byte instructions.
449  def BRcc_rr_p : PseudoInstARC<(outs),
450                                (ins btarget:$T, GPR32:$B, GPR32:$C, ccond:$cc),
451                                "pbr$cc\t$B, $C, $T",
452                                [(ARCbrcc bb:$T, i32:$B, i32:$C, imm32:$cc)]>
453                                { let Size = 8; }
454
455  def BRcc_ru6_p : PseudoInstARC<(outs),
456                                 (ins btarget:$T, GPR32:$B, i32imm:$C, ccond:$cc),
457                                 "pbr$cc\t$B, $C, $T",
458                                 [(ARCbrcc bb:$T, i32:$B, immU6:$C, imm32:$cc)]>
459                                 { let Size = 8; }
460} // let isBranch, isTerminator
461
462// Unconditional Jump.
463let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
464  // Indirect.
465  let isIndirectBranch = 1 in
466  def J :  F32_DOP_RR<0b00100, 0b100000, 0,
467                      (outs), (ins GPR32:$C),
468                      "j\t[$C]", [(brind i32:$C)]>;
469
470  // Direct.
471  def J_LImm : F32_DOP_RLIMM<0b00100, 0b100000, 0,
472                             (outs), (ins i32imm:$LImm),
473                             "j\t$LImm", []>;
474}
475
476// Call instructions.
477let isCall = 1, isBarrier = 1, Defs = [BLINK], Uses = [SP] in {
478  // Direct unconditional call.
479  def BL : F32_BR1_BL_UCOND_FAR<(outs), (ins calltargetS25:$S25),
480                      "bl\t$S25", [(ARCBranchLink tglobaladdr:$S25)]>;
481
482  // Indirect unconditional call.
483  let isIndirectBranch = 1 in
484  def JL : F32_DOP_RR<0b00100, 0b100010, 0, (outs), (ins GPR32:$C),
485                     "jl\t[$C]", [(ARCJumpLink i32:$C)]>;
486
487  // Direct unconditional call.
488  def JL_LImm : F32_DOP_RLIMM<0b00100, 0b100010, 0, (outs), (ins i32imm:$LImm),
489                              "jl\t$LImm", []>;
490} // let isCall, isBarrier, Defs, Uses
491
492// Pattern to generate BL instruction.
493def : Pat<(ARCBranchLink texternalsym:$dst), (BL texternalsym:$dst)>;
494
495// Return from call.
496let isReturn = 1, isTerminator = 1, isBarrier = 1  in
497// This is a specialized 2-byte instruction that doesn't generalize
498// to any larger 2-byte class, so go ahead and define it here.
499def J_S_BLINK : InstARC<2, (outs), (ins), "j_s\t[%blink]", [(ret)]> {
500  let Inst{15-0} = 0b0111111011100000;
501}
502
503//----------------------------------------------------------------------------
504// Compact stack-based operations.
505//----------------------------------------------------------------------------
506
507// 2-byte push/pop blink instructions commonly used for prolog/epilog
508// generation.  These 2 instructions are actually specialized 2-byte
509// format instructions that aren't generalized to a larger 2-byte
510// class, so we might as well have them here.
511let Uses = [BLINK], Defs = [SP] in
512def PUSH_S_BLINK : F16_SP_OPS_buconst<0b111, "push_s">;
513
514let Defs = [BLINK, SP] in
515def POP_S_BLINK : F16_SP_OPS_buconst<0b110, "pop_s">;
516
517def PUSH_S_r : F16_SP_OPS_uconst<0b110,
518  (outs), (ins GPR32Reduced:$b3), "push_s">;
519def POP_S_r : F16_SP_OPS_uconst<0b111,
520  (outs GPR32Reduced:$b3), (ins), "pop_s">;
521
522def SP_SUB_SP_S : F16_SP_OPS_bconst<0b001, "sub_s">;
523def SP_ADD_SP_S : F16_SP_OPS_bconst<0b000, "add_s">;
524def SP_ADD_S : F16_SP_OPS_u7_aligned<0b100,
525                (outs GPR32Reduced:$b3), (ins immU<7>:$u7),
526                "add_s\t$b3, %sp, $u7">;
527
528def SP_LD_S : F16_SP_LD<0b000, "ld_s">;
529def SP_LDB_S : F16_SP_LD<0b001, "ldb_s">;
530def SP_ST_S : F16_SP_ST<0b010, "st_s">;
531def SP_STB_S : F16_SP_ST<0b011, "stb_s">;
532
533def LEAVE_S : F16_SP_OPS<0b110,
534  (outs), (ins immU<7>:$u7), "leave_s\t$u7"> {
535
536  bits<7> u7;
537
538  let fieldB = u7{6-4};
539  let fieldU{4-1} = u7{3-0};
540  let fieldU{0} = 0b0;
541}
542
543def ENTER_S : F16_SP_OPS<0b111,
544  (outs), (ins immU<6>:$u6), "enter_s\t$u6"> {
545
546  bits<6> u6;
547
548  let fieldB{2} = 0;
549  let fieldB{1-0} = u6{5-4};
550  let fieldU{4-1} = u6{3-0};
551  let fieldU{0} = 0b0;
552}
553
554//----------------------------------------------------------------------------
555// Compact Move/Load instructions.
556//----------------------------------------------------------------------------
557class COMPACT_MOV_S :
558  F16_COMPACT<0b0, (outs GPR32:$g), (ins GPR32:$h),
559          "mov_s\t$g, $h"> {
560  let DecoderMethod = "DecodeMoveHRegInstruction";
561}
562
563def COMPACT_MOV_S_limm : COMPACT_MOV_S {
564  bits<32> LImm;
565  let Inst{47-16} = LImm;
566
567  bits<5> LImmReg = 0b11110;
568  let Inst{7-5} = LImmReg{2-0};
569  let Inst{1-0} = LImmReg{4-3};
570
571  let Size = 6;
572}
573
574def COMPACT_MOV_S_hreg : COMPACT_MOV_S;
575
576def COMPACT_LD_S :
577  F16_COMPACT<0b1, (outs GPR32:$r), (ins GPR32:$h, immU<5>:$u5),
578          "ld_s\t$r, [$h, $u5]"> {
579  bits<5> u5;
580  bits<2> r;
581
582  let Inst{10} = u5{4};
583  let Inst{9-8} = r;
584  let Inst{4-3} = u5{3-2};
585  let u5{1-0} = 0b00;
586}
587
588//----------------------------------------------------------------------------
589// Compact Load/Add/Sub.
590//----------------------------------------------------------------------------
591def LD_S_AS_rrr : F16_LD_SUB<0b0, "ld_s.as\t$a, [$b, $c]">;
592def SUB_S_rrr : F16_LD_SUB<0b1, "sub_s\t$a, $b, $c">;
593def ADD_S_rru6 : F16_ADD;
594
595//----------------------------------------------------------------------------
596// Compact Load/Store.
597//----------------------------------------------------------------------------
598def LD_S_s11 : F16_LD_ST_s11<0b0, "ld_s\t%r1, [%gp, $s11]">;
599def ST_S_s11 : F16_LD_ST_s11<0b1, "st_s\t%r0, [%gp, $s11]">;
600def LDI_S_u7 : F16_LDI_u7;
601
602//----------------------------------------------------------------------------
603// Indexed Jump or Execute.
604//----------------------------------------------------------------------------
605def JLI_S : F16_JLI_EI<0, "jli_s">;
606def EI_S : F16_JLI_EI<1, "ei_s">;
607
608//----------------------------------------------------------------------------
609// Load/Add Register-Register.
610//----------------------------------------------------------------------------
611def LD_S_rrr : F16_LD_ADD_RR<0b00, "ld_s\t$a, [$b, $c]">;
612def LDB_S_rrr : F16_LD_ADD_RR<0b01, "ldb_s\t$a, [$b, $c]">;
613def LDH_S_rrr : F16_LD_ADD_RR<0b10, "ldh_s\t$a, [$b, $c]">;
614def ADD_S_rrr : F16_LD_ADD_RR<0b11, "add_s\t$a, $b, $c">;
615
616//----------------------------------------------------------------------------
617// Load/Add GP-Relative.
618//----------------------------------------------------------------------------
619def GP_LD_S : F16_GP_LD_ADD<0b00, (ins immS<11>:$s),
620  "ld_s\t%r0, [%gp, $s]"> {
621
622  bits<11> s;
623  let Inst{8-0} = s{10-2};
624  let s{1-0} = 0b00;
625}
626
627def GP_LDB_S : F16_GP_LD_ADD<0b01, (ins immS<9>:$s),
628  "ldb_s\t%r0, [%gp, $s]"> {
629
630  bits<9> s;
631  let Inst{8-0} = s{8-0};
632}
633
634def GP_LDH_S : F16_GP_LD_ADD<0b10, (ins immS<10>:$s),
635  "ldh_s\t%r0, [%gp, $s]"> {
636
637  bits<10> s;
638  let Inst{8-0} = s{9-1};
639  let s{0} = 0b0;
640}
641
642def GP_ADD_S : F16_GP_LD_ADD<0b11, (ins immS<11>:$s),
643  "add_s\t%r0, %gp, $s"> {
644
645  bits<11> s;
646  let Inst{8-0} = s{10-2};
647  let s{1-0} = 0b00;
648}
649
650//----------------------------------------------------------------------------
651// Load PCL-Relative.
652//----------------------------------------------------------------------------
653def PCL_LD : InstARC<2, (outs GPR32:$b), (ins immU<10>:$u10),
654 "ld_s\t$b, [%pcl, $u10]", []> {
655
656  bits<3> b;
657  bits<10> u10;
658
659  let Inst{15-11} = 0b11010;
660  let Inst{10-8} = b;
661  let Inst{7-0} = u10{9-2};
662  let u10{1-0} = 0b00;
663}
664
665let isBranch = 1 in {
666  //----------------------------------------------------------------------------
667  // Branch on Compare Register with Zero.
668  //----------------------------------------------------------------------------
669  def BREQ_S : F16_BCC_REG<0b0, "breq_s">;
670  def BRNE_S : F16_BCC_REG<0b1, "brne_s">;
671
672  //----------------------------------------------------------------------------
673  // Branch Conditionally.
674  //----------------------------------------------------------------------------
675  let isBarrier = 1 in
676  def B_S : F16_BCC_s10<0b00, "b_s">;
677
678  def BEQ_S : F16_BCC_s10<0b01, "beq_s">;
679  def BNE_S : F16_BCC_s10<0b10, "bne_s">;
680  def BGT_S : F16_BCC_s7<0b000, "bgt_s">;
681  def BGE_S : F16_BCC_s7<0b001, "bge_s">;
682  def BLT_S : F16_BCC_s7<0b010, "blt_s">;
683  def BLE_S : F16_BCC_s7<0b011, "ble_s">;
684  def BHI_S : F16_BCC_s7<0b100, "bhi_s">;
685  def BHS_S : F16_BCC_s7<0b101, "bhs_s">;
686  def BLO_S : F16_BCC_s7<0b110, "blo_s">;
687  def BLS_S : F16_BCC_s7<0b111, "bls_s">;
688} // let isBranch
689
690def BL_S :
691  InstARC<2, (outs), (ins btargetS13:$s13), "bl_s\t$s13", []> {
692
693  let Inst{15-11} = 0b11111;
694
695  bits<13> s13;
696  let Inst{10-0} = s13{12-2};
697  let s13{1-0} = 0b00;
698
699  let isCall = 1;
700  let isBarrier = 1;
701}
702
703//----------------------------------------------------------------------------
704// Add/Sub/Shift Register-Immediate.
705//----------------------------------------------------------------------------
706def ADD_S_ru3 : F16_ADD_IMM<0b00,"add_s">;
707def SUB_S_ru3 : F16_ADD_IMM<0b01,"sub_s">;
708def ASL_S_ru3 : F16_ADD_IMM<0b10,"asl_s">;
709def ASR_S_ru3 : F16_ADD_IMM<0b11,"asr_s">;
710
711//----------------------------------------------------------------------------
712// Shift/Subtract/Bit Immediate.
713//----------------------------------------------------------------------------
714def ASL_S_ru5 : F16_SH_SUB_BIT_DST<0b000,"asl_s">;
715def LSR_S_ru5 : F16_SH_SUB_BIT_DST<0b001,"lsr_s">;
716def ASR_S_ru5 : F16_SH_SUB_BIT_DST<0b010,"asr_s">;
717def SUB_S_ru5 : F16_SH_SUB_BIT_DST<0b011,"sub_s">;
718def BSET_S_ru5 : F16_SH_SUB_BIT_DST<0b100,"bset_s">;
719def BCLR_S_ru5 : F16_SH_SUB_BIT_DST<0b101,"bclr_s">;
720def BMSK_S_ru5 : F16_SH_SUB_BIT_DST<0b110,"bmsk_s">;
721def BTST_S_ru5 : F16_SH_SUB_BIT<0b111, "btst_s\t$b, $u5">;
722
723//----------------------------------------------------------------------------
724// Dual Register Operations.
725//----------------------------------------------------------------------------
726def ADD_S_rlimm :
727  F16_OP_HREG_LIMM<0b000, (outs GPR32:$b_s3), (ins i32imm:$LImm),
728          !strconcat("add_s", "\t$b_s3, $b_s3, $LImm")>;
729
730def ADD_S_rr :
731  F16_OP_HREG<0b000, (outs GPR32:$b_s3), (ins GPR32:$h),
732          !strconcat("add_s", "\t$b_s3, $b_s3, $h")>;
733
734def ADD_S_rs3 :
735  F16_OP_HREG<0b001, (outs GPR32:$h), (ins immC<3>:$b_s3),
736          !strconcat("add_s", "\t$h, $h, $b_s3")>;
737
738def ADD_S_limms3 :
739  F16_OP_HREG_LIMM<0b001, (outs), (ins immC<3>:$b_s3, i32imm:$LImm),
740          !strconcat("add_s", "\t0, $LImm, $b_s3")>;
741
742def MOV_S_NE_rlimm :
743  F16_OP_HREG_LIMM<0b111, (outs GPR32:$b_s3), (ins i32imm:$LImm),
744          !strconcat("mov_s.ne", "\t$b_s3, $LImm")>;
745
746def MOV_S_NE_rr :
747  F16_OP_HREG<0b111,(outs GPR32:$b_s3), (ins GPR32:$h),
748          !strconcat("mov_s.ne", "\t$b_s3, $h")>;
749
750def MOV_S_rs3 :
751  F16_OP_HREG<0b011, (outs GPR32:$h), (ins immC<3>:$b_s3),
752          !strconcat("mov_s", "\t$h, $b_s3")>;
753
754def MOV_S_s3 :
755  F16_OP_HREG30<0b011, (outs), (ins immC<3>:$b_s3),
756          !strconcat("mov_s", "\t0, $b_s3")>;
757
758def CMP_S_rlimm :
759  F16_OP_HREG_LIMM<0b100, (outs GPR32:$b_s3), (ins i32imm:$LImm),
760          !strconcat("cmp_s", "\t$b_s3, $LImm")>;
761
762def CMP_S_rr :
763  F16_OP_HREG<0b100, (outs GPR32:$b_s3), (ins GPR32:$h),
764          !strconcat("cmp_s", "\t$b_s3, $h")>;
765
766def CMP_S_rs3 :
767  F16_OP_HREG<0b101, (outs GPR32:$h), (ins immC<3>:$b_s3),
768          !strconcat("cmp_s", "\t$h, $b_s3")>;
769
770def CMP_S_limms3 :
771  F16_OP_HREG_LIMM<0b101, (outs), (ins immC<3>:$b_s3, i32imm:$LImm),
772          !strconcat("cmp_s", "\t$LImm, $b_s3")>;
773
774//----------------------------------------------------------------------------
775// Compact MOV/ADD/CMP Immediate instructions.
776//----------------------------------------------------------------------------
777def MOV_S_u8 :
778  F16_OP_IMM<0b11011, (outs GPR32:$b), (ins immU<8>:$u8),
779          !strconcat("mov_s", "\t$b, $u8")> {
780  bits<8> u8;
781  let Inst{7-0} = u8;
782}
783
784def ADD_S_u7 :
785  F16_OP_U7<0b0, !strconcat("add_s", "\t$b, $b, $u7")>;
786
787def CMP_S_u7 :
788  F16_OP_U7<0b1, !strconcat("cmp_s", "\t$b, $u7")>;
789
790//----------------------------------------------------------------------------
791// Compact Load/Store instructions with offset.
792//----------------------------------------------------------------------------
793def LD_S_OFF :
794  F16_LD_ST_WORD_OFF<0x10, (outs GPR32:$c), (ins GPR32:$b, immU<7>:$off),
795  "ld_s">;
796
797def LDB_S_OFF :
798  F16_LD_ST_BYTE_OFF<0x11, (outs GPR32:$c), (ins GPR32:$b, immU<5>:$off),
799  "ldb_s">;
800
801class F16_LDH_OFF<bits<5> opc, string asmstr> :
802  F16_LD_ST_HALF_OFF<opc, (outs GPR32:$c), (ins GPR32:$b, immU<6>:$off),
803  asmstr>;
804
805def LDH_S_OFF : F16_LDH_OFF<0x12, "ldh_s">;
806def LDH_S_X_OFF : F16_LDH_OFF<0x13, "ldh_s.x">;
807
808def ST_S_OFF :
809  F16_LD_ST_WORD_OFF<0x14, (outs), (ins GPR32:$c, GPR32:$b, immU<7>:$off),
810  "st_s">;
811
812def STB_S_OFF :
813  F16_LD_ST_BYTE_OFF<0x15, (outs), (ins GPR32:$c, GPR32:$b, immU<5>:$off),
814  "stb_s">;
815
816def STH_S_OFF :
817  F16_LD_ST_HALF_OFF<0x16, (outs), (ins GPR32:$c, GPR32:$b, immU<6>:$off),
818  "sth_s">;
819
820//----------------------------------------------------------------------------
821// General compact instructions.
822//----------------------------------------------------------------------------
823def GEN_SUB_S : F16_GEN_DOP<0x02, "sub_s">;
824def GEN_AND_S : F16_GEN_DOP<0x04, "and_s">;
825def GEN_OR_S : F16_GEN_DOP<0x05, "or_s">;
826def GEN_BIC_S : F16_GEN_DOP<0x06, "bic_s">;
827def GEN_XOR_S : F16_GEN_DOP<0x07, "xor_s">;
828def GEN_MPYW_S : F16_GEN_DOP<0x09, "mpyw_s">;
829def GEN_MPYUW_S : F16_GEN_DOP<0x0a, "mpyuw_s">;
830def GEN_TST_S : F16_GEN_DOP_NODST<0x0b, "tst_s">;
831def GEN_MPY_S : F16_GEN_DOP<0x0c, "mpy_s">;
832def GEN_SEXB_S : F16_GEN_DOP_SINGLESRC<0x0d, "sexb_s">;
833def GEN_SEXH_S : F16_GEN_DOP_SINGLESRC<0x0e, "sexh_s">;
834def GEN_EXTB_S : F16_GEN_DOP_SINGLESRC<0x0f, "extb_s">;
835def GEN_EXTH_S : F16_GEN_DOP_SINGLESRC<0x10, "exth_s">;
836def GEN_ABS_S : F16_GEN_DOP_SINGLESRC<0x11, "abs_s">;
837def GEN_NOT_S : F16_GEN_DOP_SINGLESRC<0x12, "not_s">;
838def GEN_NEG_S : F16_GEN_DOP_SINGLESRC<0x13, "neg_s">;
839def GEN_ADD1_S : F16_GEN_DOP<0x14, "add1_s">;
840def GEN_ADD2_S : F16_GEN_DOP<0x15, "add2_s">;
841def GEN_ADD3_S : F16_GEN_DOP<0x16, "add3_s">;
842def GEN_ASL_S : F16_GEN_DOP<0x18, "asl_s">;
843def GEN_LSR_S : F16_GEN_DOP<0x19, "lsr_s">;
844def GEN_ASR_S : F16_GEN_DOP<0x1a, "asr_s">;
845def GEN_AS1L_S : F16_GEN_DOP_SINGLESRC<0x1b, "asl_s">;
846def GEN_AS1R_S : F16_GEN_DOP_SINGLESRC<0x1c, "asr_s">;
847def GEN_LS1R_S : F16_GEN_DOP_SINGLESRC<0x1d, "lsr_s">;
848def GEN_TRAP_S : F16_GEN_DOP_BASE<0x1e, (outs), (ins immU6:$u6),
849  "trap_s\t$u6"> {
850
851  bits<6> u6;
852  let b = u6{5-3};
853  let c = u6{2-0};
854}
855
856def GEN_BRK_S : F16_GEN_DOP_BASE<0x1f, (outs), (ins),
857  "brk_s"> {
858
859  let b = 0b111;
860  let c = 0b111;
861}
862
863let isBarrier = 1 in {
864  let isBranch = 1 in {
865    def GEN_J_S : F16_GEN_SOP<0x0, "j_s\t[$b]">;
866    def GEN_J_S_D : F16_GEN_SOP<0x1, "j_s.d\t[$b]">;
867  } // let isBranch
868
869  let isCall = 1 in {
870    def GEN_JL_S : F16_GEN_SOP<0x2, "jl_s\t[$b]">;
871    def GEN_JL_S_D : F16_GEN_SOP<0x3, "jl_s.d\t[$b]">;
872  } // let isCall
873} // let isBarrier
874
875def GEN_SUB_S_NE : F16_GEN_SOP<0x6, "sub_s.ne\t$b, $b, $b">;
876
877def GEN_NOP_S : F16_GEN_ZOP<0x0, "nop_s">;
878def GEN_UNIMP_S : F16_GEN_ZOP<0x1, "unimp_s">;
879def GEN_SWI_S : F16_GEN_ZOP<0x2, "swi_s">;
880
881let isReturn = 1, isTerminator = 1 in {
882  def GEN_JEQ_S : F16_GEN_ZOP<0x4, "jeq_s\t[%blink]">;
883  def GEN_JNE_S : F16_GEN_ZOP<0x5, "jne_s\t[%blink]">;
884  let isBarrier = 1 in {
885    //def GEN_J_S_BLINK : F16_GEN_ZOP<0x6, "j_s\t[%blink]">;
886    def GEN_J_S_D_BLINK : F16_GEN_ZOP<0x7, "j_s.d\t[%blink]">;
887  } // let isBarrier
888} // let isReturn, isTerminator
889
890//----------------------------------------------------------------------------
891// Load/Store instructions.
892//----------------------------------------------------------------------------
893
894// Filter  class for load/store mappings
895class ArcLdStRel;
896
897// Load instruction variants:
898// Control bits: x, aa, di, zz
899// x - sign extend.
900// aa - incrementing mode. (N/A for LIMM).
901// di - uncached.
902// zz - data size.
903multiclass ArcLdInst<DataSizeMode zz, ExtMode x, CacheMode di, string asmop> {
904  let mayLoad = 1, ZZ = zz, X = x, DI = di in {
905    def _rs9: F32_LD_ADDR<x.Value, NoAM.Value, di.Value, zz.Value,
906			   (outs GPR32:$A), (ins MEMrs9:$addr),
907			   !strconcat(asmop, "\t$A, [$addr]"), []>, ArcLdStRel;
908
909    def _limm: F32_LD_LIMM<x.Value, di.Value, zz.Value,
910			   (outs GPR32:$A), (ins MEMii:$addr),
911			   !strconcat(asmop, "\t$A, [$addr]"), []>, ArcLdStRel;
912
913    def _rlimm: F32_LD_RLIMM<x.Value, NoAM.Value, di.Value, zz.Value,
914			     (outs GPR32:$A), (ins MEMrlimm:$addr),
915			     !strconcat(asmop, "\t$A, [$addr]"), []>, ArcLdStRel;
916
917    foreach aa = [PreIncAM, PostIncAM] in {
918      def aa.InstSuffix#_rs9: F32_LD_RS9<x.Value, aa.Value, di.Value, zz.Value,
919					  (outs GPR32:$A, GPR32:$addrout),
920					  (ins GPR32:$B, immS<9>:$S9),
921					  asmop#aa.AsmSuffix#"\t$A, [$B,$S9]", []>, ArcLdStRel
922			       { let Constraints = "$addrout = $B"; let AA = aa; }
923    }
924  }
925}
926
927foreach di = [NoCC, UncachedCC] in {
928  defm LD#di.InstSuffix : ArcLdInst<WordSM, NoEM, di, "ld"#di.AsmSuffix>;
929  foreach zz = [ByteSM, HalfSM] in {
930    foreach x = [NoEM, SignedEM] in {
931      defm LD#zz.InstSuffix#x.InstSuffix#di.InstSuffix : ArcLdInst<zz, x, di, "ld"#zz.AsmSuffix#x.AsmSuffix#di.AsmSuffix>;
932    }
933  }
934}
935
936// Load instruction patterns.
937// 32-bit loads.
938def : Pat<(load AddrModeS9:$addr), (LD_rs9 AddrModeS9:$addr)>;
939def : Pat<(load AddrModeImm:$addr), (LD_limm AddrModeImm:$addr)>;
940def : Pat<(load AddrModeFar:$addr), (LD_rs9 AddrModeFar:$addr)>;
941
942// 16-bit loads
943def : Pat<(zextloadi16 AddrModeS9:$addr), (LDH_rs9 AddrModeS9:$addr)>;
944def : Pat<(extloadi16 AddrModeS9:$addr), (LDH_rs9 AddrModeS9:$addr)>;
945def : Pat<(zextloadi16 AddrModeImm:$addr), (LDH_limm AddrModeImm:$addr)>;
946def : Pat<(extloadi16 AddrModeImm:$addr), (LDH_limm AddrModeImm:$addr)>;
947def : Pat<(zextloadi16 AddrModeFar:$addr), (LDH_rlimm AddrModeFar:$addr)>;
948def : Pat<(extloadi16 AddrModeFar:$addr), (LDH_rlimm AddrModeFar:$addr)>;
949def : Pat<(sextloadi16 AddrModeImm:$addr),(LDH_X_limm AddrModeImm:$addr)>;
950def : Pat<(sextloadi16 AddrModeFar:$addr),(LDH_X_rlimm AddrModeFar:$addr)>;
951def : Pat<(sextloadi16 AddrModeS9:$addr),(LDH_X_rs9 AddrModeS9:$addr)>;
952
953// 8-bit loads.
954def : Pat<(zextloadi8 AddrModeS9:$addr), (LDB_rs9 AddrModeS9:$addr)>;
955def : Pat<(extloadi8 AddrModeS9:$addr), (LDB_rs9 AddrModeS9:$addr)>;
956def : Pat<(zextloadi8 AddrModeImm:$addr), (LDB_limm AddrModeImm:$addr)>;
957def : Pat<(extloadi8 AddrModeImm:$addr), (LDB_limm AddrModeImm:$addr)>;
958def : Pat<(zextloadi8 AddrModeFar:$addr), (LDB_rlimm AddrModeFar:$addr)>;
959def : Pat<(extloadi8 AddrModeFar:$addr), (LDB_rlimm AddrModeFar:$addr)>;
960def : Pat<(zextloadi1 AddrModeS9:$addr), (LDB_rs9 AddrModeS9:$addr)>;
961def : Pat<(extloadi1 AddrModeS9:$addr), (LDB_rs9 AddrModeS9:$addr)>;
962def : Pat<(zextloadi1 AddrModeImm:$addr), (LDB_limm AddrModeImm:$addr)>;
963def : Pat<(extloadi1 AddrModeImm:$addr), (LDB_limm AddrModeImm:$addr)>;
964def : Pat<(zextloadi1 AddrModeFar:$addr), (LDB_rlimm AddrModeFar:$addr)>;
965def : Pat<(extloadi1 AddrModeFar:$addr), (LDB_rlimm AddrModeFar:$addr)>;
966def : Pat<(sextloadi8 AddrModeImm:$addr),(LDB_X_limm AddrModeImm:$addr)>;
967def : Pat<(sextloadi8 AddrModeFar:$addr),(LDB_X_rlimm AddrModeFar:$addr)>;
968def : Pat<(sextloadi8 AddrModeS9:$addr),(LDB_X_rs9 AddrModeS9:$addr)>;
969
970
971// Store instruction variants:
972// Control bits: aa, di, zz
973// aa - incrementing mode. (N/A for LIMM).
974// di - uncached.
975// zz - data size.
976multiclass ArcStInst<DataSizeMode zz, CacheMode di, string asmop> {
977  let mayStore = 1, ZZ = zz, DI = di in {
978    def _rs9: F32_ST_ADDR<NoAM.Value, di.Value, zz.Value,
979			   (outs), (ins GPR32:$C, MEMrs9:$addr),
980			   !strconcat(asmop, "\t$C, [$addr]"), []>, ArcLdStRel;
981
982    def _limm: F32_ST_LIMM<di.Value, zz.Value,
983			   (outs), (ins GPR32:$C, MEMii:$addr),
984			   !strconcat(asmop, "\t$C, [$addr]"), []>, ArcLdStRel;
985
986
987    foreach aa = [PreIncAM, PostIncAM] in {
988      def aa.InstSuffix#_rs9: F32_ST_RS9<aa.Value, di.Value, zz.Value,
989					  (outs GPR32:$addrout),
990					  (ins GPR32:$C, GPR32:$B, immS<9>:$S9),
991					  asmop#aa.AsmSuffix#"\t$C, [$B,$S9]", []>, ArcLdStRel
992			       { let Constraints = "$addrout = $B"; let AA = aa; }
993    }
994  }
995}
996
997foreach di = [NoCC, UncachedCC] in {
998  foreach zz = [ByteSM, HalfSM, WordSM] in {
999      defm ST#zz.InstSuffix#di.InstSuffix : ArcStInst<zz, di, "st"#zz.AsmSuffix#di.AsmSuffix>;
1000  }
1001}
1002
1003// Store instruction patterns.
1004// 32-bit stores
1005def : Pat<(store i32:$C, AddrModeS9:$addr),
1006          (ST_rs9 i32:$C, AddrModeS9:$addr)>;
1007def : Pat<(store i32:$C, AddrModeImm:$addr),
1008          (ST_limm i32:$C, AddrModeImm:$addr)>;
1009
1010// 16-bit stores
1011def : Pat<(truncstorei16 i32:$C, AddrModeS9:$addr),
1012          (STH_rs9 i32:$C, AddrModeS9:$addr)>;
1013def : Pat<(truncstorei16 i32:$C, AddrModeImm:$addr),
1014          (STH_limm i32:$C, AddrModeImm:$addr)>;
1015
1016// 8-bit stores
1017def : Pat<(truncstorei8 i32:$C, AddrModeS9:$addr),
1018          (STB_rs9 i32:$C, AddrModeS9:$addr)>;
1019def : Pat<(truncstorei8 i32:$C, AddrModeImm:$addr),
1020          (STB_limm i32:$C, AddrModeImm:$addr)>;
1021
1022def getPostIncOpcode : InstrMapping {
1023  let FilterClass = "ArcLdStRel";
1024  let RowFields = [ "BaseOpcode", "ZZ", "DI", "X"];
1025  let ColFields = [ "AA" ];
1026  let KeyCol = [ "NoAM" ];
1027  let ValueCols = [["PostIncAM"]];
1028}
1029