xref: /openbsd/gnu/usr.bin/gcc/gcc/config/m32r/m32r.md (revision d415bd75)
1;; Machine description of the Mitsubishi M32R cpu for GNU C compiler
2;; Copyright (C) 1996, 1997, 1998, 1999, 2001, 2003 Free Software Foundation, Inc.
3
4;; This file is part of GCC.
5
6;; GCC 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)
9;; any later version.
10
11;; GCC 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.
15
16;; You should have received a copy of the GNU General Public License
17;; along with GCC; see the file COPYING.  If not, write to
18;; the Free Software Foundation, 59 Temple Place - Suite 330,
19;; Boston, MA 02111-1307, USA.
20
21;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
22
23;; unspec usage
24;; 0 - blockage
25;; 1 - flush_icache
26;; 2 - load_sda_base
27;; 3 - setting carry in addx/subx instructions.
28
29;; Insn type.  Used to default other attribute values.
30(define_attr "type"
31  "int2,int4,load2,load4,load8,store2,store4,store8,shift2,shift4,mul2,div4,uncond_branch,branch,call,multi,misc"
32  (const_string "misc"))
33
34;; Length in bytes.
35(define_attr "length" ""
36  (cond [(eq_attr "type" "int2,load2,store2,shift2,mul2")
37	 (const_int 2)
38
39	 (eq_attr "type" "int4,load4,store4,shift4,div4")
40	 (const_int 4)
41
42	 (eq_attr "type" "multi")
43	 (const_int 8)
44
45	 (eq_attr "type" "uncond_branch,branch,call")
46	 (const_int 4)]
47
48	 (const_int 4)))
49
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")])
55
56
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")))
62
63(define_attr "debug" "no,yes"
64  (const (symbol_ref "(TARGET_DEBUG != 0)")))
65
66(define_attr "opt_size" "no,yes"
67  (const (symbol_ref "(optimize_size != 0)")))
68
69(define_attr "m32r" "no,yes"
70  (const (symbol_ref "(TARGET_M32R != 0)")))
71
72(define_attr "m32rx" "no,yes"
73  (const (symbol_ref "(TARGET_M32RX != 0)")))
74
75(define_attr "m32rx_pipeline" "either,s,o,long,m32r"
76  (cond [(eq_attr "m32rx" "no")
77         (const_string "m32r")
78
79         (eq_attr "insn_size" "!short")
80         (const_string "long")]
81
82        (cond [(eq_attr "type" "int2")
83               (const_string "either")
84
85               (eq_attr "type" "load2,store2,shift2,uncond_branch,branch,call")
86               (const_string "o")
87
88               (eq_attr "type" "mul2")
89               (const_string "s")]
90
91              (const_string "long"))))
92
93;; ::::::::::::::::::::
94;; ::
95;; :: Function Units
96;; ::
97;; ::::::::::::::::::::
98
99;; On most RISC machines, there are instructions whose results are not
100;; available for a specific number of cycles.  Common cases are instructions
101;; that load data from memory.  On many machines, a pipeline stall will result
102;; if the data is referenced too soon after the load instruction.
103
104;; In addition, many newer microprocessors have multiple function units,
105;; usually one for integer and one for floating point, and often will incur
106;; pipeline stalls when a result that is needed is not yet ready.
107
108;; The descriptions in this section allow the specification of how much time
109;; must elapse between the execution of an instruction and the time when its
110;; result is used.  It also allows specification of when the execution of an
111;; instruction will delay execution of similar instructions due to function
112;; unit conflicts.
113
114;; For the purposes of the specifications in this section, a machine is divided
115;; into "function units", each of which execute a specific class of
116;; instructions in first-in-first-out order.  Function units that accept one
117;; instruction each cycle and allow a result to be used in the succeeding
118;; instruction (usually via forwarding) need not be specified.  Classic RISC
119;; microprocessors will normally have a single function unit, which we can call
120;; `memory'.  The newer "superscalar" processors will often have function units
121;; for floating point operations, usually at least a floating point adder and
122;; multiplier.
123
124;; Each usage of a function units by a class of insns is specified with a
125;; `define_function_unit' expression, which looks like this:
126
127;; (define_function_unit NAME MULTIPLICITY SIMULTANEITY TEST READY-DELAY
128;;   ISSUE-DELAY [CONFLICT-LIST])
129
130;; NAME is a string giving the name of the function unit.
131
132;; MULTIPLICITY is an integer specifying the number of identical units in the
133;; processor.  If more than one unit is specified, they will be scheduled
134;; independently.  Only truly independent units should be counted; a pipelined
135;; unit should be specified as a single unit.  (The only common example of a
136;; machine that has multiple function units for a single instruction class that
137;; are truly independent and not pipelined are the two multiply and two
138;; increment units of the CDC 6600.)
139
140;; SIMULTANEITY specifies the maximum number of insns that can be executing in
141;; each instance of the function unit simultaneously or zero if the unit is
142;; pipelined and has no limit.
143
144;; All `define_function_unit' definitions referring to function unit NAME must
145;; have the same name and values for MULTIPLICITY and SIMULTANEITY.
146
147;; TEST is an attribute test that selects the insns we are describing in this
148;; definition.  Note that an insn may use more than one function unit and a
149;; function unit may be specified in more than one `define_function_unit'.
150
151;; READY-DELAY is an integer that specifies the number of cycles after which
152;; the result of the instruction can be used without introducing any stalls.
153
154;; ISSUE-DELAY is an integer that specifies the number of cycles after the
155;; instruction matching the TEST expression begins using this unit until a
156;; subsequent instruction can begin.  A cost of N indicates an N-1 cycle delay.
157;; A subsequent instruction may also be delayed if an earlier instruction has a
158;; longer READY-DELAY value.  This blocking effect is computed using the
159;; SIMULTANEITY, READY-DELAY, ISSUE-DELAY, and CONFLICT-LIST terms.  For a
160;; normal non-pipelined function unit, SIMULTANEITY is one, the unit is taken
161;; to block for the READY-DELAY cycles of the executing insn, and smaller
162;; values of ISSUE-DELAY are ignored.
163
164;; CONFLICT-LIST is an optional list giving detailed conflict costs for this
165;; unit.  If specified, it is a list of condition test expressions to be
166;; applied to insns chosen to execute in NAME following the particular insn
167;; matching TEST that is already executing in NAME.  For each insn in the list,
168;; ISSUE-DELAY specifies the conflict cost; for insns not in the list, the cost
169;; is zero.  If not specified, CONFLICT-LIST defaults to all instructions that
170;; use the function unit.
171
172;; Typical uses of this vector are where a floating point function unit can
173;; pipeline either single- or double-precision operations, but not both, or
174;; where a memory unit can pipeline loads, but not stores, etc.
175
176;; As an example, consider a classic RISC machine where the result of a load
177;; instruction is not available for two cycles (a single "delay" instruction is
178;; required) and where only one load instruction can be executed
179;; simultaneously.  This would be specified as:
180
181;; (define_function_unit "memory" 1 1 (eq_attr "type" "load") 2 0)
182
183;; For the case of a floating point function unit that can pipeline
184;; either single or double precision, but not both, the following could be
185;; specified:
186;;
187;; (define_function_unit "fp" 1 0
188;;   (eq_attr "type" "sp_fp") 4 4
189;;   [(eq_attr "type" "dp_fp")])
190;;
191;; (define_function_unit "fp" 1 0
192;;   (eq_attr "type" "dp_fp") 4 4
193;;   [(eq_attr "type" "sp_fp")])
194
195;; Note: The scheduler attempts to avoid function unit conflicts and uses all
196;; the specifications in the `define_function_unit' expression.  It has
197;; recently come to our attention that these specifications may not allow
198;; modeling of some of the newer "superscalar" processors that have insns using
199;; multiple pipelined units.  These insns will cause a potential conflict for
200;; the second unit used during their execution and there is no way of
201;; representing that conflict.  We welcome any examples of how function unit
202;; conflicts work in such processors and suggestions for their representation.
203
204;; Function units of the M32R
205;; Units that take one cycle do not need to be specified.
206
207;; (define_function_unit {name} {multiplicity} {simulataneity} {test}
208;;                       {ready-delay} {issue-delay} [{conflict-list}])
209
210;; Hack to get GCC to better pack the instructions.
211;; We pretend there is a separate long function unit that conflicts with
212;; both the left and right 16 bit insn slots.
213
214(define_function_unit "short" 2 2
215  (and (eq_attr "m32r" "yes")
216       (and (eq_attr "insn_size" "short")
217	    (eq_attr "type" "!load2")))
218  1 0
219  [(eq_attr "insn_size" "long")])
220
221(define_function_unit "short" 2 2	;; load delay of 1 clock for mem execution + 1 clock for WB
222  (and (eq_attr "m32r" "yes")
223       (eq_attr "type" "load2"))
224  3 0
225  [(eq_attr "insn_size" "long")])
226
227(define_function_unit "long" 1 1
228  (and (eq_attr "m32r" "yes")
229       (and (eq_attr "insn_size" "long")
230	    (eq_attr "type" "!load4,load8")))
231  1 0
232  [(eq_attr "insn_size" "short")])
233
234(define_function_unit "long" 1 1	;; load delay of 1 clock for mem execution + 1 clock for WB
235  (and (eq_attr "m32r" "yes")
236       (and (eq_attr "insn_size" "long")
237	    (eq_attr "type" "load4,load8")))
238  3 0
239  [(eq_attr "insn_size" "short")])
240
241(define_function_unit "left" 1 1
242  (and (eq_attr "m32rx_pipeline" "o,either")
243       (eq_attr "type" "!load2"))
244  1 0
245  [(eq_attr "insn_size" "long")])
246
247(define_function_unit "left" 1 1	;; load delay of 1 clock for mem execution + 1 clock for WB
248  (and (eq_attr "m32rx_pipeline" "o,either")
249       (eq_attr "type" "load2"))
250  3 0
251  [(eq_attr "insn_size" "long")])
252
253(define_function_unit "right" 1 1
254  (eq_attr "m32rx_pipeline" "s,either")
255  1 0
256  [(eq_attr "insn_size" "long")])
257
258(define_function_unit "long" 1 1
259  (and (eq_attr "m32rx" "yes")
260       (and (eq_attr "insn_size" "long")
261	    (eq_attr "type" "!load4,load8")))
262  2 0
263  [(eq_attr "insn_size" "short")])
264
265(define_function_unit "long" 1 1	;; load delay of 1 clock for mem execution + 1 clock for WB
266  (and (eq_attr "m32rx" "yes")
267       (and (eq_attr "insn_size" "long")
268	    (eq_attr "type" "load4,load8")))
269  3 0
270  [(eq_attr "insn_size" "short")])
271
272;; Expand prologue as RTL
273(define_expand "prologue"
274  [(const_int 1)]
275  ""
276  "
277{
278  m32r_expand_prologue ();
279  DONE;
280}")
281
282
283;; Move instructions.
284;;
285;; For QI and HI moves, the register must contain the full properly
286;; sign-extended value.  nonzero_bits assumes this [otherwise
287;; SHORT_IMMEDIATES_SIGN_EXTEND must be used, but the comment for it
288;; says it's a kludge and the .md files should be fixed instead].
289
290(define_expand "movqi"
291  [(set (match_operand:QI 0 "general_operand" "")
292	(match_operand:QI 1 "general_operand" ""))]
293  ""
294  "
295{
296  /* Everything except mem = const or mem = mem can be done easily.
297     Objects in the small data area are handled too.  */
298
299  if (GET_CODE (operands[0]) == MEM)
300    operands[1] = force_reg (QImode, operands[1]);
301}")
302
303(define_insn "*movqi_insn"
304  [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,r,r,T,m")
305	(match_operand:QI 1 "move_src_operand" "r,I,JQR,T,m,r,r"))]
306  "register_operand (operands[0], QImode) || register_operand (operands[1], QImode)"
307  "@
308   mv %0,%1
309   ldi %0,%#%1
310   ldi %0,%#%1
311   ldub %0,%1
312   ldub %0,%1
313   stb %1,%0
314   stb %1,%0"
315  [(set_attr "type" "int2,int2,int4,load2,load4,store2,store4")
316   (set_attr "length" "2,2,4,2,4,2,4")])
317
318(define_expand "movhi"
319  [(set (match_operand:HI 0 "general_operand" "")
320	(match_operand:HI 1 "general_operand" ""))]
321  ""
322  "
323{
324  /* Everything except mem = const or mem = mem can be done easily.  */
325
326  if (GET_CODE (operands[0]) == MEM)
327    operands[1] = force_reg (HImode, operands[1]);
328}")
329
330(define_insn "*movhi_insn"
331  [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,r,r,r,T,m")
332	(match_operand:HI 1 "move_src_operand" "r,I,JQR,K,T,m,r,r"))]
333  "register_operand (operands[0], HImode) || register_operand (operands[1], HImode)"
334  "@
335   mv %0,%1
336   ldi %0,%#%1
337   ldi %0,%#%1
338   ld24 %0,%#%1
339   lduh %0,%1
340   lduh %0,%1
341   sth %1,%0
342   sth %1,%0"
343  [(set_attr "type" "int2,int2,int4,int4,load2,load4,store2,store4")
344   (set_attr "length" "2,2,4,4,2,4,2,4")])
345
346(define_expand "movsi_push"
347  [(set (mem:SI (pre_dec:SI (match_operand:SI 0 "register_operand" "")))
348	(match_operand:SI 1 "register_operand" ""))]
349  ""
350  "")
351
352(define_expand "movsi_pop"
353  [(set (match_operand:SI 0 "register_operand" "")
354	(mem:SI (post_inc:SI (match_operand:SI 1 "register_operand" ""))))]
355  ""
356  "")
357
358(define_expand "movsi"
359  [(set (match_operand:SI 0 "general_operand" "")
360	(match_operand:SI 1 "general_operand" ""))]
361  ""
362  "
363{
364  /* Everything except mem = const or mem = mem can be done easily.  */
365
366  if (GET_CODE (operands[0]) == MEM)
367    operands[1] = force_reg (SImode, operands[1]);
368
369  /* Small Data Area reference?  */
370  if (small_data_operand (operands[1], SImode))
371    {
372      emit_insn (gen_movsi_sda (operands[0], operands[1]));
373      DONE;
374    }
375
376  /* If medium or large code model, symbols have to be loaded with
377     seth/add3.  */
378  if (addr32_operand (operands[1], SImode))
379    {
380      emit_insn (gen_movsi_addr32 (operands[0], operands[1]));
381      DONE;
382    }
383}")
384
385;; ??? Do we need a const_double constraint here for large unsigned values?
386(define_insn "*movsi_insn"
387  [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,r,r,r,r,r,r,T,S,m")
388	(match_operand:SI 1 "move_src_operand" "r,I,J,MQ,L,n,T,U,m,r,r,r"))]
389  "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)"
390  "*
391{
392  if (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == SUBREG)
393    {
394      switch (GET_CODE (operands[1]))
395	{
396	  HOST_WIDE_INT value;
397
398	  default:
399	    break;
400
401	  case REG:
402	  case SUBREG:
403	    return \"mv %0,%1\";
404
405	  case MEM:
406	    if (GET_CODE (XEXP (operands[1], 0)) == POST_INC
407		&& XEXP (XEXP (operands[1], 0), 0) == stack_pointer_rtx)
408	      return \"pop %0\";
409
410	    return \"ld %0,%1\";
411
412	  case CONST_INT:
413	    value = INTVAL (operands[1]);
414	    if (INT16_P (value))
415	      return \"ldi %0,%#%1\\t; %X1\";
416
417	    if (UINT24_P (value))
418	      return \"ld24 %0,%#%1\\t; %X1\";
419
420	    if (UPPER16_P (value))
421	      return \"seth %0,%#%T1\\t; %X1\";
422
423	    return \"#\";
424
425	  case CONST:
426	  case SYMBOL_REF:
427	  case LABEL_REF:
428	    if (TARGET_ADDR24)
429	      return \"ld24 %0,%#%1\";
430
431	    return \"#\";
432	}
433    }
434
435  else if (GET_CODE (operands[0]) == MEM
436	   && (GET_CODE (operands[1]) == REG || GET_CODE (operands[1]) == SUBREG))
437    {
438      if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
439	  && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx)
440	return \"push %1\";
441
442      return \"st %1,%0\";
443    }
444
445  abort ();
446}"
447  [(set_attr "type" "int2,int2,int4,int4,int4,multi,load2,load2,load4,store2,store2,store4")
448   (set_attr "length" "2,2,4,4,4,8,2,2,4,2,2,4")])
449
450; Try to use a four byte / two byte pair for constants not loadable with
451; ldi, ld24, seth.
452
453(define_split
454 [(set (match_operand:SI 0 "register_operand" "")
455       (match_operand:SI 1 "two_insn_const_operand" ""))]
456  ""
457  [(set (match_dup 0) (match_dup 2))
458   (set (match_dup 0) (ior:SI (match_dup 0) (match_dup 3)))]
459  "
460{
461  unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
462  unsigned HOST_WIDE_INT tmp;
463  int shift;
464
465  /* In all cases we will emit two instructions.  However we try to
466     use 2 byte instructions wherever possible.  We can assume the
467     constant isn't loadable with any of ldi, ld24, or seth.  */
468
469  /* See if we can load a 24 bit unsigned value and invert it.  */
470  if (UINT24_P (~ val))
471    {
472      emit_insn (gen_movsi (operands[0], GEN_INT (~ val)));
473      emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
474      DONE;
475    }
476
477  /* See if we can load a 24 bit unsigned value and shift it into place.
478     0x01fffffe is just beyond ld24's range.  */
479  for (shift = 1, tmp = 0x01fffffe;
480       shift < 8;
481       ++shift, tmp <<= 1)
482    {
483      if ((val & ~tmp) == 0)
484	{
485	  emit_insn (gen_movsi (operands[0], GEN_INT (val >> shift)));
486	  emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (shift)));
487	  DONE;
488	}
489    }
490
491  /* Can't use any two byte insn, fall back to seth/or3.  Use ~0xffff instead
492     of 0xffff0000, since the later fails on a 64-bit host.  */
493  operands[2] = GEN_INT ((val) & ~0xffff);
494  operands[3] = GEN_INT ((val) & 0xffff);
495}")
496
497(define_split
498  [(set (match_operand:SI 0 "register_operand" "")
499	(match_operand:SI 1 "seth_add3_operand" "i"))]
500  "TARGET_ADDR32"
501  [(set (match_dup 0)
502	(high:SI (match_dup 1)))
503   (set (match_dup 0)
504	(lo_sum:SI (match_dup 0)
505		   (match_dup 1)))]
506  "")
507
508;; Small data area support.
509;; The address of _SDA_BASE_ is loaded into a register and all objects in
510;; the small data area are indexed off that.  This is done for each reference
511;; but cse will clean things up for us.  We let the compiler choose the
512;; register to use so we needn't allocate (and maybe even fix) a special
513;; register to use.  Since the load and store insns have a 16 bit offset the
514;; total size of the data area can be 64K.  However, if the data area lives
515;; above 16M (24 bits), _SDA_BASE_ will have to be loaded with seth/add3 which
516;; would then yield 3 instructions to reference an object [though there would
517;; be no net loss if two or more objects were referenced].  The 3 insns can be
518;; reduced back to 2 if the size of the small data area were reduced to 32K
519;; [then seth + ld/st would work for any object in the area].  Doing this
520;; would require special handling of _SDA_BASE_ (its value would be
521;; (.sdata + 32K) & 0xffff0000) and reloc computations would be different
522;; [I think].  What to do about this is deferred until later and for now we
523;; require .sdata to be in the first 16M.
524
525(define_expand "movsi_sda"
526  [(set (match_dup 2)
527	(unspec [(const_int 0)] 2))
528   (set (match_operand:SI 0 "register_operand" "")
529	(lo_sum:SI (match_dup 2)
530		   (match_operand:SI 1 "small_data_operand" "")))]
531  ""
532  "
533{
534  if (reload_in_progress || reload_completed)
535    operands[2] = operands[0];
536  else
537    operands[2] = gen_reg_rtx (SImode);
538}")
539
540(define_insn "*load_sda_base"
541  [(set (match_operand:SI 0 "register_operand" "=r")
542	(unspec [(const_int 0)] 2))]
543  ""
544  "ld24 %0,#_SDA_BASE_"
545  [(set_attr "type" "int4")
546   (set_attr "length" "4")])
547
548;; 32 bit address support.
549
550(define_expand "movsi_addr32"
551  [(set (match_dup 2)
552	; addr32_operand isn't used because it's too restrictive,
553	; seth_add3_operand is more general and thus safer.
554	(high:SI (match_operand:SI 1 "seth_add3_operand" "")))
555   (set (match_operand:SI 0 "register_operand" "")
556	(lo_sum:SI (match_dup 2) (match_dup 1)))]
557  ""
558  "
559{
560  if (reload_in_progress || reload_completed)
561    operands[2] = operands[0];
562  else
563    operands[2] = gen_reg_rtx (SImode);
564}")
565
566(define_insn "set_hi_si"
567  [(set (match_operand:SI 0 "register_operand" "=r")
568	(high:SI (match_operand 1 "symbolic_operand" "")))]
569  ""
570  "seth %0,%#shigh(%1)"
571  [(set_attr "type" "int4")
572   (set_attr "length" "4")])
573
574(define_insn "lo_sum_si"
575  [(set (match_operand:SI 0 "register_operand" "=r")
576	(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
577		   (match_operand:SI 2 "immediate_operand" "in")))]
578  ""
579  "add3 %0,%1,%#%B2"
580  [(set_attr "type" "int4")
581   (set_attr "length" "4")])
582
583(define_expand "movdi"
584  [(set (match_operand:DI 0 "general_operand" "")
585	(match_operand:DI 1 "general_operand" ""))]
586  ""
587  "
588{
589  /* Everything except mem = const or mem = mem can be done easily.  */
590
591  if (GET_CODE (operands[0]) == MEM)
592    operands[1] = force_reg (DImode, operands[1]);
593}")
594
595(define_insn "*movdi_insn"
596  [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,r,m")
597	(match_operand:DI 1 "move_double_src_operand" "r,nG,F,m,r"))]
598  "register_operand (operands[0], DImode) || register_operand (operands[1], DImode)"
599  "#"
600  [(set_attr "type" "multi,multi,multi,load8,store8")
601   (set_attr "length" "4,4,16,6,6")])
602
603(define_split
604  [(set (match_operand:DI 0 "move_dest_operand" "")
605	(match_operand:DI 1 "move_double_src_operand" ""))]
606  "reload_completed"
607  [(match_dup 2)]
608  "operands[2] = gen_split_move_double (operands);")
609
610;; Floating point move insns.
611
612(define_expand "movsf"
613  [(set (match_operand:SF 0 "general_operand" "")
614	(match_operand:SF 1 "general_operand" ""))]
615  ""
616  "
617{
618  /* Everything except mem = const or mem = mem can be done easily.  */
619
620  if (GET_CODE (operands[0]) == MEM)
621    operands[1] = force_reg (SFmode, operands[1]);
622}")
623
624(define_insn "*movsf_insn"
625  [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,r,r,T,S,m")
626	(match_operand:SF 1 "move_src_operand" "r,F,U,S,m,r,r,r"))]
627  "register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode)"
628  "@
629   mv %0,%1
630   #
631   ld %0,%1
632   ld %0,%1
633   ld %0,%1
634   st %1,%0
635   st %1,%0
636   st %1,%0"
637  ;; ??? Length of alternative 1 is either 2, 4 or 8.
638  [(set_attr "type" "int2,multi,load2,load2,load4,store2,store2,store4")
639   (set_attr "length" "2,8,2,2,4,2,2,4")])
640
641(define_split
642  [(set (match_operand:SF 0 "register_operand" "")
643	(match_operand:SF 1 "const_double_operand" ""))]
644  "reload_completed"
645  [(set (match_dup 2) (match_dup 3))]
646  "
647{
648  operands[2] = operand_subword (operands[0], 0, 0, SFmode);
649  operands[3] = operand_subword (operands[1], 0, 0, SFmode);
650}")
651
652(define_expand "movdf"
653  [(set (match_operand:DF 0 "general_operand" "")
654	(match_operand:DF 1 "general_operand" ""))]
655  ""
656  "
657{
658  /* Everything except mem = const or mem = mem can be done easily.  */
659
660  if (GET_CODE (operands[0]) == MEM)
661    operands[1] = force_reg (DFmode, operands[1]);
662}")
663
664(define_insn "*movdf_insn"
665  [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m")
666	(match_operand:DF 1 "move_double_src_operand" "r,F,m,r"))]
667  "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)"
668  "#"
669  [(set_attr "type" "multi,multi,load8,store8")
670   (set_attr "length" "4,16,6,6")])
671
672(define_split
673  [(set (match_operand:DF 0 "move_dest_operand" "")
674	(match_operand:DF 1 "move_double_src_operand" ""))]
675  "reload_completed"
676  [(match_dup 2)]
677  "operands[2] = gen_split_move_double (operands);")
678
679;; Zero extension instructions.
680
681(define_insn "zero_extendqihi2"
682  [(set (match_operand:HI 0 "register_operand" "=r,r,r")
683	(zero_extend:HI (match_operand:QI 1 "extend_operand" "r,T,m")))]
684  ""
685  "@
686   and3 %0,%1,%#255
687   ldub %0,%1
688   ldub %0,%1"
689  [(set_attr "type" "int4,load2,load4")
690   (set_attr "length" "4,2,4")])
691
692(define_insn "zero_extendqisi2"
693  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
694	(zero_extend:SI (match_operand:QI 1 "extend_operand" "r,T,m")))]
695  ""
696  "@
697   and3 %0,%1,%#255
698   ldub %0,%1
699   ldub %0,%1"
700  [(set_attr "type" "int4,load2,load4")
701   (set_attr "length" "4,2,4")])
702
703(define_insn "zero_extendhisi2"
704  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
705	(zero_extend:SI (match_operand:HI 1 "extend_operand" "r,T,m")))]
706  ""
707  "@
708   and3 %0,%1,%#65535
709   lduh %0,%1
710   lduh %0,%1"
711  [(set_attr "type" "int4,load2,load4")
712   (set_attr "length" "4,2,4")])
713
714;; Signed conversions from a smaller integer to a larger integer
715(define_insn "extendqihi2"
716  [(set (match_operand:HI 0 "register_operand" "=r,r,r")
717	(sign_extend:HI (match_operand:QI 1 "extend_operand" "0,T,m")))]
718  ""
719  "@
720    #
721    ldb %0,%1
722    ldb %0,%1"
723  [(set_attr "type" "multi,load2,load4")
724   (set_attr "length" "2,2,4")])
725
726(define_split
727  [(set (match_operand:HI 0 "register_operand" "")
728	(sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
729  "reload_completed"
730  [(match_dup 2)
731   (match_dup 3)]
732  "
733{
734  rtx op0   = gen_lowpart (SImode, operands[0]);
735  rtx shift = gen_rtx (CONST_INT, VOIDmode, 24);
736
737  operands[2] = gen_ashlsi3 (op0, op0, shift);
738  operands[3] = gen_ashrsi3 (op0, op0, shift);
739}")
740
741(define_insn "extendqisi2"
742  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
743	(sign_extend:SI (match_operand:QI 1 "extend_operand" "0,T,m")))]
744  ""
745  "@
746    #
747    ldb %0,%1
748    ldb %0,%1"
749  [(set_attr "type" "multi,load2,load4")
750   (set_attr "length" "4,2,4")])
751
752(define_split
753  [(set (match_operand:SI 0 "register_operand" "")
754	(sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
755  "reload_completed"
756  [(match_dup 2)
757   (match_dup 3)]
758  "
759{
760  rtx op0   = gen_lowpart (SImode, operands[0]);
761  rtx shift = gen_rtx (CONST_INT, VOIDmode, 24);
762
763  operands[2] = gen_ashlsi3 (op0, op0, shift);
764  operands[3] = gen_ashrsi3 (op0, op0, shift);
765}")
766
767(define_insn "extendhisi2"
768  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
769	(sign_extend:SI (match_operand:HI 1 "extend_operand" "0,T,m")))]
770  ""
771  "@
772    #
773    ldh %0,%1
774    ldh %0,%1"
775  [(set_attr "type" "multi,load2,load4")
776   (set_attr "length" "4,2,4")])
777
778(define_split
779  [(set (match_operand:SI 0 "register_operand" "")
780	(sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
781  "reload_completed"
782  [(match_dup 2)
783   (match_dup 3)]
784  "
785{
786  rtx op0   = gen_lowpart (SImode, operands[0]);
787  rtx shift = gen_rtx (CONST_INT, VOIDmode, 16);
788
789  operands[2] = gen_ashlsi3 (op0, op0, shift);
790  operands[3] = gen_ashrsi3 (op0, op0, shift);
791}")
792
793;; Arithmetic instructions.
794
795; ??? Adding an alternative to split add3 of small constants into two
796; insns yields better instruction packing but slower code.  Adds of small
797; values is done a lot.
798
799(define_insn "addsi3"
800  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
801	(plus:SI (match_operand:SI 1 "register_operand" "%0,0,r")
802		 (match_operand:SI 2 "nonmemory_operand" "r,I,J")))]
803  ""
804  "@
805   add %0,%2
806   addi %0,%#%2
807   add3 %0,%1,%#%2"
808  [(set_attr "type" "int2,int2,int4")
809   (set_attr "length" "2,2,4")])
810
811;(define_split
812;  [(set (match_operand:SI 0 "register_operand" "")
813;	(plus:SI (match_operand:SI 1 "register_operand" "")
814;		 (match_operand:SI 2 "int8_operand" "")))]
815;  "reload_completed
816;   && REGNO (operands[0]) != REGNO (operands[1])
817;   && INT8_P (INTVAL (operands[2]))
818;   && INTVAL (operands[2]) != 0"
819;  [(set (match_dup 0) (match_dup 1))
820;   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
821;  "")
822
823(define_insn "adddi3"
824  [(set (match_operand:DI 0 "register_operand" "=r")
825	(plus:DI (match_operand:DI 1 "register_operand" "%0")
826		 (match_operand:DI 2 "register_operand" "r")))
827   (clobber (reg:SI 17))]
828  ""
829  "#"
830  [(set_attr "type" "multi")
831   (set_attr "length" "6")])
832
833;; ??? The cmp clears the condition bit.  Can we speed up somehow?
834(define_split
835  [(set (match_operand:DI 0 "register_operand" "")
836	(plus:DI (match_operand:DI 1 "register_operand" "")
837		 (match_operand:DI 2 "register_operand" "")))
838   (clobber (match_operand 3 "" ""))]
839  "reload_completed"
840  [(parallel [(set (match_dup 3)
841		   (const_int 0))
842	      (use (match_dup 4))])
843   (parallel [(set (match_dup 4)
844		   (plus:SI (match_dup 4)
845			    (plus:SI (match_dup 5)
846				     (match_dup 3))))
847	      (set (match_dup 3)
848		   (unspec [(const_int 0)] 3))])
849   (parallel [(set (match_dup 6)
850		   (plus:SI (match_dup 6)
851			    (plus:SI (match_dup 7)
852				     (match_dup 3))))
853	      (set (match_dup 3)
854		   (unspec [(const_int 0)] 3))])]
855  "
856{
857  operands[4] = operand_subword (operands[0], (WORDS_BIG_ENDIAN != 0), 0, DImode);
858  operands[5] = operand_subword (operands[2], (WORDS_BIG_ENDIAN != 0), 0, DImode);
859  operands[6] = operand_subword (operands[0], (WORDS_BIG_ENDIAN == 0), 0, DImode);
860  operands[7] = operand_subword (operands[2], (WORDS_BIG_ENDIAN == 0), 0, DImode);
861}")
862
863(define_insn "*clear_c"
864  [(set (reg:SI 17)
865	(const_int 0))
866   (use (match_operand:SI 0 "register_operand" "r"))]
867  ""
868  "cmp %0,%0"
869  [(set_attr "type" "int2")
870   (set_attr "length" "2")])
871
872(define_insn "*add_carry"
873  [(set (match_operand:SI 0 "register_operand" "=r")
874	(plus:SI (match_operand:SI 1 "register_operand" "%0")
875		 (plus:SI (match_operand:SI 2 "register_operand" "r")
876			  (reg:SI 17))))
877   (set (reg:SI 17)
878	(unspec [(const_int 0)] 3))]
879  ""
880  "addx %0,%2"
881  [(set_attr "type" "int2")
882   (set_attr "length" "2")])
883
884(define_insn "subsi3"
885  [(set (match_operand:SI 0 "register_operand" "=r")
886	(minus:SI (match_operand:SI 1 "register_operand" "0")
887		  (match_operand:SI 2 "register_operand" "r")))]
888  ""
889  "sub %0,%2"
890  [(set_attr "type" "int2")
891   (set_attr "length" "2")])
892
893(define_insn "subdi3"
894  [(set (match_operand:DI 0 "register_operand" "=r")
895	(minus:DI (match_operand:DI 1 "register_operand" "0")
896		  (match_operand:DI 2 "register_operand" "r")))
897   (clobber (reg:SI 17))]
898  ""
899  "#"
900  [(set_attr "type" "multi")
901   (set_attr "length" "6")])
902
903;; ??? The cmp clears the condition bit.  Can we speed up somehow?
904(define_split
905  [(set (match_operand:DI 0 "register_operand" "")
906	(minus:DI (match_operand:DI 1 "register_operand" "")
907		  (match_operand:DI 2 "register_operand" "")))
908   (clobber (match_operand 3 "" ""))]
909  "reload_completed"
910  [(parallel [(set (match_dup 3)
911		   (const_int 0))
912	      (use (match_dup 4))])
913   (parallel [(set (match_dup 4)
914		   (minus:SI (match_dup 4)
915			     (minus:SI (match_dup 5)
916				       (match_dup 3))))
917	      (set (match_dup 3)
918		   (unspec [(const_int 0)] 3))])
919   (parallel [(set (match_dup 6)
920		   (minus:SI (match_dup 6)
921			     (minus:SI (match_dup 7)
922				       (match_dup 3))))
923	      (set (match_dup 3)
924		   (unspec [(const_int 0)] 3))])]
925  "
926{
927  operands[4] = operand_subword (operands[0], (WORDS_BIG_ENDIAN != 0), 0, DImode);
928  operands[5] = operand_subword (operands[2], (WORDS_BIG_ENDIAN != 0), 0, DImode);
929  operands[6] = operand_subword (operands[0], (WORDS_BIG_ENDIAN == 0), 0, DImode);
930  operands[7] = operand_subword (operands[2], (WORDS_BIG_ENDIAN == 0), 0, DImode);
931}")
932
933(define_insn "*sub_carry"
934  [(set (match_operand:SI 0 "register_operand" "=r")
935	(minus:SI (match_operand:SI 1 "register_operand" "%0")
936		  (minus:SI (match_operand:SI 2 "register_operand" "r")
937			    (reg:SI 17))))
938   (set (reg:SI 17)
939	(unspec [(const_int 0)] 3))]
940  ""
941  "subx %0,%2"
942  [(set_attr "type" "int2")
943   (set_attr "length" "2")])
944
945; Multiply/Divide instructions.
946
947(define_insn "mulhisi3"
948  [(set (match_operand:SI 0 "register_operand" "=r")
949	(mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
950		 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
951  ""
952  "mullo %1,%2\;mvfacmi %0"
953  [(set_attr "type" "multi")
954   (set_attr "length" "4")])
955
956(define_insn "mulsi3"
957  [(set (match_operand:SI 0 "register_operand" "=r")
958	(mult:SI (match_operand:SI 1 "register_operand" "%0")
959		 (match_operand:SI 2 "register_operand" "r")))]
960  ""
961  "mul %0,%2"
962  [(set_attr "type" "mul2")
963   (set_attr "length" "2")])
964
965(define_insn "divsi3"
966  [(set (match_operand:SI 0 "register_operand" "=r")
967	(div:SI (match_operand:SI 1 "register_operand" "0")
968		(match_operand:SI 2 "register_operand" "r")))]
969  ""
970  "div %0,%2"
971  [(set_attr "type" "div4")
972   (set_attr "length" "4")])
973
974(define_insn "udivsi3"
975  [(set (match_operand:SI 0 "register_operand" "=r")
976	(udiv:SI (match_operand:SI 1 "register_operand" "0")
977		 (match_operand:SI 2 "register_operand" "r")))]
978  ""
979  "divu %0,%2"
980  [(set_attr "type" "div4")
981   (set_attr "length" "4")])
982
983(define_insn "modsi3"
984  [(set (match_operand:SI 0 "register_operand" "=r")
985	(mod:SI (match_operand:SI 1 "register_operand" "0")
986		(match_operand:SI 2 "register_operand" "r")))]
987  ""
988  "rem %0,%2"
989  [(set_attr "type" "div4")
990   (set_attr "length" "4")])
991
992(define_insn "umodsi3"
993  [(set (match_operand:SI 0 "register_operand" "=r")
994	(umod:SI (match_operand:SI 1 "register_operand" "0")
995		 (match_operand:SI 2 "register_operand" "r")))]
996  ""
997  "remu %0,%2"
998  [(set_attr "type" "div4")
999   (set_attr "length" "4")])
1000
1001;; Boolean instructions.
1002;;
1003;; We don't define the DImode versions as expand_binop does a good enough job.
1004;; And if it doesn't it should be fixed.
1005
1006(define_insn "andsi3"
1007  [(set (match_operand:SI 0 "register_operand" "=r,r")
1008	(and:SI (match_operand:SI 1 "register_operand" "%0,r")
1009		(match_operand:SI 2 "reg_or_uint16_operand" "r,K")))]
1010  ""
1011  "*
1012{
1013  /* If we are worried about space, see if we can break this up into two
1014     short instructions, which might eliminate a NOP being inserted.  */
1015  if (optimize_size
1016      && m32r_not_same_reg (operands[0], operands[1])
1017      && GET_CODE (operands[2]) == CONST_INT
1018      && INT8_P (INTVAL (operands[2])))
1019    return \"#\";
1020
1021  else if (GET_CODE (operands[2]) == CONST_INT)
1022    return \"and3 %0,%1,%#%X2\";
1023
1024  return \"and %0,%2\";
1025}"
1026  [(set_attr "type" "int2,int4")
1027   (set_attr "length" "2,4")])
1028
1029(define_split
1030  [(set (match_operand:SI 0 "register_operand" "")
1031	(and:SI (match_operand:SI 1 "register_operand" "")
1032		(match_operand:SI 2 "int8_operand" "")))]
1033  "optimize_size && m32r_not_same_reg (operands[0], operands[1])"
1034  [(set (match_dup 0) (match_dup 2))
1035   (set (match_dup 0) (and:SI (match_dup 0) (match_dup 1)))]
1036  "")
1037
1038(define_insn "iorsi3"
1039  [(set (match_operand:SI 0 "register_operand" "=r,r")
1040	(ior:SI (match_operand:SI 1 "register_operand" "%0,r")
1041		(match_operand:SI 2 "reg_or_uint16_operand" "r,K")))]
1042  ""
1043  "*
1044{
1045  /* If we are worried about space, see if we can break this up into two
1046     short instructions, which might eliminate a NOP being inserted.  */
1047  if (optimize_size
1048      && m32r_not_same_reg (operands[0], operands[1])
1049      && GET_CODE (operands[2]) == CONST_INT
1050      && INT8_P (INTVAL (operands[2])))
1051    return \"#\";
1052
1053  else if (GET_CODE (operands[2]) == CONST_INT)
1054    return \"or3 %0,%1,%#%X2\";
1055
1056  return \"or %0,%2\";
1057}"
1058  [(set_attr "type" "int2,int4")
1059   (set_attr "length" "2,4")])
1060
1061(define_split
1062  [(set (match_operand:SI 0 "register_operand" "")
1063	(ior:SI (match_operand:SI 1 "register_operand" "")
1064		(match_operand:SI 2 "int8_operand" "")))]
1065  "optimize_size && m32r_not_same_reg (operands[0], operands[1])"
1066  [(set (match_dup 0) (match_dup 2))
1067   (set (match_dup 0) (ior:SI (match_dup 0) (match_dup 1)))]
1068  "")
1069
1070(define_insn "xorsi3"
1071  [(set (match_operand:SI 0 "register_operand" "=r,r")
1072	(xor:SI (match_operand:SI 1 "register_operand" "%0,r")
1073		(match_operand:SI 2 "reg_or_uint16_operand" "r,K")))]
1074  ""
1075  "*
1076{
1077  /* If we are worried about space, see if we can break this up into two
1078     short instructions, which might eliminate a NOP being inserted.  */
1079  if (optimize_size
1080      && m32r_not_same_reg (operands[0], operands[1])
1081      && GET_CODE (operands[2]) == CONST_INT
1082      && INT8_P (INTVAL (operands[2])))
1083    return \"#\";
1084
1085  else if (GET_CODE (operands[2]) == CONST_INT)
1086    return \"xor3 %0,%1,%#%X2\";
1087
1088  return \"xor %0,%2\";
1089}"
1090  [(set_attr "type" "int2,int4")
1091   (set_attr "length" "2,4")])
1092
1093(define_split
1094  [(set (match_operand:SI 0 "register_operand" "")
1095	(xor:SI (match_operand:SI 1 "register_operand" "")
1096		(match_operand:SI 2 "int8_operand" "")))]
1097  "optimize_size && m32r_not_same_reg (operands[0], operands[1])"
1098  [(set (match_dup 0) (match_dup 2))
1099   (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 1)))]
1100  "")
1101
1102(define_insn "negsi2"
1103  [(set (match_operand:SI 0 "register_operand" "=r")
1104	(neg:SI (match_operand:SI 1 "register_operand" "r")))]
1105  ""
1106  "neg %0,%1"
1107  [(set_attr "type" "int2")
1108   (set_attr "length" "2")])
1109
1110(define_insn "one_cmplsi2"
1111  [(set (match_operand:SI 0 "register_operand" "=r")
1112	(not:SI (match_operand:SI 1 "register_operand" "r")))]
1113  ""
1114  "not %0,%1"
1115  [(set_attr "type" "int2")
1116   (set_attr "length" "2")])
1117
1118;; Shift instructions.
1119
1120(define_insn "ashlsi3"
1121  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1122	(ashift:SI (match_operand:SI 1 "register_operand" "0,0,r")
1123		   (match_operand:SI 2 "reg_or_uint16_operand" "r,O,K")))]
1124  ""
1125  "@
1126   sll %0,%2
1127   slli %0,%#%2
1128   sll3 %0,%1,%#%2"
1129  [(set_attr "type" "shift2,shift2,shift4")
1130   (set_attr "length" "2,2,4")])
1131
1132(define_insn "ashrsi3"
1133  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1134	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1135		     (match_operand:SI 2 "reg_or_uint16_operand" "r,O,K")))]
1136  ""
1137  "@
1138   sra %0,%2
1139   srai %0,%#%2
1140   sra3 %0,%1,%#%2"
1141  [(set_attr "type" "shift2,shift2,shift4")
1142   (set_attr "length" "2,2,4")])
1143
1144(define_insn "lshrsi3"
1145  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1146	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1147		     (match_operand:SI 2 "reg_or_uint16_operand" "r,O,K")))]
1148  ""
1149  "@
1150   srl %0,%2
1151   srli %0,%#%2
1152   srl3 %0,%1,%#%2"
1153  [(set_attr "type" "shift2,shift2,shift4")
1154   (set_attr "length" "2,2,4")])
1155
1156;; Compare instructions.
1157;; This controls RTL generation and register allocation.
1158
1159;; We generate RTL for comparisons and branches by having the cmpxx
1160;; patterns store away the operands.  Then the bcc patterns
1161;; emit RTL for both the compare and the branch.
1162;;
1163;; On the m32r it is more efficient to use the bxxz instructions and
1164;; thus merge the compare and branch into one instruction, so they are
1165;; preferred.
1166
1167(define_expand "cmpsi"
1168  [(set (reg:SI 17)
1169	(compare:CC (match_operand:SI 0 "register_operand" "")
1170		    (match_operand:SI 1 "reg_or_cmp_int16_operand" "")))]
1171  ""
1172  "
1173{
1174  m32r_compare_op0 = operands[0];
1175  m32r_compare_op1 = operands[1];
1176  DONE;
1177}")
1178
1179(define_insn "cmp_eqsi_zero_insn"
1180  [(set (reg:SI 17)
1181        (eq:SI (match_operand:SI 0 "register_operand" "r,r")
1182               (match_operand:SI 1 "reg_or_zero_operand" "r,P")))]
1183  "TARGET_M32RX"
1184  "@
1185   cmpeq %0, %1
1186   cmpz  %0"
1187  [(set_attr "type" "int4")
1188   (set_attr "length" "4")])
1189
1190;; The cmp_xxx_insn patterns set the condition bit to the result of the
1191;; comparison.  There isn't a "compare equal" instruction so cmp_eqsi_insn
1192;; is quite inefficient.  However, it is rarely used.
1193
1194(define_insn "cmp_eqsi_insn"
1195  [(set (reg:SI 17)
1196        (eq:SI (match_operand:SI 0 "register_operand" "r,r")
1197               (match_operand:SI 1 "reg_or_cmp_int16_operand" "r,P")))
1198   (clobber (match_scratch:SI 2 "=&r,&r"))]
1199  ""
1200  "*
1201{
1202  if (which_alternative == 0)
1203    {
1204         return \"mv %2,%0\;sub %2,%1\;cmpui %2,#1\";
1205    }
1206  else
1207    {
1208        if (INTVAL (operands [1]) == 0)
1209          return \"cmpui %0, #1\";
1210        else if (REGNO (operands [2]) == REGNO (operands [0]))
1211          return \"addi %0,%#%N1\;cmpui %2,#1\";
1212        else
1213          return \"add3 %2,%0,%#%N1\;cmpui %2,#1\";
1214    }
1215}"
1216  [(set_attr "type" "multi,multi")
1217   (set_attr "length" "8,8")])
1218
1219(define_insn "cmp_ltsi_insn"
1220  [(set (reg:SI 17)
1221        (lt:SI (match_operand:SI 0 "register_operand" "r,r")
1222               (match_operand:SI 1 "reg_or_int16_operand" "r,J")))]
1223  ""
1224  "@
1225   cmp %0,%1
1226   cmpi %0,%#%1"
1227  [(set_attr "type" "int2,int4")
1228   (set_attr "length" "2,4")])
1229
1230(define_insn "cmp_ltusi_insn"
1231  [(set (reg:SI 17)
1232        (ltu:SI (match_operand:SI 0 "register_operand" "r,r")
1233                (match_operand:SI 1 "reg_or_int16_operand" "r,J")))]
1234  ""
1235  "@
1236   cmpu %0,%1
1237   cmpui %0,%#%1"
1238  [(set_attr "type" "int2,int4")
1239   (set_attr "length" "2,4")])
1240
1241(define_insn "movstrsi_small_internal"
1242  [(set (mem:BLK (match_operand:SI 0 "register_operand" "r"))	;; destination
1243	(mem:BLK (match_operand:SI 1 "register_operand" "r")))	;; source
1244   (use (match_operand:SI 2 "m32r_block_small_immediate_operand" "J"));; # bytes to move
1245   (clobber (match_scratch:SI 3 "=&r"))				;; temp 1
1246   (clobber (match_scratch:SI 4 "=&r"))]			;; temp 2
1247  ""
1248  "* m32r_output_block_move (insn, operands); return \"\"; "
1249  [(set_attr "type"	"store8")
1250   (set_attr "length"	"20")]) ;; Maximum
1251
1252;; reg == small constant comparisons are best handled by putting the result
1253;; of the comparison in a tmp reg and then using beqz/bnez.
1254;; ??? The result register doesn't contain 0/STORE_FLAG_VALUE,
1255;; it contains 0/nonzero.
1256
1257(define_insn "cmp_ne_small_const_insn"
1258  [(set (match_operand:SI 0 "register_operand" "=r,r")
1259	(ne:SI (match_operand:SI 1 "register_operand" "0,r")
1260	       (match_operand:SI 2 "cmp_int16_operand" "N,P")))]
1261  ""
1262  "@
1263   addi %0,%#%N2
1264   add3 %0,%1,%#%N2"
1265  [(set_attr "type" "int2,int4")
1266   (set_attr "length" "2,4")])
1267
1268;; These control RTL generation for conditional jump insns.
1269
1270(define_expand "beq"
1271  [(set (pc)
1272	(if_then_else (match_dup 1)
1273		      (label_ref (match_operand 0 "" ""))
1274		      (pc)))]
1275  ""
1276  "
1277{
1278  operands[1] = gen_compare (EQ, m32r_compare_op0, m32r_compare_op1, FALSE);
1279}")
1280
1281(define_expand "bne"
1282  [(set (pc)
1283	(if_then_else (match_dup 1)
1284		      (label_ref (match_operand 0 "" ""))
1285		      (pc)))]
1286  ""
1287  "
1288{
1289  operands[1] = gen_compare (NE, m32r_compare_op0, m32r_compare_op1, FALSE);
1290}")
1291
1292(define_expand "bgt"
1293  [(set (pc)
1294	(if_then_else (match_dup 1)
1295		      (label_ref (match_operand 0 "" ""))
1296		      (pc)))]
1297  ""
1298  "
1299{
1300  operands[1] = gen_compare (GT, m32r_compare_op0, m32r_compare_op1, FALSE);
1301}")
1302
1303(define_expand "ble"
1304  [(set (pc)
1305	(if_then_else (match_dup 1)
1306		      (label_ref (match_operand 0 "" ""))
1307		      (pc)))]
1308  ""
1309  "
1310{
1311  operands[1] = gen_compare (LE, m32r_compare_op0, m32r_compare_op1, FALSE);
1312}")
1313
1314(define_expand "bge"
1315  [(set (pc)
1316	(if_then_else (match_dup 1)
1317		      (label_ref (match_operand 0 "" ""))
1318		      (pc)))]
1319  ""
1320  "
1321{
1322  operands[1] = gen_compare (GE, m32r_compare_op0, m32r_compare_op1, FALSE);
1323}")
1324
1325(define_expand "blt"
1326  [(set (pc)
1327	(if_then_else (match_dup 1)
1328		      (label_ref (match_operand 0 "" ""))
1329		      (pc)))]
1330  ""
1331  "
1332{
1333  operands[1] = gen_compare (LT, m32r_compare_op0, m32r_compare_op1, FALSE);
1334}")
1335
1336(define_expand "bgtu"
1337  [(set (pc)
1338	(if_then_else (match_dup 1)
1339		      (label_ref (match_operand 0 "" ""))
1340		      (pc)))]
1341  ""
1342  "
1343{
1344  operands[1] = gen_compare (GTU, m32r_compare_op0, m32r_compare_op1, FALSE);
1345}")
1346
1347(define_expand "bleu"
1348  [(set (pc)
1349	(if_then_else (match_dup 1)
1350		      (label_ref (match_operand 0 "" ""))
1351		      (pc)))]
1352  ""
1353  "
1354{
1355  operands[1] = gen_compare (LEU, m32r_compare_op0, m32r_compare_op1, FALSE);
1356}")
1357
1358(define_expand "bgeu"
1359  [(set (pc)
1360	(if_then_else (match_dup 1)
1361		      (label_ref (match_operand 0 "" ""))
1362		      (pc)))]
1363  ""
1364  "
1365{
1366  operands[1] = gen_compare (GEU, m32r_compare_op0, m32r_compare_op1, FALSE);
1367}")
1368
1369(define_expand "bltu"
1370  [(set (pc)
1371	(if_then_else (match_dup 1)
1372		      (label_ref (match_operand 0 "" ""))
1373		      (pc)))]
1374  ""
1375  "
1376{
1377  operands[1] = gen_compare (LTU, m32r_compare_op0, m32r_compare_op1, FALSE);
1378}")
1379
1380;; Now match both normal and inverted jump.
1381
1382(define_insn "*branch_insn"
1383  [(set (pc)
1384	(if_then_else (match_operator 1 "eqne_comparison_operator"
1385				      [(reg 17) (const_int 0)])
1386		      (label_ref (match_operand 0 "" ""))
1387		      (pc)))]
1388  ""
1389  "*
1390{
1391  static char instruction[40];
1392  sprintf (instruction, \"%s%s %%l0\",
1393	   (GET_CODE (operands[1]) == NE) ? \"bc\" : \"bnc\",
1394	   (get_attr_length (insn) == 2) ? \".s\" : \"\");
1395  return instruction;
1396}"
1397  [(set_attr "type" "branch")
1398   ; We use 400/800 instead of 512,1024 to account for inaccurate insn
1399   ; lengths and insn alignments that are complex to track.
1400   ; It's not important that we be hyper-precise here.  It may be more
1401   ; important blah blah blah when the chip supports parallel execution
1402   ; blah blah blah but until then blah blah blah this is simple and
1403   ; suffices.
1404   (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1405						 (const_int 400))
1406					   (const_int 800))
1407				      (const_int 2)
1408				      (const_int 4)))])
1409
1410(define_insn "*rev_branch_insn"
1411  [(set (pc)
1412	(if_then_else (match_operator 1 "eqne_comparison_operator"
1413				      [(reg 17) (const_int 0)])
1414		      (pc)
1415		      (label_ref (match_operand 0 "" ""))))]
1416  ;"REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
1417  ""
1418  "*
1419{
1420  static char instruction[40];
1421  sprintf (instruction, \"%s%s %%l0\",
1422	   (GET_CODE (operands[1]) == EQ) ? \"bc\" : \"bnc\",
1423	   (get_attr_length (insn) == 2) ? \".s\" : \"\");
1424  return instruction;
1425}"
1426  [(set_attr "type" "branch")
1427   ; We use 400/800 instead of 512,1024 to account for inaccurate insn
1428   ; lengths and insn alignments that are complex to track.
1429   ; It's not important that we be hyper-precise here.  It may be more
1430   ; important blah blah blah when the chip supports parallel execution
1431   ; blah blah blah but until then blah blah blah this is simple and
1432   ; suffices.
1433   (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1434						 (const_int 400))
1435					   (const_int 800))
1436				      (const_int 2)
1437				      (const_int 4)))])
1438
1439; reg/reg compare and branch insns
1440
1441(define_insn "*reg_branch_insn"
1442  [(set (pc)
1443	(if_then_else (match_operator 1 "eqne_comparison_operator"
1444				      [(match_operand:SI 2 "register_operand" "r")
1445				       (match_operand:SI 3 "register_operand" "r")])
1446		      (label_ref (match_operand 0 "" ""))
1447		      (pc)))]
1448  ""
1449  "*
1450{
1451  /* Is branch target reachable with beq/bne?  */
1452  if (get_attr_length (insn) == 4)
1453    {
1454      if (GET_CODE (operands[1]) == EQ)
1455	return \"beq %2,%3,%l0\";
1456      else
1457	return \"bne %2,%3,%l0\";
1458    }
1459  else
1460    {
1461      if (GET_CODE (operands[1]) == EQ)
1462	return \"bne %2,%3,1f\;bra %l0\;1:\";
1463      else
1464	return \"beq %2,%3,1f\;bra %l0\;1:\";
1465    }
1466}"
1467  [(set_attr "type" "branch")
1468  ; We use 25000/50000 instead of 32768/65536 to account for slot filling
1469  ; which is complex to track and inaccurate length specs.
1470   (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1471						 (const_int 25000))
1472					   (const_int 50000))
1473				      (const_int 4)
1474				      (const_int 8)))])
1475
1476(define_insn "*rev_reg_branch_insn"
1477  [(set (pc)
1478	(if_then_else (match_operator 1 "eqne_comparison_operator"
1479				      [(match_operand:SI 2 "register_operand" "r")
1480				       (match_operand:SI 3 "register_operand" "r")])
1481		      (pc)
1482		      (label_ref (match_operand 0 "" ""))))]
1483  ""
1484  "*
1485{
1486  /* Is branch target reachable with beq/bne?  */
1487  if (get_attr_length (insn) == 4)
1488    {
1489      if (GET_CODE (operands[1]) == NE)
1490	return \"beq %2,%3,%l0\";
1491      else
1492	return \"bne %2,%3,%l0\";
1493    }
1494  else
1495    {
1496      if (GET_CODE (operands[1]) == NE)
1497	return \"bne %2,%3,1f\;bra %l0\;1:\";
1498      else
1499	return \"beq %2,%3,1f\;bra %l0\;1:\";
1500    }
1501}"
1502  [(set_attr "type" "branch")
1503  ; We use 25000/50000 instead of 32768/65536 to account for slot filling
1504  ; which is complex to track and inaccurate length specs.
1505   (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1506						 (const_int 25000))
1507					   (const_int 50000))
1508				      (const_int 4)
1509				      (const_int 8)))])
1510
1511; reg/zero compare and branch insns
1512
1513(define_insn "*zero_branch_insn"
1514  [(set (pc)
1515	(if_then_else (match_operator 1 "signed_comparison_operator"
1516				      [(match_operand:SI 2 "register_operand" "r")
1517				       (const_int 0)])
1518		      (label_ref (match_operand 0 "" ""))
1519		      (pc)))]
1520  ""
1521  "*
1522{
1523  const char *br,*invbr;
1524  char asmtext[40];
1525
1526  switch (GET_CODE (operands[1]))
1527    {
1528      case EQ : br = \"eq\"; invbr = \"ne\"; break;
1529      case NE : br = \"ne\"; invbr = \"eq\"; break;
1530      case LE : br = \"le\"; invbr = \"gt\"; break;
1531      case GT : br = \"gt\"; invbr = \"le\"; break;
1532      case LT : br = \"lt\"; invbr = \"ge\"; break;
1533      case GE : br = \"ge\"; invbr = \"lt\"; break;
1534
1535      default: abort();
1536    }
1537
1538  /* Is branch target reachable with bxxz?  */
1539  if (get_attr_length (insn) == 4)
1540    {
1541      sprintf (asmtext, \"b%sz %%2,%%l0\", br);
1542      output_asm_insn (asmtext, operands);
1543    }
1544  else
1545    {
1546      sprintf (asmtext, \"b%sz %%2,1f\;bra %%l0\;1:\", invbr);
1547      output_asm_insn (asmtext, operands);
1548    }
1549  return \"\";
1550}"
1551  [(set_attr "type" "branch")
1552  ; We use 25000/50000 instead of 32768/65536 to account for slot filling
1553  ; which is complex to track and inaccurate length specs.
1554   (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1555						 (const_int 25000))
1556					   (const_int 50000))
1557				      (const_int 4)
1558				      (const_int 8)))])
1559
1560(define_insn "*rev_zero_branch_insn"
1561  [(set (pc)
1562	(if_then_else (match_operator 1 "eqne_comparison_operator"
1563				      [(match_operand:SI 2 "register_operand" "r")
1564				       (const_int 0)])
1565		      (pc)
1566		      (label_ref (match_operand 0 "" ""))))]
1567  ""
1568  "*
1569{
1570  const char *br,*invbr;
1571  char asmtext[40];
1572
1573  switch (GET_CODE (operands[1]))
1574    {
1575      case EQ : br = \"eq\"; invbr = \"ne\"; break;
1576      case NE : br = \"ne\"; invbr = \"eq\"; break;
1577      case LE : br = \"le\"; invbr = \"gt\"; break;
1578      case GT : br = \"gt\"; invbr = \"le\"; break;
1579      case LT : br = \"lt\"; invbr = \"ge\"; break;
1580      case GE : br = \"ge\"; invbr = \"lt\"; break;
1581
1582      default: abort();
1583    }
1584
1585  /* Is branch target reachable with bxxz?  */
1586  if (get_attr_length (insn) == 4)
1587    {
1588      sprintf (asmtext, \"b%sz %%2,%%l0\", invbr);
1589      output_asm_insn (asmtext, operands);
1590    }
1591  else
1592    {
1593      sprintf (asmtext, \"b%sz %%2,1f\;bra %%l0\;1:\", br);
1594      output_asm_insn (asmtext, operands);
1595    }
1596  return \"\";
1597}"
1598  [(set_attr "type" "branch")
1599  ; We use 25000/50000 instead of 32768/65536 to account for slot filling
1600  ; which is complex to track and inaccurate length specs.
1601   (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1602						 (const_int 25000))
1603					   (const_int 50000))
1604				      (const_int 4)
1605				      (const_int 8)))])
1606
1607;; S<cc> operations to set a register to 1/0 based on a comparison
1608
1609(define_expand "seq"
1610  [(match_operand:SI 0 "register_operand" "")]
1611  ""
1612  "
1613{
1614  rtx op0 = operands[0];
1615  rtx op1 = m32r_compare_op0;
1616  rtx op2 = m32r_compare_op1;
1617  enum machine_mode mode = GET_MODE (op0);
1618
1619  if (mode != SImode)
1620    FAIL;
1621
1622  if (! register_operand (op1, mode))
1623    op1 = force_reg (mode, op1);
1624
1625  if (TARGET_M32RX)
1626    {
1627      if (! reg_or_zero_operand (op2, mode))
1628        op2 = force_reg (mode, op2);
1629
1630      emit_insn (gen_seq_insn_m32rx (op0, op1, op2));
1631      DONE;
1632    }
1633  if (GET_CODE (op2) == CONST_INT && INTVAL (op2) == 0)
1634    {
1635      emit_insn (gen_seq_zero_insn (op0, op1));
1636      DONE;
1637    }
1638
1639  if (! reg_or_eq_int16_operand (op2, mode))
1640    op2 = force_reg (mode, op2);
1641
1642  emit_insn (gen_seq_insn (op0, op1, op2));
1643  DONE;
1644}")
1645
1646(define_insn "seq_insn_m32rx"
1647  [(set (match_operand:SI 0 "register_operand" "=r")
1648	(eq:SI (match_operand:SI 1 "register_operand" "%r")
1649	       (match_operand:SI 2 "reg_or_zero_operand" "rP")))
1650   (clobber (reg:SI 17))]
1651  "TARGET_M32RX"
1652  "#"
1653  [(set_attr "type" "multi")
1654   (set_attr "length" "6")])
1655
1656(define_split
1657  [(set (match_operand:SI 0 "register_operand" "")
1658	(eq:SI (match_operand:SI 1 "register_operand" "")
1659	       (match_operand:SI 2 "reg_or_zero_operand" "")))
1660   (clobber (reg:SI 17))]
1661  "TARGET_M32RX"
1662  [(set (reg:SI 17)
1663	(eq:SI (match_dup 1)
1664	       (match_dup 2)))
1665   (set (match_dup 0)
1666	(reg:SI 17))]
1667  "")
1668
1669(define_insn "seq_zero_insn"
1670  [(set (match_operand:SI 0 "register_operand" "=r")
1671	(eq:SI (match_operand:SI 1 "register_operand" "r")
1672	       (const_int 0)))
1673   (clobber (reg:SI 17))]
1674  "TARGET_M32R"
1675  "#"
1676  [(set_attr "type" "multi")
1677   (set_attr "length" "6")])
1678
1679(define_split
1680  [(set (match_operand:SI 0 "register_operand" "")
1681	(eq:SI (match_operand:SI 1 "register_operand" "")
1682	       (const_int 0)))
1683   (clobber (reg:SI 17))]
1684  "TARGET_M32R"
1685  [(match_dup 3)]
1686  "
1687{
1688  rtx op0 = operands[0];
1689  rtx op1 = operands[1];
1690
1691  start_sequence ();
1692  emit_insn (gen_cmp_ltusi_insn (op1, GEN_INT (1)));
1693  emit_insn (gen_movcc_insn (op0));
1694  operands[3] = get_insns ();
1695  end_sequence ();
1696}")
1697
1698(define_insn "seq_insn"
1699  [(set (match_operand:SI 0 "register_operand" "=r,r,??r,r")
1700	(eq:SI (match_operand:SI 1 "register_operand" "r,r,r,r")
1701	       (match_operand:SI 2 "reg_or_eq_int16_operand" "r,r,r,PK")))
1702   (clobber (reg:SI 17))
1703   (clobber (match_scratch:SI 3 "=1,2,&r,r"))]
1704  "TARGET_M32R"
1705  "#"
1706  [(set_attr "type" "multi")
1707   (set_attr "length" "8,8,10,10")])
1708
1709(define_split
1710  [(set (match_operand:SI 0 "register_operand" "")
1711	(eq:SI (match_operand:SI 1 "register_operand" "")
1712	       (match_operand:SI 2 "reg_or_eq_int16_operand" "")))
1713   (clobber (reg:SI 17))
1714   (clobber (match_scratch:SI 3 ""))]
1715  "TARGET_M32R && reload_completed"
1716  [(match_dup 4)]
1717  "
1718{
1719  rtx op0 = operands[0];
1720  rtx op1 = operands[1];
1721  rtx op2 = operands[2];
1722  rtx op3 = operands[3];
1723  HOST_WIDE_INT value;
1724
1725  if (GET_CODE (op2) == REG && GET_CODE (op3) == REG
1726      && REGNO (op2) == REGNO (op3))
1727    {
1728      op1 = operands[2];
1729      op2 = operands[1];
1730    }
1731
1732  start_sequence ();
1733  if (GET_CODE (op1) == REG && GET_CODE (op3) == REG
1734      && REGNO (op1) != REGNO (op3))
1735    {
1736      emit_move_insn (op3, op1);
1737      op1 = op3;
1738    }
1739
1740  if (GET_CODE (op2) == CONST_INT && (value = INTVAL (op2)) != 0
1741      && CMP_INT16_P (value))
1742    emit_insn (gen_addsi3 (op3, op1, GEN_INT (-value)));
1743  else
1744    emit_insn (gen_xorsi3 (op3, op1, op2));
1745
1746  emit_insn (gen_cmp_ltusi_insn (op3, GEN_INT (1)));
1747  emit_insn (gen_movcc_insn (op0));
1748  operands[4] = get_insns ();
1749  end_sequence ();
1750}")
1751
1752(define_expand "sne"
1753  [(match_operand:SI 0 "register_operand" "")]
1754  ""
1755  "
1756{
1757  rtx op0 = operands[0];
1758  rtx op1 = m32r_compare_op0;
1759  rtx op2 = m32r_compare_op1;
1760  enum machine_mode mode = GET_MODE (op0);
1761
1762  if (mode != SImode)
1763    FAIL;
1764
1765  if (GET_CODE (op2) != CONST_INT
1766      || (INTVAL (op2) != 0 && UINT16_P (INTVAL (op2))))
1767    {
1768      rtx reg;
1769
1770      if (reload_completed || reload_in_progress)
1771	FAIL;
1772
1773      reg = gen_reg_rtx (SImode);
1774      emit_insn (gen_xorsi3 (reg, op1, op2));
1775      op1 = reg;
1776
1777      if (! register_operand (op1, mode))
1778        op1 = force_reg (mode, op1);
1779
1780      emit_insn (gen_sne_zero_insn (op0, op1));
1781      DONE;
1782    }
1783  else
1784    FAIL;
1785}")
1786
1787(define_insn "sne_zero_insn"
1788  [(set (match_operand:SI 0 "register_operand" "=r")
1789	(ne:SI (match_operand:SI 1 "register_operand" "r")
1790	       (const_int 0)))
1791   (clobber (reg:SI 17))
1792   (clobber (match_scratch:SI 2 "=&r"))]
1793  ""
1794  "#"
1795  [(set_attr "type" "multi")
1796   (set_attr "length" "6")])
1797
1798(define_split
1799  [(set (match_operand:SI 0 "register_operand" "")
1800	(ne:SI (match_operand:SI 1 "register_operand" "")
1801	       (const_int 0)))
1802   (clobber (reg:SI 17))
1803   (clobber (match_scratch:SI 2 ""))]
1804  "reload_completed"
1805  [(set (match_dup 2)
1806	(const_int 0))
1807   (set (reg:SI 17)
1808	(ltu:SI (match_dup 2)
1809		(match_dup 1)))
1810   (set (match_dup 0)
1811	(reg:SI 17))]
1812  "")
1813
1814(define_expand "slt"
1815  [(match_operand:SI 0 "register_operand" "")]
1816  ""
1817  "
1818{
1819  rtx op0 = operands[0];
1820  rtx op1 = m32r_compare_op0;
1821  rtx op2 = m32r_compare_op1;
1822  enum machine_mode mode = GET_MODE (op0);
1823
1824  if (mode != SImode)
1825    FAIL;
1826
1827  if (! register_operand (op1, mode))
1828    op1 = force_reg (mode, op1);
1829
1830  if (! reg_or_int16_operand (op2, mode))
1831    op2 = force_reg (mode, op2);
1832
1833  emit_insn (gen_slt_insn (op0, op1, op2));
1834  DONE;
1835}")
1836
1837(define_insn "slt_insn"
1838  [(set (match_operand:SI 0 "register_operand" "=r,r")
1839	(lt:SI (match_operand:SI 1 "register_operand" "r,r")
1840	       (match_operand:SI 2 "reg_or_int16_operand" "r,J")))
1841   (clobber (reg:SI 17))]
1842  ""
1843  "#"
1844  [(set_attr "type" "multi")
1845   (set_attr "length" "4,6")])
1846
1847(define_split
1848  [(set (match_operand:SI 0 "register_operand" "")
1849	(lt:SI (match_operand:SI 1 "register_operand" "")
1850	       (match_operand:SI 2 "reg_or_int16_operand" "")))
1851   (clobber (reg:SI 17))]
1852  ""
1853  [(set (reg:SI 17)
1854	(lt:SI (match_dup 1)
1855	       (match_dup 2)))
1856   (set (match_dup 0)
1857	(reg:SI 17))]
1858  "")
1859
1860(define_expand "sle"
1861  [(match_operand:SI 0 "register_operand" "")]
1862  ""
1863  "
1864{
1865  rtx op0 = operands[0];
1866  rtx op1 = m32r_compare_op0;
1867  rtx op2 = m32r_compare_op1;
1868  enum machine_mode mode = GET_MODE (op0);
1869
1870  if (mode != SImode)
1871    FAIL;
1872
1873  if (! register_operand (op1, mode))
1874    op1 = force_reg (mode, op1);
1875
1876  if (GET_CODE (op2) == CONST_INT)
1877    {
1878      HOST_WIDE_INT value = INTVAL (op2);
1879      if (value >= 2147483647)
1880	{
1881	  emit_move_insn (op0, GEN_INT (1));
1882	  DONE;
1883	}
1884
1885      op2 = GEN_INT (value+1);
1886      if (value < -32768 || value >= 32767)
1887	op2 = force_reg (mode, op2);
1888
1889      emit_insn (gen_slt_insn (op0, op1, op2));
1890      DONE;
1891    }
1892
1893  if (! register_operand (op2, mode))
1894    op2 = force_reg (mode, op2);
1895
1896  emit_insn (gen_sle_insn (op0, op1, op2));
1897  DONE;
1898}")
1899
1900(define_insn "sle_insn"
1901  [(set (match_operand:SI 0 "register_operand" "=r")
1902	(le:SI (match_operand:SI 1 "register_operand" "r")
1903	       (match_operand:SI 2 "register_operand" "r")))
1904   (clobber (reg:SI 17))]
1905  ""
1906  "#"
1907  [(set_attr "type" "multi")
1908   (set_attr "length" "8")])
1909
1910(define_split
1911  [(set (match_operand:SI 0 "register_operand" "")
1912	(le:SI (match_operand:SI 1 "register_operand" "")
1913	       (match_operand:SI 2 "register_operand" "")))
1914   (clobber (reg:SI 17))]
1915  "!optimize_size"
1916  [(set (reg:SI 17)
1917	(lt:SI (match_dup 2)
1918	       (match_dup 1)))
1919   (set (match_dup 0)
1920	(reg:SI 17))
1921   (set (match_dup 0)
1922	(xor:SI (match_dup 0)
1923		(const_int 1)))]
1924  "")
1925
1926;; If optimizing for space, use -(reg - 1) to invert the comparison rather than
1927;; xor reg,reg,1 which might eliminate a NOP being inserted.
1928(define_split
1929  [(set (match_operand:SI 0 "register_operand" "")
1930	(le:SI (match_operand:SI 1 "register_operand" "")
1931	       (match_operand:SI 2 "register_operand" "")))
1932   (clobber (reg:SI 17))]
1933  "optimize_size"
1934  [(set (reg:SI 17)
1935	(lt:SI (match_dup 2)
1936	       (match_dup 1)))
1937   (set (match_dup 0)
1938	(reg:SI 17))
1939   (set (match_dup 0)
1940	(plus:SI (match_dup 0)
1941		 (const_int -1)))
1942   (set (match_dup 0)
1943	(neg:SI (match_dup 0)))]
1944  "")
1945
1946(define_expand "sgt"
1947  [(match_operand:SI 0 "register_operand" "")]
1948  ""
1949  "
1950{
1951  rtx op0 = operands[0];
1952  rtx op1 = m32r_compare_op0;
1953  rtx op2 = m32r_compare_op1;
1954  enum machine_mode mode = GET_MODE (op0);
1955
1956  if (mode != SImode)
1957    FAIL;
1958
1959  if (! register_operand (op1, mode))
1960    op1 = force_reg (mode, op1);
1961
1962  if (! register_operand (op2, mode))
1963    op2 = force_reg (mode, op2);
1964
1965  emit_insn (gen_slt_insn (op0, op2, op1));
1966  DONE;
1967}")
1968
1969(define_expand "sge"
1970  [(match_operand:SI 0 "register_operand" "")]
1971  ""
1972  "
1973{
1974  rtx op0 = operands[0];
1975  rtx op1 = m32r_compare_op0;
1976  rtx op2 = m32r_compare_op1;
1977  enum machine_mode mode = GET_MODE (op0);
1978
1979  if (mode != SImode)
1980    FAIL;
1981
1982  if (! register_operand (op1, mode))
1983    op1 = force_reg (mode, op1);
1984
1985  if (! reg_or_int16_operand (op2, mode))
1986    op2 = force_reg (mode, op2);
1987
1988  emit_insn (gen_sge_insn (op0, op1, op2));
1989  DONE;
1990}")
1991
1992(define_insn "sge_insn"
1993  [(set (match_operand:SI 0 "register_operand" "=r,r")
1994	(ge:SI (match_operand:SI 1 "register_operand" "r,r")
1995	       (match_operand:SI 2 "reg_or_int16_operand" "r,J")))
1996   (clobber (reg:SI 17))]
1997  ""
1998  "#"
1999  [(set_attr "type" "multi")
2000   (set_attr "length" "8,10")])
2001
2002(define_split
2003  [(set (match_operand:SI 0 "register_operand" "")
2004	(ge:SI (match_operand:SI 1 "register_operand" "")
2005	       (match_operand:SI 2 "reg_or_int16_operand" "")))
2006   (clobber (reg:SI 17))]
2007  "!optimize_size"
2008  [(set (reg:SI 17)
2009	(lt:SI (match_dup 1)
2010	       (match_dup 2)))
2011   (set (match_dup 0)
2012	(reg:SI 17))
2013   (set (match_dup 0)
2014	(xor:SI (match_dup 0)
2015		(const_int 1)))]
2016  "")
2017
2018;; If optimizing for space, use -(reg - 1) to invert the comparison rather than
2019;; xor reg,reg,1 which might eliminate a NOP being inserted.
2020(define_split
2021  [(set (match_operand:SI 0 "register_operand" "")
2022	(ge:SI (match_operand:SI 1 "register_operand" "")
2023	       (match_operand:SI 2 "reg_or_int16_operand" "")))
2024   (clobber (reg:SI 17))]
2025  "optimize_size"
2026  [(set (reg:SI 17)
2027	(lt:SI (match_dup 1)
2028	       (match_dup 2)))
2029   (set (match_dup 0)
2030	(reg:SI 17))
2031   (set (match_dup 0)
2032	(plus:SI (match_dup 0)
2033		 (const_int -1)))
2034   (set (match_dup 0)
2035	(neg:SI (match_dup 0)))]
2036  "")
2037
2038(define_expand "sltu"
2039  [(match_operand:SI 0 "register_operand" "")]
2040  ""
2041  "
2042{
2043  rtx op0 = operands[0];
2044  rtx op1 = m32r_compare_op0;
2045  rtx op2 = m32r_compare_op1;
2046  enum machine_mode mode = GET_MODE (op0);
2047
2048  if (mode != SImode)
2049    FAIL;
2050
2051  if (! register_operand (op1, mode))
2052    op1 = force_reg (mode, op1);
2053
2054  if (! reg_or_int16_operand (op2, mode))
2055    op2 = force_reg (mode, op2);
2056
2057  emit_insn (gen_sltu_insn (op0, op1, op2));
2058  DONE;
2059}")
2060
2061(define_insn "sltu_insn"
2062  [(set (match_operand:SI 0 "register_operand" "=r,r")
2063	(ltu:SI (match_operand:SI 1 "register_operand" "r,r")
2064		(match_operand:SI 2 "reg_or_int16_operand" "r,J")))
2065   (clobber (reg:SI 17))]
2066  ""
2067  "#"
2068  [(set_attr "type" "multi")
2069   (set_attr "length" "6,8")])
2070
2071(define_split
2072  [(set (match_operand:SI 0 "register_operand" "")
2073	(ltu:SI (match_operand:SI 1 "register_operand" "")
2074		(match_operand:SI 2 "reg_or_int16_operand" "")))
2075   (clobber (reg:SI 17))]
2076  ""
2077  [(set (reg:SI 17)
2078	(ltu:SI (match_dup 1)
2079		(match_dup 2)))
2080   (set (match_dup 0)
2081	(reg:SI 17))]
2082  "")
2083
2084(define_expand "sleu"
2085  [(match_operand:SI 0 "register_operand" "")]
2086  ""
2087  "
2088{
2089  rtx op0 = operands[0];
2090  rtx op1 = m32r_compare_op0;
2091  rtx op2 = m32r_compare_op1;
2092  enum machine_mode mode = GET_MODE (op0);
2093
2094  if (mode != SImode)
2095    FAIL;
2096
2097  if (GET_CODE (op2) == CONST_INT)
2098    {
2099      HOST_WIDE_INT value = INTVAL (op2);
2100      if (value >= 2147483647)
2101	{
2102	  emit_move_insn (op0, GEN_INT (1));
2103	  DONE;
2104	}
2105
2106      op2 = GEN_INT (value+1);
2107      if (value < 0 || value >= 32767)
2108	op2 = force_reg (mode, op2);
2109
2110      emit_insn (gen_sltu_insn (op0, op1, op2));
2111      DONE;
2112    }
2113
2114  if (! register_operand (op2, mode))
2115    op2 = force_reg (mode, op2);
2116
2117  emit_insn (gen_sleu_insn (op0, op1, op2));
2118  DONE;
2119}")
2120
2121(define_insn "sleu_insn"
2122  [(set (match_operand:SI 0 "register_operand" "=r")
2123	(leu:SI (match_operand:SI 1 "register_operand" "r")
2124		(match_operand:SI 2 "register_operand" "r")))
2125   (clobber (reg:SI 17))]
2126  ""
2127  "#"
2128  [(set_attr "type" "multi")
2129   (set_attr "length" "8")])
2130
2131(define_split
2132  [(set (match_operand:SI 0 "register_operand" "")
2133	(leu:SI (match_operand:SI 1 "register_operand" "")
2134		(match_operand:SI 2 "register_operand" "")))
2135   (clobber (reg:SI 17))]
2136  "!optimize_size"
2137  [(set (reg:SI 17)
2138	(ltu:SI (match_dup 2)
2139		(match_dup 1)))
2140   (set (match_dup 0)
2141	(reg:SI 17))
2142   (set (match_dup 0)
2143	(xor:SI (match_dup 0)
2144		(const_int 1)))]
2145  "")
2146
2147;; If optimizing for space, use -(reg - 1) to invert the comparison rather than
2148;; xor reg,reg,1 which might eliminate a NOP being inserted.
2149(define_split
2150  [(set (match_operand:SI 0 "register_operand" "")
2151	(leu:SI (match_operand:SI 1 "register_operand" "")
2152		(match_operand:SI 2 "register_operand" "")))
2153   (clobber (reg:SI 17))]
2154  "optimize_size"
2155  [(set (reg:SI 17)
2156	(ltu:SI (match_dup 2)
2157		(match_dup 1)))
2158   (set (match_dup 0)
2159	(reg:SI 17))
2160   (set (match_dup 0)
2161	(plus:SI (match_dup 0)
2162		 (const_int -1)))
2163   (set (match_dup 0)
2164	(neg:SI (match_dup 0)))]
2165  "")
2166
2167(define_expand "sgtu"
2168  [(match_operand:SI 0 "register_operand" "")]
2169  ""
2170  "
2171{
2172  rtx op0 = operands[0];
2173  rtx op1 = m32r_compare_op0;
2174  rtx op2 = m32r_compare_op1;
2175  enum machine_mode mode = GET_MODE (op0);
2176
2177  if (mode != SImode)
2178    FAIL;
2179
2180  if (! register_operand (op1, mode))
2181    op1 = force_reg (mode, op1);
2182
2183  if (! register_operand (op2, mode))
2184    op2 = force_reg (mode, op2);
2185
2186  emit_insn (gen_sltu_insn (op0, op2, op1));
2187  DONE;
2188}")
2189
2190(define_expand "sgeu"
2191  [(match_operand:SI 0 "register_operand" "")]
2192  ""
2193  "
2194{
2195  rtx op0 = operands[0];
2196  rtx op1 = m32r_compare_op0;
2197  rtx op2 = m32r_compare_op1;
2198  enum machine_mode mode = GET_MODE (op0);
2199
2200  if (mode != SImode)
2201    FAIL;
2202
2203  if (! register_operand (op1, mode))
2204    op1 = force_reg (mode, op1);
2205
2206  if (! reg_or_int16_operand (op2, mode))
2207    op2 = force_reg (mode, op2);
2208
2209  emit_insn (gen_sgeu_insn (op0, op1, op2));
2210  DONE;
2211}")
2212
2213(define_insn "sgeu_insn"
2214  [(set (match_operand:SI 0 "register_operand" "=r,r")
2215	(geu:SI (match_operand:SI 1 "register_operand" "r,r")
2216		(match_operand:SI 2 "reg_or_int16_operand" "r,J")))
2217   (clobber (reg:SI 17))]
2218  ""
2219  "#"
2220  [(set_attr "type" "multi")
2221   (set_attr "length" "8,10")])
2222
2223(define_split
2224  [(set (match_operand:SI 0 "register_operand" "")
2225	(geu:SI (match_operand:SI 1 "register_operand" "")
2226		(match_operand:SI 2 "reg_or_int16_operand" "")))
2227   (clobber (reg:SI 17))]
2228  "!optimize_size"
2229  [(set (reg:SI 17)
2230	(ltu:SI (match_dup 1)
2231		(match_dup 2)))
2232   (set (match_dup 0)
2233	(reg:SI 17))
2234   (set (match_dup 0)
2235	(xor:SI (match_dup 0)
2236		(const_int 1)))]
2237  "")
2238
2239;; If optimizing for space, use -(reg - 1) to invert the comparison rather than
2240;; xor reg,reg,1 which might eliminate a NOP being inserted.
2241(define_split
2242  [(set (match_operand:SI 0 "register_operand" "")
2243	(geu:SI (match_operand:SI 1 "register_operand" "")
2244		(match_operand:SI 2 "reg_or_int16_operand" "")))
2245   (clobber (reg:SI 17))]
2246  "optimize_size"
2247  [(set (reg:SI 17)
2248	(ltu:SI (match_dup 1)
2249		(match_dup 2)))
2250   (set (match_dup 0)
2251	(reg:SI 17))
2252   (set (match_dup 0)
2253	(plus:SI (match_dup 0)
2254		 (const_int -1)))
2255   (set (match_dup 0)
2256	(neg:SI (match_dup 0)))]
2257  "")
2258
2259(define_insn "movcc_insn"
2260  [(set (match_operand:SI 0 "register_operand" "=r")
2261	(reg:SI 17))]
2262  ""
2263  "mvfc %0, cbr"
2264  [(set_attr "type" "misc")
2265   (set_attr "length" "2")])
2266
2267
2268;; Unconditional and other jump instructions.
2269
2270(define_insn "jump"
2271  [(set (pc) (label_ref (match_operand 0 "" "")))]
2272  ""
2273  "bra %l0"
2274  [(set_attr "type" "uncond_branch")
2275   (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
2276						 (const_int 400))
2277					   (const_int 800))
2278				      (const_int 2)
2279				      (const_int 4)))])
2280
2281(define_insn "indirect_jump"
2282  [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
2283  ""
2284  "jmp %a0"
2285  [(set_attr "type" "uncond_branch")
2286   (set_attr "length" "2")])
2287
2288(define_insn "return"
2289  [(return)]
2290  "direct_return ()"
2291  "jmp lr"
2292  [(set_attr "type" "uncond_branch")
2293   (set_attr "length" "2")])
2294
2295(define_insn "tablejump"
2296  [(set (pc) (match_operand:SI 0 "address_operand" "p"))
2297   (use (label_ref (match_operand 1 "" "")))]
2298  ""
2299  "jmp %a0"
2300  [(set_attr "type" "uncond_branch")
2301   (set_attr "length" "2")])
2302
2303(define_expand "call"
2304  ;; operands[1] is stack_size_rtx
2305  ;; operands[2] is next_arg_register
2306  [(parallel [(call (match_operand:SI 0 "call_operand" "")
2307		    (match_operand 1 "" ""))
2308	     (clobber (reg:SI 14))])]
2309  ""
2310  "")
2311
2312(define_insn "*call_via_reg"
2313  [(call (mem:SI (match_operand:SI 0 "register_operand" "r"))
2314	 (match_operand 1 "" ""))
2315   (clobber (reg:SI 14))]
2316  ""
2317  "jl %0"
2318  [(set_attr "type" "call")
2319   (set_attr "length" "2")])
2320
2321(define_insn "*call_via_label"
2322  [(call (mem:SI (match_operand:SI 0 "call_address_operand" ""))
2323	 (match_operand 1 "" ""))
2324   (clobber (reg:SI 14))]
2325  ""
2326  "*
2327{
2328  int call26_p = call26_operand (operands[0], FUNCTION_MODE);
2329
2330  if (! call26_p)
2331    {
2332      /* We may not be able to reach with a `bl' insn so punt and leave it to
2333	 the linker.
2334	 We do this here, rather than doing a force_reg in the define_expand
2335	 so these insns won't be separated, say by scheduling, thus simplifying
2336	 the linker.  */
2337      return \"seth r14,%T0\;add3 r14,r14,%B0\;jl r14\";
2338    }
2339  else
2340    return \"bl %0\";
2341}"
2342  [(set_attr "type" "call")
2343   (set (attr "length")
2344	(if_then_else (eq (symbol_ref "call26_operand (operands[0], FUNCTION_MODE)")
2345			  (const_int 0))
2346		      (const_int 12) ; 10 + 2 for nop filler
2347		      ; The return address must be on a 4 byte boundary so
2348		      ; there's no point in using a value of 2 here.  A 2 byte
2349		      ; insn may go in the left slot but we currently can't
2350		      ; use such knowledge.
2351		      (const_int 4)))])
2352
2353(define_expand "call_value"
2354  ;; operand 2 is stack_size_rtx
2355  ;; operand 3 is next_arg_register
2356  [(parallel [(set (match_operand 0 "register_operand" "=r")
2357		   (call (match_operand:SI 1 "call_operand" "")
2358			 (match_operand 2 "" "")))
2359	     (clobber (reg:SI 14))])]
2360  ""
2361  "")
2362
2363(define_insn "*call_value_via_reg"
2364  [(set (match_operand 0 "register_operand" "=r")
2365	(call (mem:SI (match_operand:SI 1 "register_operand" "r"))
2366	      (match_operand 2 "" "")))
2367   (clobber (reg:SI 14))]
2368  ""
2369  "jl %1"
2370  [(set_attr "type" "call")
2371   (set_attr "length" "2")])
2372
2373(define_insn "*call_value_via_label"
2374  [(set (match_operand 0 "register_operand" "=r")
2375	(call (mem:SI (match_operand:SI 1 "call_address_operand" ""))
2376	      (match_operand 2 "" "")))
2377   (clobber (reg:SI 14))]
2378  ""
2379  "*
2380{
2381  int call26_p = call26_operand (operands[1], FUNCTION_MODE);
2382
2383  if (! call26_p)
2384    {
2385      /* We may not be able to reach with a `bl' insn so punt and leave it to
2386	 the linker.
2387	 We do this here, rather than doing a force_reg in the define_expand
2388	 so these insns won't be separated, say by scheduling, thus simplifying
2389	 the linker.  */
2390      return \"seth r14,%T1\;add3 r14,r14,%B1\;jl r14\";
2391    }
2392  else
2393    return \"bl %1\";
2394}"
2395  [(set_attr "type" "call")
2396   (set (attr "length")
2397	(if_then_else (eq (symbol_ref "call26_operand (operands[1], FUNCTION_MODE)")
2398			  (const_int 0))
2399		      (const_int 12) ; 10 + 2 for nop filler
2400		      ; The return address must be on a 4 byte boundary so
2401		      ; there's no point in using a value of 2 here.  A 2 byte
2402		      ; insn may go in the left slot but we currently can't
2403		      ; use such knowledge.
2404		      (const_int 4)))])
2405
2406(define_insn "nop"
2407  [(const_int 0)]
2408  ""
2409  "nop"
2410  [(set_attr "type" "int2")
2411   (set_attr "length" "2")])
2412
2413;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
2414;; all of memory.  This blocks insns from being moved across this point.
2415
2416(define_insn "blockage"
2417  [(unspec_volatile [(const_int 0)] 0)]
2418  ""
2419  "")
2420
2421;; Special pattern to flush the icache.
2422
2423(define_insn "flush_icache"
2424  [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)]
2425  ""
2426  "* return \"nop ; flush-icache\";"
2427  [(set_attr "type" "int2")
2428   (set_attr "length" "2")])
2429
2430;; Speed up fabs and provide correct sign handling for -0
2431
2432(define_insn "absdf2"
2433  [(set (match_operand:DF 0 "register_operand" "=r")
2434	(abs:DF (match_operand:DF 1 "register_operand" "0")))]
2435  ""
2436  "#"
2437  [(set_attr "type" "multi")
2438   (set_attr "length" "4")])
2439
2440(define_split
2441  [(set (match_operand:DF 0 "register_operand" "")
2442	(abs:DF (match_operand:DF 1 "register_operand" "")))]
2443  "reload_completed"
2444  [(set (match_dup 2)
2445	(ashift:SI (match_dup 2)
2446		   (const_int 1)))
2447   (set (match_dup 2)
2448	(lshiftrt:SI (match_dup 2)
2449		     (const_int 1)))]
2450  "operands[2] = gen_highpart (SImode, operands[0]);")
2451
2452(define_insn "abssf2"
2453  [(set (match_operand:SF 0 "register_operand" "=r")
2454	(abs:SF (match_operand:SF 1 "register_operand" "0")))]
2455  ""
2456  "#"
2457  [(set_attr "type" "multi")
2458   (set_attr "length" "4")])
2459
2460(define_split
2461  [(set (match_operand:SF 0 "register_operand" "")
2462	(abs:SF (match_operand:SF 1 "register_operand" "")))]
2463  "reload_completed"
2464  [(set (match_dup 2)
2465	(ashift:SI (match_dup 2)
2466		   (const_int 1)))
2467   (set (match_dup 2)
2468	(lshiftrt:SI (match_dup 2)
2469		     (const_int 1)))]
2470  "operands[2] = gen_highpart (SImode, operands[0]);")
2471
2472;; Conditional move instructions
2473;; Based on those done for the d10v
2474
2475(define_expand "movsicc"
2476  [
2477   (set (match_operand:SI 0 "register_operand" "r")
2478	(if_then_else:SI (match_operand 1 "" "")
2479			 (match_operand:SI 2 "conditional_move_operand" "O")
2480			 (match_operand:SI 3 "conditional_move_operand" "O")
2481        )
2482   )
2483  ]
2484  ""
2485  "
2486{
2487  if (! zero_and_one (operands [2], operands [3]))
2488    FAIL;
2489
2490  /* Generate the comparision that will set the carry flag.  */
2491  operands[1] = gen_compare (GET_CODE (operands[1]), m32r_compare_op0,
2492			     m32r_compare_op1, TRUE);
2493
2494  /* See other movsicc pattern below for reason why.  */
2495  emit_insn (gen_blockage ());
2496}")
2497
2498;; Generate the conditional instructions based on how the carry flag is examined.
2499(define_insn "*movsicc_internal"
2500  [(set (match_operand:SI 0 "register_operand" "=r")
2501	(if_then_else:SI (match_operand 1 "carry_compare_operand" "")
2502			 (match_operand:SI 2 "conditional_move_operand" "O")
2503			 (match_operand:SI 3 "conditional_move_operand" "O")
2504        )
2505   )]
2506  "zero_and_one (operands [2], operands[3])"
2507  "* return emit_cond_move (operands, insn);"
2508  [(set_attr "type" "multi")
2509   (set_attr "length" "8")
2510  ]
2511)
2512
2513
2514;; Split up troublesome insns for better scheduling.
2515;; FIXME: Peepholes go at the end.
2516
2517;; ??? Setting the type attribute may not be useful, but for completeness
2518;; we do it.
2519
2520(define_peephole
2521  [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
2522			 (const_int 4)))
2523        (match_operand:SI 1 "register_operand" "r"))]
2524  "0 && dead_or_set_p (insn, operands[0])"
2525  "st %1,@+%0"
2526  [(set_attr "type" "store2")
2527   (set_attr "length" "2")])
2528
2529;; This case is triggered by compiling this code:
2530;;
2531;; extern void sub(int *);
2532;; void main (void)
2533;; {
2534;;   int i=2,j=3,k;
2535;;   while (i < j)  sub(&k);
2536;;   i = j / k;
2537;;   sub(&i);
2538;;   i = j - k;
2539;;   sub(&i);
2540;; }
2541;;
2542;; Without the peephole the following assembler is generated for the
2543;; divide and subtract expressions:
2544;;
2545;;         div r5,r4
2546;;         mv r4,r5
2547;;         st r4,@(4,sp)
2548;;         bl sub
2549;;
2550;; Simialr code is produced for the subtract expression.  With this
2551;; peephole the redundant move is eliminated.
2552;;
2553;; This optimisation onbly works if PRESERVE_DEATH_INFO_REGNO_P is
2554;; defined in m32r.h
2555
2556(define_peephole
2557  [(set (match_operand:SI 0 "register_operand" "r")
2558        (match_operand:SI 1 "register_operand" "r")
2559   )
2560   (set (mem:SI (plus: SI (match_operand:SI 2 "register_operand" "r")
2561                (match_operand:SI 3 "immediate_operand" "J")))
2562        (match_dup 0)
2563   )
2564  ]
2565  "0 && dead_or_set_p (insn, operands [0])"
2566  "st %1,@(%3,%2)"
2567  [(set_attr "type" "store4")
2568   (set_attr "length" "4")
2569  ]
2570)
2571
2572;; Block moves, see m32r.c for more details.
2573;; Argument 0 is the destination
2574;; Argument 1 is the source
2575;; Argument 2 is the length
2576;; Argument 3 is the alignment
2577
2578(define_expand "movstrsi"
2579  [(parallel [(set (match_operand:BLK 0 "general_operand" "")
2580		   (match_operand:BLK 1 "general_operand" ""))
2581	      (use (match_operand:SI  2 "immediate_operand" ""))
2582	      (use (match_operand:SI  3 "immediate_operand" ""))])]
2583  ""
2584  "
2585{
2586  if (operands[0])		/* avoid unused code messages */
2587    {
2588      m32r_expand_block_move (operands);
2589      DONE;
2590    }
2591}")
2592
2593;; Insn generated by block moves
2594
2595(define_insn "movstrsi_internal"
2596  [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r"))	;; destination
2597	(mem:BLK (match_operand:SI 1 "register_operand" "+r")))	;; source
2598   (use (match_operand:SI 2 "m32r_block_immediate_operand" "J"));; # bytes to move
2599   (set (match_dup 0) (plus:SI (match_dup 0) (minus:SI (match_dup 2) (const_int 4))))
2600   (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))
2601   (clobber (match_scratch:SI 3 "=&r"))				;; temp 1
2602   (clobber (match_scratch:SI 4 "=&r"))]			;; temp 2
2603  ""
2604  "* m32r_output_block_move (insn, operands); return \"\"; "
2605  [(set_attr "type"	"store8")
2606   (set_attr "length"	"72")]) ;; Maximum
2607