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