1;; Machine description of the Argonaut ARC cpu for GNU C compiler 2;; Copyright (C) 1994, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. 3 4;; This file is part of GNU CC. 5 6;; GNU CC is free software; you can redistribute it and/or modify 7;; it under the terms of the GNU General Public License as published by 8;; the Free Software Foundation; either version 2, or (at your option) 9;; any later version. 10 11;; GNU CC is distributed in the hope that it will be useful, 12;; but WITHOUT ANY WARRANTY; without even the implied warranty of 13;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14;; GNU General Public License for more details. 15 16;; You should have received a copy of the GNU General Public License 17;; along with GNU CC; see the file COPYING. If not, write to 18;; the Free Software Foundation, 59 Temple Place - Suite 330, 19;; Boston, MA 02111-1307, USA. 20 21;; See file "rtl.def" for documentation on define_insn, match_*, et. al. 22 23;; ??? 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 (eg: 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;; Function units of the ARC 118 119;; (define_function_unit {name} {num-units} {n-users} {test} 120;; {ready-delay} {issue-delay} [{conflict-list}]) 121 122;; 1) A conditional jump cannot immediately follow the insn setting the flags. 123;; This isn't a complete solution as it doesn't come with guarantees. That 124;; is done in the branch patterns and in arc_print_operand. This exists to 125;; avoid inserting a nop when we can. 126(define_function_unit "compare" 1 0 (eq_attr "type" "compare") 2 2 [(eq_attr "type" "branch")]) 127 128;; 2) References to loaded registers should wait a cycle. 129 130;; Memory with load-delay of 1 (i.e., 2 cycle load). 131(define_function_unit "memory" 1 1 (eq_attr "type" "load") 2 0) 132 133;; Units that take one cycle do not need to be specified. 134 135;; Move instructions. 136 137(define_expand "movqi" 138 [(set (match_operand:QI 0 "general_operand" "") 139 (match_operand:QI 1 "general_operand" ""))] 140 "" 141 " 142{ 143 /* Everything except mem = const or mem = mem can be done easily. */ 144 145 if (GET_CODE (operands[0]) == MEM) 146 operands[1] = force_reg (QImode, operands[1]); 147}") 148 149(define_insn "*movqi_insn" 150 [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,m") 151 (match_operand:QI 1 "move_src_operand" "rI,Ji,m,r"))] 152;; ??? Needed? 153 "register_operand (operands[0], QImode) 154 || register_operand (operands[1], QImode)" 155 "@ 156 mov%? %0,%1 157 mov%? %0,%1 158 ldb%U1%V1 %0,%1 159 stb%U0%V0 %1,%0" 160 [(set_attr "type" "move,move,load,store")]) 161 162;; ??? This may never match since there's no cmpqi insn. 163 164(define_insn "*movqi_set_cc_insn" 165 [(set (reg:CCZN 61) (compare:CCZN 166 (sign_extend:SI (match_operand:QI 1 "move_src_operand" "rIJi")) 167 (const_int 0))) 168 (set (match_operand:QI 0 "move_dest_operand" "=r") 169 (match_dup 1))] 170 "" 171 "mov%?.f %0,%1" 172 [(set_attr "type" "move") 173 (set_attr "cond" "set_zn")]) 174 175(define_expand "movhi" 176 [(set (match_operand:HI 0 "general_operand" "") 177 (match_operand:HI 1 "general_operand" ""))] 178 "" 179 " 180{ 181 /* Everything except mem = const or mem = mem can be done easily. */ 182 183 if (GET_CODE (operands[0]) == MEM) 184 operands[1] = force_reg (HImode, operands[1]); 185}") 186 187(define_insn "*movhi_insn" 188 [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,m") 189 (match_operand:HI 1 "move_src_operand" "rI,Ji,m,r"))] 190 "register_operand (operands[0], HImode) 191 || register_operand (operands[1], HImode)" 192 "@ 193 mov%? %0,%1 194 mov%? %0,%1 195 ldw%U1%V1 %0,%1 196 stw%U0%V0 %1,%0" 197 [(set_attr "type" "move,move,load,store")]) 198 199;; ??? Will this ever match? 200 201(define_insn "*movhi_set_cc_insn" 202 [(set (reg:CCZN 61) (compare:CCZN 203 (sign_extend:SI (match_operand:HI 1 "move_src_operand" "rIJi")) 204 (const_int 0))) 205 (set (match_operand:HI 0 "move_dest_operand" "=r") 206 (match_dup 1))] 207;; ??? Needed? 208 "register_operand (operands[0], HImode) 209 || register_operand (operands[1], HImode)" 210 "mov%?.f %0,%1" 211 [(set_attr "type" "move") 212 (set_attr "cond" "set_zn")]) 213 214(define_expand "movsi" 215 [(set (match_operand:SI 0 "general_operand" "") 216 (match_operand:SI 1 "general_operand" ""))] 217 "" 218 " 219{ 220 /* Everything except mem = const or mem = mem can be done easily. */ 221 222 if (GET_CODE (operands[0]) == MEM) 223 operands[1] = force_reg (SImode, operands[1]); 224}") 225 226(define_insn "*movsi_insn" 227 [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,m") 228 (match_operand:SI 1 "move_src_operand" "rI,GJi,m,r"))] 229 "register_operand (operands[0], SImode) 230 || register_operand (operands[1], SImode)" 231 "@ 232 mov%? %0,%1 233 mov%? %0,%S1 234 ld%U1%V1 %0,%1 235 st%U0%V0 %1,%0" 236 [(set_attr "type" "move,move,load,store")]) 237 238(define_insn "*movsi_set_cc_insn" 239 [(set (reg:CCZN 61) (compare:CCZN 240 (match_operand:SI 1 "move_src_operand" "rIJi") 241 (const_int 0))) 242 (set (match_operand:SI 0 "move_dest_operand" "=r") 243 (match_dup 1))] 244 "register_operand (operands[0], SImode) 245 || register_operand (operands[1], SImode)" 246 "mov%?.f %0,%S1" 247 [(set_attr "type" "move") 248 (set_attr "cond" "set_zn")]) 249 250(define_expand "movdi" 251 [(set (match_operand:DI 0 "general_operand" "") 252 (match_operand:DI 1 "general_operand" ""))] 253 "" 254 " 255{ 256 /* Everything except mem = const or mem = mem can be done easily. */ 257 258 if (GET_CODE (operands[0]) == MEM) 259 operands[1] = force_reg (DImode, operands[1]); 260}") 261 262(define_insn "*movdi_insn" 263 [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,m") 264 (match_operand:DI 1 "move_double_src_operand" "r,HK,m,r"))] 265 "register_operand (operands[0], DImode) 266 || register_operand (operands[1], DImode)" 267 "* 268{ 269 switch (which_alternative) 270 { 271 case 0 : 272 /* We normally copy the low-numbered register first. However, if 273 the first register operand 0 is the same as the second register of 274 operand 1, we must copy in the opposite order. */ 275 if (REGNO (operands[0]) == REGNO (operands[1]) + 1) 276 return \"mov %R0,%R1\;mov %0,%1\"; 277 else 278 return \"mov %0,%1\;mov %R0,%R1\"; 279 case 1 : 280 return \"mov %0,%L1\;mov %R0,%H1\"; 281 case 2 : 282 /* If the low-address word is used in the address, we must load it 283 last. Otherwise, load it first. Note that we cannot have 284 auto-increment in that case since the address register is known to be 285 dead. */ 286 if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, 287 operands [1], 0)) 288 return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\"; 289 else 290 return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\"; 291 case 3 : 292 return \"st%V0 %1,%0\;st%V0 %R1,%R0\"; 293 default: 294 abort(); 295 } 296}" 297 [(set_attr "type" "move,move,load,store") 298 ;; ??? The ld/st values could be 4 if it's [reg,bignum]. 299 (set_attr "length" "2,4,2,2")]) 300 301;(define_expand "movdi" 302; [(set (match_operand:DI 0 "general_operand" "") 303; (match_operand:DI 1 "general_operand" ""))] 304; "" 305; " 306;{ 307; /* Flow doesn't understand that this is effectively a DFmode move. 308; It doesn't know that all of `operands[0]' is set. */ 309; emit_insn (gen_rtx_CLOBBER (VOIDmode, operands[0])); 310; 311; /* Emit insns that movsi_insn can handle. */ 312; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DImode), 313; operand_subword (operands[1], 0, 0, DImode))); 314; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DImode), 315; operand_subword (operands[1], 1, 0, DImode))); 316; DONE; 317;}") 318 319;; Floating point move insns. 320 321(define_expand "movsf" 322 [(set (match_operand:SF 0 "general_operand" "") 323 (match_operand:SF 1 "general_operand" ""))] 324 "" 325 " 326{ 327 /* Everything except mem = const or mem = mem can be done easily. */ 328 if (GET_CODE (operands[0]) == MEM) 329 operands[1] = force_reg (SFmode, operands[1]); 330}") 331 332(define_insn "*movsf_insn" 333 [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,m") 334 (match_operand:SF 1 "move_src_operand" "r,E,m,r"))] 335 "register_operand (operands[0], SFmode) 336 || register_operand (operands[1], SFmode)" 337 "@ 338 mov%? %0,%1 339 mov%? %0,%1 ; %A1 340 ld%U1%V1 %0,%1 341 st%U0%V0 %1,%0" 342 [(set_attr "type" "move,move,load,store")]) 343 344(define_expand "movdf" 345 [(set (match_operand:DF 0 "general_operand" "") 346 (match_operand:DF 1 "general_operand" ""))] 347 "" 348 " 349{ 350 /* Everything except mem = const or mem = mem can be done easily. */ 351 if (GET_CODE (operands[0]) == MEM) 352 operands[1] = force_reg (DFmode, operands[1]); 353}") 354 355(define_insn "*movdf_insn" 356 [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m") 357 (match_operand:DF 1 "move_double_src_operand" "r,E,m,r"))] 358 "register_operand (operands[0], DFmode) 359 || register_operand (operands[1], DFmode)" 360 "* 361{ 362 switch (which_alternative) 363 { 364 case 0 : 365 /* We normally copy the low-numbered register first. However, if 366 the first register operand 0 is the same as the second register of 367 operand 1, we must copy in the opposite order. */ 368 if (REGNO (operands[0]) == REGNO (operands[1]) + 1) 369 return \"mov %R0,%R1\;mov %0,%1\"; 370 else 371 return \"mov %0,%1\;mov %R0,%R1\"; 372 case 1 : 373 return \"mov %0,%L1\;mov %R0,%H1 ; %A1\"; 374 case 2 : 375 /* If the low-address word is used in the address, we must load it 376 last. Otherwise, load it first. Note that we cannot have 377 auto-increment in that case since the address register is known to be 378 dead. */ 379 if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, 380 operands [1], 0)) 381 return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\"; 382 else 383 return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\"; 384 case 3 : 385 return \"st%V0 %1,%0\;st%V0 %R1,%R0\"; 386 default: 387 abort(); 388 } 389}" 390 [(set_attr "type" "move,move,load,store") 391 ;; ??? The ld/st values could be 4 if it's [reg,bignum]. 392 (set_attr "length" "2,4,2,2")]) 393 394;(define_expand "movdf" 395; [(set (match_operand:DF 0 "general_operand" "") 396; (match_operand:DF 1 "general_operand" ""))] 397; "" 398; " 399;{ 400; /* Flow doesn't understand that this is effectively a DFmode move. 401; It doesn't know that all of `operands[0]' is set. */ 402; emit_insn (gen_rtx_CLOBBER (VOIDmode, operands[0])); 403; 404; /* Emit insns that movsi_insn can handle. */ 405; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DFmode), 406; operand_subword (operands[1], 0, 0, DFmode))); 407; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DFmode), 408; operand_subword (operands[1], 1, 0, DFmode))); 409; DONE; 410;}") 411 412;; Load/Store with update instructions. 413;; 414;; Some of these we can get by using pre-decrement or pre-increment, but the 415;; hardware can also do cases where the increment is not the size of the 416;; object. 417;; 418;; In all these cases, we use operands 0 and 1 for the register being 419;; incremented because those are the operands that local-alloc will 420;; tie and these are the pair most likely to be tieable (and the ones 421;; that will benefit the most). 422;; 423;; We use match_operator here because we need to know whether the memory 424;; object is volatile or not. 425 426(define_insn "*loadqi_update" 427 [(set (match_operand:QI 3 "register_operand" "=r,r") 428 (match_operator:QI 4 "load_update_operand" 429 [(match_operand:SI 1 "register_operand" "0,0") 430 (match_operand:SI 2 "nonmemory_operand" "rI,J")])) 431 (set (match_operand:SI 0 "register_operand" "=r,r") 432 (plus:SI (match_dup 1) (match_dup 2)))] 433 "" 434 "ldb.a%V4 %3,[%0,%2]" 435 [(set_attr "type" "load,load") 436 (set_attr "length" "1,2")]) 437 438(define_insn "*load_zeroextendqisi_update" 439 [(set (match_operand:SI 3 "register_operand" "=r,r") 440 (zero_extend:SI (match_operator:QI 4 "load_update_operand" 441 [(match_operand:SI 1 "register_operand" "0,0") 442 (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) 443 (set (match_operand:SI 0 "register_operand" "=r,r") 444 (plus:SI (match_dup 1) (match_dup 2)))] 445 "" 446 "ldb.a%V4 %3,[%0,%2]" 447 [(set_attr "type" "load,load") 448 (set_attr "length" "1,2")]) 449 450(define_insn "*load_signextendqisi_update" 451 [(set (match_operand:SI 3 "register_operand" "=r,r") 452 (sign_extend:SI (match_operator:QI 4 "load_update_operand" 453 [(match_operand:SI 1 "register_operand" "0,0") 454 (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) 455 (set (match_operand:SI 0 "register_operand" "=r,r") 456 (plus:SI (match_dup 1) (match_dup 2)))] 457 "" 458 "ldb.x.a%V4 %3,[%0,%2]" 459 [(set_attr "type" "load,load") 460 (set_attr "length" "1,2")]) 461 462(define_insn "*storeqi_update" 463 [(set (match_operator:QI 4 "store_update_operand" 464 [(match_operand:SI 1 "register_operand" "0") 465 (match_operand:SI 2 "short_immediate_operand" "I")]) 466 (match_operand:QI 3 "register_operand" "r")) 467 (set (match_operand:SI 0 "register_operand" "=r") 468 (plus:SI (match_dup 1) (match_dup 2)))] 469 "" 470 "stb.a%V4 %3,[%0,%2]" 471 [(set_attr "type" "store") 472 (set_attr "length" "1")]) 473 474(define_insn "*loadhi_update" 475 [(set (match_operand:HI 3 "register_operand" "=r,r") 476 (match_operator:HI 4 "load_update_operand" 477 [(match_operand:SI 1 "register_operand" "0,0") 478 (match_operand:SI 2 "nonmemory_operand" "rI,J")])) 479 (set (match_operand:SI 0 "register_operand" "=r,r") 480 (plus:SI (match_dup 1) (match_dup 2)))] 481 "" 482 "ldw.a%V4 %3,[%0,%2]" 483 [(set_attr "type" "load,load") 484 (set_attr "length" "1,2")]) 485 486(define_insn "*load_zeroextendhisi_update" 487 [(set (match_operand:SI 3 "register_operand" "=r,r") 488 (zero_extend:SI (match_operator:HI 4 "load_update_operand" 489 [(match_operand:SI 1 "register_operand" "0,0") 490 (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) 491 (set (match_operand:SI 0 "register_operand" "=r,r") 492 (plus:SI (match_dup 1) (match_dup 2)))] 493 "" 494 "ldw.a%V4 %3,[%0,%2]" 495 [(set_attr "type" "load,load") 496 (set_attr "length" "1,2")]) 497 498(define_insn "*load_signextendhisi_update" 499 [(set (match_operand:SI 3 "register_operand" "=r,r") 500 (sign_extend:SI (match_operator:HI 4 "load_update_operand" 501 [(match_operand:SI 1 "register_operand" "0,0") 502 (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) 503 (set (match_operand:SI 0 "register_operand" "=r,r") 504 (plus:SI (match_dup 1) (match_dup 2)))] 505 "" 506 "ldw.x.a%V4 %3,[%0,%2]" 507 [(set_attr "type" "load,load") 508 (set_attr "length" "1,2")]) 509 510(define_insn "*storehi_update" 511 [(set (match_operator:HI 4 "store_update_operand" 512 [(match_operand:SI 1 "register_operand" "0") 513 (match_operand:SI 2 "short_immediate_operand" "I")]) 514 (match_operand:HI 3 "register_operand" "r")) 515 (set (match_operand:SI 0 "register_operand" "=r") 516 (plus:SI (match_dup 1) (match_dup 2)))] 517 "" 518 "stw.a%V4 %3,[%0,%2]" 519 [(set_attr "type" "store") 520 (set_attr "length" "1")]) 521 522(define_insn "*loadsi_update" 523 [(set (match_operand:SI 3 "register_operand" "=r,r") 524 (match_operator:SI 4 "load_update_operand" 525 [(match_operand:SI 1 "register_operand" "0,0") 526 (match_operand:SI 2 "nonmemory_operand" "rI,J")])) 527 (set (match_operand:SI 0 "register_operand" "=r,r") 528 (plus:SI (match_dup 1) (match_dup 2)))] 529 "" 530 "ld.a%V4 %3,[%0,%2]" 531 [(set_attr "type" "load,load") 532 (set_attr "length" "1,2")]) 533 534(define_insn "*storesi_update" 535 [(set (match_operator:SI 4 "store_update_operand" 536 [(match_operand:SI 1 "register_operand" "0") 537 (match_operand:SI 2 "short_immediate_operand" "I")]) 538 (match_operand:SI 3 "register_operand" "r")) 539 (set (match_operand:SI 0 "register_operand" "=r") 540 (plus:SI (match_dup 1) (match_dup 2)))] 541 "" 542 "st.a%V4 %3,[%0,%2]" 543 [(set_attr "type" "store") 544 (set_attr "length" "1")]) 545 546(define_insn "*loadsf_update" 547 [(set (match_operand:SF 3 "register_operand" "=r,r") 548 (match_operator:SF 4 "load_update_operand" 549 [(match_operand:SI 1 "register_operand" "0,0") 550 (match_operand:SI 2 "nonmemory_operand" "rI,J")])) 551 (set (match_operand:SI 0 "register_operand" "=r,r") 552 (plus:SI (match_dup 1) (match_dup 2)))] 553 "" 554 "ld.a%V4 %3,[%0,%2]" 555 [(set_attr "type" "load,load") 556 (set_attr "length" "1,2")]) 557 558(define_insn "*storesf_update" 559 [(set (match_operator:SF 4 "store_update_operand" 560 [(match_operand:SI 1 "register_operand" "0") 561 (match_operand:SI 2 "short_immediate_operand" "I")]) 562 (match_operand:SF 3 "register_operand" "r")) 563 (set (match_operand:SI 0 "register_operand" "=r") 564 (plus:SI (match_dup 1) (match_dup 2)))] 565 "" 566 "st.a%V4 %3,[%0,%2]" 567 [(set_attr "type" "store") 568 (set_attr "length" "1")]) 569 570;; Conditional move instructions. 571 572(define_expand "movsicc" 573 [(set (match_operand:SI 0 "register_operand" "") 574 (if_then_else:SI (match_operand 1 "comparison_operator" "") 575 (match_operand:SI 2 "nonmemory_operand" "") 576 (match_operand:SI 3 "register_operand" "")))] 577 "" 578 " 579{ 580 enum rtx_code code = GET_CODE (operands[1]); 581 rtx ccreg 582 = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), 583 61); 584 585 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 586}") 587 588;(define_expand "movdicc" 589; [(set (match_operand:DI 0 "register_operand" "") 590; (if_then_else:DI (match_operand 1 "comparison_operator" "") 591; (match_operand:DI 2 "nonmemory_operand" "") 592; (match_operand:DI 3 "register_operand" "")))] 593; "0 /* ??? this would work better if we had cmpdi */" 594; " 595;{ 596; enum rtx_code code = GET_CODE (operands[1]); 597; rtx ccreg 598; = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), 599; 61); 600; 601; operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 602;}") 603 604(define_expand "movsfcc" 605 [(set (match_operand:SF 0 "register_operand" "") 606 (if_then_else:SF (match_operand 1 "comparison_operator" "") 607 (match_operand:SF 2 "nonmemory_operand" "") 608 (match_operand:SF 3 "register_operand" "")))] 609 "" 610 " 611{ 612 enum rtx_code code = GET_CODE (operands[1]); 613 rtx ccreg 614 = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), 615 61); 616 617 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 618}") 619 620;(define_expand "movdfcc" 621; [(set (match_operand:DF 0 "register_operand" "") 622; (if_then_else:DF (match_operand 1 "comparison_operator" "") 623; (match_operand:DF 2 "nonmemory_operand" "") 624; (match_operand:DF 3 "register_operand" "")))] 625; "0 /* ??? can generate less efficient code if constants involved */" 626; " 627;{ 628; enum rtx_code code = GET_CODE (operands[1]); 629; rtx ccreg 630; = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), 631; 61); 632; 633; operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 634;}") 635 636(define_insn "*movsicc_insn" 637 [(set (match_operand:SI 0 "register_operand" "=r") 638 (if_then_else:SI (match_operand 1 "comparison_operator" "") 639 (match_operand:SI 2 "nonmemory_operand" "rJi") 640 (match_operand:SI 3 "register_operand" "0")))] 641 "" 642 "mov.%d1 %0,%S2" 643 [(set_attr "type" "cmove")]) 644 645; ??? This doesn't properly handle constants. 646;(define_insn "*movdicc_insn" 647; [(set (match_operand:DI 0 "register_operand" "=r,r") 648; (if_then_else:DI (match_operand 1 "comparison_operator" "") 649; (match_operand:DI 2 "nonmemory_operand" "r,Ji") 650; (match_operand:DI 3 "register_operand" "0,0")))] 651; "0" 652; "* 653;{ 654; switch (which_alternative) 655; { 656; case 0 : 657; /* We normally copy the low-numbered register first. However, if 658; the first register operand 0 is the same as the second register of 659; operand 1, we must copy in the opposite order. */ 660; if (REGNO (operands[0]) == REGNO (operands[2]) + 1) 661; return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\"; 662; else 663; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; 664; case 1 : 665; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; 666; } 667;}" 668; [(set_attr "type" "cmove,cmove") 669; (set_attr "length" "2,4")]) 670 671(define_insn "*movsfcc_insn" 672 [(set (match_operand:SF 0 "register_operand" "=r,r") 673 (if_then_else:SF (match_operand 1 "comparison_operator" "") 674 (match_operand:SF 2 "nonmemory_operand" "r,E") 675 (match_operand:SF 3 "register_operand" "0,0")))] 676 "" 677 "@ 678 mov.%d1 %0,%2 679 mov.%d1 %0,%2 ; %A2" 680 [(set_attr "type" "cmove,cmove")]) 681 682;(define_insn "*movdfcc_insn" 683; [(set (match_operand:DF 0 "register_operand" "=r,r") 684; (if_then_else:DF (match_operand 1 "comparison_operator" "") 685; (match_operand:DF 2 "nonmemory_operand" "r,E") 686; (match_operand:DF 3 "register_operand" "0,0")))] 687; "0" 688; "* 689;{ 690; switch (which_alternative) 691; { 692; case 0 : 693; /* We normally copy the low-numbered register first. However, if 694; the first register operand 0 is the same as the second register of 695; operand 1, we must copy in the opposite order. */ 696; if (REGNO (operands[0]) == REGNO (operands[2]) + 1) 697; return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\"; 698; else 699; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; 700; case 1 : 701; return \"mov.%d1 %0,%L2\;mov.%d1 %R0,%H2 ; %A2\"; 702; } 703;}" 704; [(set_attr "type" "cmove,cmove") 705; (set_attr "length" "2,4")]) 706 707;; Zero extension instructions. 708;; ??? We don't support volatile memrefs here, but I'm not sure why. 709 710(define_insn "zero_extendqihi2" 711 [(set (match_operand:HI 0 "register_operand" "=r,r") 712 (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] 713 "" 714 "@ 715 extb%? %0,%1 716 ldb%U1 %0,%1" 717 [(set_attr "type" "unary,load")]) 718 719(define_insn "*zero_extendqihi2_set_cc_insn" 720 [(set (reg:CCZN 61) (compare:CCZN 721 (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) 722 (const_int 0))) 723 (set (match_operand:HI 0 "register_operand" "=r") 724 (zero_extend:HI (match_dup 1)))] 725 "" 726 "extb%?.f %0,%1" 727 [(set_attr "type" "unary") 728 (set_attr "cond" "set_zn")]) 729 730(define_insn "zero_extendqisi2" 731 [(set (match_operand:SI 0 "register_operand" "=r,r") 732 (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] 733 "" 734 "@ 735 extb%? %0,%1 736 ldb%U1 %0,%1" 737 [(set_attr "type" "unary,load")]) 738 739(define_insn "*zero_extendqisi2_set_cc_insn" 740 [(set (reg:CCZN 61) (compare:CCZN 741 (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) 742 (const_int 0))) 743 (set (match_operand:SI 0 "register_operand" "=r") 744 (zero_extend:SI (match_dup 1)))] 745 "" 746 "extb%?.f %0,%1" 747 [(set_attr "type" "unary") 748 (set_attr "cond" "set_zn")]) 749 750(define_insn "zero_extendhisi2" 751 [(set (match_operand:SI 0 "register_operand" "=r,r") 752 (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))] 753 "" 754 "@ 755 extw%? %0,%1 756 ldw%U1 %0,%1" 757 [(set_attr "type" "unary,load")]) 758 759(define_insn "*zero_extendhisi2_set_cc_insn" 760 [(set (reg:CCZN 61) (compare:CCZN 761 (zero_extend:SI (match_operand:HI 1 "register_operand" "r")) 762 (const_int 0))) 763 (set (match_operand:SI 0 "register_operand" "=r") 764 (zero_extend:SI (match_dup 1)))] 765 "" 766 "extw%?.f %0,%1" 767 [(set_attr "type" "unary") 768 (set_attr "cond" "set_zn")]) 769 770;; Sign extension instructions. 771 772(define_insn "extendqihi2" 773 [(set (match_operand:HI 0 "register_operand" "=r,r") 774 (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] 775 "" 776 "@ 777 sexb%? %0,%1 778 ldb.x%U1 %0,%1" 779 [(set_attr "type" "unary,load")]) 780 781(define_insn "*extendqihi2_set_cc_insn" 782 [(set (reg:CCZN 61) (compare:CCZN 783 (sign_extend:SI (match_operand:QI 1 "register_operand" "r")) 784 (const_int 0))) 785 (set (match_operand:HI 0 "register_operand" "=r") 786 (sign_extend:HI (match_dup 1)))] 787 "" 788 "sexb%?.f %0,%1" 789 [(set_attr "type" "unary") 790 (set_attr "cond" "set_zn")]) 791 792(define_insn "extendqisi2" 793 [(set (match_operand:SI 0 "register_operand" "=r,r") 794 (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] 795 "" 796 "@ 797 sexb%? %0,%1 798 ldb.x%U1 %0,%1" 799 [(set_attr "type" "unary,load")]) 800 801(define_insn "*extendqisi2_set_cc_insn" 802 [(set (reg:CCZN 61) (compare:CCZN 803 (sign_extend:SI (match_operand:QI 1 "register_operand" "r")) 804 (const_int 0))) 805 (set (match_operand:SI 0 "register_operand" "=r") 806 (sign_extend:SI (match_dup 1)))] 807 "" 808 "sexb%?.f %0,%1" 809 [(set_attr "type" "unary") 810 (set_attr "cond" "set_zn")]) 811 812(define_insn "extendhisi2" 813 [(set (match_operand:SI 0 "register_operand" "=r,r") 814 (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))] 815 "" 816 "@ 817 sexw%? %0,%1 818 ldw.x%U1 %0,%1" 819 [(set_attr "type" "unary,load")]) 820 821(define_insn "*extendhisi2_set_cc_insn" 822 [(set (reg:CCZN 61) (compare:CCZN 823 (sign_extend:SI (match_operand:HI 1 "register_operand" "r")) 824 (const_int 0))) 825 (set (match_operand:SI 0 "register_operand" "=r") 826 (sign_extend:SI (match_dup 1)))] 827 "" 828 "sexw%?.f %0,%1" 829 [(set_attr "type" "unary") 830 (set_attr "cond" "set_zn")]) 831 832;; Arithmetic instructions. 833 834(define_insn "addsi3" 835 [(set (match_operand:SI 0 "register_operand" "=r") 836 (plus:SI (match_operand:SI 1 "register_operand" "%r") 837 (match_operand:SI 2 "nonmemory_operand" "rIJ")))] 838 "" 839 "add%? %0,%1,%2") 840 841(define_insn "*addsi3_set_cc_insn" 842 [(set (reg:CC 61) (compare:CC 843 (plus:SI (match_operand:SI 1 "register_operand" "%r") 844 (match_operand:SI 2 "nonmemory_operand" "rIJ")) 845 (const_int 0))) 846 (set (match_operand:SI 0 "register_operand" "=r") 847 (plus:SI (match_dup 1) 848 (match_dup 2)))] 849 "" 850 "add%?.f %0,%1,%2" 851 [(set_attr "cond" "set")]) 852 853(define_insn "adddi3" 854 [(set (match_operand:DI 0 "register_operand" "=r") 855 (plus:DI (match_operand:DI 1 "nonmemory_operand" "%r") 856 (match_operand:DI 2 "nonmemory_operand" "ri"))) 857 (clobber (reg:CC 61))] 858 "" 859 "* 860{ 861 rtx op2 = operands[2]; 862 863 if (GET_CODE (op2) == CONST_INT) 864 { 865 int sign = INTVAL (op2); 866 if (sign < 0) 867 return \"add.f %L0,%L1,%2\;adc %H0,%H1,-1\"; 868 else 869 return \"add.f %L0,%L1,%2\;adc %H0,%H1,0\"; 870 } 871 else 872 return \"add.f %L0,%L1,%L2\;adc %H0,%H1,%H2\"; 873}" 874 [(set_attr "length" "2")]) 875 876(define_insn "subsi3" 877 [(set (match_operand:SI 0 "register_operand" "=r") 878 (minus:SI (match_operand:SI 1 "register_operand" "r") 879 (match_operand:SI 2 "nonmemory_operand" "rIJ")))] 880 "" 881 "sub%? %0,%1,%2") 882 883(define_insn "*subsi3_set_cc_insn" 884 [(set (reg:CC 61) (compare:CC 885 (minus:SI (match_operand:SI 1 "register_operand" "%r") 886 (match_operand:SI 2 "nonmemory_operand" "rIJ")) 887 (const_int 0))) 888 (set (match_operand:SI 0 "register_operand" "=r") 889 (minus:SI (match_dup 1) 890 (match_dup 2)))] 891 "" 892 "sub%?.f %0,%1,%2" 893 [(set_attr "cond" "set")]) 894 895(define_insn "subdi3" 896 [(set (match_operand:DI 0 "register_operand" "=r") 897 (minus:DI (match_operand:DI 1 "nonmemory_operand" "r") 898 (match_operand:DI 2 "nonmemory_operand" "ri"))) 899 (clobber (reg:CC 61))] 900 "" 901 "* 902{ 903 rtx op2 = operands[2]; 904 905 if (GET_CODE (op2) == CONST_INT) 906 { 907 int sign = INTVAL (op2); 908 if (sign < 0) 909 return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,-1\"; 910 else 911 return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,0\"; 912 } 913 else 914 return \"sub.f %L0,%L1,%L2\;sbc %H0,%H1,%H2\"; 915}" 916 [(set_attr "length" "2")]) 917 918;; Boolean instructions. 919;; 920;; We don't define the DImode versions as expand_binop does a good enough job. 921 922(define_insn "andsi3" 923 [(set (match_operand:SI 0 "register_operand" "=r") 924 (and:SI (match_operand:SI 1 "register_operand" "%r") 925 (match_operand:SI 2 "nonmemory_operand" "rIJ")))] 926 "" 927 "and%? %0,%1,%2") 928 929(define_insn "*andsi3_set_cc_insn" 930 [(set (reg:CCZN 61) (compare:CCZN 931 (and:SI (match_operand:SI 1 "register_operand" "%r") 932 (match_operand:SI 2 "nonmemory_operand" "rIJ")) 933 (const_int 0))) 934 (set (match_operand:SI 0 "register_operand" "=r") 935 (and:SI (match_dup 1) 936 (match_dup 2)))] 937 "" 938 "and%?.f %0,%1,%2" 939 [(set_attr "cond" "set_zn")]) 940 941(define_insn "*bicsi3_insn" 942 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") 943 (and:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") 944 (not:SI (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r"))))] 945 "" 946 "bic%? %0,%1,%2" 947 [(set_attr "length" "1,2,1,2")]) 948 949(define_insn "*bicsi3_set_cc_insn" 950 [(set (reg:CCZN 61) (compare:CCZN 951 (and:SI (match_operand:SI 1 "register_operand" "%r") 952 (not:SI (match_operand:SI 2 "nonmemory_operand" "rIJ"))) 953 (const_int 0))) 954 (set (match_operand:SI 0 "register_operand" "=r") 955 (and:SI (match_dup 1) 956 (not:SI (match_dup 2))))] 957 "" 958 "bic%?.f %0,%1,%2" 959 [(set_attr "cond" "set_zn")]) 960 961(define_insn "iorsi3" 962 [(set (match_operand:SI 0 "register_operand" "=r") 963 (ior:SI (match_operand:SI 1 "register_operand" "%r") 964 (match_operand:SI 2 "nonmemory_operand" "rIJ")))] 965 "" 966 "or%? %0,%1,%2") 967 968(define_insn "*iorsi3_set_cc_insn" 969 [(set (reg:CCZN 61) (compare:CCZN 970 (ior:SI (match_operand:SI 1 "register_operand" "%r") 971 (match_operand:SI 2 "nonmemory_operand" "rIJ")) 972 (const_int 0))) 973 (set (match_operand:SI 0 "register_operand" "=r") 974 (ior:SI (match_dup 1) 975 (match_dup 2)))] 976 "" 977 "or%?.f %0,%1,%2" 978 [(set_attr "cond" "set_zn")]) 979 980(define_insn "xorsi3" 981 [(set (match_operand:SI 0 "register_operand" "=r") 982 (xor:SI (match_operand:SI 1 "register_operand" "%r") 983 (match_operand:SI 2 "nonmemory_operand" "rIJ")))] 984 "" 985 "xor%? %0,%1,%2") 986 987(define_insn "*xorsi3_set_cc_insn" 988 [(set (reg:CCZN 61) (compare:CCZN 989 (xor:SI (match_operand:SI 1 "register_operand" "%r") 990 (match_operand:SI 2 "nonmemory_operand" "rIJ")) 991 (const_int 0))) 992 (set (match_operand:SI 0 "register_operand" "=r") 993 (xor:SI (match_dup 1) 994 (match_dup 2)))] 995 "" 996 "xor%?.f %0,%1,%2" 997 [(set_attr "cond" "set_zn")]) 998 999(define_insn "negsi2" 1000 [(set (match_operand:SI 0 "register_operand" "=r") 1001 (neg:SI (match_operand:SI 1 "register_operand" "r")))] 1002 "" 1003 "sub%? %0,0,%1" 1004 [(set_attr "type" "unary")]) 1005 1006(define_insn "*negsi2_set_cc_insn" 1007 [(set (reg:CC 61) (compare:CC 1008 (neg:SI (match_operand:SI 1 "register_operand" "r")) 1009 (const_int 0))) 1010 (set (match_operand:SI 0 "register_operand" "=r") 1011 (neg:SI (match_dup 1)))] 1012 "" 1013 "sub%?.f %0,0,%1" 1014 [(set_attr "type" "unary") 1015 (set_attr "cond" "set")]) 1016 1017(define_insn "negdi2" 1018 [(set (match_operand:DI 0 "register_operand" "=r") 1019 (neg:DI (match_operand:DI 1 "register_operand" "r"))) 1020 (clobber (reg:SI 61))] 1021 "" 1022 "sub.f %L0,0,%L1\;sbc %H0,0,%H1" 1023 [(set_attr "type" "unary") 1024 (set_attr "length" "2")]) 1025 1026(define_insn "one_cmplsi2" 1027 [(set (match_operand:SI 0 "register_operand" "=r") 1028 (not:SI (match_operand:SI 1 "register_operand" "r")))] 1029 "" 1030 "xor%? %0,%1,-1" 1031 [(set_attr "type" "unary")]) 1032 1033(define_insn "*one_cmplsi2_set_cc_insn" 1034 [(set (reg:CCZN 61) (compare:CCZN 1035 (not:SI (match_operand:SI 1 "register_operand" "r")) 1036 (const_int 0))) 1037 (set (match_operand:SI 0 "register_operand" "=r") 1038 (not:SI (match_dup 1)))] 1039 "" 1040 "xor%?.f %0,%1,-1" 1041 [(set_attr "type" "unary") 1042 (set_attr "cond" "set_zn")]) 1043 1044;; Shift instructions. 1045 1046(define_expand "ashlsi3" 1047 [(set (match_operand:SI 0 "register_operand" "") 1048 (ashift:SI (match_operand:SI 1 "register_operand" "") 1049 (match_operand:SI 2 "nonmemory_operand" "")))] 1050 "" 1051 " 1052{ 1053 if (! TARGET_SHIFTER) 1054 { 1055 emit_insn (gen_rtx_PARALLEL 1056 (VOIDmode, 1057 gen_rtvec (2, 1058 gen_rtx_SET (VOIDmode, operands[0], 1059 gen_rtx_ASHIFT (SImode, operands[1], 1060 operands[2])), 1061 gen_rtx_CLOBBER (VOIDmode, 1062 gen_rtx_SCRATCH (SImode))))); 1063 DONE; 1064 } 1065}") 1066 1067(define_expand "ashrsi3" 1068 [(set (match_operand:SI 0 "register_operand" "") 1069 (ashiftrt:SI (match_operand:SI 1 "register_operand" "") 1070 (match_operand:SI 2 "nonmemory_operand" "")))] 1071 "" 1072 " 1073{ 1074 if (! TARGET_SHIFTER) 1075 { 1076 emit_insn (gen_rtx_PARALLEL 1077 (VOIDmode, 1078 gen_rtvec (2, 1079 gen_rtx_SET (VOIDmode, operands[0], 1080 gen_rtx_ASHIFTRT (SImode, 1081 operands[1], 1082 operands[2])), 1083 gen_rtx_CLOBBER (VOIDmode, 1084 gen_rtx_SCRATCH (SImode))))); 1085 DONE; 1086 } 1087}") 1088 1089(define_expand "lshrsi3" 1090 [(set (match_operand:SI 0 "register_operand" "") 1091 (lshiftrt:SI (match_operand:SI 1 "register_operand" "") 1092 (match_operand:SI 2 "nonmemory_operand" "")))] 1093 "" 1094 " 1095{ 1096 if (! TARGET_SHIFTER) 1097 { 1098 emit_insn (gen_rtx_PARALLEL 1099 (VOIDmode, 1100 gen_rtvec (2, 1101 gen_rtx_SET (VOIDmode, operands[0], 1102 gen_rtx_LSHIFTRT (SImode, 1103 operands[1], 1104 operands[2])), 1105 gen_rtx_CLOBBER (VOIDmode, 1106 gen_rtx_SCRATCH (SImode))))); 1107 DONE; 1108 } 1109}") 1110 1111(define_insn "*ashlsi3_insn" 1112 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") 1113 (ashift:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") 1114 (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))] 1115 "TARGET_SHIFTER" 1116 "asl%? %0,%1,%2" 1117 [(set_attr "type" "shift") 1118 (set_attr "length" "1,2,1,2")]) 1119 1120(define_insn "*ashrsi3_insn" 1121 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") 1122 (ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") 1123 (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))] 1124 "TARGET_SHIFTER" 1125 "asr%? %0,%1,%2" 1126 [(set_attr "type" "shift") 1127 (set_attr "length" "1,2,1,2")]) 1128 1129(define_insn "*lshrsi3_insn" 1130 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") 1131 (lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") 1132 (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))] 1133 "TARGET_SHIFTER" 1134 "lsr%? %0,%1,%2" 1135 [(set_attr "type" "shift") 1136 (set_attr "length" "1,2,1,2")]) 1137 1138(define_insn "*shift_si3" 1139 [(set (match_operand:SI 0 "register_operand" "=r") 1140 (match_operator:SI 3 "shift_operator" 1141 [(match_operand:SI 1 "register_operand" "0") 1142 (match_operand:SI 2 "nonmemory_operand" "rIJ")])) 1143 (clobber (match_scratch:SI 4 "=&r"))] 1144 "! TARGET_SHIFTER" 1145 "* return output_shift (operands);" 1146 [(set_attr "type" "shift") 1147 (set_attr "length" "8")]) 1148 1149;; Compare instructions. 1150;; This controls RTL generation and register allocation. 1151 1152;; We generate RTL for comparisons and branches by having the cmpxx 1153;; patterns store away the operands. Then, the scc and bcc patterns 1154;; emit RTL for both the compare and the branch. 1155 1156(define_expand "cmpsi" 1157 [(set (reg:CC 61) 1158 (compare:CC (match_operand:SI 0 "register_operand" "") 1159 (match_operand:SI 1 "nonmemory_operand" "")))] 1160 "" 1161 " 1162{ 1163 arc_compare_op0 = operands[0]; 1164 arc_compare_op1 = operands[1]; 1165 DONE; 1166}") 1167 1168;; ??? We may be able to relax this a bit by adding a new constant 'K' for 0. 1169;; This assumes sub.f 0,symbol,0 is a valid insn. 1170;; Note that "sub.f 0,r0,1" is an 8 byte insn. To avoid unnecessarily 1171;; creating 8 byte insns we duplicate %1 in the destination reg of the insn 1172;; if it's a small constant. 1173 1174(define_insn "*cmpsi_cc_insn" 1175 [(set (reg:CC 61) 1176 (compare:CC (match_operand:SI 0 "register_operand" "r,r,r") 1177 (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] 1178 "" 1179 "@ 1180 sub.f 0,%0,%1 1181 sub.f %1,%0,%1 1182 sub.f 0,%0,%1" 1183 [(set_attr "type" "compare,compare,compare")]) 1184 1185(define_insn "*cmpsi_cczn_insn" 1186 [(set (reg:CCZN 61) 1187 (compare:CCZN (match_operand:SI 0 "register_operand" "r,r,r") 1188 (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] 1189 "" 1190 "@ 1191 sub.f 0,%0,%1 1192 sub.f %1,%0,%1 1193 sub.f 0,%0,%1" 1194 [(set_attr "type" "compare,compare,compare")]) 1195 1196(define_insn "*cmpsi_ccznc_insn" 1197 [(set (reg:CCZNC 61) 1198 (compare:CCZNC (match_operand:SI 0 "register_operand" "r,r,r") 1199 (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] 1200 "" 1201 "@ 1202 sub.f 0,%0,%1 1203 sub.f %1,%0,%1 1204 sub.f 0,%0,%1" 1205 [(set_attr "type" "compare,compare,compare")]) 1206 1207;; Next come the scc insns. 1208 1209(define_expand "seq" 1210 [(set (match_operand:SI 0 "register_operand" "=r") 1211 (eq:SI (match_dup 1) (const_int 0)))] 1212 "" 1213 " 1214{ 1215 operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1); 1216}") 1217 1218(define_expand "sne" 1219 [(set (match_operand:SI 0 "register_operand" "=r") 1220 (ne:SI (match_dup 1) (const_int 0)))] 1221 "" 1222 " 1223{ 1224 operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1); 1225}") 1226 1227(define_expand "sgt" 1228 [(set (match_operand:SI 0 "register_operand" "=r") 1229 (gt:SI (match_dup 1) (const_int 0)))] 1230 "" 1231 " 1232{ 1233 operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1); 1234}") 1235 1236(define_expand "sle" 1237 [(set (match_operand:SI 0 "register_operand" "=r") 1238 (le:SI (match_dup 1) (const_int 0)))] 1239 "" 1240 " 1241{ 1242 operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1); 1243}") 1244 1245(define_expand "sge" 1246 [(set (match_operand:SI 0 "register_operand" "=r") 1247 (ge:SI (match_dup 1) (const_int 0)))] 1248 "" 1249 " 1250{ 1251 operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1); 1252}") 1253 1254(define_expand "slt" 1255 [(set (match_operand:SI 0 "register_operand" "=r") 1256 (lt:SI (match_dup 1) (const_int 0)))] 1257 "" 1258 " 1259{ 1260 operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1); 1261}") 1262 1263(define_expand "sgtu" 1264 [(set (match_operand:SI 0 "register_operand" "=r") 1265 (gtu:SI (match_dup 1) (const_int 0)))] 1266 "" 1267 " 1268{ 1269 operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1); 1270}") 1271 1272(define_expand "sleu" 1273 [(set (match_operand:SI 0 "register_operand" "=r") 1274 (leu:SI (match_dup 1) (const_int 0)))] 1275 "" 1276 " 1277{ 1278 operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1); 1279}") 1280 1281(define_expand "sgeu" 1282 [(set (match_operand:SI 0 "register_operand" "=r") 1283 (geu:SI (match_dup 1) (const_int 0)))] 1284 "" 1285 " 1286{ 1287 operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1); 1288}") 1289 1290(define_expand "sltu" 1291 [(set (match_operand:SI 0 "register_operand" "=r") 1292 (ltu:SI (match_dup 1) (const_int 0)))] 1293 "" 1294 " 1295{ 1296 operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1); 1297}") 1298 1299(define_insn "*scc_insn" 1300 [(set (match_operand:SI 0 "register_operand" "=r") 1301 (match_operator:SI 1 "comparison_operator" [(reg 61) (const_int 0)]))] 1302 "" 1303 "mov %0,1\;sub.%D1 %0,%0,%0" 1304 [(set_attr "type" "unary") 1305 (set_attr "length" "2")]) 1306 1307;; ??? Look up negscc insn. See pa.md for example. 1308(define_insn "*neg_scc_insn" 1309 [(set (match_operand:SI 0 "register_operand" "=r") 1310 (neg:SI (match_operator:SI 1 "comparison_operator" 1311 [(reg 61) (const_int 0)])))] 1312 "" 1313 "mov %0,-1\;sub.%D1 %0,%0,%0" 1314 [(set_attr "type" "unary") 1315 (set_attr "length" "2")]) 1316 1317(define_insn "*not_scc_insn" 1318 [(set (match_operand:SI 0 "register_operand" "=r") 1319 (not:SI (match_operator:SI 1 "comparison_operator" 1320 [(reg 61) (const_int 0)])))] 1321 "" 1322 "mov %0,1\;sub.%d1 %0,%0,%0" 1323 [(set_attr "type" "unary") 1324 (set_attr "length" "2")]) 1325 1326;; These control RTL generation for conditional jump insns 1327 1328(define_expand "beq" 1329 [(set (pc) 1330 (if_then_else (eq (match_dup 1) (const_int 0)) 1331 (label_ref (match_operand 0 "" "")) 1332 (pc)))] 1333 "" 1334 " 1335{ 1336 operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1); 1337}") 1338 1339(define_expand "bne" 1340 [(set (pc) 1341 (if_then_else (ne (match_dup 1) (const_int 0)) 1342 (label_ref (match_operand 0 "" "")) 1343 (pc)))] 1344 "" 1345 " 1346{ 1347 operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1); 1348}") 1349 1350(define_expand "bgt" 1351 [(set (pc) 1352 (if_then_else (gt (match_dup 1) (const_int 0)) 1353 (label_ref (match_operand 0 "" "")) 1354 (pc)))] 1355 "" 1356 " 1357{ 1358 operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1); 1359}") 1360 1361(define_expand "ble" 1362 [(set (pc) 1363 (if_then_else (le (match_dup 1) (const_int 0)) 1364 (label_ref (match_operand 0 "" "")) 1365 (pc)))] 1366 "" 1367 " 1368{ 1369 operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1); 1370}") 1371 1372(define_expand "bge" 1373 [(set (pc) 1374 (if_then_else (ge (match_dup 1) (const_int 0)) 1375 (label_ref (match_operand 0 "" "")) 1376 (pc)))] 1377 "" 1378 " 1379{ 1380 operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1); 1381}") 1382 1383(define_expand "blt" 1384 [(set (pc) 1385 (if_then_else (lt (match_dup 1) (const_int 0)) 1386 (label_ref (match_operand 0 "" "")) 1387 (pc)))] 1388 "" 1389 " 1390{ 1391 operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1); 1392}") 1393 1394(define_expand "bgtu" 1395 [(set (pc) 1396 (if_then_else (gtu (match_dup 1) (const_int 0)) 1397 (label_ref (match_operand 0 "" "")) 1398 (pc)))] 1399 "" 1400 " 1401{ 1402 operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1); 1403}") 1404 1405(define_expand "bleu" 1406 [(set (pc) 1407 (if_then_else (leu (match_dup 1) (const_int 0)) 1408 (label_ref (match_operand 0 "" "")) 1409 (pc)))] 1410 "" 1411 " 1412{ 1413 operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1); 1414}") 1415 1416(define_expand "bgeu" 1417 [(set (pc) 1418 (if_then_else (geu (match_dup 1) (const_int 0)) 1419 (label_ref (match_operand 0 "" "")) 1420 (pc)))] 1421 "" 1422 " 1423{ 1424 operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1); 1425}") 1426 1427(define_expand "bltu" 1428 [(set (pc) 1429 (if_then_else (ltu (match_dup 1) (const_int 0)) 1430 (label_ref (match_operand 0 "" "")) 1431 (pc)))] 1432 "" 1433 " 1434{ 1435 operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1); 1436}") 1437 1438;; Now match both normal and inverted jump. 1439 1440(define_insn "*branch_insn" 1441 [(set (pc) 1442 (if_then_else (match_operator 1 "proper_comparison_operator" 1443 [(reg 61) (const_int 0)]) 1444 (label_ref (match_operand 0 "" "")) 1445 (pc)))] 1446 "" 1447 "* 1448{ 1449 if (arc_ccfsm_branch_deleted_p ()) 1450 { 1451 arc_ccfsm_record_branch_deleted (); 1452 return \"; branch deleted, next insns conditionalized\"; 1453 } 1454 else 1455 return \"%~b%d1%# %l0\"; 1456}" 1457 [(set_attr "type" "branch")]) 1458 1459(define_insn "*rev_branch_insn" 1460 [(set (pc) 1461 (if_then_else (match_operator 1 "proper_comparison_operator" 1462 [(reg 61) (const_int 0)]) 1463 (pc) 1464 (label_ref (match_operand 0 "" ""))))] 1465 "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))" 1466 "* 1467{ 1468 if (arc_ccfsm_branch_deleted_p ()) 1469 { 1470 arc_ccfsm_record_branch_deleted (); 1471 return \"; branch deleted, next insns conditionalized\"; 1472 } 1473 else 1474 return \"%~b%D1%# %l0\"; 1475}" 1476 [(set_attr "type" "branch")]) 1477 1478;; Unconditional and other jump instructions. 1479 1480(define_insn "jump" 1481 [(set (pc) (label_ref (match_operand 0 "" "")))] 1482 "" 1483 "b%* %l0" 1484 [(set_attr "type" "uncond_branch")]) 1485 1486(define_insn "indirect_jump" 1487 [(set (pc) (match_operand:SI 0 "address_operand" "p"))] 1488 "" 1489 "j%* %a0" 1490 [(set_attr "type" "uncond_branch")]) 1491 1492;; Implement a switch statement. 1493;; This wouldn't be necessary in the non-pic case if we could distinguish 1494;; label refs of the jump table from other label refs. The problem is that 1495;; label refs are output as "%st(.LL42)" but we don't want the %st - we want 1496;; the real address since it's the address of the table. 1497 1498(define_expand "casesi" 1499 [(set (match_dup 5) 1500 (minus:SI (match_operand:SI 0 "register_operand" "") 1501 (match_operand:SI 1 "nonmemory_operand" ""))) 1502 (set (reg:CC 61) 1503 (compare:CC (match_dup 5) 1504 (match_operand:SI 2 "nonmemory_operand" ""))) 1505 (set (pc) 1506 (if_then_else (gtu (reg:CC 61) 1507 (const_int 0)) 1508 (label_ref (match_operand 4 "" "")) 1509 (pc))) 1510 (parallel 1511 [(set (pc) 1512 (mem:SI (plus:SI (mult:SI (match_dup 5) 1513 (const_int 4)) 1514 (label_ref (match_operand 3 "" ""))))) 1515 (clobber (match_scratch:SI 6 "")) 1516 (clobber (match_scratch:SI 7 ""))])] 1517 "" 1518 " 1519{ 1520 operands[5] = gen_reg_rtx (SImode); 1521}") 1522 1523(define_insn "*casesi_insn" 1524 [(set (pc) 1525 (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r") 1526 (const_int 4)) 1527 (label_ref (match_operand 1 "" ""))))) 1528 (clobber (match_scratch:SI 2 "=r")) 1529 (clobber (match_scratch:SI 3 "=r"))] 1530 "" 1531 "* 1532{ 1533 output_asm_insn (\"mov %2,%1\", operands); 1534 if (TARGET_SHIFTER) 1535 output_asm_insn (\"asl %3,%0,2\", operands); 1536 else 1537 output_asm_insn (\"asl %3,%0\;asl %3,%3\", operands); 1538 output_asm_insn (\"ld %2,[%2,%3]\", operands); 1539 output_asm_insn (\"j.nd %a2\", operands); 1540 return \"\"; 1541}" 1542 [(set_attr "type" "uncond_branch") 1543 (set_attr "length" "6")]) 1544 1545(define_insn "tablejump" 1546 [(set (pc) (match_operand:SI 0 "address_operand" "p")) 1547 (use (label_ref (match_operand 1 "" "")))] 1548 "0 /* disabled -> using casesi now */" 1549 "j%* %a0" 1550 [(set_attr "type" "uncond_branch")]) 1551 1552(define_expand "call" 1553 ;; operands[1] is stack_size_rtx 1554 ;; operands[2] is next_arg_register 1555 [(parallel [(call (match_operand:SI 0 "call_operand" "") 1556 (match_operand 1 "" "")) 1557 (clobber (reg:SI 31))])] 1558 "" 1559 "") 1560 1561(define_insn "*call_via_reg" 1562 [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) 1563 (match_operand 1 "" "")) 1564 (clobber (reg:SI 31))] 1565 "" 1566 "lr blink,[status]\;j.d %0\;add blink,blink,2" 1567 [(set_attr "type" "call_no_delay_slot") 1568 (set_attr "length" "3")]) 1569 1570(define_insn "*call_via_label" 1571 [(call (mem:SI (match_operand:SI 0 "call_address_operand" "")) 1572 (match_operand 1 "" "")) 1573 (clobber (reg:SI 31))] 1574 "" 1575 ; The %~ is necessary in case this insn gets conditionalized and the previous 1576 ; insn is the cc setter. 1577 "%~bl%!%* %0" 1578 [(set_attr "type" "call") 1579 (set_attr "cond" "canuse")]) 1580 1581(define_expand "call_value" 1582 ;; operand 2 is stack_size_rtx 1583 ;; operand 3 is next_arg_register 1584 [(parallel [(set (match_operand 0 "register_operand" "=r") 1585 (call (match_operand:SI 1 "call_operand" "") 1586 (match_operand 2 "" ""))) 1587 (clobber (reg:SI 31))])] 1588 "" 1589 "") 1590 1591(define_insn "*call_value_via_reg" 1592 [(set (match_operand 0 "register_operand" "=r") 1593 (call (mem:SI (match_operand:SI 1 "register_operand" "r")) 1594 (match_operand 2 "" ""))) 1595 (clobber (reg:SI 31))] 1596 "" 1597 "lr blink,[status]\;j.d %1\;add blink,blink,2" 1598 [(set_attr "type" "call_no_delay_slot") 1599 (set_attr "length" "3")]) 1600 1601(define_insn "*call_value_via_label" 1602 [(set (match_operand 0 "register_operand" "=r") 1603 (call (mem:SI (match_operand:SI 1 "call_address_operand" "")) 1604 (match_operand 2 "" ""))) 1605 (clobber (reg:SI 31))] 1606 "" 1607 ; The %~ is necessary in case this insn gets conditionalized and the previous 1608 ; insn is the cc setter. 1609 "%~bl%!%* %1" 1610 [(set_attr "type" "call") 1611 (set_attr "cond" "canuse")]) 1612 1613(define_insn "nop" 1614 [(const_int 0)] 1615 "" 1616 "nop" 1617 [(set_attr "type" "misc")]) 1618 1619;; Special pattern to flush the icache. 1620;; ??? Not sure what to do here. Some ARC's are known to support this. 1621 1622(define_insn "flush_icache" 1623 [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)] 1624 "" 1625 "* return \"\";" 1626 [(set_attr "type" "misc")]) 1627 1628;; Split up troublesome insns for better scheduling. 1629 1630;; Peepholes go at the end. 1631