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