]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/v850/v850.md
v850e3v5.md (fmasf4): Use fmaf.s on E3V5 architectures.
[thirdparty/gcc.git] / gcc / config / v850 / v850.md
1 ;; GCC machine description for NEC V850
2 ;; Copyright (C) 1996-2013 Free Software Foundation, Inc.
3 ;; Contributed by Jeff Law (law@cygnus.com).
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 ;; The original PO technology requires these to be ordered by speed,
22 ;; so that assigner will pick the fastest.
23
24 ;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
25
26 ;; The V851 manual states that the instruction address space is 16M;
27 ;; the various branch/call instructions only have a 22bit offset (4M range).
28 ;;
29 ;; One day we'll probably need to handle calls to targets more than 4M
30 ;; away.
31
32 ;; The size of instructions in bytes.
33
34 ;;---------------------------------------------------------------------------
35 ;; Constants
36
37 ;;
38 (define_constants
39 [(ZERO_REGNUM 0) ; constant zero
40 (SP_REGNUM 3) ; Stack Pointer
41 (GP_REGNUM 4) ; GP Pointer
42 (EP_REGNUM 30) ; EP pointer
43 (LP_REGNUM 31) ; Return address register
44 (CC_REGNUM 32) ; Condition code pseudo register
45 (FCC_REGNUM 33) ; Floating Condition code pseudo register
46 (UNSPEC_LOOP 200) ; loop counter
47 ]
48 )
49
50 (define_attr "length" ""
51 (const_int 4))
52
53 (define_attr "long_calls" "yes,no"
54 (const (if_then_else (symbol_ref "TARGET_LONG_CALLS")
55 (const_string "yes")
56 (const_string "no"))))
57
58 ;; Types of instructions (for scheduling purposes).
59
60 (define_attr "type" "load,store,bit1,mult,macc,div,fpu,single,other"
61 (const_string "other"))
62
63 (define_attr "cpu" "none,v850,v850e,v850e1,v850e2,v850e2v3,v850e3v5"
64 (cond [(match_test "TARGET_V850")
65 (const_string "v850")
66 (match_test "TARGET_V850E")
67 (const_string "v850e")
68 (match_test "TARGET_V850E1")
69 (const_string "v850e1")
70 (match_test "TARGET_V850E2")
71 (const_string "v850e2")
72 (match_test "TARGET_V850E2V3")
73 (const_string "v850e2v3")
74 (match_test "TARGET_V850E3V5")
75 (const_string "v850e3v5")]
76 (const_string "none")))
77
78 ;; Condition code settings.
79 ;; none - insn does not affect cc
80 ;; none_0hit - insn does not affect cc but it does modify operand 0
81 ;; This attribute is used to keep track of when operand 0 changes.
82 ;; See the description of NOTICE_UPDATE_CC for more info.
83 ;; set_znv - sets z,n,v to usable values; c is unknown.
84 ;; set_zn - sets z,n to usable values; v,c is unknown.
85 ;; compare - compare instruction
86 ;; clobber - value of cc is unknown
87 (define_attr "cc" "none,none_0hit,set_z,set_zn,set_znv,compare,clobber"
88 (const_string "clobber"))
89 \f
90 ;; Function units for the V850. As best as I can tell, there's
91 ;; a traditional memory load/use stall as well as a stall if
92 ;; the result of a multiply is used too early.
93
94 (define_insn_reservation "v850_other" 1
95 (eq_attr "type" "other")
96 "nothing")
97 (define_insn_reservation "v850_mult" 2
98 (eq_attr "type" "mult")
99 "nothing")
100 (define_insn_reservation "v850_memory" 2
101 (eq_attr "type" "load")
102 "nothing")
103
104 (include "predicates.md")
105 (include "constraints.md")
106 \f
107 ;; ----------------------------------------------------------------------
108 ;; MOVE INSTRUCTIONS
109 ;; ----------------------------------------------------------------------
110 (define_insn "sign23byte_load"
111 [(set (match_operand:SI 0 "register_operand" "=r")
112 (sign_extend:SI
113 (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "r")
114 (match_operand 2 "disp23_operand" "W")))))]
115 "TARGET_V850E2V3_UP"
116 "ld.b %2[%1],%0"
117 [(set_attr "length" "4")
118 (set_attr "cc" "none_0hit")])
119
120 (define_insn "unsign23byte_load"
121 [(set (match_operand:SI 0 "register_operand" "=r")
122 (zero_extend:SI
123 (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "r")
124 (match_operand 2 "disp23_operand" "W")))))]
125 "TARGET_V850E2V3_UP"
126 "ld.bu %2[%1],%0"
127 [(set_attr "length" "4")
128 (set_attr "cc" "none_0hit")])
129
130 (define_insn "sign23hword_load"
131 [(set (match_operand:SI 0 "register_operand" "=r")
132 (sign_extend:SI
133 (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "r")
134 (match_operand 2 "disp23_operand" "W")))))]
135 "TARGET_V850E2V3_UP"
136 "ld.h %2[%1],%0"
137 [(set_attr "length" "4")
138 (set_attr "cc" "none_0hit")])
139
140 (define_insn "unsign23hword_load"
141 [(set (match_operand:SI 0 "register_operand" "=r")
142 (zero_extend:SI
143 (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "r")
144 (match_operand 2 "disp23_operand" "W")))))]
145 "TARGET_V850E2V3_UP"
146 "ld.hu %2[%1],%0"
147 [(set_attr "length" "4")
148 (set_attr "cc" "none_0hit")])
149
150 (define_insn "23word_load"
151 [(set (match_operand:SI 0 "register_operand" "=r")
152 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
153 (match_operand 2 "disp23_operand" "W"))))]
154 "TARGET_V850E2V3_UP"
155 "ld.w %2[%1],%0"
156 [(set_attr "length" "4")
157 (set_attr "cc" "none_0hit")])
158
159 (define_insn "23byte_store"
160 [(set (mem:QI (plus:SI (match_operand:SI 0 "register_operand" "r")
161 (match_operand 1 "disp23_operand" "W")))
162 (match_operand:QI 2 "register_operand" "r"))]
163 "TARGET_V850E2V3_UP"
164 "st.b %2,%1[%0]"
165 [(set_attr "length" "4")
166 (set_attr "cc" "none_0hit")])
167
168 (define_insn "23hword_store"
169 [(set (mem:HI (plus:SI (match_operand:SI 0 "register_operand" "r")
170 (match_operand 1 "disp23_operand" "W")))
171 (match_operand:HI 2 "register_operand" "r"))]
172 "TARGET_V850E2V3_UP"
173 "st.h %2,%1[%0]"
174 [(set_attr "length" "4")
175 (set_attr "cc" "none_0hit")])
176
177 (define_insn "23word_store"
178 [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
179 (match_operand 1 "disp23_operand" "W")))
180 (match_operand:SI 2 "register_operand" "r"))]
181 "TARGET_V850E2V3_UP"
182 "st.w %2,%1[%0]"
183 [(set_attr "length" "4")
184 (set_attr "cc" "none_0hit")])
185
186 ;; movdi
187
188 (define_expand "movdi"
189 [(set (match_operand:DI 0 "general_operand")
190 (match_operand:DI 1 "general_operand"))]
191 "TARGET_V850E3V5_UP"
192 {
193 /* One of the ops has to be in a register or 0. */
194 if (!register_operand (operand0, DImode)
195 && !register_operand (operand1, DImode))
196 operands[1] = copy_to_mode_reg (DImode, operand1);
197
198 if (register_operand (operand0, DImode)
199 && (CONST_INT_P (operands[1]) || CONST_DOUBLE_P (operands[1])))
200 {
201 int i;
202
203 for (i = 0; i < UNITS_PER_WORD * 2; i += UNITS_PER_WORD)
204 emit_move_insn (simplify_gen_subreg (SImode, operands[0], DImode, i),
205 simplify_gen_subreg (SImode, operands[1], DImode, i));
206 DONE;
207 }
208 }
209 )
210
211 (define_insn "*movdi_internal"
212 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,e!r,m")
213 (match_operand:DI 1 "nonimmediate_operand" "r,m,e!r"))]
214 "TARGET_V850E3V5_UP
215 || (register_operand (operands[0], DImode) && register_operand (operands[1], DImode))"
216 { return v850_gen_movdi (operands); }
217 [(set_attr "length" "4,12,12")
218 (set_attr "cc" "none_0hit")
219 (set_attr "type" "other,load,store")]
220 )
221
222 ;; movqi
223
224 (define_expand "movqi"
225 [(set (match_operand:QI 0 "general_operand" "")
226 (match_operand:QI 1 "general_operand" ""))]
227 ""
228 {
229 /* One of the ops has to be in a register or 0 */
230 if (!register_operand (operand0, QImode)
231 && !reg_or_0_operand (operand1, QImode))
232 operands[1] = copy_to_mode_reg (QImode, operand1);
233 })
234
235 (define_insn "*movqi_internal"
236 [(set (match_operand:QI 0 "general_operand" "=r,r,r,Q,r,m,m")
237 (match_operand:QI 1 "general_operand" "Jr,n,Q,Ir,m,r,I"))]
238 "register_operand (operands[0], QImode)
239 || reg_or_0_operand (operands[1], QImode)"
240 {
241 return output_move_single (operands);
242 }
243 [(set_attr "length" "2,4,2,2,4,4,4")
244 (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")
245 (set_attr "type" "other,other,load,other,load,store,store")])
246
247 ;; movhi
248
249 (define_expand "movhi"
250 [(set (match_operand:HI 0 "general_operand" "")
251 (match_operand:HI 1 "general_operand" ""))]
252 ""
253 {
254 /* One of the ops has to be in a register or 0 */
255 if (!register_operand (operand0, HImode)
256 && !reg_or_0_operand (operand1, HImode))
257 operands[1] = copy_to_mode_reg (HImode, operand1);
258 })
259
260 (define_insn "*movhi_internal"
261 [(set (match_operand:HI 0 "general_operand" "=r,r,r,Q,r,m,m")
262 (match_operand:HI 1 "general_operand" "Jr,n,Q,Ir,m,r,I"))]
263 "register_operand (operands[0], HImode)
264 || reg_or_0_operand (operands[1], HImode)"
265 {
266 return output_move_single (operands);
267 }
268 [(set_attr "length" "2,4,2,2,4,4,4")
269 (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")
270 (set_attr "type" "other,other,load,other,load,store,store")])
271
272 ;; movsi and helpers
273
274 (define_insn "*movsi_high"
275 [(set (match_operand:SI 0 "register_operand" "=r")
276 (high:SI (match_operand 1 "immediate_operand" "i")))]
277 ""
278 "movhi hi(%1),%.,%0"
279 [(set_attr "length" "4")
280 (set_attr "cc" "none_0hit")
281 (set_attr "type" "other")])
282
283 (define_insn "*movsi_lo"
284 [(set (match_operand:SI 0 "register_operand" "=r")
285 (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
286 (match_operand:SI 2 "immediate_operand" "i")))]
287 ""
288 "movea lo(%2),%1,%0"
289 [(set_attr "length" "4")
290 (set_attr "cc" "none_0hit")
291 (set_attr "type" "other")])
292
293 (define_expand "movsi"
294 [(set (match_operand:SI 0 "general_operand" "")
295 (match_operand:SI 1 "general_operand" ""))]
296 ""
297 {
298 /* One of the ops has to be in a register or 0 */
299 if (!register_operand (operand0, SImode)
300 && !reg_or_0_operand (operand1, SImode))
301 operands[1] = copy_to_mode_reg (SImode, operand1);
302
303 /* Some constants, as well as symbolic operands
304 must be done with HIGH & LO_SUM patterns. */
305 if (CONSTANT_P (operands[1])
306 && GET_CODE (operands[1]) != HIGH
307 && ! (TARGET_V850E_UP)
308 && !special_symbolref_operand (operands[1], VOIDmode)
309 && !(GET_CODE (operands[1]) == CONST_INT
310 && (CONST_OK_FOR_J (INTVAL (operands[1]))
311 || CONST_OK_FOR_K (INTVAL (operands[1]))
312 || CONST_OK_FOR_L (INTVAL (operands[1])))))
313 {
314 rtx temp;
315
316 if (reload_in_progress || reload_completed)
317 temp = operands[0];
318 else
319 temp = gen_reg_rtx (SImode);
320
321 emit_insn (gen_rtx_SET (SImode, temp,
322 gen_rtx_HIGH (SImode, operand1)));
323 emit_insn (gen_rtx_SET (SImode, operand0,
324 gen_rtx_LO_SUM (SImode, temp, operand1)));
325 DONE;
326 }
327 })
328
329 ;; This is the same as the following pattern, except that it includes
330 ;; support for arbitrary 32-bit immediates.
331
332 ;; ??? This always loads addresses using hilo. If the only use of this address
333 ;; was in a load/store, then we would get smaller code if we only loaded the
334 ;; upper part with hi, and then put the lower part in the load/store insn.
335
336 (define_insn "*movsi_internal_v850e"
337 [(set (match_operand:SI 0 "general_operand" "=r,r,r,r,Q,r,r,m,m,r")
338 (match_operand:SI 1 "general_operand" "Jr,K,L,Q,Ir,m,R,r,I,i"))]
339 "(TARGET_V850E_UP)
340 && (register_operand (operands[0], SImode)
341 || reg_or_0_operand (operands[1], SImode))"
342 {
343 return output_move_single (operands);
344 }
345 [(set_attr "length" "2,4,4,2,2,4,4,4,4,6")
346 (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")
347 (set_attr "type" "other,other,other,load,other,load,other,store,store,other")])
348
349 (define_insn "*movsi_internal"
350 [(set (match_operand:SI 0 "general_operand" "=r,r,r,r,Q,r,r,m,m")
351 (match_operand:SI 1 "movsi_source_operand" "Jr,K,L,Q,Ir,m,R,r,I"))]
352 "register_operand (operands[0], SImode)
353 || reg_or_0_operand (operands[1], SImode)"
354 {
355 return output_move_single (operands);
356 }
357 [(set_attr "length" "2,4,4,2,2,4,4,4,4")
358 (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")
359 (set_attr "type" "other,other,other,load,other,load,store,store,other")])
360
361 (define_insn "*movsf_internal"
362 [(set (match_operand:SF 0 "general_operand" "=r,r,r,r,r,Q,r,m,m,r")
363 (match_operand:SF 1 "general_operand" "Jr,K,L,n,Q,Ir,m,r,IG,iF"))]
364 "register_operand (operands[0], SFmode)
365 || reg_or_0_operand (operands[1], SFmode)"
366 {
367 return output_move_single (operands);
368 }
369 [(set_attr "length" "2,4,4,8,2,2,4,4,4,8")
370 (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")
371 (set_attr "type" "other,other,other,other,load,other,load,store,store,other")])
372
373 ;; ----------------------------------------------------------------------
374 ;; TEST INSTRUCTIONS
375 ;; ----------------------------------------------------------------------
376
377 (define_insn "*v850_tst1"
378 [(set (cc0)
379 (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m")
380 (const_int 1)
381 (match_operand:QI 1 "const_int_operand" "n"))
382 (const_int 0)))]
383 ""
384 "tst1 %1,%0"
385 [(set_attr "length" "4")
386 (set_attr "cc" "clobber")])
387
388 ;; This replaces ld.b;sar;andi with tst1;setf nz.
389
390 (define_split
391 [(set (match_operand:SI 0 "register_operand" "")
392 (compare (zero_extract:SI (match_operand:QI 1 "memory_operand" "")
393 (const_int 1)
394 (match_operand 2 "const_int_operand" ""))
395 (const_int 0)))]
396 ""
397 [(set (cc0) (compare (zero_extract:SI (match_dup 1)
398 (const_int 1)
399 (match_dup 2))
400 (const_int 0)))
401 (set (match_dup 0) (ne:SI (cc0) (const_int 0)))])
402
403 (define_expand "cbranchsi4"
404 [(set (cc0)
405 (compare (match_operand:SI 1 "register_operand" "")
406 (match_operand:SI 2 "reg_or_int5_operand" "")))
407 (set (pc)
408 (if_then_else
409 (match_operator 0 "ordered_comparison_operator" [(cc0)
410 (const_int 0)])
411 (label_ref (match_operand 3 "" ""))
412 (pc)))]
413 "")
414
415 (define_expand "cstoresi4"
416 [(set (cc0)
417 (compare (match_operand:SI 2 "register_operand" "")
418 (match_operand:SI 3 "reg_or_int5_operand" "")))
419 (set (match_operand:SI 0 "register_operand")
420 (match_operator:SI 1 "ordered_comparison_operator" [(cc0)
421 (const_int 0)]))]
422 "")
423
424 (define_expand "cmpsi"
425 [(set (cc0)
426 (compare (match_operand:SI 0 "register_operand" "r,r")
427 (match_operand:SI 1 "reg_or_int5_operand" "r,J")))]
428 ""
429 {
430 v850_compare_op0 = operands[0];
431 v850_compare_op1 = operands[1];
432 DONE;
433 })
434
435 (define_insn "cmpsi_insn"
436 [(set (cc0)
437 (compare (match_operand:SI 0 "register_operand" "r,r")
438 (match_operand:SI 1 "reg_or_int5_operand" "r,J")))]
439 ""
440 "@
441 cmp %1,%0
442 cmp %1,%0"
443 [(set_attr "length" "2,2")
444 (set_attr "cc" "compare")])
445
446 (define_expand "cbranchsf4"
447 [(set (pc)
448 (if_then_else (match_operator 0 "ordered_comparison_operator"
449 [(match_operand:SF 1 "register_operand")
450 (match_operand:SF 2 "register_operand")])
451 (label_ref (match_operand 3 ""))
452 (pc)))
453 (clobber (cc0))]
454 "TARGET_USE_FPU"
455 {
456 enum rtx_code cond = GET_CODE (operands[0]);
457 enum machine_mode mode;
458 rtx fcc_reg;
459 rtx cc_reg;
460 rtx tmp;
461
462 v850_compare_op0 = operands[1];
463 v850_compare_op1 = operands[2];
464
465 if (GET_MODE_CLASS (GET_MODE (v850_compare_op0)) != MODE_FLOAT)
466 FAIL;
467
468 mode = v850_gen_float_compare (cond, VOIDmode, v850_compare_op0, v850_compare_op1);
469 fcc_reg = gen_rtx_REG (mode, FCC_REGNUM);
470 cc_reg = gen_rtx_REG (mode, CC_REGNUM);
471 emit_insn(gen_rtx_SET (mode, cc_reg, fcc_reg));
472 tmp = gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx);
473 tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
474 gen_rtx_LABEL_REF (VOIDmode, operands[3]), pc_rtx);
475 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
476 DONE;
477 })
478
479 (define_insn "cstoresf4"
480 [(set (match_operand:SI 0 "register_operand" "=r")
481 (match_operator:SI 1 "ordered_comparison_operator"
482 [(match_operand:SF 2 "register_operand" "r")
483 (match_operand:SF 3 "register_operand" "r")]))]
484 "TARGET_USE_FPU"
485 {
486 if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE)
487 return "cmpf.s %c1, %z2, %z3 ; trfsr ; setf nz, %0";
488 if (GET_CODE (operands[1]) == LT || GET_CODE (operands[1]) == LE)
489 return "cmpf.s %c1, %z2, %z3 ; trfsr ; setf z, %0";
490 if (GET_CODE (operands[1]) == EQ)
491 return "cmpf.s eq, %z2, %z3 ; trfsr ; setf z, %0";
492 if (GET_CODE (operands[1]) == NE)
493 return "cmpf.s neq, %z2, %z3 ; trfsr ; setf nz, %0";
494 gcc_unreachable ();
495 }
496 [(set_attr "length" "12")
497 (set_attr "type" "fpu")]
498 )
499
500 (define_expand "cbranchdf4"
501 [(set (pc)
502 (if_then_else (match_operator 0 "ordered_comparison_operator"
503 [(match_operand:DF 1 "even_reg_operand")
504 (match_operand:DF 2 "even_reg_operand")])
505 (label_ref (match_operand 3 ""))
506 (pc)))
507 (clobber (cc0))]
508 "TARGET_USE_FPU"
509 {
510 enum rtx_code cond = GET_CODE (operands[0]);
511 enum machine_mode mode;
512 rtx fcc_reg;
513 rtx cc_reg;
514 rtx tmp;
515
516 v850_compare_op0 = operands[1];
517 v850_compare_op1 = operands[2];
518
519 if (GET_MODE_CLASS (GET_MODE (v850_compare_op0)) != MODE_FLOAT)
520 FAIL;
521
522 mode = v850_gen_float_compare (cond, VOIDmode, v850_compare_op0, v850_compare_op1);
523 fcc_reg = gen_rtx_REG (mode, FCC_REGNUM);
524 cc_reg = gen_rtx_REG (mode, CC_REGNUM);
525 emit_insn(gen_rtx_SET (mode, cc_reg, fcc_reg));
526 tmp = gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx);
527 tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
528 gen_rtx_LABEL_REF (VOIDmode, operands[3]), pc_rtx);
529 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
530 DONE;
531 })
532
533 (define_insn "cstoredf4"
534 [(set (match_operand:SI 0 "register_operand" "=r")
535 (match_operator:SI 1 "ordered_comparison_operator"
536 [(match_operand:DF 2 "even_reg_operand" "r")
537 (match_operand:DF 3 "even_reg_operand" "r")]))]
538 "TARGET_USE_FPU"
539 {
540 if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE)
541 return "cmpf.d %c1, %z2, %z3 ; trfsr ; setf nz, %0";
542 if (GET_CODE (operands[1]) == LT || GET_CODE (operands[1]) == LE)
543 return "cmpf.d %c1, %z2, %z3 ; trfsr ; setf z, %0";
544 if (GET_CODE (operands[1]) == EQ)
545 return "cmpf.d eq, %z2, %z3 ; trfsr ; setf z ,%0";
546 if (GET_CODE (operands[1]) == NE)
547 return "cmpf.d neq, %z2, %z3 ; trfsr ; setf nz, %0";
548 gcc_unreachable ();
549 }
550 [(set_attr "length" "12")
551 (set_attr "type" "fpu")]
552 )
553
554 (define_expand "cmpsf"
555 [(set (reg:CC CC_REGNUM)
556 (compare (match_operand:SF 0 "register_operand" "r")
557 (match_operand:SF 1 "register_operand" "r")))]
558 "TARGET_USE_FPU"
559 {
560 v850_compare_op0 = operands[0];
561 v850_compare_op1 = operands[1];
562 DONE;
563 })
564
565 (define_expand "cmpdf"
566 [(set (reg:CC CC_REGNUM)
567 (compare (match_operand:DF 0 "even_reg_operand" "r")
568 (match_operand:DF 1 "even_reg_operand" "r")))]
569 "TARGET_USE_FPU"
570 {
571 v850_compare_op0 = operands[0];
572 v850_compare_op1 = operands[1];
573 DONE;
574 })
575
576 ;; ----------------------------------------------------------------------
577 ;; ADD INSTRUCTIONS
578 ;; ----------------------------------------------------------------------
579
580 (define_insn "addsi3"
581 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
582 (plus:SI (match_operand:SI 1 "register_operand" "%0,r,r")
583 (match_operand:SI 2 "nonmemory_operand" "rJ,K,U")))
584 (clobber (reg:CC CC_REGNUM))]
585
586 ""
587 "@
588 add %2,%0
589 addi %2,%1,%0
590 addi %O2(%P2),%1,%0"
591 [(set_attr "length" "2,4,4")
592 (set_attr "cc" "set_zn,set_zn,set_zn")])
593
594 ;; ----------------------------------------------------------------------
595 ;; SUBTRACT INSTRUCTIONS
596 ;; ----------------------------------------------------------------------
597
598 (define_insn "subsi3"
599 [(set (match_operand:SI 0 "register_operand" "=r,r")
600 (minus:SI (match_operand:SI 1 "register_operand" "0,r")
601 (match_operand:SI 2 "register_operand" "r,0")))
602 (clobber (reg:CC CC_REGNUM))]
603 ""
604 "@
605 sub %2,%0
606 subr %1,%0"
607 [(set_attr "length" "2,2")
608 (set_attr "cc" "set_zn,set_zn")])
609
610 (define_insn "negsi2"
611 [(set (match_operand:SI 0 "register_operand" "=r")
612 (neg:SI (match_operand:SI 1 "register_operand" "0")))
613 (clobber (reg:CC CC_REGNUM))]
614 ""
615 "subr %.,%0"
616 [(set_attr "length" "2")
617 (set_attr "cc" "set_zn")])
618
619 ;; ----------------------------------------------------------------------
620 ;; MULTIPLY INSTRUCTIONS
621 ;; ----------------------------------------------------------------------
622
623 (define_expand "mulhisi3"
624 [(set (match_operand:SI 0 "register_operand" "")
625 (mult:SI
626 (sign_extend:SI (match_operand:HI 1 "register_operand" ""))
627 (sign_extend:SI (match_operand:HI 2 "nonmemory_operand" ""))))]
628 ""
629 {
630 if (GET_CODE (operands[2]) == CONST_INT)
631 {
632 emit_insn (gen_mulhisi3_internal2 (operands[0], operands[1], operands[2]));
633 DONE;
634 }
635 })
636
637 (define_insn "*mulhisi3_internal1"
638 [(set (match_operand:SI 0 "register_operand" "=r")
639 (mult:SI
640 (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
641 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
642 ""
643 "mulh %2,%0"
644 [(set_attr "length" "2")
645 (set_attr "cc" "none_0hit")
646 (set_attr "type" "mult")])
647
648 (define_insn "mulhisi3_internal2"
649 [(set (match_operand:SI 0 "register_operand" "=r,r")
650 (mult:SI
651 (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,r"))
652 (match_operand:HI 2 "const_int_operand" "J,K")))]
653 ""
654 "@
655 mulh %2,%0
656 mulhi %2,%1,%0"
657 [(set_attr "length" "2,4")
658 (set_attr "cc" "none_0hit,none_0hit")
659 (set_attr "type" "mult")])
660
661 ;; ??? The scheduling info is probably wrong.
662
663 ;; ??? This instruction can also generate the 32-bit highpart, but using it
664 ;; may increase code size counter to the desired result.
665
666 ;; ??? This instructions can also give a DImode result.
667
668 ;; ??? There is unsigned version, but it matters only for the DImode/highpart
669 ;; results.
670
671 (define_insn "mulsi3"
672 [(set (match_operand:SI 0 "register_operand" "=r")
673 (mult:SI (match_operand:SI 1 "register_operand" "%0")
674 (match_operand:SI 2 "reg_or_int9_operand" "rO")))]
675 "(TARGET_V850E_UP)"
676 "mul %2,%1,%."
677 [(set_attr "length" "4")
678 (set_attr "cc" "none_0hit")
679 (set_attr "type" "mult")])
680
681 ;; ----------------------------------------------------------------------
682 ;; DIVIDE INSTRUCTIONS
683 ;; ----------------------------------------------------------------------
684
685 ;; ??? These insns do set the Z/N condition codes, except that they are based
686 ;; on only one of the two results, so it doesn't seem to make sense to use
687 ;; them.
688
689 ;; ??? The scheduling info is probably wrong.
690
691 (define_insn "divmodsi4"
692 [(set (match_operand:SI 0 "register_operand" "=r")
693 (div:SI (match_operand:SI 1 "register_operand" "0")
694 (match_operand:SI 2 "register_operand" "r")))
695 (set (match_operand:SI 3 "register_operand" "=r")
696 (mod:SI (match_dup 1)
697 (match_dup 2)))
698 (clobber (reg:CC CC_REGNUM))]
699 "TARGET_V850E_UP"
700 {
701 if (TARGET_V850E2_UP)
702 return "divq %2,%0,%3";
703 else
704 return "div %2,%0,%3";
705 }
706 [(set_attr "length" "4")
707 (set_attr "cc" "clobber")
708 (set_attr "type" "div")])
709
710 (define_insn "udivmodsi4"
711 [(set (match_operand:SI 0 "register_operand" "=r")
712 (udiv:SI (match_operand:SI 1 "register_operand" "0")
713 (match_operand:SI 2 "register_operand" "r")))
714 (set (match_operand:SI 3 "register_operand" "=r")
715 (umod:SI (match_dup 1)
716 (match_dup 2)))
717 (clobber (reg:CC CC_REGNUM))]
718 "TARGET_V850E_UP"
719 {
720 if (TARGET_V850E2_UP)
721 return "divqu %2,%0,%3";
722 else
723 return "divu %2,%0,%3";
724 }
725 [(set_attr "length" "4")
726 (set_attr "cc" "clobber")
727 (set_attr "type" "div")])
728
729 ;; ??? There is a 2 byte instruction for generating only the quotient.
730 ;; However, it isn't clear how to compute the length field correctly.
731
732 (define_insn "divmodhi4"
733 [(set (match_operand:HI 0 "register_operand" "=r")
734 (div:HI (match_operand:HI 1 "register_operand" "0")
735 (match_operand:HI 2 "register_operand" "r")))
736 (set (match_operand:HI 3 "register_operand" "=r")
737 (mod:HI (match_dup 1)
738 (match_dup 2)))
739 (clobber (reg:CC CC_REGNUM))]
740 "TARGET_V850E_UP"
741 "divh %2,%0,%3"
742 [(set_attr "length" "4")
743 (set_attr "cc" "clobber")
744 (set_attr "type" "div")])
745
746 ;; Half-words are sign-extended by default, so we must zero extend to a word
747 ;; here before doing the divide.
748
749 (define_insn "udivmodhi4"
750 [(set (match_operand:HI 0 "register_operand" "=r")
751 (udiv:HI (match_operand:HI 1 "register_operand" "0")
752 (match_operand:HI 2 "register_operand" "r")))
753 (set (match_operand:HI 3 "register_operand" "=r")
754 (umod:HI (match_dup 1)
755 (match_dup 2)))
756 (clobber (reg:CC CC_REGNUM))]
757 "TARGET_V850E_UP"
758 "zxh %0 ; divhu %2,%0,%3"
759 [(set_attr "length" "4")
760 (set_attr "cc" "clobber")
761 (set_attr "type" "div")])
762 \f
763 ;; ----------------------------------------------------------------------
764 ;; AND INSTRUCTIONS
765 ;; ----------------------------------------------------------------------
766
767 (define_insn "*v850_clr1_1"
768 [(set (match_operand:QI 0 "memory_operand" "=m")
769 (subreg:QI
770 (and:SI (subreg:SI (match_dup 0) 0)
771 (match_operand:QI 1 "not_power_of_two_operand" "")) 0))
772 (clobber (reg:CC CC_REGNUM))]
773 ""
774 {
775 rtx xoperands[2];
776 xoperands[0] = operands[0];
777 xoperands[1] = GEN_INT (~INTVAL (operands[1]) & 0xff);
778 output_asm_insn ("clr1 %M1,%0", xoperands);
779 return "";
780 }
781 [(set_attr "length" "4")
782 (set_attr "cc" "clobber")
783 (set_attr "type" "bit1")])
784
785 (define_insn "*v850_clr1_2"
786 [(set (match_operand:HI 0 "indirect_operand" "=m")
787 (subreg:HI
788 (and:SI (subreg:SI (match_dup 0) 0)
789 (match_operand:HI 1 "not_power_of_two_operand" "")) 0))
790 (clobber (reg:CC CC_REGNUM))]
791 ""
792 {
793 int log2 = exact_log2 (~INTVAL (operands[1]) & 0xffff);
794
795 rtx xoperands[2];
796 xoperands[0] = gen_rtx_MEM (QImode,
797 plus_constant (Pmode, XEXP (operands[0], 0),
798 log2 / 8));
799 xoperands[1] = GEN_INT (log2 % 8);
800 output_asm_insn ("clr1 %1,%0", xoperands);
801 return "";
802 }
803 [(set_attr "length" "4")
804 (set_attr "cc" "clobber")
805 (set_attr "type" "bit1")])
806
807 (define_insn "*v850_clr1_3"
808 [(set (match_operand:SI 0 "indirect_operand" "=m")
809 (and:SI (match_dup 0)
810 (match_operand:SI 1 "not_power_of_two_operand" "")))
811 (clobber (reg:CC CC_REGNUM))]
812 ""
813 {
814 int log2 = exact_log2 (~INTVAL (operands[1]) & 0xffffffff);
815
816 rtx xoperands[2];
817 xoperands[0] = gen_rtx_MEM (QImode,
818 plus_constant (Pmode, XEXP (operands[0], 0),
819 log2 / 8));
820 xoperands[1] = GEN_INT (log2 % 8);
821 output_asm_insn ("clr1 %1,%0", xoperands);
822 return "";
823 }
824 [(set_attr "length" "4")
825 (set_attr "cc" "clobber")
826 (set_attr "type" "bit1")])
827
828 (define_insn "andsi3"
829 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
830 (and:SI (match_operand:SI 1 "register_operand" "%0,0,r")
831 (match_operand:SI 2 "nonmemory_operand" "r,I,M")))
832 (clobber (reg:CC CC_REGNUM))]
833 ""
834 "@
835 and %2,%0
836 and %.,%0
837 andi %2,%1,%0"
838 [(set_attr "length" "2,2,4")
839 (set_attr "cc" "set_zn")])
840
841 ;; ----------------------------------------------------------------------
842 ;; OR INSTRUCTIONS
843 ;; ----------------------------------------------------------------------
844
845 (define_insn "*v850_set1_1"
846 [(set (match_operand:QI 0 "memory_operand" "=m")
847 (subreg:QI (ior:SI (subreg:SI (match_dup 0) 0)
848 (match_operand 1 "power_of_two_operand" "")) 0))
849 (clobber (reg:CC CC_REGNUM))]
850 ""
851 "set1 %M1,%0"
852 [(set_attr "length" "4")
853 (set_attr "cc" "clobber")
854 (set_attr "type" "bit1")])
855
856 (define_insn "*v850_set1_2"
857 [(set (match_operand:HI 0 "indirect_operand" "=m")
858 (subreg:HI (ior:SI (subreg:SI (match_dup 0) 0)
859 (match_operand 1 "power_of_two_operand" "")) 0))]
860 ""
861 {
862 int log2 = exact_log2 (INTVAL (operands[1]));
863
864 if (log2 < 8)
865 return "set1 %M1,%0";
866 else
867 {
868 rtx xoperands[2];
869 xoperands[0] = gen_rtx_MEM (QImode,
870 plus_constant (Pmode, XEXP (operands[0], 0),
871 log2 / 8));
872 xoperands[1] = GEN_INT (log2 % 8);
873 output_asm_insn ("set1 %1,%0", xoperands);
874 }
875 return "";
876 }
877 [(set_attr "length" "4")
878 (set_attr "cc" "clobber")
879 (set_attr "type" "bit1")])
880
881 (define_insn "*v850_set1_3"
882 [(set (match_operand:SI 0 "indirect_operand" "=m")
883 (ior:SI (match_dup 0)
884 (match_operand 1 "power_of_two_operand" "")))
885 (clobber (reg:CC CC_REGNUM))]
886 ""
887 {
888 int log2 = exact_log2 (INTVAL (operands[1]));
889
890 if (log2 < 8)
891 return "set1 %M1,%0";
892 else
893 {
894 rtx xoperands[2];
895 xoperands[0] = gen_rtx_MEM (QImode,
896 plus_constant (Pmode, XEXP (operands[0], 0),
897 log2 / 8));
898 xoperands[1] = GEN_INT (log2 % 8);
899 output_asm_insn ("set1 %1,%0", xoperands);
900 }
901 return "";
902 }
903 [(set_attr "length" "4")
904 (set_attr "cc" "clobber")
905 (set_attr "type" "bit1")])
906
907 (define_insn "iorsi3"
908 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
909 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,r")
910 (match_operand:SI 2 "nonmemory_operand" "r,I,M")))
911 (clobber (reg:CC CC_REGNUM))]
912 ""
913 "@
914 or %2,%0
915 or %.,%0
916 ori %2,%1,%0"
917 [(set_attr "length" "2,2,4")
918 (set_attr "cc" "set_zn")])
919
920 ;; ----------------------------------------------------------------------
921 ;; XOR INSTRUCTIONS
922 ;; ----------------------------------------------------------------------
923
924 (define_insn "*v850_not1_1"
925 [(set (match_operand:QI 0 "memory_operand" "=m")
926 (subreg:QI (xor:SI (subreg:SI (match_dup 0) 0)
927 (match_operand 1 "power_of_two_operand" "")) 0))
928 (clobber (reg:CC CC_REGNUM))]
929 ""
930 "not1 %M1,%0"
931 [(set_attr "length" "4")
932 (set_attr "cc" "clobber")
933 (set_attr "type" "bit1")])
934
935 (define_insn "*v850_not1_2"
936 [(set (match_operand:HI 0 "indirect_operand" "=m")
937 (subreg:HI (xor:SI (subreg:SI (match_dup 0) 0)
938 (match_operand 1 "power_of_two_operand" "")) 0))]
939 ""
940 {
941 int log2 = exact_log2 (INTVAL (operands[1]));
942
943 if (log2 < 8)
944 return "not1 %M1,%0";
945 else
946 {
947 rtx xoperands[2];
948 xoperands[0] = gen_rtx_MEM (QImode,
949 plus_constant (Pmode, XEXP (operands[0], 0),
950 log2 / 8));
951 xoperands[1] = GEN_INT (log2 % 8);
952 output_asm_insn ("not1 %1,%0", xoperands);
953 }
954 return "";
955 }
956 [(set_attr "length" "4")
957 (set_attr "cc" "clobber")
958 (set_attr "type" "bit1")])
959
960 (define_insn "*v850_not1_3"
961 [(set (match_operand:SI 0 "indirect_operand" "=m")
962 (xor:SI (match_dup 0)
963 (match_operand 1 "power_of_two_operand" "")))
964 (clobber (reg:CC CC_REGNUM))]
965 ""
966 {
967 int log2 = exact_log2 (INTVAL (operands[1]));
968
969 if (log2 < 8)
970 return "not1 %M1,%0";
971 else
972 {
973 rtx xoperands[2];
974 xoperands[0] = gen_rtx_MEM (QImode,
975 plus_constant (Pmode, XEXP (operands[0], 0),
976 log2 / 8));
977 xoperands[1] = GEN_INT (log2 % 8);
978 output_asm_insn ("not1 %1,%0", xoperands);
979 }
980 return "";
981 }
982 [(set_attr "length" "4")
983 (set_attr "cc" "clobber")
984 (set_attr "type" "bit1")])
985
986 (define_insn "xorsi3"
987 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
988 (xor:SI (match_operand:SI 1 "register_operand" "%0,0,r")
989 (match_operand:SI 2 "nonmemory_operand" "r,I,M")))
990 (clobber (reg:CC CC_REGNUM))]
991 ""
992 "@
993 xor %2,%0
994 xor %.,%0
995 xori %2,%1,%0"
996 [(set_attr "length" "2,2,4")
997 (set_attr "cc" "set_zn")])
998 \f
999 ;; ----------------------------------------------------------------------
1000 ;; NOT INSTRUCTIONS
1001 ;; ----------------------------------------------------------------------
1002
1003 (define_insn "one_cmplsi2"
1004 [(set (match_operand:SI 0 "register_operand" "=r")
1005 (not:SI (match_operand:SI 1 "register_operand" "r")))
1006 (clobber (reg:CC CC_REGNUM))]
1007 ""
1008 "not %1,%0"
1009 [(set_attr "length" "2")
1010 (set_attr "cc" "set_zn")])
1011
1012 ;; -----------------------------------------------------------------
1013 ;; BIT FIELDS
1014 ;; -----------------------------------------------------------------
1015
1016 ;; ??? Is it worth defining insv and extv for the V850 series?!?
1017
1018 ;; An insv pattern would be useful, but does not get used because
1019 ;; store_bit_field never calls insv when storing a constant value into a
1020 ;; single-bit bitfield.
1021
1022 ;; extv/extzv patterns would be useful, but do not get used because
1023 ;; optimize_bitfield_compare in fold-const usually converts single
1024 ;; bit extracts into an AND with a mask.
1025
1026 (define_insn "insv"
1027 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
1028 (match_operand:SI 1 "immediate_operand" "n")
1029 (match_operand:SI 2 "immediate_operand" "n"))
1030 (match_operand:SI 3 "register_operand" "r"))]
1031 "TARGET_V850E3V5_UP"
1032 "bins %3, %2, %1, %0"
1033 [(set_attr "length" "4")
1034 (set_attr "cc" "set_zn")]
1035 )
1036
1037 ;; -----------------------------------------------------------------
1038 ;; Scc INSTRUCTIONS
1039 ;; -----------------------------------------------------------------
1040
1041 (define_insn "*setcc"
1042 [(set (match_operand:SI 0 "register_operand" "=r")
1043 (match_operator:SI 1 "comparison_operator"
1044 [(cc0) (const_int 0)]))]
1045 ""
1046 {
1047 if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
1048 && (GET_CODE (operands[1]) == GT
1049 || GET_CODE (operands[1]) == GE
1050 || GET_CODE (operands[1]) == LE
1051 || GET_CODE (operands[1]) == LT))
1052 return 0;
1053
1054 return "setf %c1,%0";
1055 }
1056 [(set_attr "length" "4")
1057 (set_attr "cc" "none_0hit")])
1058
1059 (define_insn "setf_insn"
1060 [(set (match_operand:SI 0 "register_operand" "=r")
1061 (match_operator:SI 1 "comparison_operator"
1062 [(reg:CC CC_REGNUM) (const_int 0)]))]
1063 ""
1064 "setf %b1,%0"
1065 [(set_attr "length" "4")
1066 (set_attr "cc" "none_0hit")])
1067
1068 (define_insn "set_z_insn"
1069 [(set (match_operand:SI 0 "register_operand" "=r")
1070 (match_operand 1 "v850_float_z_comparison_operator" ""))]
1071 "TARGET_V850E2V3_UP"
1072 "setf z,%0"
1073 [(set_attr "length" "4")
1074 (set_attr "cc" "none_0hit")])
1075
1076 (define_insn "set_nz_insn"
1077 [(set (match_operand:SI 0 "register_operand" "=r")
1078 (match_operand 1 "v850_float_nz_comparison_operator" ""))]
1079 "TARGET_V850E2V3_UP"
1080 "setf nz,%0"
1081 [(set_attr "length" "4")
1082 (set_attr "cc" "none_0hit")])
1083
1084 ;; ----------------------------------------------------------------------
1085 ;; CONDITIONAL MOVE INSTRUCTIONS
1086 ;; ----------------------------------------------------------------------
1087
1088 ;; Instructions using cc0 aren't allowed to have input reloads, so we must
1089 ;; hide the fact that this instruction uses cc0. We do so by including the
1090 ;; compare instruction inside it.
1091
1092 (define_expand "movsicc"
1093 [(set (match_operand:SI 0 "register_operand" "=r")
1094 (if_then_else:SI
1095 (match_operand 1 "comparison_operator")
1096 (match_operand:SI 2 "reg_or_const_operand" "rJ")
1097 (match_operand:SI 3 "reg_or_const_operand" "rI")))]
1098 "(TARGET_V850E_UP)"
1099 {
1100 /* Make sure that we have an integer comparison... */
1101 if (GET_MODE (XEXP (operands[1], 0)) != CCmode
1102 && GET_MODE (XEXP (operands[1], 0)) != SImode)
1103 FAIL;
1104
1105 if ((GET_CODE (operands[2]) == CONST_INT
1106 && GET_CODE (operands[3]) == CONST_INT))
1107 {
1108 int o2 = INTVAL (operands[2]);
1109 int o3 = INTVAL (operands[3]);
1110
1111 if (o2 == 1 && o3 == 0)
1112 FAIL; /* setf */
1113 if (o3 == 1 && o2 == 0)
1114 FAIL; /* setf */
1115 if (o2 == 0 && (o3 < -16 || o3 > 15) && exact_log2 (o3) >= 0)
1116 FAIL; /* setf + shift */
1117 if (o3 == 0 && (o2 < -16 || o2 > 15) && exact_log2 (o2) >=0)
1118 FAIL; /* setf + shift */
1119 if (o2 != 0)
1120 operands[2] = copy_to_mode_reg (SImode, operands[2]);
1121 if (o3 !=0 )
1122 operands[3] = copy_to_mode_reg (SImode, operands[3]);
1123 }
1124 else
1125 {
1126 if (GET_CODE (operands[2]) != REG)
1127 operands[2] = copy_to_mode_reg (SImode,operands[2]);
1128 if (GET_CODE (operands[3]) != REG)
1129 operands[3] = copy_to_mode_reg (SImode, operands[3]);
1130 }
1131 })
1132
1133 ;; ??? Clobbering the condition codes is overkill.
1134
1135 ;; ??? We sometimes emit an unnecessary compare instruction because the
1136 ;; condition codes may have already been set by an earlier instruction,
1137 ;; but we have no code here to avoid the compare if it is unnecessary.
1138
1139 (define_insn "movsicc_normal_cc"
1140 [(set (match_operand:SI 0 "register_operand" "=r")
1141 (if_then_else:SI
1142 (match_operator 1 "comparison_operator"
1143 [(reg:CC CC_REGNUM) (const_int 0)])
1144 (match_operand:SI 2 "reg_or_int5_operand" "rJ")
1145 (match_operand:SI 3 "reg_or_0_operand" "rI")))]
1146 "(TARGET_V850E_UP)"
1147 "cmov %c1,%2,%z3,%0";
1148 [(set_attr "length" "6")
1149 (set_attr "cc" "compare")])
1150
1151 (define_insn "movsicc_reversed_cc"
1152 [(set (match_operand:SI 0 "register_operand" "=r")
1153 (if_then_else:SI
1154 (match_operator 1 "comparison_operator"
1155 [(reg:CC CC_REGNUM) (const_int 0)])
1156 (match_operand:SI 2 "reg_or_0_operand" "rI")
1157 (match_operand:SI 3 "reg_or_int5_operand" "rJ")))]
1158 "(TARGET_V850E_UP)"
1159 "cmov %C1,%3,%z2,%0"
1160 [(set_attr "length" "6")
1161 (set_attr "cc" "compare")])
1162
1163 (define_insn "*movsicc_normal"
1164 [(set (match_operand:SI 0 "register_operand" "=r")
1165 (if_then_else:SI
1166 (match_operator 1 "comparison_operator"
1167 [(match_operand:SI 4 "register_operand" "r")
1168 (match_operand:SI 5 "reg_or_int5_operand" "rJ")])
1169 (match_operand:SI 2 "reg_or_int5_operand" "rJ")
1170 (match_operand:SI 3 "reg_or_0_operand" "rI")))]
1171 "(TARGET_V850E_UP)"
1172 "cmp %5,%4 ; cmov %c1,%2,%z3,%0"
1173 [(set_attr "length" "6")
1174 (set_attr "cc" "clobber")])
1175
1176 (define_insn "*movsicc_reversed"
1177 [(set (match_operand:SI 0 "register_operand" "=r")
1178 (if_then_else:SI
1179 (match_operator 1 "comparison_operator"
1180 [(match_operand:SI 4 "register_operand" "r")
1181 (match_operand:SI 5 "reg_or_int5_operand" "rJ")])
1182 (match_operand:SI 2 "reg_or_0_operand" "rI")
1183 (match_operand:SI 3 "reg_or_int5_operand" "rJ")))]
1184 "(TARGET_V850E_UP)"
1185 "cmp %5,%4 ; cmov %C1,%3,%z2,%0"
1186 [(set_attr "length" "6")
1187 (set_attr "cc" "clobber")])
1188
1189 (define_insn "*movsicc_tst1"
1190 [(set (match_operand:SI 0 "register_operand" "=r")
1191 (if_then_else:SI
1192 (match_operator 1 "comparison_operator"
1193 [(zero_extract:SI
1194 (match_operand:QI 2 "memory_operand" "m")
1195 (const_int 1)
1196 (match_operand 3 "const_int_operand" "n"))
1197 (const_int 0)])
1198 (match_operand:SI 4 "reg_or_int5_operand" "rJ")
1199 (match_operand:SI 5 "reg_or_0_operand" "rI")))]
1200 "(TARGET_V850E_UP)"
1201 "tst1 %3,%2 ; cmov %c1,%4,%z5,%0"
1202 [(set_attr "length" "8")
1203 (set_attr "cc" "clobber")])
1204
1205 (define_insn "*movsicc_tst1_reversed"
1206 [(set (match_operand:SI 0 "register_operand" "=r")
1207 (if_then_else:SI
1208 (match_operator 1 "comparison_operator"
1209 [(zero_extract:SI
1210 (match_operand:QI 2 "memory_operand" "m")
1211 (const_int 1)
1212 (match_operand 3 "const_int_operand" "n"))
1213 (const_int 0)])
1214 (match_operand:SI 4 "reg_or_0_operand" "rI")
1215 (match_operand:SI 5 "reg_or_int5_operand" "rJ")))]
1216 "(TARGET_V850E_UP)"
1217 "tst1 %3,%2 ; cmov %C1,%5,%z4,%0"
1218 [(set_attr "length" "8")
1219 (set_attr "cc" "clobber")])
1220
1221 ;; Matching for sasf requires combining 4 instructions, so we provide a
1222 ;; dummy pattern to match the first 3, which will always be turned into the
1223 ;; second pattern by subsequent combining. As above, we must include the
1224 ;; comparison to avoid input reloads in an insn using cc0.
1225
1226 (define_insn "*sasf"
1227 [(set (match_operand:SI 0 "register_operand" "=r")
1228 (ior:SI
1229 (match_operator 1 "comparison_operator"
1230 [(match_operand:SI 3 "register_operand" "r")
1231 (match_operand:SI 4 "reg_or_int5_operand" "rJ")])
1232 (ashift:SI (match_operand:SI 2 "register_operand" "0")
1233 (const_int 1))))
1234 (clobber (reg:CC CC_REGNUM))]
1235 "(TARGET_V850E_UP)"
1236 "cmp %4,%3 ; sasf %c1,%0"
1237 [(set_attr "length" "6")
1238 (set_attr "cc" "clobber")])
1239
1240 (define_split
1241 [(set (match_operand:SI 0 "register_operand" "")
1242 (if_then_else:SI
1243 (match_operator 1 "comparison_operator"
1244 [(match_operand:SI 4 "register_operand" "")
1245 (match_operand:SI 5 "reg_or_int5_operand" "")])
1246 (match_operand:SI 2 "const_int_operand" "")
1247 (match_operand:SI 3 "const_int_operand" "")))
1248 (clobber (reg:CC CC_REGNUM))]
1249 "(TARGET_V850E_UP)
1250 && ((INTVAL (operands[2]) ^ INTVAL (operands[3])) == 1)
1251 && ((INTVAL (operands[2]) + INTVAL (operands[3])) != 1)
1252 && (GET_CODE (operands[5]) == CONST_INT
1253 || REGNO (operands[0]) != REGNO (operands[5]))
1254 && REGNO (operands[0]) != REGNO (operands[4])"
1255 [(set (match_dup 0) (match_dup 6))
1256 (parallel [(set (match_dup 0)
1257 (ior:SI (match_op_dup 7 [(match_dup 4) (match_dup 5)])
1258 (ashift:SI (match_dup 0) (const_int 1))))
1259 (clobber (reg:CC CC_REGNUM))])]
1260 {
1261 operands[6] = GEN_INT (INTVAL (operands[2]) >> 1);
1262 if (INTVAL (operands[2]) & 0x1)
1263 operands[7] = operands[1];
1264 else
1265 operands[7] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])),
1266 GET_MODE (operands[1]),
1267 XEXP (operands[1], 0), XEXP (operands[1], 1));
1268 })
1269
1270 ;; ---------------------------------------------------------------------
1271 ;; BYTE SWAP INSTRUCTIONS
1272 ;; ---------------------------------------------------------------------
1273 (define_expand "rotlhi3"
1274 [(parallel [(set (match_operand:HI 0 "register_operand" "")
1275 (rotate:HI (match_operand:HI 1 "register_operand" "")
1276 (match_operand:HI 2 "const_int_operand" "")))
1277 (clobber (reg:CC CC_REGNUM))])]
1278 "(TARGET_V850E_UP)"
1279 {
1280 if (INTVAL (operands[2]) != 8)
1281 FAIL;
1282 })
1283
1284 (define_insn "*rotlhi3_8"
1285 [(set (match_operand:HI 0 "register_operand" "=r")
1286 (rotate:HI (match_operand:HI 1 "register_operand" "r")
1287 (const_int 8)))
1288 (clobber (reg:CC CC_REGNUM))]
1289 "(TARGET_V850E_UP)"
1290 "bsh %1,%0"
1291 [(set_attr "length" "4")
1292 (set_attr "cc" "clobber")])
1293
1294 (define_expand "rotlsi3"
1295 [(parallel [(set (match_operand:SI 0 "register_operand" "")
1296 (rotate:SI (match_operand:SI 1 "register_operand" "")
1297 (match_operand:SI 2 "const_int_operand" "")))
1298 (clobber (reg:CC CC_REGNUM))])]
1299 "(TARGET_V850E_UP)"
1300 {
1301 if (INTVAL (operands[2]) != 16)
1302 FAIL;
1303 })
1304
1305 (define_insn "rotlsi3_a"
1306 [(set (match_operand:SI 0 "register_operand" "=r")
1307 (match_operator:SI 4 "ior_operator"
1308 [(ashift:SI (match_operand:SI 1 "register_operand" "r")
1309 (match_operand:SI 2 "const_int_operand" "n"))
1310 (lshiftrt:SI (match_dup 1)
1311 (match_operand:SI 3 "const_int_operand" "n"))]))]
1312 "TARGET_V850E3V5_UP && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32)"
1313 "rotl %2, %1, %0"
1314 [(set_attr "length" "4")
1315 (set_attr "cc" "set_zn")]
1316 )
1317
1318 (define_insn "rotlsi3_b"
1319 [(set (match_operand:SI 0 "register_operand" "=r")
1320 (match_operator:SI 4 "ior_operator"
1321 [(lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
1322 (match_operand:SI 3 "const_int_operand" "n"))
1323 (ashift:SI (match_dup 1)
1324 (match_operand:SI 2 "const_int_operand" "n"))]))]
1325 "TARGET_V850E3V5_UP && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32)"
1326 "rotl %2, %1, %0"
1327 [(set_attr "length" "4")
1328 (set_attr "cc" "set_zn")]
1329 )
1330
1331 (define_insn "rotlsi3_v850e3v5"
1332 [(set (match_operand:SI 0 "register_operand" "=r")
1333 (rotate:SI (match_operand:SI 1 "register_operand" "r")
1334 (match_operand:SI 2 "e3v5_shift_operand" "rn")))
1335 (clobber (reg:CC CC_REGNUM))]
1336 "TARGET_V850E3V5_UP"
1337 "rotl %2, %1, %0"
1338 [(set_attr "length" "4")
1339 (set_attr "cc" "set_zn")]
1340 )
1341
1342 (define_insn "*rotlsi3_16"
1343 [(set (match_operand:SI 0 "register_operand" "=r")
1344 (rotate:SI (match_operand:SI 1 "register_operand" "r")
1345 (const_int 16)))
1346 (clobber (reg:CC CC_REGNUM))]
1347 "(TARGET_V850E_UP)"
1348 "hsw %1,%0"
1349 [(set_attr "length" "4")
1350 (set_attr "cc" "clobber")])
1351
1352 ;; ----------------------------------------------------------------------
1353 ;; JUMP INSTRUCTIONS
1354 ;; ----------------------------------------------------------------------
1355
1356 ;; Doloop
1357
1358 (define_expand "doloop_begin"
1359 [(use (match_operand 0 "" "")) ; loop pseudo
1360 (use (match_operand 1 "" "")) ; iterations; zero if unknown
1361 (use (match_operand 2 "" "")) ; max iterations
1362 (use (match_operand 3 "" "")) ; loop level
1363 (use (match_operand 4 "" ""))] ; condition
1364 "TARGET_V850E3V5_UP && TARGET_LOOP"
1365 {
1366 rtx loop_cnt = operands[0];
1367 rtx loop_level = operands[3];
1368
1369 if (INTVAL (loop_level) > 1)
1370 FAIL;
1371 if (GET_MODE (loop_cnt) != SImode)
1372 FAIL;
1373
1374 emit_insn (gen_fix_loop_counter (loop_cnt));
1375 DONE;
1376 }
1377 )
1378
1379 (define_insn "fix_loop_counter"
1380 [(unspec:SI [(match_operand:SI 0 "register_operand" "+r,!m")
1381 (clobber (match_scratch:SI 1 "=X,r"))] UNSPEC_LOOP)]
1382 "TARGET_V850E3V5_UP && TARGET_LOOP"
1383 {
1384 switch (which_alternative)
1385 {
1386 case 0: return "add 1, %0 # LOOP_BEGIN";
1387 case 1: return "ld.w %0, %1; add 1, %1; st.w %1, %0 # LOOP_BEGIN";
1388 default: gcc_unreachable ();
1389 }
1390 }
1391 [(set_attr "length" "2,6")
1392 (set_attr "cc" "none")]
1393 )
1394
1395 (define_expand "doloop_end"
1396 [(use (match_operand 0 "" "")) ; loop pseudo
1397 (use (match_operand 1 "" "")) ; iterations; zero if unknown
1398 (use (match_operand 2 "" "")) ; max iterations
1399 (use (match_operand 3 "" "")) ; loop level
1400 (use (match_operand 4 "" "")) ; label
1401 (use (match_operand 5 "" ""))] ; entered at top
1402 "TARGET_V850E3V5_UP && TARGET_LOOP"
1403 {
1404 rtx loop_cnt = operands[0];
1405 rtx loop_level = operands[3];
1406 rtx label = operands[4];
1407
1408 if (INTVAL (loop_level) > 1)
1409 FAIL;
1410 if (GET_MODE (loop_cnt) != SImode)
1411 FAIL;
1412
1413 emit_jump_insn (gen_doloop_end_internal_loop (label, loop_cnt));
1414 DONE;
1415 }
1416 )
1417
1418 (define_insn "doloop_end_internal_loop"
1419 [(set (pc)
1420 (if_then_else (ne (match_operand:SI 1 "register_operand" "+r,!m")
1421 (const_int 0))
1422 (label_ref (match_operand 0 "" ""))
1423 (pc)))
1424 (set (match_dup 1) (plus:SI (match_dup 1) (const_int -1)))
1425 (clobber (match_scratch:SI 2 "=X,r"))
1426 (clobber (reg:CC CC_REGNUM))]
1427 "TARGET_V850E3V5_UP && TARGET_LOOP"
1428 {
1429 switch (which_alternative)
1430 {
1431 case 0:
1432 if (get_attr_length (insn) == 4)
1433 return "loop %1, %0 # LOOP.1.0";
1434
1435 return "add -1, %1; bne %l0 # LOOP.1.1";
1436 case 1:
1437 return "ld.w %1, %2; add -1, %2; st.w %2, %1; bne %l0 # LOOP.2.1";
1438 default:
1439 gcc_unreachable ();
1440 }
1441 }
1442 [(set (attr "length")
1443 (if_then_else (lt (abs (minus (match_dup 0) (pc)))
1444 (const_int 65534))
1445 (const_int 4)
1446 (const_int 14)))
1447 (set_attr "cc" "none")])
1448
1449 ;; Conditional jump instructions
1450
1451 (define_insn "*branch_normal"
1452 [(set (pc)
1453 (if_then_else (match_operator 1 "comparison_operator"
1454 [(cc0) (const_int 0)])
1455 (label_ref (match_operand 0 "" ""))
1456 (pc)))]
1457 ""
1458 {
1459 if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
1460 && (GET_CODE (operands[1]) == GT
1461 || GET_CODE (operands[1]) == GE
1462 || GET_CODE (operands[1]) == LE
1463 || GET_CODE (operands[1]) == LT))
1464 return 0;
1465
1466 if (get_attr_length (insn) == 2)
1467 return "b%b1 %l0";
1468 if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
1469 return "b%b1 %l0";
1470 return "b%B1 .+6 ; jr %l0";
1471 }
1472 [(set (attr "length")
1473 (if_then_else (lt (abs (minus (match_dup 0) (pc)))
1474 (const_int 256))
1475 (const_int 2)
1476 (if_then_else (lt (abs (minus (match_dup 0) (pc)))
1477 (const_int 65536))
1478 (const_int 4)
1479 (const_int 6))))
1480 (set_attr "cc" "none")])
1481
1482 (define_insn "*branch_invert"
1483 [(set (pc)
1484 (if_then_else (match_operator 1 "comparison_operator"
1485 [(cc0) (const_int 0)])
1486 (pc)
1487 (label_ref (match_operand 0 "" ""))))]
1488 ""
1489 {
1490 if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
1491 && (GET_CODE (operands[1]) == GT
1492 || GET_CODE (operands[1]) == GE
1493 || GET_CODE (operands[1]) == LE
1494 || GET_CODE (operands[1]) == LT))
1495 return NULL;
1496
1497 if (get_attr_length (insn) == 2)
1498 return "b%B1 %l0";
1499
1500 if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
1501 return "b%B1 %l0";
1502
1503 return "b%b1 .+6 ; jr %l0";
1504 }
1505 [(set (attr "length")
1506 (if_then_else (lt (abs (minus (match_dup 0) (pc)))
1507 (const_int 256))
1508 (const_int 2)
1509 (if_then_else (lt (abs (minus (match_dup 0) (pc)))
1510 (const_int 65536))
1511 (const_int 4)
1512 (const_int 6))))
1513 (set_attr "cc" "none")])
1514
1515 (define_insn "branch_z_normal"
1516 [(set (pc)
1517 (if_then_else (match_operand 1 "v850_float_z_comparison_operator" "")
1518 (label_ref (match_operand 0 "" ""))
1519 (pc)))]
1520 "TARGET_V850E2V3_UP"
1521 {
1522 if (get_attr_length (insn) == 2)
1523 return "bz %l0";
1524
1525 if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
1526 return "bz %l0";
1527
1528 return "bnz 1f ; jr %l0 ; 1:";
1529 }
1530 [(set (attr "length")
1531 (if_then_else (lt (abs (minus (match_dup 0) (pc)))
1532 (const_int 256))
1533 (const_int 2)
1534 (if_then_else (lt (abs (minus (match_dup 0) (pc)))
1535 (const_int 65536))
1536 (const_int 4)
1537 (const_int 6))))
1538 (set_attr "cc" "none")])
1539
1540 (define_insn "*branch_z_invert"
1541 [(set (pc)
1542 (if_then_else (match_operand 1 "v850_float_z_comparison_operator" "")
1543 (pc)
1544 (label_ref (match_operand 0 "" ""))))]
1545 "TARGET_V850E2V3_UP"
1546 {
1547 if (get_attr_length (insn) == 2)
1548 return "bnz %l0";
1549
1550 if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
1551 return "bnz %l0";
1552
1553 return "bz 1f ; jr %l0 ; 1:";
1554 }
1555 [(set (attr "length")
1556 (if_then_else (lt (abs (minus (match_dup 0) (pc)))
1557 (const_int 256))
1558 (const_int 2)
1559 (if_then_else (lt (abs (minus (match_dup 0) (pc)))
1560 (const_int 65536))
1561 (const_int 4)
1562 (const_int 6))))
1563 (set_attr "cc" "none")])
1564
1565 (define_insn "branch_nz_normal"
1566 [(set (pc)
1567 (if_then_else (match_operand 1 "v850_float_nz_comparison_operator" "")
1568 (label_ref (match_operand 0 "" ""))
1569 (pc)))]
1570 "TARGET_V850E2V3_UP"
1571 {
1572 if (get_attr_length (insn) == 2)
1573 return "bnz %l0";
1574
1575 if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
1576 return "bnz %l0";
1577
1578 return "bz 1f ; jr %l0 ; 1:";
1579 }
1580 [(set (attr "length")
1581 (if_then_else (lt (abs (minus (match_dup 0) (pc)))
1582 (const_int 256))
1583 (const_int 2)
1584 (if_then_else (lt (abs (minus (match_dup 0) (pc)))
1585 (const_int 65536))
1586 (const_int 4)
1587 (const_int 6))))
1588 (set_attr "cc" "none")])
1589
1590 (define_insn "*branch_nz_invert"
1591 [(set (pc)
1592 (if_then_else (match_operand 1 "v850_float_nz_comparison_operator" "")
1593 (pc)
1594 (label_ref (match_operand 0 "" ""))))]
1595 "TARGET_V850E2V3_UP"
1596 {
1597 if (get_attr_length (insn) == 2)
1598 return "bz %l0";
1599
1600 if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
1601 return "bz %l0";
1602
1603 return "bnz 1f ; jr %l0 ; 1:";
1604 }
1605 [(set (attr "length")
1606 (if_then_else (lt (abs (minus (match_dup 0) (pc)))
1607 (const_int 256))
1608 (const_int 2)
1609 (if_then_else (lt (abs (minus (match_dup 0) (pc)))
1610 (const_int 65536))
1611 (const_int 4)
1612 (const_int 6))))
1613 (set_attr "cc" "none")])
1614
1615 ;; Unconditional and other jump instructions.
1616
1617 (define_insn "jump"
1618 [(set (pc)
1619 (label_ref (match_operand 0 "" "")))]
1620 ""
1621 {
1622 if (get_attr_length (insn) == 2)
1623 return "br %0";
1624 else
1625 return "jr %0";
1626 }
1627 [(set (attr "length")
1628 (if_then_else (lt (abs (minus (match_dup 0) (pc)))
1629 (const_int 256))
1630 (const_int 2)
1631 (const_int 4)))
1632 (set_attr "cc" "none")])
1633
1634 (define_insn "indirect_jump"
1635 [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
1636 ""
1637 "jmp %0"
1638 [(set_attr "length" "2")
1639 (set_attr "cc" "none")])
1640
1641 (define_insn "tablejump"
1642 [(set (pc) (match_operand:SI 0 "register_operand" "r"))
1643 (use (label_ref (match_operand 1 "" "")))]
1644 ""
1645 "jmp %0"
1646 [(set_attr "length" "2")
1647 (set_attr "cc" "none")])
1648
1649 (define_insn "switch"
1650 [(set (pc)
1651 (plus:SI
1652 (sign_extend:SI
1653 (mem:HI
1654 (plus:SI (ashift:SI (match_operand:SI 0 "register_operand" "r")
1655 (const_int 1))
1656 (label_ref (match_operand 1 "" "")))))
1657 (label_ref (match_dup 1))))]
1658 "(TARGET_V850E_UP)"
1659 "switch %0"
1660 [(set_attr "length" "2")
1661 (set_attr "cc" "none")])
1662
1663 (define_expand "casesi"
1664 [(match_operand:SI 0 "register_operand" "")
1665 (match_operand:SI 1 "register_operand" "")
1666 (match_operand:SI 2 "register_operand" "")
1667 (match_operand 3 "" "") (match_operand 4 "" "")]
1668 ""
1669 {
1670 rtx reg = gen_reg_rtx (SImode);
1671 rtx tableaddress = gen_reg_rtx (SImode);
1672 rtx test;
1673 rtx mem;
1674
1675 /* Subtract the lower bound from the index. */
1676 emit_insn (gen_subsi3 (reg, operands[0], operands[1]));
1677
1678 /* Compare the result against the number of table entries;
1679 branch to the default label if out of range of the table. */
1680 test = gen_rtx_fmt_ee (GTU, VOIDmode, reg, operands[2]);
1681 emit_jump_insn (gen_cbranchsi4 (test, reg, operands[2], operands[4]));
1682
1683 /* Shift index for the table array access. */
1684 emit_insn (gen_ashlsi3 (reg, reg, GEN_INT (TARGET_BIG_SWITCH ? 2 : 1)));
1685 /* Load the table address into a pseudo. */
1686 emit_insn (gen_movsi (tableaddress,
1687 gen_rtx_LABEL_REF (Pmode, operands[3])));
1688 /* Add the table address to the index. */
1689 emit_insn (gen_addsi3 (reg, reg, tableaddress));
1690 /* Load the table entry. */
1691 mem = gen_const_mem (CASE_VECTOR_MODE, reg);
1692 if (! TARGET_BIG_SWITCH)
1693 {
1694 rtx reg2 = gen_reg_rtx (HImode);
1695 emit_insn (gen_movhi (reg2, mem));
1696 emit_insn (gen_extendhisi2 (reg, reg2));
1697 }
1698 else
1699 emit_insn (gen_movsi (reg, mem));
1700 /* Add the table address. */
1701 emit_insn (gen_addsi3 (reg, reg, tableaddress));
1702 /* Branch to the switch label. */
1703 emit_jump_insn (gen_tablejump (reg, operands[3]));
1704 DONE;
1705 })
1706
1707 ;; Call subroutine with no return value.
1708
1709 (define_expand "call"
1710 [(call (match_operand:QI 0 "general_operand" "")
1711 (match_operand:SI 1 "general_operand" ""))]
1712 ""
1713 {
1714 if (! call_address_operand (XEXP (operands[0], 0), QImode)
1715 || TARGET_LONG_CALLS)
1716 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
1717 if (TARGET_LONG_CALLS)
1718 emit_call_insn (gen_call_internal_long (XEXP (operands[0], 0), operands[1]));
1719 else
1720 emit_call_insn (gen_call_internal_short (XEXP (operands[0], 0), operands[1]));
1721
1722 DONE;
1723 })
1724
1725 (define_insn "call_internal_short"
1726 [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r"))
1727 (match_operand:SI 1 "general_operand" "g,g"))
1728 (clobber (reg:SI 31))]
1729 "! TARGET_LONG_CALLS"
1730 {
1731 if (which_alternative == 1)
1732 {
1733 if (TARGET_V850E3V5_UP)
1734 return "jarl [%0], r31";
1735
1736 return "jarl .+4, r31 ; add 4, r31 ; jmp %0";
1737 }
1738
1739 return "jarl %0, r31";
1740 }
1741 [(set_attr "length" "4,8")
1742 (set_attr "cc" "clobber,clobber")]
1743 )
1744
1745 (define_insn "call_internal_long"
1746 [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r"))
1747 (match_operand:SI 1 "general_operand" "g,g"))
1748 (clobber (reg:SI 31))]
1749 "TARGET_LONG_CALLS"
1750 {
1751 if (which_alternative == 0)
1752 {
1753 if (GET_CODE (operands[0]) == REG)
1754 return "jarl %0,r31";
1755
1756 if (TARGET_V850E3V5_UP)
1757 return "mov hilo(%0), r11 ; jarl [r11], r31";
1758
1759 return "movhi hi(%0), r0, r11 ; movea lo(%0), r11, r11 ; jarl .+4,r31 ; add 4, r31 ; jmp r11";
1760 }
1761
1762 if (TARGET_V850E3V5_UP)
1763 return "jarl [%0], r31";
1764
1765 return "jarl .+4,r31 ; add 4,r31 ; jmp %0";
1766 }
1767 [(set_attr "length" "16,8")
1768 (set_attr "cc" "clobber,clobber")]
1769 )
1770
1771 ;; Call subroutine, returning value in operand 0
1772 ;; (which must be a hard register).
1773
1774 (define_expand "call_value"
1775 [(set (match_operand 0 "" "")
1776 (call (match_operand:QI 1 "general_operand" "")
1777 (match_operand:SI 2 "general_operand" "")))]
1778 ""
1779 {
1780 if (! call_address_operand (XEXP (operands[1], 0), QImode)
1781 || TARGET_LONG_CALLS)
1782 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
1783 if (TARGET_LONG_CALLS)
1784 emit_call_insn (gen_call_value_internal_long (operands[0],
1785 XEXP (operands[1], 0),
1786 operands[2]));
1787 else
1788 emit_call_insn (gen_call_value_internal_short (operands[0],
1789 XEXP (operands[1], 0),
1790 operands[2]));
1791 DONE;
1792 })
1793
1794 (define_insn "call_value_internal_short"
1795 [(set (match_operand 0 "" "=r,r")
1796 (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r"))
1797 (match_operand:SI 2 "general_operand" "g,g")))
1798 (clobber (reg:SI 31))]
1799 "! TARGET_LONG_CALLS"
1800 {
1801 if (which_alternative == 1)
1802 {
1803 if (TARGET_V850E3V5_UP)
1804 return "jarl [%1], r31";
1805
1806 return "jarl .+4, r31 ; add 4, r31 ; jmp %1";
1807 }
1808
1809 return "jarl %1, r31";
1810 }
1811 [(set_attr "length" "4,8")
1812 (set_attr "cc" "clobber,clobber")]
1813 )
1814
1815 (define_insn "call_value_internal_long"
1816 [(set (match_operand 0 "" "=r,r")
1817 (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r"))
1818 (match_operand:SI 2 "general_operand" "g,g")))
1819 (clobber (reg:SI 31))]
1820 "TARGET_LONG_CALLS"
1821 {
1822 if (which_alternative == 0)
1823 {
1824 if (GET_CODE (operands[1]) == REG)
1825 return "jarl %1, r31";
1826
1827 /* Reload can generate this pattern.... */
1828 if (TARGET_V850E3V5_UP)
1829 return "mov hilo(%1), r11 ; jarl [r11], r31";
1830
1831 return "movhi hi(%1), r0, r11 ; movea lo(%1), r11, r11 ; jarl .+4, r31 ; add 4, r31 ; jmp r11";
1832 }
1833
1834 if (TARGET_V850E3V5_UP)
1835 return "jarl [%1], r31";
1836
1837 return "jarl .+4, r31 ; add 4, r31 ; jmp %1";
1838 }
1839 [(set_attr "length" "16,8")
1840 (set_attr "cc" "clobber,clobber")]
1841 )
1842
1843 (define_insn "nop"
1844 [(const_int 0)]
1845 ""
1846 "nop"
1847 [(set_attr "length" "2")
1848 (set_attr "cc" "none")])
1849 \f
1850 ;; ----------------------------------------------------------------------
1851 ;; EXTEND INSTRUCTIONS
1852 ;; ----------------------------------------------------------------------
1853
1854 (define_insn "*zero_extendhisi2_v850e"
1855 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1856 (zero_extend:SI
1857 (match_operand:HI 1 "nonimmediate_operand" "0,r,T,m")))
1858 (clobber (reg:CC CC_REGNUM))]
1859 "(TARGET_V850E_UP)"
1860 "@
1861 zxh %0
1862 andi 65535,%1,%0
1863 sld.hu %1,%0
1864 ld.hu %1,%0"
1865 [(set_attr "length" "2,4,2,4")
1866 (set_attr "cc" "none_0hit,set_zn,none_0hit,none_0hit")])
1867
1868 (define_insn "*zero_extendhisi2_v850"
1869 [(set (match_operand:SI 0 "register_operand" "=r")
1870 (zero_extend:SI
1871 (match_operand:HI 1 "register_operand" "r")))
1872 (clobber (reg:CC CC_REGNUM))] ;; A lie, but we have to match the expander
1873 ""
1874 "andi 65535,%1,%0"
1875 [(set_attr "length" "4")
1876 (set_attr "cc" "set_zn")])
1877
1878 (define_expand "zero_extendhisi2"
1879 [(parallel [(set (match_operand:SI 0 "register_operand")
1880 (zero_extend:SI
1881 (match_operand:HI 1 "nonimmediate_operand")))
1882 (clobber (reg:CC CC_REGNUM))])]
1883 ""
1884 {
1885 if (! (TARGET_V850E_UP))
1886 operands[1] = force_reg (HImode, operands[1]);
1887 })
1888
1889 (define_insn "*zero_extendqisi2_v850e"
1890 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1891 (zero_extend:SI
1892 (match_operand:QI 1 "nonimmediate_operand" "0,r,T,m")))
1893 (clobber (reg:CC CC_REGNUM))]
1894 "(TARGET_V850E_UP)"
1895 "@
1896 zxb %0
1897 andi 255,%1,%0
1898 sld.bu %1,%0
1899 ld.bu %1,%0"
1900 [(set_attr "length" "2,4,2,4")
1901 (set_attr "cc" "none_0hit,set_zn,none_0hit,none_0hit")])
1902
1903 (define_insn "*zero_extendqisi2_v850"
1904 [(set (match_operand:SI 0 "register_operand" "=r")
1905 (zero_extend:SI
1906 (match_operand:QI 1 "register_operand" "r")))
1907 (clobber (reg:CC CC_REGNUM))] ;; A lie, but we have to match the expander
1908 ""
1909 "andi 255,%1,%0"
1910 [(set_attr "length" "4")
1911 (set_attr "cc" "set_zn")])
1912
1913 (define_expand "zero_extendqisi2"
1914 [(parallel [(set (match_operand:SI 0 "register_operand")
1915 (zero_extend:SI
1916 (match_operand:QI 1 "nonimmediate_operand")))
1917 (clobber (reg:CC CC_REGNUM))])]
1918 ""
1919 {
1920 if (! (TARGET_V850E_UP))
1921 operands[1] = force_reg (QImode, operands[1]);
1922 })
1923
1924 ;;- sign extension instructions
1925
1926 ;; ??? The extendhisi2 pattern should not emit shifts for v850e?
1927
1928 (define_insn "*extendhisi_insn"
1929 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1930 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,Q,m")))
1931 (clobber (reg:CC CC_REGNUM))]
1932 "(TARGET_V850E_UP)"
1933 "@
1934 sxh %0
1935 sld.h %1,%0
1936 ld.h %1,%0"
1937 [(set_attr "length" "2,2,4")
1938 (set_attr "cc" "none_0hit,none_0hit,none_0hit")])
1939
1940 ;; ??? This is missing a sign extend from memory pattern to match the ld.h
1941 ;; instruction.
1942
1943 (define_expand "extendhisi2"
1944 [(parallel [(set (match_dup 2)
1945 (ashift:SI (match_operand:HI 1 "register_operand" "")
1946 (const_int 16)))
1947 (clobber (reg:CC CC_REGNUM))])
1948 (parallel [(set (match_operand:SI 0 "register_operand" "")
1949 (ashiftrt:SI (match_dup 2)
1950 (const_int 16)))
1951 (clobber (reg:CC CC_REGNUM))])]
1952 ""
1953 {
1954 operands[1] = gen_lowpart (SImode, operands[1]);
1955 operands[2] = gen_reg_rtx (SImode);
1956 })
1957
1958 ;; ??? The extendqisi2 pattern should not emit shifts for v850e?
1959
1960 (define_insn "*extendqisi_insn"
1961 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1962 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,Q,m")))
1963 (clobber (reg:CC CC_REGNUM))]
1964 "(TARGET_V850E_UP)"
1965 "@
1966 sxb %0
1967 sld.b %1,%0
1968 ld.b %1,%0"
1969 [(set_attr "length" "2,2,4")
1970 (set_attr "cc" "none_0hit,none_0hit,none_0hit")])
1971
1972 ;; ??? This is missing a sign extend from memory pattern to match the ld.b
1973 ;; instruction.
1974
1975 (define_expand "extendqisi2"
1976 [(parallel [(set (match_dup 2)
1977 (ashift:SI (match_operand:QI 1 "register_operand" "")
1978 (const_int 24)))
1979 (clobber (reg:CC CC_REGNUM))])
1980 (parallel [(set (match_operand:SI 0 "register_operand" "")
1981 (ashiftrt:SI (match_dup 2)
1982 (const_int 24)))
1983 (clobber (reg:CC CC_REGNUM))])]
1984 ""
1985 {
1986 operands[1] = gen_lowpart (SImode, operands[1]);
1987 operands[2] = gen_reg_rtx (SImode);
1988 })
1989 \f
1990 ;; ----------------------------------------------------------------------
1991 ;; SHIFTS
1992 ;; ----------------------------------------------------------------------
1993
1994 (define_insn "ashlsi3"
1995 [(set (match_operand:SI 0 "register_operand" "=r,r")
1996 (ashift:SI
1997 (match_operand:SI 1 "register_operand" "0,0")
1998 (match_operand:SI 2 "nonmemory_operand" "r,N")))
1999 (clobber (reg:CC CC_REGNUM))]
2000 ""
2001 "@
2002 shl %2,%0
2003 shl %2,%0"
2004 [(set_attr "length" "4,2")
2005 (set_attr "cc" "set_zn")])
2006
2007 (define_insn "ashlsi3_v850e2"
2008 [(set (match_operand:SI 0 "register_operand" "=r")
2009 (ashift:SI
2010 (match_operand:SI 1 "register_operand" "r")
2011 (match_operand:SI 2 "nonmemory_operand" "r")))
2012 (clobber (reg:CC CC_REGNUM))]
2013 "TARGET_V850E2_UP"
2014 "shl %2,%1,%0"
2015 [(set_attr "length" "4")
2016 (set_attr "cc" "set_znv")])
2017
2018 (define_insn "lshrsi3"
2019 [(set (match_operand:SI 0 "register_operand" "=r,r")
2020 (lshiftrt:SI
2021 (match_operand:SI 1 "register_operand" "0,0")
2022 (match_operand:SI 2 "nonmemory_operand" "r,N")))
2023 (clobber (reg:CC CC_REGNUM))]
2024 ""
2025 "@
2026 shr %2,%0
2027 shr %2,%0"
2028 [(set_attr "length" "4,2")
2029 (set_attr "cc" "set_zn")])
2030
2031 (define_insn "lshrsi3_v850e2"
2032 [(set (match_operand:SI 0 "register_operand" "=r")
2033 (lshiftrt:SI
2034 (match_operand:SI 1 "register_operand" "r")
2035 (match_operand:SI 2 "nonmemory_operand" "r")))
2036 (clobber (reg:CC CC_REGNUM))]
2037 "TARGET_V850E2_UP"
2038 "shr %2,%1,%0"
2039 [(set_attr "length" "4")
2040 (set_attr "cc" "set_zn")])
2041
2042 (define_insn "ashrsi3"
2043 [(set (match_operand:SI 0 "register_operand" "=r,r")
2044 (ashiftrt:SI
2045 (match_operand:SI 1 "register_operand" "0,0")
2046 (match_operand:SI 2 "nonmemory_operand" "r,N")))
2047 (clobber (reg:CC CC_REGNUM))]
2048 ""
2049 "@
2050 sar %2,%0
2051 sar %2,%0"
2052 [(set_attr "length" "4,2")
2053 (set_attr "cc" "set_zn, set_zn")])
2054
2055 (define_insn "ashrsi3_v850e2"
2056 [(set (match_operand:SI 0 "register_operand" "=r")
2057 (ashiftrt:SI
2058 (match_operand:SI 1 "register_operand" "r")
2059 (match_operand:SI 2 "nonmemory_operand" "r")))
2060 (clobber (reg:CC CC_REGNUM))]
2061 "TARGET_V850E2_UP"
2062 "sar %2,%1,%0"
2063 [(set_attr "length" "4")
2064 (set_attr "cc" "set_zn")])
2065
2066 ;; ----------------------------------------------------------------------
2067 ;; FIND FIRST BIT INSTRUCTION
2068 ;; ----------------------------------------------------------------------
2069
2070 (define_insn "ffssi2"
2071 [(set (match_operand:SI 0 "register_operand" "=r")
2072 (ffs:SI (match_operand:SI 1 "register_operand" "r")))
2073 (clobber (reg:CC CC_REGNUM))]
2074 "TARGET_V850E2_UP"
2075 "sch1r %1,%0"
2076 [(set_attr "length" "4")
2077 (set_attr "cc" "clobber")])
2078
2079 ;; ----------------------------------------------------------------------
2080 ;; PROLOGUE/EPILOGUE
2081 ;; ----------------------------------------------------------------------
2082 (define_expand "prologue"
2083 [(const_int 0)]
2084 ""
2085 {
2086 expand_prologue ();
2087 DONE;
2088 })
2089
2090 (define_expand "epilogue"
2091 [(return)]
2092 ""
2093 {
2094 expand_epilogue ();
2095 DONE;
2096 })
2097
2098 (define_insn "return_simple"
2099 [(return)]
2100 "reload_completed"
2101 "jmp [r31]"
2102 [(set_attr "length" "2")
2103 (set_attr "cc" "none")])
2104
2105 (define_insn "return_internal"
2106 [(return)
2107 (use (reg:SI 31))]
2108 ""
2109 "jmp [r31]"
2110 [(set_attr "length" "2")
2111 (set_attr "cc" "none")])
2112
2113 ;; ----------------------------------------------------------------------
2114 ;; v850e2V3 floating-point hardware support
2115 ;; ----------------------------------------------------------------------
2116
2117
2118 (define_insn "addsf3"
2119 [(set (match_operand:SF 0 "register_operand" "=r")
2120 (plus:SF (match_operand:SF 1 "register_operand" "r")
2121 (match_operand:SF 2 "register_operand" "r")))]
2122 "TARGET_USE_FPU"
2123 "addf.s %1,%2,%0"
2124 [(set_attr "length" "4")
2125 (set_attr "cc" "none_0hit")
2126 (set_attr "type" "fpu")])
2127
2128 (define_insn "adddf3"
2129 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2130 (plus:DF (match_operand:DF 1 "even_reg_operand" "r")
2131 (match_operand:DF 2 "even_reg_operand" "r")))]
2132 "TARGET_USE_FPU"
2133 "addf.d %1,%2,%0"
2134 [(set_attr "length" "4")
2135 (set_attr "cc" "none_0hit")
2136 (set_attr "type" "fpu")])
2137
2138 (define_insn "subsf3"
2139 [(set (match_operand:SF 0 "register_operand" "=r")
2140 (minus:SF (match_operand:SF 1 "register_operand" "r")
2141 (match_operand:SF 2 "register_operand" "r")))]
2142 "TARGET_USE_FPU"
2143 "subf.s %2,%1,%0"
2144 [(set_attr "length" "4")
2145 (set_attr "cc" "none_0hit")
2146 (set_attr "type" "fpu")])
2147
2148 (define_insn "subdf3"
2149 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2150 (minus:DF (match_operand:DF 1 "even_reg_operand" "r")
2151 (match_operand:DF 2 "even_reg_operand" "r")))]
2152 "TARGET_USE_FPU"
2153 "subf.d %2,%1,%0"
2154 [(set_attr "length" "4")
2155 (set_attr "cc" "none_0hit")
2156 (set_attr "type" "fpu")])
2157
2158 (define_insn "mulsf3"
2159 [(set (match_operand:SF 0 "register_operand" "=r")
2160 (mult:SF (match_operand:SF 1 "register_operand" "r")
2161 (match_operand:SF 2 "register_operand" "r")))]
2162 "TARGET_USE_FPU"
2163 "mulf.s %1,%2,%0"
2164 [(set_attr "length" "4")
2165 (set_attr "cc" "none_0hit")
2166 (set_attr "type" "fpu")])
2167
2168 (define_insn "muldf3"
2169 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2170 (mult:DF (match_operand:DF 1 "even_reg_operand" "r")
2171 (match_operand:DF 2 "even_reg_operand" "r")))]
2172 "TARGET_USE_FPU"
2173 "mulf.d %1,%2,%0"
2174 [(set_attr "length" "4")
2175 (set_attr "cc" "none_0hit")
2176 (set_attr "type" "fpu")])
2177
2178 (define_insn "divsf3"
2179 [(set (match_operand:SF 0 "register_operand" "=r")
2180 (div:SF (match_operand:SF 1 "register_operand" "r")
2181 (match_operand:SF 2 "register_operand" "r")))]
2182 "TARGET_USE_FPU"
2183 "divf.s %2,%1,%0"
2184 [(set_attr "length" "4")
2185 (set_attr "cc" "none_0hit")
2186 (set_attr "type" "fpu")])
2187
2188 (define_insn "divdf3"
2189 [(set (match_operand:DF 0 "register_operand" "=r")
2190 (div:DF (match_operand:DF 1 "even_reg_operand" "r")
2191 (match_operand:DF 2 "even_reg_operand" "r")))]
2192 "TARGET_USE_FPU"
2193 "divf.d %2,%1,%0"
2194 [(set_attr "length" "4")
2195 (set_attr "cc" "none_0hit")
2196 (set_attr "type" "fpu")])
2197
2198 (define_insn "minsf3"
2199 [(set (match_operand:SF 0 "register_operand" "=r")
2200 (smin:SF (match_operand:SF 1 "reg_or_0_operand" "r")
2201 (match_operand:SF 2 "reg_or_0_operand" "r")))]
2202 "TARGET_USE_FPU"
2203 "minf.s %z1,%z2,%0"
2204 [(set_attr "length" "4")
2205 (set_attr "cc" "none_0hit")
2206 (set_attr "type" "fpu")])
2207
2208 (define_insn "mindf3"
2209 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2210 (smin:DF (match_operand:DF 1 "even_reg_operand" "r")
2211 (match_operand:DF 2 "even_reg_operand" "r")))]
2212 "TARGET_USE_FPU"
2213 "minf.d %1,%2,%0"
2214 [(set_attr "length" "4")
2215 (set_attr "cc" "none_0hit")
2216 (set_attr "type" "fpu")])
2217
2218 (define_insn "maxsf3"
2219 [(set (match_operand:SF 0 "register_operand" "=r")
2220 (smax:SF (match_operand:SF 1 "reg_or_0_operand" "r")
2221 (match_operand:SF 2 "reg_or_0_operand" "r")))]
2222 "TARGET_USE_FPU"
2223 "maxf.s %z1,%z2,%0"
2224 [(set_attr "length" "4")
2225 (set_attr "cc" "none_0hit")
2226 (set_attr "type" "fpu")])
2227
2228 (define_insn "maxdf3"
2229 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2230 (smax:DF (match_operand:DF 1 "even_reg_operand" "r")
2231 (match_operand:DF 2 "even_reg_operand" "r")))]
2232 "TARGET_USE_FPU"
2233 "maxf.d %1,%2,%0"
2234 [(set_attr "length" "4")
2235 (set_attr "cc" "none_0hit")
2236 (set_attr "type" "fpu")])
2237
2238 (define_insn "abssf2"
2239 [(set (match_operand:SF 0 "register_operand" "=r")
2240 (abs:SF (match_operand:SF 1 "register_operand" "r")))]
2241 "TARGET_USE_FPU"
2242 "absf.s %1,%0"
2243 [(set_attr "length" "4")
2244 (set_attr "cc" "none_0hit")
2245 (set_attr "type" "fpu")])
2246
2247 (define_insn "absdf2"
2248 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2249 (abs:DF (match_operand:DF 1 "even_reg_operand" "r")))]
2250 "TARGET_USE_FPU"
2251 "absf.d %1,%0"
2252 [(set_attr "length" "4")
2253 (set_attr "cc" "none_0hit")
2254 (set_attr "type" "fpu")])
2255
2256 (define_insn "negsf2"
2257 [(set (match_operand:SF 0 "register_operand" "=r")
2258 (neg:SF (match_operand:SF 1 "register_operand" "r")))]
2259 "TARGET_USE_FPU"
2260 "negf.s %1,%0"
2261 [(set_attr "length" "4")
2262 (set_attr "cc" "none_0hit")
2263 (set_attr "type" "fpu")])
2264
2265 (define_insn "negdf2"
2266 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2267 (neg:DF (match_operand:DF 1 "even_reg_operand" "r")))]
2268 "TARGET_USE_FPU"
2269 "negf.d %1,%0"
2270 [(set_attr "length" "4")
2271 (set_attr "cc" "none_0hit")
2272 (set_attr "type" "fpu")])
2273
2274 ;; square-root
2275 (define_insn "sqrtsf2"
2276 [(set (match_operand:SF 0 "register_operand" "=r")
2277 (sqrt:SF (match_operand:SF 1 "register_operand" "r")))]
2278 "TARGET_USE_FPU"
2279 "sqrtf.s %1,%0"
2280 [(set_attr "length" "4")
2281 (set_attr "cc" "none_0hit")
2282 (set_attr "type" "fpu")])
2283
2284 (define_insn "sqrtdf2"
2285 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2286 (sqrt:DF (match_operand:DF 1 "even_reg_operand" "r")))]
2287 "TARGET_USE_FPU"
2288 "sqrtf.d %1,%0"
2289 [(set_attr "length" "4")
2290 (set_attr "cc" "none_0hit")
2291 (set_attr "type" "fpu")])
2292
2293 ;; float -> int
2294 (define_insn "fix_truncsfsi2"
2295 [(set (match_operand:SI 0 "register_operand" "=r")
2296 (fix:SI (match_operand:SF 1 "register_operand" "r")))]
2297 "TARGET_USE_FPU"
2298 "trncf.sw %1,%0"
2299 [(set_attr "length" "4")
2300 (set_attr "cc" "none_0hit")
2301 (set_attr "type" "fpu")])
2302
2303 (define_insn "fixuns_truncsfsi2"
2304 [(set (match_operand:SI 0 "register_operand" "=r")
2305 (unsigned_fix:SI (match_operand:SF 1 "register_operand" "r")))]
2306 "TARGET_USE_FPU"
2307 "trncf.suw %1, %0"
2308 [(set_attr "length" "4")
2309 (set_attr "cc" "none_0hit")
2310 (set_attr "type" "fpu")]
2311 )
2312
2313 (define_insn "fix_truncdfsi2"
2314 [(set (match_operand:SI 0 "register_operand" "=r")
2315 (fix:SI (match_operand:DF 1 "even_reg_operand" "r")))]
2316 "TARGET_USE_FPU"
2317 "trncf.dw %1,%0"
2318 [(set_attr "length" "4")
2319 (set_attr "cc" "none_0hit")
2320 (set_attr "type" "fpu")])
2321
2322 (define_insn "fixuns_truncdfsi2"
2323 [(set (match_operand:SI 0 "register_operand" "=r")
2324 (unsigned_fix:SI (match_operand:DF 1 "even_reg_operand" "r")))]
2325 "TARGET_USE_FPU"
2326 "trncf.duw %1, %0"
2327 [(set_attr "length" "4")
2328 (set_attr "cc" "none_0hit")
2329 (set_attr "type" "fpu")]
2330 )
2331
2332 (define_insn "fix_truncsfdi2"
2333 [(set (match_operand:DI 0 "register_operand" "=r")
2334 (fix:DI (match_operand:SF 1 "register_operand" "r")))]
2335 "TARGET_USE_FPU"
2336 "trncf.sl %1, %0"
2337 [(set_attr "length" "4")
2338 (set_attr "cc" "none_0hit")
2339 (set_attr "type" "fpu")])
2340
2341 (define_insn "fixuns_truncsfdi2"
2342 [(set (match_operand:DI 0 "register_operand" "=r")
2343 (unsigned_fix:DI (match_operand:SF 1 "register_operand" "r")))]
2344 "TARGET_USE_FPU"
2345 "trncf.sul %1, %0"
2346 [(set_attr "length" "4")
2347 (set_attr "cc" "none_0hit")
2348 (set_attr "type" "fpu")]
2349 )
2350
2351 (define_insn "fix_truncdfdi2"
2352 [(set (match_operand:DI 0 "register_operand" "=r")
2353 (fix:DI (match_operand:DF 1 "even_reg_operand" "r")))]
2354 "TARGET_USE_FPU"
2355 "trncf.dl %1, %0"
2356 [(set_attr "length" "4")
2357 (set_attr "cc" "none_0hit")
2358 (set_attr "type" "fpu")])
2359
2360 (define_insn "fixuns_truncdfdi2"
2361 [(set (match_operand:DI 0 "register_operand" "=r")
2362 (unsigned_fix:DI (match_operand:DF 1 "even_reg_operand" "r")))]
2363 "TARGET_USE_FPU"
2364 "trncf.dul %1, %0"
2365 [(set_attr "length" "4")
2366 (set_attr "cc" "none_0hit")
2367 (set_attr "type" "fpu")]
2368 )
2369
2370 ;; int -> float
2371 (define_insn "floatsisf2"
2372 [(set (match_operand:SF 0 "register_operand" "=r")
2373 (float:SF (match_operand:SI 1 "reg_or_0_operand" "rI")))]
2374 "TARGET_USE_FPU"
2375 "cvtf.ws %z1, %0"
2376 [(set_attr "length" "4")
2377 (set_attr "cc" "none_0hit")
2378 (set_attr "type" "fpu")])
2379
2380 (define_insn "unsfloatsisf2"
2381 [(set (match_operand:SF 0 "register_operand" "=r")
2382 (unsigned_float:SF (match_operand:SI 1 "reg_or_0_operand" "rI")))]
2383 "TARGET_USE_FPU"
2384 "cvtf.uws %z1, %0"
2385 [(set_attr "length" "4")
2386 (set_attr "cc" "none_0hit")
2387 (set_attr "type" "fpu")])
2388
2389 (define_insn "floatsidf2"
2390 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2391 (float:DF (match_operand:SI 1 "reg_or_0_operand" "rI")))]
2392 "TARGET_USE_FPU"
2393 "cvtf.wd %z1,%0"
2394 [(set_attr "length" "4")
2395 (set_attr "cc" "none_0hit")
2396 (set_attr "type" "fpu")])
2397
2398 (define_insn "unsfloatsidf2"
2399 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2400 (unsigned_float:DF (match_operand:SI 1 "reg_or_0_operand" "rI")))]
2401 "TARGET_USE_FPU"
2402 "cvtf.uwd %z1, %0"
2403 [(set_attr "length" "4")
2404 (set_attr "cc" "none_0hit")
2405 (set_attr "type" "fpu")])
2406
2407 (define_insn "floatdisf2"
2408 [(set (match_operand:SF 0 "even_reg_operand" "=r")
2409 (float:SF (match_operand:DI 1 "reg_or_0_operand" "rI")))]
2410 "TARGET_USE_FPU"
2411 "cvtf.ls %z1, %0"
2412 [(set_attr "length" "4")
2413 (set_attr "cc" "none_0hit")
2414 (set_attr "type" "fpu")])
2415
2416 (define_insn "unsfloatdisf2"
2417 [(set (match_operand:SF 0 "even_reg_operand" "=r")
2418 (unsigned_float:SF (match_operand:DI 1 "reg_or_0_operand" "rI")))]
2419 "TARGET_USE_FPU"
2420 "cvtf.uls %z1, %0"
2421 [(set_attr "length" "4")
2422 (set_attr "cc" "none_0hit")
2423 (set_attr "type" "fpu")])
2424
2425 (define_insn "floatdidf2"
2426 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2427 (float:DF (match_operand:DI 1 "reg_or_0_operand" "rI")))]
2428 "TARGET_USE_FPU"
2429 "cvtf.ld %z1, %0"
2430 [(set_attr "length" "4")
2431 (set_attr "cc" "none_0hit")
2432 (set_attr "type" "fpu")])
2433
2434 (define_insn "unsfloatdidf2"
2435 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2436 (unsigned_float:DF (match_operand:DI 1 "reg_or_0_operand" "rI")))]
2437 "TARGET_USE_FPU"
2438 "cvtf.uld %z1, %0"
2439 [(set_attr "length" "4")
2440 (set_attr "cc" "none_0hit")
2441 (set_attr "type" "fpu")])
2442
2443 ;; single-float -> double-float
2444 (define_insn "extendsfdf2"
2445 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2446 (float_extend:DF
2447 (match_operand:SF 1 "reg_or_0_operand" "rI")))]
2448 "TARGET_USE_FPU"
2449 "cvtf.sd %z1,%0"
2450 [(set_attr "length" "4")
2451 (set_attr "cc" "none_0hit")
2452 (set_attr "type" "fpu")])
2453
2454 ;; double-float -> single-float
2455 (define_insn "truncdfsf2"
2456 [(set (match_operand:SF 0 "register_operand" "=r")
2457 (float_truncate:SF
2458 (match_operand:DF 1 "even_reg_operand" "r")))]
2459 "TARGET_USE_FPU"
2460 "cvtf.ds %1,%0"
2461 [(set_attr "length" "4")
2462 (set_attr "cc" "none_0hit")
2463 (set_attr "type" "fpu")])
2464
2465 ;;
2466 ;; ---------------- special insns
2467 ;;
2468
2469 ;;; reciprocal
2470 (define_insn "recipsf2"
2471 [(set (match_operand:SF 0 "register_operand" "=r")
2472 (div:SF (match_operand:SF 1 "const_float_1_operand" "")
2473 (match_operand:SF 2 "register_operand" "r")))]
2474 "TARGET_USE_FPU"
2475 "recipf.s %2,%0"
2476 [(set_attr "length" "4")
2477 (set_attr "cc" "none_0hit")
2478 (set_attr "type" "fpu")])
2479
2480 (define_insn "recipdf2"
2481 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2482 (div:DF (match_operand:DF 1 "const_float_1_operand" "")
2483 (match_operand:DF 2 "even_reg_operand" "r")))]
2484 "TARGET_USE_FPU"
2485 "recipf.d %2,%0"
2486 [(set_attr "length" "4")
2487 (set_attr "cc" "none_0hit")
2488 (set_attr "type" "fpu")])
2489
2490 ;;; reciprocal of square-root
2491 (define_insn "rsqrtsf2"
2492 [(set (match_operand:SF 0 "register_operand" "=r")
2493 (div:SF (match_operand:SF 1 "const_float_1_operand" "")
2494 (sqrt:SF (match_operand:SF 2 "register_operand" "r"))))]
2495 "TARGET_USE_FPU"
2496 "rsqrtf.s %2,%0"
2497 [(set_attr "length" "4")
2498 (set_attr "cc" "none_0hit")
2499 (set_attr "type" "fpu")])
2500
2501 (define_insn "rsqrtdf2"
2502 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2503 (div:DF (match_operand:DF 1 "const_float_1_operand" "")
2504 (sqrt:DF (match_operand:DF 2 "even_reg_operand" "r"))))]
2505 "TARGET_USE_FPU"
2506 "rsqrtf.d %2,%0"
2507 [(set_attr "length" "4")
2508 (set_attr "cc" "none_0hit")
2509 (set_attr "type" "fpu")])
2510
2511 ;; Note: The FPU-2.0 (ie pre e3v5) versions of these routines do not actually
2512 ;; need operand 4 to be the same as operand 0. But the FPU-2.0 versions are
2513 ;; also deprecated so the loss of flexibility is unimportant.
2514
2515 ;;; multiply-add
2516 (define_insn "fmasf4"
2517 [(set (match_operand:SF 0 "register_operand" "=r")
2518 (fma:SF (match_operand:SF 1 "register_operand" "r")
2519 (match_operand:SF 2 "register_operand" "r")
2520 (match_operand:SF 3 "register_operand" "0")))]
2521 "TARGET_USE_FPU"
2522 { return TARGET_V850E3V5_UP ? "fmaf.s %1, %2, %0" : "maddf.s %2, %1, %3, %0"; }
2523 [(set_attr "length" "4")
2524 (set_attr "cc" "none_0hit")
2525 (set_attr "type" "fpu")])
2526
2527 ;;; multiply-subtract
2528 (define_insn "fmssf4"
2529 [(set (match_operand:SF 0 "register_operand" "=r")
2530 (fma:SF (match_operand:SF 1 "register_operand" "r")
2531 (match_operand:SF 2 "register_operand" "r")
2532 (neg:SF (match_operand:SF 3 "register_operand" "0"))))]
2533 "TARGET_USE_FPU"
2534 { return TARGET_V850E3V5_UP ? "fmsf.s %1, %2, %0" : "msubf.s %2, %1, %3, %0"; }
2535 [(set_attr "length" "4")
2536 (set_attr "cc" "none_0hit")
2537 (set_attr "type" "fpu")])
2538
2539 ;;; negative-multiply-add
2540 (define_insn "fnmasf4"
2541 [(set (match_operand:SF 0 "register_operand" "=r")
2542 (neg:SF (fma:SF (match_operand:SF 1 "register_operand" "r")
2543 (match_operand:SF 2 "register_operand" "r")
2544 (match_operand:SF 3 "register_operand" "0"))))]
2545 "TARGET_USE_FPU"
2546 { return TARGET_V850E3V5_UP ? "fnmaf.s %1, %2, %0" : "nmaddf.s %2, %1, %3, %0"; }
2547 [(set_attr "length" "4")
2548 (set_attr "cc" "none_0hit")
2549 (set_attr "type" "fpu")])
2550
2551 ;; negative-multiply-subtract
2552 (define_insn "fnmssf4"
2553 [(set (match_operand:SF 0 "register_operand" "=r")
2554 (neg:SF (fma:SF (match_operand:SF 1 "register_operand" "r")
2555 (match_operand:SF 2 "register_operand" "r")
2556 (neg:SF (match_operand:SF 3 "register_operand" "0")))))]
2557 "TARGET_USE_FPU"
2558 { return TARGET_V850E3V5_UP ? "fnmsf.s %1, %2, %0" : "nmsubf.s %2, %1, %3, %0"; }
2559 [(set_attr "length" "4")
2560 (set_attr "cc" "none_0hit")
2561 (set_attr "type" "fpu")])
2562 ;
2563 ; ---------------- comparison/conditionals
2564 ;
2565 ; SF
2566
2567 (define_insn "cmpsf_le_insn"
2568 [(set (reg:CC_FPU_LE FCC_REGNUM)
2569 (compare:CC_FPU_LE (match_operand:SF 0 "register_operand" "r")
2570 (match_operand:SF 1 "register_operand" "r")))]
2571 "TARGET_USE_FPU"
2572 "cmpf.s le, %z0, %z1"
2573 [(set_attr "length" "4")
2574 (set_attr "cc" "none_0hit")
2575 (set_attr "type" "fpu")])
2576
2577 (define_insn "cmpsf_lt_insn"
2578 [(set (reg:CC_FPU_LT FCC_REGNUM)
2579 (compare:CC_FPU_LT (match_operand:SF 0 "register_operand" "r")
2580 (match_operand:SF 1 "register_operand" "r")))]
2581 "TARGET_USE_FPU"
2582 "cmpf.s lt, %z0, %z1"
2583 [(set_attr "length" "4")
2584 (set_attr "cc" "none_0hit")
2585 (set_attr "type" "fpu")])
2586
2587 (define_insn "cmpsf_ge_insn"
2588 [(set (reg:CC_FPU_GE FCC_REGNUM)
2589 (compare:CC_FPU_GE (match_operand:SF 0 "register_operand" "r")
2590 (match_operand:SF 1 "register_operand" "r")))]
2591 "TARGET_USE_FPU"
2592 "cmpf.s le, %z1, %z0"
2593 [(set_attr "length" "4")
2594 (set_attr "cc" "none_0hit")
2595 (set_attr "type" "fpu")])
2596
2597 (define_insn "cmpsf_gt_insn"
2598 [(set (reg:CC_FPU_GT FCC_REGNUM)
2599 (compare:CC_FPU_GT (match_operand:SF 0 "register_operand" "r")
2600 (match_operand:SF 1 "register_operand" "r")))]
2601 "TARGET_USE_FPU"
2602 "cmpf.s lt, %z1, %z0"
2603 [(set_attr "length" "4")
2604 (set_attr "cc" "none_0hit")
2605 (set_attr "type" "fpu")])
2606
2607 (define_insn "cmpsf_eq_insn"
2608 [(set (reg:CC_FPU_EQ FCC_REGNUM)
2609 (compare:CC_FPU_EQ (match_operand:SF 0 "register_operand" "r")
2610 (match_operand:SF 1 "register_operand" "r")))]
2611 "TARGET_USE_FPU"
2612 "cmpf.s eq, %z0, %z1"
2613 [(set_attr "length" "4")
2614 (set_attr "cc" "none_0hit")
2615 (set_attr "type" "fpu")])
2616
2617 ; DF
2618
2619 (define_insn "cmpdf_le_insn"
2620 [(set (reg:CC_FPU_LE FCC_REGNUM)
2621 (compare:CC_FPU_LE (match_operand:DF 0 "even_reg_operand" "r")
2622 (match_operand:DF 1 "even_reg_operand" "r")))]
2623 "TARGET_USE_FPU"
2624 "cmpf.d le, %z0, %z1"
2625 [(set_attr "length" "4")
2626 (set_attr "cc" "none_0hit")
2627 (set_attr "type" "fpu")])
2628
2629 (define_insn "cmpdf_lt_insn"
2630 [(set (reg:CC_FPU_LT FCC_REGNUM)
2631 (compare:CC_FPU_LT (match_operand:DF 0 "even_reg_operand" "r")
2632 (match_operand:DF 1 "even_reg_operand" "r")))]
2633 "TARGET_USE_FPU"
2634 "cmpf.d lt, %z0, %z1"
2635 [(set_attr "length" "4")
2636 (set_attr "cc" "none_0hit")
2637 (set_attr "type" "fpu")])
2638
2639 (define_insn "cmpdf_ge_insn"
2640 [(set (reg:CC_FPU_GE FCC_REGNUM)
2641 (compare:CC_FPU_GE (match_operand:DF 0 "even_reg_operand" "r")
2642 (match_operand:DF 1 "even_reg_operand" "r")))]
2643 "TARGET_USE_FPU"
2644 "cmpf.d le, %z1, %z0"
2645 [(set_attr "length" "4")
2646 (set_attr "cc" "none_0hit")
2647 (set_attr "type" "fpu")])
2648
2649 (define_insn "cmpdf_gt_insn"
2650 [(set (reg:CC_FPU_GT FCC_REGNUM)
2651 (compare:CC_FPU_GT (match_operand:DF 0 "even_reg_operand" "r")
2652 (match_operand:DF 1 "even_reg_operand" "r")))]
2653 "TARGET_USE_FPU"
2654 "cmpf.d lt, %z1, %z0"
2655 [(set_attr "length" "4")
2656 (set_attr "cc" "none_0hit")
2657 (set_attr "type" "fpu")])
2658
2659 (define_insn "cmpdf_eq_insn"
2660 [(set (reg:CC_FPU_EQ FCC_REGNUM)
2661 (compare:CC_FPU_EQ (match_operand:DF 0 "even_reg_operand" "r")
2662 (match_operand:DF 1 "even_reg_operand" "r")))]
2663 "TARGET_USE_FPU"
2664 "cmpf.d eq, %z0, %z1"
2665 [(set_attr "length" "4")
2666 (set_attr "cc" "none_0hit")
2667 (set_attr "type" "fpu")])
2668
2669 ;;
2670 ;; Transfer a v850e2v3 fcc to the Z bit of CC0 (this is necessary to do a
2671 ;; conditional branch based on a floating-point compare)
2672 ;;
2673
2674 (define_insn "trfsr"
2675 [(set (match_operand 0 "" "") (match_operand 1 "" ""))]
2676 "TARGET_USE_FPU
2677 && GET_MODE(operands[0]) == GET_MODE(operands[1])
2678 && GET_CODE(operands[0]) == REG && REGNO (operands[0]) == CC_REGNUM
2679 && GET_CODE(operands[1]) == REG && REGNO (operands[1]) == FCC_REGNUM
2680 && (GET_MODE(operands[0]) == CC_FPU_LEmode
2681 || GET_MODE(operands[0]) == CC_FPU_GEmode
2682 || GET_MODE(operands[0]) == CC_FPU_LTmode
2683 || GET_MODE(operands[0]) == CC_FPU_GTmode
2684 || GET_MODE(operands[0]) == CC_FPU_EQmode
2685 || GET_MODE(operands[0]) == CC_FPU_NEmode)"
2686 "trfsr"
2687 [(set_attr "length" "4")
2688 (set_attr "cc" "set_z")
2689 (set_attr "type" "fpu")])
2690
2691 ;;
2692 ;; Floating-point conditional moves for the v850e2v3.
2693 ;;
2694
2695 ;; The actual v850e2v3 conditional move instructions
2696 ;;
2697 (define_insn "movsfcc_z_insn"
2698 [(set (match_operand:SF 0 "register_operand" "=r")
2699 (if_then_else:SF
2700 (match_operand 3 "v850_float_z_comparison_operator" "")
2701 (match_operand:SF 1 "reg_or_0_operand" "rIG")
2702 (match_operand:SF 2 "reg_or_0_operand" "rIG")))]
2703 "TARGET_USE_FPU"
2704 "cmovf.s 0,%z1,%z2,%0"
2705 [(set_attr "cc" "clobber")]) ;; ??? or none_0hit
2706
2707 (define_insn "movsfcc_nz_insn"
2708 [(set (match_operand:SF 0 "register_operand" "=r")
2709 (if_then_else:SF
2710 (match_operand 3 "v850_float_nz_comparison_operator" "")
2711 (match_operand:SF 1 "reg_or_0_operand" "rIG")
2712 (match_operand:SF 2 "reg_or_0_operand" "rIG")))]
2713 "TARGET_USE_FPU"
2714 "cmovf.s 0,%z2,%z1,%0"
2715 [(set_attr "cc" "clobber")]) ;; ??? or none_0hit
2716
2717 (define_insn "movdfcc_z_insn"
2718 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2719 (if_then_else:DF
2720 (match_operand 3 "v850_float_z_comparison_operator" "")
2721 (match_operand:DF 1 "even_reg_operand" "r")
2722 (match_operand:DF 2 "even_reg_operand" "r")))]
2723 "TARGET_USE_FPU"
2724 "cmovf.d 0,%z1,%z2,%0"
2725 [(set_attr "cc" "clobber")]) ;; ??? or none_0hit
2726
2727 (define_insn "movdfcc_nz_insn"
2728 [(set (match_operand:DF 0 "even_reg_operand" "=r")
2729 (if_then_else:DF
2730 (match_operand 3 "v850_float_nz_comparison_operator" "")
2731 (match_operand:DF 1 "even_reg_operand" "r")
2732 (match_operand:DF 2 "even_reg_operand" "r")))]
2733 "TARGET_USE_FPU"
2734 "cmovf.d 0,%z2,%z1,%0"
2735 [(set_attr "cc" "clobber")]) ;; ??? or none_0hit
2736
2737 (define_insn "movedfcc_z_zero"
2738 [(set (match_operand:DF 0 "register_operand" "=r")
2739 (if_then_else:DF
2740 (match_operand 3 "v850_float_z_comparison_operator" "")
2741 (match_operand:DF 1 "reg_or_0_operand" "rIG")
2742 (match_operand:DF 2 "reg_or_0_operand" "rIG")))]
2743 "TARGET_USE_FPU"
2744 "cmovf.s 0,%z1,%z2,%0 ; cmovf.s 0,%Z1,%Z2,%R0"
2745 [(set_attr "length" "8")
2746 (set_attr "cc" "clobber")]) ;; ??? or none_0hit
2747
2748 (define_insn "movedfcc_nz_zero"
2749 [(set (match_operand:DF 0 "register_operand" "=r")
2750 (if_then_else:DF
2751 (match_operand 3 "v850_float_nz_comparison_operator" "")
2752 (match_operand:DF 1 "reg_or_0_operand" "rIG")
2753 (match_operand:DF 2 "reg_or_0_operand" "rIG")))]
2754 "TARGET_USE_FPU"
2755 "cmovf.s 0,%z2,%z1,%0 ; cmovf.s 0,%Z2,%Z1,%R0"
2756 [(set_attr "length" "8")
2757 (set_attr "cc" "clobber")]) ;; ??? or none_0hit
2758
2759
2760 ;; ----------------------------------------------------------------------
2761 ;; HELPER INSTRUCTIONS for saving the prologue and epilogue registers
2762 ;; ----------------------------------------------------------------------
2763
2764 ;; This pattern will match a stack adjust RTX followed by any number of push
2765 ;; RTXs. These RTXs will then be turned into a suitable call to a worker
2766 ;; function.
2767
2768 ;;
2769 ;; Actually, convert the RTXs into a PREPARE instruction.
2770 ;;
2771
2772 (define_insn ""
2773 [(match_parallel 0 "pattern_is_ok_for_prepare"
2774 [(set (reg:SI 3)
2775 (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i")))
2776 (set (mem:SI (plus:SI (reg:SI 3)
2777 (match_operand:SI 2 "immediate_operand" "i")))
2778 (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))])]
2779 "TARGET_PROLOG_FUNCTION && (TARGET_V850E_UP)"
2780 {
2781 return construct_prepare_instruction (operands[0]);
2782 }
2783 [(set_attr "length" "4")
2784 (set_attr "cc" "clobber")])
2785
2786 (define_insn ""
2787 [(match_parallel 0 "pattern_is_ok_for_prologue"
2788 [(set (reg:SI 3)
2789 (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i")))
2790 (set (mem:SI (plus:SI (reg:SI 3)
2791 (match_operand:SI 2 "immediate_operand" "i")))
2792 (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))])]
2793 "TARGET_PROLOG_FUNCTION"
2794 {
2795 return construct_save_jarl (operands[0]);
2796 }
2797 [(set (attr "length") (if_then_else (eq_attr "long_calls" "yes")
2798 (const_string "16")
2799 (const_string "4")))
2800 (set_attr "cc" "clobber")])
2801
2802 ;;
2803 ;; Actually, turn the RTXs into a DISPOSE instruction.
2804 ;;
2805 (define_insn ""
2806 [(match_parallel 0 "pattern_is_ok_for_dispose"
2807 [(return)
2808 (set (reg:SI 3)
2809 (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i")))
2810 (set (match_operand:SI 2 "register_is_ok_for_epilogue" "=r")
2811 (mem:SI (plus:SI (reg:SI 3)
2812 (match_operand:SI 3 "immediate_operand" "i"))))])]
2813 "TARGET_PROLOG_FUNCTION && (TARGET_V850E_UP)"
2814 {
2815 return construct_dispose_instruction (operands[0]);
2816 }
2817 [(set_attr "length" "4")
2818 (set_attr "cc" "clobber")])
2819
2820 ;; This pattern will match a return RTX followed by any number of pop RTXs
2821 ;; and possible a stack adjustment as well. These RTXs will be turned into
2822 ;; a suitable call to a worker function.
2823
2824 (define_insn ""
2825 [(match_parallel 0 "pattern_is_ok_for_epilogue"
2826 [(return)
2827 (set (reg:SI 3)
2828 (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i")))
2829 (set (match_operand:SI 2 "register_is_ok_for_epilogue" "=r")
2830 (mem:SI (plus:SI (reg:SI 3)
2831 (match_operand:SI 3 "immediate_operand" "i"))))])]
2832 "TARGET_PROLOG_FUNCTION"
2833 {
2834 return construct_restore_jr (operands[0]);
2835 }
2836 [(set (attr "length") (if_then_else (eq_attr "long_calls" "yes")
2837 (const_string "12")
2838 (const_string "4")))
2839 (set_attr "cc" "clobber")])
2840
2841 ;; Initialize an interrupt function. Do not depend on TARGET_PROLOG_FUNCTION.
2842 (define_insn "callt_save_interrupt"
2843 [(unspec_volatile [(const_int 0)] 2)]
2844 "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT"
2845 ;; The CALLT instruction stores the next address of CALLT to CTPC register
2846 ;; without saving its previous value. So if the interrupt handler
2847 ;; or its caller could possibly execute the CALLT insn, save_interrupt
2848 ;; MUST NOT be called via CALLT.
2849 {
2850 output_asm_insn ("addi -28, sp, sp", operands);
2851 output_asm_insn ("st.w r1, 24[sp]", operands);
2852 output_asm_insn ("st.w r10, 12[sp]", operands);
2853 output_asm_insn ("st.w r11, 16[sp]", operands);
2854 output_asm_insn ("stsr ctpc, r10", operands);
2855 output_asm_insn ("st.w r10, 20[sp]", operands);
2856 output_asm_insn ("stsr ctpsw, r10", operands);
2857 output_asm_insn ("st.w r10, 24[sp]", operands);
2858 output_asm_insn ("callt ctoff(__callt_save_interrupt)", operands);
2859 return "";
2860 }
2861 [(set_attr "length" "26")
2862 (set_attr "cc" "clobber")])
2863
2864 (define_insn "callt_return_interrupt"
2865 [(unspec_volatile [(const_int 0)] 3)]
2866 "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT"
2867 "callt ctoff(__callt_return_interrupt)"
2868 [(set_attr "length" "2")
2869 (set_attr "cc" "clobber")])
2870
2871 (define_insn "save_interrupt"
2872 [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -20)))
2873 (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 30))
2874 (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 4))
2875 (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 1))
2876 (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 10))
2877 (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 11))]
2878 ""
2879 {
2880 if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS)
2881 return "addi -20,sp,sp \; st.w r11,16[sp] \; st.w r10,12[sp] \; jarl __save_interrupt,r10";
2882 else
2883 {
2884 output_asm_insn ("addi -20, sp, sp", operands);
2885 output_asm_insn ("st.w r11, 16[sp]", operands);
2886 output_asm_insn ("st.w r10, 12[sp]", operands);
2887 output_asm_insn ("st.w ep, 0[sp]", operands);
2888 output_asm_insn ("st.w gp, 4[sp]", operands);
2889 output_asm_insn ("st.w r1, 8[sp]", operands);
2890 output_asm_insn ("movhi hi(__ep), r0, ep", operands);
2891 output_asm_insn ("movea lo(__ep), ep, ep", operands);
2892 output_asm_insn ("movhi hi(__gp), r0, gp", operands);
2893 output_asm_insn ("movea lo(__gp), gp, gp", operands);
2894 return "";
2895 }
2896 }
2897 [(set (attr "length")
2898 (if_then_else (match_test "TARGET_LONG_CALLS")
2899 (const_int 10)
2900 (const_int 34)))
2901 (set_attr "cc" "clobber")])
2902
2903 ;; Restore r1, r4, r10, and return from the interrupt
2904 (define_insn "return_interrupt"
2905 [(return)
2906 (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 20)))
2907 (set (reg:SI 11) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))
2908 (set (reg:SI 10) (mem:SI (plus:SI (reg:SI 3) (const_int 12))))
2909 (set (reg:SI 1) (mem:SI (plus:SI (reg:SI 3) (const_int 8))))
2910 (set (reg:SI 4) (mem:SI (plus:SI (reg:SI 3) (const_int 4))))
2911 (set (reg:SI 30) (mem:SI (reg:SI 3)))]
2912 ""
2913 {
2914 if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS)
2915 return "jr __return_interrupt";
2916 else
2917 {
2918 output_asm_insn ("ld.w 0[sp], ep", operands);
2919 output_asm_insn ("ld.w 4[sp], gp", operands);
2920 output_asm_insn ("ld.w 8[sp], r1", operands);
2921 output_asm_insn ("ld.w 12[sp], r10", operands);
2922 output_asm_insn ("ld.w 16[sp], r11", operands);
2923 output_asm_insn ("addi 20, sp, sp", operands);
2924 output_asm_insn ("reti", operands);
2925 return "";
2926 }
2927 }
2928 [(set (attr "length")
2929 (if_then_else (match_test "TARGET_LONG_CALLS")
2930 (const_int 4)
2931 (const_int 24)))
2932 (set_attr "cc" "clobber")])
2933
2934 ;; Save all registers except for the registers saved in save_interrupt when
2935 ;; an interrupt function makes a call.
2936 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
2937 ;; all of memory. This blocks insns from being moved across this point.
2938 ;; This is needed because the rest of the compiler is not ready to handle
2939 ;; insns this complicated.
2940
2941 (define_insn "callt_save_all_interrupt"
2942 [(unspec_volatile [(const_int 0)] 0)]
2943 "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT"
2944 "callt ctoff(__callt_save_all_interrupt)"
2945 [(set_attr "length" "2")
2946 (set_attr "cc" "none")])
2947
2948 (define_insn "save_all_interrupt"
2949 [(unspec_volatile [(const_int 0)] 0)]
2950 ""
2951 {
2952 if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS)
2953 return "jarl __save_all_interrupt,r10";
2954
2955 output_asm_insn ("addi -120, sp, sp", operands);
2956
2957 if (TARGET_EP)
2958 {
2959 output_asm_insn ("mov ep, r1", operands);
2960 output_asm_insn ("mov sp, ep", operands);
2961 output_asm_insn ("sst.w r31, 116[ep]", operands);
2962 output_asm_insn ("sst.w r2, 112[ep]", operands);
2963 output_asm_insn ("sst.w gp, 108[ep]", operands);
2964 output_asm_insn ("sst.w r6, 104[ep]", operands);
2965 output_asm_insn ("sst.w r7, 100[ep]", operands);
2966 output_asm_insn ("sst.w r8, 96[ep]", operands);
2967 output_asm_insn ("sst.w r9, 92[ep]", operands);
2968 output_asm_insn ("sst.w r11, 88[ep]", operands);
2969 output_asm_insn ("sst.w r12, 84[ep]", operands);
2970 output_asm_insn ("sst.w r13, 80[ep]", operands);
2971 output_asm_insn ("sst.w r14, 76[ep]", operands);
2972 output_asm_insn ("sst.w r15, 72[ep]", operands);
2973 output_asm_insn ("sst.w r16, 68[ep]", operands);
2974 output_asm_insn ("sst.w r17, 64[ep]", operands);
2975 output_asm_insn ("sst.w r18, 60[ep]", operands);
2976 output_asm_insn ("sst.w r19, 56[ep]", operands);
2977 output_asm_insn ("sst.w r20, 52[ep]", operands);
2978 output_asm_insn ("sst.w r21, 48[ep]", operands);
2979 output_asm_insn ("sst.w r22, 44[ep]", operands);
2980 output_asm_insn ("sst.w r23, 40[ep]", operands);
2981 output_asm_insn ("sst.w r24, 36[ep]", operands);
2982 output_asm_insn ("sst.w r25, 32[ep]", operands);
2983 output_asm_insn ("sst.w r26, 28[ep]", operands);
2984 output_asm_insn ("sst.w r27, 24[ep]", operands);
2985 output_asm_insn ("sst.w r28, 20[ep]", operands);
2986 output_asm_insn ("sst.w r29, 16[ep]", operands);
2987 output_asm_insn ("mov r1, ep", operands);
2988 }
2989 else
2990 {
2991 output_asm_insn ("st.w r31, 116[sp]", operands);
2992 output_asm_insn ("st.w r2, 112[sp]", operands);
2993 output_asm_insn ("st.w gp, 108[sp]", operands);
2994 output_asm_insn ("st.w r6, 104[sp]", operands);
2995 output_asm_insn ("st.w r7, 100[sp]", operands);
2996 output_asm_insn ("st.w r8, 96[sp]", operands);
2997 output_asm_insn ("st.w r9, 92[sp]", operands);
2998 output_asm_insn ("st.w r11, 88[sp]", operands);
2999 output_asm_insn ("st.w r12, 84[sp]", operands);
3000 output_asm_insn ("st.w r13, 80[sp]", operands);
3001 output_asm_insn ("st.w r14, 76[sp]", operands);
3002 output_asm_insn ("st.w r15, 72[sp]", operands);
3003 output_asm_insn ("st.w r16, 68[sp]", operands);
3004 output_asm_insn ("st.w r17, 64[sp]", operands);
3005 output_asm_insn ("st.w r18, 60[sp]", operands);
3006 output_asm_insn ("st.w r19, 56[sp]", operands);
3007 output_asm_insn ("st.w r20, 52[sp]", operands);
3008 output_asm_insn ("st.w r21, 48[sp]", operands);
3009 output_asm_insn ("st.w r22, 44[sp]", operands);
3010 output_asm_insn ("st.w r23, 40[sp]", operands);
3011 output_asm_insn ("st.w r24, 36[sp]", operands);
3012 output_asm_insn ("st.w r25, 32[sp]", operands);
3013 output_asm_insn ("st.w r26, 28[sp]", operands);
3014 output_asm_insn ("st.w r27, 24[sp]", operands);
3015 output_asm_insn ("st.w r28, 20[sp]", operands);
3016 output_asm_insn ("st.w r29, 16[sp]", operands);
3017 }
3018
3019 return "";
3020 }
3021 [(set (attr "length")
3022 (if_then_else (match_test "TARGET_LONG_CALLS")
3023 (const_int 4)
3024 (const_int 62)
3025 ))
3026 (set_attr "cc" "clobber")])
3027
3028 (define_insn "_save_all_interrupt"
3029 [(unspec_volatile [(const_int 0)] 0)]
3030 "TARGET_V850 && ! TARGET_LONG_CALLS"
3031 "jarl __save_all_interrupt,r10"
3032 [(set_attr "length" "4")
3033 (set_attr "cc" "clobber")])
3034
3035 ;; Restore all registers saved when an interrupt function makes a call.
3036 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
3037 ;; all of memory. This blocks insns from being moved across this point.
3038 ;; This is needed because the rest of the compiler is not ready to handle
3039 ;; insns this complicated.
3040
3041 (define_insn "callt_restore_all_interrupt"
3042 [(unspec_volatile [(const_int 0)] 1)]
3043 "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT"
3044 "callt ctoff(__callt_restore_all_interrupt)"
3045 [(set_attr "length" "2")
3046 (set_attr "cc" "none")])
3047
3048 (define_insn "restore_all_interrupt"
3049 [(unspec_volatile [(const_int 0)] 1)]
3050 ""
3051 {
3052 if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS)
3053 return "jarl __restore_all_interrupt,r10";
3054
3055 if (TARGET_EP)
3056 {
3057 output_asm_insn ("mov ep, r1", operands);
3058 output_asm_insn ("mov sp, ep", operands);
3059 output_asm_insn ("sld.w 116[ep], r31", operands);
3060 output_asm_insn ("sld.w 112[ep], r2", operands);
3061 output_asm_insn ("sld.w 108[ep], gp", operands);
3062 output_asm_insn ("sld.w 104[ep], r6", operands);
3063 output_asm_insn ("sld.w 100[ep], r7", operands);
3064 output_asm_insn ("sld.w 96[ep], r8", operands);
3065 output_asm_insn ("sld.w 92[ep], r9", operands);
3066 output_asm_insn ("sld.w 88[ep], r11", operands);
3067 output_asm_insn ("sld.w 84[ep], r12", operands);
3068 output_asm_insn ("sld.w 80[ep], r13", operands);
3069 output_asm_insn ("sld.w 76[ep], r14", operands);
3070 output_asm_insn ("sld.w 72[ep], r15", operands);
3071 output_asm_insn ("sld.w 68[ep], r16", operands);
3072 output_asm_insn ("sld.w 64[ep], r17", operands);
3073 output_asm_insn ("sld.w 60[ep], r18", operands);
3074 output_asm_insn ("sld.w 56[ep], r19", operands);
3075 output_asm_insn ("sld.w 52[ep], r20", operands);
3076 output_asm_insn ("sld.w 48[ep], r21", operands);
3077 output_asm_insn ("sld.w 44[ep], r22", operands);
3078 output_asm_insn ("sld.w 40[ep], r23", operands);
3079 output_asm_insn ("sld.w 36[ep], r24", operands);
3080 output_asm_insn ("sld.w 32[ep], r25", operands);
3081 output_asm_insn ("sld.w 28[ep], r26", operands);
3082 output_asm_insn ("sld.w 24[ep], r27", operands);
3083 output_asm_insn ("sld.w 20[ep], r28", operands);
3084 output_asm_insn ("sld.w 16[ep], r29", operands);
3085 output_asm_insn ("mov r1, ep", operands);
3086 }
3087 else
3088 {
3089 output_asm_insn ("ld.w 116[sp], r31", operands);
3090 output_asm_insn ("ld.w 112[sp], r2", operands);
3091 output_asm_insn ("ld.w 108[sp], gp", operands);
3092 output_asm_insn ("ld.w 104[sp], r6", operands);
3093 output_asm_insn ("ld.w 100[sp], r7", operands);
3094 output_asm_insn ("ld.w 96[sp], r8", operands);
3095 output_asm_insn ("ld.w 92[sp], r9", operands);
3096 output_asm_insn ("ld.w 88[sp], r11", operands);
3097 output_asm_insn ("ld.w 84[sp], r12", operands);
3098 output_asm_insn ("ld.w 80[sp], r13", operands);
3099 output_asm_insn ("ld.w 76[sp], r14", operands);
3100 output_asm_insn ("ld.w 72[sp], r15", operands);
3101 output_asm_insn ("ld.w 68[sp], r16", operands);
3102 output_asm_insn ("ld.w 64[sp], r17", operands);
3103 output_asm_insn ("ld.w 60[sp], r18", operands);
3104 output_asm_insn ("ld.w 56[sp], r19", operands);
3105 output_asm_insn ("ld.w 52[sp], r20", operands);
3106 output_asm_insn ("ld.w 48[sp], r21", operands);
3107 output_asm_insn ("ld.w 44[sp], r22", operands);
3108 output_asm_insn ("ld.w 40[sp], r23", operands);
3109 output_asm_insn ("ld.w 36[sp], r24", operands);
3110 output_asm_insn ("ld.w 32[sp], r25", operands);
3111 output_asm_insn ("ld.w 28[sp], r26", operands);
3112 output_asm_insn ("ld.w 24[sp], r27", operands);
3113 output_asm_insn ("ld.w 20[sp], r28", operands);
3114 output_asm_insn ("ld.w 16[sp], r29", operands);
3115 }
3116 output_asm_insn ("addi 120, sp, sp", operands);
3117 return "";
3118 }
3119 [(set (attr "length")
3120 (if_then_else (match_test "TARGET_LONG_CALLS")
3121 (const_int 4)
3122 (const_int 62)
3123 ))
3124 (set_attr "cc" "clobber")])
3125
3126 (define_insn "_restore_all_interrupt"
3127 [(unspec_volatile [(const_int 0)] 1)]
3128 "TARGET_V850 && ! TARGET_LONG_CALLS"
3129 "jarl __restore_all_interrupt,r10"
3130 [(set_attr "length" "4")
3131 (set_attr "cc" "clobber")])