1 ;; Machine description of the Mitsubishi M32R cpu for GNU C compiler
2 ;; Copyright (C) 1996, 1997, 1998, 1999, 2001 Free Software Foundation, Inc.
4 ;; This file is part of GNU CC.
6 ;; GNU CC is free software; you can redistribute it and/or modify
7 ;; it under the terms of the GNU General Public License as published by
8 ;; the Free Software Foundation; either version 2, or (at your option)
11 ;; GNU CC is distributed in the hope that it will be useful,
12 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ;; GNU General Public License for more details.
16 ;; You should have received a copy of the GNU General Public License
17 ;; along with GNU CC; see the file COPYING. If not, write to
18 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
19 ;; Boston, MA 02111-1307, USA.
21 ;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
27 ;; 3 - setting carry in addx/subx instructions.
29 ;; Insn type. Used to default other attribute values.
31 "int2,int4,load2,load4,load8,store2,store4,store8,shift2,shift4,mul2,div4,uncond_branch,branch,call,multi,misc"
32 (const_string "misc"))
35 (define_attr "length" ""
36 (cond [(eq_attr "type" "int2,load2,store2,shift2,mul2")
39 (eq_attr "type" "int4,load4,store4,shift4,div4")
42 (eq_attr "type" "multi")
45 (eq_attr "type" "uncond_branch,branch,call")
50 ;; The length here is the length of a single asm. Unfortunately it might be
51 ;; 2 or 4 so we must allow for 4. That's ok though.
52 (define_asm_attributes
53 [(set_attr "length" "4")
54 (set_attr "type" "multi")])
57 ;; Whether an instruction is 16-bit or 32-bit
58 (define_attr "insn_size" "short,long"
59 (if_then_else (eq_attr "type" "int2,load2,store2,shift2,mul2")
60 (const_string "short")
61 (const_string "long")))
63 (define_attr "debug" "no,yes"
64 (const (symbol_ref "(TARGET_DEBUG != 0)")))
66 (define_attr "opt_size" "no,yes"
67 (const (symbol_ref "(optimize_size != 0)")))
69 (define_attr "m32r" "no,yes"
70 (const (symbol_ref "(TARGET_M32R != 0)")))
73 ;; ::::::::::::::::::::
77 ;; ::::::::::::::::::::
79 ;; On most RISC machines, there are instructions whose results are not
80 ;; available for a specific number of cycles. Common cases are instructions
81 ;; that load data from memory. On many machines, a pipeline stall will result
82 ;; if the data is referenced too soon after the load instruction.
84 ;; In addition, many newer microprocessors have multiple function units,
85 ;; usually one for integer and one for floating point, and often will incur
86 ;; pipeline stalls when a result that is needed is not yet ready.
88 ;; The descriptions in this section allow the specification of how much time
89 ;; must elapse between the execution of an instruction and the time when its
90 ;; result is used. It also allows specification of when the execution of an
91 ;; instruction will delay execution of similar instructions due to function
94 ;; For the purposes of the specifications in this section, a machine is divided
95 ;; into "function units", each of which execute a specific class of
96 ;; instructions in first-in-first-out order. Function units that accept one
97 ;; instruction each cycle and allow a result to be used in the succeeding
98 ;; instruction (usually via forwarding) need not be specified. Classic RISC
99 ;; microprocessors will normally have a single function unit, which we can call
100 ;; `memory'. The newer "superscalar" processors will often have function units
101 ;; for floating point operations, usually at least a floating point adder and
104 ;; Each usage of a function units by a class of insns is specified with a
105 ;; `define_function_unit' expression, which looks like this:
107 ;; (define_function_unit NAME MULTIPLICITY SIMULTANEITY TEST READY-DELAY
108 ;; ISSUE-DELAY [CONFLICT-LIST])
110 ;; NAME is a string giving the name of the function unit.
112 ;; MULTIPLICITY is an integer specifying the number of identical units in the
113 ;; processor. If more than one unit is specified, they will be scheduled
114 ;; independently. Only truly independent units should be counted; a pipelined
115 ;; unit should be specified as a single unit. (The only common example of a
116 ;; machine that has multiple function units for a single instruction class that
117 ;; are truly independent and not pipelined are the two multiply and two
118 ;; increment units of the CDC 6600.)
120 ;; SIMULTANEITY specifies the maximum number of insns that can be executing in
121 ;; each instance of the function unit simultaneously or zero if the unit is
122 ;; pipelined and has no limit.
124 ;; All `define_function_unit' definitions referring to function unit NAME must
125 ;; have the same name and values for MULTIPLICITY and SIMULTANEITY.
127 ;; TEST is an attribute test that selects the insns we are describing in this
128 ;; definition. Note that an insn may use more than one function unit and a
129 ;; function unit may be specified in more than one `define_function_unit'.
131 ;; READY-DELAY is an integer that specifies the number of cycles after which
132 ;; the result of the instruction can be used without introducing any stalls.
134 ;; ISSUE-DELAY is an integer that specifies the number of cycles after the
135 ;; instruction matching the TEST expression begins using this unit until a
136 ;; subsequent instruction can begin. A cost of N indicates an N-1 cycle delay.
137 ;; A subsequent instruction may also be delayed if an earlier instruction has a
138 ;; longer READY-DELAY value. This blocking effect is computed using the
139 ;; SIMULTANEITY, READY-DELAY, ISSUE-DELAY, and CONFLICT-LIST terms. For a
140 ;; normal non-pipelined function unit, SIMULTANEITY is one, the unit is taken
141 ;; to block for the READY-DELAY cycles of the executing insn, and smaller
142 ;; values of ISSUE-DELAY are ignored.
144 ;; CONFLICT-LIST is an optional list giving detailed conflict costs for this
145 ;; unit. If specified, it is a list of condition test expressions to be
146 ;; applied to insns chosen to execute in NAME following the particular insn
147 ;; matching TEST that is already executing in NAME. For each insn in the list,
148 ;; ISSUE-DELAY specifies the conflict cost; for insns not in the list, the cost
149 ;; is zero. If not specified, CONFLICT-LIST defaults to all instructions that
150 ;; use the function unit.
152 ;; Typical uses of this vector are where a floating point function unit can
153 ;; pipeline either single- or double-precision operations, but not both, or
154 ;; where a memory unit can pipeline loads, but not stores, etc.
156 ;; As an example, consider a classic RISC machine where the result of a load
157 ;; instruction is not available for two cycles (a single "delay" instruction is
158 ;; required) and where only one load instruction can be executed
159 ;; simultaneously. This would be specified as:
161 ;; (define_function_unit "memory" 1 1 (eq_attr "type" "load") 2 0)
163 ;; For the case of a floating point function unit that can pipeline
164 ;; either single or double precision, but not both, the following could be
167 ;; (define_function_unit "fp" 1 0
168 ;; (eq_attr "type" "sp_fp") 4 4
169 ;; [(eq_attr "type" "dp_fp")])
171 ;; (define_function_unit "fp" 1 0
172 ;; (eq_attr "type" "dp_fp") 4 4
173 ;; [(eq_attr "type" "sp_fp")])
175 ;; Note: The scheduler attempts to avoid function unit conflicts and uses all
176 ;; the specifications in the `define_function_unit' expression. It has
177 ;; recently come to our attention that these specifications may not allow
178 ;; modeling of some of the newer "superscalar" processors that have insns using
179 ;; multiple pipelined units. These insns will cause a potential conflict for
180 ;; the second unit used during their execution and there is no way of
181 ;; representing that conflict. We welcome any examples of how function unit
182 ;; conflicts work in such processors and suggestions for their representation.
184 ;; Function units of the M32R
185 ;; Units that take one cycle do not need to be specified.
187 ;; (define_function_unit {name} {multiplicity} {simulataneity} {test}
188 ;; {ready-delay} {issue-delay} [{conflict-list}])
190 ;; Hack to get GCC to better pack the instructions.
191 ;; We pretend there is a separate long function unit that conflicts with
192 ;; both the left and right 16 bit insn slots.
194 (define_function_unit "short" 2 2
195 (and (eq_attr "m32r" "yes")
196 (and (eq_attr "insn_size" "short")
197 (eq_attr "type" "!load2")))
199 [(eq_attr "insn_size" "long")])
201 (define_function_unit "short" 2 2 ;; load delay of 1 clock for mem execution + 1 clock for WB
202 (and (eq_attr "m32r" "yes")
203 (eq_attr "type" "load2"))
205 [(eq_attr "insn_size" "long")])
207 (define_function_unit "long" 1 1
208 (and (eq_attr "m32r" "yes")
209 (and (eq_attr "insn_size" "long")
210 (eq_attr "type" "!load4,load8")))
212 [(eq_attr "insn_size" "short")])
214 (define_function_unit "long" 1 1 ;; load delay of 1 clock for mem execution + 1 clock for WB
215 (and (eq_attr "m32r" "yes")
216 (and (eq_attr "insn_size" "long")
217 (eq_attr "type" "load4,load8")))
219 [(eq_attr "insn_size" "short")])
222 ;; Expand prologue as RTL
223 (define_expand "prologue"
228 m32r_expand_prologue ();
233 ;; Move instructions.
235 ;; For QI and HI moves, the register must contain the full properly
236 ;; sign-extended value. nonzero_bits assumes this [otherwise
237 ;; SHORT_IMMEDIATES_SIGN_EXTEND must be used, but the comment for it
238 ;; says it's a kludge and the .md files should be fixed instead].
240 (define_expand "movqi"
241 [(set (match_operand:QI 0 "general_operand" "")
242 (match_operand:QI 1 "general_operand" ""))]
246 /* Everything except mem = const or mem = mem can be done easily.
247 Objects in the small data area are handled too. */
249 if (GET_CODE (operands[0]) == MEM)
250 operands[1] = force_reg (QImode, operands[1]);
253 (define_insn "*movqi_insn"
254 [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,r,r,T,m")
255 (match_operand:QI 1 "move_src_operand" "r,I,JQR,T,m,r,r"))]
256 "register_operand (operands[0], QImode) || register_operand (operands[1], QImode)"
265 [(set_attr "type" "int2,int2,int4,load2,load4,store2,store4")
266 (set_attr "length" "2,2,4,2,4,2,4")])
268 (define_expand "movhi"
269 [(set (match_operand:HI 0 "general_operand" "")
270 (match_operand:HI 1 "general_operand" ""))]
274 /* Everything except mem = const or mem = mem can be done easily. */
276 if (GET_CODE (operands[0]) == MEM)
277 operands[1] = force_reg (HImode, operands[1]);
280 (define_insn "*movhi_insn"
281 [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,r,r,r,T,m")
282 (match_operand:HI 1 "move_src_operand" "r,I,JQR,K,T,m,r,r"))]
283 "register_operand (operands[0], HImode) || register_operand (operands[1], HImode)"
293 [(set_attr "type" "int2,int2,int4,int4,load2,load4,store2,store4")
294 (set_attr "length" "2,2,4,4,2,4,2,4")])
296 (define_expand "movsi_push"
297 [(set (mem:SI (pre_dec:SI (match_operand:SI 0 "register_operand" "")))
298 (match_operand:SI 1 "register_operand" ""))]
302 (define_expand "movsi_pop"
303 [(set (match_operand:SI 0 "register_operand" "")
304 (mem:SI (post_inc:SI (match_operand:SI 1 "register_operand" ""))))]
308 (define_expand "movsi"
309 [(set (match_operand:SI 0 "general_operand" "")
310 (match_operand:SI 1 "general_operand" ""))]
314 /* Everything except mem = const or mem = mem can be done easily. */
316 if (GET_CODE (operands[0]) == MEM)
317 operands[1] = force_reg (SImode, operands[1]);
319 /* Small Data Area reference? */
320 if (small_data_operand (operands[1], SImode))
322 emit_insn (gen_movsi_sda (operands[0], operands[1]));
326 /* If medium or large code model, symbols have to be loaded with
328 if (addr32_operand (operands[1], SImode))
330 emit_insn (gen_movsi_addr32 (operands[0], operands[1]));
335 ;; ??? Do we need a const_double constraint here for large unsigned values?
336 (define_insn "*movsi_insn"
337 [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,r,r,r,r,r,r,T,S,m")
338 (match_operand:SI 1 "move_src_operand" "r,I,J,MQ,L,n,T,U,m,r,r,r"))]
339 "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)"
342 if (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == SUBREG)
344 switch (GET_CODE (operands[1]))
356 if (GET_CODE (XEXP (operands[1], 0)) == POST_INC
357 && XEXP (XEXP (operands[1], 0), 0) == stack_pointer_rtx)
363 value = INTVAL (operands[1]);
365 return \"ldi %0,%#%1\\t; %X1\";
367 if (UINT24_P (value))
368 return \"ld24 %0,%#%1\\t; %X1\";
370 if (UPPER16_P (value))
371 return \"seth %0,%#%T1\\t; %X1\";
379 return \"ld24 %0,%#%1\";
385 else if (GET_CODE (operands[0]) == MEM
386 && (GET_CODE (operands[1]) == REG || GET_CODE (operands[1]) == SUBREG))
388 if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
389 && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx)
397 [(set_attr "type" "int2,int2,int4,int4,int4,multi,load2,load2,load4,store2,store2,store4")
398 (set_attr "length" "2,2,4,4,4,8,2,2,4,2,2,4")])
400 ; Try to use a four byte / two byte pair for constants not loadable with
404 [(set (match_operand:SI 0 "register_operand" "")
405 (match_operand:SI 1 "two_insn_const_operand" ""))]
407 [(set (match_dup 0) (match_dup 2))
408 (set (match_dup 0) (ior:SI (match_dup 0) (match_dup 3)))]
411 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
412 unsigned HOST_WIDE_INT tmp;
415 /* In all cases we will emit two instructions. However we try to
416 use 2 byte instructions wherever possible. We can assume the
417 constant isn't loadable with any of ldi, ld24, or seth. */
419 /* See if we can load a 24 bit unsigned value and invert it. */
420 if (UINT24_P (~ val))
422 emit_insn (gen_movsi (operands[0], GEN_INT (~ val)));
423 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
427 /* See if we can load a 24 bit unsigned value and shift it into place.
428 0x01fffffe is just beyond ld24's range. */
429 for (shift = 1, tmp = 0x01fffffe;
433 if ((val & ~tmp) == 0)
435 emit_insn (gen_movsi (operands[0], GEN_INT (val >> shift)));
436 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (shift)));
441 /* Can't use any two byte insn, fall back to seth/or3. Use ~0xffff instead
442 of 0xffff0000, since the later fails on a 64-bit host. */
443 operands[2] = GEN_INT ((val) & ~0xffff);
444 operands[3] = GEN_INT ((val) & 0xffff);
448 [(set (match_operand:SI 0 "register_operand" "")
449 (match_operand:SI 1 "seth_add3_operand" "i"))]
452 (high:SI (match_dup 1)))
454 (lo_sum:SI (match_dup 0)
458 ;; Small data area support.
459 ;; The address of _SDA_BASE_ is loaded into a register and all objects in
460 ;; the small data area are indexed off that. This is done for each reference
461 ;; but cse will clean things up for us. We let the compiler choose the
462 ;; register to use so we needn't allocate (and maybe even fix) a special
463 ;; register to use. Since the load and store insns have a 16 bit offset the
464 ;; total size of the data area can be 64K. However, if the data area lives
465 ;; above 16M (24 bits), _SDA_BASE_ will have to be loaded with seth/add3 which
466 ;; would then yield 3 instructions to reference an object [though there would
467 ;; be no net loss if two or more objects were referenced]. The 3 insns can be
468 ;; reduced back to 2 if the size of the small data area were reduced to 32K
469 ;; [then seth + ld/st would work for any object in the area]. Doing this
470 ;; would require special handling of _SDA_BASE_ (its value would be
471 ;; (.sdata + 32K) & 0xffff0000) and reloc computations would be different
472 ;; [I think]. What to do about this is deferred until later and for now we
473 ;; require .sdata to be in the first 16M.
475 (define_expand "movsi_sda"
477 (unspec [(const_int 0)] 2))
478 (set (match_operand:SI 0 "register_operand" "")
479 (lo_sum:SI (match_dup 2)
480 (match_operand:SI 1 "small_data_operand" "")))]
484 if (reload_in_progress || reload_completed)
485 operands[2] = operands[0];
487 operands[2] = gen_reg_rtx (SImode);
490 (define_insn "*load_sda_base"
491 [(set (match_operand:SI 0 "register_operand" "=r")
492 (unspec [(const_int 0)] 2))]
494 "ld24 %0,#_SDA_BASE_"
495 [(set_attr "type" "int4")
496 (set_attr "length" "4")])
498 ;; 32 bit address support.
500 (define_expand "movsi_addr32"
502 ; addr32_operand isn't used because it's too restrictive,
503 ; seth_add3_operand is more general and thus safer.
504 (high:SI (match_operand:SI 1 "seth_add3_operand" "")))
505 (set (match_operand:SI 0 "register_operand" "")
506 (lo_sum:SI (match_dup 2) (match_dup 1)))]
510 if (reload_in_progress || reload_completed)
511 operands[2] = operands[0];
513 operands[2] = gen_reg_rtx (SImode);
516 (define_insn "set_hi_si"
517 [(set (match_operand:SI 0 "register_operand" "=r")
518 (high:SI (match_operand 1 "symbolic_operand" "")))]
520 "seth %0,%#shigh(%1)"
521 [(set_attr "type" "int4")
522 (set_attr "length" "4")])
524 (define_insn "lo_sum_si"
525 [(set (match_operand:SI 0 "register_operand" "=r")
526 (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
527 (match_operand:SI 2 "immediate_operand" "in")))]
530 [(set_attr "type" "int4")
531 (set_attr "length" "4")])
533 (define_expand "movdi"
534 [(set (match_operand:DI 0 "general_operand" "")
535 (match_operand:DI 1 "general_operand" ""))]
539 /* Everything except mem = const or mem = mem can be done easily. */
541 if (GET_CODE (operands[0]) == MEM)
542 operands[1] = force_reg (DImode, operands[1]);
545 (define_insn "*movdi_insn"
546 [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,r,m")
547 (match_operand:DI 1 "move_double_src_operand" "r,nG,F,m,r"))]
548 "register_operand (operands[0], DImode) || register_operand (operands[1], DImode)"
550 [(set_attr "type" "multi,multi,multi,load8,store8")
551 (set_attr "length" "4,4,16,6,6")])
554 [(set (match_operand:DI 0 "move_dest_operand" "")
555 (match_operand:DI 1 "move_double_src_operand" ""))]
558 "operands[2] = gen_split_move_double (operands);")
560 ;; Floating point move insns.
562 (define_expand "movsf"
563 [(set (match_operand:SF 0 "general_operand" "")
564 (match_operand:SF 1 "general_operand" ""))]
568 /* Everything except mem = const or mem = mem can be done easily. */
570 if (GET_CODE (operands[0]) == MEM)
571 operands[1] = force_reg (SFmode, operands[1]);
574 (define_insn "*movsf_insn"
575 [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,r,r,T,S,m")
576 (match_operand:SF 1 "move_src_operand" "r,F,U,S,m,r,r,r"))]
577 "register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode)"
587 ;; ??? Length of alternative 1 is either 2, 4 or 8.
588 [(set_attr "type" "int2,multi,load2,load2,load4,store2,store2,store4")
589 (set_attr "length" "2,8,2,2,4,2,2,4")])
592 [(set (match_operand:SF 0 "register_operand" "")
593 (match_operand:SF 1 "const_double_operand" ""))]
595 [(set (match_dup 2) (match_dup 3))]
598 operands[2] = operand_subword (operands[0], 0, 0, SFmode);
599 operands[3] = operand_subword (operands[1], 0, 0, SFmode);
602 (define_expand "movdf"
603 [(set (match_operand:DF 0 "general_operand" "")
604 (match_operand:DF 1 "general_operand" ""))]
608 /* Everything except mem = const or mem = mem can be done easily. */
610 if (GET_CODE (operands[0]) == MEM)
611 operands[1] = force_reg (DFmode, operands[1]);
614 (define_insn "*movdf_insn"
615 [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m")
616 (match_operand:DF 1 "move_double_src_operand" "r,F,m,r"))]
617 "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)"
619 [(set_attr "type" "multi,multi,load8,store8")
620 (set_attr "length" "4,16,6,6")])
623 [(set (match_operand:DF 0 "move_dest_operand" "")
624 (match_operand:DF 1 "move_double_src_operand" ""))]
627 "operands[2] = gen_split_move_double (operands);")
629 ;; Zero extension instructions.
631 (define_insn "zero_extendqihi2"
632 [(set (match_operand:HI 0 "register_operand" "=r,r,r")
633 (zero_extend:HI (match_operand:QI 1 "extend_operand" "r,T,m")))]
639 [(set_attr "type" "int4,load2,load4")
640 (set_attr "length" "4,2,4")])
642 (define_insn "zero_extendqisi2"
643 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
644 (zero_extend:SI (match_operand:QI 1 "extend_operand" "r,T,m")))]
650 [(set_attr "type" "int4,load2,load4")
651 (set_attr "length" "4,2,4")])
653 (define_insn "zero_extendhisi2"
654 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
655 (zero_extend:SI (match_operand:HI 1 "extend_operand" "r,T,m")))]
661 [(set_attr "type" "int4,load2,load4")
662 (set_attr "length" "4,2,4")])
664 ;; Signed conversions from a smaller integer to a larger integer
665 (define_insn "extendqihi2"
666 [(set (match_operand:HI 0 "register_operand" "=r,r,r")
667 (sign_extend:HI (match_operand:QI 1 "extend_operand" "0,T,m")))]
673 [(set_attr "type" "multi,load2,load4")
674 (set_attr "length" "2,2,4")])
677 [(set (match_operand:HI 0 "register_operand" "")
678 (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
684 rtx op0 = gen_lowpart (SImode, operands[0]);
685 rtx shift = gen_rtx (CONST_INT, VOIDmode, 24);
687 operands[2] = gen_ashlsi3 (op0, op0, shift);
688 operands[3] = gen_ashrsi3 (op0, op0, shift);
691 (define_insn "extendqisi2"
692 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
693 (sign_extend:SI (match_operand:QI 1 "extend_operand" "0,T,m")))]
699 [(set_attr "type" "multi,load2,load4")
700 (set_attr "length" "4,2,4")])
703 [(set (match_operand:SI 0 "register_operand" "")
704 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
710 rtx op0 = gen_lowpart (SImode, operands[0]);
711 rtx shift = gen_rtx (CONST_INT, VOIDmode, 24);
713 operands[2] = gen_ashlsi3 (op0, op0, shift);
714 operands[3] = gen_ashrsi3 (op0, op0, shift);
717 (define_insn "extendhisi2"
718 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
719 (sign_extend:SI (match_operand:HI 1 "extend_operand" "0,T,m")))]
725 [(set_attr "type" "multi,load2,load4")
726 (set_attr "length" "4,2,4")])
729 [(set (match_operand:SI 0 "register_operand" "")
730 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
736 rtx op0 = gen_lowpart (SImode, operands[0]);
737 rtx shift = gen_rtx (CONST_INT, VOIDmode, 16);
739 operands[2] = gen_ashlsi3 (op0, op0, shift);
740 operands[3] = gen_ashrsi3 (op0, op0, shift);
743 ;; Arithmetic instructions.
745 ; ??? Adding an alternative to split add3 of small constants into two
746 ; insns yields better instruction packing but slower code. Adds of small
747 ; values is done a lot.
749 (define_insn "addsi3"
750 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
751 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,r")
752 (match_operand:SI 2 "nonmemory_operand" "r,I,J")))]
758 [(set_attr "type" "int2,int2,int4")
759 (set_attr "length" "2,2,4")])
762 ; [(set (match_operand:SI 0 "register_operand" "")
763 ; (plus:SI (match_operand:SI 1 "register_operand" "")
764 ; (match_operand:SI 2 "int8_operand" "")))]
766 ; && REGNO (operands[0]) != REGNO (operands[1])
767 ; && INT8_P (INTVAL (operands[2]))
768 ; && INTVAL (operands[2]) != 0"
769 ; [(set (match_dup 0) (match_dup 1))
770 ; (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
773 (define_insn "adddi3"
774 [(set (match_operand:DI 0 "register_operand" "=r")
775 (plus:DI (match_operand:DI 1 "register_operand" "%0")
776 (match_operand:DI 2 "register_operand" "r")))
777 (clobber (reg:SI 17))]
780 [(set_attr "type" "multi")
781 (set_attr "length" "6")])
783 ;; ??? The cmp clears the condition bit. Can we speed up somehow?
785 [(set (match_operand:DI 0 "register_operand" "")
786 (plus:DI (match_operand:DI 1 "register_operand" "")
787 (match_operand:DI 2 "register_operand" "")))
788 (clobber (match_operand 3 "" ""))]
790 [(parallel [(set (match_dup 3)
792 (use (match_dup 4))])
793 (parallel [(set (match_dup 4)
794 (plus:SI (match_dup 4)
795 (plus:SI (match_dup 5)
798 (unspec [(const_int 0)] 3))])
799 (parallel [(set (match_dup 6)
800 (plus:SI (match_dup 6)
801 (plus:SI (match_dup 7)
804 (unspec [(const_int 0)] 3))])]
807 operands[4] = operand_subword (operands[0], (WORDS_BIG_ENDIAN != 0), 0, DImode);
808 operands[5] = operand_subword (operands[2], (WORDS_BIG_ENDIAN != 0), 0, DImode);
809 operands[6] = operand_subword (operands[0], (WORDS_BIG_ENDIAN == 0), 0, DImode);
810 operands[7] = operand_subword (operands[2], (WORDS_BIG_ENDIAN == 0), 0, DImode);
813 (define_insn "*clear_c"
816 (use (match_operand:SI 0 "register_operand" "r"))]
819 [(set_attr "type" "int2")
820 (set_attr "length" "2")])
822 (define_insn "*add_carry"
823 [(set (match_operand:SI 0 "register_operand" "=r")
824 (plus:SI (match_operand:SI 1 "register_operand" "%0")
825 (plus:SI (match_operand:SI 2 "register_operand" "r")
828 (unspec [(const_int 0)] 3))]
831 [(set_attr "type" "int2")
832 (set_attr "length" "2")])
834 (define_insn "subsi3"
835 [(set (match_operand:SI 0 "register_operand" "=r")
836 (minus:SI (match_operand:SI 1 "register_operand" "0")
837 (match_operand:SI 2 "register_operand" "r")))]
840 [(set_attr "type" "int2")
841 (set_attr "length" "2")])
843 (define_insn "subdi3"
844 [(set (match_operand:DI 0 "register_operand" "=r")
845 (minus:DI (match_operand:DI 1 "register_operand" "0")
846 (match_operand:DI 2 "register_operand" "r")))
847 (clobber (reg:SI 17))]
850 [(set_attr "type" "multi")
851 (set_attr "length" "6")])
853 ;; ??? The cmp clears the condition bit. Can we speed up somehow?
855 [(set (match_operand:DI 0 "register_operand" "")
856 (minus:DI (match_operand:DI 1 "register_operand" "")
857 (match_operand:DI 2 "register_operand" "")))
858 (clobber (match_operand 3 "" ""))]
860 [(parallel [(set (match_dup 3)
862 (use (match_dup 4))])
863 (parallel [(set (match_dup 4)
864 (minus:SI (match_dup 4)
865 (minus:SI (match_dup 5)
868 (unspec [(const_int 0)] 3))])
869 (parallel [(set (match_dup 6)
870 (minus:SI (match_dup 6)
871 (minus:SI (match_dup 7)
874 (unspec [(const_int 0)] 3))])]
877 operands[4] = operand_subword (operands[0], (WORDS_BIG_ENDIAN != 0), 0, DImode);
878 operands[5] = operand_subword (operands[2], (WORDS_BIG_ENDIAN != 0), 0, DImode);
879 operands[6] = operand_subword (operands[0], (WORDS_BIG_ENDIAN == 0), 0, DImode);
880 operands[7] = operand_subword (operands[2], (WORDS_BIG_ENDIAN == 0), 0, DImode);
883 (define_insn "*sub_carry"
884 [(set (match_operand:SI 0 "register_operand" "=r")
885 (minus:SI (match_operand:SI 1 "register_operand" "%0")
886 (minus:SI (match_operand:SI 2 "register_operand" "r")
889 (unspec [(const_int 0)] 3))]
892 [(set_attr "type" "int2")
893 (set_attr "length" "2")])
895 ; Multiply/Divide instructions.
897 (define_insn "mulhisi3"
898 [(set (match_operand:SI 0 "register_operand" "=r")
899 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
900 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
902 "mullo %1,%2\;mvfacmi %0"
903 [(set_attr "type" "multi")
904 (set_attr "length" "4")])
906 (define_insn "mulsi3"
907 [(set (match_operand:SI 0 "register_operand" "=r")
908 (mult:SI (match_operand:SI 1 "register_operand" "%0")
909 (match_operand:SI 2 "register_operand" "r")))]
912 [(set_attr "type" "mul2")
913 (set_attr "length" "2")])
915 (define_insn "divsi3"
916 [(set (match_operand:SI 0 "register_operand" "=r")
917 (div:SI (match_operand:SI 1 "register_operand" "0")
918 (match_operand:SI 2 "register_operand" "r")))]
921 [(set_attr "type" "div4")
922 (set_attr "length" "4")])
924 (define_insn "udivsi3"
925 [(set (match_operand:SI 0 "register_operand" "=r")
926 (udiv:SI (match_operand:SI 1 "register_operand" "0")
927 (match_operand:SI 2 "register_operand" "r")))]
930 [(set_attr "type" "div4")
931 (set_attr "length" "4")])
933 (define_insn "modsi3"
934 [(set (match_operand:SI 0 "register_operand" "=r")
935 (mod:SI (match_operand:SI 1 "register_operand" "0")
936 (match_operand:SI 2 "register_operand" "r")))]
939 [(set_attr "type" "div4")
940 (set_attr "length" "4")])
942 (define_insn "umodsi3"
943 [(set (match_operand:SI 0 "register_operand" "=r")
944 (umod:SI (match_operand:SI 1 "register_operand" "0")
945 (match_operand:SI 2 "register_operand" "r")))]
948 [(set_attr "type" "div4")
949 (set_attr "length" "4")])
951 ;; Boolean instructions.
953 ;; We don't define the DImode versions as expand_binop does a good enough job.
954 ;; And if it doesn't it should be fixed.
956 (define_insn "andsi3"
957 [(set (match_operand:SI 0 "register_operand" "=r,r")
958 (and:SI (match_operand:SI 1 "register_operand" "%0,r")
959 (match_operand:SI 2 "reg_or_uint16_operand" "r,K")))]
963 /* If we are worried about space, see if we can break this up into two
964 short instructions, which might eliminate a NOP being inserted. */
966 && m32r_not_same_reg (operands[0], operands[1])
967 && GET_CODE (operands[2]) == CONST_INT
968 && INT8_P (INTVAL (operands[2])))
971 else if (GET_CODE (operands[2]) == CONST_INT)
972 return \"and3 %0,%1,%#%X2\";
974 return \"and %0,%2\";
976 [(set_attr "type" "int2,int4")
977 (set_attr "length" "2,4")])
980 [(set (match_operand:SI 0 "register_operand" "")
981 (and:SI (match_operand:SI 1 "register_operand" "")
982 (match_operand:SI 2 "int8_operand" "")))]
983 "optimize_size && m32r_not_same_reg (operands[0], operands[1])"
984 [(set (match_dup 0) (match_dup 2))
985 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 0)))]
988 (define_insn "iorsi3"
989 [(set (match_operand:SI 0 "register_operand" "=r,r")
990 (ior:SI (match_operand:SI 1 "register_operand" "%0,r")
991 (match_operand:SI 2 "reg_or_uint16_operand" "r,K")))]
995 /* If we are worried about space, see if we can break this up into two
996 short instructions, which might eliminate a NOP being inserted. */
998 && m32r_not_same_reg (operands[0], operands[1])
999 && GET_CODE (operands[2]) == CONST_INT
1000 && INT8_P (INTVAL (operands[2])))
1003 else if (GET_CODE (operands[2]) == CONST_INT)
1004 return \"or3 %0,%1,%#%X2\";
1006 return \"or %0,%2\";
1008 [(set_attr "type" "int2,int4")
1009 (set_attr "length" "2,4")])
1012 [(set (match_operand:SI 0 "register_operand" "")
1013 (ior:SI (match_operand:SI 1 "register_operand" "")
1014 (match_operand:SI 2 "int8_operand" "")))]
1015 "optimize_size && m32r_not_same_reg (operands[0], operands[1])"
1016 [(set (match_dup 0) (match_dup 2))
1017 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 0)))]
1020 (define_insn "xorsi3"
1021 [(set (match_operand:SI 0 "register_operand" "=r,r")
1022 (xor:SI (match_operand:SI 1 "register_operand" "%0,r")
1023 (match_operand:SI 2 "reg_or_uint16_operand" "r,K")))]
1027 /* If we are worried about space, see if we can break this up into two
1028 short instructions, which might eliminate a NOP being inserted. */
1030 && m32r_not_same_reg (operands[0], operands[1])
1031 && GET_CODE (operands[2]) == CONST_INT
1032 && INT8_P (INTVAL (operands[2])))
1035 else if (GET_CODE (operands[2]) == CONST_INT)
1036 return \"xor3 %0,%1,%#%X2\";
1038 return \"xor %0,%2\";
1040 [(set_attr "type" "int2,int4")
1041 (set_attr "length" "2,4")])
1044 [(set (match_operand:SI 0 "register_operand" "")
1045 (xor:SI (match_operand:SI 1 "register_operand" "")
1046 (match_operand:SI 2 "int8_operand" "")))]
1047 "optimize_size && m32r_not_same_reg (operands[0], operands[1])"
1048 [(set (match_dup 0) (match_dup 2))
1049 (set (match_dup 0) (xor:SI (match_dup 1) (match_dup 0)))]
1052 (define_insn "negsi2"
1053 [(set (match_operand:SI 0 "register_operand" "=r")
1054 (neg:SI (match_operand:SI 1 "register_operand" "r")))]
1057 [(set_attr "type" "int2")
1058 (set_attr "length" "2")])
1060 (define_insn "one_cmplsi2"
1061 [(set (match_operand:SI 0 "register_operand" "=r")
1062 (not:SI (match_operand:SI 1 "register_operand" "r")))]
1065 [(set_attr "type" "int2")
1066 (set_attr "length" "2")])
1068 ;; Shift instructions.
1070 (define_insn "ashlsi3"
1071 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1072 (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r")
1073 (match_operand:SI 2 "reg_or_uint16_operand" "r,O,K")))]
1079 [(set_attr "type" "shift2,shift2,shift4")
1080 (set_attr "length" "2,2,4")])
1082 (define_insn "ashrsi3"
1083 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1084 (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1085 (match_operand:SI 2 "reg_or_uint16_operand" "r,O,K")))]
1091 [(set_attr "type" "shift2,shift2,shift4")
1092 (set_attr "length" "2,2,4")])
1094 (define_insn "lshrsi3"
1095 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1096 (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1097 (match_operand:SI 2 "reg_or_uint16_operand" "r,O,K")))]
1103 [(set_attr "type" "shift2,shift2,shift4")
1104 (set_attr "length" "2,2,4")])
1106 ;; Compare instructions.
1107 ;; This controls RTL generation and register allocation.
1109 ;; We generate RTL for comparisons and branches by having the cmpxx
1110 ;; patterns store away the operands. Then the bcc patterns
1111 ;; emit RTL for both the compare and the branch.
1113 ;; On the m32r it is more efficient to use the bxxz instructions and
1114 ;; thus merge the compare and branch into one instruction, so they are
1117 (define_expand "cmpsi"
1119 (compare:CC (match_operand:SI 0 "register_operand" "")
1120 (match_operand:SI 1 "reg_or_cmp_int16_operand" "")))]
1124 m32r_compare_op0 = operands[0];
1125 m32r_compare_op1 = operands[1];
1129 ;; The cmp_xxx_insn patterns set the condition bit to the result of the
1130 ;; comparison. There isn't a "compare equal" instruction so cmp_eqsi_insn
1131 ;; is quite inefficient. However, it is rarely used.
1133 (define_insn "cmp_eqsi_insn"
1135 (eq:SI (match_operand:SI 0 "register_operand" "r,r")
1136 (match_operand:SI 1 "reg_or_cmp_int16_operand" "r,P")))
1137 (clobber (match_scratch:SI 2 "=&r,&r"))]
1141 if (which_alternative == 0)
1143 return \"mv %2,%0\;sub %2,%1\;cmpui %2,#1\";
1147 if (INTVAL (operands [1]) == 0)
1148 return \"cmpui %0, #1\";
1149 else if (REGNO (operands [2]) == REGNO (operands [0]))
1150 return \"addi %0,%#%N1\;cmpui %2,#1\";
1152 return \"add3 %2,%0,%#%N1\;cmpui %2,#1\";
1155 [(set_attr "type" "multi,multi")
1156 (set_attr "length" "8,8")])
1158 (define_insn "cmp_ltsi_insn"
1160 (lt:SI (match_operand:SI 0 "register_operand" "r,r")
1161 (match_operand:SI 1 "reg_or_int16_operand" "r,J")))]
1166 [(set_attr "type" "int2,int4")
1167 (set_attr "length" "2,4")])
1169 (define_insn "cmp_ltusi_insn"
1171 (ltu:SI (match_operand:SI 0 "register_operand" "r,r")
1172 (match_operand:SI 1 "reg_or_int16_operand" "r,J")))]
1177 [(set_attr "type" "int2,int4")
1178 (set_attr "length" "2,4")])
1180 ;; reg == small constant comparisons are best handled by putting the result
1181 ;; of the comparison in a tmp reg and then using beqz/bnez.
1182 ;; ??? The result register doesn't contain 0/STORE_FLAG_VALUE,
1183 ;; it contains 0/non-zero.
1185 (define_insn "cmp_ne_small_const_insn"
1186 [(set (match_operand:SI 0 "register_operand" "=r,r")
1187 (ne:SI (match_operand:SI 1 "register_operand" "0,r")
1188 (match_operand:SI 2 "cmp_int16_operand" "N,P")))]
1193 [(set_attr "type" "int2,int4")
1194 (set_attr "length" "2,4")])
1196 ;; These control RTL generation for conditional jump insns.
1198 (define_expand "beq"
1200 (if_then_else (match_dup 1)
1201 (label_ref (match_operand 0 "" ""))
1206 operands[1] = gen_compare (EQ, m32r_compare_op0, m32r_compare_op1, FALSE);
1209 (define_expand "bne"
1211 (if_then_else (match_dup 1)
1212 (label_ref (match_operand 0 "" ""))
1217 operands[1] = gen_compare (NE, m32r_compare_op0, m32r_compare_op1, FALSE);
1220 (define_expand "bgt"
1222 (if_then_else (match_dup 1)
1223 (label_ref (match_operand 0 "" ""))
1228 operands[1] = gen_compare (GT, m32r_compare_op0, m32r_compare_op1, FALSE);
1231 (define_expand "ble"
1233 (if_then_else (match_dup 1)
1234 (label_ref (match_operand 0 "" ""))
1239 operands[1] = gen_compare (LE, m32r_compare_op0, m32r_compare_op1, FALSE);
1242 (define_expand "bge"
1244 (if_then_else (match_dup 1)
1245 (label_ref (match_operand 0 "" ""))
1250 operands[1] = gen_compare (GE, m32r_compare_op0, m32r_compare_op1, FALSE);
1253 (define_expand "blt"
1255 (if_then_else (match_dup 1)
1256 (label_ref (match_operand 0 "" ""))
1261 operands[1] = gen_compare (LT, m32r_compare_op0, m32r_compare_op1, FALSE);
1264 (define_expand "bgtu"
1266 (if_then_else (match_dup 1)
1267 (label_ref (match_operand 0 "" ""))
1272 operands[1] = gen_compare (GTU, m32r_compare_op0, m32r_compare_op1, FALSE);
1275 (define_expand "bleu"
1277 (if_then_else (match_dup 1)
1278 (label_ref (match_operand 0 "" ""))
1283 operands[1] = gen_compare (LEU, m32r_compare_op0, m32r_compare_op1, FALSE);
1286 (define_expand "bgeu"
1288 (if_then_else (match_dup 1)
1289 (label_ref (match_operand 0 "" ""))
1294 operands[1] = gen_compare (GEU, m32r_compare_op0, m32r_compare_op1, FALSE);
1297 (define_expand "bltu"
1299 (if_then_else (match_dup 1)
1300 (label_ref (match_operand 0 "" ""))
1305 operands[1] = gen_compare (LTU, m32r_compare_op0, m32r_compare_op1, FALSE);
1308 ;; Now match both normal and inverted jump.
1310 (define_insn "*branch_insn"
1312 (if_then_else (match_operator 1 "eqne_comparison_operator"
1313 [(reg 17) (const_int 0)])
1314 (label_ref (match_operand 0 "" ""))
1319 static char instruction[40];
1320 sprintf (instruction, \"%s%s %%l0\",
1321 (GET_CODE (operands[1]) == NE) ? \"bc\" : \"bnc\",
1322 (get_attr_length (insn) == 2) ? \".s\" : \"\");
1325 [(set_attr "type" "branch")
1326 ; We use 400/800 instead of 512,1024 to account for inaccurate insn
1327 ; lengths and insn alignments that are complex to track.
1328 ; It's not important that we be hyper-precise here. It may be more
1329 ; important blah blah blah when the chip supports parallel execution
1330 ; blah blah blah but until then blah blah blah this is simple and
1332 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1338 (define_insn "*rev_branch_insn"
1340 (if_then_else (match_operator 1 "eqne_comparison_operator"
1341 [(reg 17) (const_int 0)])
1343 (label_ref (match_operand 0 "" ""))))]
1344 ;"REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
1348 static char instruction[40];
1349 sprintf (instruction, \"%s%s %%l0\",
1350 (GET_CODE (operands[1]) == EQ) ? \"bc\" : \"bnc\",
1351 (get_attr_length (insn) == 2) ? \".s\" : \"\");
1354 [(set_attr "type" "branch")
1355 ; We use 400/800 instead of 512,1024 to account for inaccurate insn
1356 ; lengths and insn alignments that are complex to track.
1357 ; It's not important that we be hyper-precise here. It may be more
1358 ; important blah blah blah when the chip supports parallel execution
1359 ; blah blah blah but until then blah blah blah this is simple and
1361 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1367 ; reg/reg compare and branch insns
1369 (define_insn "*reg_branch_insn"
1371 (if_then_else (match_operator 1 "eqne_comparison_operator"
1372 [(match_operand:SI 2 "register_operand" "r")
1373 (match_operand:SI 3 "register_operand" "r")])
1374 (label_ref (match_operand 0 "" ""))
1379 /* Is branch target reachable with beq/bne? */
1380 if (get_attr_length (insn) == 4)
1382 if (GET_CODE (operands[1]) == EQ)
1383 return \"beq %2,%3,%l0\";
1385 return \"bne %2,%3,%l0\";
1389 if (GET_CODE (operands[1]) == EQ)
1390 return \"bne %2,%3,1f\;bra %l0\;1:\";
1392 return \"beq %2,%3,1f\;bra %l0\;1:\";
1395 [(set_attr "type" "branch")
1396 ; We use 25000/50000 instead of 32768/65536 to account for slot filling
1397 ; which is complex to track and inaccurate length specs.
1398 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1404 (define_insn "*rev_reg_branch_insn"
1406 (if_then_else (match_operator 1 "eqne_comparison_operator"
1407 [(match_operand:SI 2 "register_operand" "r")
1408 (match_operand:SI 3 "register_operand" "r")])
1410 (label_ref (match_operand 0 "" ""))))]
1414 /* Is branch target reachable with beq/bne? */
1415 if (get_attr_length (insn) == 4)
1417 if (GET_CODE (operands[1]) == NE)
1418 return \"beq %2,%3,%l0\";
1420 return \"bne %2,%3,%l0\";
1424 if (GET_CODE (operands[1]) == NE)
1425 return \"bne %2,%3,1f\;bra %l0\;1:\";
1427 return \"beq %2,%3,1f\;bra %l0\;1:\";
1430 [(set_attr "type" "branch")
1431 ; We use 25000/50000 instead of 32768/65536 to account for slot filling
1432 ; which is complex to track and inaccurate length specs.
1433 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1439 ; reg/zero compare and branch insns
1441 (define_insn "*zero_branch_insn"
1443 (if_then_else (match_operator 1 "signed_comparison_operator"
1444 [(match_operand:SI 2 "register_operand" "r")
1446 (label_ref (match_operand 0 "" ""))
1454 switch (GET_CODE (operands[1]))
1456 case EQ : br = \"eq\"; invbr = \"ne\"; break;
1457 case NE : br = \"ne\"; invbr = \"eq\"; break;
1458 case LE : br = \"le\"; invbr = \"gt\"; break;
1459 case GT : br = \"gt\"; invbr = \"le\"; break;
1460 case LT : br = \"lt\"; invbr = \"ge\"; break;
1461 case GE : br = \"ge\"; invbr = \"lt\"; break;
1466 /* Is branch target reachable with bxxz? */
1467 if (get_attr_length (insn) == 4)
1469 sprintf (asmtext, \"b%sz %%2,%%l0\", br);
1470 output_asm_insn (asmtext, operands);
1474 sprintf (asmtext, \"b%sz %%2,1f\;bra %%l0\;1:\", invbr);
1475 output_asm_insn (asmtext, operands);
1479 [(set_attr "type" "branch")
1480 ; We use 25000/50000 instead of 32768/65536 to account for slot filling
1481 ; which is complex to track and inaccurate length specs.
1482 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1488 (define_insn "*rev_zero_branch_insn"
1490 (if_then_else (match_operator 1 "eqne_comparison_operator"
1491 [(match_operand:SI 2 "register_operand" "r")
1494 (label_ref (match_operand 0 "" ""))))]
1501 switch (GET_CODE (operands[1]))
1503 case EQ : br = \"eq\"; invbr = \"ne\"; break;
1504 case NE : br = \"ne\"; invbr = \"eq\"; break;
1505 case LE : br = \"le\"; invbr = \"gt\"; break;
1506 case GT : br = \"gt\"; invbr = \"le\"; break;
1507 case LT : br = \"lt\"; invbr = \"ge\"; break;
1508 case GE : br = \"ge\"; invbr = \"lt\"; break;
1513 /* Is branch target reachable with bxxz? */
1514 if (get_attr_length (insn) == 4)
1516 sprintf (asmtext, \"b%sz %%2,%%l0\", invbr);
1517 output_asm_insn (asmtext, operands);
1521 sprintf (asmtext, \"b%sz %%2,1f\;bra %%l0\;1:\", br);
1522 output_asm_insn (asmtext, operands);
1526 [(set_attr "type" "branch")
1527 ; We use 25000/50000 instead of 32768/65536 to account for slot filling
1528 ; which is complex to track and inaccurate length specs.
1529 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1535 ;; S<cc> operations to set a register to 1/0 based on a comparison
1537 (define_expand "seq"
1538 [(match_operand:SI 0 "register_operand" "")]
1542 rtx op0 = operands[0];
1543 rtx op1 = m32r_compare_op0;
1544 rtx op2 = m32r_compare_op1;
1545 enum machine_mode mode = GET_MODE (op0);
1550 if (! register_operand (op1, mode))
1551 op1 = force_reg (mode, op1);
1553 if (GET_CODE (op2) == CONST_INT && INTVAL (op2) == 0)
1555 emit_insn (gen_seq_zero_insn (op0, op1));
1559 if (! reg_or_eq_int16_operand (op2, mode))
1560 op2 = force_reg (mode, op2);
1562 emit_insn (gen_seq_insn (op0, op1, op2));
1566 (define_insn "seq_zero_insn"
1567 [(set (match_operand:SI 0 "register_operand" "=r")
1568 (eq:SI (match_operand:SI 1 "register_operand" "r")
1570 (clobber (reg:SI 17))]
1573 [(set_attr "type" "multi")
1574 (set_attr "length" "6")])
1577 [(set (match_operand:SI 0 "register_operand" "")
1578 (eq:SI (match_operand:SI 1 "register_operand" "")
1580 (clobber (reg:SI 17))]
1585 rtx op0 = operands[0];
1586 rtx op1 = operands[1];
1589 emit_insn (gen_cmp_ltusi_insn (op1, GEN_INT (1)));
1590 emit_insn (gen_movcc_insn (op0));
1591 operands[3] = gen_sequence ();
1595 (define_insn "seq_insn"
1596 [(set (match_operand:SI 0 "register_operand" "=r,r,??r,r")
1597 (eq:SI (match_operand:SI 1 "register_operand" "r,r,r,r")
1598 (match_operand:SI 2 "reg_or_eq_int16_operand" "r,r,r,PK")))
1599 (clobber (reg:SI 17))
1600 (clobber (match_scratch:SI 3 "=1,2,&r,r"))]
1603 [(set_attr "type" "multi")
1604 (set_attr "length" "8,8,10,10")])
1607 [(set (match_operand:SI 0 "register_operand" "")
1608 (eq:SI (match_operand:SI 1 "register_operand" "")
1609 (match_operand:SI 2 "reg_or_eq_int16_operand" "")))
1610 (clobber (reg:SI 17))
1611 (clobber (match_scratch:SI 3 ""))]
1612 "TARGET_M32R && reload_completed"
1616 rtx op0 = operands[0];
1617 rtx op1 = operands[1];
1618 rtx op2 = operands[2];
1619 rtx op3 = operands[3];
1620 HOST_WIDE_INT value;
1622 if (GET_CODE (op2) == REG && GET_CODE (op3) == REG
1623 && REGNO (op2) == REGNO (op3))
1630 if (GET_CODE (op1) == REG && GET_CODE (op3) == REG
1631 && REGNO (op1) != REGNO (op3))
1633 emit_move_insn (op3, op1);
1637 if (GET_CODE (op2) == CONST_INT && (value = INTVAL (op2)) != 0
1638 && CMP_INT16_P (value))
1639 emit_insn (gen_addsi3 (op3, op1, GEN_INT (-value)));
1641 emit_insn (gen_xorsi3 (op3, op1, op2));
1643 emit_insn (gen_cmp_ltusi_insn (op3, GEN_INT (1)));
1644 emit_insn (gen_movcc_insn (op0));
1645 operands[4] = gen_sequence ();
1649 (define_expand "sne"
1650 [(match_operand:SI 0 "register_operand" "")]
1654 rtx op0 = operands[0];
1655 rtx op1 = m32r_compare_op0;
1656 rtx op2 = m32r_compare_op1;
1657 enum machine_mode mode = GET_MODE (op0);
1662 if (GET_CODE (op2) != CONST_INT
1663 || (INTVAL (op2) != 0 && UINT16_P (INTVAL (op2))))
1667 if (reload_completed || reload_in_progress)
1670 reg = gen_reg_rtx (SImode);
1671 emit_insn (gen_xorsi3 (reg, op1, op2));
1674 if (! register_operand (op1, mode))
1675 op1 = force_reg (mode, op1);
1677 emit_insn (gen_sne_zero_insn (op0, op1));
1684 (define_insn "sne_zero_insn"
1685 [(set (match_operand:SI 0 "register_operand" "=r")
1686 (ne:SI (match_operand:SI 1 "register_operand" "r")
1688 (clobber (reg:SI 17))
1689 (clobber (match_scratch:SI 2 "=&r"))]
1692 [(set_attr "type" "multi")
1693 (set_attr "length" "6")])
1696 [(set (match_operand:SI 0 "register_operand" "")
1697 (ne:SI (match_operand:SI 1 "register_operand" "")
1699 (clobber (reg:SI 17))
1700 (clobber (match_scratch:SI 2 ""))]
1705 (ltu:SI (match_dup 2)
1711 (define_expand "slt"
1712 [(match_operand:SI 0 "register_operand" "")]
1716 rtx op0 = operands[0];
1717 rtx op1 = m32r_compare_op0;
1718 rtx op2 = m32r_compare_op1;
1719 enum machine_mode mode = GET_MODE (op0);
1724 if (! register_operand (op1, mode))
1725 op1 = force_reg (mode, op1);
1727 if (! reg_or_int16_operand (op2, mode))
1728 op2 = force_reg (mode, op2);
1730 emit_insn (gen_slt_insn (op0, op1, op2));
1734 (define_insn "slt_insn"
1735 [(set (match_operand:SI 0 "register_operand" "=r,r")
1736 (lt:SI (match_operand:SI 1 "register_operand" "r,r")
1737 (match_operand:SI 2 "reg_or_int16_operand" "r,J")))
1738 (clobber (reg:SI 17))]
1741 [(set_attr "type" "multi")
1742 (set_attr "length" "4,6")])
1745 [(set (match_operand:SI 0 "register_operand" "")
1746 (lt:SI (match_operand:SI 1 "register_operand" "")
1747 (match_operand:SI 2 "reg_or_int16_operand" "")))
1748 (clobber (reg:SI 17))]
1751 (lt:SI (match_dup 1)
1757 (define_expand "sle"
1758 [(match_operand:SI 0 "register_operand" "")]
1762 rtx op0 = operands[0];
1763 rtx op1 = m32r_compare_op0;
1764 rtx op2 = m32r_compare_op1;
1765 enum machine_mode mode = GET_MODE (op0);
1770 if (! register_operand (op1, mode))
1771 op1 = force_reg (mode, op1);
1773 if (GET_CODE (op2) == CONST_INT)
1775 HOST_WIDE_INT value = INTVAL (op2);
1776 if (value >= 2147483647)
1778 emit_move_insn (op0, GEN_INT (1));
1782 op2 = GEN_INT (value+1);
1783 if (value < -32768 || value >= 32767)
1784 op2 = force_reg (mode, op2);
1786 emit_insn (gen_slt_insn (op0, op1, op2));
1790 if (! register_operand (op2, mode))
1791 op2 = force_reg (mode, op2);
1793 emit_insn (gen_sle_insn (op0, op1, op2));
1797 (define_insn "sle_insn"
1798 [(set (match_operand:SI 0 "register_operand" "=r")
1799 (le:SI (match_operand:SI 1 "register_operand" "r")
1800 (match_operand:SI 2 "register_operand" "r")))
1801 (clobber (reg:SI 17))]
1804 [(set_attr "type" "multi")
1805 (set_attr "length" "8")])
1808 [(set (match_operand:SI 0 "register_operand" "")
1809 (le:SI (match_operand:SI 1 "register_operand" "")
1810 (match_operand:SI 2 "register_operand" "")))
1811 (clobber (reg:SI 17))]
1814 (lt:SI (match_dup 2)
1819 (xor:SI (match_dup 0)
1823 ;; If optimizing for space, use -(reg - 1) to invert the comparison rather than
1824 ;; xor reg,reg,1 which might eliminate a NOP being inserted.
1826 [(set (match_operand:SI 0 "register_operand" "")
1827 (le:SI (match_operand:SI 1 "register_operand" "")
1828 (match_operand:SI 2 "register_operand" "")))
1829 (clobber (reg:SI 17))]
1832 (lt:SI (match_dup 2)
1837 (plus:SI (match_dup 0)
1840 (neg:SI (match_dup 0)))]
1843 (define_expand "sgt"
1844 [(match_operand:SI 0 "register_operand" "")]
1848 rtx op0 = operands[0];
1849 rtx op1 = m32r_compare_op0;
1850 rtx op2 = m32r_compare_op1;
1851 enum machine_mode mode = GET_MODE (op0);
1856 if (! register_operand (op1, mode))
1857 op1 = force_reg (mode, op1);
1859 if (! register_operand (op2, mode))
1860 op2 = force_reg (mode, op2);
1862 emit_insn (gen_slt_insn (op0, op2, op1));
1866 (define_expand "sge"
1867 [(match_operand:SI 0 "register_operand" "")]
1871 rtx op0 = operands[0];
1872 rtx op1 = m32r_compare_op0;
1873 rtx op2 = m32r_compare_op1;
1874 enum machine_mode mode = GET_MODE (op0);
1879 if (! register_operand (op1, mode))
1880 op1 = force_reg (mode, op1);
1882 if (! reg_or_int16_operand (op2, mode))
1883 op2 = force_reg (mode, op2);
1885 emit_insn (gen_sge_insn (op0, op1, op2));
1889 (define_insn "sge_insn"
1890 [(set (match_operand:SI 0 "register_operand" "=r,r")
1891 (ge:SI (match_operand:SI 1 "register_operand" "r,r")
1892 (match_operand:SI 2 "reg_or_int16_operand" "r,J")))
1893 (clobber (reg:SI 17))]
1896 [(set_attr "type" "multi")
1897 (set_attr "length" "8,10")])
1900 [(set (match_operand:SI 0 "register_operand" "")
1901 (ge:SI (match_operand:SI 1 "register_operand" "")
1902 (match_operand:SI 2 "reg_or_int16_operand" "")))
1903 (clobber (reg:SI 17))]
1906 (lt:SI (match_dup 1)
1911 (xor:SI (match_dup 0)
1915 ;; If optimizing for space, use -(reg - 1) to invert the comparison rather than
1916 ;; xor reg,reg,1 which might eliminate a NOP being inserted.
1918 [(set (match_operand:SI 0 "register_operand" "")
1919 (ge:SI (match_operand:SI 1 "register_operand" "")
1920 (match_operand:SI 2 "reg_or_int16_operand" "")))
1921 (clobber (reg:SI 17))]
1924 (lt:SI (match_dup 1)
1929 (plus:SI (match_dup 0)
1932 (neg:SI (match_dup 0)))]
1935 (define_expand "sltu"
1936 [(match_operand:SI 0 "register_operand" "")]
1940 rtx op0 = operands[0];
1941 rtx op1 = m32r_compare_op0;
1942 rtx op2 = m32r_compare_op1;
1943 enum machine_mode mode = GET_MODE (op0);
1948 if (! register_operand (op1, mode))
1949 op1 = force_reg (mode, op1);
1951 if (! reg_or_int16_operand (op2, mode))
1952 op2 = force_reg (mode, op2);
1954 emit_insn (gen_sltu_insn (op0, op1, op2));
1958 (define_insn "sltu_insn"
1959 [(set (match_operand:SI 0 "register_operand" "=r,r")
1960 (ltu:SI (match_operand:SI 1 "register_operand" "r,r")
1961 (match_operand:SI 2 "reg_or_int16_operand" "r,J")))
1962 (clobber (reg:SI 17))]
1965 [(set_attr "type" "multi")
1966 (set_attr "length" "6,8")])
1969 [(set (match_operand:SI 0 "register_operand" "")
1970 (ltu:SI (match_operand:SI 1 "register_operand" "")
1971 (match_operand:SI 2 "reg_or_int16_operand" "")))
1972 (clobber (reg:SI 17))]
1975 (ltu:SI (match_dup 1)
1981 (define_expand "sleu"
1982 [(match_operand:SI 0 "register_operand" "")]
1986 rtx op0 = operands[0];
1987 rtx op1 = m32r_compare_op0;
1988 rtx op2 = m32r_compare_op1;
1989 enum machine_mode mode = GET_MODE (op0);
1994 if (GET_CODE (op2) == CONST_INT)
1996 HOST_WIDE_INT value = INTVAL (op2);
1997 if (value >= 2147483647)
1999 emit_move_insn (op0, GEN_INT (1));
2003 op2 = GEN_INT (value+1);
2004 if (value < 0 || value >= 32767)
2005 op2 = force_reg (mode, op2);
2007 emit_insn (gen_sltu_insn (op0, op1, op2));
2011 if (! register_operand (op2, mode))
2012 op2 = force_reg (mode, op2);
2014 emit_insn (gen_sleu_insn (op0, op1, op2));
2018 (define_insn "sleu_insn"
2019 [(set (match_operand:SI 0 "register_operand" "=r")
2020 (leu:SI (match_operand:SI 1 "register_operand" "r")
2021 (match_operand:SI 2 "register_operand" "r")))
2022 (clobber (reg:SI 17))]
2025 [(set_attr "type" "multi")
2026 (set_attr "length" "8")])
2029 [(set (match_operand:SI 0 "register_operand" "")
2030 (leu:SI (match_operand:SI 1 "register_operand" "")
2031 (match_operand:SI 2 "register_operand" "")))
2032 (clobber (reg:SI 17))]
2035 (ltu:SI (match_dup 2)
2040 (xor:SI (match_dup 0)
2044 ;; If optimizing for space, use -(reg - 1) to invert the comparison rather than
2045 ;; xor reg,reg,1 which might eliminate a NOP being inserted.
2047 [(set (match_operand:SI 0 "register_operand" "")
2048 (leu:SI (match_operand:SI 1 "register_operand" "")
2049 (match_operand:SI 2 "register_operand" "")))
2050 (clobber (reg:SI 17))]
2053 (ltu:SI (match_dup 2)
2058 (plus:SI (match_dup 0)
2061 (neg:SI (match_dup 0)))]
2064 (define_expand "sgtu"
2065 [(match_operand:SI 0 "register_operand" "")]
2069 rtx op0 = operands[0];
2070 rtx op1 = m32r_compare_op0;
2071 rtx op2 = m32r_compare_op1;
2072 enum machine_mode mode = GET_MODE (op0);
2077 if (! register_operand (op1, mode))
2078 op1 = force_reg (mode, op1);
2080 if (! register_operand (op2, mode))
2081 op2 = force_reg (mode, op2);
2083 emit_insn (gen_sltu_insn (op0, op2, op1));
2087 (define_expand "sgeu"
2088 [(match_operand:SI 0 "register_operand" "")]
2092 rtx op0 = operands[0];
2093 rtx op1 = m32r_compare_op0;
2094 rtx op2 = m32r_compare_op1;
2095 enum machine_mode mode = GET_MODE (op0);
2100 if (! register_operand (op1, mode))
2101 op1 = force_reg (mode, op1);
2103 if (! reg_or_int16_operand (op2, mode))
2104 op2 = force_reg (mode, op2);
2106 emit_insn (gen_sgeu_insn (op0, op1, op2));
2110 (define_insn "sgeu_insn"
2111 [(set (match_operand:SI 0 "register_operand" "=r,r")
2112 (geu:SI (match_operand:SI 1 "register_operand" "r,r")
2113 (match_operand:SI 2 "reg_or_int16_operand" "r,J")))
2114 (clobber (reg:SI 17))]
2117 [(set_attr "type" "multi")
2118 (set_attr "length" "8,10")])
2121 [(set (match_operand:SI 0 "register_operand" "")
2122 (geu:SI (match_operand:SI 1 "register_operand" "")
2123 (match_operand:SI 2 "reg_or_int16_operand" "")))
2124 (clobber (reg:SI 17))]
2127 (ltu:SI (match_dup 1)
2132 (xor:SI (match_dup 0)
2136 ;; If optimizing for space, use -(reg - 1) to invert the comparison rather than
2137 ;; xor reg,reg,1 which might eliminate a NOP being inserted.
2139 [(set (match_operand:SI 0 "register_operand" "")
2140 (geu:SI (match_operand:SI 1 "register_operand" "")
2141 (match_operand:SI 2 "reg_or_int16_operand" "")))
2142 (clobber (reg:SI 17))]
2145 (ltu:SI (match_dup 1)
2150 (plus:SI (match_dup 0)
2153 (neg:SI (match_dup 0)))]
2156 (define_insn "movcc_insn"
2157 [(set (match_operand:SI 0 "register_operand" "=r")
2161 [(set_attr "type" "misc")
2162 (set_attr "length" "2")])
2165 ;; Unconditional and other jump instructions.
2168 [(set (pc) (label_ref (match_operand 0 "" "")))]
2171 [(set_attr "type" "uncond_branch")
2172 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
2178 (define_insn "indirect_jump"
2179 [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
2182 [(set_attr "type" "uncond_branch")
2183 (set_attr "length" "2")])
2185 (define_insn "return"
2189 [(set_attr "type" "uncond_branch")
2190 (set_attr "length" "2")])
2192 (define_insn "tablejump"
2193 [(set (pc) (match_operand:SI 0 "address_operand" "p"))
2194 (use (label_ref (match_operand 1 "" "")))]
2197 [(set_attr "type" "uncond_branch")
2198 (set_attr "length" "2")])
2200 (define_expand "call"
2201 ;; operands[1] is stack_size_rtx
2202 ;; operands[2] is next_arg_register
2203 [(parallel [(call (match_operand:SI 0 "call_operand" "")
2204 (match_operand 1 "" ""))
2205 (clobber (reg:SI 14))])]
2209 (define_insn "*call_via_reg"
2210 [(call (mem:SI (match_operand:SI 0 "register_operand" "r"))
2211 (match_operand 1 "" ""))
2212 (clobber (reg:SI 14))]
2215 [(set_attr "type" "call")
2216 (set_attr "length" "2")])
2218 (define_insn "*call_via_label"
2219 [(call (mem:SI (match_operand:SI 0 "call_address_operand" ""))
2220 (match_operand 1 "" ""))
2221 (clobber (reg:SI 14))]
2225 int call26_p = call26_operand (operands[0], FUNCTION_MODE);
2229 /* We may not be able to reach with a `bl' insn so punt and leave it to
2231 We do this here, rather than doing a force_reg in the define_expand
2232 so these insns won't be separated, say by scheduling, thus simplifying
2234 return \"seth r14,%T0\;add3 r14,r14,%B0\;jl r14\";
2239 [(set_attr "type" "call")
2240 (set (attr "length")
2241 (if_then_else (eq (symbol_ref "call26_operand (operands[0], FUNCTION_MODE)")
2243 (const_int 12) ; 10 + 2 for nop filler
2244 ; The return address must be on a 4 byte boundary so
2245 ; there's no point in using a value of 2 here. A 2 byte
2246 ; insn may go in the left slot but we currently can't
2247 ; use such knowledge.
2250 (define_expand "call_value"
2251 ;; operand 2 is stack_size_rtx
2252 ;; operand 3 is next_arg_register
2253 [(parallel [(set (match_operand 0 "register_operand" "=r")
2254 (call (match_operand:SI 1 "call_operand" "")
2255 (match_operand 2 "" "")))
2256 (clobber (reg:SI 14))])]
2260 (define_insn "*call_value_via_reg"
2261 [(set (match_operand 0 "register_operand" "=r")
2262 (call (mem:SI (match_operand:SI 1 "register_operand" "r"))
2263 (match_operand 2 "" "")))
2264 (clobber (reg:SI 14))]
2267 [(set_attr "type" "call")
2268 (set_attr "length" "2")])
2270 (define_insn "*call_value_via_label"
2271 [(set (match_operand 0 "register_operand" "=r")
2272 (call (mem:SI (match_operand:SI 1 "call_address_operand" ""))
2273 (match_operand 2 "" "")))
2274 (clobber (reg:SI 14))]
2278 int call26_p = call26_operand (operands[1], FUNCTION_MODE);
2282 /* We may not be able to reach with a `bl' insn so punt and leave it to
2284 We do this here, rather than doing a force_reg in the define_expand
2285 so these insns won't be separated, say by scheduling, thus simplifying
2287 return \"seth r14,%T1\;add3 r14,r14,%B1\;jl r14\";
2292 [(set_attr "type" "call")
2293 (set (attr "length")
2294 (if_then_else (eq (symbol_ref "call26_operand (operands[1], FUNCTION_MODE)")
2296 (const_int 12) ; 10 + 2 for nop filler
2297 ; The return address must be on a 4 byte boundary so
2298 ; there's no point in using a value of 2 here. A 2 byte
2299 ; insn may go in the left slot but we currently can't
2300 ; use such knowledge.
2307 [(set_attr "type" "int2")
2308 (set_attr "length" "2")])
2310 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
2311 ;; all of memory. This blocks insns from being moved across this point.
2313 (define_insn "blockage"
2314 [(unspec_volatile [(const_int 0)] 0)]
2318 ;; Special pattern to flush the icache.
2320 (define_insn "flush_icache"
2321 [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)]
2323 "* return \"nop ; flush-icache\";"
2324 [(set_attr "type" "int2")
2325 (set_attr "length" "2")])
2327 ;; Speed up fabs and provide correct sign handling for -0
2329 (define_insn "absdf2"
2330 [(set (match_operand:DF 0 "register_operand" "=r")
2331 (abs:DF (match_operand:DF 1 "register_operand" "0")))]
2334 [(set_attr "type" "multi")
2335 (set_attr "length" "4")])
2338 [(set (match_operand:DF 0 "register_operand" "")
2339 (abs:DF (match_operand:DF 1 "register_operand" "")))]
2342 (ashift:SI (match_dup 2)
2345 (lshiftrt:SI (match_dup 2)
2347 "operands[2] = gen_highpart (SImode, operands[0]);")
2349 (define_insn "abssf2"
2350 [(set (match_operand:SF 0 "register_operand" "=r")
2351 (abs:SF (match_operand:SF 1 "register_operand" "0")))]
2354 [(set_attr "type" "multi")
2355 (set_attr "length" "4")])
2358 [(set (match_operand:SF 0 "register_operand" "")
2359 (abs:SF (match_operand:SF 1 "register_operand" "")))]
2362 (ashift:SI (match_dup 2)
2365 (lshiftrt:SI (match_dup 2)
2367 "operands[2] = gen_highpart (SImode, operands[0]);")
2369 ;; Conditional move instructions
2370 ;; Based on those done for the d10v
2372 (define_expand "movsicc"
2374 (set (match_operand:SI 0 "register_operand" "r")
2375 (if_then_else:SI (match_operand 1 "" "")
2376 (match_operand:SI 2 "conditional_move_operand" "O")
2377 (match_operand:SI 3 "conditional_move_operand" "O")
2384 if (! zero_and_one (operands [2], operands [3]))
2387 /* Generate the comparision that will set the carry flag. */
2388 operands[1] = gen_compare (GET_CODE (operands[1]), m32r_compare_op0,
2389 m32r_compare_op1, TRUE);
2391 /* See other movsicc pattern below for reason why. */
2392 emit_insn (gen_blockage ());
2395 ;; Generate the conditional instructions based on how the carry flag is examined.
2396 (define_insn "*movsicc_internal"
2397 [(set (match_operand:SI 0 "register_operand" "=r")
2398 (if_then_else:SI (match_operand 1 "carry_compare_operand" "")
2399 (match_operand:SI 2 "conditional_move_operand" "O")
2400 (match_operand:SI 3 "conditional_move_operand" "O")
2403 "zero_and_one (operands [2], operands[3])"
2404 "* return emit_cond_move (operands, insn);"
2405 [(set_attr "type" "multi")
2406 (set_attr "length" "8")
2411 ;; Split up troublesome insns for better scheduling.
2412 ;; FIXME: Peepholes go at the end.
2414 ;; ??? Setting the type attribute may not be useful, but for completeness
2418 [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
2420 (match_operand:SI 1 "register_operand" "r"))]
2421 "0 && dead_or_set_p (insn, operands[0])"
2423 [(set_attr "type" "store2")
2424 (set_attr "length" "2")])
2426 ;; This case is triggered by compiling this code:
2428 ;; extern void sub(int *);
2432 ;; while (i < j) sub(&k);
2439 ;; Without the peephole the following assembler is generated for the
2440 ;; divide and subtract expressions:
2447 ;; Simialr code is produced for the subtract expression. With this
2448 ;; peephole the redundant move is eliminated.
2450 ;; This optimisation onbly works if PRESERVE_DEATH_INFO_REGNO_P is
2451 ;; defined in m32r.h
2454 [(set (match_operand:SI 0 "register_operand" "r")
2455 (match_operand:SI 1 "register_operand" "r")
2457 (set (mem:SI (plus: SI (match_operand:SI 2 "register_operand" "r")
2458 (match_operand:SI 3 "immediate_operand" "J")))
2462 "0 && dead_or_set_p (insn, operands [0])"
2464 [(set_attr "type" "store4")
2465 (set_attr "length" "4")
2469 ;; Block moves, see m32r.c for more details.
2470 ;; Argument 0 is the destination
2471 ;; Argument 1 is the source
2472 ;; Argument 2 is the length
2473 ;; Argument 3 is the alignment
2475 (define_expand "movstrsi"
2476 [(parallel [(set (match_operand:BLK 0 "general_operand" "")
2477 (match_operand:BLK 1 "general_operand" ""))
2478 (use (match_operand:SI 2 "immediate_operand" ""))
2479 (use (match_operand:SI 3 "immediate_operand" ""))])]
2483 if (operands[0]) /* avoid unused code messages */
2485 m32r_expand_block_move (operands);
2490 ;; Insn generated by block moves
2492 (define_insn "movstrsi_internal"
2493 [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r")) ;; destination
2494 (mem:BLK (match_operand:SI 1 "register_operand" "+r"))) ;; source
2495 (use (match_operand:SI 2 "m32r_block_immediate_operand" "J"));; # bytes to move
2496 (set (match_dup 0) (plus:SI (match_dup 0) (minus:SI (match_dup 2) (const_int 4))))
2497 (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))
2498 (clobber (match_scratch:SI 3 "=&r")) ;; temp 1
2499 (clobber (match_scratch:SI 4 "=&r"))] ;; temp 2
2501 "* m32r_output_block_move (insn, operands); return \"\"; "
2502 [(set_attr "type" "store8")
2503 (set_attr "length" "72")]) ;; Maximum