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