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