xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/cr16/cr16.md (revision c64d4171c6f912972428361000d29636c687d68b)
1;; GCC machine description for CR16.
2;; Copyright (C) 2012-2020 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 Instruction  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 (which_alternative == 0) {
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 (which_alternative == 1) {
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 (which_alternative == 2) {
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)
1085