Move immediate constant predicate templates from the Blackfin target to MathExtras.h
[oota-llvm.git] / lib / Target / Blackfin / BlackfinInstrInfo.td
1 //===- BlackfinInstrInfo.td - Target Description for Blackfin Target ------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file describes the Blackfin instructions in TableGen format.
11 //
12 //===----------------------------------------------------------------------===//
13
14 //===----------------------------------------------------------------------===//
15 // Instruction format superclass
16 //===----------------------------------------------------------------------===//
17
18 include "BlackfinInstrFormats.td"
19
20 // These are target-independent nodes, but have target-specific formats.
21 def SDT_BfinCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>;
22 def SDT_BfinCallSeqEnd   : SDCallSeqEnd<[ SDTCisVT<0, i32>,
23                                         SDTCisVT<1, i32> ]>;
24
25 def BfinCallseqStart : SDNode<"ISD::CALLSEQ_START", SDT_BfinCallSeqStart,
26                               [SDNPHasChain, SDNPOutFlag]>;
27 def BfinCallseqEnd   : SDNode<"ISD::CALLSEQ_END",   SDT_BfinCallSeqEnd,
28                               [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
29
30 def SDT_BfinCall  : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
31 def BfinCall      : SDNode<"BFISD::CALL", SDT_BfinCall,
32                            [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
33
34 def BfinRet: SDNode<"BFISD::RET_FLAG", SDTNone,
35                     [SDNPHasChain, SDNPOptInFlag]>;
36
37 def BfinWrapper: SDNode<"BFISD::Wrapper", SDTIntUnaryOp>;
38
39 //===----------------------------------------------------------------------===//
40 // Transformations
41 //===----------------------------------------------------------------------===//
42
43 def trailingZeros_xform : SDNodeXForm<imm, [{
44   return CurDAG->getTargetConstant(N->getAPIntValue().countTrailingZeros(),
45                                    MVT::i32);
46 }]>;
47
48 def trailingOnes_xform : SDNodeXForm<imm, [{
49   return CurDAG->getTargetConstant(N->getAPIntValue().countTrailingOnes(),
50                                    MVT::i32);
51 }]>;
52
53 def LO16 : SDNodeXForm<imm, [{
54   return CurDAG->getTargetConstant((unsigned short)N->getZExtValue(), MVT::i16);
55 }]>;
56
57 def HI16 : SDNodeXForm<imm, [{
58   // Transformation function: shift the immediate value down into the low bits.
59   return CurDAG->getTargetConstant((unsigned)N->getZExtValue() >> 16, MVT::i16);
60 }]>;
61
62 //===----------------------------------------------------------------------===//
63 // Immediates
64 //===----------------------------------------------------------------------===//
65
66 def imm3  : PatLeaf<(imm), [{return isInt<3>(N->getSExtValue());}]>;
67 def uimm3 : PatLeaf<(imm), [{return isUint<3>(N->getZExtValue());}]>;
68 def uimm4 : PatLeaf<(imm), [{return isUint<4>(N->getZExtValue());}]>;
69 def uimm5 : PatLeaf<(imm), [{return isUint<5>(N->getZExtValue());}]>;
70
71 def uimm5m2 : PatLeaf<(imm), [{
72     uint64_t value = N->getZExtValue();
73     return value % 2 == 0 && isUint<5>(value);
74 }]>;
75
76 def uimm6m4 : PatLeaf<(imm), [{
77     uint64_t value = N->getZExtValue();
78     return value % 4 == 0 && isUint<6>(value);
79 }]>;
80
81 def imm7   : PatLeaf<(imm), [{return isInt<7>(N->getSExtValue());}]>;
82 def imm16  : PatLeaf<(imm), [{return isInt<16>(N->getSExtValue());}]>;
83 def uimm16 : PatLeaf<(imm), [{return isUint<16>(N->getZExtValue());}]>;
84
85 def ximm16 : PatLeaf<(imm), [{
86     int64_t value = N->getSExtValue();
87     return value < (1<<16) && value >= -(1<<15);
88 }]>;
89
90 def imm17m2 : PatLeaf<(imm), [{
91     int64_t value = N->getSExtValue();
92     return value % 2 == 0 && isInt<17>(value);
93 }]>;
94
95 def imm18m4 : PatLeaf<(imm), [{
96     int64_t value = N->getSExtValue();
97     return value % 4 == 0 && isInt<18>(value);
98 }]>;
99
100 // 32-bit bitmask transformed to a bit number
101 def uimm5mask : Operand<i32>, PatLeaf<(imm), [{
102     return isPowerOf2_32(N->getZExtValue());
103 }], trailingZeros_xform>;
104
105 // 32-bit inverse bitmask transformed to a bit number
106 def uimm5imask : Operand<i32>, PatLeaf<(imm), [{
107     return isPowerOf2_32(~N->getZExtValue());
108 }], trailingOnes_xform>;
109
110 //===----------------------------------------------------------------------===//
111 // Operands
112 //===----------------------------------------------------------------------===//
113
114 def calltarget : Operand<iPTR>;
115
116 def brtarget : Operand<OtherVT>;
117
118 // Addressing modes
119 def ADDRspii : ComplexPattern<i32, 2, "SelectADDRspii", [add, frameindex], []>;
120
121 // Address operands
122 def MEMii : Operand<i32> {
123   let PrintMethod = "printMemoryOperand";
124   let MIOperandInfo = (ops i32imm, i32imm);
125 }
126
127 //===----------------------------------------------------------------------===//
128 // Instructions
129 //===----------------------------------------------------------------------===//
130
131 // Pseudo instructions.
132 class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
133    : InstBfin<outs, ins, asmstr, pattern>;
134
135 let Defs = [SP], Uses = [SP] in {
136 def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt),
137                               "${:comment}ADJCALLSTACKDOWN $amt",
138                               [(BfinCallseqStart timm:$amt)]>;
139 def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
140                             "${:comment}ADJCALLSTACKUP $amt1 $amt2",
141                             [(BfinCallseqEnd timm:$amt1, timm:$amt2)]>;
142 }
143
144 //===----------------------------------------------------------------------===//
145 // Table C-9. Program Flow Control Instructions
146 //===----------------------------------------------------------------------===//
147
148 let isBranch = 1, isTerminator = 1 in {
149
150 let isIndirectBranch = 1 in
151 def JUMPp : F1<(outs), (ins P:$target),
152                "JUMP ($target);",
153                [(brind P:$target)]>;
154
155 // TODO JUMP (PC-P)
156
157 // NOTE: assembler chooses between JUMP.S and JUMP.L
158 def JUMPa : F1<(outs), (ins brtarget:$target),
159                "jump $target;",
160                [(br bb:$target)]>;
161
162 def JUMPcc : F1<(outs), (ins AnyCC:$cc, brtarget:$target),
163                "if $cc jump $target;",
164                [(brcond AnyCC:$cc, bb:$target)]>;
165 }
166
167 let isCall = 1,
168     Defs   = [R0, R1, R2, R3, P0, P1, P2, LB0, LB1, LC0, LC1, RETS, ASTAT] in {
169 def CALLa: F1<(outs), (ins calltarget:$func, variable_ops),
170               "call $func;", []>;
171 def CALLp: F1<(outs), (ins P:$func, variable_ops),
172               "call ($func);", [(BfinCall P:$func)]>;
173 }
174
175 let isReturn     = 1,
176     isTerminator = 1,
177     Uses         = [RETS] in
178 def RTS: F1<(outs), (ins), "rts;", [(BfinRet)]>;
179
180 //===----------------------------------------------------------------------===//
181 // Table C-10. Load / Store Instructions
182 //===----------------------------------------------------------------------===//
183
184 // Immediate constant loads
185
186 // sext immediate, i32 D/P regs
187 def LOADimm7: F1<(outs DP:$dst), (ins i32imm:$src),
188                  "$dst = $src (x);",
189                  [(set DP:$dst, imm7:$src)]>;
190
191 // zext immediate, i32 reg groups 0-3
192 def LOADuimm16: F2<(outs GR:$dst), (ins i32imm:$src),
193                    "$dst = $src (z);",
194                    [(set GR:$dst, uimm16:$src)]>;
195
196 // sext immediate, i32 reg groups 0-3
197 def LOADimm16: F2<(outs GR:$dst), (ins i32imm:$src),
198                   "$dst = $src (x);",
199                   [(set GR:$dst, imm16:$src)]>;
200
201 // Pseudo-instruction for loading a general 32-bit constant.
202 def LOAD32imm: Pseudo<(outs GR:$dst), (ins i32imm:$src),
203                       "$dst.h = ($src >> 16); $dst.l = ($src & 0xffff);",
204                       [(set GR:$dst, imm:$src)]>;
205
206 def LOAD32sym: Pseudo<(outs GR:$dst), (ins i32imm:$src),
207                       "$dst.h = $src; $dst.l = $src;", []>;
208
209
210 // 16-bit immediate, i16 reg groups 0-3
211 def LOAD16i: F2<(outs GR16:$dst), (ins i16imm:$src),
212                  "$dst = $src;", []>;
213
214 def : Pat<(BfinWrapper (i32 tglobaladdr:$addr)),
215           (LOAD32sym tglobaladdr:$addr)>;
216
217 def : Pat<(BfinWrapper (i32 tjumptable:$addr)),
218           (LOAD32sym tjumptable:$addr)>;
219
220 // We cannot copy from GR16 to D16, and codegen wants to insert copies if we
221 // emit GR16 instructions. As a hack, we use this fake instruction instead.
222 def LOAD16i_d16: F2<(outs D16:$dst), (ins i16imm:$src),
223                     "$dst = $src;",
224                     [(set D16:$dst, ximm16:$src)]>;
225
226 // Memory loads with patterns
227
228 def LOAD32p: F1<(outs DP:$dst), (ins P:$ptr),
229                 "$dst = [$ptr];",
230                 [(set DP:$dst, (load P:$ptr))]>;
231
232 // Pseudo-instruction for loading a stack slot
233 def LOAD32fi: Pseudo<(outs DP:$dst), (ins MEMii:$mem),
234                      "${:comment}FI $dst = [$mem];",
235                      [(set DP:$dst, (load ADDRspii:$mem))]>;
236
237 // Note: Expands to multiple insns
238 def LOAD16fi: Pseudo<(outs D16:$dst), (ins MEMii:$mem),
239                      "${:comment}FI $dst = [$mem];",
240                      [(set D16:$dst, (load ADDRspii:$mem))]>;
241
242 // Pseudo-instruction for loading a stack slot, used for AnyCC regs.
243 // Replaced with Load D + CC=D
244 def LOAD8fi: Pseudo<(outs AnyCC:$dst), (ins MEMii:$mem),
245                     "${:comment}FI $dst = B[$mem];",
246                     [(set AnyCC:$dst, (load ADDRspii:$mem))]>;
247
248 def LOAD32p_uimm6m4: F1<(outs DP:$dst), (ins P:$ptr, i32imm:$off),
249                         "$dst = [$ptr + $off];",
250                         [(set DP:$dst, (load (add P:$ptr, uimm6m4:$off)))]>;
251
252 def LOAD32p_imm18m4: F2<(outs DP:$dst), (ins P:$ptr, i32imm:$off),
253                          "$dst = [$ptr + $off];",
254                          [(set DP:$dst, (load (add P:$ptr, imm18m4:$off)))]>;
255
256 def LOAD32p_16z: F1<(outs D:$dst), (ins P:$ptr),
257                     "$dst = W[$ptr] (z);",
258                     [(set D:$dst, (zextloadi16 P:$ptr))]>;
259
260 def : Pat<(i32 (extloadi16 P:$ptr)),(LOAD32p_16z P:$ptr)>;
261
262 def LOAD32p_uimm5m2_16z: F1<(outs D:$dst), (ins P:$ptr, i32imm:$off),
263                             "$dst = w[$ptr + $off] (z);",
264                             [(set D:$dst, (zextloadi16 (add P:$ptr,
265                                                         uimm5m2:$off)))]>;
266
267 def : Pat<(i32 (extloadi16 (add P:$ptr, uimm5m2:$off))),
268           (LOAD32p_uimm5m2_16z P:$ptr, imm:$off)>;
269
270 def LOAD32p_imm17m2_16z: F1<(outs D:$dst), (ins P:$ptr, i32imm:$off),
271                             "$dst = w[$ptr + $off] (z);",
272                             [(set D:$dst,
273                                   (zextloadi16 (add P:$ptr, imm17m2:$off)))]>;
274
275 def : Pat<(i32 (extloadi16 (add P:$ptr, imm17m2:$off))),
276           (LOAD32p_imm17m2_16z P:$ptr, imm:$off)>;
277
278 def LOAD32p_16s: F1<(outs D:$dst), (ins P:$ptr),
279                     "$dst = w[$ptr] (x);",
280                     [(set D:$dst, (sextloadi16 P:$ptr))]>;
281
282 def LOAD32p_uimm5m2_16s: F1<(outs D:$dst), (ins P:$ptr, i32imm:$off),
283                             "$dst = w[$ptr + $off] (x);",
284                             [(set D:$dst,
285                                   (sextloadi16 (add P:$ptr, uimm5m2:$off)))]>;
286
287 def LOAD32p_imm17m2_16s: F1<(outs D:$dst), (ins P:$ptr, i32imm:$off),
288                             "$dst = w[$ptr + $off] (x);",
289                             [(set D:$dst,
290                                   (sextloadi16 (add P:$ptr, imm17m2:$off)))]>;
291
292 def LOAD16pi: F1<(outs D16:$dst), (ins PI:$ptr),
293                 "$dst = w[$ptr];",
294                 [(set D16:$dst, (load PI:$ptr))]>;
295
296 def LOAD32p_8z: F1<(outs D:$dst), (ins P:$ptr),
297                    "$dst = B[$ptr] (z);",
298                    [(set D:$dst, (zextloadi8 P:$ptr))]>;
299
300 def : Pat<(i32 (extloadi8 P:$ptr)), (LOAD32p_8z P:$ptr)>;
301 def : Pat<(i16 (extloadi8 P:$ptr)),
302           (EXTRACT_SUBREG (LOAD32p_8z P:$ptr), bfin_subreg_lo16)>;
303 def : Pat<(i16 (zextloadi8 P:$ptr)),
304           (EXTRACT_SUBREG (LOAD32p_8z P:$ptr), bfin_subreg_lo16)>;
305
306 def LOAD32p_imm16_8z: F1<(outs D:$dst), (ins P:$ptr, i32imm:$off),
307                          "$dst = b[$ptr + $off] (z);",
308                          [(set D:$dst, (zextloadi8 (add P:$ptr, imm16:$off)))]>;
309
310 def : Pat<(i32 (extloadi8 (add P:$ptr, imm16:$off))),
311           (LOAD32p_imm16_8z P:$ptr, imm:$off)>;
312 def : Pat<(i16 (extloadi8 (add P:$ptr, imm16:$off))),
313           (EXTRACT_SUBREG (LOAD32p_imm16_8z P:$ptr, imm:$off),
314                            bfin_subreg_lo16)>;
315 def : Pat<(i16 (zextloadi8 (add P:$ptr, imm16:$off))),
316           (EXTRACT_SUBREG (LOAD32p_imm16_8z P:$ptr, imm:$off),
317                            bfin_subreg_lo16)>;
318
319 def LOAD32p_8s: F1<(outs D:$dst), (ins P:$ptr),
320                    "$dst = b[$ptr] (x);",
321                    [(set D:$dst, (sextloadi8 P:$ptr))]>;
322
323 def : Pat<(i16 (sextloadi8 P:$ptr)),
324           (EXTRACT_SUBREG (LOAD32p_8s P:$ptr), bfin_subreg_lo16)>;
325
326 def LOAD32p_imm16_8s: F1<(outs D:$dst), (ins P:$ptr, i32imm:$off),
327                          "$dst = b[$ptr + $off] (x);",
328                          [(set D:$dst, (sextloadi8 (add P:$ptr, imm16:$off)))]>;
329
330 def : Pat<(i16 (sextloadi8 (add P:$ptr, imm16:$off))),
331           (EXTRACT_SUBREG (LOAD32p_imm16_8s P:$ptr, imm:$off),
332                            bfin_subreg_lo16)>;
333 // Memory loads without patterns
334
335 let mayLoad = 1 in {
336
337 multiclass LOAD_incdec<RegisterClass drc, RegisterClass prc,
338                        string mem="", string suf=";"> {
339   def _inc : F1<(outs drc:$dst, prc:$ptr_wb), (ins prc:$ptr),
340                 !strconcat(!subst("M", mem, "$dst = M[$ptr++]"), suf), []>;
341   def _dec : F1<(outs drc:$dst, prc:$ptr_wb), (ins prc:$ptr),
342                 !strconcat(!subst("M", mem, "$dst = M[$ptr--]"), suf), []>;
343 }
344 multiclass LOAD_incdecpost<RegisterClass drc, RegisterClass prc,
345                            string mem="", string suf=";">
346          : LOAD_incdec<drc, prc, mem, suf> {
347   def _post : F1<(outs drc:$dst, prc:$ptr_wb), (ins prc:$ptr, prc:$off),
348                  !strconcat(!subst("M", mem, "$dst = M[$ptr++$off]"), suf), []>;
349 }
350
351 defm LOAD32p:    LOAD_incdec<DP, P>;
352 defm LOAD32i:    LOAD_incdec<D, I>;
353 defm LOAD8z32p:  LOAD_incdec<D, P, "b", " (z);">;
354 defm LOAD8s32p:  LOAD_incdec<D, P, "b", " (x);">;
355 defm LOADhi:     LOAD_incdec<D16, I, "w">;
356 defm LOAD16z32p: LOAD_incdecpost<D, P, "w", " (z);">;
357 defm LOAD16s32p: LOAD_incdecpost<D, P, "w", " (x);">;
358
359 def LOAD32p_post: F1<(outs D:$dst, P:$ptr_wb), (ins P:$ptr, P:$off),
360                      "$dst = [$ptr ++ $off];", []>;
361
362 // Note: $fp MUST be FP
363 def LOAD32fp_nimm7m4: F1<(outs DP:$dst), (ins P:$fp, i32imm:$off),
364                          "$dst = [$fp - $off];", []>;
365
366 def LOAD32i:      F1<(outs D:$dst), (ins I:$ptr),
367                      "$dst = [$ptr];", []>;
368 def LOAD32i_post: F1<(outs D:$dst, I:$ptr_wb), (ins I:$ptr, M:$off),
369                      "$dst = [$ptr ++ $off];", []>;
370
371
372
373 def LOADhp_post: F1<(outs D16:$dst, P:$ptr_wb), (ins P:$ptr, P:$off),
374                     "$dst = w[$ptr ++ $off];", []>;
375
376
377 }
378
379 // Memory stores with patterns
380 def STORE32p: F1<(outs), (ins DP:$val, P:$ptr),
381                  "[$ptr] = $val;",
382                  [(store DP:$val, P:$ptr)]>;
383
384 // Pseudo-instructions for storing to a stack slot
385 def STORE32fi: Pseudo<(outs), (ins DP:$val, MEMii:$mem),
386                       "${:comment}FI [$mem] = $val;",
387                       [(store DP:$val, ADDRspii:$mem)]>;
388
389 // Note: This stack-storing pseudo-instruction is expanded to multiple insns
390 def STORE16fi: Pseudo<(outs), (ins D16:$val, MEMii:$mem),
391                   "${:comment}FI [$mem] = $val;",
392                   [(store D16:$val, ADDRspii:$mem)]>;
393
394 // Pseudo-instructions for storing AnyCC register to a stack slot.
395 // Replaced with D=CC + STORE byte
396 def STORE8fi: Pseudo<(outs), (ins AnyCC:$val, MEMii:$mem),
397                       "${:comment}FI b[$mem] = $val;",
398                       [(store AnyCC:$val, ADDRspii:$mem)]>;
399
400 def STORE32p_uimm6m4: F1<(outs), (ins DP:$val, P:$ptr, i32imm:$off),
401                  "[$ptr + $off] = $val;",
402                  [(store DP:$val, (add P:$ptr, uimm6m4:$off))]>;
403
404 def STORE32p_imm18m4: F1<(outs), (ins DP:$val, P:$ptr, i32imm:$off),
405                  "[$ptr + $off] = $val;",
406                  [(store DP:$val, (add P:$ptr, imm18m4:$off))]>;
407
408 def STORE16pi: F1<(outs), (ins D16:$val, PI:$ptr),
409                   "w[$ptr] = $val;",
410                   [(store D16:$val, PI:$ptr)]>;
411
412 def STORE8p: F1<(outs), (ins D:$val, P:$ptr),
413                 "b[$ptr] = $val;",
414                 [(truncstorei8 D:$val, P:$ptr)]>;
415
416 def STORE8p_imm16: F1<(outs), (ins D:$val, P:$ptr, i32imm:$off),
417                  "b[$ptr + $off] = $val;",
418                  [(truncstorei8 D:$val, (add P:$ptr, imm16:$off))]>;
419
420 let Constraints = "$ptr = $ptr_wb" in {
421
422 multiclass STORE_incdec<RegisterClass drc, RegisterClass prc,
423                         int off=4, string pre=""> {
424   def _inc : F1<(outs prc:$ptr_wb), (ins drc:$val, prc:$ptr),
425                 !strconcat(pre, "[$ptr++] = $val;"),
426                 [(set prc:$ptr_wb, (post_store drc:$val, prc:$ptr, off))]>;
427   def _dec : F1<(outs prc:$ptr_wb), (ins drc:$val, prc:$ptr),
428                 !strconcat(pre, "[$ptr--] = $val;"),
429                 [(set prc:$ptr_wb, (post_store drc:$val, prc:$ptr,
430                                                (ineg off)))]>;
431 }
432
433 defm STORE32p: STORE_incdec<DP, P>;
434 defm STORE16i: STORE_incdec<D16, I, 2, "w">;
435 defm STORE8p:  STORE_incdec<D, P, 1, "b">;
436
437 def STORE32p_post: F1<(outs P:$ptr_wb), (ins D:$val, P:$ptr, P:$off),
438                       "[$ptr ++ $off] = $val;",
439                       [(set P:$ptr_wb, (post_store D:$val, P:$ptr, P:$off))]>;
440
441 def STORE16p_post: F1<(outs P:$ptr_wb), (ins D16:$val, P:$ptr, P:$off),
442                       "w[$ptr ++ $off] = $val;",
443                       [(set P:$ptr_wb, (post_store D16:$val, P:$ptr, P:$off))]>;
444 }
445
446 // Memory stores without patterns
447
448 let mayStore = 1 in {
449
450 // Note: only works for $fp == FP
451 def STORE32fp_nimm7m4: F1<(outs), (ins DP:$val, P:$fp, i32imm:$off),
452                          "[$fp - $off] = $val;", []>;
453
454 def STORE32i: F1<(outs), (ins D:$val, I:$ptr),
455                  "[$ptr] = $val;", []>;
456
457 def STORE32i_inc: F1<(outs I:$ptr_wb), (ins D:$val, I:$ptr),
458                  "[$ptr++] = $val;", []>;
459
460 def STORE32i_dec: F1<(outs I:$ptr_wb), (ins D:$val, I:$ptr),
461                  "[$ptr--] = $val;", []>;
462
463 def STORE32i_post: F1<(outs I:$ptr_wb), (ins D:$val, I:$ptr, M:$off),
464                       "[$ptr ++ $off] = $val;", []>;
465 }
466
467 def : Pat<(truncstorei16 D:$val, PI:$ptr),
468           (STORE16pi (EXTRACT_SUBREG (COPY_TO_REGCLASS D:$val, D),
469                                      bfin_subreg_lo16), PI:$ptr)>;
470
471 def : Pat<(truncstorei16 (srl D:$val, (i16 16)), PI:$ptr),
472           (STORE16pi (EXTRACT_SUBREG (COPY_TO_REGCLASS D:$val, D),
473                                      bfin_subreg_hi16), PI:$ptr)>;
474
475 def : Pat<(truncstorei8 D16L:$val, P:$ptr),
476           (STORE8p (INSERT_SUBREG (i32 (IMPLICIT_DEF)),
477                                   (COPY_TO_REGCLASS D16L:$val, D16L),
478                                   bfin_subreg_lo16),
479                    P:$ptr)>;
480
481 //===----------------------------------------------------------------------===//
482 // Table C-11. Move Instructions.
483 //===----------------------------------------------------------------------===//
484
485 def MOVE: F1<(outs ALL:$dst), (ins ALL:$src),
486              "$dst = $src;",
487              []>;
488
489 let isTwoAddress = 1 in
490 def MOVEcc: F1<(outs DP:$dst), (ins DP:$src1, DP:$src2, AnyCC:$cc),
491                "if $cc $dst = $src2;",
492                [(set DP:$dst, (select AnyCC:$cc, DP:$src2, DP:$src1))]>;
493
494 let Defs = [AZ, AN, AC0, V] in {
495 def MOVEzext: F1<(outs D:$dst), (ins D16L:$src),
496                  "$dst = $src (z);",
497                  [(set D:$dst, (zext D16L:$src))]>;
498
499 def MOVEsext: F1<(outs D:$dst), (ins D16L:$src),
500                  "$dst = $src (x);",
501                  [(set D:$dst, (sext D16L:$src))]>;
502
503 def MOVEzext8: F1<(outs D:$dst), (ins D:$src),
504                   "$dst = $src.b (z);",
505                   [(set D:$dst, (and D:$src, 0xff))]>;
506
507 def MOVEsext8: F1<(outs D:$dst), (ins D:$src),
508                   "$dst = $src.b (x);",
509                   [(set D:$dst, (sext_inreg D:$src, i8))]>;
510
511 }
512
513 def : Pat<(sext_inreg D16L:$src, i8),
514           (EXTRACT_SUBREG (MOVEsext8
515                            (INSERT_SUBREG (i32 (IMPLICIT_DEF)),
516                                           D16L:$src,
517                                           bfin_subreg_lo16)),
518                           bfin_subreg_lo16)>;
519
520 def : Pat<(sext_inreg D:$src, i16),
521           (MOVEsext (EXTRACT_SUBREG D:$src, bfin_subreg_lo16))>;
522
523 def : Pat<(and D:$src, 0xffff),
524           (MOVEzext (EXTRACT_SUBREG D:$src, bfin_subreg_lo16))>;
525
526 def : Pat<(i32 (anyext D16L:$src)),
527           (INSERT_SUBREG (i32 (IMPLICIT_DEF)),
528                          (COPY_TO_REGCLASS D16L:$src, D16L),
529                          bfin_subreg_lo16)>;
530
531 // TODO Dreg = Dreg_byte (X/Z)
532
533 // TODO Accumulator moves
534
535 //===----------------------------------------------------------------------===//
536 // Table C-12. Stack Control Instructions
537 //===----------------------------------------------------------------------===//
538
539 let Uses = [SP], Defs = [SP] in {
540 def PUSH: F1<(outs), (ins ALL:$src),
541              "[--sp] = $src;", []> { let mayStore = 1; }
542
543 // NOTE: POP does not work for DP regs, use LOAD instead
544 def POP:  F1<(outs ALL:$dst), (ins),
545              "$dst = [sp++];", []> { let mayLoad = 1; }
546 }
547
548 // TODO: push/pop multiple
549
550 def LINK: F2<(outs), (ins i32imm:$amount),
551              "link $amount;", []>;
552
553 def UNLINK: F2<(outs), (ins),
554                "unlink;", []>;
555
556 //===----------------------------------------------------------------------===//
557 // Table C-13. Control Code Bit Management Instructions
558 //===----------------------------------------------------------------------===//
559
560 multiclass SETCC<PatFrag opnode, PatFrag invnode, string cond, string suf=";"> {
561   def dd : F1<(outs JustCC:$cc), (ins D:$a, D:$b),
562               !strconcat(!subst("XX", cond, "cc = $a XX $b"), suf),
563               [(set JustCC:$cc, (opnode  D:$a, D:$b))]>;
564
565   def ri : F1<(outs JustCC:$cc), (ins DP:$a, i32imm:$b),
566               !strconcat(!subst("XX", cond, "cc = $a XX $b"), suf),
567               [(set JustCC:$cc, (opnode  DP:$a, imm3:$b))]>;
568
569   def pp : F1<(outs JustCC:$cc), (ins P:$a, P:$b),
570               !strconcat(!subst("XX", cond, "cc = $a XX $b"), suf),
571               []>;
572
573   def ri_not : F1<(outs NotCC:$cc), (ins DP:$a, i32imm:$b),
574                   !strconcat(!subst("XX", cond, "cc = $a XX $b"), suf),
575                   [(set NotCC:$cc, (invnode  DP:$a, imm3:$b))]>;
576 }
577
578 defm SETEQ  : SETCC<seteq,  setne,  "==">;
579 defm SETLT  : SETCC<setlt,  setge,  "<">;
580 defm SETLE  : SETCC<setle,  setgt,  "<=">;
581 defm SETULT : SETCC<setult, setuge, "<",  " (iu);">;
582 defm SETULE : SETCC<setule, setugt, "<=", " (iu);">;
583
584 def SETNEdd : F1<(outs NotCC:$cc), (ins D:$a, D:$b),
585                  "cc = $a == $b;",
586                  [(set NotCC:$cc, (setne  D:$a, D:$b))]>;
587
588 def : Pat<(setgt  D:$a, D:$b), (SETLTdd  D:$b, D:$a)>;
589 def : Pat<(setge  D:$a, D:$b), (SETLEdd  D:$b, D:$a)>;
590 def : Pat<(setugt D:$a, D:$b), (SETULTdd D:$b, D:$a)>;
591 def : Pat<(setuge D:$a, D:$b), (SETULEdd D:$b, D:$a)>;
592
593 // TODO: compare pointer for P-P comparisons
594 // TODO: compare accumulator
595
596 let Defs = [AC0] in
597 def OR_ac0_cc : F1<(outs), (ins JustCC:$cc),
598                    "ac0 \\|= cc;", []>;
599
600 let Uses = [AC0] in
601 def MOVE_cc_ac0 : F1<(outs JustCC:$cc), (ins),
602                    "cc = ac0;", []>;
603
604 def MOVE_ccncc : F1<(outs JustCC:$cc), (ins NotCC:$sb),
605                     "cc = !cc;", []>;
606
607 def MOVE_ncccc : F1<(outs NotCC:$cc), (ins JustCC:$sb),
608                     "cc = !cc;", []>;
609
610 def MOVECC_zext : F1<(outs D:$dst), (ins JustCC:$cc),
611                       "$dst = $cc;",
612                       [(set D:$dst, (zext JustCC:$cc))]>;
613
614 def MOVENCC_z : F1<(outs D:$dst), (ins NotCC:$cc),
615                    "$dst = cc;", []>;
616
617 def MOVECC_nz : F1<(outs AnyCC:$cc), (ins D:$src),
618                    "cc = $src;",
619                    [(set AnyCC:$cc, (setne D:$src, 0))]>;
620
621 //===----------------------------------------------------------------------===//
622 // Table C-14. Logical Operations Instructions
623 //===----------------------------------------------------------------------===//
624
625 def AND: F1<(outs D:$dst), (ins D:$src1, D:$src2),
626             "$dst = $src1 & $src2;",
627             [(set D:$dst, (and D:$src1, D:$src2))]>;
628
629 def NOT: F1<(outs D:$dst), (ins D:$src),
630             "$dst = ~$src;",
631             [(set D:$dst, (not D:$src))]>;
632
633 def OR: F1<(outs D:$dst), (ins D:$src1, D:$src2),
634            "$dst = $src1 \\| $src2;",
635            [(set D:$dst, (or D:$src1, D:$src2))]>;
636
637 def XOR: F1<(outs D:$dst), (ins D:$src1, D:$src2),
638             "$dst = $src1 ^ $src2;",
639             [(set D:$dst, (xor D:$src1, D:$src2))]>;
640
641 // missing: BXOR, BXORSHIFT
642
643 //===----------------------------------------------------------------------===//
644 // Table C-15. Bit Operations Instructions
645 //===----------------------------------------------------------------------===//
646
647 let isTwoAddress = 1 in {
648 def BITCLR: F1<(outs D:$dst), (ins D:$src1, uimm5imask:$src2),
649               "bitclr($dst, $src2);",
650               [(set D:$dst, (and D:$src1, uimm5imask:$src2))]>;
651
652 def BITSET: F1<(outs D:$dst), (ins D:$src1, uimm5mask:$src2),
653               "bitset($dst, $src2);",
654               [(set D:$dst, (or D:$src1, uimm5mask:$src2))]>;
655
656 def BITTGL: F1<(outs D:$dst), (ins D:$src1, uimm5mask:$src2),
657               "bittgl($dst, $src2);",
658               [(set D:$dst, (xor D:$src1, uimm5mask:$src2))]>;
659 }
660
661 def BITTST: F1<(outs JustCC:$cc), (ins D:$src1, uimm5mask:$src2),
662               "cc = bittst($src1, $src2);",
663               [(set JustCC:$cc, (setne (and D:$src1, uimm5mask:$src2),
664                                        (i32 0)))]>;
665
666 def NBITTST: F1<(outs JustCC:$cc), (ins D:$src1, uimm5mask:$src2),
667                "cc = !bittst($src1, $src2);",
668                [(set JustCC:$cc, (seteq (and D:$src1, uimm5mask:$src2),
669                                         (i32 0)))]>;
670
671 // TODO: DEPOSIT, EXTRACT, BITMUX
672
673 def ONES: F2<(outs D16L:$dst), (ins D:$src),
674               "$dst = ones $src;",
675               [(set D16L:$dst, (trunc (ctpop D:$src)))]>;
676
677 def : Pat<(ctpop D:$src), (MOVEzext (ONES D:$src))>;
678
679 //===----------------------------------------------------------------------===//
680 // Table C-16. Shift / Rotate Instructions
681 //===----------------------------------------------------------------------===//
682
683 multiclass SHIFT32<SDNode opnode, string ops> {
684   def i : F1<(outs D:$dst), (ins D:$src, i16imm:$amount),
685              !subst("XX", ops, "$dst XX= $amount;"),
686              [(set D:$dst, (opnode D:$src, (i16 uimm5:$amount)))]>;
687   def r : F1<(outs D:$dst), (ins D:$src, D:$amount),
688              !subst("XX", ops, "$dst XX= $amount;"),
689              [(set D:$dst, (opnode D:$src, D:$amount))]>;
690 }
691
692 let Defs = [AZ, AN, V, VS],
693     isTwoAddress = 1 in {
694 defm SRA : SHIFT32<sra, ">>>">;
695 defm SRL : SHIFT32<srl, ">>">;
696 defm SLL : SHIFT32<shl, "<<">;
697 }
698
699 // TODO: automatic switching between 2-addr and 3-addr (?)
700
701 let Defs = [AZ, AN, V, VS] in {
702 def SLLr16: F2<(outs D:$dst), (ins D:$src, D16L:$amount),
703              "$dst = lshift $src by $amount;",
704              [(set D:$dst, (shl D:$src, D16L:$amount))]>;
705
706 // Arithmetic left-shift = saturing overflow.
707 def SLAr16: F2<(outs D:$dst), (ins D:$src, D16L:$amount),
708              "$dst = ashift $src by $amount;",
709              [(set D:$dst, (sra D:$src, (ineg D16L:$amount)))]>;
710
711 def SRA16i: F1<(outs D16:$dst), (ins D16:$src, i16imm:$amount),
712               "$dst = $src >>> $amount;",
713               [(set D16:$dst, (sra D16:$src, (i16 uimm4:$amount)))]>;
714
715 def SRL16i: F1<(outs D16:$dst), (ins D16:$src, i16imm:$amount),
716               "$dst = $src >> $amount;",
717               [(set D16:$dst, (srl D16:$src, (i16 uimm4:$amount)))]>;
718
719 // Arithmetic left-shift = saturing overflow.
720 def SLA16r: F1<(outs D16:$dst), (ins D16:$src, D16L:$amount),
721               "$dst = ashift $src BY $amount;",
722               [(set D16:$dst, (srl D16:$src, (ineg D16L:$amount)))]>;
723
724 def SLL16i: F1<(outs D16:$dst), (ins D16:$src, i16imm:$amount),
725               "$dst = $src << $amount;",
726               [(set D16:$dst, (shl D16:$src, (i16 uimm4:$amount)))]>;
727
728 def SLL16r: F1<(outs D16:$dst), (ins D16:$src, D16L:$amount),
729               "$dst = lshift $src by $amount;",
730               [(set D16:$dst, (shl D16:$src, D16L:$amount))]>;
731
732 }
733
734 //===----------------------------------------------------------------------===//
735 // Table C-17. Arithmetic Operations Instructions
736 //===----------------------------------------------------------------------===//
737
738 // TODO: ABS
739
740 let Defs = [AZ, AN, AC0, V, VS] in {
741
742 def ADD: F1<(outs D:$dst), (ins D:$src1, D:$src2),
743             "$dst = $src1 + $src2;",
744             [(set D:$dst, (add D:$src1, D:$src2))]>;
745
746 def ADD16: F2<(outs D16:$dst), (ins D16:$src1, D16:$src2),
747               "$dst = $src1 + $src2;",
748               [(set D16:$dst, (add D16:$src1, D16:$src2))]>;
749
750 let isTwoAddress = 1 in
751 def ADDimm7: F1<(outs D:$dst), (ins D:$src1, i32imm:$src2),
752                 "$dst += $src2;",
753                 [(set D:$dst, (add D:$src1, imm7:$src2))]>;
754
755 def SUB: F1<(outs D:$dst), (ins D:$src1, D:$src2),
756             "$dst = $src1 - $src2;",
757             [(set D:$dst, (sub D:$src1, D:$src2))]>;
758
759 def SUB16: F2<(outs D16:$dst), (ins D16:$src1, D16:$src2),
760               "$dst = $src1 - $src2;",
761               [(set D16:$dst, (sub D16:$src1, D16:$src2))]>;
762
763 }
764
765 def : Pat<(addc D:$src1, D:$src2), (ADD D:$src1, D:$src2)>;
766 def : Pat<(subc D:$src1, D:$src2), (SUB D:$src1, D:$src2)>;
767
768 let Defs = [AZ, AN, V, VS] in
769 def NEG: F1<(outs D:$dst), (ins D:$src),
770             "$dst = -$src;",
771             [(set D:$dst, (ineg D:$src))]>;
772
773 // No pattern, it would confuse isel to have two i32 = i32+i32 patterns
774 def ADDpp: F1<(outs P:$dst), (ins P:$src1, P:$src2),
775               "$dst = $src1 + $src2;", []>;
776
777 let isTwoAddress = 1 in
778 def ADDpp_imm7: F1<(outs P:$dst), (ins P:$src1, i32imm:$src2),
779                 "$dst += $src2;", []>;
780
781 let Defs = [AZ, AN, V] in
782 def ADD_RND20: F2<(outs D16:$dst), (ins D:$src1, D:$src2),
783                   "$dst = $src1 + $src2 (rnd20);", []>;
784
785 let Defs = [V, VS] in {
786 def MUL16: F2<(outs D16:$dst), (ins D16:$src1, D16:$src2),
787               "$dst = $src1 * $src2 (is);",
788               [(set D16:$dst, (mul D16:$src1, D16:$src2))]>;
789
790 def MULHS16: F2<(outs D16:$dst), (ins D16:$src1, D16:$src2),
791                 "$dst = $src1 * $src2 (ih);",
792                 [(set D16:$dst, (mulhs D16:$src1, D16:$src2))]>;
793
794 def MULhh32s: F2<(outs D:$dst), (ins D16:$src1, D16:$src2),
795                 "$dst = $src1 * $src2 (is);",
796                 [(set D:$dst, (mul (sext D16:$src1), (sext D16:$src2)))]>;
797
798 def MULhh32u: F2<(outs D:$dst), (ins D16:$src1, D16:$src2),
799                 "$dst = $src1 * $src2 (is);",
800                 [(set D:$dst, (mul (zext D16:$src1), (zext D16:$src2)))]>;
801 }
802
803
804 let isTwoAddress = 1 in
805 def MUL32: F1<(outs D:$dst), (ins D:$src1, D:$src2),
806             "$dst *= $src2;",
807             [(set D:$dst, (mul D:$src1, D:$src2))]>;
808
809 //===----------------------------------------------------------------------===//
810 // Table C-18. External Exent Management Instructions
811 //===----------------------------------------------------------------------===//
812
813 def IDLE : F1<(outs), (ins), "idle;", [(int_bfin_idle)]>;
814 def CSYNC : F1<(outs), (ins), "csync;", [(int_bfin_csync)]>;
815 def SSYNC : F1<(outs), (ins), "ssync;", [(int_bfin_ssync)]>;
816 def EMUEXCPT : F1<(outs), (ins), "emuexcpt;", []>;
817 def CLI : F1<(outs D:$mask), (ins), "cli $mask;", []>;
818 def STI : F1<(outs), (ins D:$mask), "sti $mask;", []>;
819 def RAISE : F1<(outs), (ins i32imm:$itr), "raise $itr;", []>;
820 def EXCPT : F1<(outs), (ins i32imm:$exc), "excpt $exc;", []>;
821 def NOP : F1<(outs), (ins), "nop;", []>;
822 def MNOP : F2<(outs), (ins), "mnop;", []>;
823 def ABORT : F1<(outs), (ins), "abort;", []>;
824
825 //===----------------------------------------------------------------------===//
826 // Table C-19. Cache Control Instructions
827 //===----------------------------------------------------------------------===//
828
829 //===----------------------------------------------------------------------===//
830 // Table C-20. Video Pixel Operations Instructions
831 //===----------------------------------------------------------------------===//
832
833 def ALIGN8 : F2<(outs D:$dst), (ins D:$src1, D:$src2),
834                 "$dst = align8($src1, $src2);",
835                 [(set D:$dst, (or (shl D:$src1, (i32 24)),
836                                   (srl D:$src2, (i32 8))))]>;
837
838 def ALIGN16 : F2<(outs D:$dst), (ins D:$src1, D:$src2),
839                  "$dst = align16($src1, $src2);",
840                  [(set D:$dst, (or (shl D:$src1, (i32 16)),
841                                    (srl D:$src2, (i32 16))))]>;
842
843 def ALIGN24 : F2<(outs D:$dst), (ins D:$src1, D:$src2),
844                  "$dst = align16($src1, $src2);",
845                  [(set D:$dst, (or (shl D:$src1, (i32 8)),
846                                    (srl D:$src2, (i32 24))))]>;
847
848 def DISALGNEXCPT : F2<(outs), (ins), "disalignexcpt;", []>;
849
850 // TODO: BYTEOP3P, BYTEOP16P, BYTEOP1P, BYTEOP2P, BYTEOP16M, SAA,
851 //       BYTEPACK, BYTEUNPACK
852
853 // Table C-21. Vector Operations Instructions
854
855 // Patterns
856 def : Pat<(BfinCall (i32 tglobaladdr:$dst)),
857           (CALLa tglobaladdr:$dst)>;
858 def : Pat<(BfinCall (i32 texternalsym:$dst)),
859           (CALLa texternalsym:$dst)>;
860
861 def : Pat<(sext JustCC:$cc),
862           (NEG (MOVECC_zext JustCC:$cc))>;
863 def : Pat<(anyext JustCC:$cc),
864           (MOVECC_zext JustCC:$cc)>;
865 def : Pat<(i16 (zext JustCC:$cc)),
866           (EXTRACT_SUBREG (MOVECC_zext JustCC:$cc), bfin_subreg_lo16)>;
867 def : Pat<(i16 (sext JustCC:$cc)),
868           (EXTRACT_SUBREG (NEG (MOVECC_zext JustCC:$cc)), bfin_subreg_lo16)>;
869 def : Pat<(i16 (anyext JustCC:$cc)),
870           (EXTRACT_SUBREG (MOVECC_zext JustCC:$cc), bfin_subreg_lo16)>;
871
872 def : Pat<(i16 (trunc D:$src)),
873           (EXTRACT_SUBREG (COPY_TO_REGCLASS D:$src, D), bfin_subreg_lo16)>;