1;; Machine description of the Argonaut ARC cpu for GNU C compiler 2;; Copyright (C) 1994, 1997, 1998, 1999, 2000, 2004, 2005, 2007, 2008 3;; Free Software Foundation, Inc. 4 5;; This file is part of GCC. 6 7;; GCC is free software; you can redistribute it and/or modify 8;; it under the terms of the GNU General Public License as published by 9;; the Free Software Foundation; either version 3, or (at your option) 10;; any later version. 11 12;; GCC is distributed in the hope that it will be useful, 13;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15;; GNU General Public License for more details. 16 17;; You should have received a copy of the GNU General Public License 18;; along with GCC; see the file COPYING3. If not see 19;; <http://www.gnu.org/licenses/>. 20 21;; See file "rtl.def" for documentation on define_insn, match_*, et. al. 22 23;; ??? This is an old port, and is undoubtedly suffering from bit rot. 24 25;; Insn type. Used to default other attribute values. 26 27(define_attr "type" 28 "move,load,store,cmove,unary,binary,compare,shift,mul,uncond_branch,branch,call,call_no_delay_slot,multi,misc" 29 (const_string "binary")) 30 31;; Length (in # of insns, long immediate constants counted too). 32;; ??? There's a nasty interaction between the conditional execution fsm 33;; and insn lengths: insns with shimm values cannot be conditionally executed. 34(define_attr "length" "" 35 (cond [(eq_attr "type" "load") 36 (if_then_else (match_operand 1 "long_immediate_loadstore_operand" "") 37 (const_int 2) (const_int 1)) 38 39 (eq_attr "type" "store") 40 (if_then_else (match_operand 0 "long_immediate_loadstore_operand" "") 41 (const_int 2) (const_int 1)) 42 43 (eq_attr "type" "move,unary,compare") 44 (if_then_else (match_operand 1 "long_immediate_operand" "") 45 (const_int 2) (const_int 1)) 46 47 (eq_attr "type" "binary,mul") 48 (if_then_else (match_operand 2 "long_immediate_operand" "") 49 (const_int 2) (const_int 1)) 50 51 (eq_attr "type" "cmove") 52 (if_then_else (match_operand 2 "register_operand" "") 53 (const_int 1) (const_int 2)) 54 55 (eq_attr "type" "multi") (const_int 2) 56 ] 57 58 (const_int 1))) 59 60;; The length here is the length of a single asm. Unfortunately it might be 61;; 1 or 2 so we must allow for 2. That's ok though. How often will users 62;; lament asm's not being put in delay slots? 63(define_asm_attributes 64 [(set_attr "length" "2") 65 (set_attr "type" "multi")]) 66 67;; Condition codes: this one is used by final_prescan_insn to speed up 68;; conditionalizing instructions. It saves having to scan the rtl to see if 69;; it uses or alters the condition codes. 70 71;; USE: This insn uses the condition codes (e.g.: a conditional branch). 72;; CANUSE: This insn can use the condition codes (for conditional execution). 73;; SET: All condition codes are set by this insn. 74;; SET_ZN: the Z and N flags are set by this insn. 75;; SET_ZNC: the Z, N, and C flags are set by this insn. 76;; CLOB: The condition codes are set to unknown values by this insn. 77;; NOCOND: This insn can't use and doesn't affect the condition codes. 78 79(define_attr "cond" "use,canuse,set,set_zn,set_znc,clob,nocond" 80 (cond [(and (eq_attr "type" "unary,binary,move") 81 (eq_attr "length" "1")) 82 (const_string "canuse") 83 84 (eq_attr "type" "compare") 85 (const_string "set") 86 87 (eq_attr "type" "cmove,branch") 88 (const_string "use") 89 90 (eq_attr "type" "multi,misc") 91 (const_string "clob") 92 ] 93 94 (const_string "nocond"))) 95 96;; Delay slots. 97 98(define_attr "in_delay_slot" "false,true" 99 (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi") 100 (const_string "false") 101 ] 102 103 (if_then_else (eq_attr "length" "1") 104 (const_string "true") 105 (const_string "false")))) 106 107(define_delay (eq_attr "type" "call") 108 [(eq_attr "in_delay_slot" "true") 109 (eq_attr "in_delay_slot" "true") 110 (eq_attr "in_delay_slot" "true")]) 111 112(define_delay (eq_attr "type" "branch,uncond_branch") 113 [(eq_attr "in_delay_slot" "true") 114 (eq_attr "in_delay_slot" "true") 115 (eq_attr "in_delay_slot" "true")]) 116 117;; Scheduling description for the ARC 118 119(define_cpu_unit "branch") 120 121(define_insn_reservation "any_insn" 1 (eq_attr "type" "!load,compare,branch") 122 "nothing") 123 124;; 1) A conditional jump cannot immediately follow the insn setting the flags. 125;; This isn't a complete solution as it doesn't come with guarantees. That 126;; is done in the branch patterns and in arc_print_operand. This exists to 127;; avoid inserting a nop when we can. 128 129(define_insn_reservation "compare" 1 (eq_attr "type" "compare") 130 "nothing,branch") 131 132(define_insn_reservation "branch" 1 (eq_attr "type" "branch") 133 "branch") 134 135;; 2) References to loaded registers should wait a cycle. 136 137;; Memory with load-delay of 1 (i.e., 2 cycle load). 138 139(define_insn_reservation "memory" 2 (eq_attr "type" "load") 140 "nothing") 141 142;; Move instructions. 143 144(define_expand "movqi" 145 [(set (match_operand:QI 0 "general_operand" "") 146 (match_operand:QI 1 "general_operand" ""))] 147 "" 148 " 149{ 150 /* Everything except mem = const or mem = mem can be done easily. */ 151 152 if (GET_CODE (operands[0]) == MEM) 153 operands[1] = force_reg (QImode, operands[1]); 154}") 155 156(define_insn "*movqi_insn" 157 [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,m") 158 (match_operand:QI 1 "move_src_operand" "rI,Ji,m,r"))] 159;; ??? Needed? 160 "register_operand (operands[0], QImode) 161 || register_operand (operands[1], QImode)" 162 "@ 163 mov%? %0,%1 164 mov%? %0,%1 165 ldb%U1%V1 %0,%1 166 stb%U0%V0 %1,%0" 167 [(set_attr "type" "move,move,load,store")]) 168 169;; ??? This may never match since there's no cmpqi insn. 170 171(define_insn "*movqi_set_cc_insn" 172 [(set (reg:CCZN 61) (compare:CCZN 173 (sign_extend:SI (match_operand:QI 1 "move_src_operand" "rIJi")) 174 (const_int 0))) 175 (set (match_operand:QI 0 "move_dest_operand" "=r") 176 (match_dup 1))] 177 "" 178 "mov%?.f %0,%1" 179 [(set_attr "type" "move") 180 (set_attr "cond" "set_zn")]) 181 182(define_expand "movhi" 183 [(set (match_operand:HI 0 "general_operand" "") 184 (match_operand:HI 1 "general_operand" ""))] 185 "" 186 " 187{ 188 /* Everything except mem = const or mem = mem can be done easily. */ 189 190 if (GET_CODE (operands[0]) == MEM) 191 operands[1] = force_reg (HImode, operands[1]); 192}") 193 194(define_insn "*movhi_insn" 195 [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,m") 196 (match_operand:HI 1 "move_src_operand" "rI,Ji,m,r"))] 197 "register_operand (operands[0], HImode) 198 || register_operand (operands[1], HImode)" 199 "@ 200 mov%? %0,%1 201 mov%? %0,%1 202 ldw%U1%V1 %0,%1 203 stw%U0%V0 %1,%0" 204 [(set_attr "type" "move,move,load,store")]) 205 206;; ??? Will this ever match? 207 208(define_insn "*movhi_set_cc_insn" 209 [(set (reg:CCZN 61) (compare:CCZN 210 (sign_extend:SI (match_operand:HI 1 "move_src_operand" "rIJi")) 211 (const_int 0))) 212 (set (match_operand:HI 0 "move_dest_operand" "=r") 213 (match_dup 1))] 214;; ??? Needed? 215 "register_operand (operands[0], HImode) 216 || register_operand (operands[1], HImode)" 217 "mov%?.f %0,%1" 218 [(set_attr "type" "move") 219 (set_attr "cond" "set_zn")]) 220 221(define_expand "movsi" 222 [(set (match_operand:SI 0 "general_operand" "") 223 (match_operand:SI 1 "general_operand" ""))] 224 "" 225 " 226{ 227 /* Everything except mem = const or mem = mem can be done easily. */ 228 229 if (GET_CODE (operands[0]) == MEM) 230 operands[1] = force_reg (SImode, operands[1]); 231}") 232 233(define_insn "*movsi_insn" 234 [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,m") 235 (match_operand:SI 1 "move_src_operand" "rI,GJi,m,r"))] 236 "register_operand (operands[0], SImode) 237 || register_operand (operands[1], SImode)" 238 "@ 239 mov%? %0,%1 240 mov%? %0,%S1 241 ld%U1%V1 %0,%1 242 st%U0%V0 %1,%0" 243 [(set_attr "type" "move,move,load,store")]) 244 245(define_insn "*movsi_set_cc_insn" 246 [(set (reg:CCZN 61) (compare:CCZN 247 (match_operand:SI 1 "move_src_operand" "rIJi") 248 (const_int 0))) 249 (set (match_operand:SI 0 "move_dest_operand" "=r") 250 (match_dup 1))] 251 "register_operand (operands[0], SImode) 252 || register_operand (operands[1], SImode)" 253 "mov%?.f %0,%S1" 254 [(set_attr "type" "move") 255 (set_attr "cond" "set_zn")]) 256 257(define_expand "movdi" 258 [(set (match_operand:DI 0 "general_operand" "") 259 (match_operand:DI 1 "general_operand" ""))] 260 "" 261 " 262{ 263 /* Everything except mem = const or mem = mem can be done easily. */ 264 265 if (GET_CODE (operands[0]) == MEM) 266 operands[1] = force_reg (DImode, operands[1]); 267}") 268 269(define_insn "*movdi_insn" 270 [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,m") 271 (match_operand:DI 1 "move_double_src_operand" "r,HK,m,r"))] 272 "register_operand (operands[0], DImode) 273 || register_operand (operands[1], DImode)" 274 "* 275{ 276 switch (which_alternative) 277 { 278 case 0 : 279 /* We normally copy the low-numbered register first. However, if 280 the first register operand 0 is the same as the second register of 281 operand 1, we must copy in the opposite order. */ 282 if (REGNO (operands[0]) == REGNO (operands[1]) + 1) 283 return \"mov %R0,%R1\;mov %0,%1\"; 284 else 285 return \"mov %0,%1\;mov %R0,%R1\"; 286 case 1 : 287 return \"mov %0,%L1\;mov %R0,%H1\"; 288 case 2 : 289 /* If the low-address word is used in the address, we must load it 290 last. Otherwise, load it first. Note that we cannot have 291 auto-increment in that case since the address register is known to be 292 dead. */ 293 if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, 294 operands [1], 0)) 295 return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\"; 296 else 297 return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\"; 298 case 3 : 299 return \"st%V0 %1,%0\;st%V0 %R1,%R0\"; 300 default: 301 gcc_unreachable (); 302 } 303}" 304 [(set_attr "type" "move,move,load,store") 305 ;; ??? The ld/st values could be 4 if it's [reg,bignum]. 306 (set_attr "length" "2,4,2,2")]) 307 308;(define_expand "movdi" 309; [(set (match_operand:DI 0 "general_operand" "") 310; (match_operand:DI 1 "general_operand" ""))] 311; "" 312; " 313;{ 314; /* Flow doesn't understand that this is effectively a DFmode move. 315; It doesn't know that all of `operands[0]' is set. */ 316; emit_clobber (operands[0]); 317; 318; /* Emit insns that movsi_insn can handle. */ 319; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DImode), 320; operand_subword (operands[1], 0, 0, DImode))); 321; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DImode), 322; operand_subword (operands[1], 1, 0, DImode))); 323; DONE; 324;}") 325 326;; Floating point move insns. 327 328(define_expand "movsf" 329 [(set (match_operand:SF 0 "general_operand" "") 330 (match_operand:SF 1 "general_operand" ""))] 331 "" 332 " 333{ 334 /* Everything except mem = const or mem = mem can be done easily. */ 335 if (GET_CODE (operands[0]) == MEM) 336 operands[1] = force_reg (SFmode, operands[1]); 337}") 338 339(define_insn "*movsf_insn" 340 [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,m") 341 (match_operand:SF 1 "move_src_operand" "r,E,m,r"))] 342 "register_operand (operands[0], SFmode) 343 || register_operand (operands[1], SFmode)" 344 "@ 345 mov%? %0,%1 346 mov%? %0,%1 ; %A1 347 ld%U1%V1 %0,%1 348 st%U0%V0 %1,%0" 349 [(set_attr "type" "move,move,load,store")]) 350 351(define_expand "movdf" 352 [(set (match_operand:DF 0 "general_operand" "") 353 (match_operand:DF 1 "general_operand" ""))] 354 "" 355 " 356{ 357 /* Everything except mem = const or mem = mem can be done easily. */ 358 if (GET_CODE (operands[0]) == MEM) 359 operands[1] = force_reg (DFmode, operands[1]); 360}") 361 362(define_insn "*movdf_insn" 363 [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m") 364 (match_operand:DF 1 "move_double_src_operand" "r,E,m,r"))] 365 "register_operand (operands[0], DFmode) 366 || register_operand (operands[1], DFmode)" 367 "* 368{ 369 switch (which_alternative) 370 { 371 case 0 : 372 /* We normally copy the low-numbered register first. However, if 373 the first register operand 0 is the same as the second register of 374 operand 1, we must copy in the opposite order. */ 375 if (REGNO (operands[0]) == REGNO (operands[1]) + 1) 376 return \"mov %R0,%R1\;mov %0,%1\"; 377 else 378 return \"mov %0,%1\;mov %R0,%R1\"; 379 case 1 : 380 return \"mov %0,%L1\;mov %R0,%H1 ; %A1\"; 381 case 2 : 382 /* If the low-address word is used in the address, we must load it 383 last. Otherwise, load it first. Note that we cannot have 384 auto-increment in that case since the address register is known to be 385 dead. */ 386 if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, 387 operands [1], 0)) 388 return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\"; 389 else 390 return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\"; 391 case 3 : 392 return \"st%V0 %1,%0\;st%V0 %R1,%R0\"; 393 default: 394 gcc_unreachable (); 395 } 396}" 397 [(set_attr "type" "move,move,load,store") 398 ;; ??? The ld/st values could be 4 if it's [reg,bignum]. 399 (set_attr "length" "2,4,2,2")]) 400 401;(define_expand "movdf" 402; [(set (match_operand:DF 0 "general_operand" "") 403; (match_operand:DF 1 "general_operand" ""))] 404; "" 405; " 406;{ 407; /* Flow doesn't understand that this is effectively a DFmode move. 408; It doesn't know that all of `operands[0]' is set. */ 409; emit_clobber (operands[0]); 410; 411; /* Emit insns that movsi_insn can handle. */ 412; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DFmode), 413; operand_subword (operands[1], 0, 0, DFmode))); 414; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DFmode), 415; operand_subword (operands[1], 1, 0, DFmode))); 416; DONE; 417;}") 418 419;; Load/Store with update instructions. 420;; 421;; Some of these we can get by using pre-decrement or pre-increment, but the 422;; hardware can also do cases where the increment is not the size of the 423;; object. 424;; 425;; In all these cases, we use operands 0 and 1 for the register being 426;; incremented because those are the operands that local-alloc will 427;; tie and these are the pair most likely to be tieable (and the ones 428;; that will benefit the most). 429;; 430;; We use match_operator here because we need to know whether the memory 431;; object is volatile or not. 432 433(define_insn "*loadqi_update" 434 [(set (match_operand:QI 3 "register_operand" "=r,r") 435 (match_operator:QI 4 "load_update_operand" 436 [(match_operand:SI 1 "register_operand" "0,0") 437 (match_operand:SI 2 "nonmemory_operand" "rI,J")])) 438 (set (match_operand:SI 0 "register_operand" "=r,r") 439 (plus:SI (match_dup 1) (match_dup 2)))] 440 "" 441 "ldb.a%V4 %3,[%0,%2]" 442 [(set_attr "type" "load,load") 443 (set_attr "length" "1,2")]) 444 445(define_insn "*load_zeroextendqisi_update" 446 [(set (match_operand:SI 3 "register_operand" "=r,r") 447 (zero_extend:SI (match_operator:QI 4 "load_update_operand" 448 [(match_operand:SI 1 "register_operand" "0,0") 449 (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) 450 (set (match_operand:SI 0 "register_operand" "=r,r") 451 (plus:SI (match_dup 1) (match_dup 2)))] 452 "" 453 "ldb.a%V4 %3,[%0,%2]" 454 [(set_attr "type" "load,load") 455 (set_attr "length" "1,2")]) 456 457(define_insn "*load_signextendqisi_update" 458 [(set (match_operand:SI 3 "register_operand" "=r,r") 459 (sign_extend:SI (match_operator:QI 4 "load_update_operand" 460 [(match_operand:SI 1 "register_operand" "0,0") 461 (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) 462 (set (match_operand:SI 0 "register_operand" "=r,r") 463 (plus:SI (match_dup 1) (match_dup 2)))] 464 "" 465 "ldb.x.a%V4 %3,[%0,%2]" 466 [(set_attr "type" "load,load") 467 (set_attr "length" "1,2")]) 468 469(define_insn "*storeqi_update" 470 [(set (match_operator:QI 4 "store_update_operand" 471 [(match_operand:SI 1 "register_operand" "0") 472 (match_operand:SI 2 "short_immediate_operand" "I")]) 473 (match_operand:QI 3 "register_operand" "r")) 474 (set (match_operand:SI 0 "register_operand" "=r") 475 (plus:SI (match_dup 1) (match_dup 2)))] 476 "" 477 "stb.a%V4 %3,[%0,%2]" 478 [(set_attr "type" "store") 479 (set_attr "length" "1")]) 480 481(define_insn "*loadhi_update" 482 [(set (match_operand:HI 3 "register_operand" "=r,r") 483 (match_operator:HI 4 "load_update_operand" 484 [(match_operand:SI 1 "register_operand" "0,0") 485 (match_operand:SI 2 "nonmemory_operand" "rI,J")])) 486 (set (match_operand:SI 0 "register_operand" "=r,r") 487 (plus:SI (match_dup 1) (match_dup 2)))] 488 "" 489 "ldw.a%V4 %3,[%0,%2]" 490 [(set_attr "type" "load,load") 491 (set_attr "length" "1,2")]) 492 493(define_insn "*load_zeroextendhisi_update" 494 [(set (match_operand:SI 3 "register_operand" "=r,r") 495 (zero_extend:SI (match_operator:HI 4 "load_update_operand" 496 [(match_operand:SI 1 "register_operand" "0,0") 497 (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) 498 (set (match_operand:SI 0 "register_operand" "=r,r") 499 (plus:SI (match_dup 1) (match_dup 2)))] 500 "" 501 "ldw.a%V4 %3,[%0,%2]" 502 [(set_attr "type" "load,load") 503 (set_attr "length" "1,2")]) 504 505(define_insn "*load_signextendhisi_update" 506 [(set (match_operand:SI 3 "register_operand" "=r,r") 507 (sign_extend:SI (match_operator:HI 4 "load_update_operand" 508 [(match_operand:SI 1 "register_operand" "0,0") 509 (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) 510 (set (match_operand:SI 0 "register_operand" "=r,r") 511 (plus:SI (match_dup 1) (match_dup 2)))] 512 "" 513 "ldw.x.a%V4 %3,[%0,%2]" 514 [(set_attr "type" "load,load") 515 (set_attr "length" "1,2")]) 516 517(define_insn "*storehi_update" 518 [(set (match_operator:HI 4 "store_update_operand" 519 [(match_operand:SI 1 "register_operand" "0") 520 (match_operand:SI 2 "short_immediate_operand" "I")]) 521 (match_operand:HI 3 "register_operand" "r")) 522 (set (match_operand:SI 0 "register_operand" "=r") 523 (plus:SI (match_dup 1) (match_dup 2)))] 524 "" 525 "stw.a%V4 %3,[%0,%2]" 526 [(set_attr "type" "store") 527 (set_attr "length" "1")]) 528 529(define_insn "*loadsi_update" 530 [(set (match_operand:SI 3 "register_operand" "=r,r") 531 (match_operator:SI 4 "load_update_operand" 532 [(match_operand:SI 1 "register_operand" "0,0") 533 (match_operand:SI 2 "nonmemory_operand" "rI,J")])) 534 (set (match_operand:SI 0 "register_operand" "=r,r") 535 (plus:SI (match_dup 1) (match_dup 2)))] 536 "" 537 "ld.a%V4 %3,[%0,%2]" 538 [(set_attr "type" "load,load") 539 (set_attr "length" "1,2")]) 540 541(define_insn "*storesi_update" 542 [(set (match_operator:SI 4 "store_update_operand" 543 [(match_operand:SI 1 "register_operand" "0") 544 (match_operand:SI 2 "short_immediate_operand" "I")]) 545 (match_operand:SI 3 "register_operand" "r")) 546 (set (match_operand:SI 0 "register_operand" "=r") 547 (plus:SI (match_dup 1) (match_dup 2)))] 548 "" 549 "st.a%V4 %3,[%0,%2]" 550 [(set_attr "type" "store") 551 (set_attr "length" "1")]) 552 553(define_insn "*loadsf_update" 554 [(set (match_operand:SF 3 "register_operand" "=r,r") 555 (match_operator:SF 4 "load_update_operand" 556 [(match_operand:SI 1 "register_operand" "0,0") 557 (match_operand:SI 2 "nonmemory_operand" "rI,J")])) 558 (set (match_operand:SI 0 "register_operand" "=r,r") 559 (plus:SI (match_dup 1) (match_dup 2)))] 560 "" 561 "ld.a%V4 %3,[%0,%2]" 562 [(set_attr "type" "load,load") 563 (set_attr "length" "1,2")]) 564 565(define_insn "*storesf_update" 566 [(set (match_operator:SF 4 "store_update_operand" 567 [(match_operand:SI 1 "register_operand" "0") 568 (match_operand:SI 2 "short_immediate_operand" "I")]) 569 (match_operand:SF 3 "register_operand" "r")) 570 (set (match_operand:SI 0 "register_operand" "=r") 571 (plus:SI (match_dup 1) (match_dup 2)))] 572 "" 573 "st.a%V4 %3,[%0,%2]" 574 [(set_attr "type" "store") 575 (set_attr "length" "1")]) 576 577;; Conditional move instructions. 578 579(define_expand "movsicc" 580 [(set (match_operand:SI 0 "register_operand" "") 581 (if_then_else:SI (match_operand 1 "comparison_operator" "") 582 (match_operand:SI 2 "nonmemory_operand" "") 583 (match_operand:SI 3 "register_operand" "")))] 584 "" 585 " 586{ 587 enum rtx_code code = GET_CODE (operands[1]); 588 rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0), 589 XEXP (operands[1], 1)); 590 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx); 591}") 592 593(define_expand "movsfcc" 594 [(set (match_operand:SF 0 "register_operand" "") 595 (if_then_else:SF (match_operand 1 "comparison_operator" "") 596 (match_operand:SF 2 "nonmemory_operand" "") 597 (match_operand:SF 3 "register_operand" "")))] 598 "" 599 " 600{ 601 enum rtx_code code = GET_CODE (operands[1]); 602 rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0), 603 XEXP (operands[1], 1)); 604 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx); 605}") 606 607(define_insn "*movsicc_insn" 608 [(set (match_operand:SI 0 "register_operand" "=r") 609 (if_then_else:SI (match_operand 1 "comparison_operator" "") 610 (match_operand:SI 2 "nonmemory_operand" "rJi") 611 (match_operand:SI 3 "register_operand" "0")))] 612 "" 613 "mov.%d1 %0,%S2" 614 [(set_attr "type" "cmove")]) 615 616(define_insn "*movsfcc_insn" 617 [(set (match_operand:SF 0 "register_operand" "=r,r") 618 (if_then_else:SF (match_operand 1 "comparison_operator" "") 619 (match_operand:SF 2 "nonmemory_operand" "r,E") 620 (match_operand:SF 3 "register_operand" "0,0")))] 621 "" 622 "@ 623 mov.%d1 %0,%2 624 mov.%d1 %0,%2 ; %A2" 625 [(set_attr "type" "cmove,cmove")]) 626 627 628;; Zero extension instructions. 629;; ??? We don't support volatile memrefs here, but I'm not sure why. 630 631(define_insn "zero_extendqihi2" 632 [(set (match_operand:HI 0 "register_operand" "=r,r") 633 (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] 634 "" 635 "@ 636 extb%? %0,%1 637 ldb%U1 %0,%1" 638 [(set_attr "type" "unary,load")]) 639 640(define_insn "*zero_extendqihi2_set_cc_insn" 641 [(set (reg:CCZN 61) (compare:CCZN 642 (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) 643 (const_int 0))) 644 (set (match_operand:HI 0 "register_operand" "=r") 645 (zero_extend:HI (match_dup 1)))] 646 "" 647 "extb%?.f %0,%1" 648 [(set_attr "type" "unary") 649 (set_attr "cond" "set_zn")]) 650 651(define_insn "zero_extendqisi2" 652 [(set (match_operand:SI 0 "register_operand" "=r,r") 653 (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] 654 "" 655 "@ 656 extb%? %0,%1 657 ldb%U1 %0,%1" 658 [(set_attr "type" "unary,load")]) 659 660(define_insn "*zero_extendqisi2_set_cc_insn" 661 [(set (reg:CCZN 61) (compare:CCZN 662 (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) 663 (const_int 0))) 664 (set (match_operand:SI 0 "register_operand" "=r") 665 (zero_extend:SI (match_dup 1)))] 666 "" 667 "extb%?.f %0,%1" 668 [(set_attr "type" "unary") 669 (set_attr "cond" "set_zn")]) 670 671(define_insn "zero_extendhisi2" 672 [(set (match_operand:SI 0 "register_operand" "=r,r") 673 (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))] 674 "" 675 "@ 676 extw%? %0,%1 677 ldw%U1 %0,%1" 678 [(set_attr "type" "unary,load")]) 679 680(define_insn "*zero_extendhisi2_set_cc_insn" 681 [(set (reg:CCZN 61) (compare:CCZN 682 (zero_extend:SI (match_operand:HI 1 "register_operand" "r")) 683 (const_int 0))) 684 (set (match_operand:SI 0 "register_operand" "=r") 685 (zero_extend:SI (match_dup 1)))] 686 "" 687 "extw%?.f %0,%1" 688 [(set_attr "type" "unary") 689 (set_attr "cond" "set_zn")]) 690 691;; Sign extension instructions. 692 693(define_insn "extendqihi2" 694 [(set (match_operand:HI 0 "register_operand" "=r,r") 695 (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] 696 "" 697 "@ 698 sexb%? %0,%1 699 ldb.x%U1 %0,%1" 700 [(set_attr "type" "unary,load")]) 701 702(define_insn "*extendqihi2_set_cc_insn" 703 [(set (reg:CCZN 61) (compare:CCZN 704 (sign_extend:SI (match_operand:QI 1 "register_operand" "r")) 705 (const_int 0))) 706 (set (match_operand:HI 0 "register_operand" "=r") 707 (sign_extend:HI (match_dup 1)))] 708 "" 709 "sexb%?.f %0,%1" 710 [(set_attr "type" "unary") 711 (set_attr "cond" "set_zn")]) 712 713(define_insn "extendqisi2" 714 [(set (match_operand:SI 0 "register_operand" "=r,r") 715 (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] 716 "" 717 "@ 718 sexb%? %0,%1 719 ldb.x%U1 %0,%1" 720 [(set_attr "type" "unary,load")]) 721 722(define_insn "*extendqisi2_set_cc_insn" 723 [(set (reg:CCZN 61) (compare:CCZN 724 (sign_extend:SI (match_operand:QI 1 "register_operand" "r")) 725 (const_int 0))) 726 (set (match_operand:SI 0 "register_operand" "=r") 727 (sign_extend:SI (match_dup 1)))] 728 "" 729 "sexb%?.f %0,%1" 730 [(set_attr "type" "unary") 731 (set_attr "cond" "set_zn")]) 732 733(define_insn "extendhisi2" 734 [(set (match_operand:SI 0 "register_operand" "=r,r") 735 (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))] 736 "" 737 "@ 738 sexw%? %0,%1 739 ldw.x%U1 %0,%1" 740 [(set_attr "type" "unary,load")]) 741 742(define_insn "*extendhisi2_set_cc_insn" 743 [(set (reg:CCZN 61) (compare:CCZN 744 (sign_extend:SI (match_operand:HI 1 "register_operand" "r")) 745 (const_int 0))) 746 (set (match_operand:SI 0 "register_operand" "=r") 747 (sign_extend:SI (match_dup 1)))] 748 "" 749 "sexw%?.f %0,%1" 750 [(set_attr "type" "unary") 751 (set_attr "cond" "set_zn")]) 752 753;; Arithmetic instructions. 754 755(define_insn "addsi3" 756 [(set (match_operand:SI 0 "register_operand" "=r") 757 (plus:SI (match_operand:SI 1 "register_operand" "%r") 758 (match_operand:SI 2 "nonmemory_operand" "rIJ")))] 759 "" 760 "add%? %0,%1,%2") 761 762(define_insn "*addsi3_set_cc_insn" 763 [(set (reg:CC 61) (compare:CC 764 (plus:SI (match_operand:SI 1 "register_operand" "%r") 765 (match_operand:SI 2 "nonmemory_operand" "rIJ")) 766 (const_int 0))) 767 (set (match_operand:SI 0 "register_operand" "=r") 768 (plus:SI (match_dup 1) 769 (match_dup 2)))] 770 "" 771 "add%?.f %0,%1,%2" 772 [(set_attr "cond" "set")]) 773 774(define_insn "adddi3" 775 [(set (match_operand:DI 0 "register_operand" "=r") 776 (plus:DI (match_operand:DI 1 "nonmemory_operand" "%r") 777 (match_operand:DI 2 "nonmemory_operand" "ri"))) 778 (clobber (reg:CC 61))] 779 "" 780 "* 781{ 782 rtx op2 = operands[2]; 783 784 if (GET_CODE (op2) == CONST_INT) 785 { 786 int sign = INTVAL (op2); 787 if (sign < 0) 788 return \"add.f %L0,%L1,%2\;adc %H0,%H1,-1\"; 789 else 790 return \"add.f %L0,%L1,%2\;adc %H0,%H1,0\"; 791 } 792 else 793 return \"add.f %L0,%L1,%L2\;adc %H0,%H1,%H2\"; 794}" 795 [(set_attr "length" "2")]) 796 797(define_insn "subsi3" 798 [(set (match_operand:SI 0 "register_operand" "=r") 799 (minus:SI (match_operand:SI 1 "register_operand" "r") 800 (match_operand:SI 2 "nonmemory_operand" "rIJ")))] 801 "" 802 "sub%? %0,%1,%2") 803 804(define_insn "*subsi3_set_cc_insn" 805 [(set (reg:CC 61) (compare:CC 806 (minus:SI (match_operand:SI 1 "register_operand" "%r") 807 (match_operand:SI 2 "nonmemory_operand" "rIJ")) 808 (const_int 0))) 809 (set (match_operand:SI 0 "register_operand" "=r") 810 (minus:SI (match_dup 1) 811 (match_dup 2)))] 812 "" 813 "sub%?.f %0,%1,%2" 814 [(set_attr "cond" "set")]) 815 816(define_insn "subdi3" 817 [(set (match_operand:DI 0 "register_operand" "=r") 818 (minus:DI (match_operand:DI 1 "nonmemory_operand" "r") 819 (match_operand:DI 2 "nonmemory_operand" "ri"))) 820 (clobber (reg:CC 61))] 821 "" 822 "* 823{ 824 rtx op2 = operands[2]; 825 826 if (GET_CODE (op2) == CONST_INT) 827 { 828 int sign = INTVAL (op2); 829 if (sign < 0) 830 return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,-1\"; 831 else 832 return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,0\"; 833 } 834 else 835 return \"sub.f %L0,%L1,%L2\;sbc %H0,%H1,%H2\"; 836}" 837 [(set_attr "length" "2")]) 838 839;; Boolean instructions. 840;; 841;; We don't define the DImode versions as expand_binop does a good enough job. 842 843(define_insn "andsi3" 844 [(set (match_operand:SI 0 "register_operand" "=r") 845 (and:SI (match_operand:SI 1 "register_operand" "%r") 846 (match_operand:SI 2 "nonmemory_operand" "rIJ")))] 847 "" 848 "and%? %0,%1,%2") 849 850(define_insn "*andsi3_set_cc_insn" 851 [(set (reg:CCZN 61) (compare:CCZN 852 (and:SI (match_operand:SI 1 "register_operand" "%r") 853 (match_operand:SI 2 "nonmemory_operand" "rIJ")) 854 (const_int 0))) 855 (set (match_operand:SI 0 "register_operand" "=r") 856 (and:SI (match_dup 1) 857 (match_dup 2)))] 858 "" 859 "and%?.f %0,%1,%2" 860 [(set_attr "cond" "set_zn")]) 861 862(define_insn "*bicsi3_insn" 863 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") 864 (and:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") 865 (not:SI (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r"))))] 866 "" 867 "bic%? %0,%1,%2" 868 [(set_attr "length" "1,2,1,2")]) 869 870(define_insn "*bicsi3_set_cc_insn" 871 [(set (reg:CCZN 61) (compare:CCZN 872 (and:SI (match_operand:SI 1 "register_operand" "%r") 873 (not:SI (match_operand:SI 2 "nonmemory_operand" "rIJ"))) 874 (const_int 0))) 875 (set (match_operand:SI 0 "register_operand" "=r") 876 (and:SI (match_dup 1) 877 (not:SI (match_dup 2))))] 878 "" 879 "bic%?.f %0,%1,%2" 880 [(set_attr "cond" "set_zn")]) 881 882(define_insn "iorsi3" 883 [(set (match_operand:SI 0 "register_operand" "=r") 884 (ior:SI (match_operand:SI 1 "register_operand" "%r") 885 (match_operand:SI 2 "nonmemory_operand" "rIJ")))] 886 "" 887 "or%? %0,%1,%2") 888 889(define_insn "*iorsi3_set_cc_insn" 890 [(set (reg:CCZN 61) (compare:CCZN 891 (ior:SI (match_operand:SI 1 "register_operand" "%r") 892 (match_operand:SI 2 "nonmemory_operand" "rIJ")) 893 (const_int 0))) 894 (set (match_operand:SI 0 "register_operand" "=r") 895 (ior:SI (match_dup 1) 896 (match_dup 2)))] 897 "" 898 "or%?.f %0,%1,%2" 899 [(set_attr "cond" "set_zn")]) 900 901(define_insn "xorsi3" 902 [(set (match_operand:SI 0 "register_operand" "=r") 903 (xor:SI (match_operand:SI 1 "register_operand" "%r") 904 (match_operand:SI 2 "nonmemory_operand" "rIJ")))] 905 "" 906 "xor%? %0,%1,%2") 907 908(define_insn "*xorsi3_set_cc_insn" 909 [(set (reg:CCZN 61) (compare:CCZN 910 (xor:SI (match_operand:SI 1 "register_operand" "%r") 911 (match_operand:SI 2 "nonmemory_operand" "rIJ")) 912 (const_int 0))) 913 (set (match_operand:SI 0 "register_operand" "=r") 914 (xor:SI (match_dup 1) 915 (match_dup 2)))] 916 "" 917 "xor%?.f %0,%1,%2" 918 [(set_attr "cond" "set_zn")]) 919 920(define_insn "negsi2" 921 [(set (match_operand:SI 0 "register_operand" "=r") 922 (neg:SI (match_operand:SI 1 "register_operand" "r")))] 923 "" 924 "sub%? %0,0,%1" 925 [(set_attr "type" "unary")]) 926 927(define_insn "*negsi2_set_cc_insn" 928 [(set (reg:CC 61) (compare:CC 929 (neg:SI (match_operand:SI 1 "register_operand" "r")) 930 (const_int 0))) 931 (set (match_operand:SI 0 "register_operand" "=r") 932 (neg:SI (match_dup 1)))] 933 "" 934 "sub%?.f %0,0,%1" 935 [(set_attr "type" "unary") 936 (set_attr "cond" "set")]) 937 938(define_insn "negdi2" 939 [(set (match_operand:DI 0 "register_operand" "=r") 940 (neg:DI (match_operand:DI 1 "register_operand" "r"))) 941 (clobber (reg:SI 61))] 942 "" 943 "sub.f %L0,0,%L1\;sbc %H0,0,%H1" 944 [(set_attr "type" "unary") 945 (set_attr "length" "2")]) 946 947(define_insn "one_cmplsi2" 948 [(set (match_operand:SI 0 "register_operand" "=r") 949 (not:SI (match_operand:SI 1 "register_operand" "r")))] 950 "" 951 "xor%? %0,%1,-1" 952 [(set_attr "type" "unary")]) 953 954(define_insn "*one_cmplsi2_set_cc_insn" 955 [(set (reg:CCZN 61) (compare:CCZN 956 (not:SI (match_operand:SI 1 "register_operand" "r")) 957 (const_int 0))) 958 (set (match_operand:SI 0 "register_operand" "=r") 959 (not:SI (match_dup 1)))] 960 "" 961 "xor%?.f %0,%1,-1" 962 [(set_attr "type" "unary") 963 (set_attr "cond" "set_zn")]) 964 965;; Shift instructions. 966 967(define_expand "ashlsi3" 968 [(set (match_operand:SI 0 "register_operand" "") 969 (ashift:SI (match_operand:SI 1 "register_operand" "") 970 (match_operand:SI 2 "nonmemory_operand" "")))] 971 "" 972 " 973{ 974 if (! TARGET_SHIFTER) 975 { 976 emit_insn (gen_rtx_PARALLEL 977 (VOIDmode, 978 gen_rtvec (2, 979 gen_rtx_SET (VOIDmode, operands[0], 980 gen_rtx_ASHIFT (SImode, operands[1], 981 operands[2])), 982 gen_rtx_CLOBBER (VOIDmode, 983 gen_rtx_SCRATCH (SImode))))); 984 DONE; 985 } 986}") 987 988(define_expand "ashrsi3" 989 [(set (match_operand:SI 0 "register_operand" "") 990 (ashiftrt:SI (match_operand:SI 1 "register_operand" "") 991 (match_operand:SI 2 "nonmemory_operand" "")))] 992 "" 993 " 994{ 995 if (! TARGET_SHIFTER) 996 { 997 emit_insn (gen_rtx_PARALLEL 998 (VOIDmode, 999 gen_rtvec (2, 1000 gen_rtx_SET (VOIDmode, operands[0], 1001 gen_rtx_ASHIFTRT (SImode, 1002 operands[1], 1003 operands[2])), 1004 gen_rtx_CLOBBER (VOIDmode, 1005 gen_rtx_SCRATCH (SImode))))); 1006 DONE; 1007 } 1008}") 1009 1010(define_expand "lshrsi3" 1011 [(set (match_operand:SI 0 "register_operand" "") 1012 (lshiftrt:SI (match_operand:SI 1 "register_operand" "") 1013 (match_operand:SI 2 "nonmemory_operand" "")))] 1014 "" 1015 " 1016{ 1017 if (! TARGET_SHIFTER) 1018 { 1019 emit_insn (gen_rtx_PARALLEL 1020 (VOIDmode, 1021 gen_rtvec (2, 1022 gen_rtx_SET (VOIDmode, operands[0], 1023 gen_rtx_LSHIFTRT (SImode, 1024 operands[1], 1025 operands[2])), 1026 gen_rtx_CLOBBER (VOIDmode, 1027 gen_rtx_SCRATCH (SImode))))); 1028 DONE; 1029 } 1030}") 1031 1032(define_insn "*ashlsi3_insn" 1033 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") 1034 (ashift:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") 1035 (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))] 1036 "TARGET_SHIFTER" 1037 "asl%? %0,%1,%2" 1038 [(set_attr "type" "shift") 1039 (set_attr "length" "1,2,1,2")]) 1040 1041(define_insn "*ashrsi3_insn" 1042 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") 1043 (ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") 1044 (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))] 1045 "TARGET_SHIFTER" 1046 "asr%? %0,%1,%2" 1047 [(set_attr "type" "shift") 1048 (set_attr "length" "1,2,1,2")]) 1049 1050(define_insn "*lshrsi3_insn" 1051 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") 1052 (lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") 1053 (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))] 1054 "TARGET_SHIFTER" 1055 "lsr%? %0,%1,%2" 1056 [(set_attr "type" "shift") 1057 (set_attr "length" "1,2,1,2")]) 1058 1059(define_insn "*shift_si3" 1060 [(set (match_operand:SI 0 "register_operand" "=r") 1061 (match_operator:SI 3 "shift_operator" 1062 [(match_operand:SI 1 "register_operand" "0") 1063 (match_operand:SI 2 "nonmemory_operand" "rIJ")])) 1064 (clobber (match_scratch:SI 4 "=&r"))] 1065 "! TARGET_SHIFTER" 1066 "* return output_shift (operands);" 1067 [(set_attr "type" "shift") 1068 (set_attr "length" "8")]) 1069 1070;; Compare instructions. 1071;; This controls RTL generation and register allocation. 1072 1073;; ??? We may be able to relax this a bit by adding a new constant 'K' for 0. 1074;; This assumes sub.f 0,symbol,0 is a valid insn. 1075;; Note that "sub.f 0,r0,1" is an 8 byte insn. To avoid unnecessarily 1076;; creating 8 byte insns we duplicate %1 in the destination reg of the insn 1077;; if it's a small constant. 1078 1079(define_insn "*cmpsi_cc_insn" 1080 [(set (reg:CC 61) 1081 (compare:CC (match_operand:SI 0 "register_operand" "r,r,r") 1082 (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] 1083 "" 1084 "@ 1085 sub.f 0,%0,%1 1086 sub.f %1,%0,%1 1087 sub.f 0,%0,%1" 1088 [(set_attr "type" "compare,compare,compare")]) 1089 1090(define_insn "*cmpsi_cczn_insn" 1091 [(set (reg:CCZN 61) 1092 (compare:CCZN (match_operand:SI 0 "register_operand" "r,r,r") 1093 (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] 1094 "" 1095 "@ 1096 sub.f 0,%0,%1 1097 sub.f %1,%0,%1 1098 sub.f 0,%0,%1" 1099 [(set_attr "type" "compare,compare,compare")]) 1100 1101(define_insn "*cmpsi_ccznc_insn" 1102 [(set (reg:CCZNC 61) 1103 (compare:CCZNC (match_operand:SI 0 "register_operand" "r,r,r") 1104 (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] 1105 "" 1106 "@ 1107 sub.f 0,%0,%1 1108 sub.f %1,%0,%1 1109 sub.f 0,%0,%1" 1110 [(set_attr "type" "compare,compare,compare")]) 1111 1112;; Next come the scc insn and its expander. 1113 1114(define_expand "cstoresi4" 1115 [(set (match_dup 4) 1116 (match_op_dup 5 1117 [(match_operand:SI 2 "register_operand" "") 1118 (match_operand:SI 3 "nonmemory_operand" "")])) 1119 (set (match_operand:SI 0 "register_operand") 1120 (match_operator:SI 1 "ordered_comparison_operator" 1121 [(match_dup 4) 1122 (const_int 0)]))] 1123 "" 1124 " 1125{ 1126 operands[4] = gen_compare_reg (GET_CODE (operands[1]), 1127 operands[2], operands[3]); 1128 operands[5] = gen_rtx_fmt_ee (COMPARE, 1129 GET_MODE (operands[4]), 1130 operands[2], operands[3]); 1131}") 1132 1133(define_insn "*scc_insn" 1134 [(set (match_operand:SI 0 "register_operand" "=r") 1135 (match_operator:SI 1 "comparison_operator" [(reg 61) (const_int 0)]))] 1136 "" 1137 "mov %0,1\;sub.%D1 %0,%0,%0" 1138 [(set_attr "type" "unary") 1139 (set_attr "length" "2")]) 1140 1141;; ??? Look up negscc insn. See pa.md for example. 1142(define_insn "*neg_scc_insn" 1143 [(set (match_operand:SI 0 "register_operand" "=r") 1144 (neg:SI (match_operator:SI 1 "comparison_operator" 1145 [(reg 61) (const_int 0)])))] 1146 "" 1147 "mov %0,-1\;sub.%D1 %0,%0,%0" 1148 [(set_attr "type" "unary") 1149 (set_attr "length" "2")]) 1150 1151(define_insn "*not_scc_insn" 1152 [(set (match_operand:SI 0 "register_operand" "=r") 1153 (not:SI (match_operator:SI 1 "comparison_operator" 1154 [(reg 61) (const_int 0)])))] 1155 "" 1156 "mov %0,1\;sub.%d1 %0,%0,%0" 1157 [(set_attr "type" "unary") 1158 (set_attr "length" "2")]) 1159 1160;; These control RTL generation for conditional jump insns 1161 1162(define_expand "cbranchsi4" 1163 [(set (match_dup 4) 1164 (match_op_dup 5 1165 [(match_operand:SI 1 "register_operand" "") 1166 (match_operand:SI 2 "nonmemory_operand" "")])) 1167 (set (pc) 1168 (if_then_else 1169 (match_operator 0 "ordered_comparison_operator" 1170 [(match_dup 4) 1171 (const_int 0)]) 1172 (label_ref (match_operand 3 "" "")) 1173 (pc)))] 1174 "" 1175 " 1176{ 1177 operands[4] = gen_compare_reg (GET_CODE (operands[0]), 1178 operands[1], operands[2]); 1179 operands[5] = gen_rtx_fmt_ee (COMPARE, 1180 GET_MODE (operands[4]), 1181 operands[1], operands[2]); 1182}") 1183 1184;; Now match both normal and inverted jump. 1185 1186(define_insn "*branch_insn" 1187 [(set (pc) 1188 (if_then_else (match_operator 1 "proper_comparison_operator" 1189 [(reg 61) (const_int 0)]) 1190 (label_ref (match_operand 0 "" "")) 1191 (pc)))] 1192 "" 1193 "* 1194{ 1195 if (arc_ccfsm_branch_deleted_p ()) 1196 { 1197 arc_ccfsm_record_branch_deleted (); 1198 return \"; branch deleted, next insns conditionalized\"; 1199 } 1200 else 1201 return \"%~b%d1%# %l0\"; 1202}" 1203 [(set_attr "type" "branch")]) 1204 1205(define_insn "*rev_branch_insn" 1206 [(set (pc) 1207 (if_then_else (match_operator 1 "proper_comparison_operator" 1208 [(reg 61) (const_int 0)]) 1209 (pc) 1210 (label_ref (match_operand 0 "" ""))))] 1211 "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))" 1212 "* 1213{ 1214 if (arc_ccfsm_branch_deleted_p ()) 1215 { 1216 arc_ccfsm_record_branch_deleted (); 1217 return \"; branch deleted, next insns conditionalized\"; 1218 } 1219 else 1220 return \"%~b%D1%# %l0\"; 1221}" 1222 [(set_attr "type" "branch")]) 1223 1224;; Unconditional and other jump instructions. 1225 1226(define_insn "jump" 1227 [(set (pc) (label_ref (match_operand 0 "" "")))] 1228 "" 1229 "b%* %l0" 1230 [(set_attr "type" "uncond_branch")]) 1231 1232(define_insn "indirect_jump" 1233 [(set (pc) (match_operand:SI 0 "address_operand" "p"))] 1234 "" 1235 "j%* %a0" 1236 [(set_attr "type" "uncond_branch")]) 1237 1238;; Implement a switch statement. 1239;; This wouldn't be necessary in the non-pic case if we could distinguish 1240;; label refs of the jump table from other label refs. The problem is that 1241;; label refs are output as "%st(.LL42)" but we don't want the %st - we want 1242;; the real address since it's the address of the table. 1243 1244(define_expand "casesi" 1245 [(set (match_dup 5) 1246 (minus:SI (match_operand:SI 0 "register_operand" "") 1247 (match_operand:SI 1 "nonmemory_operand" ""))) 1248 (set (reg:CC 61) 1249 (compare:CC (match_dup 5) 1250 (match_operand:SI 2 "nonmemory_operand" ""))) 1251 (set (pc) 1252 (if_then_else (gtu (reg:CC 61) 1253 (const_int 0)) 1254 (label_ref (match_operand 4 "" "")) 1255 (pc))) 1256 (parallel 1257 [(set (pc) 1258 (mem:SI (plus:SI (mult:SI (match_dup 5) 1259 (const_int 4)) 1260 (label_ref (match_operand 3 "" ""))))) 1261 (clobber (match_scratch:SI 6 "")) 1262 (clobber (match_scratch:SI 7 ""))])] 1263 "" 1264 " 1265{ 1266 operands[5] = gen_reg_rtx (SImode); 1267}") 1268 1269(define_insn "*casesi_insn" 1270 [(set (pc) 1271 (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r") 1272 (const_int 4)) 1273 (label_ref (match_operand 1 "" ""))))) 1274 (clobber (match_scratch:SI 2 "=r")) 1275 (clobber (match_scratch:SI 3 "=r"))] 1276 "" 1277 "* 1278{ 1279 output_asm_insn (\"mov %2,%1\", operands); 1280 if (TARGET_SHIFTER) 1281 output_asm_insn (\"asl %3,%0,2\", operands); 1282 else 1283 output_asm_insn (\"asl %3,%0\;asl %3,%3\", operands); 1284 output_asm_insn (\"ld %2,[%2,%3]\", operands); 1285 output_asm_insn (\"j.nd %a2\", operands); 1286 return \"\"; 1287}" 1288 [(set_attr "type" "uncond_branch") 1289 (set_attr "length" "6")]) 1290 1291(define_insn "tablejump" 1292 [(set (pc) (match_operand:SI 0 "address_operand" "p")) 1293 (use (label_ref (match_operand 1 "" "")))] 1294 "0 /* disabled -> using casesi now */" 1295 "j%* %a0" 1296 [(set_attr "type" "uncond_branch")]) 1297 1298(define_expand "call" 1299 ;; operands[1] is stack_size_rtx 1300 ;; operands[2] is next_arg_register 1301 [(parallel [(call (match_operand:SI 0 "call_operand" "") 1302 (match_operand 1 "" "")) 1303 (clobber (reg:SI 31))])] 1304 "" 1305 "") 1306 1307(define_insn "*call_via_reg" 1308 [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) 1309 (match_operand 1 "" "")) 1310 (clobber (reg:SI 31))] 1311 "" 1312 "lr blink,[status]\;j.d %0\;add blink,blink,2" 1313 [(set_attr "type" "call_no_delay_slot") 1314 (set_attr "length" "3")]) 1315 1316(define_insn "*call_via_label" 1317 [(call (mem:SI (match_operand:SI 0 "call_address_operand" "")) 1318 (match_operand 1 "" "")) 1319 (clobber (reg:SI 31))] 1320 "" 1321 ; The %~ is necessary in case this insn gets conditionalized and the previous 1322 ; insn is the cc setter. 1323 "%~bl%!%* %0" 1324 [(set_attr "type" "call") 1325 (set_attr "cond" "canuse")]) 1326 1327(define_expand "call_value" 1328 ;; operand 2 is stack_size_rtx 1329 ;; operand 3 is next_arg_register 1330 [(parallel [(set (match_operand 0 "register_operand" "=r") 1331 (call (match_operand:SI 1 "call_operand" "") 1332 (match_operand 2 "" ""))) 1333 (clobber (reg:SI 31))])] 1334 "" 1335 "") 1336 1337(define_insn "*call_value_via_reg" 1338 [(set (match_operand 0 "register_operand" "=r") 1339 (call (mem:SI (match_operand:SI 1 "register_operand" "r")) 1340 (match_operand 2 "" ""))) 1341 (clobber (reg:SI 31))] 1342 "" 1343 "lr blink,[status]\;j.d %1\;add blink,blink,2" 1344 [(set_attr "type" "call_no_delay_slot") 1345 (set_attr "length" "3")]) 1346 1347(define_insn "*call_value_via_label" 1348 [(set (match_operand 0 "register_operand" "=r") 1349 (call (mem:SI (match_operand:SI 1 "call_address_operand" "")) 1350 (match_operand 2 "" ""))) 1351 (clobber (reg:SI 31))] 1352 "" 1353 ; The %~ is necessary in case this insn gets conditionalized and the previous 1354 ; insn is the cc setter. 1355 "%~bl%!%* %1" 1356 [(set_attr "type" "call") 1357 (set_attr "cond" "canuse")]) 1358 1359(define_insn "nop" 1360 [(const_int 0)] 1361 "" 1362 "nop" 1363 [(set_attr "type" "misc")]) 1364 1365;; Special pattern to flush the icache. 1366;; ??? Not sure what to do here. Some ARC's are known to support this. 1367 1368(define_insn "flush_icache" 1369 [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)] 1370 "" 1371 "* return \"\";" 1372 [(set_attr "type" "misc")]) 1373 1374;; Split up troublesome insns for better scheduling. 1375 1376;; Peepholes go at the end. 1377