OSDN Git Service

Adding GCC port for National Semicondutor's CR16 architecture
[pf3gnuchains/gcc-fork.git] / gcc / config / cr16 / cr16.md
1 ;; GCC machine description for CR16.
2 ;; Copyright (C) 2012 Free Software Foundation, Inc.
3 ;; Contributed by KPIT Cummins Infosystems Limited.
4
5 ;; This file is part of GCC.
6
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
11
12 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
13 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15 ;; License for more details.
16
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>. 
20
21 ;;  Register numbers
22 (define_constants
23   [(SP_REGNUM 15); Stack pointer
24    (RA_REGNUM 14); Return address
25   ]
26 )
27
28 ;; Predicates & Constraints
29 (include "predicates.md")
30 (include "constraints.md")
31
32 ;; UNSPEC usage
33 (define_constants
34   [(UNSPEC_PIC_ADDR             0)
35    (UNSPEC_PIC_LOAD_ADDR        1)
36    (UNSPEC_LIBRARY_OFFSET       2)
37    (UNSPEC_SH_LIB_PUSH_R12      3)
38    (UNSPEC_SH_LIB_POP_R12       4)
39    (UNSPEC_RETURN_ADDR          5)
40   ]
41 )
42
43 ;; Attributes
44 (define_attr "length" "" (const_int 2))
45
46 (define_asm_attributes
47   [(set_attr "length" "2")]
48 )
49
50 ;;  Mode Macro Definitions
51 (define_mode_iterator CR16IM [QI HI SI])
52 (define_mode_iterator LONG   [SI SF])
53 (define_mode_iterator ALLMTD [QI HI SI SF DI DF])
54 (define_mode_iterator DOUBLE [DI DF])
55 (define_mode_iterator SHORT  [QI HI])
56 (define_mode_attr tIsa       [(QI "b") (HI "w") (SI "d") (SF "d")])
57 (define_mode_attr lImmArith  [(QI "4") (HI "4") (SI "6") (SF "6")])
58 (define_mode_attr lImmArithD [(QI "4") (HI "4") (SI "6") (SF "6") (DI "12") (DF "12")])
59 (define_mode_attr iF         [(QI "i") (HI "i") (SI "i") (SF "F")])
60 (define_mode_attr iFD        [(DI "i") (DF "F")])
61 (define_mode_attr LL         [(QI "L") (HI "L")])
62 (define_mode_attr shImmBits  [(QI "3") (HI "4") (SI "5")])
63
64 ; In QI mode we push 2 bytes instead of 1 byte.
65 (define_mode_attr pushCnstr [(QI "X") (HI "<") (SI "<") (SF "<") (DI "<") (DF "<")])
66
67 ; tpush will be used to generate the 'number of registers to push' in the 
68 ; push instruction.
69 (define_mode_attr tpush [(QI "1") (HI "1") (SI "2") (SF "2") (DI "4") (DF "4")])
70
71 ;;  Code Macro Definitions
72 (define_code_attr  sIsa    [(sign_extend "")  (zero_extend "u")])
73 (define_code_attr  sPat    [(sign_extend "s") (zero_extend "u")])
74 (define_code_attr  szPat   [(sign_extend "")  (zero_extend "zero_")])
75 (define_code_attr  szIsa   [(sign_extend "x") (zero_extend "z")])
76
77 (define_code_iterator sz_xtnd    [ sign_extend       zero_extend])
78 (define_code_iterator any_cond   [eq ne gt gtu lt ltu ge geu le leu])
79 (define_code_iterator plusminus  [plus minus])
80
81 (define_code_attr plusminus_insn [(plus "add") (minus "sub")])
82 (define_code_attr plusminus_flag [(plus "PLUS") (minus "MINUS")])
83 (define_code_attr comm           [(plus "%") (minus "")])
84
85 (define_code_iterator any_logic  [and ior xor])
86 (define_code_attr logic          [(and "and") (ior "or") (xor "xor")])
87 (define_code_attr any_logic_insn [(and "and") (ior "ior") (xor "xor")])
88 (define_code_attr any_logic_flag [(and "AND") (ior "IOR") (xor "XOR")])
89
90 (define_mode_iterator QH         [QI HI])
91 (define_mode_attr qh             [(QI "qi") (HI "hi")])
92 (define_mode_attr QHsz           [(QI "2,2,2") (HI "2,2,4")])
93 (define_mode_attr QHsuffix       [(QI "b") (HI "w")])
94
95
96 ;;  Function Prologue and Epilogue
97 (define_expand "prologue"
98   [(const_int 0)]
99   ""
100   {
101     cr16_expand_prologue ();
102     DONE;
103   }
104 )
105
106 (define_insn "push_for_prologue"
107   [(set (reg:SI SP_REGNUM)
108         (minus:SI (reg:SI SP_REGNUM)
109                   (match_operand:SI 0 "immediate_operand" "i")))]
110   "reload_completed"
111   {
112     return cr16_prepare_push_pop_string (0);
113   }
114   [(set_attr "length" "4")]
115 )
116
117 (define_expand "epilogue"
118   [(return)]
119   ""
120   {
121     cr16_expand_epilogue ();
122     DONE;
123   }
124 )
125
126 (define_insn "pop_and_popret_return"
127   [(set (reg:SI SP_REGNUM)
128         (plus:SI (reg:SI SP_REGNUM)
129                  (match_operand:SI 0 "immediate_operand" "i")))
130    (use (reg:SI RA_REGNUM))
131    (return)]
132   "reload_completed"
133   {
134     return cr16_prepare_push_pop_string (1);
135   }
136   [(set_attr "length" "4")]
137 )
138
139 (define_insn "popret_RA_return"
140   [(use (reg:SI RA_REGNUM))
141    (return)]
142   "reload_completed"
143   "popret\tra"
144   [(set_attr "length" "2")]
145 )
146
147 ;; Arithmetic Instuction  Patterns
148
149 ;; Addition-Subtraction "adddi3/subdi3" insns.
150 (define_insn "<plusminus_insn>di3"
151   [(set (match_operand:DI 0 "register_operand" "=r")
152         (plusminus:DI (match_operand:DI 1 "register_operand" "<comm>0")
153                       (match_operand:DI 2 "register_operand" "r")))]
154   ""
155   {
156     return cr16_emit_add_sub_di (operands, <plusminus_flag>);
157   })
158
159 (define_insn "addsi3"
160   [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
161         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0")
162                  (match_operand:SI 2 "reg_si_int_operand" "r,M,N,O,i")))]
163   ""
164   "addd\t%2, %0"
165   [(set_attr "length" "2,2,4,4,6")]
166 )
167
168 ;; Addition-Subtraction "addhi3/subhi3" insns.
169 (define_insn "<plusminus_insn>hi3"
170   [(set (match_operand:HI 0 "register_operand" "=c,c,c")
171         (plusminus:HI (match_operand:HI 1 "register_operand" "<comm>0,0,0")
172                       (match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))]
173   ""
174   "<plusminus_insn>w\t%2, %0"
175   [(set_attr "length" "2,2,4")]
176 )
177
178 ;; Addition-Subtraction "addqi3/subqi3" insns.
179 (define_insn "<plusminus_insn>qi3"
180   [(set (match_operand:QI 0 "register_operand" "=c,c")
181         (plusminus:QI (match_operand:QI 1 "register_operand" "<comm>0,0")
182                       (match_operand:QI 2 "reg_qi_int_operand" "c,M")))]
183   ""
184   "<plusminus_insn>b\t%2, %0"
185   [(set_attr "length" "2,2")]
186 )
187
188 ;;  Subtract Instruction
189 (define_insn "subsi3"
190   [(set (match_operand:SI 0 "register_operand" "=r,r")
191         (minus:SI (match_operand:SI 1 "register_operand" "0,0")
192                   (match_operand:SI 2 "reg_si_int_operand" "r,i")))]
193   ""
194   "subd\t%2, %0"
195   [(set_attr "length" "4,6")]
196 )
197
198 ;;  Multiply and Accumulate Instructions "smachisi3/umachisi3"
199 (define_insn "<sPat>maddhisi4"
200   [(set (match_operand:SI 0 "register_operand" "=r")
201         (plus:SI
202         (mult:SI (sz_xtnd:SI (match_operand:HI 1 "register_operand" "r"))
203                  (sz_xtnd:SI (match_operand:HI 2 "register_operand" "r")))
204         (match_operand:SI 3 "register_operand" "0")))]
205   "TARGET_MAC"
206   "mac<sPat>w\t%1, %2, %0"
207   [(set_attr "length" "2")]
208 )
209
210 ;;  Multiply Instructions
211 (define_insn "mulhi3"
212   [(set (match_operand:HI 0 "register_operand" "=c,c,c")
213         (mult:HI (match_operand:HI 1 "register_operand" "%0,0,0")
214                  (match_operand:HI 2 "reg_or_int_operand" "c,M,N")))]
215   ""
216   "mulw\t%2, %0"
217   [(set_attr "length" "2,2,4")]
218 )
219
220 (define_insn "mulqihi3"
221   [(set (match_operand:HI 0 "register_operand" "=c")
222         (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
223                  (sign_extend:HI (match_operand:QI 2 "register_operand" "c"))))]
224   ""
225   "mulsb\t%2, %0"
226   [(set_attr "length" "2")]
227 )
228
229 ;;  Bit Set/Clear Instructions
230 (define_expand "insv"
231   [(set (zero_extract (match_operand 0 "memory_operand" "")
232                       (match_operand 1 "immediate_operand" "")
233                       (match_operand 2 "immediate_operand" ""))
234         (match_operand 3 "immediate_operand" ""))]
235   "TARGET_BIT_OPS"
236   {
237     if (INTVAL (operands[1]) != 1)
238       FAIL;
239     if (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 15)
240       FAIL;
241     if (INTVAL (operands[3]) == 1)
242       {
243         if (GET_MODE (operands[0]) == QImode)
244           {
245             emit_insn (gen_set_bitqi (operands[0], operands[2]));
246             DONE;
247           }
248         else if (GET_MODE (operands[0]) == HImode)
249           {
250             emit_insn (gen_set_bithi (operands[0], operands[2]));
251             DONE;
252           }
253       }
254     if (INTVAL (operands[3]) == 0)
255       {
256         if (GET_MODE (operands[0]) == QImode)
257           {
258             emit_insn (gen_clr_bitqi (operands[0], operands[2]));
259             DONE;
260           }
261         else if (GET_MODE (operands[0]) == HImode)
262           {
263             emit_insn (gen_clr_bithi (operands[0], operands[2]));
264             DONE;
265           }
266       }
267   }
268 )
269
270 (define_insn "set_bit<mode>"
271   [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
272                             (const_int 1)
273                             (match_operand 1 "immediate_operand" "i"))
274         (const_int 1))]
275   "TARGET_BIT_OPS"
276   "sbit<tIsa>\t%1,%0"
277   [(set_attr "length" "2")]
278 )
279
280 (define_insn "clr_bit<mode>"
281   [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m")
282                             (const_int 1)
283                             (match_operand 1 "immediate_operand" "i"))
284         (const_int 0))]
285   "TARGET_BIT_OPS"
286   "cbit<tIsa>\t%1,%0"
287   [(set_attr "length" "2")]
288 )
289
290 (define_insn "set_bit<mode>_mem"
291   [(set (match_operand:SHORT 0 "bit_operand" "=m")
292         (ior:SHORT (match_dup 0)
293                    (match_operand:SHORT 1 "one_bit_operand" "i"))
294   )]
295   "TARGET_BIT_OPS"
296   "sbit<tIsa>\t$%s1,%0"
297   [(set_attr "length" "2")]
298 )
299
300 (define_insn "clear_bit<mode>_mem"
301   [(set (match_operand:SHORT 0 "bit_operand" "=m")
302         (and:SHORT (match_dup 0)
303                    (match_operand:SHORT 1 "rev_one_bit_operand" "i"))
304   )]
305   "TARGET_BIT_OPS"
306   "cbit<tIsa>\t$%r1,%0"
307   [(set_attr "length" "2")]
308 )
309
310 ;;  Logical Instructions - and/ior/xor "anddi3/iordi3/xordi3"
311 (define_insn "<any_logic_insn>di3"
312   [(set (match_operand:DI 0 "register_operand" "=r")
313         (any_logic:DI (match_operand:DI 1 "register_operand" "%0")
314                       (match_operand:DI 2 "register_operand" "r")))]
315   ""
316   {
317     return cr16_emit_logical_di (operands, <any_logic_flag>);
318   })
319
320 ; Logical and/ior/xor "andsi3/iorsi3/xorsi3"
321 (define_insn "<any_logic_insn>si3"
322   [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
323         (any_logic:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
324                       (match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))]
325   ""
326   "<logic>d\t%2, %0"
327   [(set_attr "length" "2,2,4,6")]
328 )
329
330 ; Logical and/ior/xor in HImode "andhi3/iorhi3/xorhi3"
331 ; Logical and/ior/xor in QImode "andqi3/iorqi3/xorqi3"
332 (define_insn "<any_logic_insn><qh>3"
333   [(set (match_operand:QH 0 "register_operand" "=c,c,c")
334         (any_logic:QH (match_operand:QH 1 "register_operand" "%0,0,0")
335                       (match_operand:QH 2 "reg_hi_int_operand" "c,M,N")))]
336   ""
337   "<logic><QHsuffix>\t%2, %0"
338   [(set_attr "length" "<QHsz>")]
339 )
340
341 ;;  Sign and Zero Extend Instructions
342 (define_insn "<szPat>extendhisi2"
343   [(set (match_operand:SI 0 "register_operand" "=r")
344         (sz_xtnd:SI (match_operand:HI 1 "register_operand" "r")))]
345   ""
346   "mov<szIsa>w\t%1, %0"
347   [(set_attr "length" "4")]
348 )
349
350 (define_insn "<szPat>extendqihi2"
351   [(set (match_operand:HI 0 "register_operand" "=r")
352         (sz_xtnd:HI (match_operand:QI 1 "register_operand" "r")))]
353   ""
354   "mov<szIsa>b\t%1, %0"
355   [(set_attr "length" "4")]
356 )
357
358 ;;  One's Complement
359 (define_insn "one_cmpldi2"
360   [(set (match_operand:DI 0 "register_operand" "=r")
361         (not:DI (match_operand:DI 1 "register_operand" "0")))]
362   ""
363   {
364     rtx xoperand ;
365     int reg0 = REGNO (operands[0]);
366
367     xoperand = gen_rtx_REG (SImode, reg0 + 2);
368     output_asm_insn ("xord\t$-1, %0", operands);
369     output_asm_insn ("xord\t$-1, %0", &xoperand);
370     return "" ;
371   }
372   [(set_attr "length" "12")]
373 )
374
375 (define_insn "one_cmpl<mode>2"
376   [(set (match_operand:CR16IM 0 "register_operand" "=r")
377         (not:CR16IM (match_operand:CR16IM 1 "register_operand" "0")))]
378   ""
379   "xor<tIsa>\t$-1, %0"
380   [(set_attr "length" "2")]
381 )
382
383 ;;  Arithmetic Left and Right Shift Instructions
384 (define_insn "ashlqi3"
385   [(set (match_operand:QI 0 "register_operand" "=c,c")
386         (ashift:QI (match_operand:QI 1 "register_operand" "0,0")
387                    (match_operand:QI 2 "nonmemory_operand" "c,I")))]
388   ""
389   "ashub\t%2, %0"
390   [(set_attr "length" "2,2")]
391 )
392
393 (define_insn "ashlhi3"
394   [(set (match_operand:HI 0 "register_operand" "=c,c")
395         (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
396                    (match_operand:QI 2 "nonmemory_operand" "c,J")))]
397   ""
398   "ashuw\t%2, %0"
399   [(set_attr "length" "2,2")]
400 )
401
402 (define_insn "ashlsi3"
403   [(set (match_operand:SI 0 "register_operand" "=r,r")
404         (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
405                    (match_operand:QI 2 "nonmemory_operand" "r,K")))]
406   ""
407   "ashud\t%2, %0"
408   [(set_attr "length" "2,2")]
409 )
410
411 (define_expand "ashr<mode>3"
412   [(set (match_operand:CR16IM 0 "register_operand" "")
413         (ashiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "")
414                          (match_operand:QI 2 "nonmemory_operand" "")))]
415   ""
416   {
417     if (GET_CODE (operands[2]) == CONST_INT)
418       {
419         /* If the constant is not in range, try placing it in a reg */
420         if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>))
421         operands[2] = copy_to_mode_reg(QImode, operands[2]);
422       }
423
424     if (GET_CODE (operands[2]) != CONST_INT)
425       operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
426   }
427 )
428
429 (define_insn "ashrqi3_imm_insn"
430   [(set (match_operand:QI 0 "register_operand" "=c")
431         (ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
432                      (match_operand:QI 2 "shift_qi_imm_operand" "i")))]
433   ""
434   "ashub\t$%n2, %0"
435   [(set_attr "length" "2")]
436 )
437
438 (define_insn "ashrhi3_imm_insn"
439   [(set (match_operand:HI 0 "register_operand" "=c")
440         (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
441                      (match_operand:QI 2 "shift_hi_imm_operand" "i")))]
442   ""
443   "ashuw\t$%n2, %0"
444   [(set_attr "length" "2")]
445 )
446
447 (define_insn "ashrsi3_imm_insn"
448   [(set (match_operand:SI 0 "register_operand" "=r")
449         (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
450                      (match_operand:QI 2 "shift_si_imm_operand" "i")))]
451   ""
452   "ashud\t$%n2, %0"
453   [(set_attr "length" "2")]
454 )
455
456 (define_insn "ashrqi3_neg_insn"
457   [(set (match_operand:QI 0 "register_operand" "=c")
458         (ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
459                      (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
460   ""
461   "ashub\t%2,%0"
462   [(set_attr "length" "2")]
463 )
464
465 (define_insn "ashrhi3_neg_insn"
466   [(set (match_operand:HI 0 "register_operand" "=c")
467         (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
468                      (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
469   ""
470   "ashuw\t%2,%0"
471   [(set_attr "length" "2")]
472 )
473
474 (define_insn "ashrdi3_neg_insn"
475   [(set (match_operand:SI 0 "register_operand" "=r")
476         (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
477                      (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
478   ""
479   "ashud\t%2,%0"
480   [(set_attr "length" "2")]
481 )
482
483 (define_expand "lshr<mode>3"
484   [(set (match_operand:CR16IM 0 "register_operand" "")
485         (lshiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "")
486                          (match_operand:QI 2 "reg_or_int_operand" "")))]
487   ""
488   {
489     if (GET_CODE (operands[2]) == CONST_INT)
490       {
491         /* If the constant is not in range, try placing it in a reg */
492         if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>))
493         operands[2] = copy_to_mode_reg(QImode, operands[2]);
494       }
495
496         if (GET_CODE (operands[2]) != CONST_INT)
497         operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
498    }
499 )
500
501 (define_insn "lshrqi3_imm_insn"
502   [(set (match_operand:QI 0 "register_operand" "=c")
503         (lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
504                      (match_operand:QI 2 "shift_qi_operand" "Q")))]
505   ""
506   "lshb\t$%n2, %0"
507   [(set_attr "length" "2")]
508 )
509
510 (define_insn "lshrhi3_imm_insn"
511   [(set (match_operand:HI 0 "register_operand" "=c")
512         (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
513                      (match_operand:QI 2 "shift_hi_operand" "R")))]
514   ""
515   "lshw\t$%n2, %0"
516   [(set_attr "length" "2")]
517 )
518
519 (define_insn "lshrsi3_imm_insn"
520   [(set (match_operand:SI 0 "register_operand" "=r")
521         (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
522                      (match_operand:QI 2 "shift_si_operand" "S")))]
523   ""
524   "lshd\t$%n2, %0"
525   [(set_attr "length" "2")]
526 )
527
528 (define_insn "lshrqi3_neg_insn"
529   [(set (match_operand:QI 0 "register_operand" "=c")
530         (lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
531                      (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
532   ""
533   "lshb\t%2,%0"
534   [(set_attr "length" "2")]
535 )
536
537 (define_insn "lshrhi3_neg_insn"
538   [(set (match_operand:HI 0 "register_operand" "=c")
539         (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
540                      (neg:QI (match_operand:QI 2 "register_operand" "c"))))]
541   ""
542   "lshw\t%2,%0"
543   [(set_attr "length" "2")]
544 )
545
546 (define_insn "lshrsi3_neg_insn"
547   [(set (match_operand:SI 0 "register_operand" "=r")
548         (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
549                      (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
550   ""
551   "lshd\t%2,%0"
552   [(set_attr "length" "2")]
553 )
554
555 ;;  Move Instructions
556
557 ;; Move any non-immediate operand 0 to a general operand 1.
558 ;; This applies only before starting the reload process
559 ;; Operand 0 is not a register operand of type mode MODE
560 ;; If Operand 0 is a push operand of type mode MODE
561 ;; then, if Operand 1 is a non-SP register
562 ;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
563 ;; endif
564 ;; else
565 ;; if Operand 1 is either register or 4-bit immediate constant
566 ;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1)
567 ;; endif
568 ;; endif
569 ;;
570 ;; What does copy_to_mode_reg (mode, rtx val) do?
571 ;; Copy the value into new temp reg and return the reg where the
572 ;; mode of the new reg is always mode MODE when value is constant
573 ;;
574 ;; Why should copy_to_mode_reg be called?
575 ;; All sorts of move are nor supported by CR16. Therefore, 
576 ;; when unsupported move is encountered, the additional instructions 
577 ;; will be introduced for the purpose.
578 ;;
579 ;; A new move insn is inserted for Op 1 when one of the following
580 ;; conditions is met.
581 ;; Case 1:  Op 0 is push_operand
582 ;;          Op 1 is SP register
583 ;;
584 ;; Case 2:  Op 0 is not push_operand
585 ;;          Op 1 is neither register nor unsigned 4-bit immediate
586
587 (define_expand "mov<mode>"
588   [(set (match_operand:ALLMTD 0 "nonimmediate_operand" "")
589         (match_operand:ALLMTD 1 "general_operand" ""))]
590   ""
591   {
592     if (!(reload_in_progress || reload_completed))
593       {
594         /* Only if Op0 is a register operand.  */
595         if (!register_operand (operands[0], <MODE>mode))
596           {
597             if (push_operand (operands[0], <MODE>mode)) 
598               {
599                 /* Use copy_to_mode_reg only if the register needs 
600                 to be pushed is SP as CR16 does not support pushing SP.  */
601                 if (!nosp_reg_operand (operands[1], <MODE>mode))
602                   operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
603               }
604             else
605               {
606                 /* Use copy_to_mode_reg if op1 is not register operand
607                    subject to conditions inside.  */
608                 if (!register_operand (operands[1], <MODE>mode))
609                   {
610                     /* CR16 does not support moving immediate to SI or SF 
611                        type memory.  */
612                     if (<MODE>mode == SImode || <MODE>mode == SFmode ||
613                         <MODE>mode == DImode || <MODE>mode == DFmode)
614                       operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
615                     else
616                       /* moving imm4 is supported by CR16 instruction.  */
617                       if (!u4bits_operand (operands[1], <MODE>mode))
618                         operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
619                   }
620                }
621           }
622
623           /* If operand-1 is a symbol, convert it into a BRO or GOT Format.  */
624           if (flag_pic && ! legitimate_pic_operand_p (operands[1]))
625             {
626               operands[1] = legitimize_pic_address (operands[1], <MODE>mode, 0);
627             }
628       }
629   }
630 )
631
632 ; ALLMT     : QI,HI,SI,SF
633 ; pushCnstr : Push constraints 
634 ;                QI : X
635 ;             HI,SI,SF,DI,DF : <
636 ; b         : All non-sp registers
637 ; tpush     : Push count
638 ;                QI,HI : 1
639 ;                SI,SF : 2
640 ;                DI,DF : 4
641 (define_insn "push<mode>_internal"
642   [(set (match_operand:ALLMTD 0 "push_operand" "=<pushCnstr>")
643         (match_operand:ALLMTD 1 "nosp_reg_operand" "b"))]
644   ""
645   "push\t$<tpush>,%p1"
646   [(set_attr "length" "2")]
647 )
648
649 ; (DI, DF) move
650 (define_insn "*mov<mode>_double"
651   [(set (match_operand:DOUBLE 0 "nonimmediate_operand" "=r, r, r, m")
652         (match_operand:DOUBLE 1 "general_operand" "r, <iFD>, m, r"))]
653   "register_operand (operands[0], DImode) 
654    || register_operand (operands[0], DFmode)
655    || register_operand (operands[1], DImode)
656    || register_operand (operands[1], DFmode)"
657   {
658     if (0 == which_alternative) {
659       rtx xoperands[2] ;
660       int reg0 = REGNO (operands[0]);
661       int reg1 = REGNO (operands[1]);
662
663       xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
664       xoperands[1] = gen_rtx_REG (SImode, reg1 + 2);
665       if ((reg1 + 2) != reg0)
666         {
667           output_asm_insn ("movd\t%1, %0", operands);
668           output_asm_insn ("movd\t%1, %0", xoperands);
669         }
670       else
671         {
672           output_asm_insn ("movd\t%1, %0", xoperands);
673           output_asm_insn ("movd\t%1, %0", operands);
674         }}
675
676     else if (1 == which_alternative) {
677       rtx lo_operands[2] ;
678       rtx hi_operands[2] ;
679
680       lo_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
681       hi_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
682       lo_operands[1] = simplify_gen_subreg (SImode, operands[1],
683                        VOIDmode == GET_MODE (operands[1])
684                        ? DImode  : GET_MODE (operands[1]), 0);
685       hi_operands[1] = simplify_gen_subreg (SImode, operands[1],
686                        VOIDmode == GET_MODE (operands[1])
687                        ? DImode  : GET_MODE (operands[1]), 4);
688       output_asm_insn ("movd\t%1, %0", lo_operands);
689       output_asm_insn ("movd\t%1, %0", hi_operands);}
690
691     else if (2 == which_alternative) {
692       rtx xoperands[2] ;
693       int reg0 = REGNO (operands[0]), reg1 = -2 ;
694       rtx addr ;
695
696         if (MEM_P (operands[1]))
697           addr = XEXP (operands[1], 0);
698         else
699           addr = NULL_RTX ;
700         switch (GET_CODE (addr))
701           {
702             case REG:
703             case SUBREG:
704               reg1 = REGNO (addr);
705               break ;
706             case PLUS:
707               switch (GET_CODE (XEXP (addr, 0))) {
708                 case REG:
709                 case SUBREG:
710                   reg1 = REGNO (XEXP (addr, 0));
711                   break ;
712                 case PLUS:
713                   reg1 = REGNO (XEXP (XEXP (addr, 0), 0));
714                   break ;
715                 default:
716                   inform (DECL_SOURCE_LOCATION (cfun->decl), "unexpected expression; addr:");
717                   debug_rtx (addr);
718                   inform (DECL_SOURCE_LOCATION (cfun->decl), "operands[1]:");
719                   debug_rtx (operands[1]);
720                   inform (DECL_SOURCE_LOCATION (cfun->decl), "generated code might now work\n");
721                   break ;}
722               break ;
723             default:
724               break ;
725           }
726
727         xoperands[0] = gen_rtx_REG (SImode, reg0 + 2);
728         xoperands[1] = offset_address (operands[1], GEN_INT (4), 2);
729         gcc_assert ((reg0 + 1) != reg1);
730         if (reg0 != reg1  &&  (reg1 + 1) != reg0)
731           {
732             output_asm_insn ("loadd\t%1, %0", operands);
733             output_asm_insn ("loadd\t%1, %0", xoperands);
734           }
735         else
736           {
737             output_asm_insn ("loadd\t%1, %0", xoperands);
738             output_asm_insn ("loadd\t%1, %0", operands);
739           }}
740     else
741       {
742         rtx xoperands[2] ;
743         xoperands[0] = offset_address (operands[0], GEN_INT (4), 2);
744         xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
745         output_asm_insn ("stord\t%1, %0", operands);
746         output_asm_insn ("stord\t%1, %0", xoperands);
747       }
748     return "" ;
749   }
750   [(set_attr "length" "4, <lImmArithD>, <lImmArithD>, <lImmArithD>")]
751 )
752
753 ; All long (SI, SF) register move, load and store operations
754 ; The print_operand will take care of printing the register pair 
755 ; when mode is SI/SF and register is in SHORT_REGS
756 (define_insn "*mov<mode>_long"
757   [(set (match_operand:LONG 0 "nonimmediate_operand" "=r, r, r, m")
758         (match_operand:LONG 1 "general_operand" "r, <iF>, m, r"))]
759   "register_operand (operands[0], <MODE>mode)
760    || register_operand (operands[1], <MODE>mode)"
761   "@
762   mov<tIsa>\t%1, %0
763   mov<tIsa>\t%1, %0
764   load<tIsa>\t%1, %0
765   stor<tIsa>\t%1, %0"
766   [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>")]
767 )
768
769 ;; All short (QI, HI) register move, load and store operations
770 (define_insn "*mov<mode>_short"
771   [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r, r, r, m, m")
772         (match_operand:SHORT 1 "general_operand" "r, <iF>, m, r, <LL>"))]
773   "(register_operand (operands[0], <MODE>mode))
774     || (store_operand (operands[0], <MODE>mode)
775         && (register_operand (operands[1], <MODE>mode)
776             || u4bits_operand (operands[1], <MODE>mode)))"
777   "@
778   mov<tIsa>\t%1, %0
779   mov<tIsa>\t%1, %0
780   load<tIsa>\t%1, %0
781   stor<tIsa>\t%1, %0
782   stor<tIsa>\t%1, %0"
783   [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>,<lImmArith>")]
784 )
785
786 ;;  Compare Instructions
787 ; Instruction generated compares the operands in reverse order
788 ; Therefore, while printing the asm, the reverse of the
789 ; compare condition shall be printed.
790 (define_insn "cbranch<mode>4"
791   [(set (pc)
792         (if_then_else (match_operator 0 "ordered_comparison_operator"
793                       [(match_operand:CR16IM 1 "register_operand" "r,r")
794                        (match_operand:CR16IM 2 "nonmemory_operand" "r,n")])
795                        (label_ref (match_operand 3 "" ""))
796                       (pc)))
797    (clobber (cc0))]
798   ""
799   "cmp<tIsa>\t%2, %1\;b%d0\t%l3"
800   [(set_attr "length" "6,6")]
801 )
802
803 (define_expand "cmp<mode>"
804   [(parallel [(set (cc0)
805     (compare (match_operand:CR16IM 0 "register_operand" "")
806              (match_operand:CR16IM 1 "nonmemory_operand" "")))
807     (clobber (match_scratch:HI 2 "=r"))] ) ]
808   ""
809   "")
810
811 ;;  Scond Instructions
812 (define_expand "cstore<mode>4"
813   [(set (cc0)
814         (compare (match_operand:CR16IM 2 "register_operand" "")
815                  (match_operand:CR16IM 3 "nonmemory_operand" "")))
816    (set (match_operand:HI 0 "register_operand")
817         (match_operator:HI 1 "ordered_comparison_operator"
818         [(cc0) (const_int 0)]))]
819   ""
820   ""
821 )
822
823 (define_insn "*cmp<mode>_insn"
824   [(set (cc0)
825         (compare (match_operand:CR16IM 0 "register_operand" "r,r")
826                  (match_operand:CR16IM 1 "nonmemory_operand" "r,n")))]
827   ""
828   "cmp<tIsa>\t%1, %0"
829   [(set_attr "length" "2,4")]
830 )
831
832 (define_insn "sCOND_internal"
833   [(set (match_operand:HI 0 "register_operand" "=r")
834         (match_operator:HI 1 "ordered_comparison_operator"
835         [(cc0) (const_int 0)]))]
836   ""
837   "s%d1\t%0"
838   [(set_attr "length" "2")]
839 )
840
841 ;;  Jumps and Branches
842 (define_insn "indirect_jump_return"
843   [(set (pc)
844           (reg:SI RA_REGNUM))
845    (return)]
846   "reload_completed"
847   "jump\t (ra)"
848   [(set_attr "length" "2")]
849 )
850
851 (define_insn "jump_return"
852   [(unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR)
853    (return)]
854   "reload_completed"
855   "jump\t(ra)"
856   [(set_attr "length" "2")]
857 )
858
859 (define_insn "indirect_jump"
860   [(set (pc)
861         (match_operand:SI 0 "reg_or_sym_operand" "r,i"))]
862   ""
863   "@
864   jump\t%0
865   br\t%a0"
866   [(set_attr "length" "2,6")]
867 )
868
869 (define_insn "interrupt_return"
870   [(unspec_volatile [(const_int 0)] 0)
871    (return)]
872   ""
873   {
874     return cr16_prepare_push_pop_string (1);
875   }
876   [(set_attr "length" "14")]
877 )
878
879 (define_insn "jump_to_imm"
880   [(set (pc)
881         (match_operand 0 "jump_imm_operand" "i"))]
882   ""
883   "br\t%c0"
884   [(set_attr "length" "6")]
885 )
886
887 (define_insn "jump"
888   [(set (pc)
889         (label_ref (match_operand 0 "" "")))]
890   ""
891   "br\t%l0"
892   [(set_attr "length" "6")]
893 )
894
895 ;;  Table Jump
896 (define_insn "tablejump"
897   [(set (pc)
898         (match_operand:SI 0 "register_operand" "r"))
899    (use (label_ref:SI (match_operand 1 "" "")))]
900   "!flag_pic"
901   "jump\t%0"
902   [(set_attr "length" "2")]
903 )
904
905 ;;  Call Instructions
906 (define_expand "call"
907   [(call (match_operand:QI 0 "memory_operand" "")
908          (match_operand 1 "" ""))]
909   ""
910   {
911     if (flag_pic && ! legitimate_pic_operand_p (operands[0]))
912       {
913         operands[0] = gen_const_mem (QImode,
914         legitimize_pic_address (XEXP (operands[0], 0), Pmode, 0));
915         emit_call_insn (gen_cr16_call (operands[0], operands[1]));
916       }
917     else
918       emit_call_insn (gen_cr16_call (operands[0], operands[1]));
919       DONE;
920   }
921 )
922
923 (define_expand "cr16_call"
924   [(parallel
925     [(call (match_operand:QI 0 "memory_operand" "")
926            (match_operand 1 "" ""))
927    (clobber (reg:SI RA_REGNUM))])]
928   ""
929   ""
930 )
931
932 (define_insn "cr16_call_insn_branch_pic"
933   [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
934          (match_operand 1 "" ""))
935    (clobber (match_operand:SI 2 "register_operand" "+r"))]
936   "flag_pic == FAR_PIC"
937   {
938     if (GET_CODE (operands[0]) != CONST_INT)
939       return "loadd\t%g0, %2 \n\tjal %2";
940     else
941       return "jal %2";
942   }
943   [(set_attr "length" "8")]
944 )
945
946 (define_insn "cr16_call_insn_branch"
947   [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i"))
948          (match_operand 1 "" ""))
949    (clobber (match_operand:SI 2 "register_operand" "+r"))]
950   "flag_pic == 0 || flag_pic == NEAR_PIC"
951   {
952     /* Print the immediate address for bal 
953        'b' is used instead of 'a' to avoid compiler calling
954        the GO_IF_LEGITIMATE_ADDRESS which cannot
955        perform checks on const_int code addresses as it
956        assumes all const_int are data addresses.
957     */
958     if (GET_CODE (operands[0]) != CONST_INT)
959       return "bal (ra), %a0";
960     else
961       operands[4] = GEN_INT ((INTVAL (operands[0]))>>1);
962       return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";     
963   }
964   [(set_attr "length" "6")]
965 )
966
967 (define_insn "cr16_call_insn_jump"
968   [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
969          (match_operand 1 "" ""))
970    (clobber (match_operand:SI 2 "register_operand" "+r"))]
971   ""
972   "jal\t%0"
973   [(set_attr "length" "2")]
974 )
975
976 ;;  Call Value Instructions
977
978 (define_expand "call_value"
979   [(set (match_operand 0 "general_operand" "")
980         (call (match_operand:QI 1 "memory_operand" "")
981               (match_operand 2 "" "")))]
982   ""
983   {
984     if (flag_pic && !legitimate_pic_operand_p (operands[1]))
985       {
986         operands[1] = gen_const_mem (QImode,
987         legitimize_pic_address (XEXP (operands[1], 0), Pmode, 0));
988         emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
989       }
990     else
991         emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2]));
992     DONE;
993   }
994 )
995
996 (define_expand "cr16_call_value"
997   [(parallel
998     [(set (match_operand 0 "general_operand" "")
999           (call (match_operand 1 "memory_operand" "")
1000                 (match_operand 2 "" "")))
1001      (clobber (reg:SI RA_REGNUM))])]
1002   ""
1003   ""
1004 )
1005
1006 (define_insn "cr16_call_value_insn_branch_pic"
1007   [(set (match_operand 0 "" "=g")
1008         (call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
1009               (match_operand 2 "" "")))
1010    (clobber (match_operand:SI 3 "register_operand" "+r"))]
1011   "flag_pic == FAR_PIC"
1012   {
1013     if (GET_CODE (operands[1]) != CONST_INT)
1014       return "loadd\t%g1, %3 \n\tjal %3";
1015     else
1016       return "jal %3";
1017   }
1018   [(set_attr "length" "8")]
1019 )
1020
1021 (define_insn "cr16_call_value_insn_branch"
1022   [(set (match_operand 0 "" "=g")
1023         (call (mem:QI (match_operand:SI 1 "call_imm_operand" "i"))
1024               (match_operand 2 "" "")))
1025    (clobber (match_operand:SI 3 "register_operand" "+r"))]
1026   "flag_pic == 0 || flag_pic == NEAR_PIC"
1027   {
1028     /* Print the immediate address for bal 
1029        'b' is used instead of 'a' to avoid compiler calling
1030        the GO_IF_LEGITIMATE_ADDRESS which cannot
1031        perform checks on const_int code addresses as it
1032        assumes all const_int are data addresses.
1033     */
1034     if (GET_CODE (operands[1]) != CONST_INT) 
1035       return "bal (ra), %a1";
1036     else
1037       {
1038         operands[4] = GEN_INT ((INTVAL (operands[1]))>>1);
1039         return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)";   
1040       }
1041   }
1042   [(set_attr "length" "6")]
1043 )
1044
1045
1046 (define_insn "cr16_call_value_insn_jump"
1047   [(set (match_operand 0 "" "=g")
1048         (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
1049               (match_operand 2 "" "")))
1050    (clobber (match_operand:SI 3 "register_operand" "+r"))]
1051   ""
1052   "jal\t%1"
1053   [(set_attr "length" "2")]
1054 )
1055
1056
1057 ;;  Nop
1058 (define_insn "nop"
1059   [(const_int 0)]
1060   ""
1061   "nop\t"
1062 )
1063
1064 ;; PIC
1065 /* When generating pic, we need to load the symbol offset into a register.
1066    So that the optimizer does not confuse this with a normal symbol load
1067    we use an unspec.  The offset will be loaded from a constant pool entry,
1068    since that is the only type of relocation we can use.  */
1069                                                                                                                             
1070 (define_insn "unspec_bro_addr"
1071   [(set (match_operand:SI 0 "register_operand" "=r")
1072         (unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_ADDR))]
1073   ""
1074   "movd \t%f1, %0"
1075   [(set_attr "length" "4")]
1076 )
1077
1078 (define_insn "unspec_got_addr"
1079   [(set (match_operand:SI 0 "register_operand" "=r")
1080         (unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_LOAD_ADDR))]
1081   ""
1082   "loadd \t%g1, %0"
1083   [(set_attr "length" "6")]
1084 )