1;; Machine description of the Renesas M32R cpu for GNU C compiler 2;; Copyright (C) 1996-2021 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 it 7;; under the terms of the GNU General Public License as published 8;; by the Free Software Foundation; either version 3, or (at your 9;; option) any later version. 10 11;; GCC is distributed in the hope that it will be useful, but WITHOUT 12;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14;; 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 COPYING3. If not see 18;; <http://www.gnu.org/licenses/>. 19 20;; See file "rtl.def" for documentation on define_insn, match_*, et. al. 21 22;; UNSPEC_VOLATILE usage 23(define_constants 24 [(UNSPECV_BLOCKAGE 0) 25 (UNSPECV_FLUSH_ICACHE 1)]) 26 27;; UNSPEC usage 28(define_constants 29 [(UNSPEC_LOAD_SDA_BASE 2) 30 (UNSPEC_SET_CBIT 3) 31 (UNSPEC_PIC_LOAD_ADDR 4) 32 (UNSPEC_GET_PC 5) 33 (UNSPEC_GOTOFF 6) 34 ]) 35 36;; Insn type. Used to default other attribute values. 37(define_attr "type" 38 "int2,int4,load2,load4,load8,store2,store4,store8,shift2,shift4,mul2,div4,uncond_branch,branch,call,multi,misc" 39 (const_string "misc")) 40 41;; Length in bytes. 42(define_attr "length" "" 43 (cond [(eq_attr "type" "int2,load2,store2,shift2,mul2") 44 (const_int 2) 45 46 (eq_attr "type" "int4,load4,store4,shift4,div4") 47 (const_int 4) 48 49 (eq_attr "type" "multi") 50 (const_int 8) 51 52 (eq_attr "type" "uncond_branch,branch,call") 53 (const_int 4)] 54 55 (const_int 4))) 56 57;; The length here is the length of a single asm. Unfortunately it might be 58;; 2 or 4 so we must allow for 4. That's ok though. 59(define_asm_attributes 60 [(set_attr "length" "4") 61 (set_attr "type" "multi")]) 62 63;; Whether an instruction is short (16-bit) or long (32-bit). 64(define_attr "insn_size" "short,long" 65 (if_then_else (eq_attr "type" "int2,load2,store2,shift2,mul2") 66 (const_string "short") 67 (const_string "long"))) 68 69;; The target CPU we're compiling for. 70(define_attr "cpu" "m32r,m32r2,m32rx" 71 (cond [(match_test "TARGET_M32RX") 72 (const_string "m32rx") 73 (match_test "TARGET_M32R2") 74 (const_string "m32r2")] 75 (const_string "m32r"))) 76 77;; Defines the pipeline where an instruction can be executed on. 78;; For the M32R, a short instruction can execute one of the two pipes. 79;; For the M32Rx, the restrictions are modelled in the second 80;; condition of this attribute definition. 81(define_attr "m32r_pipeline" "either,s,o,long" 82 (cond [(and (eq_attr "cpu" "m32r") 83 (eq_attr "insn_size" "short")) 84 (const_string "either") 85 (eq_attr "insn_size" "!short") 86 (const_string "long")] 87 (cond [(eq_attr "type" "int2") 88 (const_string "either") 89 (eq_attr "type" "load2,store2,shift2,uncond_branch,branch,call") 90 (const_string "o") 91 (eq_attr "type" "mul2") 92 (const_string "s")] 93 (const_string "long")))) 94 95;; :::::::::::::::::::: 96;; :: 97;; :: Pipeline description 98;; :: 99;; :::::::::::::::::::: 100 101;; This model is based on Chapter 2, Appendix 3 and Appendix 4 of the 102;; "M32R-FPU Software Manual", Revision 1.01, plus additional information 103;; obtained by our best friend and mine, Google. 104;; 105;; The pipeline is modelled as a fetch unit, and a core with a memory unit, 106;; two execution units, where "fetch" models IF and D, "memory" for MEM1 107;; and MEM2, and "EXEC" for E, E1, E2, EM, and EA. Writeback and 108;; bypasses are not modelled. 109(define_automaton "m32r") 110 111;; We pretend there are two short (16 bits) instruction fetchers. The 112;; "s" short fetcher cannot be reserved until the "o" short fetcher is 113;; reserved. Some instructions reserve both the left and right fetchers. 114;; These fetch units are a hack to get GCC to better pack the instructions 115;; for the M32Rx processor, which has two execution pipes. 116;; 117;; In reality there is only one decoder, which can decode either two 16-bit 118;; instructions, or a single 32-bit instruction. 119;; 120;; Note, "fetch" models both the IF and the D pipeline stages. 121;; 122;; The m32rx core has two execution pipes. We name them o_E and s_E. 123;; In addition, there's a memory unit. 124 125(define_cpu_unit "o_IF,s_IF,o_E,s_E,memory" "m32r") 126 127;; Prevent the s pipe from being reserved before the o pipe. 128(absence_set "s_IF" "o_IF") 129(absence_set "s_E" "o_E") 130 131;; On the M32Rx, long instructions execute on both pipes, so reserve 132;; both fetch slots and both pipes. 133(define_reservation "long_IF" "o_IF+s_IF") 134(define_reservation "long_E" "o_E+s_E") 135 136;; :::::::::::::::::::: 137 138;; Simple instructions do 4 stages: IF D E WB. WB is not modelled. 139;; Hence, ready latency is 1. 140(define_insn_reservation "short_left" 1 141 (and (eq_attr "m32r_pipeline" "o") 142 (and (eq_attr "insn_size" "short") 143 (eq_attr "type" "!load2"))) 144 "o_IF,o_E") 145 146(define_insn_reservation "short_right" 1 147 (and (eq_attr "m32r_pipeline" "s") 148 (and (eq_attr "insn_size" "short") 149 (eq_attr "type" "!load2"))) 150 "s_IF,s_E") 151 152(define_insn_reservation "short_either" 1 153 (and (eq_attr "m32r_pipeline" "either") 154 (and (eq_attr "insn_size" "short") 155 (eq_attr "type" "!load2"))) 156 "o_IF|s_IF,o_E|s_E") 157 158(define_insn_reservation "long_m32r" 1 159 (and (eq_attr "cpu" "m32r") 160 (and (eq_attr "insn_size" "long") 161 (eq_attr "type" "!load4,load8"))) 162 "long_IF,long_E") 163 164(define_insn_reservation "long_m32rx" 2 165 (and (eq_attr "m32r_pipeline" "long") 166 (and (eq_attr "insn_size" "long") 167 (eq_attr "type" "!load4,load8"))) 168 "long_IF,long_E") 169 170;; Load/store instructions do 6 stages: IF D E MEM1 MEM2 WB. 171;; MEM1 may require more than one cycle depending on locality. We 172;; optimistically assume all memory is nearby, i.e. MEM1 takes only 173;; one cycle. Hence, ready latency is 3. 174 175;; The M32Rx can do short load/store only on the left pipe. 176(define_insn_reservation "short_load_left" 3 177 (and (eq_attr "m32r_pipeline" "o") 178 (and (eq_attr "insn_size" "short") 179 (eq_attr "type" "load2"))) 180 "o_IF,o_E,memory*2") 181 182(define_insn_reservation "short_load" 3 183 (and (eq_attr "m32r_pipeline" "either") 184 (and (eq_attr "insn_size" "short") 185 (eq_attr "type" "load2"))) 186 "s_IF|o_IF,s_E|o_E,memory*2") 187 188(define_insn_reservation "long_load" 3 189 (and (eq_attr "cpu" "m32r") 190 (and (eq_attr "insn_size" "long") 191 (eq_attr "type" "load4,load8"))) 192 "long_IF,long_E,memory*2") 193 194(define_insn_reservation "long_load_m32rx" 3 195 (and (eq_attr "m32r_pipeline" "long") 196 (eq_attr "type" "load4,load8")) 197 "long_IF,long_E,memory*2") 198 199 200(include "predicates.md") 201(include "constraints.md") 202 203;; Expand prologue as RTL 204(define_expand "prologue" 205 [(const_int 1)] 206 "" 207 " 208{ 209 m32r_expand_prologue (); 210 DONE; 211}") 212 213;; Expand epilogue as RTL 214(define_expand "epilogue" 215 [(return)] 216 "" 217 " 218{ 219 m32r_expand_epilogue (); 220 emit_jump_insn (gen_return_normal ()); 221 DONE; 222}") 223 224;; Move instructions. 225;; 226;; For QI and HI moves, the register must contain the full properly 227;; sign-extended value. nonzero_bits assumes this [otherwise 228;; SHORT_IMMEDIATES_SIGN_EXTEND must be used, but the comment for it 229;; says it's a kludge and the .md files should be fixed instead]. 230 231(define_expand "movqi" 232 [(set (match_operand:QI 0 "general_operand" "") 233 (match_operand:QI 1 "general_operand" ""))] 234 "" 235 " 236{ 237 /* Fixup PIC cases. */ 238 if (flag_pic) 239 { 240 if (symbolic_operand (operands[1], QImode)) 241 { 242 if (reload_in_progress || reload_completed) 243 operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); 244 else 245 operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); 246 } 247 } 248 249 /* Everything except mem = const or mem = mem can be done easily. 250 Objects in the small data area are handled too. */ 251 252 if (MEM_P (operands[0])) 253 operands[1] = force_reg (QImode, operands[1]); 254}") 255 256(define_insn "*movqi_insn" 257 [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,r,r,T,m") 258 (match_operand:QI 1 "move_src_operand" "r,I,JQR,T,m,r,r"))] 259 "register_operand (operands[0], QImode) || register_operand (operands[1], QImode)" 260 "@ 261 mv %0,%1 262 ldi %0,%#%1 263 ldi %0,%#%1 264 ldub %0,%1 265 ldub %0,%1 266 stb %1,%0 267 stb %1,%0" 268 [(set_attr "type" "int2,int2,int4,load2,load4,store2,store4") 269 (set_attr "length" "2,2,4,2,4,2,4")]) 270 271(define_expand "movhi" 272 [(set (match_operand:HI 0 "general_operand" "") 273 (match_operand:HI 1 "general_operand" ""))] 274 "" 275 " 276{ 277 /* Fixup PIC cases. */ 278 if (flag_pic) 279 { 280 if (symbolic_operand (operands[1], HImode)) 281 { 282 if (reload_in_progress || reload_completed) 283 operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); 284 else 285 operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); 286 } 287 } 288 289 /* Everything except mem = const or mem = mem can be done easily. */ 290 291 if (MEM_P (operands[0])) 292 operands[1] = force_reg (HImode, operands[1]); 293}") 294 295(define_insn "*movhi_insn" 296 [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,r,r,r,T,m") 297 (match_operand:HI 1 "move_src_operand" "r,I,JQR,K,T,m,r,r"))] 298 "register_operand (operands[0], HImode) || register_operand (operands[1], HImode)" 299 "@ 300 mv %0,%1 301 ldi %0,%#%1 302 ldi %0,%#%1 303 ld24 %0,%#%1 304 lduh %0,%1 305 lduh %0,%1 306 sth %1,%0 307 sth %1,%0" 308 [(set_attr "type" "int2,int2,int4,int4,load2,load4,store2,store4") 309 (set_attr "length" "2,2,4,4,2,4,2,4")]) 310 311(define_expand "movsi_push" 312 [(set (mem:SI (pre_dec:SI (match_operand:SI 0 "register_operand" ""))) 313 (match_operand:SI 1 "register_operand" ""))] 314 "" 315 "") 316 317(define_expand "movsi_pop" 318 [(set (match_operand:SI 0 "register_operand" "") 319 (mem:SI (post_inc:SI (match_operand:SI 1 "register_operand" ""))))] 320 "" 321 "") 322 323(define_expand "movsi" 324 [(set (match_operand:SI 0 "general_operand" "") 325 (match_operand:SI 1 "general_operand" ""))] 326 "" 327 " 328{ 329 /* Fixup PIC cases. */ 330 if (flag_pic) 331 { 332 if (symbolic_operand (operands[1], SImode)) 333 { 334 if (reload_in_progress || reload_completed) 335 operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); 336 else 337 operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); 338 } 339 } 340 341 /* Everything except mem = const or mem = mem can be done easily. */ 342 343 if (MEM_P (operands[0])) 344 operands[1] = force_reg (SImode, operands[1]); 345 346 /* Small Data Area reference? */ 347 if (small_data_operand (operands[1], SImode)) 348 { 349 emit_insn (gen_movsi_sda (operands[0], operands[1])); 350 DONE; 351 } 352 353 /* If medium or large code model, symbols have to be loaded with 354 seth/add3. */ 355 if (addr32_operand (operands[1], SImode)) 356 { 357 emit_insn (gen_movsi_addr32 (operands[0], operands[1])); 358 DONE; 359 } 360}") 361 362;; ??? Do we need a const_double constraint here for large unsigned values? 363(define_insn "*movsi_insn" 364 [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,r,r,r,r,r,r,T,S,m") 365 (match_operand:SI 1 "move_src_operand" "r,I,J,MQ,L,n,T,U,m,r,r,r"))] 366 "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)" 367 "* 368{ 369 if (REG_P (operands[0]) || GET_CODE (operands[1]) == SUBREG) 370 { 371 switch (GET_CODE (operands[1])) 372 { 373 default: 374 break; 375 376 case REG: 377 case SUBREG: 378 return \"mv %0,%1\"; 379 380 case MEM: 381 if (GET_CODE (XEXP (operands[1], 0)) == POST_INC 382 && XEXP (XEXP (operands[1], 0), 0) == stack_pointer_rtx) 383 return \"pop %0\"; 384 385 return \"ld %0,%1\"; 386 387 case CONST_INT: 388 if (satisfies_constraint_J (operands[1])) 389 return \"ldi %0,%#%1\\t; %X1\"; 390 391 if (satisfies_constraint_M (operands[1])) 392 return \"ld24 %0,%#%1\\t; %X1\"; 393 394 if (satisfies_constraint_L (operands[1])) 395 return \"seth %0,%#%T1\\t; %X1\"; 396 397 return \"#\"; 398 399 case CONST: 400 case SYMBOL_REF: 401 case LABEL_REF: 402 if (TARGET_ADDR24) 403 return \"ld24 %0,%#%1\"; 404 405 return \"#\"; 406 } 407 } 408 409 else if (MEM_P (operands[0]) 410 && (REG_P (operands[1]) || GET_CODE (operands[1]) == SUBREG)) 411 { 412 if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC 413 && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx) 414 return \"push %1\"; 415 416 return \"st %1,%0\"; 417 } 418 419 gcc_unreachable (); 420}" 421 [(set_attr "type" "int2,int2,int4,int4,int4,multi,load2,load2,load4,store2,store2,store4") 422 (set_attr "length" "2,2,4,4,4,8,2,2,4,2,2,4")]) 423 424; Try to use a four byte / two byte pair for constants not loadable with 425; ldi, ld24, seth. 426 427(define_split 428 [(set (match_operand:SI 0 "register_operand" "") 429 (match_operand:SI 1 "two_insn_const_operand" ""))] 430 "" 431 [(set (match_dup 0) (match_dup 2)) 432 (set (match_dup 0) (ior:SI (match_dup 0) (match_dup 3)))] 433 " 434{ 435 unsigned HOST_WIDE_INT val = INTVAL (operands[1]); 436 unsigned HOST_WIDE_INT tmp; 437 int shift; 438 439 /* In all cases we will emit two instructions. However we try to 440 use 2 byte instructions wherever possible. We can assume the 441 constant isn't loadable with any of ldi, ld24, or seth. */ 442 443 /* See if we can load a 24-bit unsigned value and invert it. */ 444 if (UINT24_P (~ val)) 445 { 446 emit_insn (gen_movsi (operands[0], GEN_INT (~ val))); 447 emit_insn (gen_one_cmplsi2 (operands[0], operands[0])); 448 DONE; 449 } 450 451 /* See if we can load a 24-bit unsigned value and shift it into place. 452 0x01fffffe is just beyond ld24's range. */ 453 for (shift = 1, tmp = 0x01fffffe; 454 shift < 8; 455 ++shift, tmp <<= 1) 456 { 457 if ((val & ~tmp) == 0) 458 { 459 emit_insn (gen_movsi (operands[0], GEN_INT (val >> shift))); 460 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (shift))); 461 DONE; 462 } 463 } 464 465 /* Can't use any two byte insn, fall back to seth/or3. Use ~0xffff instead 466 of 0xffff0000, since the later fails on a 64-bit host. */ 467 operands[2] = GEN_INT ((val) & ~0xffff); 468 operands[3] = GEN_INT ((val) & 0xffff); 469}") 470 471(define_split 472 [(set (match_operand:SI 0 "register_operand" "") 473 (match_operand:SI 1 "seth_add3_operand" ""))] 474 "TARGET_ADDR32" 475 [(set (match_dup 0) 476 (high:SI (match_dup 1))) 477 (set (match_dup 0) 478 (lo_sum:SI (match_dup 0) 479 (match_dup 1)))] 480 "") 481 482;; Small data area support. 483;; The address of _SDA_BASE_ is loaded into a register and all objects in 484;; the small data area are indexed off that. This is done for each reference 485;; but cse will clean things up for us. We let the compiler choose the 486;; register to use so we needn't allocate (and maybe even fix) a special 487;; register to use. Since the load and store insns have a 16-bit offset the 488;; total size of the data area can be 64K. However, if the data area lives 489;; above 16M (24 bits), _SDA_BASE_ will have to be loaded with seth/add3 which 490;; would then yield 3 instructions to reference an object [though there would 491;; be no net loss if two or more objects were referenced]. The 3 insns can be 492;; reduced back to 2 if the size of the small data area were reduced to 32K 493;; [then seth + ld/st would work for any object in the area]. Doing this 494;; would require special handling of _SDA_BASE_ (its value would be 495;; (.sdata + 32K) & 0xffff0000) and reloc computations would be different 496;; [I think]. What to do about this is deferred until later and for now we 497;; require .sdata to be in the first 16M. 498 499(define_expand "movsi_sda" 500 [(set (match_dup 2) 501 (unspec:SI [(const_int 0)] UNSPEC_LOAD_SDA_BASE)) 502 (set (match_operand:SI 0 "register_operand" "") 503 (lo_sum:SI (match_dup 2) 504 (match_operand:SI 1 "small_data_operand" "")))] 505 "" 506 " 507{ 508 if (reload_in_progress || reload_completed) 509 operands[2] = operands[0]; 510 else 511 operands[2] = gen_reg_rtx (SImode); 512}") 513 514(define_insn "*load_sda_base_32" 515 [(set (match_operand:SI 0 "register_operand" "=r") 516 (unspec:SI [(const_int 0)] UNSPEC_LOAD_SDA_BASE))] 517 "TARGET_ADDR32" 518 "seth %0,%#shigh(_SDA_BASE_)\;add3 %0,%0,%#low(_SDA_BASE_)" 519 [(set_attr "type" "multi") 520 (set_attr "length" "8")]) 521 522(define_insn "*load_sda_base" 523 [(set (match_operand:SI 0 "register_operand" "=r") 524 (unspec:SI [(const_int 0)] UNSPEC_LOAD_SDA_BASE))] 525 "" 526 "ld24 %0,#_SDA_BASE_" 527 [(set_attr "type" "int4") 528 (set_attr "length" "4")]) 529 530;; 32-bit address support. 531 532(define_expand "movsi_addr32" 533 [(set (match_dup 2) 534 ; addr32_operand isn't used because it's too restrictive, 535 ; seth_add3_operand is more general and thus safer. 536 (high:SI (match_operand:SI 1 "seth_add3_operand" ""))) 537 (set (match_operand:SI 0 "register_operand" "") 538 (lo_sum:SI (match_dup 2) (match_dup 1)))] 539 "" 540 " 541{ 542 if (reload_in_progress || reload_completed) 543 operands[2] = operands[0]; 544 else 545 operands[2] = gen_reg_rtx (SImode); 546}") 547 548(define_insn "set_hi_si" 549 [(set (match_operand:SI 0 "register_operand" "=r") 550 (high:SI (match_operand 1 "symbolic_operand" "")))] 551 "" 552 "seth %0,%#shigh(%1)" 553 [(set_attr "type" "int4") 554 (set_attr "length" "4")]) 555 556(define_insn "lo_sum_si" 557 [(set (match_operand:SI 0 "register_operand" "=r") 558 (lo_sum:SI (match_operand:SI 1 "register_operand" "r") 559 (match_operand:SI 2 "immediate_operand" "in")))] 560 "" 561 "add3 %0,%1,%#%B2" 562 [(set_attr "type" "int4") 563 (set_attr "length" "4")]) 564 565(define_expand "movdi" 566 [(set (match_operand:DI 0 "general_operand" "") 567 (match_operand:DI 1 "general_operand" ""))] 568 "" 569 " 570{ 571 /* Fixup PIC cases. */ 572 if (flag_pic) 573 { 574 if (symbolic_operand (operands[1], DImode)) 575 { 576 if (reload_in_progress || reload_completed) 577 operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); 578 else 579 operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); 580 } 581 } 582 583 /* Everything except mem = const or mem = mem can be done easily. */ 584 585 if (MEM_P (operands[0])) 586 operands[1] = force_reg (DImode, operands[1]); 587}") 588 589(define_insn "*movdi_insn" 590 [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,r,m") 591 (match_operand:DI 1 "move_double_src_operand" "r,nG,F,m,r"))] 592 "register_operand (operands[0], DImode) || register_operand (operands[1], DImode)" 593 "#" 594 [(set_attr "type" "multi,multi,multi,load8,store8") 595 (set_attr "length" "4,4,16,6,6")]) 596 597(define_split 598 [(set (match_operand:DI 0 "move_dest_operand" "") 599 (match_operand:DI 1 "move_double_src_operand" ""))] 600 "reload_completed" 601 [(match_dup 2)] 602 "operands[2] = gen_split_move_double (operands);") 603 604;; Floating point move insns. 605 606(define_expand "movsf" 607 [(set (match_operand:SF 0 "general_operand" "") 608 (match_operand:SF 1 "general_operand" ""))] 609 "" 610 " 611{ 612 /* Fixup PIC cases. */ 613 if (flag_pic) 614 { 615 if (symbolic_operand (operands[1], SFmode)) 616 { 617 if (reload_in_progress || reload_completed) 618 operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); 619 else 620 operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); 621 } 622 } 623 624 /* Everything except mem = const or mem = mem can be done easily. */ 625 626 if (MEM_P (operands[0])) 627 operands[1] = force_reg (SFmode, operands[1]); 628}") 629 630(define_insn "*movsf_insn" 631 [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,r,r,T,S,m") 632 (match_operand:SF 1 "move_src_operand" "r,F,U,S,m,r,r,r"))] 633 "register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode)" 634 "@ 635 mv %0,%1 636 # 637 ld %0,%1 638 ld %0,%1 639 ld %0,%1 640 st %1,%0 641 st %1,%0 642 st %1,%0" 643 ;; ??? Length of alternative 1 is either 2, 4 or 8. 644 [(set_attr "type" "int2,multi,load2,load2,load4,store2,store2,store4") 645 (set_attr "length" "2,8,2,2,4,2,2,4")]) 646 647(define_split 648 [(set (match_operand:SF 0 "register_operand" "") 649 (match_operand:SF 1 "const_double_operand" ""))] 650 "reload_completed" 651 [(set (match_dup 2) (match_dup 3))] 652 " 653{ 654 operands[2] = operand_subword (operands[0], 0, 0, SFmode); 655 operands[3] = operand_subword (operands[1], 0, 0, SFmode); 656}") 657 658(define_expand "movdf" 659 [(set (match_operand:DF 0 "general_operand" "") 660 (match_operand:DF 1 "general_operand" ""))] 661 "" 662 " 663{ 664 /* Fixup PIC cases. */ 665 if (flag_pic) 666 { 667 if (symbolic_operand (operands[1], DFmode)) 668 { 669 if (reload_in_progress || reload_completed) 670 operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); 671 else 672 operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); 673 } 674 } 675 676 /* Everything except mem = const or mem = mem can be done easily. */ 677 678 if (MEM_P (operands[0])) 679 operands[1] = force_reg (DFmode, operands[1]); 680}") 681 682(define_insn "*movdf_insn" 683 [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m") 684 (match_operand:DF 1 "move_double_src_operand" "r,F,m,r"))] 685 "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)" 686 "#" 687 [(set_attr "type" "multi,multi,load8,store8") 688 (set_attr "length" "4,16,6,6")]) 689 690(define_split 691 [(set (match_operand:DF 0 "move_dest_operand" "") 692 (match_operand:DF 1 "move_double_src_operand" ""))] 693 "reload_completed" 694 [(match_dup 2)] 695 "operands[2] = gen_split_move_double (operands);") 696 697;; Zero extension instructions. 698 699(define_insn "zero_extendqihi2" 700 [(set (match_operand:HI 0 "register_operand" "=r,r,r") 701 (zero_extend:HI (match_operand:QI 1 "extend_operand" "r,T,m")))] 702 "" 703 "@ 704 and3 %0,%1,%#255 705 ldub %0,%1 706 ldub %0,%1" 707 [(set_attr "type" "int4,load2,load4") 708 (set_attr "length" "4,2,4")]) 709 710(define_insn "zero_extendqisi2" 711 [(set (match_operand:SI 0 "register_operand" "=r,r,r") 712 (zero_extend:SI (match_operand:QI 1 "extend_operand" "r,T,m")))] 713 "" 714 "@ 715 and3 %0,%1,%#255 716 ldub %0,%1 717 ldub %0,%1" 718 [(set_attr "type" "int4,load2,load4") 719 (set_attr "length" "4,2,4")]) 720 721(define_insn "zero_extendhisi2" 722 [(set (match_operand:SI 0 "register_operand" "=r,r,r") 723 (zero_extend:SI (match_operand:HI 1 "extend_operand" "r,T,m")))] 724 "" 725 "@ 726 and3 %0,%1,%#65535 727 lduh %0,%1 728 lduh %0,%1" 729 [(set_attr "type" "int4,load2,load4") 730 (set_attr "length" "4,2,4")]) 731 732;; Signed conversions from a smaller integer to a larger integer 733(define_insn "extendqihi2" 734 [(set (match_operand:HI 0 "register_operand" "=r,r,r") 735 (sign_extend:HI (match_operand:QI 1 "extend_operand" "0,T,m")))] 736 "" 737 "@ 738 # 739 ldb %0,%1 740 ldb %0,%1" 741 [(set_attr "type" "multi,load2,load4") 742 (set_attr "length" "2,2,4")]) 743 744(define_split 745 [(set (match_operand:HI 0 "register_operand" "") 746 (sign_extend:HI (match_operand:QI 1 "register_operand" "")))] 747 "reload_completed" 748 [(match_dup 2) 749 (match_dup 3)] 750 " 751{ 752 rtx op0 = gen_lowpart (SImode, operands[0]); 753 rtx shift = GEN_INT (24); 754 755 operands[2] = gen_ashlsi3 (op0, op0, shift); 756 operands[3] = gen_ashrsi3 (op0, op0, shift); 757}") 758 759(define_insn "extendqisi2" 760 [(set (match_operand:SI 0 "register_operand" "=r,r,r") 761 (sign_extend:SI (match_operand:QI 1 "extend_operand" "0,T,m")))] 762 "" 763 "@ 764 # 765 ldb %0,%1 766 ldb %0,%1" 767 [(set_attr "type" "multi,load2,load4") 768 (set_attr "length" "4,2,4")]) 769 770(define_split 771 [(set (match_operand:SI 0 "register_operand" "") 772 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))] 773 "reload_completed" 774 [(match_dup 2) 775 (match_dup 3)] 776 " 777{ 778 rtx shift = GEN_INT (24); 779 780 operands[2] = gen_ashlsi3 (operands[0], operands[0], shift); 781 operands[3] = gen_ashrsi3 (operands[0], operands[0], shift); 782}") 783 784(define_insn "extendhisi2" 785 [(set (match_operand:SI 0 "register_operand" "=r,r,r") 786 (sign_extend:SI (match_operand:HI 1 "extend_operand" "0,T,m")))] 787 "" 788 "@ 789 # 790 ldh %0,%1 791 ldh %0,%1" 792 [(set_attr "type" "multi,load2,load4") 793 (set_attr "length" "4,2,4")]) 794 795(define_split 796 [(set (match_operand:SI 0 "register_operand" "") 797 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] 798 "reload_completed" 799 [(match_dup 2) 800 (match_dup 3)] 801 " 802{ 803 rtx shift = GEN_INT (16); 804 805 operands[2] = gen_ashlsi3 (operands[0], operands[0], shift); 806 operands[3] = gen_ashrsi3 (operands[0], operands[0], shift); 807}") 808 809;; Arithmetic instructions. 810 811; ??? Adding an alternative to split add3 of small constants into two 812; insns yields better instruction packing but slower code. Adds of small 813; values is done a lot. 814 815(define_insn "addsi3" 816 [(set (match_operand:SI 0 "register_operand" "=r,r,r") 817 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,r") 818 (match_operand:SI 2 "nonmemory_operand" "r,I,J")))] 819 "" 820 "@ 821 add %0,%2 822 addi %0,%#%2 823 add3 %0,%1,%#%2" 824 [(set_attr "type" "int2,int2,int4") 825 (set_attr "length" "2,2,4")]) 826 827;(define_split 828; [(set (match_operand:SI 0 "register_operand" "") 829; (plus:SI (match_operand:SI 1 "register_operand" "") 830; (match_operand:SI 2 "int8_operand" "")))] 831; "reload_completed 832; && REGNO (operands[0]) != REGNO (operands[1]) 833; && satisfies_constraint_I (operands[2]) 834; && INTVAL (operands[2]) != 0" 835; [(set (match_dup 0) (match_dup 1)) 836; (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))] 837; "") 838 839(define_insn "adddi3" 840 [(set (match_operand:DI 0 "register_operand" "=r") 841 (plus:DI (match_operand:DI 1 "register_operand" "%0") 842 (match_operand:DI 2 "register_operand" "r"))) 843 (clobber (reg:CC 17))] 844 "" 845 "#" 846 [(set_attr "type" "multi") 847 (set_attr "length" "6")]) 848 849;; ??? The cmp clears the condition bit. Can we speed up somehow? 850(define_split 851 [(set (match_operand:DI 0 "register_operand" "") 852 (plus:DI (match_operand:DI 1 "register_operand" "") 853 (match_operand:DI 2 "register_operand" ""))) 854 (clobber (reg:CC 17))] 855 "reload_completed" 856 [(parallel [(set (reg:CC 17) 857 (const_int 0)) 858 (use (match_dup 4))]) 859 (parallel [(set (match_dup 4) 860 (plus:SI (match_dup 4) 861 (plus:SI (match_dup 5) 862 (ne:SI (reg:CC 17) (const_int 0))))) 863 (set (reg:CC 17) 864 (unspec:CC [(const_int 0)] UNSPEC_SET_CBIT))]) 865 (parallel [(set (match_dup 6) 866 (plus:SI (match_dup 6) 867 (plus:SI (match_dup 7) 868 (ne:SI (reg:CC 17) (const_int 0))))) 869 (set (reg:CC 17) 870 (unspec:CC [(const_int 0)] UNSPEC_SET_CBIT))])] 871 " 872{ 873 operands[4] = operand_subword (operands[0], (WORDS_BIG_ENDIAN != 0), 0, DImode); 874 operands[5] = operand_subword (operands[2], (WORDS_BIG_ENDIAN != 0), 0, DImode); 875 operands[6] = operand_subword (operands[0], (WORDS_BIG_ENDIAN == 0), 0, DImode); 876 operands[7] = operand_subword (operands[2], (WORDS_BIG_ENDIAN == 0), 0, DImode); 877}") 878 879(define_insn "*clear_c" 880 [(set (reg:CC 17) 881 (const_int 0)) 882 (use (match_operand:SI 0 "register_operand" "r"))] 883 "" 884 "cmp %0,%0" 885 [(set_attr "type" "int2") 886 (set_attr "length" "2")]) 887 888(define_insn "*add_carry" 889 [(set (match_operand:SI 0 "register_operand" "=r") 890 (plus:SI (match_operand:SI 1 "register_operand" "%0") 891 (plus:SI (match_operand:SI 2 "register_operand" "r") 892 (ne:SI (reg:CC 17) (const_int 0))))) 893 (set (reg:CC 17) 894 (unspec:CC [(const_int 0)] UNSPEC_SET_CBIT))] 895 "" 896 "addx %0,%2" 897 [(set_attr "type" "int2") 898 (set_attr "length" "2")]) 899 900(define_insn "subsi3" 901 [(set (match_operand:SI 0 "register_operand" "=r") 902 (minus:SI (match_operand:SI 1 "register_operand" "0") 903 (match_operand:SI 2 "register_operand" "r")))] 904 "" 905 "sub %0,%2" 906 [(set_attr "type" "int2") 907 (set_attr "length" "2")]) 908 909(define_insn "subdi3" 910 [(set (match_operand:DI 0 "register_operand" "=r") 911 (minus:DI (match_operand:DI 1 "register_operand" "0") 912 (match_operand:DI 2 "register_operand" "r"))) 913 (clobber (reg:CC 17))] 914 "" 915 "#" 916 [(set_attr "type" "multi") 917 (set_attr "length" "6")]) 918 919;; ??? The cmp clears the condition bit. Can we speed up somehow? 920(define_split 921 [(set (match_operand:DI 0 "register_operand" "") 922 (minus:DI (match_operand:DI 1 "register_operand" "") 923 (match_operand:DI 2 "register_operand" ""))) 924 (clobber (reg:CC 17))] 925 "reload_completed" 926 [(parallel [(set (reg:CC 17) 927 (const_int 0)) 928 (use (match_dup 4))]) 929 (parallel [(set (match_dup 4) 930 (minus:SI (match_dup 4) 931 (minus:SI (match_dup 5) 932 (ne:SI (reg:CC 17) (const_int 0))))) 933 (set (reg:CC 17) 934 (unspec:CC [(const_int 0)] UNSPEC_SET_CBIT))]) 935 (parallel [(set (match_dup 6) 936 (minus:SI (match_dup 6) 937 (minus:SI (match_dup 7) 938 (ne:SI (reg:CC 17) (const_int 0))))) 939 (set (reg:CC 17) 940 (unspec:CC [(const_int 0)] UNSPEC_SET_CBIT))])] 941 " 942{ 943 operands[4] = operand_subword (operands[0], (WORDS_BIG_ENDIAN != 0), 0, DImode); 944 operands[5] = operand_subword (operands[2], (WORDS_BIG_ENDIAN != 0), 0, DImode); 945 operands[6] = operand_subword (operands[0], (WORDS_BIG_ENDIAN == 0), 0, DImode); 946 operands[7] = operand_subword (operands[2], (WORDS_BIG_ENDIAN == 0), 0, DImode); 947}") 948 949(define_insn "*sub_carry" 950 [(set (match_operand:SI 0 "register_operand" "=r") 951 (minus:SI (match_operand:SI 1 "register_operand" "%0") 952 (minus:SI (match_operand:SI 2 "register_operand" "r") 953 (ne:SI (reg:CC 17) (const_int 0))))) 954 (set (reg:CC 17) 955 (unspec:CC [(const_int 0)] UNSPEC_SET_CBIT))] 956 "" 957 "subx %0,%2" 958 [(set_attr "type" "int2") 959 (set_attr "length" "2")]) 960 961; Multiply/Divide instructions. 962 963(define_insn "mulhisi3" 964 [(set (match_operand:SI 0 "register_operand" "=r") 965 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "r")) 966 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))] 967 "" 968 "mullo %1,%2\;mvfacmi %0" 969 [(set_attr "type" "multi") 970 (set_attr "length" "4")]) 971 972(define_insn "mulsi3" 973 [(set (match_operand:SI 0 "register_operand" "=r") 974 (mult:SI (match_operand:SI 1 "register_operand" "%0") 975 (match_operand:SI 2 "register_operand" "r")))] 976 "" 977 "mul %0,%2" 978 [(set_attr "type" "mul2") 979 (set_attr "length" "2")]) 980 981(define_insn "divsi3" 982 [(set (match_operand:SI 0 "register_operand" "=r") 983 (div:SI (match_operand:SI 1 "register_operand" "0") 984 (match_operand:SI 2 "register_operand" "r")))] 985 "" 986 "div %0,%2" 987 [(set_attr "type" "div4") 988 (set_attr "length" "4")]) 989 990(define_insn "udivsi3" 991 [(set (match_operand:SI 0 "register_operand" "=r") 992 (udiv:SI (match_operand:SI 1 "register_operand" "0") 993 (match_operand:SI 2 "register_operand" "r")))] 994 "" 995 "divu %0,%2" 996 [(set_attr "type" "div4") 997 (set_attr "length" "4")]) 998 999(define_insn "modsi3" 1000 [(set (match_operand:SI 0 "register_operand" "=r") 1001 (mod:SI (match_operand:SI 1 "register_operand" "0") 1002 (match_operand:SI 2 "register_operand" "r")))] 1003 "" 1004 "rem %0,%2" 1005 [(set_attr "type" "div4") 1006 (set_attr "length" "4")]) 1007 1008(define_insn "umodsi3" 1009 [(set (match_operand:SI 0 "register_operand" "=r") 1010 (umod:SI (match_operand:SI 1 "register_operand" "0") 1011 (match_operand:SI 2 "register_operand" "r")))] 1012 "" 1013 "remu %0,%2" 1014 [(set_attr "type" "div4") 1015 (set_attr "length" "4")]) 1016 1017;; Boolean instructions. 1018;; 1019;; We don't define the DImode versions as expand_binop does a good enough job. 1020;; And if it doesn't it should be fixed. 1021 1022(define_insn "andsi3" 1023 [(set (match_operand:SI 0 "register_operand" "=r,r") 1024 (and:SI (match_operand:SI 1 "register_operand" "%0,r") 1025 (match_operand:SI 2 "reg_or_uint16_operand" "r,K")))] 1026 "" 1027 "* 1028{ 1029 /* If we are worried about space, see if we can break this up into two 1030 short instructions, which might eliminate a NOP being inserted. */ 1031 if (optimize_size 1032 && m32r_not_same_reg (operands[0], operands[1]) 1033 && satisfies_constraint_I (operands[2])) 1034 return \"#\"; 1035 1036 else if (CONST_INT_P (operands[2])) 1037 return \"and3 %0,%1,%#%X2\"; 1038 1039 return \"and %0,%2\"; 1040}" 1041 [(set_attr "type" "int2,int4") 1042 (set_attr "length" "2,4")]) 1043 1044(define_split 1045 [(set (match_operand:SI 0 "register_operand" "") 1046 (and:SI (match_operand:SI 1 "register_operand" "") 1047 (match_operand:SI 2 "int8_operand" "")))] 1048 "optimize_size && m32r_not_same_reg (operands[0], operands[1])" 1049 [(set (match_dup 0) (match_dup 2)) 1050 (set (match_dup 0) (and:SI (match_dup 0) (match_dup 1)))] 1051 "") 1052 1053(define_insn "iorsi3" 1054 [(set (match_operand:SI 0 "register_operand" "=r,r") 1055 (ior:SI (match_operand:SI 1 "register_operand" "%0,r") 1056 (match_operand:SI 2 "reg_or_uint16_operand" "r,K")))] 1057 "" 1058 "* 1059{ 1060 /* If we are worried about space, see if we can break this up into two 1061 short instructions, which might eliminate a NOP being inserted. */ 1062 if (optimize_size 1063 && m32r_not_same_reg (operands[0], operands[1]) 1064 && satisfies_constraint_I (operands[2])) 1065 return \"#\"; 1066 1067 else if (CONST_INT_P (operands[2])) 1068 return \"or3 %0,%1,%#%X2\"; 1069 1070 return \"or %0,%2\"; 1071}" 1072 [(set_attr "type" "int2,int4") 1073 (set_attr "length" "2,4")]) 1074 1075(define_split 1076 [(set (match_operand:SI 0 "register_operand" "") 1077 (ior:SI (match_operand:SI 1 "register_operand" "") 1078 (match_operand:SI 2 "int8_operand" "")))] 1079 "optimize_size && m32r_not_same_reg (operands[0], operands[1])" 1080 [(set (match_dup 0) (match_dup 2)) 1081 (set (match_dup 0) (ior:SI (match_dup 0) (match_dup 1)))] 1082 "") 1083 1084(define_insn "xorsi3" 1085 [(set (match_operand:SI 0 "register_operand" "=r,r") 1086 (xor:SI (match_operand:SI 1 "register_operand" "%0,r") 1087 (match_operand:SI 2 "reg_or_uint16_operand" "r,K")))] 1088 "" 1089 "* 1090{ 1091 /* If we are worried about space, see if we can break this up into two 1092 short instructions, which might eliminate a NOP being inserted. */ 1093 if (optimize_size 1094 && m32r_not_same_reg (operands[0], operands[1]) 1095 && satisfies_constraint_I (operands[2])) 1096 return \"#\"; 1097 1098 else if (CONST_INT_P (operands[2])) 1099 return \"xor3 %0,%1,%#%X2\"; 1100 1101 return \"xor %0,%2\"; 1102}" 1103 [(set_attr "type" "int2,int4") 1104 (set_attr "length" "2,4")]) 1105 1106(define_split 1107 [(set (match_operand:SI 0 "register_operand" "") 1108 (xor:SI (match_operand:SI 1 "register_operand" "") 1109 (match_operand:SI 2 "int8_operand" "")))] 1110 "optimize_size && m32r_not_same_reg (operands[0], operands[1])" 1111 [(set (match_dup 0) (match_dup 2)) 1112 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 1)))] 1113 "") 1114 1115(define_insn "negsi2" 1116 [(set (match_operand:SI 0 "register_operand" "=r") 1117 (neg:SI (match_operand:SI 1 "register_operand" "r")))] 1118 "" 1119 "neg %0,%1" 1120 [(set_attr "type" "int2") 1121 (set_attr "length" "2")]) 1122 1123(define_insn "one_cmplsi2" 1124 [(set (match_operand:SI 0 "register_operand" "=r") 1125 (not:SI (match_operand:SI 1 "register_operand" "r")))] 1126 "" 1127 "not %0,%1" 1128 [(set_attr "type" "int2") 1129 (set_attr "length" "2")]) 1130 1131;; Shift instructions. 1132 1133(define_insn "ashlsi3" 1134 [(set (match_operand:SI 0 "register_operand" "=r,r,r") 1135 (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r") 1136 (match_operand:SI 2 "reg_or_uint16_operand" "r,O,K")))] 1137 "" 1138 "@ 1139 sll %0,%2 1140 slli %0,%#%2 1141 sll3 %0,%1,%#%2" 1142 [(set_attr "type" "shift2,shift2,shift4") 1143 (set_attr "length" "2,2,4")]) 1144 1145(define_insn "ashrsi3" 1146 [(set (match_operand:SI 0 "register_operand" "=r,r,r") 1147 (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r") 1148 (match_operand:SI 2 "reg_or_uint16_operand" "r,O,K")))] 1149 "" 1150 "@ 1151 sra %0,%2 1152 srai %0,%#%2 1153 sra3 %0,%1,%#%2" 1154 [(set_attr "type" "shift2,shift2,shift4") 1155 (set_attr "length" "2,2,4")]) 1156 1157(define_insn "lshrsi3" 1158 [(set (match_operand:SI 0 "register_operand" "=r,r,r") 1159 (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r") 1160 (match_operand:SI 2 "reg_or_uint16_operand" "r,O,K")))] 1161 "" 1162 "@ 1163 srl %0,%2 1164 srli %0,%#%2 1165 srl3 %0,%1,%#%2" 1166 [(set_attr "type" "shift2,shift2,shift4") 1167 (set_attr "length" "2,2,4")]) 1168 1169;; Compare instructions. 1170;; This controls RTL generation and register allocation. 1171 1172;; We generate RTL for comparisons and branches by having the cmpxx 1173;; patterns store away the operands. Then the bcc patterns 1174;; emit RTL for both the compare and the branch. 1175;; 1176;; On the m32r it is more efficient to use the bxxz instructions and 1177;; thus merge the compare and branch into one instruction, so they are 1178;; preferred. 1179 1180(define_insn "cmp_eqsi_zero_insn" 1181 [(set (reg:CC 17) 1182 (eq:CC (match_operand:SI 0 "register_operand" "r,r") 1183 (match_operand:SI 1 "reg_or_zero_operand" "r,P")))] 1184 "TARGET_M32RX || TARGET_M32R2" 1185 "@ 1186 cmpeq %0, %1 1187 cmpz %0" 1188 [(set_attr "type" "int4") 1189 (set_attr "length" "4")]) 1190 1191;; The cmp_xxx_insn patterns set the condition bit to the result of the 1192;; comparison. There isn't a "compare equal" instruction so cmp_eqsi_insn 1193;; is quite inefficient. However, it is rarely used. 1194 1195(define_insn "cmp_eqsi_insn" 1196 [(set (reg:CC 17) 1197 (eq:CC (match_operand:SI 0 "register_operand" "r,r") 1198 (match_operand:SI 1 "reg_or_cmp_int16_operand" "r,P"))) 1199 (clobber (match_scratch:SI 2 "=&r,&r"))] 1200 "" 1201 "* 1202{ 1203 if (which_alternative == 0) 1204 { 1205 return \"mv %2,%0\;sub %2,%1\;cmpui %2,#1\"; 1206 } 1207 else 1208 { 1209 if (INTVAL (operands [1]) == 0) 1210 return \"cmpui %0, #1\"; 1211 else if (REGNO (operands [2]) == REGNO (operands [0])) 1212 return \"addi %0,%#%N1\;cmpui %2,#1\"; 1213 else 1214 return \"add3 %2,%0,%#%N1\;cmpui %2,#1\"; 1215 } 1216}" 1217 [(set_attr "type" "multi,multi") 1218 (set_attr "length" "8,8")]) 1219 1220(define_insn "cmp_ltsi_insn" 1221 [(set (reg:CC 17) 1222 (lt:CC (match_operand:SI 0 "register_operand" "r,r") 1223 (match_operand:SI 1 "reg_or_int16_operand" "r,J")))] 1224 "" 1225 "@ 1226 cmp %0,%1 1227 cmpi %0,%#%1" 1228 [(set_attr "type" "int2,int4") 1229 (set_attr "length" "2,4")]) 1230 1231(define_insn "cmp_ltusi_insn" 1232 [(set (reg:CC 17) 1233 (ltu:CC (match_operand:SI 0 "register_operand" "r,r") 1234 (match_operand:SI 1 "reg_or_int16_operand" "r,J")))] 1235 "" 1236 "@ 1237 cmpu %0,%1 1238 cmpui %0,%#%1" 1239 [(set_attr "type" "int2,int4") 1240 (set_attr "length" "2,4")]) 1241 1242;; These control RTL generation for conditional jump insns. 1243 1244(define_expand "cbranchsi4" 1245 ; the comparison is emitted by gen_compare if needed. 1246 [(set (pc) 1247 (if_then_else (match_operator 0 "ordered_comparison_operator" 1248 [(match_operand:SI 1 "register_operand" "") 1249 (match_operand:SI 2 "reg_or_cmp_int16_operand" "")]) 1250 (label_ref (match_operand 3 "" "")) 1251 (pc)))] 1252 "" 1253 " 1254{ 1255 operands[0] = gen_compare (GET_CODE (operands[0]), operands[1], operands[2], FALSE); 1256 operands[1] = XEXP (operands[0], 0); 1257 operands[2] = XEXP (operands[0], 1); 1258}") 1259 1260;; Now match both normal and inverted jump. 1261 1262(define_insn "*branch_insn" 1263 [(set (pc) 1264 (if_then_else (match_operator 1 "eqne_comparison_operator" 1265 [(reg 17) (const_int 0)]) 1266 (label_ref (match_operand 0 "" "")) 1267 (pc)))] 1268 "" 1269 "* 1270{ 1271 static char instruction[40]; 1272 sprintf (instruction, \"%s%s %%l0\", 1273 (GET_CODE (operands[1]) == NE) ? \"bc\" : \"bnc\", 1274 (get_attr_length (insn) == 2) ? \".s\" : \"\"); 1275 return instruction; 1276}" 1277 [(set_attr "type" "branch") 1278 ; cf PR gcc/28508 1279 ; We use 300/600 instead of 512,1024 to account for inaccurate insn 1280 ; lengths and insn alignments that are complex to track. 1281 ; It's not important that we be hyper-precise here. It may be more 1282 ; important blah blah blah when the chip supports parallel execution 1283 ; blah blah blah but until then blah blah blah this is simple and 1284 ; suffices. 1285 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) 1286 (const_int 300)) 1287 (const_int 600)) 1288 (const_int 2) 1289 (const_int 4)))]) 1290 1291(define_insn "*rev_branch_insn" 1292 [(set (pc) 1293 (if_then_else (match_operator 1 "eqne_comparison_operator" 1294 [(reg 17) (const_int 0)]) 1295 (pc) 1296 (label_ref (match_operand 0 "" ""))))] 1297 ;"REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))" 1298 "" 1299 "* 1300{ 1301 static char instruction[40]; 1302 sprintf (instruction, \"%s%s %%l0\", 1303 (GET_CODE (operands[1]) == EQ) ? \"bc\" : \"bnc\", 1304 (get_attr_length (insn) == 2) ? \".s\" : \"\"); 1305 return instruction; 1306}" 1307 [(set_attr "type" "branch") 1308 ; cf PR gcc/28508 1309 ; We use 300/600 instead of 512,1024 to account for inaccurate insn 1310 ; lengths and insn alignments that are complex to track. 1311 ; It's not important that we be hyper-precise here. It may be more 1312 ; important blah blah blah when the chip supports parallel execution 1313 ; blah blah blah but until then blah blah blah this is simple and 1314 ; suffices. 1315 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) 1316 (const_int 300)) 1317 (const_int 600)) 1318 (const_int 2) 1319 (const_int 4)))]) 1320 1321; reg/reg compare and branch insns 1322 1323(define_insn "*reg_branch_insn" 1324 [(set (pc) 1325 (if_then_else (match_operator 1 "eqne_comparison_operator" 1326 [(match_operand:SI 2 "register_operand" "r") 1327 (match_operand:SI 3 "register_operand" "r")]) 1328 (label_ref (match_operand 0 "" "")) 1329 (pc)))] 1330 "" 1331 "* 1332{ 1333 /* Is branch target reachable with beq/bne? */ 1334 if (get_attr_length (insn) == 4) 1335 { 1336 if (GET_CODE (operands[1]) == EQ) 1337 return \"beq %2,%3,%l0\"; 1338 else 1339 return \"bne %2,%3,%l0\"; 1340 } 1341 else 1342 { 1343 if (GET_CODE (operands[1]) == EQ) 1344 return \"bne %2,%3,1f\;bra %l0\;1:\"; 1345 else 1346 return \"beq %2,%3,1f\;bra %l0\;1:\"; 1347 } 1348}" 1349 [(set_attr "type" "branch") 1350 ; We use 25000/50000 instead of 32768/65536 to account for slot filling 1351 ; which is complex to track and inaccurate length specs. 1352 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) 1353 (const_int 25000)) 1354 (const_int 50000)) 1355 (const_int 4) 1356 (const_int 8)))]) 1357 1358(define_insn "*rev_reg_branch_insn" 1359 [(set (pc) 1360 (if_then_else (match_operator 1 "eqne_comparison_operator" 1361 [(match_operand:SI 2 "register_operand" "r") 1362 (match_operand:SI 3 "register_operand" "r")]) 1363 (pc) 1364 (label_ref (match_operand 0 "" ""))))] 1365 "" 1366 "* 1367{ 1368 /* Is branch target reachable with beq/bne? */ 1369 if (get_attr_length (insn) == 4) 1370 { 1371 if (GET_CODE (operands[1]) == NE) 1372 return \"beq %2,%3,%l0\"; 1373 else 1374 return \"bne %2,%3,%l0\"; 1375 } 1376 else 1377 { 1378 if (GET_CODE (operands[1]) == NE) 1379 return \"bne %2,%3,1f\;bra %l0\;1:\"; 1380 else 1381 return \"beq %2,%3,1f\;bra %l0\;1:\"; 1382 } 1383}" 1384 [(set_attr "type" "branch") 1385 ; We use 25000/50000 instead of 32768/65536 to account for slot filling 1386 ; which is complex to track and inaccurate length specs. 1387 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) 1388 (const_int 25000)) 1389 (const_int 50000)) 1390 (const_int 4) 1391 (const_int 8)))]) 1392 1393; reg/zero compare and branch insns 1394 1395(define_insn "*zero_branch_insn" 1396 [(set (pc) 1397 (if_then_else (match_operator 1 "signed_comparison_operator" 1398 [(match_operand:SI 2 "register_operand" "r") 1399 (const_int 0)]) 1400 (label_ref (match_operand 0 "" "")) 1401 (pc)))] 1402 "" 1403 "* 1404{ 1405 const char *br,*invbr; 1406 char asmtext[40]; 1407 1408 switch (GET_CODE (operands[1])) 1409 { 1410 case EQ : br = \"eq\"; invbr = \"ne\"; break; 1411 case NE : br = \"ne\"; invbr = \"eq\"; break; 1412 case LE : br = \"le\"; invbr = \"gt\"; break; 1413 case GT : br = \"gt\"; invbr = \"le\"; break; 1414 case LT : br = \"lt\"; invbr = \"ge\"; break; 1415 case GE : br = \"ge\"; invbr = \"lt\"; break; 1416 1417 default: gcc_unreachable (); 1418 } 1419 1420 /* Is branch target reachable with bxxz? */ 1421 if (get_attr_length (insn) == 4) 1422 { 1423 sprintf (asmtext, \"b%sz %%2,%%l0\", br); 1424 output_asm_insn (asmtext, operands); 1425 } 1426 else 1427 { 1428 sprintf (asmtext, \"b%sz %%2,1f\;bra %%l0\;1:\", invbr); 1429 output_asm_insn (asmtext, operands); 1430 } 1431 return \"\"; 1432}" 1433 [(set_attr "type" "branch") 1434 ; We use 25000/50000 instead of 32768/65536 to account for slot filling 1435 ; which is complex to track and inaccurate length specs. 1436 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) 1437 (const_int 25000)) 1438 (const_int 50000)) 1439 (const_int 4) 1440 (const_int 8)))]) 1441 1442(define_insn "*rev_zero_branch_insn" 1443 [(set (pc) 1444 (if_then_else (match_operator 1 "eqne_comparison_operator" 1445 [(match_operand:SI 2 "register_operand" "r") 1446 (const_int 0)]) 1447 (pc) 1448 (label_ref (match_operand 0 "" ""))))] 1449 "" 1450 "* 1451{ 1452 const char *br,*invbr; 1453 char asmtext[40]; 1454 1455 switch (GET_CODE (operands[1])) 1456 { 1457 case EQ : br = \"eq\"; invbr = \"ne\"; break; 1458 case NE : br = \"ne\"; invbr = \"eq\"; break; 1459 case LE : br = \"le\"; invbr = \"gt\"; break; 1460 case GT : br = \"gt\"; invbr = \"le\"; break; 1461 case LT : br = \"lt\"; invbr = \"ge\"; break; 1462 case GE : br = \"ge\"; invbr = \"lt\"; break; 1463 1464 default: gcc_unreachable (); 1465 } 1466 1467 /* Is branch target reachable with bxxz? */ 1468 if (get_attr_length (insn) == 4) 1469 { 1470 sprintf (asmtext, \"b%sz %%2,%%l0\", invbr); 1471 output_asm_insn (asmtext, operands); 1472 } 1473 else 1474 { 1475 sprintf (asmtext, \"b%sz %%2,1f\;bra %%l0\;1:\", br); 1476 output_asm_insn (asmtext, operands); 1477 } 1478 return \"\"; 1479}" 1480 [(set_attr "type" "branch") 1481 ; We use 25000/50000 instead of 32768/65536 to account for slot filling 1482 ; which is complex to track and inaccurate length specs. 1483 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) 1484 (const_int 25000)) 1485 (const_int 50000)) 1486 (const_int 4) 1487 (const_int 8)))]) 1488 1489;; S<cc> operations to set a register to 1/0 based on a comparison 1490 1491(define_expand "cstoresi4" 1492 [(match_operand:SI 0 "register_operand" "") 1493 (match_operator:SI 1 "ordered_comparison_operator" 1494 [(match_operand:SI 2 "register_operand" "") 1495 (match_operand:SI 3 "reg_or_cmp_int16_operand" "")])] 1496 "" 1497 " 1498{ 1499 if (GET_MODE (operands[0]) != SImode) 1500 FAIL; 1501 1502 if (!gen_cond_store (GET_CODE (operands[1]), 1503 operands[0], operands[2], operands[3])) 1504 FAIL; 1505 1506 DONE; 1507}") 1508 1509(define_insn "seq_insn_m32rx" 1510 [(set (match_operand:SI 0 "register_operand" "=r") 1511 (eq:SI (match_operand:SI 1 "register_operand" "%r") 1512 (match_operand:SI 2 "reg_or_zero_operand" "rP"))) 1513 (clobber (reg:CC 17))] 1514 "TARGET_M32RX || TARGET_M32R2" 1515 "#" 1516 [(set_attr "type" "multi") 1517 (set_attr "length" "6")]) 1518 1519(define_split 1520 [(set (match_operand:SI 0 "register_operand" "") 1521 (eq:SI (match_operand:SI 1 "register_operand" "") 1522 (match_operand:SI 2 "reg_or_zero_operand" ""))) 1523 (clobber (reg:CC 17))] 1524 "TARGET_M32RX || TARGET_M32R2" 1525 [(set (reg:CC 17) 1526 (eq:CC (match_dup 1) 1527 (match_dup 2))) 1528 (set (match_dup 0) 1529 (ne:SI (reg:CC 17) (const_int 0)))] 1530 "") 1531 1532(define_insn "seq_zero_insn" 1533 [(set (match_operand:SI 0 "register_operand" "=r") 1534 (eq:SI (match_operand:SI 1 "register_operand" "r") 1535 (const_int 0))) 1536 (clobber (reg:CC 17))] 1537 "TARGET_M32R" 1538 "#" 1539 [(set_attr "type" "multi") 1540 (set_attr "length" "6")]) 1541 1542(define_split 1543 [(set (match_operand:SI 0 "register_operand" "") 1544 (eq:SI (match_operand:SI 1 "register_operand" "") 1545 (const_int 0))) 1546 (clobber (reg:CC 17))] 1547 "TARGET_M32R" 1548 [(match_dup 3)] 1549 " 1550{ 1551 rtx op0 = operands[0]; 1552 rtx op1 = operands[1]; 1553 1554 start_sequence (); 1555 emit_insn (gen_cmp_ltusi_insn (op1, const1_rtx)); 1556 emit_insn (gen_movcc_insn (op0)); 1557 operands[3] = get_insns (); 1558 end_sequence (); 1559}") 1560 1561(define_insn "seq_insn" 1562 [(set (match_operand:SI 0 "register_operand" "=r,r,??r,r") 1563 (eq:SI (match_operand:SI 1 "register_operand" "r,r,r,r") 1564 (match_operand:SI 2 "reg_or_eq_int16_operand" "r,r,r,PK"))) 1565 (clobber (reg:CC 17)) 1566 (clobber (match_scratch:SI 3 "=1,2,&r,r"))] 1567 "TARGET_M32R" 1568 "#" 1569 [(set_attr "type" "multi") 1570 (set_attr "length" "8,8,10,10")]) 1571 1572(define_split 1573 [(set (match_operand:SI 0 "register_operand" "") 1574 (eq:SI (match_operand:SI 1 "register_operand" "") 1575 (match_operand:SI 2 "reg_or_eq_int16_operand" ""))) 1576 (clobber (reg:CC 17)) 1577 (clobber (match_scratch:SI 3 ""))] 1578 "TARGET_M32R && reload_completed" 1579 [(match_dup 4)] 1580 " 1581{ 1582 rtx op0 = operands[0]; 1583 rtx op1 = operands[1]; 1584 rtx op2 = operands[2]; 1585 rtx op3 = operands[3]; 1586 HOST_WIDE_INT value; 1587 1588 if (REG_P (op2) && REG_P (op3) 1589 && REGNO (op2) == REGNO (op3)) 1590 { 1591 op1 = operands[2]; 1592 op2 = operands[1]; 1593 } 1594 1595 start_sequence (); 1596 if (REG_P (op1) && REG_P (op3) 1597 && REGNO (op1) != REGNO (op3)) 1598 { 1599 emit_move_insn (op3, op1); 1600 op1 = op3; 1601 } 1602 1603 if (satisfies_constraint_P (op2) && (value = INTVAL (op2)) != 0) 1604 emit_insn (gen_addsi3 (op3, op1, GEN_INT (-value))); 1605 else 1606 emit_insn (gen_xorsi3 (op3, op1, op2)); 1607 1608 emit_insn (gen_cmp_ltusi_insn (op3, const1_rtx)); 1609 emit_insn (gen_movcc_insn (op0)); 1610 operands[4] = get_insns (); 1611 end_sequence (); 1612}") 1613 1614(define_insn "sne_zero_insn" 1615 [(set (match_operand:SI 0 "register_operand" "=r") 1616 (ne:SI (match_operand:SI 1 "register_operand" "r") 1617 (const_int 0))) 1618 (clobber (reg:CC 17)) 1619 (clobber (match_scratch:SI 2 "=&r"))] 1620 "" 1621 "#" 1622 [(set_attr "type" "multi") 1623 (set_attr "length" "6")]) 1624 1625(define_split 1626 [(set (match_operand:SI 0 "register_operand" "") 1627 (ne:SI (match_operand:SI 1 "register_operand" "") 1628 (const_int 0))) 1629 (clobber (reg:CC 17)) 1630 (clobber (match_scratch:SI 2 ""))] 1631 "reload_completed" 1632 [(set (match_dup 2) 1633 (const_int 0)) 1634 (set (reg:CC 17) 1635 (ltu:CC (match_dup 2) 1636 (match_dup 1))) 1637 (set (match_dup 0) 1638 (ne:SI (reg:CC 17) (const_int 0)))] 1639 "") 1640 1641(define_insn "slt_insn" 1642 [(set (match_operand:SI 0 "register_operand" "=r,r") 1643 (lt:SI (match_operand:SI 1 "register_operand" "r,r") 1644 (match_operand:SI 2 "reg_or_int16_operand" "r,J"))) 1645 (clobber (reg:CC 17))] 1646 "" 1647 "#" 1648 [(set_attr "type" "multi") 1649 (set_attr "length" "4,6")]) 1650 1651(define_split 1652 [(set (match_operand:SI 0 "register_operand" "") 1653 (lt:SI (match_operand:SI 1 "register_operand" "") 1654 (match_operand:SI 2 "reg_or_int16_operand" ""))) 1655 (clobber (reg:CC 17))] 1656 "" 1657 [(set (reg:CC 17) 1658 (lt:CC (match_dup 1) 1659 (match_dup 2))) 1660 (set (match_dup 0) 1661 (ne:SI (reg:CC 17) (const_int 0)))] 1662 "") 1663 1664(define_insn "sle_insn" 1665 [(set (match_operand:SI 0 "register_operand" "=r") 1666 (le:SI (match_operand:SI 1 "register_operand" "r") 1667 (match_operand:SI 2 "register_operand" "r"))) 1668 (clobber (reg:CC 17))] 1669 "" 1670 "#" 1671 [(set_attr "type" "multi") 1672 (set_attr "length" "8")]) 1673 1674(define_split 1675 [(set (match_operand:SI 0 "register_operand" "") 1676 (le:SI (match_operand:SI 1 "register_operand" "") 1677 (match_operand:SI 2 "register_operand" ""))) 1678 (clobber (reg:CC 17))] 1679 "!optimize_size" 1680 [(set (reg:CC 17) 1681 (lt:CC (match_dup 2) 1682 (match_dup 1))) 1683 (set (match_dup 0) 1684 (ne:SI (reg:CC 17) (const_int 0))) 1685 (set (match_dup 0) 1686 (xor:SI (match_dup 0) 1687 (const_int 1)))] 1688 "") 1689 1690;; If optimizing for space, use -(reg - 1) to invert the comparison rather than 1691;; xor reg,reg,1 which might eliminate a NOP being inserted. 1692(define_split 1693 [(set (match_operand:SI 0 "register_operand" "") 1694 (le:SI (match_operand:SI 1 "register_operand" "") 1695 (match_operand:SI 2 "register_operand" ""))) 1696 (clobber (reg:CC 17))] 1697 "optimize_size" 1698 [(set (reg:CC 17) 1699 (lt:CC (match_dup 2) 1700 (match_dup 1))) 1701 (set (match_dup 0) 1702 (ne:SI (reg:CC 17) (const_int 0))) 1703 (set (match_dup 0) 1704 (plus:SI (match_dup 0) 1705 (const_int -1))) 1706 (set (match_dup 0) 1707 (neg:SI (match_dup 0)))] 1708 "") 1709 1710(define_insn "sge_insn" 1711 [(set (match_operand:SI 0 "register_operand" "=r,r") 1712 (ge:SI (match_operand:SI 1 "register_operand" "r,r") 1713 (match_operand:SI 2 "reg_or_int16_operand" "r,J"))) 1714 (clobber (reg:CC 17))] 1715 "" 1716 "#" 1717 [(set_attr "type" "multi") 1718 (set_attr "length" "8,10")]) 1719 1720(define_split 1721 [(set (match_operand:SI 0 "register_operand" "") 1722 (ge:SI (match_operand:SI 1 "register_operand" "") 1723 (match_operand:SI 2 "reg_or_int16_operand" ""))) 1724 (clobber (reg:CC 17))] 1725 "!optimize_size" 1726 [(set (reg:CC 17) 1727 (lt:CC (match_dup 1) 1728 (match_dup 2))) 1729 (set (match_dup 0) 1730 (ne:SI (reg:CC 17) (const_int 0))) 1731 (set (match_dup 0) 1732 (xor:SI (match_dup 0) 1733 (const_int 1)))] 1734 "") 1735 1736;; If optimizing for space, use -(reg - 1) to invert the comparison rather than 1737;; xor reg,reg,1 which might eliminate a NOP being inserted. 1738(define_split 1739 [(set (match_operand:SI 0 "register_operand" "") 1740 (ge:SI (match_operand:SI 1 "register_operand" "") 1741 (match_operand:SI 2 "reg_or_int16_operand" ""))) 1742 (clobber (reg:CC 17))] 1743 "optimize_size" 1744 [(set (reg:CC 17) 1745 (lt:CC (match_dup 1) 1746 (match_dup 2))) 1747 (set (match_dup 0) 1748 (ne:SI (reg:CC 17) (const_int 0))) 1749 (set (match_dup 0) 1750 (plus:SI (match_dup 0) 1751 (const_int -1))) 1752 (set (match_dup 0) 1753 (neg:SI (match_dup 0)))] 1754 "") 1755 1756(define_insn "sltu_insn" 1757 [(set (match_operand:SI 0 "register_operand" "=r,r") 1758 (ltu:SI (match_operand:SI 1 "register_operand" "r,r") 1759 (match_operand:SI 2 "reg_or_int16_operand" "r,J"))) 1760 (clobber (reg:CC 17))] 1761 "" 1762 "#" 1763 [(set_attr "type" "multi") 1764 (set_attr "length" "6,8")]) 1765 1766(define_split 1767 [(set (match_operand:SI 0 "register_operand" "") 1768 (ltu:SI (match_operand:SI 1 "register_operand" "") 1769 (match_operand:SI 2 "reg_or_int16_operand" ""))) 1770 (clobber (reg:CC 17))] 1771 "" 1772 [(set (reg:CC 17) 1773 (ltu:CC (match_dup 1) 1774 (match_dup 2))) 1775 (set (match_dup 0) 1776 (ne:SI (reg:CC 17) (const_int 0)))] 1777 "") 1778 1779(define_insn "sleu_insn" 1780 [(set (match_operand:SI 0 "register_operand" "=r") 1781 (leu:SI (match_operand:SI 1 "register_operand" "r") 1782 (match_operand:SI 2 "register_operand" "r"))) 1783 (clobber (reg:CC 17))] 1784 "" 1785 "#" 1786 [(set_attr "type" "multi") 1787 (set_attr "length" "8")]) 1788 1789(define_split 1790 [(set (match_operand:SI 0 "register_operand" "") 1791 (leu:SI (match_operand:SI 1 "register_operand" "") 1792 (match_operand:SI 2 "register_operand" ""))) 1793 (clobber (reg:CC 17))] 1794 "!optimize_size" 1795 [(set (reg:CC 17) 1796 (ltu:CC (match_dup 2) 1797 (match_dup 1))) 1798 (set (match_dup 0) 1799 (ne:SI (reg:CC 17) (const_int 0))) 1800 (set (match_dup 0) 1801 (xor:SI (match_dup 0) 1802 (const_int 1)))] 1803 "") 1804 1805;; If optimizing for space, use -(reg - 1) to invert the comparison rather than 1806;; xor reg,reg,1 which might eliminate a NOP being inserted. 1807(define_split 1808 [(set (match_operand:SI 0 "register_operand" "") 1809 (leu:SI (match_operand:SI 1 "register_operand" "") 1810 (match_operand:SI 2 "register_operand" ""))) 1811 (clobber (reg:CC 17))] 1812 "optimize_size" 1813 [(set (reg:CC 17) 1814 (ltu:CC (match_dup 2) 1815 (match_dup 1))) 1816 (set (match_dup 0) 1817 (ne:SI (reg:CC 17) (const_int 0))) 1818 (set (match_dup 0) 1819 (plus:SI (match_dup 0) 1820 (const_int -1))) 1821 (set (match_dup 0) 1822 (neg:SI (match_dup 0)))] 1823 "") 1824 1825(define_insn "sgeu_insn" 1826 [(set (match_operand:SI 0 "register_operand" "=r,r") 1827 (geu:SI (match_operand:SI 1 "register_operand" "r,r") 1828 (match_operand:SI 2 "reg_or_int16_operand" "r,J"))) 1829 (clobber (reg:CC 17))] 1830 "" 1831 "#" 1832 [(set_attr "type" "multi") 1833 (set_attr "length" "8,10")]) 1834 1835(define_split 1836 [(set (match_operand:SI 0 "register_operand" "") 1837 (geu:SI (match_operand:SI 1 "register_operand" "") 1838 (match_operand:SI 2 "reg_or_int16_operand" ""))) 1839 (clobber (reg:CC 17))] 1840 "!optimize_size" 1841 [(set (reg:CC 17) 1842 (ltu:CC (match_dup 1) 1843 (match_dup 2))) 1844 (set (match_dup 0) 1845 (ne:SI (reg:CC 17) (const_int 0))) 1846 (set (match_dup 0) 1847 (xor:SI (match_dup 0) 1848 (const_int 1)))] 1849 "") 1850 1851;; If optimizing for space, use -(reg - 1) to invert the comparison rather than 1852;; xor reg,reg,1 which might eliminate a NOP being inserted. 1853(define_split 1854 [(set (match_operand:SI 0 "register_operand" "") 1855 (geu:SI (match_operand:SI 1 "register_operand" "") 1856 (match_operand:SI 2 "reg_or_int16_operand" ""))) 1857 (clobber (reg:CC 17))] 1858 "optimize_size" 1859 [(set (reg:CC 17) 1860 (ltu:CC (match_dup 1) 1861 (match_dup 2))) 1862 (set (match_dup 0) 1863 (ne:SI (reg:CC 17) (const_int 0))) 1864 (set (match_dup 0) 1865 (plus:SI (match_dup 0) 1866 (const_int -1))) 1867 (set (match_dup 0) 1868 (neg:SI (match_dup 0)))] 1869 "") 1870 1871(define_insn "movcc_insn" 1872 [(set (match_operand:SI 0 "register_operand" "=r") 1873 (ne:SI (reg:CC 17) (const_int 0)))] 1874 "" 1875 "mvfc %0, cbr" 1876 [(set_attr "type" "misc") 1877 (set_attr "length" "2")]) 1878 1879 1880;; Unconditional and other jump instructions. 1881 1882(define_insn "jump" 1883 [(set (pc) (label_ref (match_operand 0 "" "")))] 1884 "" 1885 "bra %l0" 1886 [(set_attr "type" "uncond_branch") 1887 (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) 1888 (const_int 400)) 1889 (const_int 800)) 1890 (const_int 2) 1891 (const_int 4)))]) 1892 1893(define_insn "indirect_jump" 1894 [(set (pc) (match_operand:SI 0 "address_operand" "p"))] 1895 "" 1896 "jmp %a0" 1897 [(set_attr "type" "uncond_branch") 1898 (set_attr "length" "2")]) 1899 1900(define_insn "return_lr" 1901 [(parallel [(return) (use (reg:SI 14))])] 1902 "" 1903 "jmp lr" 1904 [(set_attr "type" "uncond_branch") 1905 (set_attr "length" "2")]) 1906 1907(define_insn "return_rte" 1908 [(return)] 1909 "" 1910 "rte" 1911 [(set_attr "type" "uncond_branch") 1912 (set_attr "length" "2")]) 1913 1914(define_expand "return" 1915 [(return)] 1916 "direct_return ()" 1917 " 1918{ 1919 emit_jump_insn (gen_return_lr ()); 1920 DONE; 1921}") 1922 1923(define_expand "return_normal" 1924 [(return)] 1925 "!direct_return ()" 1926 " 1927{ 1928 enum m32r_function_type fn_type; 1929 1930 fn_type = m32r_compute_function_type (current_function_decl); 1931 if (M32R_INTERRUPT_P (fn_type)) 1932 { 1933 emit_jump_insn (gen_return_rte ()); 1934 DONE; 1935 } 1936 1937 emit_jump_insn (gen_return_lr ()); 1938 DONE; 1939}") 1940 1941(define_expand "tablejump" 1942 [(parallel [(set (pc) (match_operand 0 "register_operand" "r")) 1943 (use (label_ref (match_operand 1 "" "")))])] 1944 "" 1945 " 1946{ 1947 /* In pic mode, our address differences are against the base of the 1948 table. Add that base value back in; CSE ought to be able to combine 1949 the two address loads. */ 1950 if (flag_pic) 1951 { 1952 rtx tmp, tmp2; 1953 1954 tmp = gen_rtx_LABEL_REF (Pmode, operands[1]); 1955 tmp2 = operands[0]; 1956 tmp = gen_rtx_PLUS (Pmode, tmp2, tmp); 1957 operands[0] = memory_address (Pmode, tmp); 1958 } 1959}") 1960 1961(define_insn "*tablejump_insn" 1962 [(set (pc) (match_operand:SI 0 "address_operand" "p")) 1963 (use (label_ref (match_operand 1 "" "")))] 1964 "" 1965 "jmp %a0" 1966 [(set_attr "type" "uncond_branch") 1967 (set_attr "length" "2")]) 1968 1969(define_expand "call" 1970 ;; operands[1] is stack_size_rtx 1971 ;; operands[2] is next_arg_register 1972 [(parallel [(call (match_operand:SI 0 "call_operand" "") 1973 (match_operand 1 "" "")) 1974 (clobber (reg:SI 14))])] 1975 "" 1976 " 1977{ 1978 if (flag_pic) 1979 crtl->uses_pic_offset_table = 1; 1980}") 1981 1982(define_insn "*call_via_reg" 1983 [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) 1984 (match_operand 1 "" "")) 1985 (clobber (reg:SI 14))] 1986 "" 1987 "jl %0" 1988 [(set_attr "type" "call") 1989 (set_attr "length" "2")]) 1990 1991(define_insn "*call_via_label" 1992 [(call (mem:SI (match_operand:SI 0 "call_address_operand" "")) 1993 (match_operand 1 "" "")) 1994 (clobber (reg:SI 14))] 1995 "" 1996 "* 1997{ 1998 int call26_p = call26_operand (operands[0], FUNCTION_MODE); 1999 2000 if (! call26_p) 2001 { 2002 /* We may not be able to reach with a `bl' insn so punt and leave it to 2003 the linker. 2004 We do this here, rather than doing a force_reg in the define_expand 2005 so these insns won't be separated, say by scheduling, thus simplifying 2006 the linker. */ 2007 return \"seth r14,%T0\;add3 r14,r14,%B0\;jl r14\"; 2008 } 2009 else 2010 return \"bl %0\"; 2011}" 2012 [(set_attr "type" "call") 2013 (set (attr "length") 2014 (if_then_else (not (match_test "call26_operand (operands[0], FUNCTION_MODE)")) 2015 (const_int 12) ; 10 + 2 for nop filler 2016 ; The return address must be on a 4 byte boundary so 2017 ; there's no point in using a value of 2 here. A 2 byte 2018 ; insn may go in the left slot but we currently can't 2019 ; use such knowledge. 2020 (const_int 4)))]) 2021 2022(define_expand "call_value" 2023 ;; operand 2 is stack_size_rtx 2024 ;; operand 3 is next_arg_register 2025 [(parallel [(set (match_operand 0 "register_operand" "=r") 2026 (call (match_operand:SI 1 "call_operand" "") 2027 (match_operand 2 "" ""))) 2028 (clobber (reg:SI 14))])] 2029 "" 2030 " 2031{ 2032 if (flag_pic) 2033 crtl->uses_pic_offset_table = 1; 2034}") 2035 2036(define_insn "*call_value_via_reg" 2037 [(set (match_operand 0 "register_operand" "=r") 2038 (call (mem:SI (match_operand:SI 1 "register_operand" "r")) 2039 (match_operand 2 "" ""))) 2040 (clobber (reg:SI 14))] 2041 "" 2042 "jl %1" 2043 [(set_attr "type" "call") 2044 (set_attr "length" "2")]) 2045 2046(define_insn "*call_value_via_label" 2047 [(set (match_operand 0 "register_operand" "=r") 2048 (call (mem:SI (match_operand:SI 1 "call_address_operand" "")) 2049 (match_operand 2 "" ""))) 2050 (clobber (reg:SI 14))] 2051 "" 2052 "* 2053{ 2054 int call26_p = call26_operand (operands[1], FUNCTION_MODE); 2055 2056 if (flag_pic) 2057 crtl->uses_pic_offset_table = 1; 2058 2059 if (! call26_p) 2060 { 2061 /* We may not be able to reach with a `bl' insn so punt and leave it to 2062 the linker. 2063 We do this here, rather than doing a force_reg in the define_expand 2064 so these insns won't be separated, say by scheduling, thus simplifying 2065 the linker. */ 2066 return \"seth r14,%T1\;add3 r14,r14,%B1\;jl r14\"; 2067 } 2068 else 2069 return \"bl %1\"; 2070}" 2071 [(set_attr "type" "call") 2072 (set (attr "length") 2073 (if_then_else (not (match_test "call26_operand (operands[1], FUNCTION_MODE)")) 2074 (const_int 12) ; 10 + 2 for nop filler 2075 ; The return address must be on a 4 byte boundary so 2076 ; there's no point in using a value of 2 here. A 2 byte 2077 ; insn may go in the left slot but we currently can't 2078 ; use such knowledge. 2079 (const_int 4)))]) 2080 2081(define_insn "nop" 2082 [(const_int 0)] 2083 "" 2084 "nop" 2085 [(set_attr "type" "int2") 2086 (set_attr "length" "2")]) 2087 2088;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and 2089;; all of memory. This blocks insns from being moved across this point. 2090 2091(define_insn "blockage" 2092 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] 2093 "" 2094 "") 2095 2096;; Special pattern to flush the icache. 2097 2098(define_insn "flush_icache" 2099 [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 2100 UNSPECV_FLUSH_ICACHE) 2101 (match_operand 1 "" "") 2102 (clobber (reg:SI 17))] 2103 "" 2104 "* return \"trap %#%1 ; flush-icache\";" 2105 [(set_attr "type" "int4") 2106 (set_attr "length" "4")]) 2107 2108;; Speed up fabs and provide correct sign handling for -0 2109 2110(define_insn "absdf2" 2111 [(set (match_operand:DF 0 "register_operand" "=r") 2112 (abs:DF (match_operand:DF 1 "register_operand" "0")))] 2113 "" 2114 "#" 2115 [(set_attr "type" "multi") 2116 (set_attr "length" "4")]) 2117 2118(define_split 2119 [(set (match_operand:DF 0 "register_operand" "") 2120 (abs:DF (match_operand:DF 1 "register_operand" "")))] 2121 "reload_completed" 2122 [(set (match_dup 2) 2123 (ashift:SI (match_dup 2) 2124 (const_int 1))) 2125 (set (match_dup 2) 2126 (lshiftrt:SI (match_dup 2) 2127 (const_int 1)))] 2128 "operands[2] = gen_highpart (SImode, operands[0]);") 2129 2130(define_insn "abssf2" 2131 [(set (match_operand:SF 0 "register_operand" "=r") 2132 (abs:SF (match_operand:SF 1 "register_operand" "0")))] 2133 "" 2134 "#" 2135 [(set_attr "type" "multi") 2136 (set_attr "length" "4")]) 2137 2138(define_split 2139 [(set (match_operand:SF 0 "register_operand" "") 2140 (abs:SF (match_operand:SF 1 "register_operand" "")))] 2141 "reload_completed" 2142 [(set (match_dup 2) 2143 (ashift:SI (match_dup 2) 2144 (const_int 1))) 2145 (set (match_dup 2) 2146 (lshiftrt:SI (match_dup 2) 2147 (const_int 1)))] 2148 "operands[2] = gen_highpart (SImode, operands[0]);") 2149 2150;; Conditional move instructions 2151;; Based on those done for the d10v 2152 2153(define_expand "movsicc" 2154 [ 2155 (set (match_operand:SI 0 "register_operand" "r") 2156 (if_then_else:SI (match_operand 1 "" "") 2157 (match_operand:SI 2 "conditional_move_operand" "O") 2158 (match_operand:SI 3 "conditional_move_operand" "O") 2159 ) 2160 ) 2161 ] 2162 "" 2163 " 2164{ 2165 /* FIXME: This expansion is hold over from a failed conversion of this 2166 port away from using cc0. It still relies upon the last comparison 2167 being the one that is now tested. Disabled for now in order to 2168 improve the generation of working code. */ 2169 FAIL; 2170 2171 if (! zero_and_one (operands [2], operands [3])) 2172 FAIL; 2173 2174 /* Generate the comparison that will set the carry flag. */ 2175 operands[1] = gen_compare (GET_CODE (operands[1]), XEXP (operands[1], 0), 2176 XEXP (operands[1], 1), TRUE); 2177 2178 /* See other movsicc pattern below for reason why. */ 2179 emit_insn (gen_blockage ()); 2180}") 2181 2182;; Generate the conditional instructions based on how the carry flag is examined. 2183(define_insn "*movsicc_internal" 2184 [(set (match_operand:SI 0 "register_operand" "=r") 2185 (if_then_else:SI (match_operand 1 "carry_compare_operand" "") 2186 (match_operand:SI 2 "conditional_move_operand" "O") 2187 (match_operand:SI 3 "conditional_move_operand" "O") 2188 ) 2189 )] 2190 "zero_and_one (operands [2], operands[3])" 2191 "* return emit_cond_move (operands, insn);" 2192 [(set_attr "type" "multi") 2193 (set_attr "length" "8") 2194 ] 2195) 2196 2197 2198;; Block moves, see m32r.c for more details. 2199;; Argument 0 is the destination 2200;; Argument 1 is the source 2201;; Argument 2 is the length 2202;; Argument 3 is the alignment 2203 2204(define_expand "cpymemsi" 2205 [(parallel [(set (match_operand:BLK 0 "general_operand" "") 2206 (match_operand:BLK 1 "general_operand" "")) 2207 (use (match_operand:SI 2 "immediate_operand" "")) 2208 (use (match_operand:SI 3 "immediate_operand" ""))])] 2209 "" 2210 " 2211{ 2212 if (operands[0]) /* Avoid unused code messages. */ 2213 { 2214 if (m32r_expand_block_move (operands)) 2215 DONE; 2216 else 2217 FAIL; 2218 } 2219}") 2220 2221;; Insn generated by block moves 2222 2223(define_insn "cpymemsi_internal" 2224 [(set (mem:BLK (match_operand:SI 0 "register_operand" "r")) ;; destination 2225 (mem:BLK (match_operand:SI 1 "register_operand" "r"))) ;; source 2226 (use (match_operand:SI 2 "m32r_block_immediate_operand" "J"));; # bytes to move 2227 (set (match_operand:SI 3 "register_operand" "=0") 2228 (plus:SI (minus (match_dup 2) (const_int 4)) 2229 (match_dup 0))) 2230 (set (match_operand:SI 4 "register_operand" "=1") 2231 (plus:SI (match_dup 1) 2232 (match_dup 2))) 2233 (clobber (match_scratch:SI 5 "=&r")) ;; temp1 2234 (clobber (match_scratch:SI 6 "=&r"))] ;; temp2 2235 "" 2236 "* m32r_output_block_move (insn, operands); return \"\"; " 2237 [(set_attr "type" "store8") 2238 (set_attr "length" "72")]) ;; Maximum 2239 2240;; PIC 2241 2242/* When generating pic, we need to load the symbol offset into a register. 2243 So that the optimizer does not confuse this with a normal symbol load 2244 we use an unspec. The offset will be loaded from a constant pool entry, 2245 since that is the only type of relocation we can use. */ 2246 2247(define_insn "pic_load_addr" 2248 [(set (match_operand:SI 0 "register_operand" "=r") 2249 (unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_LOAD_ADDR))] 2250 "flag_pic" 2251 "ld24 %0,%#%1" 2252 [(set_attr "type" "int4")]) 2253 2254(define_insn "gotoff_load_addr" 2255 [(set (match_operand:SI 0 "register_operand" "=r") 2256 (unspec:SI [(match_operand 1 "" "")] UNSPEC_GOTOFF))] 2257 "flag_pic" 2258 "seth %0, %#shigh(%1@GOTOFF)\;add3 %0, %0, low(%1@GOTOFF)" 2259 [(set_attr "type" "int4") 2260 (set_attr "length" "8")]) 2261 2262;; Load program counter insns. 2263 2264(define_insn "get_pc" 2265 [(clobber (reg:SI 14)) 2266 (set (match_operand 0 "register_operand" "=r,r") 2267 (unspec [(match_operand 1 "" "")] UNSPEC_GET_PC)) 2268 (use (match_operand:SI 2 "immediate_operand" "W,i"))] 2269 "flag_pic" 2270 "@ 2271 bl.s .+4\;seth %0,%#shigh(%1)\;add3 %0,%0,%#low(%1+4)\;add %0,lr 2272 bl.s .+4\;ld24 %0,%#%1\;add %0,lr" 2273 [(set_attr "length" "12,8")]) 2274 2275(define_expand "builtin_setjmp_receiver" 2276 [(label_ref (match_operand 0 "" ""))] 2277 "flag_pic" 2278 " 2279{ 2280 m32r_load_pic_register (); 2281 DONE; 2282}") 2283