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