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