1;; Machine description of the Adaptiva epiphany cpu for GNU C compiler
2;; Copyright (C) 1994-2013 Free Software Foundation, Inc.
3;; Contributed by Embecosm on behalf of Adapteva, Inc.
4
5;; This file is part of GCC.
6
7;; GCC is free software; you can redistribute it and/or modify
8;; it 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,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15;; GNU General Public 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;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
22
23(define_constants
24  [(GPR_0			 0)
25   (GPR_FP			11)
26   (GPR_IP			12)
27   (GPR_SP			13)
28   (GPR_LR			14)
29   (GPR_16			16)
30   (GPR_18			18)
31   (GPR_20			20)
32   (ARG_POINTER_REGNUM		64)
33   (FRAME_POINTER_REGNUM	65)
34   (CC_REGNUM			66)   ;; 66 or 17
35   (CCFP_REGNUM			67)   ;; 67 or 18
36   (CONFIG_REGNUM		68)
37   (STATUS_REGNUM		69)
38   (LC_REGNUM			70)
39   (LS_REGNUM			71)
40   (LE_REGNUM			72)
41   (IRET_REGNUM			73)
42   (FP_NEAREST_REGNUM		74)
43   (FP_TRUNCATE_REGNUM		75)
44   (FP_ANYFP_REGNUM		76)
45   (UNKNOWN_REGNUM		77) ; used for addsi3_r and friends
46   ; We represent the return address as an unspec rather than a reg.
47   ; If we used a reg, we could use register elimination, but eliminating
48   ; to GPR_LR would make the latter visible to dataflow, thus making it
49   ; harder to determine when it must be saved.
50   (UNSPEC_RETURN_ADDR		 0)
51   (UNSPEC_FP_MODE		 1)
52
53   (UNSPECV_GID			 0)
54   (UNSPECV_GIE			 1)])
55
56;; Insn type.  Used to default other attribute values.
57
58(define_attr "type"
59  "move,load,store,cmove,unary,compare,shift,mul,uncond_branch,branch,call,fp,fp_int,v2fp,misc,sfunc,fp_sfunc,flow"
60  (const_string "misc"))
61
62;; Length (in # bytes)
63
64(define_attr "length" "" (const_int 4))
65
66;; The length here is the length of a single asm.
67
68(define_asm_attributes
69  [(set_attr "length" "4")
70   (set_attr "type" "misc")])
71
72;; pipeline model; so far we have only one.
73(define_attr "pipe_model" "epiphany" (const_string "epiphany"))
74
75(define_attr "rounding" "trunc,nearest"
76  (cond [(ne (symbol_ref "TARGET_ROUND_NEAREST") (const_int 0))
77	 (const_string "nearest")]
78	(const_string "trunc")))
79
80(define_attr "fp_mode" "round_unknown,round_nearest,round_trunc,int,caller,none"
81  (cond [(eq_attr "type" "fp,v2fp,fp_sfunc")
82	 (symbol_ref "(enum attr_fp_mode) epiphany_normal_fp_rounding")
83	 (eq_attr "type" "call")
84	 (symbol_ref "(enum attr_fp_mode) epiphany_normal_fp_mode")
85	 (eq_attr "type" "fp_int")
86	 (const_string "int")]
87	(const_string "none")))
88
89(include "epiphany-sched.md")
90
91(include "predicates.md")
92(include "constraints.md")
93
94;; modes that are held in a single register, and hence, a word.
95(define_mode_iterator WMODE [SI SF HI QI V2HI V4QI])
96(define_mode_iterator WMODE2 [SI SF HI QI V2HI V4QI])
97
98;; modes that are held in a two single registers
99(define_mode_iterator DWMODE [DI DF V2SI V2SF V4HI V8QI])
100
101;; Double-word mode made up of two single-word mode values.
102(define_mode_iterator DWV2MODE [V2SI V2SF])
103(define_mode_attr vmode_part [(V2SI "si") (V2SF "sf")])
104(define_mode_attr vmode_PART [(V2SI "SI") (V2SF "SF")])
105(define_mode_attr vmode_fp_type [(V2SI "fp_int") (V2SF "fp")])
106(define_mode_attr vmode_ccmode [(V2SI "CC") (V2SF "CC_FP")])
107(define_mode_attr vmode_cc [(V2SI "CC_REGNUM") (V2SF "CCFP_REGNUM")])
108
109;; Move instructions.
110
111(define_expand "mov<mode>"
112  [(set (match_operand:WMODE 0 "general_operand" "")
113	(match_operand:WMODE 1 "general_operand" ""))]
114  ""
115{
116  if (<MODE>mode == V4QImode || <MODE>mode == V2HImode)
117    {
118      operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0);
119      operands[1] = simplify_gen_subreg (SImode, operands[1], <MODE>mode, 0);
120      emit_insn (gen_movsi (operands[0], operands[1]));
121      DONE;
122    }
123  if (GET_CODE (operands[0]) == MEM)
124    operands[1] = force_reg (<MODE>mode, operands[1]);
125  if (<MODE>mode == SImode
126      && (operands[1] == frame_pointer_rtx || operands[1] == arg_pointer_rtx))
127    {
128      rtx reg = operands[0];
129
130      if (!REG_P (reg))
131	reg = gen_reg_rtx (SImode);
132      emit_insn (gen_move_frame (reg, operands[1]));
133      operands[1] = reg;
134      if (operands[0] == reg)
135	DONE;
136    }
137})
138
139(define_insn "*movqi_insn"
140  [(set (match_operand:QI 0 "move_dest_operand" "=Rcs,   r,  r,r,m")
141	(match_operand:QI 1 "move_src_operand"   "Rcs,rU16,Cal,m,r"))]
142;; ??? Needed?
143  "gpr_operand (operands[0], QImode)
144   || gpr_operand (operands[1], QImode)"
145  "@
146   mov %0,%1
147   mov %0,%1
148   mov %0,%1
149   ldrb %0,%1
150   strb %1,%0"
151  [(set_attr "type" "move,move,move,load,store")])
152
153(define_insn_and_split "*movhi_insn"
154  [(set (match_operand:HI 0 "move_dest_operand" "=r,  r,r,m")
155	(match_operand:HI 1 "move_src_operand""rU16,Cal,m,r"))]
156  "gpr_operand (operands[0], HImode)
157   || gpr_operand (operands[1], HImode)"
158  "@
159   mov %0,%1
160   mov %0,%%low(%1); %1
161   ldrh %0,%c1
162   strh %1,%c0"
163  "reload_completed && CONSTANT_P (operands[1])
164   && !satisfies_constraint_U16 (operands[1]) && TARGET_SPLIT_LOHI"
165  [(set (match_dup 2) (match_dup 3))]
166  "operands[2] = simplify_gen_subreg (SImode, operands[0], HImode, 0);
167   operands[3] = simplify_gen_subreg (SImode, operands[1], HImode, 0);"
168  [(set_attr "type" "move,move,load,store")])
169
170;; We use a special pattern for a move from the frame pointer to
171;; show the flag clobber that is needed when this move is changed
172;; to an add by register elimination.
173;; ??? A pseudo register might be equivalent to a function invariant,
174;; and thus placed by reload into reg_equiv_invariant; if the pseudo
175;; does not get a hard register, we then end up with the function
176;; invariant in its place, i.e. an unexpected clobber of the flags
177;; register.
178;;
179;; N.B. operand 1 is an operand so that reload will perform elimination.
180;;
181;; The post-reload pattern recognition and splitting is done in frame_move_1.
182(define_insn "move_frame"
183  [(set (match_operand:SI 0 "gpr_operand" "=r")
184	(match_operand:SI 1 "register_operand" "r"))
185   (clobber (reg:CC CC_REGNUM))]
186  "operands[1] == frame_pointer_rtx || operands[1] == arg_pointer_rtx"
187  "#")
188
189(define_insn "movsi_high"
190  [(set (match_operand:SI 0 "gpr_operand" "+r")
191	(ior:SI (and:SI (match_dup 0) (const_int 65535))
192		(high:SI (match_operand:SI 1 "move_src_operand" "i"))))]
193  ""
194  "movt %0, %%high(%1)"
195  [(set_attr "type" "move")
196   (set_attr "length" "4")])
197
198(define_insn "movsi_lo_sum"
199  [(set (match_operand:SI 0 "gpr_operand" "=r")
200	(lo_sum:SI (const_int 0)
201		   (match_operand:SI 1 "move_src_operand" "i")))]
202  ""
203  "mov %0, %%low(%1)"
204  [(set_attr "type" "move")
205   (set_attr "length" "4")])
206
207(define_insn_and_split "*movsi_insn"
208  [(set (match_operand:SI 0 "move_dest_operand"
209	 "=   r,  r,  r,  r,  r,   r,   m,  r,  Rct")
210	(match_operand:SI 1 "move_src_operand"
211	 "rU16Rra,Cm1,Cl1,Cr1,Cal,mSra,rRra,Rct,r"))]
212  "gpr_operand (operands[0], SImode)
213   || gpr_operand (operands[1], SImode)
214   || satisfies_constraint_Sra (operands[1])"
215{
216  switch (which_alternative)
217    {
218    case 0: return "mov %0,%1";
219    case 1: return "add %0,%-,(1+%1)";
220    case 2: operands[1] = GEN_INT (exact_log2 (-INTVAL (operands[1])));
221      return "lsl %0,%-,%1";
222    case 3: operands[1] = GEN_INT (32 - exact_log2 (INTVAL (operands[1]) + 1));
223      return "lsr %0,%-,%1";
224    case 4: return "mov %0,%%low(%1)\;movt %0,%%high(%1) ; %1";
225    case 5: return "ldr %0,%C1";
226    case 6: return "str %1,%C0";
227    case 7: return "movfs %0,%1";
228    case 8: return "movts %0,%1";
229    default: gcc_unreachable ();
230    }
231}
232  "reload_completed && CONSTANT_P (operands[1])
233   && !satisfies_constraint_U16 (operands[1])
234   && !satisfies_constraint_Cm1 (operands[1])
235   && !satisfies_constraint_Cl1 (operands[1])
236   && !satisfies_constraint_Cr1 (operands[1])
237   && TARGET_SPLIT_LOHI"
238  [(match_dup 2) (match_dup 3)]
239  "operands[2] = gen_movsi_lo_sum (operands[0], operands[1]);
240   operands[3] = gen_movsi_high (operands[0], operands[1]);"
241  [(set_attr "type" "move,misc,misc,misc,move,load,store,flow,flow")
242   (set_attr "length" "4,4,4,4,8,4,4,4,4")])
243
244(define_split
245  [(set (match_operand:SI 0 "nonimmediate_operand")
246	(unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR))]
247  "reload_completed && !MACHINE_FUNCTION (cfun)->lr_clobbered"
248  [(set (match_dup 0) (reg:SI GPR_LR))])
249
250(define_split
251  [(set (match_operand:SI 0 "gpr_operand")
252	(unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR))]
253  "reload_completed"
254  [(set (match_dup 0) (match_dup 1))]
255{
256  emit_insn (gen_reload_insi_ra (operands[0], operands[1]));
257  DONE;
258})
259
260(define_expand "reload_insi_ra"
261  [(set (match_operand:SI 0 "gpr_operand" "r") (match_operand:SI 1 "" "Sra"))]
262  ""
263{
264  rtx addr
265    = (frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx);
266
267  addr = plus_constant (Pmode, addr, MACHINE_FUNCTION (cfun)->lr_slot_offset);
268  operands[1] = gen_frame_mem (SImode, addr);
269})
270
271;; If the frame pointer elimination offset is zero, we'll use this pattern.
272;; Note that the splitter can accept any gpr in operands[1]; this is
273;; necessary, (e.g. for compile/20021015-1.c -O0,)
274;; because when register elimination cannot be done with the constant
275;; as an immediate operand of the add instruction, reload will resort to
276;; loading the constant into a reload register, using gen_add2_insn to add
277;; the stack pointer, and then use the reload register as new source in
278;; the move_frame pattern.
279(define_insn_and_split "*move_frame_1"
280  [(set (match_operand:SI 0 "gpr_operand" "=r")
281	(match_operand:SI 1 "gpr_operand" "r"))
282   (clobber (reg:CC CC_REGNUM))]
283  "(reload_in_progress || reload_completed)
284   && (operands[1] == stack_pointer_rtx
285       || operands[1] == hard_frame_pointer_rtx)"
286  "#"
287  "reload_in_progress || reload_completed"
288  [(set (match_dup 0) (match_dup 1))])
289
290(define_expand "mov<mode>"
291  [(set (match_operand:DWMODE 0 "general_operand" "")
292	(match_operand:DWMODE 1 "general_operand" ""))]
293  ""
294  "
295{
296  if (GET_MODE_CLASS (<MODE>mode) == MODE_VECTOR_INT
297      || GET_MODE_CLASS (<MODE>mode) == MODE_VECTOR_FLOAT)
298    {
299      if (epiphany_vect_align == 4 && TARGET_SPLIT_VECMOVE_EARLY)
300	{
301	  rtx o0l, o0h, o1l, o1h;
302
303	  o0l = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0);
304	  o0h = simplify_gen_subreg (SImode, operands[0], <MODE>mode,
305				     UNITS_PER_WORD);
306	  o1l = simplify_gen_subreg (SImode, operands[1], <MODE>mode, 0);
307	  o1h = simplify_gen_subreg (SImode, operands[1], <MODE>mode,
308				     UNITS_PER_WORD);
309	  if (reg_overlap_mentioned_p (o0l, o1h))
310	    {
311	      emit_move_insn (o0h, o1h);
312	      emit_move_insn (o0l, o1l);
313	    }
314	  else
315	    {
316	      emit_move_insn (o0l, o1l);
317	      emit_move_insn (o0h, o1h);
318	    }
319	  DONE;
320	}
321      /* lower_subreg has a tendency to muck up vectorized code.
322	 To protect the wide memory accesses, we must use same-size
323	 subregs.  */
324      if (epiphany_vect_align != 4 /* == 8 */
325	  && !reload_in_progress
326	  && (GET_CODE (operands[0]) == MEM || GET_CODE (operands[1]) == MEM)
327	  && !misaligned_operand (operands[1], <MODE>mode)
328	  && (GET_CODE (operands[0]) != SUBREG
329	      || (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0])))
330		  != GET_MODE_SIZE (<MODE>mode)
331		  && GET_CODE (operands[1]) != SUBREG)))
332	{
333	  operands[0]
334	    = simplify_gen_subreg (DImode, operands[0], <MODE>mode, 0);
335	  operands[1]
336	    = simplify_gen_subreg (DImode, operands[1], <MODE>mode, 0);
337	  emit_insn (gen_movdi (operands[0], operands[1]));
338	  DONE;
339	}
340    }
341  /* Everything except mem = const or mem = mem can be done easily.  */
342
343  if (GET_CODE (operands[0]) == MEM)
344    operands[1] = force_reg (<MODE>mode, operands[1]);
345}")
346
347(define_insn_and_split "*mov<mode>_insn"
348  [(set (match_operand:DWMODE 0 "move_dest_operand"      "=r,   r,r,m")
349	(match_operand:DWMODE 1 "move_double_src_operand" "r,CalE,m,r"))]
350  "(gpr_operand (operands[0], <MODE>mode)
351    || gpr_operand (operands[1], <MODE>mode))"
352  "@
353   #
354   #
355   ldrd %0,%X1
356   strd %1,%X0"
357  "reload_completed
358   && (((!MEM_P (operands[0]) || misaligned_operand (operands[0], <MODE>mode))
359	&& (!MEM_P (operands[1])
360	    || misaligned_operand (operands[1], <MODE>mode)))
361       || epiphany_vect_align == 4)"
362  [(set (match_dup 2) (match_dup 3))
363   (set (match_dup 4) (match_dup 5))]
364{
365  int word0 = 0, word1 = UNITS_PER_WORD;
366
367  if (post_modify_operand (operands[0], <MODE>mode)
368      || post_modify_operand (operands[1], <MODE>mode))
369    word0 = UNITS_PER_WORD, word1 = 0;
370
371  operands[2] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, word0);
372  operands[3] = simplify_gen_subreg (SImode, operands[1], <MODE>mode, word0);
373  operands[4] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, word1);
374  operands[5] = simplify_gen_subreg (SImode, operands[1], <MODE>mode, word1);
375  if (post_modify_operand (operands[0], <MODE>mode))
376    operands[2]
377      = change_address (operands[2], VOIDmode,
378			plus_constant (Pmode, XEXP (XEXP (operands[0], 0), 0),
379				       UNITS_PER_WORD));
380  if (post_modify_operand (operands[1], <MODE>mode))
381    operands[3]
382      = change_address (operands[3], VOIDmode,
383			plus_constant (Pmode, XEXP (XEXP (operands[1], 0), 0),
384				       UNITS_PER_WORD));
385}
386  [(set_attr "type" "move,move,load,store")
387   (set_attr "length" "8,16,4,4")])
388
389
390(define_insn_and_split "*movsf_insn"
391  [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,m")
392	(match_operand:SF 1 "move_src_operand"   "r,E,m,r"))]
393  "gpr_operand (operands[0], SFmode)
394   || gpr_operand (operands[1], SFmode)"
395  "@
396   mov %0,%1
397   mov %0,%%low(%1)\;movt %0,%%high(%1) ; %1
398   ldr %0,%C1
399   str %1,%C0"
400  "reload_completed && CONSTANT_P (operands[1]) && TARGET_SPLIT_LOHI"
401  [(set (match_dup 2) (match_dup 3))]
402  "operands[2] = simplify_gen_subreg (SImode, operands[0], SFmode, 0);
403   operands[3] = simplify_gen_subreg (SImode, operands[1], SFmode, 0);"
404  [(set_attr "type" "move,move,load,store")
405   (set_attr "length" "4,8,4,4")])
406
407(define_expand "addsi3"
408  [(set (match_operand:SI 0 "add_reg_operand" "")
409	(plus:SI (match_operand:SI 1 "add_reg_operand" "")
410		 (match_operand:SI 2 "add_operand" "")))]
411  ""
412  "
413{
414  if (reload_in_progress || reload_completed)
415    emit_insn (gen_addsi3_r (operands[0], operands[1], operands[2]));
416  else if (TARGET_FP_IARITH && add_reg_operand (operands[2], SImode))
417    emit_insn (gen_iadd (operands[0], operands[1], operands[2]));
418  else
419    emit_insn (gen_addsi3_i (operands[0], operands[1], operands[2]));
420  DONE;
421}")
422
423(define_insn "addsi3_i"
424  [(set (match_operand:SI 0 "add_reg_operand" "=r")
425	(plus:SI (match_operand:SI 1 "add_reg_operand" "%r")
426		 (match_operand:SI 2 "add_operand" "rL")))
427   (clobber (reg:CC CC_REGNUM))]
428  ""
429  "add %0,%1,%2"
430[(set_attr "type" "misc")])
431
432; We use a clobber of UNKNOWN_REGNUM here so that the peephole optimizers
433; can identify the unresolved flags clobber problem, and also to
434; avoid unwanted matches.
435;
436; At -O0 / -O1 we don't peephole all instances away.  We could get better
437; debug unwinding through the emitted code if we added a splitter.
438(define_insn "addsi3_r"
439  [(set (match_operand:SI 0 "gpr_operand" "=r")
440	(plus:SI (match_operand:SI 1 "gpr_operand" "%r")
441		 (match_operand:SI 2 "nonmemory_operand" "rCar")))
442   (clobber (reg:CC UNKNOWN_REGNUM))]
443  "reload_in_progress || reload_completed"
444{
445  int scratch = (0x17
446		 ^ (true_regnum (operands[0]) & 1)
447		 ^ (true_regnum (operands[1]) & 2)
448		 ^ (true_regnum (operands[2]) & 4));
449  asm_fprintf (asm_out_file, "\tstr r%d,[sp,#0]\n", scratch);
450  asm_fprintf (asm_out_file, "\tmovfs r%d,status\n", scratch);
451  output_asm_insn ("add %0,%1,%2", operands);
452  asm_fprintf (asm_out_file, "\tmovts status,r%d\n", scratch);
453  asm_fprintf (asm_out_file, "\tldr r%d,[sp,#0]\n", scratch);
454  return "";
455}
456  [(set_attr "length" "20")
457   (set_attr "type" "misc")])
458
459;; reload uses gen_addsi2 because it doesn't understand the need for
460;; the clobber.
461(define_peephole2
462  [(set (match_operand:SI 0 "gpr_operand" "")
463	(match_operand:SI 1 "const_int_operand" ""))
464   (parallel [(set (match_dup 0)
465		   (plus:SI (match_dup 0)
466			    (match_operand:SI 2 "gpr_operand")))
467	      (clobber (reg:CC UNKNOWN_REGNUM))])]
468  "satisfies_constraint_L (operands[1])
469   || ((operands[2] == stack_pointer_rtx
470	|| (operands[2] == hard_frame_pointer_rtx && frame_pointer_needed))
471       && !peep2_regno_dead_p (2, CC_REGNUM)
472       && satisfies_constraint_Car (operands[1]))"
473  [(parallel [(set (match_dup 0)
474		   (plus:SI (match_dup 2) (match_dup 1)))
475	      (clobber (reg:CC UNKNOWN_REGNUM))])]
476  ;; FIXME:
477  ;; need this patch: http://gcc.gnu.org/ml/gcc-patches/2011-10/msg02819.html
478  ;; "peep2_rescan = true;"
479)
480
481(define_peephole2
482  [(match_parallel 5 ""
483     [(set (match_operand 3 "cc_operand" "") (match_operand 4 "" ""))])
484   (parallel [(set (match_operand:SI 0 "gpr_operand" "")
485		   (plus:SI (match_operand:SI 1 "gpr_operand" "")
486			    (match_operand:SI 2 "nonmemory_operand" "")))
487	      (clobber (reg:CC UNKNOWN_REGNUM))])]
488  "REGNO (operands[3]) == CC_REGNUM
489   && (gpr_operand (operands[2], SImode)
490       || satisfies_constraint_L (operands[2]))
491   && !reg_overlap_mentioned_p (operands[0], operands[5])
492   && !reg_set_p (operands[1], operands[5])
493   && !reg_set_p (operands[2], operands[5])"
494  [(parallel [(set (match_operand:SI 0 "gpr_operand" "")
495		   (plus:SI (match_operand:SI 1 "gpr_operand" "")
496			    (match_operand:SI 2 "nonmemory_operand" "")))
497	      (clobber (reg:CC CC_REGNUM))])
498   (match_dup 5)]
499  "")
500
501(define_peephole2
502  [(parallel [(set (match_operand:SI 0 "gpr_operand" "")
503		   (plus:SI (match_operand:SI 1 "gpr_operand" "")
504			    (match_operand:SI 2 "nonmemory_operand" "")))
505	      (clobber (reg:CC UNKNOWN_REGNUM))])]
506  "peep2_regno_dead_p (1, CC_REGNUM)
507   && (gpr_operand (operands[2], SImode)
508       || satisfies_constraint_L (operands[2]))"
509  [(parallel [(set (match_operand:SI 0 "gpr_operand" "")
510		   (plus:SI (match_operand:SI 1 "gpr_operand" "")
511			    (match_operand:SI 2 "nonmemory_operand" "")))
512	      (clobber (reg:CC CC_REGNUM))])]
513  "")
514
515(define_peephole2
516  [(parallel [(set (match_operand:SI 0 "gpr_operand" "")
517		   (plus:SI (reg:SI GPR_SP)
518			    (match_operand:SI 1 "nonmemory_operand" "")))
519	      (clobber (reg:CC UNKNOWN_REGNUM))])]
520  "(REG_P (operands[1]) && !reg_overlap_mentioned_p (operands[0], operands[1]))
521   || RTX_OK_FOR_OFFSET_P (<MODE>mode, operands[1])"
522  [(set (match_dup 0) (reg:SI GPR_SP))
523   (set (mem:WMODE (post_modify (match_dup 0)
524				(plus:SI (match_dup 0) (match_dup 1))))
525	(reg:WMODE GPR_SP))]
526  "")
527
528
529
530(define_peephole2
531  [(parallel [(set (match_operand:SI 0 "gpr_operand" "")
532		   (plus:SI (reg:SI GPR_FP)
533			    (match_operand:SI 1 "nonmemory_operand" "")))
534	      (clobber (reg:CC UNKNOWN_REGNUM))])
535   (match_scratch:WMODE 2 "r")]
536  "frame_pointer_needed
537   && ((REG_P (operands[1])
538	&& !reg_overlap_mentioned_p (operands[0], operands[1]))
539       || RTX_OK_FOR_OFFSET_P (<MODE>mode, operands[1]))"
540  [(set (match_dup 0) (reg:SI GPR_FP))
541   (set (match_dup 2)
542	(mem:WMODE (post_modify (match_dup 0)
543				(plus:SI (match_dup 0) (match_dup 1)))))]
544  "")
545
546(define_expand "subsi3"
547  [(set (match_operand:SI 0 "gpr_operand" "")
548	(plus:SI (match_operand:SI 1 "add_reg_operand" "")
549		 (match_operand:SI 2 "arith_operand" "")))]
550  ""
551  "
552{
553  gcc_assert (!reload_in_progress && !reload_completed);
554
555  if (TARGET_FP_IARITH)
556    emit_insn (gen_isub (operands[0], operands[1], operands[2]));
557  else
558    emit_insn (gen_subsi3_i (operands[0], operands[1], operands[2]));
559  DONE;
560}")
561
562(define_insn "subsi3_i"
563  [(set (match_operand:SI 0 "gpr_operand" "=r")
564	(minus:SI (match_operand:SI 1 "add_reg_operand" "r")
565		  (match_operand:SI 2 "arith_operand" "rL")))
566   (clobber (reg:CC CC_REGNUM))]
567  ""
568  "sub %0,%1,%2"
569  [(set_attr "type" "misc")])
570
571; After mode-switching, floating point operations, fp_sfuncs and calls
572; must exhibit the use of the control register, lest the setting of the
573; control register could be deleted or moved.  OTOH a use of a hard register
574; greatly coundounds optimizers like the rtl loop optimizers or combine.
575; Therefore, we put an extra pass immediately after the mode switching pass
576; that inserts the USEs of the control registers, and sets a flag in struct
577; machine_function that float_operation can henceforth only match with that
578; USE.
579
580;; Addition
581(define_expand "addsf3"
582  [(parallel
583     [(set (match_operand:SF 0 "gpr_operand" "")
584	   (plus:SF (match_operand:SF 1 "gpr_operand" "")
585		    (match_operand:SF 2 "gpr_operand" "")))
586      (clobber (reg:CC_FP CCFP_REGNUM))])])
587
588(define_insn "*addsf3_i"
589  [(match_parallel 3 "float_operation"
590     [(set (match_operand:SF 0 "gpr_operand" "=r")
591	   (plus:SF (match_operand:SF 1 "gpr_operand" "%r")
592		    (match_operand:SF 2 "gpr_operand" "r")))
593      (clobber (reg:CC_FP CCFP_REGNUM))])]
594  ""
595  "fadd %0,%1,%2"
596  [(set_attr "type" "fp")])
597
598;; Subtraction
599(define_expand "subsf3"
600  [(parallel
601     [(set (match_operand:SF 0 "gpr_operand" "")
602	   (minus:SF (match_operand:SF 1 "gpr_operand" "")
603		     (match_operand:SF 2 "gpr_operand" "")))
604      (clobber (reg:CC_FP CCFP_REGNUM))])])
605
606(define_insn "*subsf3_i"
607  [(match_parallel 3 "float_operation"
608     [(set (match_operand:SF 0 "gpr_operand" "=r")
609	   (minus:SF (match_operand:SF 1 "gpr_operand" "r")
610		     (match_operand:SF 2 "gpr_operand" "r")))
611      (clobber (reg:CC_FP CCFP_REGNUM))])]
612  ""
613  "fsub %0,%1,%2"
614  [(set_attr "type" "fp")])
615
616(define_expand "subsf3_f"
617  [(parallel
618     [(set (reg:CC_FP CCFP_REGNUM)
619	   (compare:CC_FP (match_operand:SF 1 "gpr_operand" "r")
620			  (match_operand:SF 2 "gpr_operand" "r")))
621      (set (match_operand:SF 0 "gpr_operand" "=r")
622	   (minus:SF (match_dup 1) (match_dup 2)))])]
623  "!TARGET_SOFT_CMPSF")
624
625(define_insn "*subsf3_f_i"
626  [(match_parallel 3 "float_operation"
627     [(set (reg:CC_FP CCFP_REGNUM)
628	   (compare:CC_FP (match_operand:SF 1 "gpr_operand" "r")
629			  (match_operand:SF 2 "gpr_operand" "r")))
630      (set (match_operand:SF 0 "gpr_operand" "=r")
631	   (minus:SF (match_dup 1) (match_dup 2)))])]
632  "!TARGET_SOFT_CMPSF"
633  "fsub %0,%1,%2"
634  [(set_attr "type" "fp")])
635
636; There is an fabs instruction, but it has longer latency.
637(define_expand "abssf2"
638  [(set (match_operand:SF 0 "gpr_operand" "")
639	(abs:SF (match_operand:SF 1 "gpr_operand" "")))]
640  ""
641  "
642{
643  rtx op1 = copy_to_mode_reg (SImode, simplify_gen_subreg (SImode, operands[1],
644							   SFmode, 0));
645  rtx op0 = simplify_gen_subreg (SImode, operands[0], SFmode, 0);
646
647  emit_insn (gen_ashlsi3 (op1, op1, const1_rtx));
648  emit_insn (gen_lshrsi3 (op0, op1, const1_rtx));
649  DONE;
650}")
651
652;; Multiplication
653(define_expand "mulsf3"
654  [(parallel
655     [(set (match_operand:SF 0 "gpr_operand" "")
656	   (mult:SF (match_operand:SF 1 "gpr_operand" "")
657		    (match_operand:SF 2 "gpr_operand" "")))
658      (clobber (reg:CC_FP CCFP_REGNUM))])])
659
660(define_insn "*mulsf3_i"
661  [(match_parallel 3 "float_operation"
662     [(set (match_operand:SF 0 "gpr_operand" "=r")
663	   (mult:SF (match_operand:SF 1 "gpr_operand" "%r")
664		    (match_operand:SF 2 "gpr_operand" "r")))
665      (clobber (reg:CC_FP CCFP_REGNUM))])]
666  ""
667  "fmul %0,%1,%2"
668  [(set_attr "type" "fp")])
669
670;; Division
671(define_expand "divsf3"
672  [(set (match_operand:SF 0 "gpr_operand" "")
673	(div:SF (match_operand:SF 1 "gpr_operand" "")
674		(match_operand:SF 2 "gpr_operand" "")))]
675  "flag_reciprocal_math"
676{
677  rtx one = CONST1_RTX (SFmode);
678  rtx dst = operands[0];
679
680  if (rtx_equal_p (dst, operands[1]))
681    {
682      emit_move_insn (dst, one);
683      DONE;
684    }
685  else if (!register_operand (dst, SFmode) && can_create_pseudo_p ())
686    dst = gen_reg_rtx (SFmode);
687  emit_insn (gen_recipsf2 (dst, one, operands[2],
688			   sfunc_symbol (\"__fast_recipsf2\")));
689  emit_insn (gen_mulsf3 (operands[0], operands[1], dst));
690  DONE;
691})
692
693;; Before reload, keep the hard reg usage to clobbers so that the loop
694;; optimizers can more easily move this insn.
695;; It would be nicer to use a constraint for a GPR_0 - only register class,
696;; but sched1 can still cause trouble then, and there is no guarantee of
697;; better register allocations.
698;; Neither is there when using the opposite strategy - putting explicit
699;; hard register references into pre-reload rtl.
700(define_expand "recipsf2"
701  [(parallel
702     [(set (match_operand:SF 0 "gpr_operand" "")
703	   (div:SF (match_operand:SF 1 "const_float_1_operand" "")
704		   (match_operand:SF 2 "move_src_operand" "")))
705      (use (match_operand:SI 3 "move_src_operand" ""))
706      (clobber (reg:SF 0))
707      (clobber (reg:SI 1))
708      (clobber (reg:SF GPR_IP))
709      (clobber (reg:DI GPR_16))
710      (clobber (reg:DI GPR_18))
711      (clobber (reg:SI GPR_20))
712      (clobber (reg:SI GPR_LR))
713      (clobber (reg:CC CC_REGNUM))
714      (clobber (reg:CC_FP CCFP_REGNUM))])])
715
716(define_insn_and_split "*recipsf2_1"
717  [(match_parallel 4 "float_operation"
718     [(set (match_operand:SF 0 "gpr_operand" "=r,r")
719	   (div:SF (match_operand:SF 1 "const_float_1_operand" "")
720		   (match_operand:SF 2 "move_src_operand" "rU16m,rU16mCal")))
721      (use (match_operand:SI 3 "move_src_operand" "rU16m,rU16mCal"))
722      (clobber (reg:SF 0))
723      (clobber (reg:SI 1))
724      (clobber (reg:SF GPR_IP))
725      (clobber (reg:DI GPR_16))
726      (clobber (reg:DI GPR_18))
727      (clobber (reg:SI GPR_20))
728      (clobber (reg:SI GPR_LR))
729      (clobber (reg:CC CC_REGNUM))
730      (clobber (reg:CC_FP CCFP_REGNUM))])]
731  "flag_reciprocal_math"
732  "#"
733  "&& reload_completed"
734  [(set (reg:SI 1) (match_dup 3))
735   (set (reg:SF 0) (match_dup 2))
736   (parallel
737     [(set (reg:SF 0)
738	   (div:SF (match_dup 1)
739		   (reg:SF 0)))
740      (use (reg:SI 1))
741      (clobber (reg:SI GPR_IP))
742      (clobber (reg:DI GPR_16))
743      (clobber (reg:DI GPR_18))
744      (clobber (reg:SI GPR_20))
745      (clobber (reg:SI GPR_LR))
746      (clobber (reg:CC CC_REGNUM))
747      (clobber (reg:CC_FP CCFP_REGNUM))
748      (match_dup 5)
749      (match_dup 6)])
750   (set (match_dup 0) (reg:SF 0))]
751  "operands[5] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);
752   operands[6] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);"
753  [(set_attr "type" "fp_sfunc")
754   (set_attr "length" "16,24")])
755
756(define_insn "*recipsf2_2"
757  [(match_parallel 1 "float_operation"
758     [(set (reg:SF 0)
759	   (div:SF (match_operand:SF 0 "const_float_1_operand" "")
760		   (reg:SF 0)))
761      (use (reg:SI 1))
762      (clobber (reg:SI GPR_IP))
763      (clobber (reg:DI GPR_16))
764      (clobber (reg:DI GPR_18))
765      (clobber (reg:SI GPR_20))
766      (clobber (reg:SI GPR_LR))
767      (clobber (reg:CC CC_REGNUM))
768      (clobber (reg:CC_FP CCFP_REGNUM))])]
769  "flag_reciprocal_math"
770  "jalr r1"
771  [(set_attr "type" "fp_sfunc")])
772
773
774;; Fused multiply-add
775(define_expand "fmasf4"
776  [(parallel
777     [(set (match_operand:SF 0 "gpr_operand" "")
778	   (fma:SF (match_operand:SF 1 "gpr_operand" "")
779		   (match_operand:SF 2 "gpr_operand" "")
780		   (match_operand:SF 3 "gpr_operand" "")))
781      (clobber (reg:CC_FP CCFP_REGNUM))])]
782  "")
783
784; The multiply operands are commutative, but since they have the
785; same constraints, there is no point in telling reload about this.
786(define_insn "*fmadd"
787  [(match_parallel 4 "float_operation"
788     [(set (match_operand:SF 0 "gpr_operand" "=r")
789	   (fma:SF (match_operand:SF 1 "gpr_operand" "r")
790		   (match_operand:SF 2 "gpr_operand" "r")
791		   (match_operand:SF 3 "gpr_operand" "0")))
792      (clobber (reg:CC_FP CCFP_REGNUM))])]
793  ""
794  "fmadd %0,%1,%2"
795  [(set_attr "type" "fp")])
796
797; Once vetorization consistently works for this port, should check
798; if the fmadd / fmsub patterns still serve a purpose.  With the
799; introduction of fma / fnma handling by the SSA optimizers,
800; at least scalars should be handled by these optimizers, would
801; have to see how well they do on vectors from auto-vectorization.
802;
803; combiner pattern, also used by vector combiner pattern
804(define_expand "maddsf"
805  [(parallel
806     [(set (match_operand:SF 0 "gpr_operand" "=r")
807	   (plus:SF (mult:SF (match_operand:SF 1 "gpr_operand" "r")
808			     (match_operand:SF 2 "gpr_operand" "r"))
809		    (match_operand:SF 3 "gpr_operand" "0")))
810      (clobber (reg:CC_FP CCFP_REGNUM))])]
811  "TARGET_FUSED_MADD")
812
813(define_insn "*maddsf_combine"
814  [(match_parallel 4 "float_operation"
815     [(set (match_operand:SF 0 "gpr_operand" "=r")
816	   (plus:SF (mult:SF (match_operand:SF 1 "gpr_operand" "r")
817			     (match_operand:SF 2 "gpr_operand" "r"))
818		    (match_operand:SF 3 "gpr_operand" "0")))
819      (clobber (reg:CC_FP CCFP_REGNUM))])]
820  "TARGET_FUSED_MADD"
821  "fmadd %0,%1,%2"
822  [(set_attr "type" "fp")])
823
824;; Fused multiply-sub
825(define_expand "fnmasf4"
826  [(parallel
827     [(set (match_operand:SF 0 "gpr_operand" "")
828	   (fma:SF (neg:SF (match_operand:SF 1 "gpr_operand" ""))
829		   (match_operand:SF 2 "gpr_operand" "")
830		   (match_operand:SF 3 "gpr_operand" "")))
831      (clobber (reg:CC_FP CCFP_REGNUM))])]
832  "")
833
834(define_insn "*fmsub"
835  [(match_parallel 4 "float_operation"
836     [(set (match_operand:SF 0 "gpr_operand" "=r")
837	   (fma:SF (neg:SF (match_operand:SF 1 "gpr_operand" "r"))
838		   (match_operand:SF 2 "gpr_operand" "r")
839		   (match_operand:SF 3 "gpr_operand" "0")))
840      (clobber (reg:CC_FP CCFP_REGNUM))])]
841  ""
842  "fmsub %0,%1,%2"
843  [(set_attr "type" "fp")])
844
845(define_insn "*fmsub_combine"
846  [(match_parallel 4 "float_operation"
847     [(set (match_operand:SF 0 "gpr_operand" "=r")
848	   (minus:SF  (match_operand:SF 3 "gpr_operand" "0")
849		      (mult:SF (match_operand:SF 1 "gpr_operand" "r")
850			       (match_operand:SF 2 "gpr_operand" "r"))))
851      (clobber (reg:CC_FP CCFP_REGNUM))])]
852  "TARGET_FUSED_MADD"
853  "fmsub %0,%1,%2"
854  [(set_attr "type" "fp")])
855
856;; float / integer conversions
857
858(define_expand "floatsisf2"
859  [(parallel
860     [(set (match_operand:SF 0 "gpr_operand" "")
861	   (float:SF (match_operand:SI 1 "gpr_operand" "")))
862      (clobber (reg:CC_FP CCFP_REGNUM))])])
863
864(define_insn "*floatsisf2_i"
865  [(match_parallel 2 "float_operation"
866     [(set (match_operand:SF 0 "gpr_operand" "=r")
867	   (float:SF (match_operand:SI 1 "gpr_operand" "r")))
868      (clobber (reg:CC_FP CCFP_REGNUM))])]
869  ""
870  "float %0, %1"
871  [(set_attr "type" "fp")])
872
873(define_expand "floatsisf2_cmp"
874  [(parallel
875     [(set (reg:CC_FP CCFP_REGNUM)
876	   (compare:CC_FP (float:SF (match_operand:SF 1 "gpr_operand" "r"))
877			  (match_dup 2)))
878      (set (match_operand:SF 0 "gpr_operand" "=r")
879	   (float:SF (match_dup 1)))])]
880  ""
881  "operands[2] = CONST0_RTX (SFmode);")
882
883(define_insn "*floatsisf2_cmp_i"
884  [(match_parallel 3 "float_operation"
885     [(set (reg:CC_FP CCFP_REGNUM)
886	   (compare:CC_FP (float:SF (match_operand:SF 1 "gpr_operand" "r"))
887			  (match_operand:SF 2 "const0_operand" "")))
888      (set (match_operand:SF 0 "gpr_operand" "=r")
889	   (float:SF (match_dup 1)))])]
890  ""
891  "float %0, %1"
892  [(set_attr "type" "fp")])
893
894(define_expand "floatunssisf2"
895  [(set (match_operand:SF 0 "gpr_operand" "")
896	(float:SF (match_operand:SI 1 "gpr_operand" "")))]
897  "epiphany_normal_fp_rounding == /*FP_MODE_ROUND_TRUNC*/ 2"
898{
899  rtx cst = force_reg (SImode, gen_int_mode (0xb0800000, SImode));
900  rtx tmp = gen_reg_rtx (SImode);
901  rtx cmp = gen_rtx_GTU (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx);
902
903  if (reg_overlap_mentioned_p (operands[0], operands[1]))
904    operands[1] = copy_to_mode_reg (SImode, operands[1]);
905  emit_insn (gen_floatsisf2 (operands[0], operands[1]));
906  emit_insn (gen_ashrsi3 (tmp, operands[1], GEN_INT (8)));
907  emit_insn (gen_sub_f (tmp, tmp, cst));
908  emit_insn (gen_movsfcc (operands[0], cmp,
909			  simplify_gen_subreg (SFmode, tmp, SImode, 0),
910			  operands[0]));
911  DONE;
912})
913
914(define_expand "fix_truncsfsi2"
915  [(parallel
916     [(set (match_operand:SI 0 "gpr_operand" "")
917	   (fix:SI (match_operand:SF 1 "gpr_operand" "")))
918      (clobber (reg:CC_FP CCFP_REGNUM))])])
919
920(define_insn "*fix_truncsfsi2_i"
921  [(match_parallel 2 "float_operation"
922     [(set (match_operand:SI 0 "gpr_operand" "=r")
923	   (fix:SI (match_operand:SF 1 "gpr_operand" "r")))
924      (clobber (reg:CC_FP CCFP_REGNUM))])]
925  ""
926  "fix %0, %1"
927  [(set_attr "type" "fp")
928   (set (attr "fp_mode")
929	(cond [(match_test "TARGET_MAY_ROUND_FOR_TRUNC")
930	       (const_string "round_unknown")]
931	      (const_string "round_trunc")))])
932
933(define_expand "fixuns_truncsfsi2"
934  [(set (match_operand:SI 0 "gpr_operand" "")
935	(unsigned_fix:SI (match_operand:SF 1 "gpr_operand" "")))]
936  ""
937{
938  if (reg_overlap_mentioned_p (operands[0], operands[1]))
939    operands[1] = copy_to_mode_reg (SImode, operands[1]);
940  if (TARGET_SOFT_CMPSF || optimize_function_for_speed_p (cfun))
941    {
942      rtx op1si;
943      /* By toggling what it to be bit31 before the shift, we get a chance to
944	 use a short movt insn.  */
945      rtx bit31 = force_reg (SImode, GEN_INT (0x800000));
946      rtx tmp = gen_reg_rtx (SImode);
947      rtx limit = force_reg (SImode, gen_int_mode (0x4f000000, SImode));
948      rtx cmp
949	= gen_rtx_GE (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx);
950
951      op1si = simplify_gen_subreg (SImode, operands[1], SFmode, 0);
952      emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1]));
953      emit_insn (gen_subsi3_i (tmp, op1si, bit31));
954      emit_insn (gen_ashlsi3 (tmp, tmp, GEN_INT (8)));
955      emit_insn (gen_cmpsi_cc_insn (op1si, limit));
956      emit_insn (gen_movsicc (operands[0], cmp, tmp, operands[0]));
957    }
958  else
959    {
960      REAL_VALUE_TYPE offset;
961      rtx limit;
962      rtx tmp = gen_reg_rtx (SFmode);
963      rtx label = gen_label_rtx ();
964      rtx bit31;
965      rtx cc1 = gen_rtx_REG (CC_FPmode, CCFP_REGNUM);
966      rtx cmp = gen_rtx_LT (VOIDmode, cc1, CONST0_RTX (SFmode));
967
968      real_2expN (&offset, 31, SFmode);
969      limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode);
970      limit = force_reg (SFmode, limit);
971      emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1]));
972      emit_insn (gen_subsf3_f (tmp, operands[1], limit));
973      emit_jump_insn (gen_branch_insn (label, cmp, cc1));
974      bit31 = force_reg (SImode, gen_int_mode (0x80000000, SImode));
975      emit_insn (gen_fix_truncsfsi2 (operands[0], tmp));
976      emit_insn (gen_xorsi3 (operands[0], operands[0], bit31));
977      emit_label (label);
978    }
979  DONE;
980})
981
982(define_expand "iadd"
983  [(parallel
984     [(set (match_operand:SF 0 "gpr_operand" "")
985	   (plus:SI (match_operand:SF 1 "gpr_operand" "")
986		    (match_operand:SF 2 "gpr_operand" "")))
987      (clobber (reg:CC_FP CCFP_REGNUM))])])
988
989(define_insn "*iadd_i"
990  [(match_parallel 3 "float_operation"
991     [(set (match_operand:SI 0 "gpr_operand" "=r")
992	   (plus:SI (match_operand:SI 1 "gpr_operand" "%r")
993		    (match_operand:SI 2 "gpr_operand" "r")))
994      (clobber (reg:CC_FP CCFP_REGNUM))])]
995  ""
996  "iadd %0, %1, %2"
997  [(set_attr "type" "fp_int")])
998
999(define_expand "isub"
1000  [(parallel
1001     [(set (match_operand:SF 0 "gpr_operand" "")
1002	   (minus:SI (match_operand:SF 1 "gpr_operand" "")
1003		     (match_operand:SF 2 "gpr_operand" "")))
1004      (clobber (reg:CC_FP CCFP_REGNUM))])])
1005
1006(define_insn "*isub_i"
1007  [(match_parallel 3 "float_operation"
1008     [(set (match_operand:SI 0 "gpr_operand" "=r")
1009	   (minus:SI (match_operand:SI 1 "gpr_operand" "r")
1010		     (match_operand:SI 2 "gpr_operand" "r")))
1011      (clobber (reg:CC_FP CCFP_REGNUM))])]
1012  ""
1013  "isub %0, %1, %2"
1014  [(set_attr "type" "fp_int")])
1015
1016; Try to figure out if we over-committed the FPU, and if so, move
1017; some insns back over to the integer pipe.
1018
1019; The peephole optimizer 'consumes' the insns that are explicitly
1020; mentioned.  We do not want the preceding insn reconsidered, but
1021; we do want that for the following one, so that if we have a run
1022; of five fpu users, two of them get changed.  Therefore, we
1023; use next_active_insn to look at the 'following' insn.  That should
1024; exist, because peephole2 runs after reload, and there has to be
1025; a return after an fp_int insn.
1026; ??? However, we can not even ordinarily match the preceding insn;
1027; there is some bug in the generators such that then it leaves out
1028; the check for PARALLEL before the length check for the then-second
1029; main insn.  Observed when compiling compatibility-atomic-c++0x.cc
1030; from libstdc++-v3.
1031(define_peephole2
1032  [(match_parallel 3 "float_operation"
1033     [(set (match_operand:SI 0 "gpr_operand" "")
1034	   (match_operator:SI 4 "addsub_operator"
1035	     [(match_operand:SI 1 "gpr_operand" "")
1036	      (match_operand:SI 2 "gpr_operand" "")]))
1037      (clobber (reg:CC_FP CCFP_REGNUM))])]
1038  "get_attr_sched_use_fpu (prev_active_insn (peep2_next_insn (0)))
1039   && peep2_regno_dead_p (1, CC_REGNUM)
1040   && get_attr_sched_use_fpu (next_active_insn (peep2_next_insn (0)))"
1041  [(parallel [(set (match_dup 0) (match_dup 4))
1042	      (clobber (reg:CC CC_REGNUM))])]
1043)
1044
1045(define_expand "mulsi3"
1046  [(parallel
1047     [(set (match_operand:SI 0 "gpr_operand" "")
1048	   (mult:SI (match_operand:SI 1 "gpr_operand" "")
1049		    (match_operand:SI 2 "gpr_operand" "")))
1050      (clobber (reg:CC_FP CCFP_REGNUM))])])
1051
1052(define_insn "*imul"
1053  [(match_parallel 3 "float_operation"
1054     [(set (match_operand:SI 0 "gpr_operand" "=r")
1055	   (mult:SI (match_operand:SI 1 "gpr_operand" "%r")
1056		    (match_operand:SI 2 "gpr_operand" "r")))
1057      (clobber (reg:CC_FP CCFP_REGNUM))])]
1058  ""
1059  "imul %0, %1, %2"
1060  [(set_attr "type" "fp_int")])
1061
1062; combiner pattern, also used by vector combiner pattern
1063(define_expand "maddsi"
1064  [(parallel
1065     [(set (match_operand:SI 0 "gpr_operand" "=r")
1066	   (plus:SI (mult:SI (match_operand:SI 1 "gpr_operand" "r")
1067			     (match_operand:SI 2 "gpr_operand" "r"))
1068		    (match_operand:SI 3 "gpr_operand" "0")))
1069      (clobber (reg:CC_FP CCFP_REGNUM))])]
1070  "")
1071
1072(define_insn "*maddsi_combine"
1073  [(match_parallel 4 "float_operation"
1074     [(set (match_operand:SI 0 "gpr_operand" "=r")
1075	   (plus:SI (mult:SI (match_operand:SI 1 "gpr_operand" "r")
1076			     (match_operand:SI 2 "gpr_operand" "r"))
1077		    (match_operand:SI 3 "gpr_operand" "0")))
1078      (clobber (reg:CC_FP CCFP_REGNUM))])]
1079  ""
1080  "imadd %0, %1, %2"
1081  [(set_attr "type" "fp_int")])
1082
1083(define_insn "*imsub"
1084  [(match_parallel 4 "float_operation"
1085     [(set (match_operand:SI 0 "gpr_operand" "=r")
1086	   (minus:SI (match_operand:SI 3 "gpr_operand" "0")
1087		     (mult:SI (match_operand:SI 1 "gpr_operand" "r")
1088			      (match_operand:SI 2 "gpr_operand" "r"))))
1089      (clobber (reg:CC_FP CCFP_REGNUM))])]
1090  ""
1091  "imsub %0, %1, %2"
1092  [(set_attr "type" "fp_int")])
1093
1094(define_expand "divsi3"
1095  [(parallel
1096     [(set (match_operand:SI 0 "move_dest_operand" "")
1097	   (div:SI (match_operand:SI 1 "move_src_operand" "")
1098		   (match_operand:SI 2 "move_src_operand" "")))
1099      (use (match_dup 3))
1100      (clobber (reg:SI 0))
1101      (clobber (reg:SI 1))
1102      (clobber (reg:SI GPR_IP))
1103      (clobber (reg:DI GPR_16))
1104      (clobber (reg:DI GPR_18))
1105      (clobber (reg:SI GPR_20))
1106      (clobber (reg:SI GPR_LR))
1107      (clobber (reg:CC CC_REGNUM))
1108      (clobber (reg:CC_FP CCFP_REGNUM))])]
1109  ""
1110  "operands[3] = sfunc_symbol (\"__divsi3\");")
1111
1112;; Before reload, keep the hard reg usage to clobbers so that the loop
1113;; optimizers can more easily move this insn.
1114(define_insn_and_split "*divsi3_1"
1115  [(match_parallel 4 "float_operation"
1116     [(set (match_operand:SI 0 "move_dest_operand" "=r,r")
1117	   (div:SI (match_operand:SI 1 "move_src_operand" "rU16m,rU16mCal")
1118		   (match_operand:SI 2 "move_src_operand" "rU16m,rU16mCal")))
1119      (use (match_operand:SI 3 "call_address_operand" "Csy,r"))
1120      (clobber (reg:SI 0))
1121      (clobber (reg:SI 1))
1122      (clobber (reg:SI GPR_IP))
1123      (clobber (reg:DI GPR_16))
1124      (clobber (reg:DI GPR_18))
1125      (clobber (reg:SI GPR_20))
1126      (clobber (reg:SI GPR_LR))
1127      (clobber (reg:CC CC_REGNUM))
1128      (clobber (reg:CC_FP CCFP_REGNUM))])]
1129  ""
1130  "#"
1131  "&& reload_completed"
1132  [(set (reg:SI 0) (match_dup 1))
1133   (set (reg:SI 1) (match_dup 2))
1134   (parallel
1135     [(set (reg:SI 0) (div:SI (reg:SI 0) (reg:SI 1)))
1136      (use (match_dup 3))
1137      (clobber (reg:SI 1))
1138      (clobber (reg:SI GPR_IP))
1139      (clobber (reg:DI GPR_16))
1140      (clobber (reg:DI GPR_18))
1141      (clobber (reg:SI GPR_20))
1142      (clobber (reg:SI GPR_LR))
1143      (clobber (reg:CC CC_REGNUM))
1144      (clobber (reg:CC_FP CCFP_REGNUM))
1145      (match_dup 5)
1146      (match_dup 6)])
1147   (set (match_dup 0) (reg:SI 0))]
1148  "operands[5] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);
1149   operands[6] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);"
1150  [(set_attr "type" "fp_sfunc")
1151   (set_attr "length" "16,24")])
1152
1153(define_insn "*divsi3_2"
1154  [(match_parallel 1 "float_operation"
1155     [(set (reg:SI 0) (div:SI (reg:SI 0) (reg:SI 1)))
1156      (use (match_operand:SI 0 "call_address_operand" "Csy,r"))
1157      (clobber (reg:SI 1))
1158      (clobber (reg:SI GPR_IP))
1159      (clobber (reg:DI GPR_16))
1160      (clobber (reg:DI GPR_18))
1161      (clobber (reg:SI GPR_20))
1162      (clobber (reg:SI GPR_LR))
1163      (clobber (reg:CC CC_REGNUM))
1164      (clobber (reg:CC_FP CCFP_REGNUM))])]
1165  ""
1166  "%f0"
1167  [(set_attr "type" "fp_sfunc")])
1168
1169(define_expand "udivsi3"
1170  [(parallel
1171     [(set (match_operand:SI 0 "move_dest_operand" "")
1172	   (udiv:SI (match_operand:SI 1 "move_src_operand" "")
1173		    (match_operand:SI 2 "move_src_operand" "")))
1174      (use (match_dup 3))
1175      (clobber (reg:SI 0))
1176      (clobber (reg:SI 1))
1177      (clobber (reg:SI GPR_IP))
1178      (clobber (reg:DI GPR_16))
1179      (clobber (reg:SI GPR_18))
1180      (clobber (reg:SI GPR_LR))
1181      (clobber (reg:CC CC_REGNUM))
1182      (clobber (reg:CC_FP CCFP_REGNUM))])]
1183  ""
1184  "operands[3] = sfunc_symbol (\"__udivsi3\");")
1185
1186;; Before reload, keep the hard reg usage to clobbers so that the loop
1187;; optimizers can more easily move this insn.
1188(define_insn_and_split "*udivsi3_1"
1189  [(match_parallel 4 "float_operation"
1190     [(set (match_operand:SI 0 "move_dest_operand" "=r,r")
1191	   (udiv:SI (match_operand:SI 1 "move_src_operand" "rU16m,rU16mCal")
1192		    (match_operand:SI 2 "move_src_operand" "rU16m,rU16mCal")))
1193      (use (match_operand:SI 3 "call_address_operand" "Csy,r"))
1194      (clobber (reg:SI 0))
1195      (clobber (reg:SI 1))
1196      (clobber (reg:SI GPR_IP))
1197      (clobber (reg:DI GPR_16))
1198      (clobber (reg:SI GPR_18))
1199      (clobber (reg:SI GPR_LR))
1200      (clobber (reg:CC CC_REGNUM))
1201      (clobber (reg:CC_FP CCFP_REGNUM))])]
1202  ""
1203  "#"
1204  "&& reload_completed"
1205  [(set (reg:SI 0) (match_dup 1))
1206   (set (reg:SI 1) (match_dup 2))
1207   (parallel
1208     [(set (reg:SI 0) (udiv:SI (reg:SI 0) (reg:SI 1)))
1209      (use (match_dup 3))
1210      (clobber (reg:SI 1))
1211      (clobber (reg:SI GPR_IP))
1212      (clobber (reg:DI GPR_16))
1213      (clobber (reg:SI GPR_18))
1214      (clobber (reg:SI GPR_LR))
1215      (clobber (reg:CC CC_REGNUM))
1216      (clobber (reg:CC_FP CCFP_REGNUM))
1217      (match_dup 5)
1218      (match_dup 6)])
1219   (set (match_dup 0) (reg:SI 0))]
1220  "operands[5] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);
1221   operands[6] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);"
1222  [(set_attr "type" "fp_sfunc")
1223   (set_attr "length" "16,24")])
1224
1225(define_insn "*udivsi3_2"
1226  [(match_parallel 1 "float_operation"
1227     [(set (reg:SI 0) (udiv:SI (reg:SI 0) (reg:SI 1)))
1228      (use (match_operand:SI 0 "call_address_operand" "Csy,r"))
1229      (clobber (reg:SI 1))
1230      (clobber (reg:SI GPR_IP))
1231      (clobber (reg:DI GPR_16))
1232      (clobber (reg:SI GPR_18))
1233      (clobber (reg:SI GPR_LR))
1234      (clobber (reg:CC CC_REGNUM))
1235      (clobber (reg:CC_FP CCFP_REGNUM))])]
1236  ""
1237  "%f0"
1238  [(set_attr "type" "fp_sfunc")])
1239
1240(define_expand "modsi3"
1241  [(parallel
1242     [(set (match_operand:SI 0 "move_dest_operand" "")
1243	   (mod:SI (match_operand:SI 1 "move_src_operand" "")
1244		   (match_operand:SI 2 "move_src_operand" "")))
1245      (use (match_dup 3))
1246      (clobber (reg:SI 0))
1247      (clobber (reg:SI 1))
1248      (clobber (reg:SI 2))
1249      (clobber (reg:SI GPR_IP))
1250      (clobber (reg:DI GPR_16))
1251      (clobber (reg:DI GPR_18))
1252      (clobber (reg:SI GPR_LR))
1253      (clobber (reg:CC CC_REGNUM))
1254      (clobber (reg:CC_FP CCFP_REGNUM))])]
1255  ""
1256  "operands[3] = sfunc_symbol (\"__modsi3\");")
1257
1258;; Before reload, keep the hard reg usage to clobbers so that the loop
1259;; optimizers can more easily move this insn.
1260(define_insn_and_split "*modsi3_1"
1261  [(match_parallel 4 "float_operation"
1262     [(set (match_operand:SI 0 "move_dest_operand" "=r,r")
1263	   (mod:SI (match_operand:SI 1 "move_src_operand" "rU16m,rU16mCal")
1264		   (match_operand:SI 2 "move_src_operand" "rU16m,rU16mCal")))
1265      (use (match_operand:SI 3 "call_address_operand" "Csy,r"))
1266      (clobber (reg:SI 0))
1267      (clobber (reg:SI 1))
1268      (clobber (reg:SI 2))
1269      (clobber (reg:SI GPR_IP))
1270      (clobber (reg:DI GPR_16))
1271      (clobber (reg:DI GPR_18))
1272      (clobber (reg:SI GPR_LR))
1273      (clobber (reg:CC CC_REGNUM))
1274      (clobber (reg:CC_FP CCFP_REGNUM))])]
1275  ""
1276  "#"
1277  "&& reload_completed"
1278  [(set (reg:SI 0) (match_dup 1))
1279   (set (reg:SI 1) (match_dup 2))
1280   (parallel
1281     [(set (reg:SI 0) (mod:SI (reg:SI 0) (reg:SI 1)))
1282      (use (match_dup 3))
1283      (clobber (reg:SI 2))
1284      (clobber (reg:SI GPR_IP))
1285      (clobber (reg:DI GPR_16))
1286      (clobber (reg:DI GPR_18))
1287      (clobber (reg:SI GPR_LR))
1288      (clobber (reg:CC CC_REGNUM))
1289      (clobber (reg:CC_FP CCFP_REGNUM))
1290      (match_dup 5)
1291      (match_dup 6)])
1292   (set (match_dup 0) (reg:SI 0))]
1293  "operands[5] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);
1294   operands[6] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);"
1295  [(set_attr "type" "fp_sfunc")
1296   (set_attr "length" "16,24")])
1297
1298(define_insn "*modsi3_2"
1299  [(match_parallel 1 "float_operation"
1300     [(set (reg:SI 0) (mod:SI (reg:SI 0) (reg:SI 1)))
1301      (use (match_operand:SI 0 "call_address_operand" "Csy,r"))
1302      (clobber (reg:SI 2))
1303      (clobber (reg:SI GPR_IP))
1304      (clobber (reg:DI GPR_16))
1305      (clobber (reg:DI GPR_18))
1306      (clobber (reg:SI GPR_LR))
1307      (clobber (reg:CC CC_REGNUM))
1308      (clobber (reg:CC_FP CCFP_REGNUM))])]
1309  ""
1310  "%f0"
1311  [(set_attr "type" "fp_sfunc")])
1312
1313(define_expand "umodsi3"
1314  [(parallel
1315     [(set (match_operand:SI 0 "move_dest_operand" "")
1316	   (umod:SI (match_operand:SI 1 "move_src_operand" "")
1317		    (match_operand:SI 2 "move_src_operand" "")))
1318      (use (match_dup 3))
1319      (clobber (reg:SI 0))
1320      (clobber (reg:SI 1))
1321      (clobber (reg:SI 2))
1322      (clobber (reg:SI GPR_IP))
1323      (clobber (reg:DI GPR_16))
1324      (clobber (reg:SI GPR_LR))
1325      (clobber (reg:CC CC_REGNUM))
1326      (clobber (reg:CC_FP CCFP_REGNUM))])]
1327  ""
1328  "operands[3] = sfunc_symbol (\"__umodsi3\");")
1329
1330;; Before reload, keep the hard reg usage to clobbers so that the loop
1331;; optimizers can more easily move this insn.
1332(define_insn_and_split "*umodsi3_1"
1333  [(match_parallel 4 "float_operation"
1334     [(set (match_operand:SI 0 "move_dest_operand" "=r,r")
1335	   (umod:SI (match_operand:SI 1 "move_src_operand" "rU16m,rU16mCal")
1336		    (match_operand:SI 2 "move_src_operand" "rU16m,rU16mCal")))
1337      (use (match_operand:SI 3 "call_address_operand" "Csy,r"))
1338      (clobber (reg:SI 0))
1339      (clobber (reg:SI 1))
1340      (clobber (reg:SI 2))
1341      (clobber (reg:SI GPR_IP))
1342      (clobber (reg:DI GPR_16))
1343      (clobber (reg:SI GPR_LR))
1344      (clobber (reg:CC CC_REGNUM))
1345      (clobber (reg:CC_FP CCFP_REGNUM))])]
1346  ""
1347  "#"
1348  "&& reload_completed"
1349  [(set (reg:SI 0) (match_dup 1))
1350   (set (reg:SI 1) (match_dup 2))
1351   (parallel
1352     [(set (reg:SI 0) (umod:SI (reg:SI 0) (reg:SI 1)))
1353      (use (match_dup 3))
1354      (clobber (reg:SI 2))
1355      (clobber (reg:SI GPR_IP))
1356      (clobber (reg:DI GPR_16))
1357      (clobber (reg:SI GPR_LR))
1358      (clobber (reg:CC CC_REGNUM))
1359      (clobber (reg:CC_FP CCFP_REGNUM))
1360      (match_dup 5)
1361      (match_dup 6)])
1362   (set (match_dup 0) (reg:SI 0))]
1363  "operands[5] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);
1364   operands[6] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);"
1365  [(set_attr "type" "fp_sfunc")
1366   (set_attr "length" "16,24")])
1367
1368(define_insn "*umodsi3_2"
1369  [(match_parallel 1 "float_operation"
1370     [(set (reg:SI 0) (umod:SI (reg:SI 0) (reg:SI 1)))
1371      (use (match_operand:SI 0 "call_address_operand" "Csy,r"))
1372      (clobber (reg:SI 2))
1373      (clobber (reg:SI GPR_IP))
1374      (clobber (reg:DI GPR_16))
1375      (clobber (reg:SI GPR_LR))
1376      (clobber (reg:CC CC_REGNUM))
1377      (clobber (reg:CC_FP CCFP_REGNUM))])]
1378  ""
1379  "%f0"
1380  [(set_attr "type" "fp_sfunc")])
1381
1382; Disable interrupts.
1383; Any earlier values read from CONFIG_REGNUM are out of date, since interrupts
1384; might have changed settings that we do not want to mess with.
1385(define_insn "gid"
1386  [(set (reg:SI CONFIG_REGNUM)
1387	(unspec_volatile:SI [(const_int 0)] UNSPECV_GID))]
1388  ""
1389  "gid"
1390  [(set_attr "type" "flow")])
1391
1392; Enable interrupts.
1393; Present CONTROL_REGNUM here to make sure it is live before the
1394; actual uses in floating point insns / calls are inserted.
1395; FWIW, interrupts also do mind what is in the control register.
1396(define_insn "gie"
1397  [(unspec_volatile [(reg:SI CONFIG_REGNUM)] UNSPECV_GIE)]
1398  ""
1399  "gie"
1400  [(set_attr "type" "flow")])
1401
1402; Floating point instructions require manipulating the control register.
1403; Manipulating the control register needs aritmetic.
1404; Arithmetic clobbers flags.
1405; The flags are in the status register, which also contains the alternate
1406; flag and the interrupt enable/disable bits.
1407; saving/restoring status and mixing up the order with gid/gie could
1408; lead to disaster.
1409; Usually, saving/restoring the status is unnecessary, and will be optimized
1410; away.  But when we really need it, we must make sure that we don't change
1411; anything but the flags.
1412; N.B.: We could make the constant easier to load by inverting it, but
1413; then we'd need to clobber the saved value - and that would make optimizing
1414; away unneeded saves/restores harder / less likely.
1415(define_expand "movcc"
1416  [(parallel [(set (match_operand:CC 0 "cc_move_operand"  "")
1417		   (match_operand:CC 1 "cc_move_operand" ""))
1418	      (use (match_dup 2))
1419	      (clobber (match_scratch:SI 3                 "=X, &r"))])]
1420  ""
1421  "operands[2] = gen_int_mode (~0x10f0, SImode);")
1422
1423(define_insn "*movcc_i"
1424  [(set (match_operand:CC 0 "cc_move_operand"  "=r,Rcc")
1425	(match_operand:CC 1 "cc_move_operand" "Rcc,  r"))
1426   (use (match_operand:SI 2 "nonmemory_operand"  "X,  r"))
1427   (clobber (match_scratch:SI 3                 "=X, &r"))]
1428  ""
1429  "@
1430   movfs %0,status
1431   movfs %3,status\;eor %3,%3,%1\;and %3,%3,%2\;eor %3,%3,%1\;movts status,%3"
1432  [(set_attr "type" "flow")
1433   (set_attr "length" "20,4")])
1434
1435(define_insn_and_split "save_config"
1436  [(set (match_operand:SI 0 "gpr_operand" "=r") (reg:SI CONFIG_REGNUM))
1437   (use (reg:SI FP_NEAREST_REGNUM))
1438   (use (reg:SI FP_TRUNCATE_REGNUM))
1439   (use (reg:SI FP_ANYFP_REGNUM))]
1440  ""
1441  "#"
1442  "reload_completed"
1443  [(set (match_dup 0) (reg:SI CONFIG_REGNUM))])
1444
1445(define_insn_and_split "set_fp_mode"
1446  [(set (reg:SI FP_NEAREST_REGNUM)
1447	(match_operand:SI 0 "set_fp_mode_operand" "rCfm"))
1448   (set (reg:SI FP_TRUNCATE_REGNUM) (match_dup 0))
1449   (set (reg:SI FP_ANYFP_REGNUM)
1450	(match_operand:SI 1 "set_fp_mode_operand" "rCfm"))
1451   (use (match_operand:SI 2 "gpr_operand" "r"))
1452   (clobber (reg:CC CC_REGNUM))
1453   (clobber (match_scratch:SI 3 "=&r"))]
1454  ""
1455  "#"
1456  "reload_completed || !rtx_equal_p (operands[0], operands[1])"
1457  [(const_int 0)]
1458{
1459  if (!reload_completed)
1460    emit_note (NOTE_INSN_DELETED);
1461  else
1462    epiphany_expand_set_fp_mode (operands);
1463  DONE;
1464})
1465
1466
1467;; Boolean instructions.
1468;;
1469;; We don't define the DImode versions as expand_binop does a good enough job.
1470
1471(define_insn "andsi3"
1472  [(set (match_operand:SI 0 "gpr_operand" "=r")
1473	(and:SI (match_operand:SI 1 "gpr_operand" "r")
1474		(match_operand:SI 2 "gpr_operand" "r")))
1475   (clobber (reg:CC CC_REGNUM))]
1476  ""
1477  "and %0,%1,%2")
1478
1479(define_insn "iorsi3"
1480  [(set (match_operand:SI 0 "gpr_operand" "=r")
1481	(ior:SI (match_operand:SI 1 "gpr_operand" "r")
1482		(match_operand:SI 2 "gpr_operand" "r")))
1483   (clobber (reg:CC CC_REGNUM))]
1484  ""
1485  "orr %0,%1,%2")
1486
1487(define_insn "xorsi3"
1488  [(set (match_operand:SI 0 "gpr_operand" "=r")
1489	(xor:SI (match_operand:SI 1 "gpr_operand" "r")
1490		(match_operand:SI 2 "gpr_operand" "r")))
1491   (clobber (reg:CC CC_REGNUM))]
1492  ""
1493  "eor %0,%1,%2")
1494
1495(define_expand "one_cmplsi2"
1496  [(set (match_operand:SI 0 "gpr_operand" "")
1497	(xor:SI (match_operand:SI 1 "gpr_operand" "")
1498		(match_dup 2)))]
1499  ""
1500{
1501  if (epiphany_m1reg >= 0)
1502    emit_insn (gen_one_cmplsi2_i (operands[0], operands[1]));
1503  else
1504    emit_insn (gen_xorsi3 (operands[0], operands[1],
1505			   force_reg (SImode, GEN_INT (-1))));
1506  DONE;
1507})
1508
1509; Note that folding this pattern into the xorsi3 pattern would make combine
1510; less effective.
1511(define_insn "one_cmplsi2_i"
1512  [(set (match_operand:SI 0 "gpr_operand" "=r")
1513        (not:SI (match_operand:SI 1 "gpr_operand" "r")))
1514   (clobber (reg:CC CC_REGNUM))]
1515  "epiphany_m1reg >= 0"
1516  "eor %0,%1,%-")
1517
1518;; Shift instructions.
1519;; In principle we could support arbitrary symbolic values as shift constant
1520;; (truncating the value appropriately), but that would require a suitable
1521;; relocation and assembler & linker support.
1522(define_insn "ashrsi3"
1523  [(set (match_operand:SI 0 "gpr_operand" "=r,r")
1524	(ashiftrt:SI (match_operand:SI 1 "gpr_operand" "r,r")
1525		     (match_operand:SI 2 "arith_operand" "r,K")))
1526   (clobber (reg:CC CC_REGNUM))]
1527  ""
1528  "asr %0,%1,%2"
1529  [(set_attr "length" "4")
1530   (set_attr "type" "shift")])
1531
1532(define_insn "ashrsi3_tst"
1533  [(set (reg:CC CC_REGNUM)
1534	(compare:CC
1535	  (ashiftrt:SI (match_operand:SI 1 "gpr_operand" "r,r")
1536		       (match_operand:SI 2 "arith_operand" "r,K"))
1537	(const_int 0)))
1538   (set (match_operand:SI 0 "gpr_operand" "=r,r")
1539	(ashiftrt:SI (match_dup 1) (match_dup 2)))]
1540  ""
1541  "asr %0,%1,%2"
1542  [(set_attr "length" "4")
1543   (set_attr "type" "shift")])
1544
1545;; Logical Shift Right
1546(define_insn "lshrsi3"
1547  [(set (match_operand:SI 0 "gpr_operand" "=r,r")
1548	(lshiftrt:SI (match_operand:SI 1 "gpr_operand" "r,r")
1549		     (match_operand:SI 2 "arith_operand" "r,K")))
1550   (clobber (reg:CC CC_REGNUM))]
1551  ""
1552  "lsr %0,%1,%2"
1553  [(set_attr "length" "4")
1554   (set_attr "type" "shift")])
1555
1556(define_insn "lshrsi3_tst"
1557  [(set (reg:CC CC_REGNUM)
1558	(compare:CC
1559	  (lshiftrt:SI (match_operand:SI 1 "gpr_operand" "r,r")
1560		       (match_operand:SI 2 "arith_operand" "r,K"))
1561	(const_int 0)))
1562   (set (match_operand:SI 0 "gpr_operand" "=r,r")
1563	(lshiftrt:SI (match_dup 1) (match_dup 2)))]
1564  ""
1565  "lsr %0,%1,%2"
1566  [(set_attr "length" "4")
1567   (set_attr "type" "shift")])
1568
1569;; Logical/Arithmetic Shift Left
1570(define_insn "ashlsi3"
1571  [(set (match_operand:SI 0 "gpr_operand" "=r,r")
1572	(ashift:SI (match_operand:SI 1 "gpr_operand" "r,r")
1573		   (match_operand:SI 2 "arith_operand" "r,K")))
1574   (clobber (reg:CC CC_REGNUM))]
1575  ""
1576  "lsl %0,%1,%2"
1577  [(set_attr "length" "4")
1578   (set_attr "type" "shift")])
1579
1580(define_insn "*ashlsi_btst"
1581  [(set (reg:CC_N_NE CC_REGNUM)
1582	(compare:CC_N_NE
1583	  (zero_extract:SI (match_operand:SI 1 "gpr_operand" "r")
1584			   (const_int 1)
1585			   (match_operand 2 "const_int_operand" "K"))
1586	  (const_int 0)))
1587   (clobber (match_scratch:SI 0 "=r"))]
1588  ""
1589{
1590  rtx xop[3];
1591
1592  xop[0] = operands[0];
1593  xop[1] = operands[1];
1594  xop[2] = GEN_INT (31-INTVAL (operands[2]));
1595  output_asm_insn ("lsl %0,%1,%2", xop);
1596  return "";
1597})
1598
1599;; zero extensions
1600(define_insn_and_split "zero_extendqisi2"
1601  [(set (match_operand:SI 0 "register_operand" "=r,r")
1602	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))
1603   (clobber (reg:CC CC_REGNUM))]
1604  ""
1605  "@
1606   #
1607   ldrb %0,%1"
1608  "reload_completed
1609   ? true_regnum (operands[1]) >= 0
1610   : REG_P (operands[1]) && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER"
1611  [(parallel [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
1612	      (clobber (reg:CC CC_REGNUM))])
1613   (parallel [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))
1614	      (clobber (reg:CC CC_REGNUM))])]
1615  "operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);")
1616
1617(define_insn "zero_extendhisi2"
1618  [(set (match_operand:SI 0 "register_operand" "=r,r")
1619	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,m")))]
1620  ""
1621  "@
1622   movt %0, 0
1623   ldrh %0,%c1")
1624
1625
1626;; Compare instructions.
1627
1628(define_insn "cmpsi_cc_insn"
1629  [(set (reg:CC CC_REGNUM)
1630	(compare:CC (match_operand:SI 0 "add_reg_operand" "r,r")
1631		    (match_operand:SI 1 "arith_operand" "r,L")))
1632   (clobber (match_scratch:SI 2 "=r,r"))]
1633  ""
1634  "sub %2,%0,%1"
1635  [(set_attr "type" "compare")])
1636
1637(define_insn "sub_f"
1638  [(set (reg:CC CC_REGNUM)
1639        (compare:CC (match_operand:SI 1 "gpr_operand"  "r,r")
1640                    (match_operand:SI 2 "arith_operand" "r,L")))
1641   (set (match_operand:SI 0 "gpr_operand" "=r,r")
1642        (minus:SI (match_dup 1) (match_dup 2)))]
1643  ""
1644  "sub %0,%1,%2"
1645  [(set_attr "type" "compare")])
1646
1647(define_insn "*sub_f_add_imm"
1648  [(set (reg:CC CC_REGNUM)
1649        (compare:CC (match_operand:SI 1 "gpr_operand"  "r")
1650                    (match_operand:SI 2 "arith_int_operand" "L")))
1651   (set (match_operand:SI 0 "gpr_operand" "=r")
1652        (plus:SI (match_dup 1) (match_operand:SI 3 "const_int_operand" "L")))]
1653  "INTVAL (operands[2]) == -INTVAL (operands[3])"
1654  "sub %0,%1,%2"
1655  [(set_attr "type" "compare")])
1656
1657(define_expand "abssi2"
1658  [(set (match_dup 2) (const_int 0))
1659   (parallel [(set (reg:CC CC_REGNUM)
1660		   (compare:CC (match_dup 2)
1661			       (match_operand:SI 1 "nonmemory_operand" "")))
1662	      (set (match_dup 3)
1663		   (minus:SI (match_dup 2) (match_dup 1)))])
1664   (set (match_operand:SI 0 "gpr_operand" "=r")
1665	(if_then_else:SI (gt:SI (reg:CC CC_REGNUM) (const_int 0))
1666			 (match_dup 3)
1667			 (match_dup 1)))]
1668  "TARGET_CMOVE"
1669  "operands[2] = gen_reg_rtx (SImode); operands[3] = gen_reg_rtx (SImode);")
1670
1671(define_insn "*add_c"
1672  [(set (reg:CC_C_LTU CC_REGNUM)
1673        (compare:CC_C_LTU
1674	  (plus:SI (match_operand:SI 1 "gpr_operand" "%r,r")
1675		   (match_operand:SI 2 "arith_operand" "r,L"))
1676	  (match_dup 1)))
1677   (set (match_operand:SI 0 "gpr_operand" "=r,r")
1678        (plus:SI (match_dup 1) (match_dup 2)))]
1679  ""
1680  "add %0,%1,%2"
1681  [(set_attr "type" "compare")])
1682
1683(define_insn "*add_c_rev"
1684  [(set (reg:CC_C_LTU CC_REGNUM)
1685        (compare:CC_C_LTU
1686	  (plus:SI (match_operand:SI 1 "gpr_operand" "%r,r")
1687		   (match_operand:SI 2 "arith_operand" "r,L"))
1688	  (match_dup 1)))
1689   (set (match_operand:SI 0 "gpr_operand" "=r,r")
1690        (plus:SI (match_dup 2) (match_dup 1)))]
1691  ""
1692  "add %0,%1,%2"
1693  [(set_attr "type" "compare")])
1694
1695(define_insn "*sub_c"
1696  [(set (reg:CC_C_GTU CC_REGNUM)
1697        (compare:CC_C_GTU
1698	  (minus:SI (match_operand:SI 1 "gpr_operand"  "r,r")
1699		    (match_operand:SI 2 "arith_operand" "r,L"))
1700	  (match_dup 1)))
1701   (set (match_operand:SI 0 "gpr_operand" "=r,r")
1702        (minus:SI (match_dup 1) (match_dup 2)))]
1703  ""
1704  "sub %0,%1,%2"
1705  [(set_attr "type" "compare")])
1706
1707(define_insn "*sub_c_void"
1708  [(set (reg:CC_C_GTU CC_REGNUM)
1709        (compare:CC_C_GTU
1710	  (minus:SI (match_operand:SI 1 "gpr_operand"  "r,r")
1711		    (match_operand:SI 2 "arith_operand" "r,L"))
1712	  (match_dup 1)))
1713   (clobber (match_scratch:SI 0 "=r,r"))]
1714  ""
1715  "sub %0,%1,%2"
1716  [(set_attr "type" "compare")])
1717
1718; floating point comparisons
1719
1720(define_insn "*cmpsf_cc_insn"
1721  [(match_parallel 3 "float_operation"
1722     [(set (reg:CC_FP CCFP_REGNUM)
1723	   (compare:CC_FP (match_operand:SF 0 "gpr_operand" "r")
1724			  (match_operand:SF 1 "gpr_operand" "r")))
1725      (clobber (match_scratch:SF 2 "=r"))])]
1726  "!TARGET_SOFT_CMPSF"
1727  "fsub %2,%0,%1"
1728  [(set_attr "type" "fp")
1729   (set_attr "fp_mode" "round_unknown")])
1730
1731;; ??? do we have to relax the operand0 predicate to immediate_operand
1732;; to allow the rtl loop optimizer to generate comparisons?  OTOH
1733;; we want call_address_operand to enforce valid operands so that
1734;; combine won't do silly things, allowing instruction scheduling to do
1735;; a proper job.
1736(define_insn "*cmpsf_eq"
1737  [(set (reg:CC_FP_EQ CC_REGNUM) (compare:CC_FP_EQ (reg:SF 0) (reg:SF 1)))
1738   (use (match_operand:SI 0 "call_address_operand" "Csy,r"))
1739   (clobber (reg:SI GPR_IP))
1740   (clobber (reg:SI GPR_LR))]
1741  "TARGET_SOFT_CMPSF"
1742  "%f0"
1743  [(set_attr "type" "sfunc")])
1744
1745(define_insn "*cmpsf_gte"
1746  [(set (reg:CC_FP_GTE CC_REGNUM) (compare:CC_FP_GTE (reg:SF 0) (reg:SF 1)))
1747   (use (match_operand:SI 0 "call_address_operand" "Csy,r"))
1748   (clobber (reg:SI GPR_IP))
1749   (clobber (reg:SI GPR_LR))]
1750  "TARGET_SOFT_CMPSF"
1751  "%f0"
1752  [(set_attr "type" "sfunc")])
1753
1754(define_insn "*cmpsf_ord"
1755  [(set (reg:CC_FP_ORD CC_REGNUM) (compare:CC_FP_ORD (reg:SF 0) (reg:SF 1)))
1756   (use (match_operand:SI 0 "call_address_operand" "Csy,r"))
1757   (clobber (reg:SI GPR_IP))
1758   (clobber (reg:SI GPR_16))
1759   (clobber (reg:SI GPR_LR))]
1760  "TARGET_SOFT_CMPSF"
1761  "%f0"
1762  [(set_attr "type" "sfunc")])
1763
1764(define_insn "*cmpsf_uneq"
1765  [(set (reg:CC_FP_UNEQ CC_REGNUM) (compare:CC_FP_UNEQ (reg:SF 0) (reg:SF 1)))
1766   (use (match_operand:SI 0 "call_address_operand" "Csy,r"))
1767   (clobber (reg:SI GPR_IP))
1768   (clobber (reg:SI GPR_16))
1769   (clobber (reg:SI GPR_LR))]
1770  "TARGET_SOFT_CMPSF"
1771  "%f0"
1772  [(set_attr "type" "sfunc")])
1773
1774;; conditional moves
1775
1776(define_expand "mov<mode>cc"
1777  [(set (match_operand:WMODE 0 "gpr_operand" "")
1778	(if_then_else:WMODE (match_operand 1 "comparison_operator" "")
1779			    (match_operand:WMODE 2 "gpr_operand" "")
1780			    (match_operand:WMODE 3 "gpr_operand" "")))]
1781  "TARGET_CMOVE"
1782{
1783  rtx cmp_op0 = XEXP (operands[1], 0);
1784  rtx cmp_op1 = XEXP (operands[1], 1);
1785  enum machine_mode cmp_in_mode;
1786  enum rtx_code code = GET_CODE (operands[1]);
1787
1788  cmp_in_mode = GET_MODE (cmp_op0);
1789  if (cmp_in_mode == VOIDmode)
1790    cmp_in_mode = GET_MODE (cmp_op1);
1791  if (cmp_in_mode == VOIDmode)
1792    cmp_in_mode = SImode;
1793  /* If the operands are a better match when reversed, swap them now.
1794     This allows combine to see the proper comparison codes.  */
1795  if (rtx_equal_p (operands[0], operands[2])
1796      && !rtx_equal_p (operands[0], operands[3]))
1797    {
1798      rtx tmp = operands[2]; operands[2] = operands[3]; operands[3] = tmp;
1799      code = (FLOAT_MODE_P (GET_MODE (cmp_op0))
1800	      ? reverse_condition_maybe_unordered (code)
1801	      : reverse_condition (code));
1802    }
1803
1804  if (proper_comparison_operator (operands[1], VOIDmode))
1805    operands[1] = gen_rtx_fmt_ee (code, cmp_in_mode, cmp_op0, cmp_op1);
1806  else
1807    {
1808      if (!currently_expanding_to_rtl)
1809	{
1810	  /* ???  It would seem safest to FAIL here, but that would defeat
1811	     the purpose of having an if-conversion pass; its logic currently
1812	     assumes that the backend should be safe to insert condition code
1813	     setting instructions, as the same condition codes were presumably
1814	     set by the if-conversion input code.  */
1815	}
1816      /* What mode to give as first operand to gen_compare_reg here is
1817	 debatable.  VOIDmode would be minimalist; telling gen_compare_reg
1818	 to use the mode of CC_REGNUM (or putting it on the comparison
1819	 operator afterwards) is also a logical choice.  OTOH, by using
1820	 <MODE>mode, we have mode combine opportunities with flag setting
1821	 operations - if we get some.  */
1822      operands[1]
1823	= gen_compare_reg (<MODE>mode, code, cmp_in_mode, cmp_op0, cmp_op1);
1824    }
1825})
1826
1827(define_insn "*mov<mode>cc_insn"
1828  [(set (match_operand:WMODE 0 "gpr_operand" "=r")
1829	(if_then_else:WMODE (match_operator 3 "proper_comparison_operator"
1830			      [(match_operand 4 "cc_operand") (const_int 0)])
1831			    (match_operand:WMODE 1 "gpr_operand" "r")
1832			    (match_operand:WMODE 2 "gpr_operand" "0")))]
1833  "TARGET_CMOVE"
1834  "mov%d3 %0,%1"
1835  [(set_attr "type" "cmove")])
1836
1837(define_peephole2
1838  [(parallel [(set (match_operand:WMODE 0 "gpr_operand" "")
1839		   (match_operand:WMODE 1 "" ""))
1840	      (clobber (match_operand 8 "cc_operand"))])
1841   (match_operand 2 "" "")
1842   (set (match_operand:WMODE2 3 "gpr_operand" "")
1843	(match_operand:WMODE2 9 "gpr_operand" ""))
1844   (set (match_dup 3)
1845	(if_then_else:WMODE2 (match_operator 5 "proper_comparison_operator"
1846			       [(match_operand 6 "cc_operand")
1847				(match_operand 7 "const0_operand")])
1848			     (match_operand:WMODE2 4 "nonmemory_operand" "")
1849			     (match_dup 3)))]
1850  "REGNO (operands[0]) == REGNO (operands[9])
1851   && peep2_reg_dead_p (3, operands[0])
1852   && !reg_set_p (operands[0], operands[2])
1853   && !reg_set_p (operands[3], operands[2])
1854   && !reg_overlap_mentioned_p (operands[3], operands[2])"
1855  [(parallel [(set (match_dup 10) (match_dup 1))
1856	      (clobber (match_dup 8))])
1857   (match_dup 2)
1858   (set (match_dup 3)
1859	(if_then_else:WMODE2 (match_dup 5) (match_dup 4) (match_dup 3)))]
1860{
1861  operands[10] = simplify_gen_subreg (<WMODE:MODE>mode, operands[3],
1862				      <WMODE2:MODE>mode, 0);
1863  replace_rtx (operands[2], operands[9], operands[3]);
1864  replace_rtx (operands[2], operands[0], operands[10]);
1865  gcc_assert (!reg_overlap_mentioned_p (operands[0], operands[2]));
1866})
1867
1868(define_peephole2
1869  [(parallel [(set (match_operand 6 "cc_operand") (match_operand 2 "" ""))
1870	      (set (match_operand:WMODE 0 "gpr_operand" "")
1871		   (match_operand:WMODE 1 "" ""))])
1872   (set (match_operand:WMODE2 3 "gpr_operand" "")
1873	(match_operand:WMODE2 4 "gpr_operand"))
1874   (set (match_dup 3)
1875	(if_then_else:WMODE2 (match_operator 5 "proper_comparison_operator"
1876			       [(match_dup 6)
1877			       (match_operand:WMODE 7 "const0_operand")])
1878			    (match_operand:WMODE2 8 "gpr_operand")
1879			    (match_dup 3)))]
1880  "REGNO (operands[0]) == REGNO (operands[8])
1881   && REVERSIBLE_CC_MODE (GET_MODE (operands[6]))
1882   && peep2_reg_dead_p (3, operands[6])
1883   && peep2_reg_dead_p (3, operands[0])
1884   && !reg_overlap_mentioned_p (operands[4], operands[3])"
1885  [(parallel [(set (match_dup 6) (match_dup 2))
1886	      (set (match_dup 9) (match_dup 1))])
1887   (set (match_dup 3)
1888	(if_then_else:WMODE2 (match_dup 5) (match_dup 4) (match_dup 3)))]
1889  "
1890{
1891  operands[5]
1892    = gen_rtx_fmt_ee (REVERSE_CONDITION (GET_CODE (operands[5]),
1893					 GET_MODE (operands[6])),
1894		      GET_MODE (operands[5]), operands[6], operands[7]);
1895  operands[9] = simplify_gen_subreg (<WMODE:MODE>mode, operands[3],
1896				     <WMODE2:MODE>mode, 0);
1897}")
1898
1899;; These control RTL generation for conditional jump insns
1900
1901;; To signal to can_compare_p that the cbranchs?4 patterns work,
1902;; they must allow const0_rtx for both comparison operands
1903(define_expand "cbranchsi4"
1904  [(set (reg CC_REGNUM)
1905	(compare (match_operand:SI 1 "add_operand" "")
1906		 (match_operand:SI 2 "arith_operand" "")))
1907   (set (pc)
1908	(if_then_else
1909	      (match_operator 0 "ordered_comparison_operator" [(reg CC_REGNUM)
1910							       (const_int 0)])
1911	      (label_ref (match_operand 3 "" ""))
1912	      (pc)))]
1913  ""
1914{
1915  rtx cmp = gen_compare_reg (VOIDmode, GET_CODE (operands[0]), SImode,
1916			     operands[1], operands[2]);
1917  emit_jump_insn (gen_branch_insn (operands[3], cmp, XEXP (cmp, 0)));
1918  DONE;
1919})
1920
1921(define_expand "cbranchsf4"
1922  [(set (reg CC_REGNUM)
1923	(compare (match_operand:SF 1 "arith_operand" "")
1924		 (match_operand:SF 2 "arith_operand" "")))
1925   (set (pc)
1926	(if_then_else
1927	      (match_operator 0 "comparison_operator" [(reg CC_REGNUM)
1928						       (const_int 0)])
1929	      (label_ref (match_operand 3 "" ""))
1930	      (pc)))]
1931  ""
1932{
1933  rtx cmp = gen_compare_reg (VOIDmode, GET_CODE (operands[0]), SFmode,
1934			     operands[1], operands[2]);
1935  emit_jump_insn (gen_branch_insn (operands[3], cmp, XEXP (cmp, 0)));
1936  DONE;
1937})
1938
1939;; Now match both normal and inverted jump.
1940
1941(define_insn "branch_insn"
1942  [(set (pc)
1943	(if_then_else (match_operator 1 "proper_comparison_operator"
1944				      [(match_operand 2 "cc_operand")
1945				       (const_int 0)])
1946		      (label_ref (match_operand 0 "" ""))
1947		      (pc)))]
1948  ""
1949  "b%d1 %l0"
1950  [(set_attr "type" "branch")])
1951
1952(define_insn "*rev_branch_insn"
1953  [(set (pc)
1954	(if_then_else (match_operator 1 "proper_comparison_operator"
1955				      [(reg CC_REGNUM) (const_int 0)])
1956		      (pc)
1957		      (label_ref (match_operand 0 "" ""))))]
1958  ""
1959  "b%D1 %l0"
1960  [(set_attr "type" "branch")])
1961
1962;; Unconditional and other jump instructions.
1963
1964(define_insn "jump"
1965  [(set (pc) (label_ref (match_operand 0 "" "")))]
1966  ""
1967  "b %l0"
1968  [(set_attr "type" "uncond_branch")])
1969
1970(define_insn "indirect_jump"
1971  [(set (pc) (match_operand:SI 0 "gpr_operand" "r"))]
1972  ""
1973  "jr %0"
1974  [(set_attr "type" "uncond_branch")])
1975
1976(define_expand "tablejump"
1977  [(parallel [(set (pc) (match_operand:SI 0 "gpr_operand" ""))
1978              (use (label_ref (match_operand 1 "" "")))])]
1979  ""
1980{
1981  /* In PIC mode, the table entries are stored PC relative.
1982     Convert the relative address to an absolute address.  */
1983  if (flag_pic)
1984    {
1985      rtx op1 = gen_rtx_LABEL_REF (Pmode, operands[1]);
1986
1987      operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
1988					 op1, NULL_RTX, 0, OPTAB_DIRECT);
1989    }
1990})
1991
1992(define_insn "*tablejump_internal"
1993  [(set (pc) (match_operand:SI 0 "gpr_operand" "r"))
1994   (use (label_ref (match_operand 1 "" "")))]
1995  ""
1996  "jr %0;"
1997  [(set_attr "type" "uncond_branch")])
1998
1999(define_insn "*tablejump_hi_internal"
2000  [(set (pc) (match_operand:HI 0 "gpr_operand" "r"))
2001   (use (label_ref (match_operand 1 "" "")))]
2002  "optimize_size && TARGET_SMALL16"
2003  "jr %0;"
2004  [(set_attr "type" "uncond_branch")])
2005
2006
2007(define_expand "call"
2008  ;; operands[1] is stack_size_rtx
2009  ;; operands[2] is next_arg_register
2010  [(parallel [(call (match_operand:SI 0 "call_operand" "")
2011		    (match_operand 1 "" ""))
2012	     (clobber (reg:SI GPR_LR))])]
2013  ""
2014{
2015  bool target_uninterruptible = epiphany_call_uninterruptible_p (operands[0]);
2016
2017  if (!call_operand (operands[1], VOIDmode))
2018    operands[0]
2019      = change_address (operands[0], VOIDmode,
2020			copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
2021  if (epiphany_uninterruptible_p (current_function_decl)
2022      != target_uninterruptible)
2023    {
2024      emit_insn (target_uninterruptible ? gen_gid (): gen_gie ());
2025      emit_call_insn
2026	(gen_rtx_PARALLEL
2027	  (VOIDmode,
2028	   gen_rtvec (2, gen_rtx_CALL (VOIDmode, operands[0], operands[1]),
2029			 gen_rtx_CLOBBER (VOIDmode,
2030					  gen_rtx_REG (SImode, GPR_LR)))));
2031      emit_insn (target_uninterruptible ? gen_gie (): gen_gid ());
2032      DONE;
2033    }
2034})
2035
2036(define_insn "*call_i"
2037  [(match_parallel 2 "float_operation"
2038     [(call (mem:SI (match_operand:SI 0 "call_address_operand" "Csy,r"))
2039	    (match_operand 1 "" ""))
2040      (clobber (reg:SI GPR_LR))])]
2041  ""
2042  "%f0"
2043  [(set_attr "type" "call")])
2044
2045(define_expand "sibcall"
2046  ;; operands[1] is stack_size_rtx
2047  ;; operands[2] is next_arg_register
2048  [(parallel [(call (match_operand:SI 0 "call_operand" "")
2049		    (match_operand 1 "" ""))
2050	     (return)])]
2051  ""
2052{
2053  bool target_uninterruptible = epiphany_call_uninterruptible_p (operands[0]);
2054
2055  if (!call_operand (operands[1], VOIDmode))
2056    operands[0]
2057      = change_address (operands[0], VOIDmode,
2058			copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
2059  if (epiphany_uninterruptible_p (current_function_decl)
2060      != target_uninterruptible)
2061    {
2062      emit_insn (target_uninterruptible ? gen_gid (): gen_gie ());
2063      emit_call_insn
2064	(gen_rtx_PARALLEL
2065	  (VOIDmode,
2066	   gen_rtvec (2, gen_rtx_CALL (VOIDmode, operands[0], operands[1]),
2067			 ret_rtx)));
2068      emit_insn (target_uninterruptible ? gen_gie (): gen_gid ());
2069      DONE;
2070    }
2071})
2072
2073(define_insn "*sibcall_i"
2074  [(call (mem:SI (match_operand:SI 0 "call_address_operand" "Csy,Rsc"))
2075	 (match_operand 1 "" ""))
2076   (return)]
2077  ""
2078  "@
2079   b %0
2080   jr %0"
2081  [(set_attr "type" "call")])
2082
2083(define_expand "call_value"
2084  ;; operand 2 is stack_size_rtx
2085  ;; operand 3 is next_arg_register
2086  [(parallel [(set (match_operand 0 "gpr_operand" "=r")
2087		   (call (match_operand:SI 1 "call_operand" "")
2088			 (match_operand 2 "" "")))
2089	     (clobber (reg:SI GPR_LR))])]
2090  ""
2091{
2092  bool target_uninterruptible = epiphany_call_uninterruptible_p (operands[1]);
2093
2094  if (!call_operand (operands[1], VOIDmode))
2095    operands[1]
2096      = change_address (operands[1], VOIDmode,
2097			copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
2098  if (epiphany_uninterruptible_p (current_function_decl)
2099      != target_uninterruptible)
2100    {
2101      emit_insn (target_uninterruptible ? gen_gid (): gen_gie ());
2102      emit_call_insn
2103	(gen_rtx_PARALLEL
2104	  (VOIDmode,
2105	   gen_rtvec (2, gen_rtx_SET
2106			   (VOIDmode, operands[0],
2107			    gen_rtx_CALL (VOIDmode, operands[1], operands[2])),
2108			 gen_rtx_CLOBBER (VOIDmode,
2109					  gen_rtx_REG (SImode, GPR_LR)))));
2110      emit_insn (target_uninterruptible ? gen_gie (): gen_gid ());
2111      DONE;
2112    }
2113})
2114
2115(define_insn "*call_value_i"
2116  [(match_parallel 3 "float_operation"
2117     [(set (match_operand 0 "gpr_operand" "=r,r")
2118	   (call (mem:SI (match_operand:SI 1 "call_address_operand" "Csy,r"))
2119	         (match_operand 2 "" "")))
2120      (clobber (reg:SI GPR_LR))])]
2121  ""
2122  "%f1"
2123  [(set_attr "type" "call")
2124   (set_attr "length" "4")])
2125
2126(define_expand "sibcall_value"
2127  ;; operand 2 is stack_size_rtx
2128  ;; operand 3 is next_arg_register
2129  [(parallel [(set (match_operand 0 "gpr_operand" "=r")
2130		   (call (match_operand:SI 1 "call_operand" "")
2131			 (match_operand 2 "" "")))
2132	     (return)])]
2133  ""
2134{
2135  bool target_uninterruptible = epiphany_call_uninterruptible_p (operands[1]);
2136
2137  if (!call_operand (operands[1], VOIDmode))
2138    operands[1]
2139      = change_address (operands[1], VOIDmode,
2140			copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
2141  if (epiphany_uninterruptible_p (current_function_decl)
2142      != target_uninterruptible)
2143    {
2144      emit_insn (target_uninterruptible ? gen_gid (): gen_gie ());
2145      emit_call_insn
2146	(gen_rtx_PARALLEL
2147	  (VOIDmode,
2148	   gen_rtvec (2, gen_rtx_SET
2149			   (VOIDmode, operands[0],
2150			    gen_rtx_CALL (VOIDmode, operands[1], operands[2])),
2151			 ret_rtx)));
2152      emit_insn (target_uninterruptible ? gen_gie (): gen_gid ());
2153      DONE;
2154    }
2155})
2156
2157(define_insn "*sibcall_value_i"
2158  [(set (match_operand 0 "gpr_operand" "=r,r")
2159	(call (mem:SI (match_operand:SI 1 "call_address_operand" "Csy,Rsc"))
2160	      (match_operand 2 "" "")))
2161   (return)]
2162  ""
2163  "@
2164   b %1
2165   jr %1"
2166  [(set_attr "type" "call")
2167   (set_attr "length" "4")])
2168
2169(define_expand "prologue"
2170  [(pc)]
2171  ""
2172{
2173  epiphany_expand_prologue ();
2174  DONE;
2175})
2176
2177(define_expand "epilogue"
2178  [(pc)]
2179  ""
2180{
2181  epiphany_expand_epilogue (0);
2182  DONE;
2183})
2184
2185(define_expand "sibcall_epilogue"
2186  [(pc)]
2187  ""
2188{
2189  epiphany_expand_epilogue (1);
2190  DONE;
2191})
2192
2193; Since the demise of REG_N_SETS, it is no longer possible to find out
2194; in the prologue / epilogue expanders how many times lr is set.
2195; Using df_regs_ever_live_p to decide if lr needs saving means that
2196; any explicit use of lr will cause it to be saved; hence we cannot
2197; represent the blink use in return / sibcall instructions themselves, and
2198; instead have to show it in EPILOGUE_USES.
2199(define_insn "return_i"
2200  [(return)]
2201  "reload_completed"
2202  "rts"
2203  [(set_attr "type" "uncond_branch")])
2204
2205(define_insn "return_internal_interrupt"
2206  [(return)
2207   (unspec_volatile [(const_int 0)] 1)]
2208  ""
2209  "rti"
2210  [(set_attr "type" "uncond_branch")])
2211
2212(define_insn "stack_adjust_add"
2213  [(set (reg:SI GPR_SP)
2214	(plus:SI (reg:SI GPR_SP) (match_operand:SI 0 "arith_operand" "rL")))
2215   (clobber (reg:CC CC_REGNUM))
2216   (clobber (reg:SI STATUS_REGNUM))
2217   (clobber (match_operand:BLK 1 "memory_operand" "=m"))]
2218  "reload_completed"
2219  "add sp,sp,%0")
2220
2221(define_insn "stack_adjust_mov"
2222  [(set (reg:SI GPR_SP) (reg:SI GPR_FP))
2223   (clobber (match_operand:BLK 0 "memory_operand" "=m"))]
2224  "reload_completed"
2225  "mov sp,fp"
2226  [(set_attr "type" "move")])
2227
2228(define_insn "stack_adjust_str"
2229  [(set (match_operand 0 "stacktop_operand" "=m")
2230	(match_operand 1 "any_gpr_operand" "r"))
2231   (set (reg:SI GPR_SP)
2232	(plus:SI (reg:SI GPR_SP) (match_operand:SI 2 "nonmemory_operand" "rn")))
2233   (clobber (match_operand:BLK 3 "memory_operand" "=m"))]
2234  "reload_completed"
2235{
2236  return (GET_MODE_SIZE (GET_MODE (operands[0])) <= 4
2237	  ? \"str %1,%0,%C2\" : \"strd %1,%0,%X2\");
2238}
2239  [(set_attr "type" "store")])
2240
2241(define_insn "stack_adjust_ldr"
2242  [(set (match_operand:SI 0 "gpr_operand" "=r")
2243	(match_operand:SI 1 "stacktop_operand" "m"))
2244   (set (reg:SI GPR_SP)
2245	(plus:SI (reg:SI GPR_SP) (match_operand:SI 2 "nonmemory_operand" "rn")))
2246   (clobber (match_operand:BLK 3 "memory_operand" "=m"))]
2247  "reload_completed"
2248  "ldr %0,%1,%C2"
2249  [(set_attr "type" "load")])
2250
2251;; Define some fake vector operations so that the vectorizer is happy to use
2252;; 64 bit loads/stores.
2253(define_expand "vec_unpacks_lo_v4hi"
2254  [(match_operand:V2SI 0 "gpr_operand")
2255   (match_operand:V4HI 1 "gpr_operand")]
2256  ""
2257{
2258  rtx in = simplify_gen_subreg (SImode, operands[1], V4HImode, 0);
2259  rtx outl = simplify_gen_subreg (SImode, operands[0], V2SImode, 0);
2260  rtx outh
2261    = simplify_gen_subreg (SImode, operands[0], V2SImode, UNITS_PER_WORD);
2262
2263  if (reg_overlap_mentioned_p (outl, in))
2264    in = copy_to_mode_reg (SImode, in);
2265  emit_insn (gen_ashlsi3 (outl, in, GEN_INT (16)));
2266  emit_insn (gen_ashrsi3 (outl, outl, GEN_INT (16)));
2267  emit_insn (gen_ashrsi3 (outh, in, GEN_INT (16)));
2268  DONE;
2269})
2270
2271(define_expand "vec_unpacks_hi_v4hi"
2272  [(match_operand:V2SI 0 "gpr_operand")
2273   (match_operand:V4HI 1 "gpr_operand")]
2274  ""
2275{
2276  rtx in = simplify_gen_subreg (SImode, operands[1], V4HImode, UNITS_PER_WORD);
2277  rtx outl = simplify_gen_subreg (SImode, operands[0], V2SImode, 0);
2278  rtx outh
2279    = simplify_gen_subreg (SImode, operands[0], V2SImode, UNITS_PER_WORD);
2280
2281  if (reg_overlap_mentioned_p (outl, in))
2282    in = copy_to_mode_reg (SImode, in);
2283  emit_insn (gen_ashlsi3 (outl, in, GEN_INT (16)));
2284  emit_insn (gen_ashrsi3 (outl, outl, GEN_INT (16)));
2285  emit_insn (gen_ashrsi3 (outh, in, GEN_INT (16)));
2286  DONE;
2287})
2288
2289(define_code_iterator addsub [plus minus])
2290
2291(define_code_iterator alu_binop
2292  [plus minus and ior xor])
2293
2294(define_code_attr insn_opname
2295  [(plus "add") (minus "sub") (mult "mul") (div "div")
2296   (and "and") (ior "ior") (xor "xor")])
2297
2298; You might think that this would work better as a define_expand, but
2299; again lower_subreg pessimizes the code if it sees indiviudual operations.
2300; We need to keep inputs and outputs as register pairs if we want to
2301; get sensible register allocation for double-word load and store operations.
2302(define_insn_and_split "<insn_opname>v2si3"
2303  [(set (match_operand:V2SI 0 "gpr_operand" "=r")
2304	(alu_binop:V2SI (match_operand:V2SI 1 "gpr_operand" "r")
2305			(match_operand:V2SI 2 "gpr_operand" "r")))
2306   (clobber (reg:CC CC_REGNUM))]
2307  ""
2308  "#"
2309  "reload_completed || (epiphany_vect_align == 4 && TARGET_SPLIT_VECMOVE_EARLY)"
2310  [(const_int 0)]
2311{
2312  rtx o0l, o0h, o1l, o1h, o2l, o2h;
2313
2314  o0l = simplify_gen_subreg (SImode, operands[0], V2SImode, 0);
2315  o0h = simplify_gen_subreg (SImode, operands[0], V2SImode, UNITS_PER_WORD);
2316  o1l = simplify_gen_subreg (SImode, operands[1], V2SImode, 0);
2317  o1h = simplify_gen_subreg (SImode, operands[1], V2SImode, UNITS_PER_WORD);
2318  o2l = simplify_gen_subreg (SImode, operands[2], V2SImode, 0);
2319  o2h = simplify_gen_subreg (SImode, operands[2], V2SImode, UNITS_PER_WORD);
2320  if (reg_overlap_mentioned_p (o0l, o1h))
2321    o1h = copy_to_mode_reg (SImode, o1h);
2322  if (reg_overlap_mentioned_p (o0l, o2h))
2323    o2h = copy_to_mode_reg (SImode, o2h);
2324  emit_insn (gen_<insn_opname>si3 (o0l, o1l, o2l));
2325  emit_insn (gen_<insn_opname>si3 (o0h, o1h, o2h));
2326  DONE;
2327}
2328  [(set_attr "length" "8")])
2329
2330(define_expand "<insn_opname>v2sf3"
2331  [(parallel
2332     [(set (match_operand:V2SF 0 "gpr_operand" "")
2333	   (addsub:V2SF (match_operand:V2SF 1 "gpr_operand" "")
2334			(match_operand:V2SF 2 "gpr_operand" "")))
2335      (clobber (reg:CC_FP CCFP_REGNUM))])])
2336
2337(define_insn_and_split "<insn_opname>v2sf3_i"
2338  [(match_parallel 3 "float_operation"
2339     [(set (match_operand:V2SF 0 "gpr_operand" "=r")
2340	   (addsub:V2SF (match_operand:V2SF 1 "gpr_operand" "r")
2341			(match_operand:V2SF 2 "gpr_operand" "r")))
2342      (clobber (reg:CC_FP CCFP_REGNUM))])]
2343  ""
2344  "#"
2345  "reload_completed || (epiphany_vect_align == 4 && TARGET_SPLIT_VECMOVE_EARLY)"
2346  [(parallel
2347     [(set (match_dup 4) (addsub:SF (match_dup 5) (match_dup 6)))
2348      (clobber (reg:CC_FP CCFP_REGNUM))
2349      (match_dup 10)
2350      (match_dup 11)])
2351   (parallel
2352     [(set (match_dup 7) (addsub:SF (match_dup 8) (match_dup 9)))
2353      (clobber (reg:CC_FP CCFP_REGNUM))
2354      (match_dup 10)
2355      (match_dup 11)])]
2356{
2357  operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
2358  operands[5] = simplify_gen_subreg (SFmode, operands[1], V2SFmode, 0);
2359  operands[6] = simplify_gen_subreg (SFmode, operands[2], V2SFmode, 0);
2360  operands[7]
2361    = simplify_gen_subreg (SFmode, operands[0], V2SFmode, UNITS_PER_WORD);
2362  operands[8]
2363    = simplify_gen_subreg (SFmode, operands[1], V2SFmode, UNITS_PER_WORD);
2364  operands[9]
2365    = simplify_gen_subreg (SFmode, operands[2], V2SFmode, UNITS_PER_WORD);
2366  if (!reload_completed)
2367    {
2368      if (reg_overlap_mentioned_p (operands[4], operands[8]))
2369	operands[8] = copy_to_mode_reg (SFmode, operands[8]);
2370      if (reg_overlap_mentioned_p (operands[4], operands[9]))
2371	operands[9] = copy_to_mode_reg (SFmode, operands[9]);
2372      emit_insn (gen_<insn_opname>sf3 (operands[4], operands[5], operands[6]));
2373      emit_insn (gen_<insn_opname>sf3 (operands[7], operands[8], operands[9]));
2374      DONE;
2375    }
2376  gcc_assert (!reg_overlap_mentioned_p (operands[4], operands[8]));
2377  gcc_assert (!reg_overlap_mentioned_p (operands[4], operands[9]));
2378  operands[10] = XVECEXP (operands[3], 0, XVECLEN (operands[3], 0) - 2);
2379  operands[11] = XVECEXP (operands[3], 0, XVECLEN (operands[3], 0) - 1);
2380}
2381  [(set_attr "length" "8")
2382   (set_attr "type" "v2fp")])
2383
2384(define_expand "mul<mode>3"
2385  [(parallel
2386     [(set (match_operand:DWV2MODE 0 "gpr_operand" "")
2387	   (mult:DWV2MODE (match_operand:DWV2MODE 1 "gpr_operand" "")
2388			  (match_operand:DWV2MODE 2 "gpr_operand" "")))
2389      (clobber (reg:CC_FP CCFP_REGNUM))])])
2390
2391(define_insn_and_split "mul<mode>3_i"
2392  [(match_parallel 3 "float_operation"
2393     [(set (match_operand:DWV2MODE 0 "gpr_operand" "=r")
2394	   (mult:DWV2MODE (match_operand:DWV2MODE 1 "gpr_operand" "r")
2395			  (match_operand:DWV2MODE 2 "gpr_operand" "r")))
2396      (clobber (reg:CC_FP CCFP_REGNUM))])]
2397  ""
2398  "#"
2399  "reload_completed || (epiphany_vect_align == 4 && TARGET_SPLIT_VECMOVE_EARLY)"
2400  [(parallel
2401     [(set (match_dup 4) (mult:<vmode_PART> (match_dup 5) (match_dup 6)))
2402      (clobber (reg:CC_FP CCFP_REGNUM))
2403      (match_dup 10)
2404      (match_dup 11)])
2405   (parallel
2406     [(set (match_dup 7) (mult:<vmode_PART> (match_dup 8) (match_dup 9)))
2407      (clobber (reg:CC_FP CCFP_REGNUM))
2408      (match_dup 10)
2409      (match_dup 11)])]
2410{
2411  operands[4]
2412    = simplify_gen_subreg (<vmode_PART>mode, operands[0], <MODE>mode, 0);
2413  operands[5]
2414    = simplify_gen_subreg (<vmode_PART>mode, operands[1], <MODE>mode, 0);
2415  operands[6]
2416    = simplify_gen_subreg (<vmode_PART>mode, operands[2], <MODE>mode, 0);
2417  operands[7] = simplify_gen_subreg (<vmode_PART>mode, operands[0],
2418				     <MODE>mode, UNITS_PER_WORD);
2419  operands[8] = simplify_gen_subreg (<vmode_PART>mode, operands[1],
2420				     <MODE>mode, UNITS_PER_WORD);
2421  operands[9] = simplify_gen_subreg (<vmode_PART>mode, operands[2],
2422				     <MODE>mode, UNITS_PER_WORD);
2423  if (!reload_completed)
2424    {
2425      if (reg_overlap_mentioned_p (operands[4], operands[8]))
2426	operands[8] = copy_to_mode_reg (<vmode_PART>mode, operands[8]);
2427      if (reg_overlap_mentioned_p (operands[4], operands[9]))
2428	operands[9] = copy_to_mode_reg (<vmode_PART>mode, operands[9]);
2429      emit_insn (gen_mul<vmode_part>3 (operands[4], operands[5], operands[6]));
2430      emit_insn (gen_mul<vmode_part>3 (operands[7], operands[8], operands[9]));
2431      DONE;
2432    }
2433  gcc_assert (!reg_overlap_mentioned_p (operands[4], operands[8]));
2434  gcc_assert (!reg_overlap_mentioned_p (operands[4], operands[9]));
2435  operands[10] = XVECEXP (operands[3], 0, XVECLEN (operands[3], 0) - 2);
2436  operands[11] = XVECEXP (operands[3], 0, XVECLEN (operands[3], 0) - 1);
2437}
2438  [(set_attr "length" "8")
2439   (set_attr "type" "<vmode_fp_type>")])
2440
2441(define_insn_and_split "*fmadd<mode>_combine"
2442  [(match_parallel 4 "float_operation"
2443     [(set (match_operand:DWV2MODE 0 "gpr_operand" "=r")
2444	   (plus:DWV2MODE (mult:<MODE>
2445				(match_operand:<MODE> 1 "gpr_operand" "r")
2446				(match_operand:<MODE> 2 "gpr_operand" "r"))
2447			  (match_operand:<MODE> 3 "gpr_operand" "0")))
2448      (clobber (reg:CC_FP CCFP_REGNUM))])]
2449  "TARGET_FUSED_MADD || <MODE>mode == V2SImode"
2450  "#"
2451  "reload_completed || (epiphany_vect_align == 4 && TARGET_SPLIT_VECMOVE_EARLY)"
2452  [(parallel
2453     [(set (match_dup 5)
2454	   (plus:<vmode_PART> (mult:<vmode_PART> (match_dup 6) (match_dup 7))
2455			      (match_dup 8)))
2456      (clobber (reg:CC_FP CCFP_REGNUM))
2457      (match_dup 13)
2458      (match_dup 14)])
2459   (parallel
2460     [(set (match_dup 9)
2461	   (plus:<vmode_PART> (mult:<vmode_PART> (match_dup 10) (match_dup 11))
2462			      (match_dup 12)))
2463      (clobber (reg:CC_FP CCFP_REGNUM))
2464      (match_dup 13)
2465      (match_dup 14)])]
2466{
2467  operands[5]
2468    = simplify_gen_subreg (<vmode_PART>mode, operands[0], <MODE>mode, 0);
2469  operands[6]
2470    = simplify_gen_subreg (<vmode_PART>mode, operands[1], <MODE>mode, 0);
2471  operands[7]
2472    = simplify_gen_subreg (<vmode_PART>mode, operands[2], <MODE>mode, 0);
2473  operands[8]
2474    = simplify_gen_subreg (<vmode_PART>mode, operands[3], <MODE>mode, 0);
2475  operands[9] = simplify_gen_subreg (<vmode_PART>mode, operands[0],
2476				     <MODE>mode, UNITS_PER_WORD);
2477  operands[10] = simplify_gen_subreg (<vmode_PART>mode, operands[1],
2478				      <MODE>mode, UNITS_PER_WORD);
2479  operands[11] = simplify_gen_subreg (<vmode_PART>mode, operands[2],
2480				      <MODE>mode, UNITS_PER_WORD);
2481  operands[12] = simplify_gen_subreg (<vmode_PART>mode, operands[3],
2482				      <MODE>mode, UNITS_PER_WORD);
2483  if (!reload_completed)
2484    {
2485      if (reg_overlap_mentioned_p (operands[5], operands[10]))
2486	operands[10] = copy_to_mode_reg (<vmode_PART>mode, operands[10]);
2487      if (reg_overlap_mentioned_p (operands[5], operands[11]))
2488	operands[11] = copy_to_mode_reg (<vmode_PART>mode, operands[11]);
2489      if (reg_overlap_mentioned_p (operands[5], operands[12]))
2490	operands[12] = copy_to_mode_reg (<vmode_PART>mode, operands[12]);
2491      emit_insn (gen_madd<vmode_part> (operands[5], operands[6], operands[7],
2492				       operands[8]));
2493      emit_insn (gen_madd<vmode_part> (operands[9], operands[10], operands[11],
2494				       operands[12]));
2495      DONE;
2496    }
2497  gcc_assert (!reg_overlap_mentioned_p (operands[5], operands[10]));
2498  gcc_assert (!reg_overlap_mentioned_p (operands[5], operands[11]));
2499  gcc_assert (!reg_overlap_mentioned_p (operands[5], operands[12]));
2500  operands[13] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);
2501  operands[14] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);
2502}
2503  [(set_attr "length" "8")
2504   (set_attr "type" "<vmode_fp_type>")])
2505
2506(define_expand "vec_set<mode>"
2507  [(match_operand:DWV2MODE 0 "register_operand")
2508   (match_operand:<vmode_PART> 1 "register_operand")
2509   (match_operand 2 "const_int_operand" "")]
2510  ""
2511{
2512  operands[0]
2513    = simplify_gen_subreg (<vmode_PART>mode, operands[0], <MODE>mode,
2514			   UNITS_PER_WORD * INTVAL (operands[2]));
2515  emit_move_insn (operands[0], operands[1]);
2516  DONE;
2517})
2518
2519(define_expand "movmisalign<mode>"
2520 [(set (match_operand:DWV2MODE 0 "nonimmediate_operand" "")
2521       (match_operand:DWV2MODE 1 "general_operand" ""))]
2522 ""
2523{
2524  rtx op00, op01, op10, op11;
2525
2526  op00 = simplify_gen_subreg (<vmode_PART>mode, operands[0], <MODE>mode, 0);
2527  op01 = simplify_gen_subreg (<vmode_PART>mode, operands[0], <MODE>mode,
2528			      UNITS_PER_WORD);
2529  op10 = simplify_gen_subreg (<vmode_PART>mode, operands[1], <MODE>mode, 0);
2530  op11 = simplify_gen_subreg (<vmode_PART>mode, operands[1], <MODE>mode,
2531			      UNITS_PER_WORD);
2532  emit_move_insn (op00, op10);
2533  emit_move_insn (op01, op11);
2534  DONE;
2535})
2536
2537(define_insn "nop"
2538  [(const_int 0)]
2539  ""
2540  "nop"
2541  [(set_attr "type" "flow")])
2542