]> gcc.gnu.org Git - gcc.git/blame - gcc/config/m32r/m32r.md
m32r.c: Add support for m32rx processor.
[gcc.git] / gcc / config / m32r / m32r.md
CommitLineData
4b6bb562 1;; Machine description of the Mitsubishi M32R cpu for GNU C compiler
16f104b3 2;; Copyright (C) 1996, 1997, 1998, 1999, 2001 Free Software Foundation, Inc.
8c5ca3b9
DE
3
4;; This file is part of GNU CC.
5
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)
9;; any later version.
10
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.
15
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.
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
5b8ae21f 27;; 3 - setting carry in addx/subx instructions.
8c5ca3b9
DE
28\f
29;; Insn type. Used to default other attribute values.
8c5ca3b9 30(define_attr "type"
5b8ae21f 31 "int2,int4,load2,load4,load8,store2,store4,store8,shift2,shift4,mul2,div4,uncond_branch,branch,call,multi,misc"
8c5ca3b9
DE
32 (const_string "misc"))
33
34;; Length in bytes.
35(define_attr "length" ""
5b8ae21f 36 (cond [(eq_attr "type" "int2,load2,store2,shift2,mul2")
8c5ca3b9
DE
37 (const_int 2)
38
5b8ae21f
MM
39 (eq_attr "type" "int4,load4,store4,shift4,div4")
40 (const_int 4)
8c5ca3b9
DE
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")])
2b7972b0
MM
55
56
57;; Whether an instruction is 16-bit or 32-bit
58(define_attr "insn_size" "short,long"
5b8ae21f 59 (if_then_else (eq_attr "type" "int2,load2,store2,shift2,mul2")
2b7972b0
MM
60 (const_string "short")
61 (const_string "long")))
62
5b8ae21f
MM
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
2b7972b0
MM
69(define_attr "m32r" "no,yes"
70 (const (symbol_ref "(TARGET_M32R != 0)")))
71
de41e41c
BE
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"))))
8c5ca3b9 92\f
2b7972b0
MM
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
8c5ca3b9
DE
204;; Function units of the M32R
205;; Units that take one cycle do not need to be specified.
206
2b7972b0 207;; (define_function_unit {name} {multiplicity} {simulataneity} {test}
8c5ca3b9
DE
208;; {ready-delay} {issue-delay} [{conflict-list}])
209
8c5ca3b9
DE
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
5b8ae21f
MM
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")))
8c5ca3b9 218 1 0
5b8ae21f 219 [(eq_attr "insn_size" "long")])
8c5ca3b9 220
5b8ae21f
MM
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")])
8c5ca3b9
DE
226
227(define_function_unit "long" 1 1
5b8ae21f
MM
228 (and (eq_attr "m32r" "yes")
229 (and (eq_attr "insn_size" "long")
230 (eq_attr "type" "!load4,load8")))
8c5ca3b9 231 1 0
5b8ae21f
MM
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
de41e41c
BE
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")])
8c5ca3b9
DE
271\f
272;; Expand prologue as RTL
5b8ae21f
MM
273(define_expand "prologue"
274 [(const_int 1)]
275 ""
276 "
277{
278 m32r_expand_prologue ();
279 DONE;
280}")
281
8c5ca3b9
DE
282\f
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"
5b8ae21f
MM
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"))]
8c5ca3b9
DE
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
5b8ae21f
MM
312 ldub %0,%1
313 stb %1,%0
8c5ca3b9 314 stb %1,%0"
5b8ae21f
MM
315 [(set_attr "type" "int2,int2,int4,load2,load4,store2,store4")
316 (set_attr "length" "2,2,4,2,4,2,4")])
8c5ca3b9
DE
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"
5b8ae21f
MM
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"))]
8c5ca3b9
DE
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
5b8ae21f
MM
340 lduh %0,%1
341 sth %1,%0
8c5ca3b9 342 sth %1,%0"
5b8ae21f
MM
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 "")
8c5ca3b9
DE
357
358(define_expand "movsi"
359 [(set (match_operand:SI 0 "general_operand" "")
360 (match_operand:SI 1 "general_operand" ""))]
361 ""
362 "
363{
4d6c607f 364 /* Everything except mem = const or mem = mem can be done easily. */
8c5ca3b9
DE
365
366 if (GET_CODE (operands[0]) == MEM)
367 operands[1] = force_reg (SImode, operands[1]);
368
4d6c607f 369 /* Small Data Area reference? */
8c5ca3b9
DE
370 if (small_data_operand (operands[1], SImode))
371 {
372 emit_insn (gen_movsi_sda (operands[0], operands[1]));
373 DONE;
374 }
4d6c607f
DE
375
376 /* If medium or large code model, symbols have to be loaded with
377 seth/add3. */
378 if (addr32_operand (operands[1], SImode))
8c5ca3b9
DE
379 {
380 emit_insn (gen_movsi_addr32 (operands[0], operands[1]));
381 DONE;
382 }
383}")
384
4b6bb562 385;; ??? Do we need a const_double constraint here for large unsigned values?
5b8ae21f 386(define_insn "*movsi_insn"
56e2e762 387 [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,r,r,r,r,r,r,T,S,m")
5b8ae21f 388 (match_operand:SI 1 "move_src_operand" "r,I,J,MQ,L,n,T,U,m,r,r,r"))]
8c5ca3b9 389 "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)"
5b8ae21f
MM
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:
56e2e762
NC
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
5b8ae21f
MM
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))
56e2e762
NC
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 }
5b8ae21f 444
61f3b78f 445 abort ();
5b8ae21f
MM
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")])
8c5ca3b9 449
4d6c607f
DE
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
4b6bb562 466 use 2 byte instructions wherever possible. We can assume the
4d6c607f
DE
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
737e7965
JW
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);
4d6c607f
DE
494 operands[3] = GEN_INT ((val) & 0xffff);
495}")
496
5b8ae21f
MM
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
8c5ca3b9
DE
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
4b6bb562 522;; [I think]. What to do about this is deferred until later and for now we
8c5ca3b9
DE
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_"
5b8ae21f
MM
545 [(set_attr "type" "int4")
546 (set_attr "length" "4")])
8c5ca3b9
DE
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)"
5b8ae21f
MM
571 [(set_attr "type" "int4")
572 (set_attr "length" "4")])
8c5ca3b9
DE
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"
5b8ae21f
MM
580 [(set_attr "type" "int4")
581 (set_attr "length" "4")])
8c5ca3b9
DE
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]);
8c5ca3b9
DE
593}")
594
595(define_insn "*movdi_insn"
5b8ae21f
MM
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"))]
8c5ca3b9 598 "register_operand (operands[0], DImode) || register_operand (operands[1], DImode)"
5b8ae21f
MM
599 "#"
600 [(set_attr "type" "multi,multi,multi,load8,store8")
601 (set_attr "length" "4,4,16,6,6")])
8c5ca3b9
DE
602
603(define_split
5b8ae21f
MM
604 [(set (match_operand:DI 0 "move_dest_operand" "")
605 (match_operand:DI 1 "move_double_src_operand" ""))]
8c5ca3b9 606 "reload_completed"
5b8ae21f
MM
607 [(match_dup 2)]
608 "operands[2] = gen_split_move_double (operands);")
8c5ca3b9
DE
609\f
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"
56e2e762
NC
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"))]
8c5ca3b9 627 "register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode)"
5b8ae21f
MM
628 "@
629 mv %0,%1
630 #
631 ld %0,%1
632 ld %0,%1
56e2e762
NC
633 ld %0,%1
634 st %1,%0
5b8ae21f
MM
635 st %1,%0
636 st %1,%0"
8c5ca3b9 637 ;; ??? Length of alternative 1 is either 2, 4 or 8.
56e2e762
NC
638 [(set_attr "type" "int2,multi,load2,load2,load4,store2,store2,store4")
639 (set_attr "length" "2,8,2,2,4,2,2,4")])
5b8ae21f
MM
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{
5b8ae21f 648 operands[2] = operand_subword (operands[0], 0, 0, SFmode);
b5a3eb84 649 operands[3] = operand_subword (operands[1], 0, 0, SFmode);
5b8ae21f 650}")
8c5ca3b9
DE
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]);
8c5ca3b9
DE
662}")
663
664(define_insn "*movdf_insn"
665 [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m")
5b8ae21f 666 (match_operand:DF 1 "move_double_src_operand" "r,F,m,r"))]
8c5ca3b9 667 "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)"
5b8ae21f
MM
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);")
8c5ca3b9
DE
678\f
679;; Zero extension instructions.
680
681(define_insn "zero_extendqihi2"
5b8ae21f 682 [(set (match_operand:HI 0 "register_operand" "=r,r,r")
56e2e762 683 (zero_extend:HI (match_operand:QI 1 "extend_operand" "r,T,m")))]
8c5ca3b9
DE
684 ""
685 "@
686 and3 %0,%1,%#255
5b8ae21f 687 ldub %0,%1
8c5ca3b9 688 ldub %0,%1"
5b8ae21f
MM
689 [(set_attr "type" "int4,load2,load4")
690 (set_attr "length" "4,2,4")])
8c5ca3b9
DE
691
692(define_insn "zero_extendqisi2"
5b8ae21f 693 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
56e2e762 694 (zero_extend:SI (match_operand:QI 1 "extend_operand" "r,T,m")))]
8c5ca3b9
DE
695 ""
696 "@
697 and3 %0,%1,%#255
5b8ae21f 698 ldub %0,%1
8c5ca3b9 699 ldub %0,%1"
5b8ae21f
MM
700 [(set_attr "type" "int4,load2,load4")
701 (set_attr "length" "4,2,4")])
8c5ca3b9
DE
702
703(define_insn "zero_extendhisi2"
5b8ae21f 704 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
56e2e762 705 (zero_extend:SI (match_operand:HI 1 "extend_operand" "r,T,m")))]
8c5ca3b9
DE
706 ""
707 "@
708 and3 %0,%1,%#65535
5b8ae21f 709 lduh %0,%1
8c5ca3b9 710 lduh %0,%1"
5b8ae21f
MM
711 [(set_attr "type" "int4,load2,load4")
712 (set_attr "length" "4,2,4")])
8c5ca3b9 713\f
56e2e762
NC
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")])
8c5ca3b9 725
56e2e762 726(define_split
8c5ca3b9
DE
727 [(set (match_operand:HI 0 "register_operand" "")
728 (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
56e2e762
NC
729 "reload_completed"
730 [(match_dup 2)
731 (match_dup 3)]
8c5ca3b9
DE
732 "
733{
56e2e762
NC
734 rtx op0 = gen_lowpart (SImode, operands[0]);
735 rtx shift = gen_rtx (CONST_INT, VOIDmode, 24);
8c5ca3b9 736
56e2e762
NC
737 operands[2] = gen_ashlsi3 (op0, op0, shift);
738 operands[3] = gen_ashrsi3 (op0, op0, shift);
8c5ca3b9
DE
739}")
740
56e2e762
NC
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")))]
8c5ca3b9 744 ""
56e2e762
NC
745 "@
746 #
747 ldb %0,%1
748 ldb %0,%1"
749 [(set_attr "type" "multi,load2,load4")
750 (set_attr "length" "4,2,4")])
8c5ca3b9 751
56e2e762 752(define_split
8c5ca3b9
DE
753 [(set (match_operand:SI 0 "register_operand" "")
754 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
56e2e762
NC
755 "reload_completed"
756 [(match_dup 2)
757 (match_dup 3)]
8c5ca3b9
DE
758 "
759{
56e2e762
NC
760 rtx op0 = gen_lowpart (SImode, operands[0]);
761 rtx shift = gen_rtx (CONST_INT, VOIDmode, 24);
8c5ca3b9 762
56e2e762
NC
763 operands[2] = gen_ashlsi3 (op0, op0, shift);
764 operands[3] = gen_ashrsi3 (op0, op0, shift);
8c5ca3b9
DE
765}")
766
56e2e762
NC
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")))]
8c5ca3b9 770 ""
56e2e762
NC
771 "@
772 #
773 ldh %0,%1
774 ldh %0,%1"
775 [(set_attr "type" "multi,load2,load4")
776 (set_attr "length" "4,2,4")])
8c5ca3b9 777
56e2e762 778(define_split
8c5ca3b9
DE
779 [(set (match_operand:SI 0 "register_operand" "")
780 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
56e2e762
NC
781 "reload_completed"
782 [(match_dup 2)
783 (match_dup 3)]
8c5ca3b9
DE
784 "
785{
56e2e762
NC
786 rtx op0 = gen_lowpart (SImode, operands[0]);
787 rtx shift = gen_rtx (CONST_INT, VOIDmode, 16);
8c5ca3b9 788
56e2e762
NC
789 operands[2] = gen_ashlsi3 (op0, op0, shift);
790 operands[3] = gen_ashrsi3 (op0, op0, shift);
8c5ca3b9 791}")
8c5ca3b9
DE
792\f
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"
5b8ae21f 808 [(set_attr "type" "int2,int2,int4")
8c5ca3b9
DE
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")))
51c10c4e 827 (clobber (reg:SI 17))]
8c5ca3b9 828 ""
5b8ae21f
MM
829 "#"
830 [(set_attr "type" "multi")
8c5ca3b9
DE
831 (set_attr "length" "6")])
832
5b8ae21f
MM
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"
51c10c4e 864 [(set (reg:SI 17)
5b8ae21f
MM
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")
51c10c4e
NC
876 (reg:SI 17))))
877 (set (reg:SI 17)
5b8ae21f
MM
878 (unspec [(const_int 0)] 3))]
879 ""
880 "addx %0,%2"
881 [(set_attr "type" "int2")
882 (set_attr "length" "2")])
883
8c5ca3b9
DE
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"
5b8ae21f
MM
890 [(set_attr "type" "int2")
891 (set_attr "length" "2")])
8c5ca3b9
DE
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")))
51c10c4e 897 (clobber (reg:SI 17))]
8c5ca3b9 898 ""
5b8ae21f
MM
899 "#"
900 [(set_attr "type" "multi")
8c5ca3b9 901 (set_attr "length" "6")])
5b8ae21f
MM
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")
51c10c4e
NC
937 (reg:SI 17))))
938 (set (reg:SI 17)
5b8ae21f
MM
939 (unspec [(const_int 0)] 3))]
940 ""
941 "subx %0,%2"
942 [(set_attr "type" "int2")
943 (set_attr "length" "2")])
8c5ca3b9
DE
944\f
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"
5b8ae21f 953 [(set_attr "type" "multi")
8c5ca3b9
DE
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"
5b8ae21f
MM
962 [(set_attr "type" "mul2")
963 (set_attr "length" "2")])
8c5ca3b9
DE
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"
5b8ae21f
MM
971 [(set_attr "type" "div4")
972 (set_attr "length" "4")])
8c5ca3b9
DE
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"
5b8ae21f
MM
980 [(set_attr "type" "div4")
981 (set_attr "length" "4")])
8c5ca3b9
DE
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"
5b8ae21f
MM
989 [(set_attr "type" "div4")
990 (set_attr "length" "4")])
8c5ca3b9
DE
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"
5b8ae21f
MM
998 [(set_attr "type" "div4")
999 (set_attr "length" "4")])
8c5ca3b9
DE
1000\f
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")
56e2e762 1009 (match_operand:SI 2 "reg_or_uint16_operand" "r,K")))]
8c5ca3b9 1010 ""
56e2e762
NC
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}"
5b8ae21f
MM
1026 [(set_attr "type" "int2,int4")
1027 (set_attr "length" "2,4")])
8c5ca3b9 1028
56e2e762
NC
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 1) (match_dup 0)))]
1036 "")
1037
8c5ca3b9
DE
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")
56e2e762 1041 (match_operand:SI 2 "reg_or_uint16_operand" "r,K")))]
8c5ca3b9 1042 ""
56e2e762
NC
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}"
5b8ae21f
MM
1058 [(set_attr "type" "int2,int4")
1059 (set_attr "length" "2,4")])
8c5ca3b9 1060
56e2e762
NC
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 1) (match_dup 0)))]
1068 "")
1069
8c5ca3b9
DE
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")
56e2e762 1073 (match_operand:SI 2 "reg_or_uint16_operand" "r,K")))]
8c5ca3b9 1074 ""
56e2e762
NC
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}"
5b8ae21f
MM
1090 [(set_attr "type" "int2,int4")
1091 (set_attr "length" "2,4")])
8c5ca3b9 1092
56e2e762
NC
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 1) (match_dup 0)))]
1100 "")
1101
8c5ca3b9
DE
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"
5b8ae21f
MM
1107 [(set_attr "type" "int2")
1108 (set_attr "length" "2")])
8c5ca3b9
DE
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"
5b8ae21f
MM
1115 [(set_attr "type" "int2")
1116 (set_attr "length" "2")])
8c5ca3b9
DE
1117\f
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"
5b8ae21f 1129 [(set_attr "type" "shift2,shift2,shift4")
8c5ca3b9
DE
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"
5b8ae21f 1141 [(set_attr "type" "shift2,shift2,shift4")
8c5ca3b9
DE
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"
5b8ae21f 1153 [(set_attr "type" "shift2,shift2,shift4")
8c5ca3b9
DE
1154 (set_attr "length" "2,2,4")])
1155\f
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
4b6bb562 1165;; preferred.
8c5ca3b9
DE
1166
1167(define_expand "cmpsi"
51c10c4e 1168 [(set (reg:SI 17)
56e2e762
NC
1169 (compare:CC (match_operand:SI 0 "register_operand" "")
1170 (match_operand:SI 1 "reg_or_cmp_int16_operand" "")))]
8c5ca3b9
DE
1171 ""
1172 "
1173{
1174 m32r_compare_op0 = operands[0];
1175 m32r_compare_op1 = operands[1];
1176 DONE;
1177}")
1178
de41e41c
BE
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
8c5ca3b9
DE
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"
51c10c4e 1195 [(set (reg:SI 17)
de41e41c
BE
1196 (eq:SI (match_operand:SI 0 "register_operand" "r,r")
1197 (match_operand:SI 1 "reg_or_cmp_int16_operand" "r,P")))
8c5ca3b9 1198 (clobber (match_scratch:SI 2 "=&r,&r"))]
2b7972b0
MM
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}"
5b8ae21f 1216 [(set_attr "type" "multi,multi")
8c5ca3b9
DE
1217 (set_attr "length" "8,8")])
1218
1219(define_insn "cmp_ltsi_insn"
51c10c4e 1220 [(set (reg:SI 17)
de41e41c
BE
1221 (lt:SI (match_operand:SI 0 "register_operand" "r,r")
1222 (match_operand:SI 1 "reg_or_int16_operand" "r,J")))]
8c5ca3b9
DE
1223 ""
1224 "@
1225 cmp %0,%1
1226 cmpi %0,%#%1"
5b8ae21f
MM
1227 [(set_attr "type" "int2,int4")
1228 (set_attr "length" "2,4")])
8c5ca3b9
DE
1229
1230(define_insn "cmp_ltusi_insn"
51c10c4e 1231 [(set (reg:SI 17)
de41e41c
BE
1232 (ltu:SI (match_operand:SI 0 "register_operand" "r,r")
1233 (match_operand:SI 1 "reg_or_int16_operand" "r,J")))]
8c5ca3b9 1234 ""
5b8ae21f
MM
1235 "@
1236 cmpu %0,%1
1237 cmpui %0,%#%1"
1238 [(set_attr "type" "int2,int4")
1239 (set_attr "length" "2,4")])
8c5ca3b9 1240
de41e41c 1241
8c5ca3b9
DE
1242;; reg == small constant comparisons are best handled by putting the result
1243;; of the comparison in a tmp reg and then using beqz/bnez.
1244;; ??? The result register doesn't contain 0/STORE_FLAG_VALUE,
1245;; it contains 0/non-zero.
1246
1247(define_insn "cmp_ne_small_const_insn"
2b7972b0
MM
1248 [(set (match_operand:SI 0 "register_operand" "=r,r")
1249 (ne:SI (match_operand:SI 1 "register_operand" "0,r")
5b8ae21f 1250 (match_operand:SI 2 "cmp_int16_operand" "N,P")))]
8c5ca3b9 1251 ""
2b7972b0
MM
1252 "@
1253 addi %0,%#%N2
1254 add3 %0,%1,%#%N2"
5b8ae21f 1255 [(set_attr "type" "int2,int4")
2b7972b0 1256 (set_attr "length" "2,4")])
8c5ca3b9
DE
1257\f
1258;; These control RTL generation for conditional jump insns.
1259
1260(define_expand "beq"
1261 [(set (pc)
1262 (if_then_else (match_dup 1)
1263 (label_ref (match_operand 0 "" ""))
1264 (pc)))]
1265 ""
1266 "
1267{
56e2e762 1268 operands[1] = gen_compare (EQ, m32r_compare_op0, m32r_compare_op1, FALSE);
8c5ca3b9
DE
1269}")
1270
1271(define_expand "bne"
1272 [(set (pc)
1273 (if_then_else (match_dup 1)
1274 (label_ref (match_operand 0 "" ""))
1275 (pc)))]
1276 ""
1277 "
1278{
56e2e762 1279 operands[1] = gen_compare (NE, m32r_compare_op0, m32r_compare_op1, FALSE);
8c5ca3b9
DE
1280}")
1281
1282(define_expand "bgt"
1283 [(set (pc)
1284 (if_then_else (match_dup 1)
1285 (label_ref (match_operand 0 "" ""))
1286 (pc)))]
1287 ""
1288 "
1289{
56e2e762 1290 operands[1] = gen_compare (GT, m32r_compare_op0, m32r_compare_op1, FALSE);
8c5ca3b9
DE
1291}")
1292
1293(define_expand "ble"
1294 [(set (pc)
1295 (if_then_else (match_dup 1)
1296 (label_ref (match_operand 0 "" ""))
1297 (pc)))]
1298 ""
1299 "
1300{
56e2e762 1301 operands[1] = gen_compare (LE, m32r_compare_op0, m32r_compare_op1, FALSE);
8c5ca3b9
DE
1302}")
1303
1304(define_expand "bge"
1305 [(set (pc)
1306 (if_then_else (match_dup 1)
1307 (label_ref (match_operand 0 "" ""))
1308 (pc)))]
1309 ""
1310 "
1311{
56e2e762 1312 operands[1] = gen_compare (GE, m32r_compare_op0, m32r_compare_op1, FALSE);
8c5ca3b9
DE
1313}")
1314
1315(define_expand "blt"
1316 [(set (pc)
1317 (if_then_else (match_dup 1)
1318 (label_ref (match_operand 0 "" ""))
1319 (pc)))]
1320 ""
1321 "
1322{
56e2e762 1323 operands[1] = gen_compare (LT, m32r_compare_op0, m32r_compare_op1, FALSE);
8c5ca3b9
DE
1324}")
1325
1326(define_expand "bgtu"
1327 [(set (pc)
1328 (if_then_else (match_dup 1)
1329 (label_ref (match_operand 0 "" ""))
1330 (pc)))]
1331 ""
1332 "
1333{
56e2e762 1334 operands[1] = gen_compare (GTU, m32r_compare_op0, m32r_compare_op1, FALSE);
8c5ca3b9
DE
1335}")
1336
1337(define_expand "bleu"
1338 [(set (pc)
1339 (if_then_else (match_dup 1)
1340 (label_ref (match_operand 0 "" ""))
1341 (pc)))]
1342 ""
1343 "
1344{
56e2e762 1345 operands[1] = gen_compare (LEU, m32r_compare_op0, m32r_compare_op1, FALSE);
8c5ca3b9
DE
1346}")
1347
1348(define_expand "bgeu"
1349 [(set (pc)
1350 (if_then_else (match_dup 1)
1351 (label_ref (match_operand 0 "" ""))
1352 (pc)))]
1353 ""
1354 "
1355{
56e2e762 1356 operands[1] = gen_compare (GEU, m32r_compare_op0, m32r_compare_op1, FALSE);
8c5ca3b9
DE
1357}")
1358
1359(define_expand "bltu"
1360 [(set (pc)
1361 (if_then_else (match_dup 1)
1362 (label_ref (match_operand 0 "" ""))
1363 (pc)))]
1364 ""
1365 "
1366{
56e2e762 1367 operands[1] = gen_compare (LTU, m32r_compare_op0, m32r_compare_op1, FALSE);
8c5ca3b9
DE
1368}")
1369
1370;; Now match both normal and inverted jump.
1371
1372(define_insn "*branch_insn"
1373 [(set (pc)
1374 (if_then_else (match_operator 1 "eqne_comparison_operator"
1375 [(reg 17) (const_int 0)])
1376 (label_ref (match_operand 0 "" ""))
1377 (pc)))]
1378 ""
1379 "*
1380{
2b7972b0
MM
1381 static char instruction[40];
1382 sprintf (instruction, \"%s%s %%l0\",
1383 (GET_CODE (operands[1]) == NE) ? \"bc\" : \"bnc\",
1384 (get_attr_length (insn) == 2) ? \".s\" : \"\");
1385 return instruction;
8c5ca3b9
DE
1386}"
1387 [(set_attr "type" "branch")
1388 ; We use 400/800 instead of 512,1024 to account for inaccurate insn
1389 ; lengths and insn alignments that are complex to track.
1390 ; It's not important that we be hyper-precise here. It may be more
1391 ; important blah blah blah when the chip supports parallel execution
1392 ; blah blah blah but until then blah blah blah this is simple and
1393 ; suffices.
1394 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1395 (const_int 400))
1396 (const_int 800))
1397 (const_int 2)
1398 (const_int 4)))])
1399
1400(define_insn "*rev_branch_insn"
1401 [(set (pc)
1402 (if_then_else (match_operator 1 "eqne_comparison_operator"
1403 [(reg 17) (const_int 0)])
1404 (pc)
1405 (label_ref (match_operand 0 "" ""))))]
1406 ;"REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
1407 ""
1408 "*
1409{
2b7972b0
MM
1410 static char instruction[40];
1411 sprintf (instruction, \"%s%s %%l0\",
1412 (GET_CODE (operands[1]) == EQ) ? \"bc\" : \"bnc\",
1413 (get_attr_length (insn) == 2) ? \".s\" : \"\");
1414 return instruction;
8c5ca3b9
DE
1415}"
1416 [(set_attr "type" "branch")
1417 ; We use 400/800 instead of 512,1024 to account for inaccurate insn
1418 ; lengths and insn alignments that are complex to track.
1419 ; It's not important that we be hyper-precise here. It may be more
1420 ; important blah blah blah when the chip supports parallel execution
1421 ; blah blah blah but until then blah blah blah this is simple and
1422 ; suffices.
1423 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1424 (const_int 400))
1425 (const_int 800))
1426 (const_int 2)
1427 (const_int 4)))])
1428
1429; reg/reg compare and branch insns
1430
1431(define_insn "*reg_branch_insn"
1432 [(set (pc)
1433 (if_then_else (match_operator 1 "eqne_comparison_operator"
1434 [(match_operand:SI 2 "register_operand" "r")
1435 (match_operand:SI 3 "register_operand" "r")])
1436 (label_ref (match_operand 0 "" ""))
1437 (pc)))]
1438 ""
1439 "*
1440{
1441 /* Is branch target reachable with beq/bne? */
1442 if (get_attr_length (insn) == 4)
1443 {
1444 if (GET_CODE (operands[1]) == EQ)
1445 return \"beq %2,%3,%l0\";
1446 else
1447 return \"bne %2,%3,%l0\";
1448 }
1449 else
1450 {
1451 if (GET_CODE (operands[1]) == EQ)
1452 return \"bne %2,%3,1f\;bra %l0\;1:\";
1453 else
1454 return \"beq %2,%3,1f\;bra %l0\;1:\";
1455 }
1456}"
1457 [(set_attr "type" "branch")
1458 ; We use 25000/50000 instead of 32768/65536 to account for slot filling
1459 ; which is complex to track and inaccurate length specs.
1460 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1461 (const_int 25000))
1462 (const_int 50000))
1463 (const_int 4)
1464 (const_int 8)))])
1465
1466(define_insn "*rev_reg_branch_insn"
1467 [(set (pc)
1468 (if_then_else (match_operator 1 "eqne_comparison_operator"
1469 [(match_operand:SI 2 "register_operand" "r")
1470 (match_operand:SI 3 "register_operand" "r")])
1471 (pc)
1472 (label_ref (match_operand 0 "" ""))))]
1473 ""
1474 "*
1475{
1476 /* Is branch target reachable with beq/bne? */
1477 if (get_attr_length (insn) == 4)
1478 {
1479 if (GET_CODE (operands[1]) == NE)
1480 return \"beq %2,%3,%l0\";
1481 else
1482 return \"bne %2,%3,%l0\";
1483 }
1484 else
1485 {
1486 if (GET_CODE (operands[1]) == NE)
1487 return \"bne %2,%3,1f\;bra %l0\;1:\";
1488 else
1489 return \"beq %2,%3,1f\;bra %l0\;1:\";
1490 }
1491}"
1492 [(set_attr "type" "branch")
1493 ; We use 25000/50000 instead of 32768/65536 to account for slot filling
1494 ; which is complex to track and inaccurate length specs.
1495 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1496 (const_int 25000))
1497 (const_int 50000))
1498 (const_int 4)
1499 (const_int 8)))])
1500
1501; reg/zero compare and branch insns
1502
1503(define_insn "*zero_branch_insn"
1504 [(set (pc)
1505 (if_then_else (match_operator 1 "signed_comparison_operator"
1506 [(match_operand:SI 2 "register_operand" "r")
1507 (const_int 0)])
1508 (label_ref (match_operand 0 "" ""))
1509 (pc)))]
1510 ""
1511 "*
1512{
de41e41c 1513 char *br,*invbr;
8c5ca3b9
DE
1514 char asmtext[40];
1515
1516 switch (GET_CODE (operands[1]))
1517 {
1518 case EQ : br = \"eq\"; invbr = \"ne\"; break;
1519 case NE : br = \"ne\"; invbr = \"eq\"; break;
1520 case LE : br = \"le\"; invbr = \"gt\"; break;
1521 case GT : br = \"gt\"; invbr = \"le\"; break;
1522 case LT : br = \"lt\"; invbr = \"ge\"; break;
1523 case GE : br = \"ge\"; invbr = \"lt\"; break;
61f3b78f
RH
1524
1525 default: abort();
8c5ca3b9
DE
1526 }
1527
1528 /* Is branch target reachable with bxxz? */
1529 if (get_attr_length (insn) == 4)
1530 {
1531 sprintf (asmtext, \"b%sz %%2,%%l0\", br);
1532 output_asm_insn (asmtext, operands);
1533 }
1534 else
1535 {
1536 sprintf (asmtext, \"b%sz %%2,1f\;bra %%l0\;1:\", invbr);
1537 output_asm_insn (asmtext, operands);
1538 }
1539 return \"\";
1540}"
1541 [(set_attr "type" "branch")
1542 ; We use 25000/50000 instead of 32768/65536 to account for slot filling
1543 ; which is complex to track and inaccurate length specs.
1544 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1545 (const_int 25000))
1546 (const_int 50000))
1547 (const_int 4)
1548 (const_int 8)))])
1549
1550(define_insn "*rev_zero_branch_insn"
1551 [(set (pc)
1552 (if_then_else (match_operator 1 "eqne_comparison_operator"
1553 [(match_operand:SI 2 "register_operand" "r")
1554 (const_int 0)])
1555 (pc)
1556 (label_ref (match_operand 0 "" ""))))]
1557 ""
1558 "*
1559{
de41e41c 1560 char *br,*invbr;
8c5ca3b9
DE
1561 char asmtext[40];
1562
1563 switch (GET_CODE (operands[1]))
1564 {
1565 case EQ : br = \"eq\"; invbr = \"ne\"; break;
1566 case NE : br = \"ne\"; invbr = \"eq\"; break;
1567 case LE : br = \"le\"; invbr = \"gt\"; break;
1568 case GT : br = \"gt\"; invbr = \"le\"; break;
1569 case LT : br = \"lt\"; invbr = \"ge\"; break;
1570 case GE : br = \"ge\"; invbr = \"lt\"; break;
61f3b78f
RH
1571
1572 default: abort();
8c5ca3b9
DE
1573 }
1574
1575 /* Is branch target reachable with bxxz? */
1576 if (get_attr_length (insn) == 4)
1577 {
1578 sprintf (asmtext, \"b%sz %%2,%%l0\", invbr);
1579 output_asm_insn (asmtext, operands);
1580 }
1581 else
1582 {
1583 sprintf (asmtext, \"b%sz %%2,1f\;bra %%l0\;1:\", br);
1584 output_asm_insn (asmtext, operands);
1585 }
1586 return \"\";
1587}"
1588 [(set_attr "type" "branch")
1589 ; We use 25000/50000 instead of 32768/65536 to account for slot filling
1590 ; which is complex to track and inaccurate length specs.
1591 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1592 (const_int 25000))
1593 (const_int 50000))
1594 (const_int 4)
1595 (const_int 8)))])
1596\f
56e2e762
NC
1597;; S<cc> operations to set a register to 1/0 based on a comparison
1598
1599(define_expand "seq"
1600 [(match_operand:SI 0 "register_operand" "")]
1601 ""
1602 "
1603{
1604 rtx op0 = operands[0];
1605 rtx op1 = m32r_compare_op0;
1606 rtx op2 = m32r_compare_op1;
1607 enum machine_mode mode = GET_MODE (op0);
1608
1609 if (mode != SImode)
1610 FAIL;
1611
1612 if (! register_operand (op1, mode))
1613 op1 = force_reg (mode, op1);
1614
de41e41c
BE
1615 if (TARGET_M32RX)
1616 {
1617 if (! reg_or_zero_operand (op2, mode))
1618 op2 = force_reg (mode, op2);
1619
1620 emit_insn (gen_seq_insn_m32rx (op0, op1, op2));
1621 DONE;
1622 }
56e2e762
NC
1623 if (GET_CODE (op2) == CONST_INT && INTVAL (op2) == 0)
1624 {
1625 emit_insn (gen_seq_zero_insn (op0, op1));
1626 DONE;
1627 }
1628
1629 if (! reg_or_eq_int16_operand (op2, mode))
1630 op2 = force_reg (mode, op2);
1631
1632 emit_insn (gen_seq_insn (op0, op1, op2));
1633 DONE;
1634}")
1635
de41e41c
BE
1636(define_insn "seq_insn_m32rx"
1637 [(set (match_operand:SI 0 "register_operand" "=r")
1638 (eq:SI (match_operand:SI 1 "register_operand" "%r")
1639 (match_operand:SI 2 "reg_or_zero_operand" "rP")))
1640 (clobber (reg:SI 17))]
1641 "TARGET_M32RX"
1642 "#"
1643 [(set_attr "type" "multi")
1644 (set_attr "length" "6")])
1645
1646(define_split
1647 [(set (match_operand:SI 0 "register_operand" "")
1648 (eq:SI (match_operand:SI 1 "register_operand" "")
1649 (match_operand:SI 2 "reg_or_zero_operand" "")))
1650 (clobber (reg:SI 17))]
1651 "TARGET_M32RX"
1652 [(set (reg:SI 17)
1653 (eq:SI (match_dup 1)
1654 (match_dup 2)))
1655 (set (match_dup 0)
1656 (reg:SI 17))]
1657 "")
1658
56e2e762
NC
1659(define_insn "seq_zero_insn"
1660 [(set (match_operand:SI 0 "register_operand" "=r")
1661 (eq:SI (match_operand:SI 1 "register_operand" "r")
1662 (const_int 0)))
1663 (clobber (reg:SI 17))]
1664 "TARGET_M32R"
1665 "#"
1666 [(set_attr "type" "multi")
1667 (set_attr "length" "6")])
1668
1669(define_split
1670 [(set (match_operand:SI 0 "register_operand" "")
1671 (eq:SI (match_operand:SI 1 "register_operand" "")
1672 (const_int 0)))
1673 (clobber (reg:SI 17))]
1674 "TARGET_M32R"
1675 [(match_dup 3)]
1676 "
1677{
1678 rtx op0 = operands[0];
1679 rtx op1 = operands[1];
1680
1681 start_sequence ();
1682 emit_insn (gen_cmp_ltusi_insn (op1, GEN_INT (1)));
1683 emit_insn (gen_movcc_insn (op0));
1684 operands[3] = gen_sequence ();
1685 end_sequence ();
1686}")
1687
1688(define_insn "seq_insn"
1689 [(set (match_operand:SI 0 "register_operand" "=r,r,??r,r")
1690 (eq:SI (match_operand:SI 1 "register_operand" "r,r,r,r")
1691 (match_operand:SI 2 "reg_or_eq_int16_operand" "r,r,r,PK")))
1692 (clobber (reg:SI 17))
1693 (clobber (match_scratch:SI 3 "=1,2,&r,r"))]
1694 "TARGET_M32R"
1695 "#"
1696 [(set_attr "type" "multi")
1697 (set_attr "length" "8,8,10,10")])
1698
1699(define_split
1700 [(set (match_operand:SI 0 "register_operand" "")
1701 (eq:SI (match_operand:SI 1 "register_operand" "")
1702 (match_operand:SI 2 "reg_or_eq_int16_operand" "")))
1703 (clobber (reg:SI 17))
1704 (clobber (match_scratch:SI 3 ""))]
1705 "TARGET_M32R && reload_completed"
1706 [(match_dup 4)]
1707 "
1708{
1709 rtx op0 = operands[0];
1710 rtx op1 = operands[1];
1711 rtx op2 = operands[2];
1712 rtx op3 = operands[3];
1713 HOST_WIDE_INT value;
1714
1715 if (GET_CODE (op2) == REG && GET_CODE (op3) == REG
1716 && REGNO (op2) == REGNO (op3))
1717 {
1718 op1 = operands[2];
1719 op2 = operands[1];
1720 }
1721
1722 start_sequence ();
1723 if (GET_CODE (op1) == REG && GET_CODE (op3) == REG
1724 && REGNO (op1) != REGNO (op3))
1725 {
1726 emit_move_insn (op3, op1);
1727 op1 = op3;
1728 }
1729
1730 if (GET_CODE (op2) == CONST_INT && (value = INTVAL (op2)) != 0
1731 && CMP_INT16_P (value))
1732 emit_insn (gen_addsi3 (op3, op1, GEN_INT (-value)));
1733 else
1734 emit_insn (gen_xorsi3 (op3, op1, op2));
1735
1736 emit_insn (gen_cmp_ltusi_insn (op3, GEN_INT (1)));
1737 emit_insn (gen_movcc_insn (op0));
1738 operands[4] = gen_sequence ();
1739 end_sequence ();
1740}")
1741
1742(define_expand "sne"
1743 [(match_operand:SI 0 "register_operand" "")]
1744 ""
1745 "
1746{
1747 rtx op0 = operands[0];
1748 rtx op1 = m32r_compare_op0;
1749 rtx op2 = m32r_compare_op1;
1750 enum machine_mode mode = GET_MODE (op0);
1751
1752 if (mode != SImode)
1753 FAIL;
1754
1755 if (GET_CODE (op2) != CONST_INT
1756 || (INTVAL (op2) != 0 && UINT16_P (INTVAL (op2))))
1757 {
1758 rtx reg;
1759
1760 if (reload_completed || reload_in_progress)
1761 FAIL;
1762
1763 reg = gen_reg_rtx (SImode);
1764 emit_insn (gen_xorsi3 (reg, op1, op2));
1765 op1 = reg;
1766
1767 if (! register_operand (op1, mode))
1768 op1 = force_reg (mode, op1);
1769
1770 emit_insn (gen_sne_zero_insn (op0, op1));
1771 DONE;
1772 }
1773 else
1774 FAIL;
1775}")
1776
1777(define_insn "sne_zero_insn"
1778 [(set (match_operand:SI 0 "register_operand" "=r")
1779 (ne:SI (match_operand:SI 1 "register_operand" "r")
1780 (const_int 0)))
1781 (clobber (reg:SI 17))
1782 (clobber (match_scratch:SI 2 "=&r"))]
1783 ""
1784 "#"
1785 [(set_attr "type" "multi")
1786 (set_attr "length" "6")])
1787
1788(define_split
1789 [(set (match_operand:SI 0 "register_operand" "")
1790 (ne:SI (match_operand:SI 1 "register_operand" "")
1791 (const_int 0)))
1792 (clobber (reg:SI 17))
1793 (clobber (match_scratch:SI 2 ""))]
1794 "reload_completed"
1795 [(set (match_dup 2)
1796 (const_int 0))
1797 (set (reg:SI 17)
1798 (ltu:SI (match_dup 2)
1799 (match_dup 1)))
1800 (set (match_dup 0)
1801 (reg:SI 17))]
1802 "")
1803
1804(define_expand "slt"
1805 [(match_operand:SI 0 "register_operand" "")]
1806 ""
1807 "
1808{
1809 rtx op0 = operands[0];
1810 rtx op1 = m32r_compare_op0;
1811 rtx op2 = m32r_compare_op1;
1812 enum machine_mode mode = GET_MODE (op0);
1813
1814 if (mode != SImode)
1815 FAIL;
1816
1817 if (! register_operand (op1, mode))
1818 op1 = force_reg (mode, op1);
1819
1820 if (! reg_or_int16_operand (op2, mode))
1821 op2 = force_reg (mode, op2);
1822
1823 emit_insn (gen_slt_insn (op0, op1, op2));
1824 DONE;
1825}")
1826
1827(define_insn "slt_insn"
1828 [(set (match_operand:SI 0 "register_operand" "=r,r")
1829 (lt:SI (match_operand:SI 1 "register_operand" "r,r")
1830 (match_operand:SI 2 "reg_or_int16_operand" "r,J")))
1831 (clobber (reg:SI 17))]
1832 ""
1833 "#"
1834 [(set_attr "type" "multi")
1835 (set_attr "length" "4,6")])
1836
1837(define_split
1838 [(set (match_operand:SI 0 "register_operand" "")
1839 (lt:SI (match_operand:SI 1 "register_operand" "")
1840 (match_operand:SI 2 "reg_or_int16_operand" "")))
1841 (clobber (reg:SI 17))]
1842 ""
1843 [(set (reg:SI 17)
1844 (lt:SI (match_dup 1)
1845 (match_dup 2)))
1846 (set (match_dup 0)
1847 (reg:SI 17))]
1848 "")
1849
1850(define_expand "sle"
1851 [(match_operand:SI 0 "register_operand" "")]
1852 ""
1853 "
1854{
1855 rtx op0 = operands[0];
1856 rtx op1 = m32r_compare_op0;
1857 rtx op2 = m32r_compare_op1;
1858 enum machine_mode mode = GET_MODE (op0);
1859
1860 if (mode != SImode)
1861 FAIL;
1862
1863 if (! register_operand (op1, mode))
1864 op1 = force_reg (mode, op1);
1865
1866 if (GET_CODE (op2) == CONST_INT)
1867 {
1868 HOST_WIDE_INT value = INTVAL (op2);
1869 if (value >= 2147483647)
1870 {
1871 emit_move_insn (op0, GEN_INT (1));
1872 DONE;
1873 }
1874
1875 op2 = GEN_INT (value+1);
1876 if (value < -32768 || value >= 32767)
1877 op2 = force_reg (mode, op2);
1878
1879 emit_insn (gen_slt_insn (op0, op1, op2));
1880 DONE;
1881 }
1882
1883 if (! register_operand (op2, mode))
1884 op2 = force_reg (mode, op2);
1885
1886 emit_insn (gen_sle_insn (op0, op1, op2));
1887 DONE;
1888}")
1889
1890(define_insn "sle_insn"
1891 [(set (match_operand:SI 0 "register_operand" "=r")
1892 (le:SI (match_operand:SI 1 "register_operand" "r")
1893 (match_operand:SI 2 "register_operand" "r")))
1894 (clobber (reg:SI 17))]
1895 ""
1896 "#"
1897 [(set_attr "type" "multi")
1898 (set_attr "length" "8")])
1899
1900(define_split
1901 [(set (match_operand:SI 0 "register_operand" "")
1902 (le:SI (match_operand:SI 1 "register_operand" "")
1903 (match_operand:SI 2 "register_operand" "")))
1904 (clobber (reg:SI 17))]
1905 "!optimize_size"
1906 [(set (reg:SI 17)
1907 (lt:SI (match_dup 2)
1908 (match_dup 1)))
1909 (set (match_dup 0)
1910 (reg:SI 17))
1911 (set (match_dup 0)
1912 (xor:SI (match_dup 0)
1913 (const_int 1)))]
1914 "")
1915
1916;; If optimizing for space, use -(reg - 1) to invert the comparison rather than
1917;; xor reg,reg,1 which might eliminate a NOP being inserted.
1918(define_split
1919 [(set (match_operand:SI 0 "register_operand" "")
1920 (le:SI (match_operand:SI 1 "register_operand" "")
1921 (match_operand:SI 2 "register_operand" "")))
1922 (clobber (reg:SI 17))]
1923 "optimize_size"
1924 [(set (reg:SI 17)
1925 (lt:SI (match_dup 2)
1926 (match_dup 1)))
1927 (set (match_dup 0)
1928 (reg:SI 17))
1929 (set (match_dup 0)
1930 (plus:SI (match_dup 0)
1931 (const_int -1)))
1932 (set (match_dup 0)
1933 (neg:SI (match_dup 0)))]
1934 "")
1935
1936(define_expand "sgt"
1937 [(match_operand:SI 0 "register_operand" "")]
1938 ""
1939 "
1940{
1941 rtx op0 = operands[0];
1942 rtx op1 = m32r_compare_op0;
1943 rtx op2 = m32r_compare_op1;
1944 enum machine_mode mode = GET_MODE (op0);
1945
1946 if (mode != SImode)
1947 FAIL;
1948
1949 if (! register_operand (op1, mode))
1950 op1 = force_reg (mode, op1);
1951
1952 if (! register_operand (op2, mode))
1953 op2 = force_reg (mode, op2);
1954
1955 emit_insn (gen_slt_insn (op0, op2, op1));
1956 DONE;
1957}")
1958
1959(define_expand "sge"
1960 [(match_operand:SI 0 "register_operand" "")]
1961 ""
1962 "
1963{
1964 rtx op0 = operands[0];
1965 rtx op1 = m32r_compare_op0;
1966 rtx op2 = m32r_compare_op1;
1967 enum machine_mode mode = GET_MODE (op0);
1968
1969 if (mode != SImode)
1970 FAIL;
1971
1972 if (! register_operand (op1, mode))
1973 op1 = force_reg (mode, op1);
1974
1975 if (! reg_or_int16_operand (op2, mode))
1976 op2 = force_reg (mode, op2);
1977
1978 emit_insn (gen_sge_insn (op0, op1, op2));
1979 DONE;
1980}")
1981
1982(define_insn "sge_insn"
1983 [(set (match_operand:SI 0 "register_operand" "=r,r")
1984 (ge:SI (match_operand:SI 1 "register_operand" "r,r")
1985 (match_operand:SI 2 "reg_or_int16_operand" "r,J")))
1986 (clobber (reg:SI 17))]
1987 ""
1988 "#"
1989 [(set_attr "type" "multi")
1990 (set_attr "length" "8,10")])
1991
1992(define_split
1993 [(set (match_operand:SI 0 "register_operand" "")
1994 (ge:SI (match_operand:SI 1 "register_operand" "")
1995 (match_operand:SI 2 "reg_or_int16_operand" "")))
1996 (clobber (reg:SI 17))]
1997 "!optimize_size"
1998 [(set (reg:SI 17)
1999 (lt:SI (match_dup 1)
2000 (match_dup 2)))
2001 (set (match_dup 0)
2002 (reg:SI 17))
2003 (set (match_dup 0)
2004 (xor:SI (match_dup 0)
2005 (const_int 1)))]
2006 "")
2007
2008;; If optimizing for space, use -(reg - 1) to invert the comparison rather than
2009;; xor reg,reg,1 which might eliminate a NOP being inserted.
2010(define_split
2011 [(set (match_operand:SI 0 "register_operand" "")
2012 (ge:SI (match_operand:SI 1 "register_operand" "")
2013 (match_operand:SI 2 "reg_or_int16_operand" "")))
2014 (clobber (reg:SI 17))]
2015 "optimize_size"
2016 [(set (reg:SI 17)
2017 (lt:SI (match_dup 1)
2018 (match_dup 2)))
2019 (set (match_dup 0)
2020 (reg:SI 17))
2021 (set (match_dup 0)
2022 (plus:SI (match_dup 0)
2023 (const_int -1)))
2024 (set (match_dup 0)
2025 (neg:SI (match_dup 0)))]
2026 "")
2027
2028(define_expand "sltu"
2029 [(match_operand:SI 0 "register_operand" "")]
2030 ""
2031 "
2032{
2033 rtx op0 = operands[0];
2034 rtx op1 = m32r_compare_op0;
2035 rtx op2 = m32r_compare_op1;
2036 enum machine_mode mode = GET_MODE (op0);
2037
2038 if (mode != SImode)
2039 FAIL;
2040
2041 if (! register_operand (op1, mode))
2042 op1 = force_reg (mode, op1);
2043
2044 if (! reg_or_int16_operand (op2, mode))
2045 op2 = force_reg (mode, op2);
2046
2047 emit_insn (gen_sltu_insn (op0, op1, op2));
2048 DONE;
2049}")
2050
2051(define_insn "sltu_insn"
2052 [(set (match_operand:SI 0 "register_operand" "=r,r")
2053 (ltu:SI (match_operand:SI 1 "register_operand" "r,r")
2054 (match_operand:SI 2 "reg_or_int16_operand" "r,J")))
2055 (clobber (reg:SI 17))]
2056 ""
2057 "#"
2058 [(set_attr "type" "multi")
2059 (set_attr "length" "6,8")])
2060
2061(define_split
2062 [(set (match_operand:SI 0 "register_operand" "")
2063 (ltu:SI (match_operand:SI 1 "register_operand" "")
2064 (match_operand:SI 2 "reg_or_int16_operand" "")))
2065 (clobber (reg:SI 17))]
2066 ""
2067 [(set (reg:SI 17)
2068 (ltu:SI (match_dup 1)
2069 (match_dup 2)))
2070 (set (match_dup 0)
2071 (reg:SI 17))]
2072 "")
2073
2074(define_expand "sleu"
2075 [(match_operand:SI 0 "register_operand" "")]
2076 ""
2077 "
2078{
2079 rtx op0 = operands[0];
2080 rtx op1 = m32r_compare_op0;
2081 rtx op2 = m32r_compare_op1;
2082 enum machine_mode mode = GET_MODE (op0);
2083
2084 if (mode != SImode)
2085 FAIL;
2086
2087 if (GET_CODE (op2) == CONST_INT)
2088 {
2089 HOST_WIDE_INT value = INTVAL (op2);
2090 if (value >= 2147483647)
2091 {
2092 emit_move_insn (op0, GEN_INT (1));
2093 DONE;
2094 }
2095
2096 op2 = GEN_INT (value+1);
2097 if (value < 0 || value >= 32767)
2098 op2 = force_reg (mode, op2);
2099
2100 emit_insn (gen_sltu_insn (op0, op1, op2));
2101 DONE;
2102 }
2103
2104 if (! register_operand (op2, mode))
2105 op2 = force_reg (mode, op2);
2106
2107 emit_insn (gen_sleu_insn (op0, op1, op2));
2108 DONE;
2109}")
2110
2111(define_insn "sleu_insn"
2112 [(set (match_operand:SI 0 "register_operand" "=r")
2113 (leu:SI (match_operand:SI 1 "register_operand" "r")
2114 (match_operand:SI 2 "register_operand" "r")))
2115 (clobber (reg:SI 17))]
2116 ""
2117 "#"
2118 [(set_attr "type" "multi")
2119 (set_attr "length" "8")])
2120
2121(define_split
2122 [(set (match_operand:SI 0 "register_operand" "")
2123 (leu:SI (match_operand:SI 1 "register_operand" "")
2124 (match_operand:SI 2 "register_operand" "")))
2125 (clobber (reg:SI 17))]
2126 "!optimize_size"
2127 [(set (reg:SI 17)
2128 (ltu:SI (match_dup 2)
2129 (match_dup 1)))
2130 (set (match_dup 0)
2131 (reg:SI 17))
2132 (set (match_dup 0)
2133 (xor:SI (match_dup 0)
2134 (const_int 1)))]
2135 "")
2136
2137;; If optimizing for space, use -(reg - 1) to invert the comparison rather than
2138;; xor reg,reg,1 which might eliminate a NOP being inserted.
2139(define_split
2140 [(set (match_operand:SI 0 "register_operand" "")
2141 (leu:SI (match_operand:SI 1 "register_operand" "")
2142 (match_operand:SI 2 "register_operand" "")))
2143 (clobber (reg:SI 17))]
2144 "optimize_size"
2145 [(set (reg:SI 17)
2146 (ltu:SI (match_dup 2)
2147 (match_dup 1)))
2148 (set (match_dup 0)
2149 (reg:SI 17))
2150 (set (match_dup 0)
2151 (plus:SI (match_dup 0)
2152 (const_int -1)))
2153 (set (match_dup 0)
2154 (neg:SI (match_dup 0)))]
2155 "")
2156
2157(define_expand "sgtu"
2158 [(match_operand:SI 0 "register_operand" "")]
2159 ""
2160 "
2161{
2162 rtx op0 = operands[0];
2163 rtx op1 = m32r_compare_op0;
2164 rtx op2 = m32r_compare_op1;
2165 enum machine_mode mode = GET_MODE (op0);
2166
2167 if (mode != SImode)
2168 FAIL;
2169
2170 if (! register_operand (op1, mode))
2171 op1 = force_reg (mode, op1);
2172
2173 if (! register_operand (op2, mode))
2174 op2 = force_reg (mode, op2);
2175
2176 emit_insn (gen_sltu_insn (op0, op2, op1));
2177 DONE;
2178}")
2179
2180(define_expand "sgeu"
2181 [(match_operand:SI 0 "register_operand" "")]
2182 ""
2183 "
2184{
2185 rtx op0 = operands[0];
2186 rtx op1 = m32r_compare_op0;
2187 rtx op2 = m32r_compare_op1;
2188 enum machine_mode mode = GET_MODE (op0);
2189
2190 if (mode != SImode)
2191 FAIL;
2192
2193 if (! register_operand (op1, mode))
2194 op1 = force_reg (mode, op1);
2195
2196 if (! reg_or_int16_operand (op2, mode))
2197 op2 = force_reg (mode, op2);
2198
2199 emit_insn (gen_sgeu_insn (op0, op1, op2));
2200 DONE;
2201}")
2202
2203(define_insn "sgeu_insn"
2204 [(set (match_operand:SI 0 "register_operand" "=r,r")
2205 (geu:SI (match_operand:SI 1 "register_operand" "r,r")
2206 (match_operand:SI 2 "reg_or_int16_operand" "r,J")))
2207 (clobber (reg:SI 17))]
2208 ""
2209 "#"
2210 [(set_attr "type" "multi")
2211 (set_attr "length" "8,10")])
2212
2213(define_split
2214 [(set (match_operand:SI 0 "register_operand" "")
2215 (geu:SI (match_operand:SI 1 "register_operand" "")
2216 (match_operand:SI 2 "reg_or_int16_operand" "")))
2217 (clobber (reg:SI 17))]
2218 "!optimize_size"
2219 [(set (reg:SI 17)
2220 (ltu:SI (match_dup 1)
2221 (match_dup 2)))
2222 (set (match_dup 0)
2223 (reg:SI 17))
2224 (set (match_dup 0)
2225 (xor:SI (match_dup 0)
2226 (const_int 1)))]
2227 "")
2228
2229;; If optimizing for space, use -(reg - 1) to invert the comparison rather than
2230;; xor reg,reg,1 which might eliminate a NOP being inserted.
2231(define_split
2232 [(set (match_operand:SI 0 "register_operand" "")
2233 (geu:SI (match_operand:SI 1 "register_operand" "")
2234 (match_operand:SI 2 "reg_or_int16_operand" "")))
2235 (clobber (reg:SI 17))]
2236 "optimize_size"
2237 [(set (reg:SI 17)
2238 (ltu:SI (match_dup 1)
2239 (match_dup 2)))
2240 (set (match_dup 0)
2241 (reg:SI 17))
2242 (set (match_dup 0)
2243 (plus:SI (match_dup 0)
2244 (const_int -1)))
2245 (set (match_dup 0)
2246 (neg:SI (match_dup 0)))]
2247 "")
2248
2249(define_insn "movcc_insn"
2250 [(set (match_operand:SI 0 "register_operand" "=r")
2251 (reg:SI 17))]
2252 ""
2253 "mvfc %0, cbr"
2254 [(set_attr "type" "misc")
2255 (set_attr "length" "2")])
2256
2257\f
8c5ca3b9
DE
2258;; Unconditional and other jump instructions.
2259
2260(define_insn "jump"
2261 [(set (pc) (label_ref (match_operand 0 "" "")))]
2262 ""
2263 "bra %l0"
2264 [(set_attr "type" "uncond_branch")
2265 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
2266 (const_int 400))
2267 (const_int 800))
2268 (const_int 2)
2269 (const_int 4)))])
2270
2271(define_insn "indirect_jump"
2272 [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
2273 ""
2274 "jmp %a0"
2275 [(set_attr "type" "uncond_branch")
2276 (set_attr "length" "2")])
56e2e762
NC
2277
2278(define_insn "return"
2279 [(return)]
2280 "direct_return ()"
2281 "jmp lr"
2282 [(set_attr "type" "uncond_branch")
2283 (set_attr "length" "2")])
8c5ca3b9
DE
2284
2285(define_insn "tablejump"
2286 [(set (pc) (match_operand:SI 0 "address_operand" "p"))
2287 (use (label_ref (match_operand 1 "" "")))]
2288 ""
2289 "jmp %a0"
2290 [(set_attr "type" "uncond_branch")
2291 (set_attr "length" "2")])
2292
2293(define_expand "call"
2294 ;; operands[1] is stack_size_rtx
2295 ;; operands[2] is next_arg_register
2296 [(parallel [(call (match_operand:SI 0 "call_operand" "")
2297 (match_operand 1 "" ""))
2298 (clobber (reg:SI 14))])]
2299 ""
2300 "")
2301
2302(define_insn "*call_via_reg"
2303 [(call (mem:SI (match_operand:SI 0 "register_operand" "r"))
2304 (match_operand 1 "" ""))
2305 (clobber (reg:SI 14))]
2306 ""
2307 "jl %0"
2308 [(set_attr "type" "call")
2309 (set_attr "length" "2")])
2310
2311(define_insn "*call_via_label"
2312 [(call (mem:SI (match_operand:SI 0 "call_address_operand" ""))
2313 (match_operand 1 "" ""))
2314 (clobber (reg:SI 14))]
2315 ""
2316 "*
2317{
2318 int call26_p = call26_operand (operands[0], FUNCTION_MODE);
2319
2320 if (! call26_p)
2321 {
2322 /* We may not be able to reach with a `bl' insn so punt and leave it to
2323 the linker.
2324 We do this here, rather than doing a force_reg in the define_expand
2325 so these insns won't be separated, say by scheduling, thus simplifying
2326 the linker. */
2327 return \"seth r14,%T0\;add3 r14,r14,%B0\;jl r14\";
2328 }
2329 else
2330 return \"bl %0\";
2331}"
2332 [(set_attr "type" "call")
2333 (set (attr "length")
2334 (if_then_else (eq (symbol_ref "call26_operand (operands[0], FUNCTION_MODE)")
2335 (const_int 0))
2336 (const_int 12) ; 10 + 2 for nop filler
2337 ; The return address must be on a 4 byte boundary so
2338 ; there's no point in using a value of 2 here. A 2 byte
2339 ; insn may go in the left slot but we currently can't
2340 ; use such knowledge.
2341 (const_int 4)))])
2342
2343(define_expand "call_value"
2344 ;; operand 2 is stack_size_rtx
2345 ;; operand 3 is next_arg_register
2346 [(parallel [(set (match_operand 0 "register_operand" "=r")
2347 (call (match_operand:SI 1 "call_operand" "")
2348 (match_operand 2 "" "")))
2349 (clobber (reg:SI 14))])]
2350 ""
2351 "")
2352
2353(define_insn "*call_value_via_reg"
2354 [(set (match_operand 0 "register_operand" "=r")
2355 (call (mem:SI (match_operand:SI 1 "register_operand" "r"))
2356 (match_operand 2 "" "")))
2357 (clobber (reg:SI 14))]
2358 ""
2359 "jl %1"
2360 [(set_attr "type" "call")
2361 (set_attr "length" "2")])
2362
2363(define_insn "*call_value_via_label"
2364 [(set (match_operand 0 "register_operand" "=r")
2365 (call (mem:SI (match_operand:SI 1 "call_address_operand" ""))
2366 (match_operand 2 "" "")))
2367 (clobber (reg:SI 14))]
2368 ""
2369 "*
2370{
2371 int call26_p = call26_operand (operands[1], FUNCTION_MODE);
2372
2373 if (! call26_p)
2374 {
2375 /* We may not be able to reach with a `bl' insn so punt and leave it to
2376 the linker.
2377 We do this here, rather than doing a force_reg in the define_expand
2378 so these insns won't be separated, say by scheduling, thus simplifying
2379 the linker. */
2380 return \"seth r14,%T1\;add3 r14,r14,%B1\;jl r14\";
2381 }
2382 else
2383 return \"bl %1\";
2384}"
2385 [(set_attr "type" "call")
2386 (set (attr "length")
2387 (if_then_else (eq (symbol_ref "call26_operand (operands[1], FUNCTION_MODE)")
2388 (const_int 0))
2389 (const_int 12) ; 10 + 2 for nop filler
2390 ; The return address must be on a 4 byte boundary so
2391 ; there's no point in using a value of 2 here. A 2 byte
2392 ; insn may go in the left slot but we currently can't
2393 ; use such knowledge.
2394 (const_int 4)))])
2395\f
2396(define_insn "nop"
2397 [(const_int 0)]
2398 ""
2399 "nop"
5b8ae21f 2400 [(set_attr "type" "int2")
8c5ca3b9
DE
2401 (set_attr "length" "2")])
2402
2403;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
2404;; all of memory. This blocks insns from being moved across this point.
2405
2406(define_insn "blockage"
2407 [(unspec_volatile [(const_int 0)] 0)]
2408 ""
2409 "")
2410
2411;; Special pattern to flush the icache.
2412
2413(define_insn "flush_icache"
2414 [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)]
2415 ""
2416 "* return \"nop ; flush-icache\";"
5b8ae21f
MM
2417 [(set_attr "type" "int2")
2418 (set_attr "length" "2")])
2b7972b0 2419\f
56e2e762
NC
2420;; Speed up fabs and provide correct sign handling for -0
2421
2422(define_insn "absdf2"
2423 [(set (match_operand:DF 0 "register_operand" "=r")
2424 (abs:DF (match_operand:DF 1 "register_operand" "0")))]
2425 ""
2426 "#"
2427 [(set_attr "type" "multi")
2428 (set_attr "length" "4")])
2429
2430(define_split
2431 [(set (match_operand:DF 0 "register_operand" "")
2432 (abs:DF (match_operand:DF 1 "register_operand" "")))]
2433 "reload_completed"
2434 [(set (match_dup 2)
2435 (ashift:SI (match_dup 2)
2436 (const_int 1)))
2437 (set (match_dup 2)
2438 (lshiftrt:SI (match_dup 2)
2439 (const_int 1)))]
2440 "operands[2] = gen_highpart (SImode, operands[0]);")
2441
2442(define_insn "abssf2"
2443 [(set (match_operand:SF 0 "register_operand" "=r")
2444 (abs:SF (match_operand:SF 1 "register_operand" "0")))]
2445 ""
2446 "#"
2447 [(set_attr "type" "multi")
2448 (set_attr "length" "4")])
2449
2450(define_split
2451 [(set (match_operand:SF 0 "register_operand" "")
2452 (abs:SF (match_operand:SF 1 "register_operand" "")))]
2453 "reload_completed"
2454 [(set (match_dup 2)
2455 (ashift:SI (match_dup 2)
2456 (const_int 1)))
2457 (set (match_dup 2)
2458 (lshiftrt:SI (match_dup 2)
2459 (const_int 1)))]
2460 "operands[2] = gen_highpart (SImode, operands[0]);")
2461\f
2b7972b0
MM
2462;; Conditional move instructions
2463;; Based on those done for the d10v
2464
2b7972b0
MM
2465(define_expand "movsicc"
2466 [
2467 (set (match_operand:SI 0 "register_operand" "r")
2468 (if_then_else:SI (match_operand 1 "" "")
2469 (match_operand:SI 2 "conditional_move_operand" "O")
2470 (match_operand:SI 3 "conditional_move_operand" "O")
2471 )
2472 )
2473 ]
2474 ""
2475 "
2476{
2477 if (! zero_and_one (operands [2], operands [3]))
2478 FAIL;
2479
2480 /* Generate the comparision that will set the carry flag. */
56e2e762 2481 operands[1] = gen_compare (GET_CODE (operands[1]), m32r_compare_op0,
2b7972b0
MM
2482 m32r_compare_op1, TRUE);
2483
2484 /* See other movsicc pattern below for reason why. */
56e2e762 2485 emit_insn (gen_blockage ());
2b7972b0
MM
2486}")
2487
2488;; Generate the conditional instructions based on how the carry flag is examined.
2489(define_insn "*movsicc_internal"
997718c7 2490 [(set (match_operand:SI 0 "register_operand" "=r")
2b7972b0
MM
2491 (if_then_else:SI (match_operand 1 "carry_compare_operand" "")
2492 (match_operand:SI 2 "conditional_move_operand" "O")
2493 (match_operand:SI 3 "conditional_move_operand" "O")
2494 )
2495 )]
2496 "zero_and_one (operands [2], operands[3])"
2497 "* return emit_cond_move (operands, insn);"
5b8ae21f 2498 [(set_attr "type" "multi")
2b7972b0
MM
2499 (set_attr "length" "8")
2500 ]
2501)
2502
8c5ca3b9
DE
2503\f
2504;; Split up troublesome insns for better scheduling.
56e2e762 2505;; FIXME: Peepholes go at the end.
8c5ca3b9
DE
2506
2507;; ??? Setting the type attribute may not be useful, but for completeness
2508;; we do it.
2509
2510(define_peephole
2511 [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
2512 (const_int 4)))
2513 (match_operand:SI 1 "register_operand" "r"))]
5b8ae21f 2514 "0 && dead_or_set_p (insn, operands[0])"
8c5ca3b9 2515 "st %1,@+%0"
5b8ae21f 2516 [(set_attr "type" "store2")
8c5ca3b9 2517 (set_attr "length" "2")])
2b7972b0
MM
2518
2519;; This case is triggered by compiling this code:
2520;;
2521;; extern void sub(int *);
2522;; void main (void)
2523;; {
2524;; int i=2,j=3,k;
2525;; while (i < j) sub(&k);
2526;; i = j / k;
2527;; sub(&i);
2528;; i = j - k;
2529;; sub(&i);
2530;; }
2531;;
2532;; Without the peephole the following assembler is generated for the
2533;; divide and subtract expressions:
2534;;
2535;; div r5,r4
2536;; mv r4,r5
2537;; st r4,@(4,sp)
2538;; bl sub
2539;;
2540;; Simialr code is produced for the subtract expression. With this
2541;; peephole the redundant move is eliminated.
2542;;
2543;; This optimisation onbly works if PRESERVE_DEATH_INFO_REGNO_P is
2544;; defined in m32r.h
2545
2546(define_peephole
2547 [(set (match_operand:SI 0 "register_operand" "r")
2548 (match_operand:SI 1 "register_operand" "r")
2549 )
2550 (set (mem:SI (plus: SI (match_operand:SI 2 "register_operand" "r")
2551 (match_operand:SI 3 "immediate_operand" "J")))
2552 (match_dup 0)
2553 )
2554 ]
5b8ae21f 2555 "0 && dead_or_set_p (insn, operands [0])"
2b7972b0 2556 "st %1,@(%3,%2)"
5b8ae21f 2557 [(set_attr "type" "store4")
2b7972b0
MM
2558 (set_attr "length" "4")
2559 ]
2560)
d2a73f8e
NC
2561
2562;; Block moves, see m32r.c for more details.
2563;; Argument 0 is the destination
2564;; Argument 1 is the source
2565;; Argument 2 is the length
2566;; Argument 3 is the alignment
2567
2568(define_expand "movstrsi"
2569 [(parallel [(set (match_operand:BLK 0 "general_operand" "")
2570 (match_operand:BLK 1 "general_operand" ""))
2571 (use (match_operand:SI 2 "immediate_operand" ""))
2572 (use (match_operand:SI 3 "immediate_operand" ""))])]
2573 ""
2574 "
2575{
2576 if (operands[0]) /* avoid unused code messages */
2577 {
2578 m32r_expand_block_move (operands);
2579 DONE;
2580 }
2581}")
2582
2583;; Insn generated by block moves
2584
2585(define_insn "movstrsi_internal"
997718c7
RH
2586 [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r")) ;; destination
2587 (mem:BLK (match_operand:SI 1 "register_operand" "+r"))) ;; source
d2a73f8e 2588 (use (match_operand:SI 2 "m32r_block_immediate_operand" "J"));; # bytes to move
6970d948
NC
2589 (set (match_dup 0) (plus:SI (match_dup 0) (minus:SI (match_dup 2) (const_int 4))))
2590 (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))
d2a73f8e 2591 (clobber (match_scratch:SI 3 "=&r")) ;; temp 1
6970d948 2592 (clobber (match_scratch:SI 4 "=&r"))] ;; temp 2
d2a73f8e 2593 ""
16f104b3 2594 "* m32r_output_block_move (insn, operands); return \"\"; "
d2a73f8e
NC
2595 [(set_attr "type" "store8")
2596 (set_attr "length" "72")]) ;; Maximum
This page took 0.980156 seconds and 5 git commands to generate.