1;;- Machine description for the pdp11 for GNU C compiler 2;; Copyright (C) 1994-2020 Free Software Foundation, Inc. 3;; Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at). 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(include "predicates.md") 22(include "constraints.md") 23 24(define_c_enum "unspecv" 25 [ 26 UNSPECV_BLOCKAGE 27 UNSPECV_SETD 28 UNSPECV_SETI 29 UNSPECV_CPYMEM 30 ]) 31 32(define_constants 33 [ 34 ;; Register numbers 35 (R0_REGNUM 0) 36 (RETVAL_REGNUM 0) 37 (FRAME_POINTER_REGNUM 5) 38 (STACK_POINTER_REGNUM 6) 39 (PC_REGNUM 7) 40 (AC0_REGNUM 8) 41 (AC3_REGNUM 11) 42 (AC4_REGNUM 12) 43 (AC5_REGNUM 13) 44 ;; The next one is not a physical register but is used for 45 ;; addressing arguments. 46 (ARG_POINTER_REGNUM 14) 47 ;; Condition code registers 48 (CC_REGNUM 15) 49 (FCC_REGNUM 16) 50 ;; End of hard registers 51 (FIRST_PSEUDO_REGISTER 17) 52 53 ;; Branch offset limits, as byte offsets from (pc). That is NOT 54 ;; the same thing as "instruction address" -- it is for backward 55 ;; branches, but for forward branches it refers to the address 56 ;; following the instruction. So the max forward distance 57 ;; matches what the processor handbook says, while the max 58 ;; backward branch is 2 less than the book. 59 (MIN_BRANCH -254) 60 (MAX_BRANCH 254) 61 (MIN_SOB -124) 62 (MAX_SOB 0)]) 63 64;; DF is 64 bit 65;; SF is 32 bit 66;; SI is 32 bit 67;; HI is 16 bit 68;; QI is 8 bit 69 70;; Integer modes supported on the PDP11, with a mapping from machine mode 71;; to mnemonic suffix. SImode and DImode are usually special cases. 72(define_mode_iterator PDPint [QI HI]) 73(define_mode_attr isfx [(QI "b") (HI "")]) 74(define_mode_attr mname [(QI "QImode") (HI "HImode") (SI "SImode") (DI "DImode")]) 75(define_mode_attr e_mname [(QI "E_QImode") (HI "E_HImode") (SI "E_SImode") (DI "E_DImode")]) 76(define_mode_attr hmode [(QI "hi") (HI "hi") (SI "si") (DI "di")]) 77 78;; These are analogous for use in splitters and expanders. 79(define_mode_iterator HSint [HI SI]) 80(define_mode_iterator QHSint [QI HI SI]) 81(define_mode_iterator QHSDint [QI HI SI DI]) 82 83(define_code_iterator SHF [ashift ashiftrt lshiftrt]) 84 85;; Substitution to turn a CC clobber into a CC setter. We have four of 86;; these: for CCmode vs. CCNZmode, and for CC_REGNUM vs. FCC_REGNUM. 87(define_subst "cc_cc" 88 [(set (match_operand 0 "") (match_operand 1 "")) 89 (clobber (reg CC_REGNUM))] 90 "" 91 [(set (reg:CC CC_REGNUM) 92 (compare:CC (match_dup 1) (const_int 0))) 93 (set (match_dup 0) (match_dup 1))]) 94 95(define_subst "cc_ccnz" 96 [(set (match_operand 0 "") (match_operand 1 "")) 97 (clobber (reg CC_REGNUM))] 98 "" 99 [(set (reg:CCNZ CC_REGNUM) 100 (compare:CCNZ (match_dup 1) (const_int 0))) 101 (set (match_dup 0) (match_dup 1))]) 102 103(define_subst "fcc_cc" 104 [(set (match_operand 0 "") (match_operand 1 "")) 105 (clobber (reg FCC_REGNUM))] 106 "" 107 [(set (reg:CC FCC_REGNUM) 108 (compare:CC (match_dup 1) (const_int 0))) 109 (set (match_dup 0) (match_dup 1))]) 110 111(define_subst "fcc_ccnz" 112 [(set (match_operand 0 "") (match_operand 1 "")) 113 (clobber (reg FCC_REGNUM))] 114 "" 115 [(set (reg:CCNZ FCC_REGNUM) 116 (compare:CCNZ (match_dup 1) (const_int 0))) 117 (set (match_dup 0) (match_dup 1))]) 118 119(define_subst_attr "cc_cc" "cc_cc" "_nocc" "_cc") 120(define_subst_attr "fcc_cc" "fcc_cc" "_nocc" "_cc") 121(define_subst_attr "cc_ccnz" "cc_ccnz" "_nocc" "_cc") 122(define_subst_attr "fcc_ccnz" "fcc_ccnz" "_nocc" "_cc") 123 124;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. 125 126;; Compare instructions. 127 128;; currently we only support df floats, which saves us quite some 129;; hassle switching the FP mode! 130;; we assume that CPU is always in long float mode, and 131;; 16 bit integer mode - currently, the prologue for main does this, 132;; but maybe we should just set up a NEW crt0 properly, 133;; -- and what about signal handling code? 134;; (we don't even let sf floats in the register file, so 135;; we only should have to worry about truncating and widening 136;; when going to memory) 137 138;; abort() call by g++ - must define libfunc for cmp_optab 139;; and ucmp_optab for mode SImode, because we don't have that!!! 140;; - yet since no libfunc is there, we abort () 141 142;; define attributes 143;; currently type is only fpu or arith or unknown, maybe branch later ? 144;; default is arith 145(define_attr "type" "unknown,arith,fp" (const_string "arith")) 146 147;; length default is 2 bytes each 148(define_attr "length" "" (const_int 2)) 149 150;; instruction base cost (not counting operands) 151(define_attr "base_cost" "" (const_int 2)) 152 153;; a user's asm statement 154(define_asm_attributes 155 [(set_attr "type" "unknown") 156; length for asm is the max length per statement. That would be 157; 3 words, for a two-operand instruction with extra word addressing 158; modes for both operands. 159 (set_attr "length" "6")]) 160 161;; define function units 162 163;; Prologue and epilogue support. 164 165(define_expand "prologue" 166 [(const_int 0)] 167 "" 168{ 169 pdp11_expand_prologue (); 170 DONE; 171}) 172 173(define_expand "epilogue" 174 [(const_int 0)] 175 "" 176{ 177 pdp11_expand_epilogue (); 178 DONE; 179}) 180 181(define_insn "rtspc" 182 [(return)] 183 "" 184 "rts\tpc") 185 186(define_insn "blockage" 187 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] 188 "" 189 "" 190 [(set_attr "length" "0")]) 191 192(define_insn "setd" 193 [(unspec_volatile [(const_int 0)] UNSPECV_SETD)] 194 "" 195 "setd") 196 197(define_insn "seti" 198 [(unspec_volatile [(const_int 0)] UNSPECV_SETI)] 199 "" 200 "seti") 201 202;; arithmetic - values here immediately when next insn issued 203;; or does it mean the number of cycles after this insn was issued? 204;; how do I say that fpu insns use cpu also? (pre-interaction phase) 205 206;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0) 207;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0) 208 209;; compare 210(define_insn "*cmpdf" 211 [(set (reg:CC FCC_REGNUM) 212 (compare:CC (match_operand:DF 0 "general_operand" "fR,fR,Q,QF") 213 (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))] 214 "TARGET_FPU && reload_completed" 215 "* 216{ 217 if (which_alternative == 0 || which_alternative == 2) 218 return \"{tstd|tstf}\t%0\"; 219 else 220 return \"{cmpd|cmpf}\t%0,%1\"; 221}" 222 [(set_attr "length" "2,2,4,4") 223 (set_attr "base_cost" "4") 224 (set_attr "type" "fp")]) 225 226;; Copy floating point processor condition code register to main CPU 227;; condition code register. 228(define_insn "*cfcc" 229 [(set (reg CC_REGNUM) (reg FCC_REGNUM))] 230 "TARGET_FPU && reload_completed" 231 "cfcc") 232 233(define_insn "cmp<mode>" 234 [(set (reg:CC CC_REGNUM) 235 (compare:CC (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi") 236 (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))] 237 "" 238 "@ 239 tst<PDPint:isfx>\t%0 240 cmp<PDPint:isfx>\t%0,%1 241 cmp<PDPint:isfx>\t%0,%1 242 tst<PDPint:isfx>\t%0 243 cmp<PDPint:isfx>\t%0,%1 244 cmp<PDPint:isfx>\t%0,%1" 245 [(set_attr "length" "2,2,4,4,4,6")]) 246 247;; Two word compare 248(define_insn "cmpsi" 249 [(set (reg:CC CC_REGNUM) 250 (compare:CC (match_operand:SI 0 "general_operand" "rDQi") 251 (match_operand:SI 1 "general_operand" "rDQi")))] 252 "" 253{ 254 rtx inops[2]; 255 rtx exops[2][2]; 256 rtx lb[1]; 257 258 inops[0] = operands[0]; 259 inops[1] = operands[1]; 260 pdp11_expand_operands (inops, exops, 2, 2, NULL, big); 261 lb[0] = gen_label_rtx (); 262 263 if (CONST_INT_P (exops[0][1]) && INTVAL (exops[0][1]) == 0) 264 output_asm_insn ("tst\t%0", exops[0]); 265 else 266 output_asm_insn ("cmp\t%0,%1", exops[0]); 267 output_asm_insn ("bne\t%l0", lb); 268 if (CONST_INT_P (exops[1][1]) && INTVAL (exops[1][1]) == 0) 269 output_asm_insn ("tst\t%0", exops[1]); 270 else 271 output_asm_insn ("cmp\t%0,%1", exops[1]); 272 output_asm_label (lb[0]); 273 fputs (":\n", asm_out_file); 274 275 return ""; 276} 277 [(set (attr "length") 278 (symbol_ref "pdp11_cmp_length (operands, 2)")) 279 (set_attr "base_cost" "0")]) 280 281;; Four word compare 282(define_insn "cmpdi" 283 [(set (reg:CC CC_REGNUM) 284 (compare:CC (match_operand:DI 0 "general_operand" "rDQi") 285 (match_operand:DI 1 "general_operand" "rDQi")))] 286 "" 287{ 288 rtx inops[4]; 289 rtx exops[4][2]; 290 rtx lb[1]; 291 int i; 292 293 inops[0] = operands[0]; 294 inops[1] = operands[1]; 295 pdp11_expand_operands (inops, exops, 2, 4, NULL, big); 296 lb[0] = gen_label_rtx (); 297 298 for (i = 0; i < 3; i++) 299 { 300 if (CONST_INT_P (exops[i][1]) && INTVAL (exops[i][1]) == 0) 301 output_asm_insn ("tst\t%0", exops[i]); 302 else 303 output_asm_insn ("cmp\t%0,%1", exops[i]); 304 output_asm_insn ("bne\t%l0", lb); 305 } 306 if (CONST_INT_P (exops[3][1]) && INTVAL (exops[3][1]) == 0) 307 output_asm_insn ("tst\t%0", exops[3]); 308 else 309 output_asm_insn ("cmp\t%0,%1", exops[3]); 310 output_asm_label (lb[0]); 311 fputs (":\n", asm_out_file); 312 313 return ""; 314} 315 [(set (attr "length") 316 (symbol_ref "pdp11_cmp_length (operands, 2)")) 317 (set_attr "base_cost" "0")]) 318 319;; sob instruction 320;; 321;; This expander has to check for mode match because the doloop pass 322;; in gcc that invokes it does not do so, i.e., it may attempt to apply 323;; this pattern even if the count operand is QI or SI mode. 324(define_expand "doloop_end" 325 [(parallel [(set (pc) 326 (if_then_else 327 (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m") 328 (const_int 1)) 329 (label_ref (match_operand 1 "" "")) 330 (pc))) 331 (set (match_dup 0) 332 (plus:HI (match_dup 0) 333 (const_int -1)))])] 334 "TARGET_40_PLUS" 335 "{ 336 if (GET_MODE (operands[0]) != HImode) 337 FAIL; 338 }") 339 340;; Do a define_split because some alternatives clobber CC. 341;; Some don't, but it isn't all that interesting to cover that case. 342(define_insn_and_split "doloop_end_insn" 343 [(set (pc) 344 (if_then_else 345 (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m") 346 (const_int 1)) 347 (label_ref (match_operand 1 "" "")) 348 (pc))) 349 (set (match_dup 0) 350 (plus:HI (match_dup 0) 351 (const_int -1)))] 352 "TARGET_40_PLUS" 353 "#" 354 "&& reload_completed" 355 [(parallel [(set (pc) 356 (if_then_else 357 (ne (match_dup 0) (const_int 1)) 358 (label_ref (match_dup 1)) 359 (pc))) 360 (set (match_dup 0) 361 (plus:HI (match_dup 0) 362 (const_int -1))) 363 (clobber (reg:CC CC_REGNUM))])] 364 "") 365 366;; Note that there is a memory alternative here. This is as documented 367;; in gccint, which says that doloop_end, since it has both a jump and 368;; an output interrupt "must handle its own reloads". That translates 369;; to: must accept memory operands as valid though they may be deprecated. 370(define_insn "doloop_end_nocc" 371 [(set (pc) 372 (if_then_else 373 (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m") 374 (const_int 1)) 375 (label_ref (match_operand 1 "" "")) 376 (pc))) 377 (set (match_dup 0) 378 (plus:HI (match_dup 0) 379 (const_int -1))) 380 (clobber (reg:CC CC_REGNUM))] 381 "TARGET_40_PLUS && reload_completed" 382 "* 383{ 384 rtx lb[1]; 385 386 if (get_attr_length (insn) == 2) 387 return \"sob\t%0,%l1\"; 388 389 /* emulate sob */ 390 lb[0] = gen_label_rtx (); 391 output_asm_insn (\"dec\t%0\", operands); 392 output_asm_insn (\"beq\t%l0\", lb); 393 output_asm_insn (\"jmp\t%l1\", operands); 394 395 output_asm_label (lb[0]); 396 fputs (\":\\n\", asm_out_file); 397 398 return \"\"; 399}" 400 [(set (attr "length") 401 (if_then_else (eq (symbol_ref ("which_alternative")) (const_int 1)) 402 (const_int 10) 403 (if_then_else (ior (lt (minus (match_dup 1) (pc)) 404 (const_int MIN_SOB)) 405 (gt (minus (match_dup 1) (pc)) 406 (const_int MAX_SOB))) 407 (const_int 8) 408 (const_int 2))))]) 409 410;; These control RTL generation for conditional jump insns 411;; and match them for register allocation. 412;; Post reload these get expanded into insns that actually 413;; manipulate the condition code registers. We can't do that before 414;; because instructions generated by reload clobber condition codes (new 415;; CC design, type #2). 416(define_insn_and_split "cbranchdf4" 417 [(set (pc) 418 (if_then_else (match_operator 0 "ordered_comparison_operator" 419 [(match_operand:DF 1 "general_operand" "fg") 420 (match_operand:DF 2 "general_operand" "a")]) 421 (label_ref (match_operand 3 "" "")) 422 (pc)))] 423 "TARGET_FPU" 424 "#" 425 "&& reload_completed" 426 [(set (reg:CC FCC_REGNUM) 427 (compare:CC (match_dup 1) (match_dup 2))) 428 (set (pc) 429 (if_then_else (match_op_dup 0 430 [(reg:CC FCC_REGNUM) (const_int 0)]) 431 (label_ref (match_dup 3)) 432 (pc)))] 433 "") 434 435(define_insn_and_split "cbranch<mode>4" 436 [(set (pc) 437 (if_then_else (match_operator 0 "ordered_comparison_operator" 438 [(match_operand:QHSDint 1 "general_operand" "g") 439 (match_operand:QHSDint 2 "general_operand" "g")]) 440 (label_ref (match_operand 3 "" "")) 441 (pc)))] 442 "" 443 "#" 444 "reload_completed" 445 [(set (reg:CC CC_REGNUM) 446 (compare:CC (match_dup 1) (match_dup 2))) 447 (set (pc) 448 (if_then_else (match_op_dup 0 449 [(reg:CC CC_REGNUM) (const_int 0)]) 450 (label_ref (match_dup 3)) 451 (pc)))] 452 "") 453 454;; This splitter turns a branch on float condition into a branch on 455;; CPU condition, by adding a CFCC. 456(define_split 457 [(set (pc) 458 (if_then_else (match_operator 0 "ordered_comparison_operator" 459 [(reg:CC FCC_REGNUM) (const_int 0)]) 460 (label_ref (match_operand 1 "" "")) 461 (pc)))] 462 "TARGET_FPU && reload_completed" 463 [(set (reg:CC CC_REGNUM) (reg:CC FCC_REGNUM)) 464 (set (pc) 465 (if_then_else (match_op_dup 0 466 [(reg:CC CC_REGNUM) (const_int 0)]) 467 (label_ref (match_dup 1)) 468 (pc)))] 469 "") 470 471(define_insn "cond_branch" 472 [(set (pc) 473 (if_then_else (match_operator 0 "ordered_comparison_operator" 474 [(reg:CC CC_REGNUM) (const_int 0)]) 475 (label_ref (match_operand 1 "" "")) 476 (pc)))] 477 "reload_completed" 478 "* return output_jump (operands, 0, get_attr_length (insn));" 479 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1) 480 (pc)) 481 (const_int MIN_BRANCH)) 482 (gt (minus (match_dup 1) 483 (pc)) 484 (const_int MAX_BRANCH))) 485 (const_int 6) 486 (const_int 2)))]) 487 488(define_insn "*branch" 489 [(set (pc) 490 (if_then_else (match_operator 0 "ccnz_operator" 491 [(reg:CCNZ CC_REGNUM) (const_int 0)]) 492 (label_ref (match_operand 1 "" "")) 493 (pc)))] 494 "reload_completed" 495 "* return output_jump (operands, 1, get_attr_length (insn));" 496 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1) 497 (pc)) 498 (const_int MIN_BRANCH)) 499 (gt (minus (match_dup 1) 500 (pc)) 501 (const_int MAX_BRANCH))) 502 (const_int 6) 503 (const_int 2)))]) 504 505 506;; Move instructions 507 508;; "length" is defined even though this pattern won't appear at 509;; assembly language output time. But the length is used by 510;; pdp11_insn_cost, before the post-reload splitter adds the 511;; CC clobber to the insn. 512(define_insn "movdi" 513 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g") 514 (match_operand:DI 1 "general_operand" "rN,g"))] 515 "" 516 "" 517 [(set_attr "length" "16,32")]) 518 519 520(define_insn "*movdi_nocc" 521 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g") 522 (match_operand:DI 1 "general_operand" "rN,g")) 523 (clobber (reg:CC CC_REGNUM))] 524 "" 525 "* return output_move_multiple (operands);" 526 [(set_attr "length" "16,32")]) 527 528(define_insn "movsi" 529 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g") 530 (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))] 531 "" 532 "" 533 [(set_attr "length" "4,6,8,16")]) 534 535(define_insn "*movsi_nocc" 536 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g") 537 (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g")) 538 (clobber (reg:CC CC_REGNUM))] 539 "" 540 "* return output_move_multiple (operands);" 541 [(set_attr "length" "4,6,8,16")]) 542 543;; That long string of "Z" constraints enforces the restriction that 544;; a register source and auto increment or decrement destination must 545;; not use the same register, because that case is not consistently 546;; implemented across the PDP11 models. 547;; TODO: the same should be applied to insn like add, but this is not 548;; necessary yet because the incdec optimization pass does not apply 549;; that optimization to 3-operand insns at the moment. 550(define_insn "mov<mode>" 551 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Za,Zb,Zc,Zd,Ze,Zf,Zg,rD,rR,Q,Q") 552 (match_operand:PDPint 1 "general_operand" "RN,Z0,Z1,Z2,Z3,Z4,Z5,Z6,r,Qi,rRN,Qi"))] 553 "" 554 "" 555 [(set_attr "length" "2,2,2,2,2,2,2,2,2,4,4,6")]) 556 557;; This splits all the integer moves: DI and SI modes as well as 558;; the simple machine operations. 559(define_split 560 [(set (match_operand:QHSDint 0 "nonimmediate_operand" "") 561 (match_operand:QHSDint 1 "general_operand" ""))] 562 "reload_completed" 563 [(parallel [(set (match_dup 0) 564 (match_dup 1)) 565 (clobber (reg:CC CC_REGNUM))])] 566 "") 567 568;; MOV clears V 569(define_insn "*mov<mode>_<cc_cc>" 570 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Za,Zb,Zc,Zd,Ze,Zf,Zg,rD,rR,Q,Q") 571 (match_operand:PDPint 1 "general_operand" "RN,Z0,Z1,Z2,Z3,Z4,Z5,Z6,r,Qi,rRN,Qi")) 572 (clobber (reg:CC CC_REGNUM))] 573 "reload_completed" 574 "* 575{ 576 if (operands[1] == const0_rtx) 577 return \"clr<PDPint:isfx>\t%0\"; 578 579 return \"mov<PDPint:isfx>\t%1,%0\"; 580}" 581 [(set_attr "length" "2,2,2,2,2,2,2,2,2,4,4,6")]) 582 583;; movdf has unusually complicated condition code handling, because 584;; load (into float register) updates the FCC, while store (from 585;; float register) leaves it untouched. 586;; 587;; 1. Loads are: ac4, ac5, or non-register into load-register 588;; 2. Stores are: load-register to non-register, ac4, or ac5 589;; 3. Moves from ac0-ac3 to another ac0-ac3 can be handled 590;; either as loads or as stores. 591 592(define_expand "movdf" 593 [(set (match_operand:DF 0 "float_nonimm_operand" "") 594 (match_operand:DF 1 "float_operand" ""))] 595 "TARGET_FPU" 596 "") 597 598;; Splitter for all these cases. Store is the first two 599;; alternatives, which are not split. Note that case 3 600;; is treated as a store, i.e., not split. 601(define_insn_and_split "movdf_split" 602 [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,FQ,a,a,a") 603 (match_operand:DF 1 "float_operand" "a,a,hR,FQ,G"))] 604 "TARGET_FPU" 605 "* 606 gcc_assert (which_alternative < 2); 607 return \"std\t%1,%0\"; 608 " 609 "&& reload_completed" 610 [(parallel [(set (match_dup 0) 611 (match_dup 1)) 612 (clobber (reg:CC FCC_REGNUM))])] 613 "{ 614 if (GET_CODE (operands[1]) == REG && 615 REGNO_REG_CLASS (REGNO (operands[1])) == LOAD_FPU_REGS) 616 FAIL; 617 }" 618 [(set_attr "length" "2,4,0,0,0")]) 619 620;; Loads (case 1). 621(define_insn "*ldd<fcc_cc>" 622 [(set (match_operand:DF 0 "float_nonimm_operand" "=a,a,a") 623 (match_operand:DF 1 "float_operand" "hR,FQ,G")) 624 (clobber (reg:CC FCC_REGNUM))] 625 "TARGET_FPU && reload_completed" 626 "@ 627 ldd\t%1,%0 628 ldd\t%1,%0 629 clrd\t%0" 630 [(set_attr "length" "2,4,2")]) 631 632;; SFmode is easier because that uses convert load/store, which 633;; always change condition codes. 634;; Note that these insns are cheating a bit. We actually have 635;; DFmode operands in the FPU registers, which is why the 636;; ldcfd and stcdf instructions appear. But GCC likes to think 637;; of these as SFmode loads and does the conversion once in the 638;; register, at least in many cases. So we pretend to do this, 639;; but then extend and truncate register-to-register are NOP and 640;; generate no code. 641(define_insn_and_split "movsf" 642 [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,a") 643 (match_operand:SF 1 "float_operand" "fRG,a,FQ,a,G"))] 644 "TARGET_FPU" 645 "#" 646 "&& reload_completed" 647 [(parallel [(set (match_dup 0) 648 (match_dup 1)) 649 (clobber (reg:CC FCC_REGNUM))])] 650 "" 651 [(set_attr "length" "2,2,4,4,2")]) 652 653(define_insn "*movsf<fcc_ccnz>" 654 [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,a") 655 (match_operand:SF 1 "float_operand" "fR,a,FQ,a,G")) 656 (clobber (reg:CC FCC_REGNUM))] 657 "TARGET_FPU && reload_completed" 658 "@ 659 {ldcfd|movof}\t%1,%0 660 {stcdf|movfo}\t%1,%0 661 {ldcfd|movof}\t%1,%0 662 {stcdf|movfo}\t%1,%0 663 clrf\t%0" 664 [(set_attr "length" "2,2,4,4,2")]) 665 666;; Expand a block move. We turn this into a move loop. 667(define_expand "cpymemhi" 668 [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM) 669 (match_operand:BLK 0 "general_operand" "=g") 670 (match_operand:BLK 1 "general_operand" "g") 671 (match_operand:HI 2 "immediate_operand" "i") 672 (match_operand:HI 3 "immediate_operand" "i") 673 (clobber (mem:BLK (scratch))) 674 (clobber (match_dup 0)) 675 (clobber (match_dup 1)) 676 (clobber (match_dup 2))])] 677 "" 678 " 679{ 680 int count; 681 count = INTVAL (operands[2]); 682 if (count == 0) 683 DONE; 684 if (INTVAL (operands [3]) >= 2 && (count & 1) == 0) 685 count >>= 1; 686 else 687 operands[3] = const1_rtx; 688 operands[2] = copy_to_mode_reg (HImode, 689 gen_rtx_CONST_INT (HImode, count)); 690 691 /* Load BLKmode MEM addresses into scratch registers. */ 692 operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); 693 operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); 694}") 695 696;; Expand a block move. We turn this into a move loop. 697(define_insn_and_split "cpymemhi1" 698 [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM) 699 (match_operand:HI 0 "register_operand" "+r") 700 (match_operand:HI 1 "register_operand" "+r") 701 (match_operand:HI 2 "register_operand" "+r") 702 (match_operand:HI 3 "immediate_operand" "i") 703 (clobber (mem:BLK (scratch))) 704 (clobber (match_dup 0)) 705 (clobber (match_dup 1)) 706 (clobber (match_dup 2))] 707 "" 708 "#" 709 "reload_completed" 710 [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM) 711 (match_dup 0) 712 (match_dup 1) 713 (match_dup 2) 714 (match_dup 3) 715 (clobber (mem:BLK (scratch))) 716 (clobber (match_dup 0)) 717 (clobber (match_dup 1)) 718 (clobber (match_dup 2)) 719 (clobber (reg:CC CC_REGNUM))])] 720 "") 721 722(define_insn "cpymemhi_nocc" 723 [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM) 724 (match_operand:HI 0 "register_operand" "+r") 725 (match_operand:HI 1 "register_operand" "+r") 726 (match_operand:HI 2 "register_operand" "+r") 727 (match_operand:HI 3 "immediate_operand" "i") 728 (clobber (mem:BLK (scratch))) 729 (clobber (match_dup 0)) 730 (clobber (match_dup 1)) 731 (clobber (match_dup 2)) 732 (clobber (reg:CC CC_REGNUM))] 733 "reload_completed" 734 "* 735{ 736 rtx lb[2]; 737 738 lb[0] = operands[2]; 739 lb[1] = gen_label_rtx (); 740 741 output_asm_label (lb[1]); 742 fputs (\":\n\", asm_out_file); 743 if (INTVAL (operands[3]) > 1) 744 output_asm_insn (\"mov\t(%1)+,(%0)+\", operands); 745 else 746 output_asm_insn (\"movb\t(%1)+,(%0)+\", operands); 747 if (TARGET_40_PLUS) 748 output_asm_insn (\"sob\t%0,%l1\", lb); 749 else 750 { 751 output_asm_insn (\"dec\t%0\", lb); 752 output_asm_insn (\"bne\t%l1\", lb); 753 } 754 return \"\"; 755}" 756 [(set (attr "length") 757 (if_then_else (match_test "TARGET_40_PLUS") 758 (const_int 4) 759 (const_int 6)))]) 760 761;;- truncation instructions 762 763;; We sometimes end up doing a register to register truncate, 764;; which isn't right because we actually load registers always 765;; with a DFmode value. But even with PROMOTE the compiler 766;; doesn't always get that (so we don't use it). That means 767;; a register to register truncate is a NOP. 768(define_insn_and_split "truncdfsf2" 769 [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q") 770 (float_truncate:SF (match_operand:DF 1 "register_operand" "0,a,a")))] 771 "TARGET_FPU" 772 { 773 gcc_assert (which_alternative == 0); 774 return ""; 775 } 776 "&& reload_completed" 777 [(parallel [(set (match_dup 0) (float_truncate:SF (match_dup 1))) 778 (clobber (reg:CC FCC_REGNUM))])] 779 "{ 780 if (GET_CODE (operands[0]) == REG && 781 GET_CODE (operands[1]) == REG && 782 REGNO (operands[0]) == REGNO (operands[1])) 783 FAIL; 784 }" 785 [(set_attr "length" "0,0,0")]) 786 787(define_insn "*truncdfsf2_<fcc_cc>" 788 [(set (match_operand:SF 0 "float_nonimm_operand" "=R,Q") 789 (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a"))) 790 (clobber (reg:CC FCC_REGNUM))] 791 "TARGET_FPU && reload_completed" 792 "{stcdf|movfo}\t%1,%0" 793 [(set_attr "length" "2,4")]) 794 795 796;;- zero extension instruction 797 798(define_insn_and_split "zero_extendqihi2" 799 [(set (match_operand:HI 0 "nonimmediate_operand" "=rD,Q,&r,&r") 800 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0,rR,Q")))] 801 "" 802 "#" 803 "reload_completed" 804 [(parallel [(set (match_dup 0) (zero_extend:HI (match_dup 1))) 805 (clobber (reg:CC CC_REGNUM))])] 806 "{ 807 rtx r; 808 809 if (!REG_P (operands[0])) 810 { 811 r = gen_rtx_MEM (QImode, operands[0]); 812 adjust_address (r, QImode, 1); 813 emit_move_insn (r, const0_rtx); 814 DONE; 815 } 816 else if (!REG_P (operands[1]) || 817 REGNO (operands[0]) != REGNO (operands[1])) 818 { 819 /* Alternatives 2 and 3 */ 820 emit_move_insn (operands[0], const0_rtx); 821 r = gen_rtx_REG (QImode, REGNO (operands[0])); 822 emit_insn (gen_iorqi3_nocc (r, r, operands[1])); 823 DONE; 824 } 825 }" 826 [(set_attr "length" "4,4,4,6")]) 827 828(define_insn "*zero_extendqihi2<cc_cc>" 829 [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q") 830 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0"))) 831 (clobber (reg:CC CC_REGNUM))])] 832 "reload_completed" 833 "bic\t%#0177400,%0" 834 [(set_attr "length" "4,6")]) 835 836;;- sign extension instructions 837 838;; We sometimes end up doing a register to register extend, 839;; which isn't right because we actually load registers always 840;; with a DFmode value. But even with PROMOTE the compiler 841;; doesn't always get that (so we don't use it). That means 842;; a register to register truncate is a NOP. 843(define_insn_and_split "extendsfdf2" 844 [(set (match_operand:DF 0 "register_operand" "=f,a,a") 845 (float_extend:DF (match_operand:SF 1 "float_operand" "0,R,Q")))] 846 "TARGET_FPU" 847 { 848 gcc_assert (which_alternative == 0); 849 return ""; 850 } 851 "&& reload_completed" 852 [(parallel [(set (match_dup 0) (float_extend:DF (match_dup 1))) 853 (clobber (reg:CC FCC_REGNUM))])] 854 "{ 855 if (GET_CODE (operands[0]) == REG && 856 GET_CODE (operands[1]) == REG && 857 REGNO (operands[0]) == REGNO (operands[1])) 858 FAIL; 859 }" 860 [(set_attr "length" "0,0,0")]) 861 862(define_insn "*extendsfdf2_<fcc_cc>" 863 [(set (match_operand:DF 0 "register_operand" "=a,a") 864 (float_extend:DF (match_operand:SF 1 "float_operand" "R,Q"))) 865 (clobber (reg:CC FCC_REGNUM))] 866 "TARGET_FPU && reload_completed" 867 "{ldcfd|movof}\t%1,%0" 868 [(set_attr "length" "2,4") 869 (set_attr "base_cost" "6")]) 870 871;; movb sign extends if destination is a register 872(define_insn_and_split "extendqihi2" 873 [(set (match_operand:HI 0 "register_operand" "=r,r") 874 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))] 875 "" 876 "#" 877 "reload_completed" 878 [(parallel [(set (match_dup 0) (sign_extend:HI (match_dup 1))) 879 (clobber (reg:CC CC_REGNUM))])] 880 "" 881 [(set_attr "length" "2,4")]) 882 883;; MOVB clears V 884(define_insn "*extendqihi2<cc_cc>" 885 [(set (match_operand:HI 0 "register_operand" "=r,r") 886 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q"))) 887 (clobber (reg:CC CC_REGNUM))] 888 "reload_completed" 889 "movb\t%1,%0" 890 [(set_attr "length" "2,4")]) 891 892(define_insn_and_split "extendhisi2" 893 [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r") 894 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))] 895 "TARGET_40_PLUS" 896 "#" 897 "&& reload_completed" 898 [(parallel [(set (match_dup 0) (sign_extend:SI (match_dup 1))) 899 (clobber (reg:CC CC_REGNUM))])] 900 "" 901 [(set_attr "length" "10,6,6")]) 902 903(define_insn "*extendhisi2_nocc" 904 [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r") 905 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g"))) 906 (clobber (reg:CC CC_REGNUM))] 907 "TARGET_40_PLUS && reload_completed" 908 "* 909{ 910 rtx latehalf[2]; 911 912 /* we don't want to mess with auto increment */ 913 914 switch (which_alternative) 915 { 916 case 0: 917 918 latehalf[0] = operands[0]; 919 operands[0] = adjust_address(operands[0], HImode, 2); 920 921 output_asm_insn(\"mov\t%1,%0\", operands); 922 output_asm_insn(\"sxt\t%0\", latehalf); 923 924 return \"\"; 925 926 case 1: 927 928 /* - auto-decrement - right direction ;-) */ 929 output_asm_insn(\"mov\t%1,%0\", operands); 930 output_asm_insn(\"sxt\t%0\", operands); 931 932 return \"\"; 933 934 case 2: 935 936 /* make register pair available */ 937 latehalf[0] = operands[0]; 938 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1); 939 940 output_asm_insn(\"mov\t%1,%0\", operands); 941 output_asm_insn(\"sxt\t%0\", latehalf); 942 943 return \"\"; 944 945 default: 946 947 gcc_unreachable (); 948 } 949}" 950 [(set_attr "length" "10,6,6")]) 951 952;; make float to int and vice versa 953;; assume that we are normally in double and integer mode - 954;; what do pdp library routines do to fpu mode ? 955 956;; Note: the hardware treats register source as 957;; a 16-bit (high order only) source, which isn't 958;; what we want. But we do need to support register 959;; dest because gcc asks for it. 960(define_insn_and_split "floatsidf2" 961 [(set (match_operand:DF 0 "register_operand" "=a,a,a") 962 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))] 963 "TARGET_FPU" 964 "#" 965 "&& reload_completed" 966 [(parallel [(set (match_dup 0) (float:DF (match_dup 1))) 967 (clobber (reg:CC FCC_REGNUM))])] 968 "" 969 [(set_attr "length" "10,6,8")]) 970 971(define_insn "*floatsidf2<fcc_cc>" 972 [(set (match_operand:DF 0 "register_operand" "=a,a,a") 973 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q"))) 974 (clobber (reg:CC FCC_REGNUM))] 975 "TARGET_FPU && reload_completed" 976 "* if (which_alternative ==0) 977 { 978 rtx latehalf[2]; 979 980 latehalf[0] = NULL; 981 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1); 982 output_asm_insn(\"mov\t%1,-(sp)\", latehalf); 983 output_asm_insn(\"mov\t%1,-(sp)\", operands); 984 985 output_asm_insn(\"setl\", operands); 986 output_asm_insn(\"{ldcld|movif}\t(sp)+,%0\", operands); 987 output_asm_insn(\"seti\", operands); 988 return \"\"; 989 } 990 else 991 return \"setl\;{ldcld|movif}\t%1,%0\;seti\"; 992 " 993 [(set_attr "length" "10,6,8") 994 (set_attr "base_cost" "12")]) 995 996(define_insn_and_split "floathidf2" 997 [(set (match_operand:DF 0 "register_operand" "=a,a") 998 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))] 999 "TARGET_FPU" 1000 "#" 1001 "&& reload_completed" 1002 [(parallel [(set (match_dup 0) (float:DF (match_dup 1))) 1003 (clobber (reg:CC FCC_REGNUM))])] 1004 "" 1005 [(set_attr "length" "2,4")]) 1006 1007(define_insn "*floathidf2<fcc_cc>" 1008 [(set (match_operand:DF 0 "register_operand" "=a,a") 1009 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi"))) 1010 (clobber (reg:CC FCC_REGNUM))] 1011 "TARGET_FPU && reload_completed" 1012 "{ldcid|movif}\t%1,%0" 1013 [(set_attr "length" "2,4") 1014 (set_attr "base_cost" "12")]) 1015 1016;; cut float to int 1017 1018;; Note: the hardware treats register destination as 1019;; a 16-bit (high order only) destination, which isn't 1020;; what we want. But we do need to support register 1021;; dest because gcc asks for it. 1022(define_insn_and_split "fix_truncdfsi2" 1023 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q") 1024 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))] 1025 "TARGET_FPU" 1026 "#" 1027 "&& reload_completed" 1028 [(parallel [(set (match_dup 0) (fix:SI (fix:DF (match_dup 1)))) 1029 (clobber (reg:CC CC_REGNUM)) 1030 (clobber (reg:CC FCC_REGNUM))])] 1031 "" 1032 [(set_attr "length" "10,6,8")]) 1033 1034;; Note: this clobbers both sets of condition codes! 1035(define_insn "*fix_truncdfsi2_nocc" 1036 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q") 1037 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a")))) 1038 (clobber (reg:CC CC_REGNUM)) 1039 (clobber (reg:CC FCC_REGNUM))] 1040 "TARGET_FPU && reload_completed" 1041 "* if (which_alternative ==0) 1042 { 1043 output_asm_insn(\"setl\", operands); 1044 output_asm_insn(\"{stcdl|movfi}\t%1,-(sp)\", operands); 1045 output_asm_insn(\"seti\", operands); 1046 output_asm_insn(\"mov\t(sp)+,%0\", operands); 1047 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1); 1048 output_asm_insn(\"mov\t(sp)+,%0\", operands); 1049 return \"\"; 1050 } 1051 else 1052 return \"setl\;{stcdl|movfi}\t%1,%0\;seti\"; 1053 " 1054 [(set_attr "length" "10,6,8") 1055 (set_attr "base_cost" "12")]) 1056 1057(define_insn_and_split "fix_truncdfhi2" 1058 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q") 1059 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))] 1060 "TARGET_FPU" 1061 "#" 1062 "&& reload_completed" 1063 [(parallel [(set (match_dup 0) (fix:HI (fix:DF (match_dup 1)))) 1064 (clobber (reg:CC CC_REGNUM)) 1065 (clobber (reg:CC FCC_REGNUM))])] 1066 "" 1067 [(set_attr "length" "2,4")]) 1068 1069;; Note: this clobbers both sets of condition codes! 1070(define_insn "*fix_truncdfhi2_nocc" 1071 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q") 1072 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a")))) 1073 (clobber (reg:CC CC_REGNUM)) 1074 (clobber (reg:CC FCC_REGNUM))] 1075 "TARGET_FPU && reload_completed" 1076 "{stcdi|movfi}\t%1,%0" 1077 [(set_attr "length" "2,4") 1078 (set_attr "base_cost" "12")]) 1079 1080 1081;;- arithmetic instructions 1082;;- add instructions 1083 1084(define_insn_and_split "adddf3" 1085 [(set (match_operand:DF 0 "register_operand" "=a,a") 1086 (plus:DF (match_operand:DF 1 "register_operand" "%0,0") 1087 (match_operand:DF 2 "general_operand" "fR,QF")))] 1088 "TARGET_FPU" 1089 "#" 1090 "&& reload_completed" 1091 [(parallel [(set (match_dup 0) 1092 (plus:DF (match_dup 1) (match_dup 2))) 1093 (clobber (reg:CC FCC_REGNUM))])] 1094 "" 1095 [(set_attr "length" "2,4")]) 1096 1097;; Float add sets V if overflow from add 1098(define_insn "*adddf3<fcc_ccnz>" 1099 [(set (match_operand:DF 0 "register_operand" "=a,a") 1100 (plus:DF (match_operand:DF 1 "register_operand" "%0,0") 1101 (match_operand:DF 2 "general_operand" "fR,QF"))) 1102 (clobber (reg:CC FCC_REGNUM))] 1103 "TARGET_FPU && reload_completed" 1104 "{addd|addf}\t%2,%0" 1105 [(set_attr "length" "2,4") 1106 (set_attr "base_cost" "6")]) 1107 1108(define_insn_and_split "adddi3" 1109 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o") 1110 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0") 1111 (match_operand:DI 2 "general_operand" "r,on,r,on")))] 1112 "" 1113 "#" 1114 "reload_completed" 1115 [(parallel [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2))) 1116 (clobber (reg:CC CC_REGNUM))])] 1117 "" 1118 [(set_attr "length" "20,28,40,48")]) 1119 1120(define_insn "*adddi3_nocc" 1121 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o") 1122 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0") 1123 (match_operand:DI 2 "general_operand" "r,on,r,on"))) 1124 (clobber (reg:CC CC_REGNUM))] 1125 "reload_completed" 1126 "* 1127{ 1128 rtx inops[2]; 1129 rtx exops[4][2]; 1130 1131 inops[0] = operands[0]; 1132 inops[1] = operands[2]; 1133 pdp11_expand_operands (inops, exops, 2, 4, NULL, big); 1134 1135 if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0) 1136 output_asm_insn (\"add\t%1,%0\", exops[0]); 1137 if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0) 1138 { 1139 output_asm_insn (\"add\t%1,%0\", exops[1]); 1140 output_asm_insn (\"adc\t%0\", exops[0]); 1141 } 1142 if (!CONST_INT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0) 1143 { 1144 output_asm_insn (\"add\t%1,%0\", exops[2]); 1145 output_asm_insn (\"adc\t%0\", exops[1]); 1146 output_asm_insn (\"adc\t%0\", exops[0]); 1147 } 1148 if (!CONST_INT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0) 1149 { 1150 output_asm_insn (\"add\t%1,%0\", exops[3]); 1151 output_asm_insn (\"adc\t%0\", exops[2]); 1152 output_asm_insn (\"adc\t%0\", exops[1]); 1153 output_asm_insn (\"adc\t%0\", exops[0]); 1154 } 1155 1156 return \"\"; 1157}" 1158 [(set_attr "length" "20,28,40,48") 1159 (set_attr "base_cost" "0")]) 1160 1161;; Note that the register operand is not marked earlyclobber. 1162;; The reason is that SI values go in register pairs, so they 1163;; can't partially overlap. They can be either disjoint, or 1164;; source and destination can be equal. The latter case is 1165;; handled properly because of the ordering of the individual 1166;; instructions used. Specifically, carry from the low to the 1167;; high word is added at the end, so the adding of the high parts 1168;; will always used the original high part and not a high part 1169;; modified by carry (which would amount to double carry). 1170(define_insn_and_split "addsi3" 1171 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o") 1172 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0") 1173 (match_operand:SI 2 "general_operand" "r,on,r,on")))] 1174 "" 1175 "#" 1176 "reload_completed" 1177 [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2))) 1178 (clobber (reg:CC CC_REGNUM))])] 1179 "" 1180 [(set_attr "length" "6,10,12,16")]) 1181 1182(define_insn "*addsi3_nocc" 1183 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o") 1184 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0") 1185 (match_operand:SI 2 "general_operand" "r,on,r,on"))) 1186 (clobber (reg:CC CC_REGNUM))] 1187 "reload_completed" 1188 "* 1189{ 1190 rtx inops[2]; 1191 rtx exops[2][2]; 1192 1193 inops[0] = operands[0]; 1194 inops[1] = operands[2]; 1195 pdp11_expand_operands (inops, exops, 2, 2, NULL, big); 1196 1197 if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0) 1198 output_asm_insn (\"add\t%1,%0\", exops[0]); 1199 if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0) 1200 { 1201 output_asm_insn (\"add\t%1,%0\", exops[1]); 1202 output_asm_insn (\"adc\t%0\", exops[0]); 1203 } 1204 1205 return \"\"; 1206}" 1207 [(set_attr "length" "6,10,12,16") 1208 (set_attr "base_cost" "0")]) 1209 1210(define_insn_and_split "addhi3" 1211 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q") 1212 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0") 1213 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))] 1214 "" 1215 "#" 1216 "reload_completed" 1217 [(parallel [(set (match_dup 0) 1218 (plus:HI (match_dup 1) (match_dup 2))) 1219 (clobber (reg:CC CC_REGNUM))])] 1220 "" 1221 [(set_attr "length" "2,4,4,6")]) 1222 1223;; Add sets V if overflow from the add 1224(define_insn "*addhi3<cc_ccnz>" 1225 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q") 1226 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0") 1227 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi"))) 1228 (clobber (reg:CC CC_REGNUM))] 1229 "reload_completed" 1230 "* 1231{ 1232 if (GET_CODE (operands[2]) == CONST_INT) 1233 { 1234 if (INTVAL(operands[2]) == 1) 1235 return \"inc\t%0\"; 1236 else if (INTVAL(operands[2]) == -1) 1237 return \"dec\t%0\"; 1238 } 1239 1240 return \"add\t%2,%0\"; 1241}" 1242 [(set_attr "length" "2,4,4,6")]) 1243 1244(define_insn_and_split "addqi3" 1245 [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q") 1246 (plus:QI (match_operand:QI 1 "general_operand" "%0,0") 1247 (match_operand:QI 2 "incdec_operand" "LM,LM")))] 1248 "" 1249 "#" 1250 "reload_completed" 1251 [(parallel [(set (match_dup 0) 1252 (plus:QI (match_dup 1) (match_dup 2))) 1253 (clobber (reg:CC CC_REGNUM))])] 1254 "" 1255 [(set_attr "length" "2,4")]) 1256 1257;; Inc/dec sets V if overflow from the operation 1258(define_insn "*addqi3<cc_ccnz>" 1259 [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q") 1260 (plus:QI (match_operand:QI 1 "general_operand" "%0,0") 1261 (match_operand:QI 2 "incdec_operand" "LM,LM"))) 1262 (clobber (reg:CC CC_REGNUM))] 1263 "reload_completed" 1264 "* 1265{ 1266 if (INTVAL(operands[2]) == 1) 1267 return \"incb\t%0\"; 1268 else 1269 return \"decb\t%0\"; 1270}" 1271 [(set_attr "length" "2,4")]) 1272 1273 1274;;- subtract instructions 1275;; we don't have to care for constant second 1276;; args, since they are canonical plus:xx now! 1277;; also for minus:DF ?? 1278 1279(define_insn_and_split "subdf3" 1280 [(set (match_operand:DF 0 "register_operand" "=a,a") 1281 (minus:DF (match_operand:DF 1 "register_operand" "0,0") 1282 (match_operand:DF 2 "general_operand" "fR,Q")))] 1283 "TARGET_FPU" 1284 "#" 1285 "&& reload_completed" 1286 [(parallel [(set (match_dup 0) 1287 (minus:DF (match_dup 1) (match_dup 2))) 1288 (clobber (reg:CC FCC_REGNUM))])] 1289 "" 1290 [(set_attr "length" "2,4")]) 1291 1292(define_insn "*subdf3<fcc_ccnz>" 1293 [(set (match_operand:DF 0 "register_operand" "=a,a") 1294 (minus:DF (match_operand:DF 1 "register_operand" "0,0") 1295 (match_operand:DF 2 "general_operand" "fR,QF"))) 1296 (clobber (reg:CC FCC_REGNUM))] 1297 "TARGET_FPU && reload_completed" 1298 "{subd|subf}\t%2,%0" 1299 [(set_attr "length" "2,4") 1300 (set_attr "base_cost" "6")]) 1301 1302(define_insn_and_split "subdi3" 1303 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o") 1304 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0") 1305 (match_operand:DI 2 "general_operand" "r,on,r,on")))] 1306 "" 1307 "#" 1308 "reload_completed" 1309 [(parallel [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2))) 1310 (clobber (reg:CC CC_REGNUM))])] 1311 "" 1312 [(set_attr "length" "20,28,40,48")]) 1313 1314(define_insn "*subdi3_nocc" 1315 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o") 1316 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0") 1317 (match_operand:DI 2 "general_operand" "r,on,r,on"))) 1318 (clobber (reg:CC CC_REGNUM))] 1319 "reload_completed" 1320 "* 1321{ 1322 rtx inops[2]; 1323 rtx exops[4][2]; 1324 1325 inops[0] = operands[0]; 1326 inops[1] = operands[2]; 1327 pdp11_expand_operands (inops, exops, 2, 4, NULL, big); 1328 1329 if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0) 1330 output_asm_insn (\"sub\t%1,%0\", exops[0]); 1331 if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0) 1332 { 1333 output_asm_insn (\"sub\t%1,%0\", exops[1]); 1334 output_asm_insn (\"sbc\t%0\", exops[0]); 1335 } 1336 if (!CONST_INT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0) 1337 { 1338 output_asm_insn (\"sub\t%1,%0\", exops[2]); 1339 output_asm_insn (\"sbc\t%0\", exops[1]); 1340 output_asm_insn (\"sbc\t%0\", exops[0]); 1341 } 1342 if (!CONST_INT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0) 1343 { 1344 output_asm_insn (\"sub\t%1,%0\", exops[3]); 1345 output_asm_insn (\"sbc\t%0\", exops[2]); 1346 output_asm_insn (\"sbc\t%0\", exops[1]); 1347 output_asm_insn (\"sbc\t%0\", exops[0]); 1348 } 1349 1350 return \"\"; 1351}" 1352 [(set_attr "length" "20,28,40,48") 1353 (set_attr "base_cost" "0")]) 1354 1355(define_insn_and_split "subsi3" 1356 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o") 1357 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0") 1358 (match_operand:SI 2 "general_operand" "r,on,r,on")))] 1359 "" 1360 "#" 1361 "reload_completed" 1362 [(parallel [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2))) 1363 (clobber (reg:CC CC_REGNUM))])] 1364 "" 1365 [(set_attr "length" "6,10,12,16")]) 1366 1367(define_insn "*subsi3_nocc" 1368 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o") 1369 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0") 1370 (match_operand:SI 2 "general_operand" "r,on,r,on"))) 1371 (clobber (reg:CC CC_REGNUM))] 1372 "reload_completed" 1373 "* 1374{ 1375 rtx inops[2]; 1376 rtx exops[2][2]; 1377 1378 inops[0] = operands[0]; 1379 inops[1] = operands[2]; 1380 pdp11_expand_operands (inops, exops, 2, 2, NULL, big); 1381 1382 if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0) 1383 output_asm_insn (\"sub\t%1,%0\", exops[0]); 1384 if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0) 1385 { 1386 output_asm_insn (\"sub\t%1,%0\", exops[1]); 1387 output_asm_insn (\"sbc\t%0\", exops[0]); 1388 } 1389 1390 return \"\"; 1391}" 1392 [(set_attr "length" "6,10,12,16") 1393 (set_attr "base_cost" "0")]) 1394 1395(define_insn_and_split "subhi3" 1396 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q") 1397 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0") 1398 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))] 1399 "" 1400 "#" 1401 "reload_completed" 1402 [(parallel [(set (match_dup 0) 1403 (minus:HI (match_dup 1) (match_dup 2))) 1404 (clobber (reg:CC CC_REGNUM))])] 1405 "" 1406 [(set_attr "length" "2,4,4,6")]) 1407 1408;; Note: the manual says that (minus m (const_int n)) is converted 1409;; to (plus m (const_int -n)) but that does not appear to be 1410;; the case when it's wrapped in a PARALLEL. So instead we handle 1411;; that case here, which is easy enough. 1412(define_insn "*subhi3<cc_ccnz>" 1413 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q") 1414 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0") 1415 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi"))) 1416 (clobber (reg:CC CC_REGNUM))] 1417 "reload_completed" 1418 "* 1419{ 1420 if (GET_CODE (operands[2]) == CONST_INT) 1421 { 1422 if (INTVAL(operands[2]) == 1) 1423 return \"dec\t%0\"; 1424 else if (INTVAL(operands[2]) == -1) 1425 return \"inc\t%0\"; 1426 } 1427 1428 return \"sub\t%2,%0\"; 1429}" 1430 [(set_attr "length" "2,4,4,6")]) 1431 1432(define_insn_and_split "subqi3" 1433 [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q") 1434 (plus:QI (match_operand:QI 1 "general_operand" "%0,0") 1435 (match_operand:QI 2 "incdec_operand" "LM,LM")))] 1436 "" 1437 "#" 1438 "reload_completed" 1439 [(parallel [(set (match_dup 0) 1440 (plus:QI (match_dup 1) (match_dup 2))) 1441 (clobber (reg:CC CC_REGNUM))])] 1442 "" 1443 [(set_attr "length" "2,4")]) 1444 1445;; Inc/dec sets V if overflow from the operation 1446(define_insn "*subqi3<cc_ccnz>" 1447 [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q") 1448 (plus:QI (match_operand:QI 1 "general_operand" "%0,0") 1449 (match_operand:QI 2 "incdec_operand" "LM,LM"))) 1450 (clobber (reg:CC CC_REGNUM))] 1451 "reload_completed" 1452 "* 1453{ 1454 if (INTVAL(operands[2]) == -1) 1455 return \"incb\t%0\"; 1456 else 1457 return \"decb\t%0\"; 1458}" 1459 [(set_attr "length" "2,4")]) 1460 1461;;;;- and instructions 1462;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn. 1463 1464(define_expand "and<mode>3" 1465 [(set (match_operand:PDPint 0 "nonimmediate_operand" "") 1466 (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" "")) 1467 (match_operand:PDPint 2 "general_operand" "")))] 1468 "" 1469 " 1470{ 1471 rtx op1 = operands[1]; 1472 1473 /* If there is a constant argument, complement that one. 1474 Similarly, if one of the inputs is the same as the output, 1475 complement the other input. */ 1476 if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) || 1477 rtx_equal_p (operands[0], operands[1])) 1478 { 1479 operands[1] = operands[2]; 1480 operands[2] = op1; 1481 op1 = operands[1]; 1482 } 1483 1484 if (CONST_INT_P (op1)) 1485 operands[1] = GEN_INT (~INTVAL (op1)); 1486 else 1487 operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1); 1488}" 1489 [(set_attr "length" "2,4,4,6")]) 1490 1491(define_insn_and_split "*bic<mode>" 1492 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q") 1493 (and:PDPint 1494 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi")) 1495 (match_operand:PDPint 2 "general_operand" "0,0,0,0")))] 1496 "" 1497 "#" 1498 "reload_completed" 1499 [(parallel [(set (match_dup 0) 1500 (and:PDPint (not:PDPint (match_dup 1)) (match_dup 2))) 1501 (clobber (reg:CC CC_REGNUM))])] 1502 "") 1503 1504(define_insn "*bic<mode><cc_cc>" 1505 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q") 1506 (and:PDPint 1507 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi")) 1508 (match_operand:PDPint 2 "general_operand" "0,0,0,0"))) 1509 (clobber (reg:CC CC_REGNUM))] 1510 "reload_completed" 1511 "bic<PDPint:isfx>\t%1,%0" 1512 [(set_attr "length" "2,4,4,6")]) 1513 1514;;- Bit set (inclusive or) instructions 1515(define_insn_and_split "ior<mode>3" 1516 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q") 1517 (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0") 1518 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))] 1519 "" 1520 "#" 1521 "reload_completed" 1522 [(parallel [(set (match_dup 0) 1523 (ior:PDPint (match_dup 1) (match_dup 2))) 1524 (clobber (reg:CC CC_REGNUM))])] 1525 "" 1526 [(set_attr "length" "2,4,4,6")]) 1527 1528(define_insn "ior<mode>3<cc_cc>" 1529 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q") 1530 (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0") 1531 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi"))) 1532 (clobber (reg:CC CC_REGNUM))] 1533 "reload_completed" 1534 "bis<PDPint:isfx>\t%2,%0" 1535 [(set_attr "length" "2,4,4,6")]) 1536 1537;;- xor instructions 1538(define_insn_and_split "xorhi3" 1539 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q") 1540 (xor:HI (match_operand:HI 1 "general_operand" "%0,0") 1541 (match_operand:HI 2 "register_operand" "r,r")))] 1542 "TARGET_40_PLUS" 1543 "#" 1544 "&& reload_completed" 1545 [(parallel [(set (match_dup 0) 1546 (xor:HI (match_dup 1) (match_dup 2))) 1547 (clobber (reg:CC CC_REGNUM))])] 1548 "" 1549 [(set_attr "length" "2,4")]) 1550 1551(define_insn "*xorhi3<cc_cc>" 1552 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q") 1553 (xor:HI (match_operand:HI 1 "general_operand" "%0,0") 1554 (match_operand:HI 2 "register_operand" "r,r"))) 1555 (clobber (reg:CC CC_REGNUM))] 1556 "TARGET_40_PLUS && reload_completed" 1557 "xor\t%2,%0" 1558 [(set_attr "length" "2,4")]) 1559 1560;;- one complement instructions 1561 1562(define_insn_and_split "one_cmpl<mode>2" 1563 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q") 1564 (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))] 1565 "" 1566 "#" 1567 "reload_completed" 1568 [(parallel [(set (match_dup 0) 1569 (not:PDPint (match_dup 1))) 1570 (clobber (reg:CC CC_REGNUM))])] 1571 "" 1572 [(set_attr "length" "2,4")]) 1573 1574(define_insn "*one_cmpl<mode>2<cc_cc>" 1575 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q") 1576 (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0"))) 1577 (clobber (reg:CC CC_REGNUM))] 1578 "reload_completed" 1579 "com<PDPint:isfx>\t%0" 1580 [(set_attr "length" "2,4")]) 1581 1582;;- arithmetic shift instructions 1583;; 1584;; There is a fair amount of complexity here because with -m10 1585;; (pdp-11/10, /20) we only have shift by one bit. Iterators are 1586;; used to reduce the amount of very similar code. 1587;; 1588;; First the insns used for small constant shifts. 1589(define_insn_and_split "<code><mode>_sc" 1590 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q") 1591 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0") 1592 (match_operand:HI 2 "expand_shift_operand" "O,O")))] 1593 "" 1594 "#" 1595 "reload_completed" 1596 [(parallel [(set (match_dup 0) (SHF:QHSint (match_dup 1) (match_dup 2))) 1597 (clobber (reg:CC CC_REGNUM))])] 1598 "" 1599 [(set (attr "length") 1600 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>, 1601 <CODE>, which_alternative == 0)")) 1602 (set_attr "base_cost" "0")]) 1603 1604(define_insn "<code><mode>_sc<cc_ccnz>" 1605 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rD,Q") 1606 (SHF:PDPint (match_operand:PDPint 1 "general_operand" "0,0") 1607 (match_operand:HI 2 "expand_shift_operand" "O,O"))) 1608 (clobber (reg:CC CC_REGNUM))] 1609 "reload_completed" 1610 "* return pdp11_assemble_shift (operands, <PDPint:mname>, <CODE>);" 1611 [(set (attr "length") 1612 (symbol_ref "pdp11_shift_length (operands, <PDPint:mname>, 1613 <CODE>, which_alternative == 0)")) 1614 (set_attr "base_cost" "0")]) 1615 1616;; This one comes only in clobber flavor. 1617(define_insn "<code>si_sc_nocc" 1618 [(set (match_operand:SI 0 "nonimmediate_operand" "=rD,Q") 1619 (SHF:SI (match_operand:SI 1 "general_operand" "0,0") 1620 (match_operand:HI 2 "expand_shift_operand" "O,O"))) 1621 (clobber (reg:CC CC_REGNUM))] 1622 "reload_completed" 1623 "* return pdp11_assemble_shift (operands, SImode, <CODE>);" 1624 [(set (attr "length") 1625 (symbol_ref "pdp11_shift_length (operands, SImode, 1626 <CODE>, which_alternative == 0)")) 1627 (set_attr "base_cost" "0")]) 1628 1629;; Next, shifts that are done as a loop on base (11/10 class) machines. 1630;; This applies to shift counts too large to unroll, or variable shift 1631;; counts. The check for count <= 0 is done before we get here. 1632(define_insn_and_split "<code><mode>_base" 1633 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q") 1634 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0") 1635 (match_operand:HI 2 "register_operand" "r,r"))) 1636 (clobber (match_dup 2))] 1637 "" 1638 "#" 1639 "reload_completed" 1640 [(parallel [(set (match_dup 0) (SHF:QHSint (match_dup 1) (match_dup 2))) 1641 (clobber (match_dup 2)) 1642 (clobber (reg:CC CC_REGNUM))])] 1643 "" 1644 [(set (attr "length") 1645 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>, 1646 <CODE>, which_alternative == 0)")) 1647 (set_attr "base_cost" "0")]) 1648 1649(define_insn "<code><mode>_base_nocc" 1650 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q") 1651 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0") 1652 (match_operand:HI 2 "register_operand" "r,r"))) 1653 (clobber (match_dup 2)) 1654 (clobber (reg:CC CC_REGNUM))] 1655 "reload_completed" 1656 "* return pdp11_assemble_shift (operands, <QHSint:mname>, <CODE>);" 1657 [(set (attr "length") 1658 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>, 1659 <CODE>, which_alternative == 0)")) 1660 (set_attr "base_cost" "0")]) 1661 1662;; Next the insns that use the extended instructions ash and ashc. 1663;; Note that these are just left shifts, and HI/SI only. (Right shifts 1664;; are done by shifting by a negative amount.) 1665(define_insn_and_split "aslhi_op" 1666 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r") 1667 (ashift:HI (match_operand:HI 1 "general_operand" "0,0") 1668 (match_operand:HI 2 "general_operand" "rR,Qi")))] 1669 "TARGET_40_PLUS" 1670 "#" 1671 "&& reload_completed" 1672 [(parallel [(set (match_dup 0) 1673 (ashift:HI (match_dup 1) (match_dup 2))) 1674 (clobber (reg:CC CC_REGNUM))])] 1675 "" 1676 [(set_attr "length" "2,4") 1677 (set_attr "base_cost" "8")]) 1678 1679(define_insn "aslhi_op<cc_ccnz>" 1680 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r") 1681 (ashift:HI (match_operand:HI 1 "general_operand" "0,0") 1682 (match_operand:HI 2 "general_operand" "rR,Qi"))) 1683 (clobber (reg:CC CC_REGNUM))] 1684 "TARGET_40_PLUS && reload_completed" 1685 "ash\t%2,%0" 1686 [(set_attr "length" "2,4") 1687 (set_attr "base_cost" "8")]) 1688 1689(define_insn_and_split "aslsi_op" 1690 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r") 1691 (ashift:SI (match_operand:SI 1 "general_operand" "0,0") 1692 (match_operand:HI 2 "general_operand" "rR,Qi")))] 1693 "TARGET_40_PLUS" 1694 "#" 1695 "&& reload_completed" 1696 [(parallel [(set (match_dup 0) 1697 (ashift:SI (match_dup 1) (match_dup 2))) 1698 (clobber (reg:CC CC_REGNUM))])] 1699 "" 1700 [(set_attr "length" "2,4") 1701 (set_attr "base_cost" "8")]) 1702 1703(define_insn "aslsi_op_<cc_ccnz>" 1704 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r") 1705 (ashift:SI (match_operand:SI 1 "general_operand" "0,0") 1706 (match_operand:HI 2 "general_operand" "rR,Qi"))) 1707 (clobber (reg:CC CC_REGNUM))] 1708 "TARGET_40_PLUS && reload_completed" 1709 "ashc\t%2,%0" 1710 [(set_attr "length" "2,4") 1711 (set_attr "base_cost" "8")]) 1712 1713;; Now the expanders that produce the insns defined above. 1714(define_expand "ashl<mode>3" 1715 [(match_operand:QHSint 0 "nonimmediate_operand" "") 1716 (match_operand:QHSint 1 "general_operand" "") 1717 (match_operand:HI 2 "general_operand" "")] 1718 "" 1719 " 1720{ 1721 rtx r; 1722 1723 if (!pdp11_expand_shift (operands, gen_ashift<mode>_sc, gen_ashift<mode>_base)) 1724 { 1725 if (<QHSint:e_mname> == E_QImode) 1726 { 1727 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1])); 1728 emit_insn (gen_aslhi_op (r, r, operands[2])); 1729 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0))); 1730 } 1731 else 1732 { 1733 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2])); 1734 } 1735 } 1736 DONE; 1737}") 1738 1739(define_expand "ashr<mode>3" 1740 [(match_operand:QHSint 0 "nonimmediate_operand" "") 1741 (match_operand:QHSint 1 "general_operand" "") 1742 (match_operand:HI 2 "general_operand" "")] 1743 "" 1744 " 1745{ 1746 rtx r; 1747 1748 if (!pdp11_expand_shift (operands, gen_ashiftrt<mode>_sc, gen_ashiftrt<mode>_base)) 1749 { 1750 operands[2] = negate_rtx (HImode, operands[2]); 1751 if (<QHSint:e_mname> == E_QImode) 1752 { 1753 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1])); 1754 emit_insn (gen_aslhi_op (r, r, operands[2])); 1755 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0))); 1756 } 1757 else 1758 { 1759 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2])); 1760 } 1761 } 1762 DONE; 1763}") 1764 1765(define_expand "lshr<mode>3" 1766 [(match_operand:QHSint 0 "nonimmediate_operand" "") 1767 (match_operand:QHSint 1 "general_operand" "") 1768 (match_operand:HI 2 "general_operand" "")] 1769 "" 1770 " 1771{ 1772 rtx r, n; 1773 1774 if (!pdp11_expand_shift (operands, gen_lshiftrt<mode>_sc, gen_lshiftrt<mode>_base)) 1775 { 1776 if (<QHSint:e_mname> == E_QImode) 1777 { 1778 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1])); 1779 emit_insn (gen_aslhi_op (r, r, operands[2])); 1780 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0))); 1781 } 1782 else 1783 { 1784 r = gen_reg_rtx (<QHSint:mname>); 1785 emit_insn (gen_lshiftrt<mode>_sc (r, operands[1], const1_rtx)); 1786 if (GET_CODE (operands[2]) != CONST_INT) 1787 { 1788 n = gen_reg_rtx (HImode); 1789 emit_insn (gen_addhi3 (n, operands [2], GEN_INT (-1))); 1790 emit_insn (gen_ashr<mode>3 (operands[0], r, n)); 1791 } 1792 else 1793 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], r, 1794 GEN_INT (1 - INTVAL (operands[2])))); 1795 } 1796 } 1797 DONE; 1798}") 1799 1800;; absolute 1801 1802(define_insn_and_split "absdf2" 1803 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q") 1804 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))] 1805 "TARGET_FPU" 1806 "#" 1807 "&& reload_completed" 1808 [(parallel [(set (match_dup 0) (abs:DF (match_dup 1))) 1809 (clobber (reg:CC FCC_REGNUM))])] 1810 "" 1811 [(set_attr "length" "2,4")]) 1812 1813(define_insn "absdf2<fcc_cc>" 1814 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q") 1815 (abs:DF (match_operand:DF 1 "general_operand" "0,0"))) 1816 (clobber (reg:CC FCC_REGNUM))] 1817 "TARGET_FPU && reload_completed" 1818 "{absd|absf}\t%0" 1819 [(set_attr "length" "2,4")]) 1820 1821;; negate insns 1822 1823(define_insn_and_split "negdf2" 1824 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q") 1825 (neg:DF (match_operand:DF 1 "general_operand" "0,0")))] 1826 "TARGET_FPU" 1827 "#" 1828 "&& reload_completed" 1829 [(parallel [(set (match_dup 0) (neg:DF (match_dup 1))) 1830 (clobber (reg:CC FCC_REGNUM))])] 1831 "" 1832 [(set_attr "length" "2,4")]) 1833 1834(define_insn "negdf2<fcc_cc>" 1835 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q") 1836 (neg:DF (match_operand:DF 1 "general_operand" "0,0"))) 1837 (clobber (reg:CC FCC_REGNUM))] 1838 "TARGET_FPU && reload_completed" 1839 "{negd|negf}\t%0" 1840 [(set_attr "length" "2,4")]) 1841 1842(define_insn_and_split "negdi2" 1843 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o") 1844 (neg:DI (match_operand:DI 1 "general_operand" "0,0")))] 1845 "" 1846 "#" 1847 "reload_completed" 1848 [(parallel [(set (match_dup 0) (neg:DI (match_dup 1))) 1849 (clobber (reg:CC CC_REGNUM))])] 1850 "" 1851 [(set_attr "length" "18,34")]) 1852 1853;; TODO: this can be neg/adc/neg/adc... I believe. Check. Saves one word. 1854(define_insn "negdi2_nocc" 1855 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o") 1856 (neg:DI (match_operand:DI 1 "general_operand" "0,0"))) 1857 (clobber (reg:CC CC_REGNUM))] 1858 "reload_completed" 1859 { 1860 rtx inops[2]; 1861 rtx exops[4][2]; 1862 1863 inops[0] = operands[0]; 1864 pdp11_expand_operands (inops, exops, 1, 4, NULL, big); 1865 1866 output_asm_insn (\"com\t%0\", exops[3]); 1867 output_asm_insn (\"com\t%0\", exops[2]); 1868 output_asm_insn (\"com\t%0\", exops[1]); 1869 output_asm_insn (\"com\t%0\", exops[0]); 1870 output_asm_insn (\"add\t%#1,%0\", exops[3]); 1871 output_asm_insn (\"adc\t%0\", exops[2]); 1872 output_asm_insn (\"adc\t%0\", exops[1]); 1873 output_asm_insn (\"adc\t%0\", exops[0]); 1874 1875 return \"\"; 1876 } 1877 [(set_attr "length" "18,34") 1878 (set_attr "base_cost" "0")]) 1879 1880(define_insn_and_split "negsi2" 1881 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o") 1882 (neg:SI (match_operand:SI 1 "general_operand" "0,0")))] 1883 "" 1884 "#" 1885 "reload_completed" 1886 [(parallel [(set (match_dup 0) (neg:SI (match_dup 1))) 1887 (clobber (reg:CC CC_REGNUM))])] 1888 "" 1889 [(set_attr "length" "10,18")]) 1890 1891;; TODO: this can be neg/adc/neg/adc... I believe. Check. Saves one word. 1892(define_insn "negsi2_nocc" 1893 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o") 1894 (neg:SI (match_operand:SI 1 "general_operand" "0,0"))) 1895 (clobber (reg:CC CC_REGNUM))] 1896 "reload_completed" 1897 { 1898 rtx inops[2]; 1899 rtx exops[4][2]; 1900 1901 inops[0] = operands[0]; 1902 pdp11_expand_operands (inops, exops, 1, 2, NULL, big); 1903 1904 output_asm_insn (\"com\t%0\", exops[1]); 1905 output_asm_insn (\"com\t%0\", exops[0]); 1906 output_asm_insn (\"add\t%#1,%0\", exops[1]); 1907 output_asm_insn (\"adc\t%0\", exops[0]); 1908 1909 return \"\"; 1910 } 1911 [(set_attr "length" "10,18") 1912 (set_attr "base_cost" "0")]) 1913 1914(define_insn_and_split "neg<mode>2" 1915 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q") 1916 (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))] 1917 "" 1918 "#" 1919 "reload_completed" 1920 [(parallel [(set (match_dup 0) (neg:PDPint (match_dup 1))) 1921 (clobber (reg:CC CC_REGNUM))])] 1922 "" 1923 [(set_attr "length" "2,4")]) 1924 1925(define_insn "neg<mode>2<cc_ccnz>" 1926 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q") 1927 (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0"))) 1928 (clobber (reg:CC CC_REGNUM))] 1929 "" 1930 "neg<PDPint:isfx>\t%0" 1931 [(set_attr "length" "2,4")]) 1932 1933 1934;; Unconditional and other jump instructions 1935(define_insn "jump" 1936 [(set (pc) 1937 (label_ref (match_operand 0 "" "")))] 1938 "" 1939 "* 1940{ 1941 if (get_attr_length (insn) == 2) 1942 return \"br\t%l0\"; 1943 return \"jmp\t%l0\"; 1944}" 1945 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0) 1946 (pc)) 1947 (const_int MIN_BRANCH)) 1948 (gt (minus (match_dup 0) 1949 (pc)) 1950 (const_int MAX_BRANCH))) 1951 (const_int 4) 1952 (const_int 2)))]) 1953 1954(define_insn "tablejump" 1955 [(set (pc) (match_operand:HI 0 "general_operand" "r,R,Q")) 1956 (use (label_ref (match_operand 1 "" "")))] 1957 "" 1958 "@ 1959 jmp\t(%0) 1960 jmp\t%@%0 1961 jmp\t%@%0" 1962 [(set_attr "length" "2,2,4")]) 1963 1964;; indirect jump. TODO: this needs a constraint that allows memory 1965;; references but not indirection, since we add a level of indirection 1966;; in the generated code. 1967(define_insn "indirect_jump" 1968 [(set (pc) (match_operand:HI 0 "general_operand" "r"))] 1969 "" 1970 "jmp\t@%0" 1971 [(set_attr "length" "2")]) 1972 1973;;- jump to subroutine 1974 1975(define_insn "call" 1976 [(call (match_operand:HI 0 "general_operand" "rR,Q") 1977 (match_operand:HI 1 "general_operand" "g,g"))] 1978 ;;- Don't use operand 1 for most machines. 1979 "" 1980 "jsr\tpc,%0" 1981 [(set_attr "length" "2,4")]) 1982 1983;;- jump to subroutine 1984(define_insn "call_value" 1985 [(set (match_operand 0 "" "") 1986 (call (match_operand:HI 1 "general_operand" "rR,Q") 1987 (match_operand:HI 2 "general_operand" "g,g")))] 1988 ;;- Don't use operand 2 for most machines. 1989 "" 1990 "jsr\tpc,%1" 1991 [(set_attr "length" "2,4")]) 1992 1993(define_expand "untyped_call" 1994 [(parallel [(call (match_operand 0 "" "") 1995 (const_int 0)) 1996 (match_operand 1 "" "") 1997 (match_operand 2 "" "")])] 1998 "" 1999{ 2000 int i; 2001 2002 emit_call_insn (gen_call (operands[0], const0_rtx)); 2003 2004 for (i = 0; i < XVECLEN (operands[2], 0); i++) 2005 { 2006 rtx set = XVECEXP (operands[2], 0, i); 2007 emit_move_insn (SET_DEST (set), SET_SRC (set)); 2008 } 2009 2010 /* The optimizer does not know that the call sets the function value 2011 registers we stored in the result block. We avoid problems by 2012 claiming that all hard registers are used and clobbered at this 2013 point. */ 2014 emit_insn (gen_blockage ()); 2015 2016 DONE; 2017}) 2018 2019;;- nop instruction 2020(define_insn "nop" 2021 [(const_int 0)] 2022 "" 2023 "nop") 2024 2025 2026;;- multiply 2027 2028(define_insn_and_split "muldf3" 2029 [(set (match_operand:DF 0 "register_operand" "=a,a") 2030 (mult:DF (match_operand:DF 1 "register_operand" "%0,0") 2031 (match_operand:DF 2 "float_operand" "fR,QF")))] 2032 "TARGET_FPU" 2033 "#" 2034 "&& reload_completed" 2035 [(parallel [(set (match_dup 0) (mult:DF (match_dup 1) (match_dup 2))) 2036 (clobber (reg:CC FCC_REGNUM))])] 2037 "" 2038 [(set_attr "length" "2,4")]) 2039 2040(define_insn "muldf3<fcc_ccnz>" 2041 [(set (match_operand:DF 0 "register_operand" "=a,a") 2042 (mult:DF (match_operand:DF 1 "register_operand" "%0,0") 2043 (match_operand:DF 2 "float_operand" "fR,QF"))) 2044 (clobber (reg:CC FCC_REGNUM))] 2045 "TARGET_FPU && reload_completed" 2046 "{muld|mulf}\t%2,%0" 2047 [(set_attr "length" "2,4") 2048 (set_attr "base_cost" "20")]) 2049 2050;; 16 bit result multiply. This uses odd numbered registers. 2051 2052(define_insn_and_split "mulhi3" 2053 [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs 2054 (mult:HI (match_operand:HI 1 "register_operand" "%0,0") 2055 (match_operand:HI 2 "general_operand" "rR,Qi")))] 2056 "TARGET_40_PLUS" 2057 "#" 2058 "&& reload_completed" 2059 [(parallel [(set (match_dup 0) (mult:HI (match_dup 1) (match_dup 2))) 2060 (clobber (reg:CC CC_REGNUM))])] 2061 "" 2062 [(set_attr "length" "2,4")]) 2063 2064(define_insn "mulhi3<cc_cc>" 2065 [(set (match_operand:HI 0 "register_operand" "=d,d") 2066 (mult:HI (match_operand:HI 1 "register_operand" "%0,0") 2067 (match_operand:HI 2 "general_operand" "rR,Qi"))) 2068 (clobber (reg:CC CC_REGNUM))] 2069 "TARGET_40_PLUS && reload_completed" 2070 "mul\t%2,%0" 2071 [(set_attr "length" "2,4") 2072 (set_attr "base_cost" "20")]) 2073 2074;; 32 bit result from 16 bit operands 2075(define_insn_and_split "mulhisi3" 2076 [(set (match_operand:SI 0 "register_operand" "=r,r") 2077 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0")) 2078 (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi"))))] 2079 "TARGET_40_PLUS" 2080 "#" 2081 "&& reload_completed" 2082 [(parallel [(set (match_dup 0) 2083 (mult:SI (sign_extend:SI (match_dup 1)) 2084 (sign_extend:SI (match_dup 2)))) 2085 (clobber (reg:CC CC_REGNUM))])] 2086 "" 2087 [(set_attr "length" "2,4")]) 2088 2089(define_insn "mulhisi3<cc_cc>" 2090 [(set (match_operand:SI 0 "register_operand" "=r,r") 2091 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0")) 2092 (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi")))) 2093 (clobber (reg:CC CC_REGNUM))] 2094 "TARGET_40_PLUS && reload_completed" 2095 "mul\t%2,%0" 2096 [(set_attr "length" "2,4") 2097 (set_attr "base_cost" "20")]) 2098 2099;;- divide 2100(define_insn_and_split "divdf3" 2101 [(set (match_operand:DF 0 "register_operand" "=a,a") 2102 (div:DF (match_operand:DF 1 "register_operand" "0,0") 2103 (match_operand:DF 2 "general_operand" "fR,QF")))] 2104 "TARGET_FPU" 2105 "#" 2106 "&& reload_completed" 2107 [(parallel [(set (match_dup 0) (div:DF (match_dup 1) (match_dup 2))) 2108 (clobber (reg:CC FCC_REGNUM))])] 2109 "" 2110 [(set_attr "length" "2,4")]) 2111 2112(define_insn "divdf3<fcc_ccnz>" 2113 [(set (match_operand:DF 0 "register_operand" "=a,a") 2114 (div:DF (match_operand:DF 1 "register_operand" "0,0") 2115 (match_operand:DF 2 "general_operand" "fR,QF"))) 2116 (clobber (reg:CC FCC_REGNUM))] 2117 "TARGET_FPU && reload_completed" 2118 "{divd|divf}\t%2,%0" 2119 [(set_attr "length" "2,4") 2120 (set_attr "base_cost" "20")]) 2121 2122(define_expand "divmodhi4" 2123 [(parallel 2124 [(set (subreg:HI (match_dup 1) 0) 2125 (div:HI (match_operand:SI 1 "register_operand" "0") 2126 (match_operand:HI 2 "general_operand" "g"))) 2127 (set (subreg:HI (match_dup 1) 2) 2128 (mod:HI (match_dup 1) (match_dup 2)))]) 2129 (set (match_operand:HI 0 "register_operand" "=r") 2130 (subreg:HI (match_dup 1) 0)) 2131 (set (match_operand:HI 3 "register_operand" "=r") 2132 (subreg:HI (match_dup 1) 2))] 2133 "TARGET_40_PLUS" 2134 "") 2135 2136(define_insn_and_split "*divmodhi4" 2137 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0) 2138 (div:HI (match_operand:SI 1 "register_operand" "0,0") 2139 (match_operand:HI 2 "general_operand" "rR,Qi"))) 2140 (set (subreg:HI (match_dup 1) 2) 2141 (mod:HI (match_dup 1) (match_dup 2)))] 2142 "TARGET_40_PLUS" 2143 "#" 2144 "&& reload_completed" 2145 [(parallel [(set (subreg:HI (match_dup 0) 0) 2146 (div:HI (match_dup 1) (match_dup 2))) 2147 (set (subreg:HI (match_dup 1) 2) 2148 (mod:HI (match_dup 1) (match_dup 2))) 2149 (clobber (reg:CC CC_REGNUM))])] 2150 "" 2151 [(set_attr "length" "2,4")]) 2152 2153;; Note that there is no corresponding CC setter pattern. 2154;; The reason is that it won't be generated, because 2155;; compare-elim.c only does the transformation on input 2156;; insns that have a two-element PARALLEL, as opposed to 2157;; the three-element one we have here. 2158(define_insn "divmodhi4_nocc" 2159 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0) 2160 (div:HI (match_operand:SI 1 "register_operand" "0,0") 2161 (match_operand:HI 2 "general_operand" "rR,Qi"))) 2162 (set (subreg:HI (match_dup 1) 2) 2163 (mod:HI (match_dup 1) (match_dup 2))) 2164 (clobber (reg:CC CC_REGNUM))] 2165 "TARGET_40_PLUS" 2166 "div\t%2,%0" 2167 [(set_attr "length" "2,4") 2168 (set_attr "base_cost" "40")]) 2169 2170;; Byte swap 2171(define_insn_and_split "bswaphi2" 2172 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q") 2173 (bswap:HI (match_operand:HI 1 "general_operand" "0,0")))] 2174 "" 2175 "#" 2176 "reload_completed" 2177 [(parallel [(set (match_dup 0) (bswap:HI (match_dup 1))) 2178 (clobber (reg:CC CC_REGNUM))])] 2179 "" 2180 [(set_attr "length" "2,4")]) 2181 2182(define_insn "bswaphi2<cc_ccnz>" 2183 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q") 2184 (bswap:HI (match_operand:HI 1 "general_operand" "0,0"))) 2185 (clobber (reg:CC CC_REGNUM))] 2186 "" 2187 "swab\t%0" 2188 [(set_attr "length" "2,4")]) 2189 2190(define_insn_and_split "bswapsi2" 2191 [(set (match_operand:SI 0 "register_operand" "=&r") 2192 (bswap:SI (match_operand:SI 1 "general_operand" "g")))] 2193 "" 2194 "#" 2195 "reload_completed" 2196 [(parallel [(set (match_dup 0) 2197 (bswap:SI (match_dup 1))) 2198 (clobber (reg:CC CC_REGNUM))])] 2199 "" 2200 [(set_attr "length" "10")]) 2201 2202(define_insn "bswapsi2_nocc" 2203 [(set (match_operand:SI 0 "register_operand" "=&r,&r,&r") 2204 (bswap:SI (match_operand:SI 1 "general_operand" "r,D,Q"))) 2205 (clobber (reg:CC CC_REGNUM))] 2206 "" 2207 { 2208 rtx inops[2]; 2209 rtx exops[2][2]; 2210 rtx t; 2211 2212 inops[0] = operands[0]; 2213 inops[1] = operands[1]; 2214 pdp11_expand_operands (inops, exops, 2, 2, NULL, either); 2215 2216 t = exops[0][0]; 2217 exops[0][0] = exops[1][0]; 2218 exops[1][0] = t; 2219 2220 output_asm_insn ("mov\t%0,%1", exops[0]); 2221 output_asm_insn ("mov\t%0,%1", exops[1]); 2222 output_asm_insn ("swab\t%0", exops[0]); 2223 output_asm_insn ("swab\t%0", exops[1]); 2224 return ""; 2225 } 2226 [(set_attr "length" "8,10,12")]) 2227 2228(define_expand "rotrhi3" 2229 [(match_operand:HI 0 "register_operand" "") 2230 (match_operand:HI 1 "register_operand" "") 2231 (match_operand:HI 2 "general_operand" "")] 2232 "TARGET_40_PLUS" 2233 " 2234{ 2235 operands[2] = negate_rtx (HImode, operands[2]); 2236 emit_insn (gen_rotlhi3 (operands[0], operands[1], operands[2])); 2237 DONE; 2238}") 2239 2240(define_insn_and_split "rotlhi3" 2241 [(set (match_operand:HI 0 "register_operand" "=d,d") 2242 (rotate:HI (match_operand:HI 1 "register_operand" "0,0") 2243 (match_operand:HI 2 "general_operand" "rR,Qi")))] 2244 "TARGET_40_PLUS" 2245 "#" 2246 "&& reload_completed" 2247 [(parallel [(set (match_dup 0) 2248 (rotate:HI (match_dup 1) (match_dup 2))) 2249 (clobber (reg:CC CC_REGNUM))])] 2250 "" 2251 [(set_attr "length" "2,4") 2252 (set_attr "base_cost" "8")]) 2253 2254(define_insn "rotlhi3<cc_ccnz>" 2255 [(set (match_operand:HI 0 "register_operand" "=d,d") 2256 (rotate:HI (match_operand:HI 1 "register_operand" "0,0") 2257 (match_operand:HI 2 "general_operand" "rR,Qi"))) 2258 (clobber (reg:CC CC_REGNUM))] 2259 "TARGET_40_PLUS && reload_completed" 2260 "ashc\t%2,%0" 2261 [(set_attr "length" "2,4") 2262 (set_attr "base_cost" "8")]) 2263 2264 2265 2266;; Some peephole optimizations 2267 2268;; Move then conditional branch on the result of the move is handled 2269;; by compare elimination, but an earlier pass sometimes changes the 2270;; compare operand to the move input, and then the compare is not 2271;; eliminated. Do so here. 2272(define_peephole2 2273 [(parallel [(set (match_operand:PDPint 0 "nonimmediate_operand" "") 2274 (match_operand:PDPint 1 "general_operand" "")) 2275 (clobber (reg:CC CC_REGNUM))]) 2276 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))] 2277 "" 2278 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0))) 2279 (set (match_dup 0) (match_dup 1))])] 2280 "") 2281