1;;- Machine description for the pdp11 for GNU C compiler 2;; Copyright (C) 1994-2018 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 ]) 30 31(define_constants 32 [ 33 ;; Register numbers 34 (R0_REGNUM 0) 35 (RETVAL_REGNUM 0) 36 (HARD_FRAME_POINTER_REGNUM 5) 37 (STACK_POINTER_REGNUM 6) 38 (PC_REGNUM 7) 39 (AC0_REGNUM 8) 40 (AC3_REGNUM 11) 41 (AC4_REGNUM 12) 42 (AC5_REGNUM 13) 43 ;; The next two are not physical registers but are used for addressing 44 ;; arguments. 45 (FRAME_POINTER_REGNUM 14) 46 (ARG_POINTER_REGNUM 15) 47 (FIRST_PSEUDO_REGISTER 16) 48 ;; Branch offset limits, as byte offsets from instruction address 49 (MIN_BRANCH -254) 50 (MAX_BRANCH 256) 51 (MIN_SOB -126) 52 (MAX_SOB 0)]) 53 54;; HI is 16 bit 55;; QI is 8 bit 56 57;; Integer modes supported on the PDP11, with a mapping from machine mode 58;; to mnemonic suffix. SImode and DImode always are special cases. 59(define_mode_iterator PDPint [QI HI]) 60(define_mode_attr isfx [(QI "b") (HI "")]) 61 62;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. 63 64;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code 65;;- updates for most instructions. 66 67;;- Operand classes for the register allocator: 68 69;; Compare instructions. 70 71;; currently we only support df floats, which saves us quite some 72;; hassle switching the FP mode! 73;; we assume that CPU is always in long float mode, and 74;; 16 bit integer mode - currently, the prologue for main does this, 75;; but maybe we should just set up a NEW crt0 properly, 76;; -- and what about signal handling code? 77;; (we don't even let sf floats in the register file, so 78;; we only should have to worry about truncating and widening 79;; when going to memory) 80 81;; abort() call by g++ - must define libfunc for cmp_optab 82;; and ucmp_optab for mode SImode, because we don't have that!!! 83;; - yet since no libfunc is there, we abort () 84 85;; The only thing that remains to be done then is output 86;; the floats in a way the assembler can handle it (and 87;; if you're really into it, use a PDP11 float emulation 88;; library to do floating point constant folding - but 89;; I guess you'll get reasonable results even when not 90;; doing this) 91;; the last thing to do is fix the UPDATE_CC macro to check 92;; for floating point condition codes, and set cc_status 93;; properly, also setting the CC_IN_FCCR flag. 94 95;; define attributes 96;; currently type is only fpu or arith or unknown, maybe branch later ? 97;; default is arith 98(define_attr "type" "unknown,arith,fp" (const_string "arith")) 99 100;; length default is 2 bytes each 101(define_attr "length" "" (const_int 2)) 102 103;; a user's asm statement 104(define_asm_attributes 105 [(set_attr "type" "unknown") 106; length for asm is the max length per statement. That would be 107; 3 words, for a two-operand instruction with extra word addressing 108; modes for both operands. 109 (set_attr "length" "6")]) 110 111;; define function units 112 113;; Prologue and epilogue support. 114 115(define_expand "prologue" 116 [(const_int 0)] 117 "" 118{ 119 pdp11_expand_prologue (); 120 DONE; 121}) 122 123(define_expand "epilogue" 124 [(const_int 0)] 125 "" 126{ 127 pdp11_expand_epilogue (); 128 DONE; 129}) 130 131(define_expand "return" 132 [(return)] 133 "reload_completed && !frame_pointer_needed && pdp11_sp_frame_offset () == 0" 134 "") 135 136(define_insn "*rts" 137 [(return)] 138 "" 139 "rts pc") 140 141(define_insn "blockage" 142 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] 143 "" 144 "" 145 [(set_attr "length" "0")]) 146 147(define_insn "setd" 148 [(unspec_volatile [(const_int 0)] UNSPECV_SETD)] 149 "" 150 "setd") 151 152(define_insn "seti" 153 [(unspec_volatile [(const_int 0)] UNSPECV_SETI)] 154 "" 155 "seti") 156 157;; arithmetic - values here immediately when next insn issued 158;; or does it mean the number of cycles after this insn was issued? 159;; how do I say that fpu insns use cpu also? (pre-interaction phase) 160 161;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0) 162;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0) 163 164;; compare 165(define_insn "*cmpdf" 166 [(set (cc0) 167 (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,QF") 168 (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))] 169 "TARGET_FPU" 170 "* 171{ 172 cc_status.flags = CC_IN_FPU; 173 if (which_alternative == 0 || which_alternative == 2) 174 return \"{tstd|tstf} %0\;cfcc\"; 175 else 176 return \"{cmpd|cmpf} %0, %1\;cfcc\"; 177}" 178 [(set_attr "length" "4,4,6,6")]) 179 180(define_insn "*cmp<mode>" 181 [(set (cc0) 182 (compare (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi") 183 (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))] 184 "" 185 "@ 186 tst<PDPint:isfx> %0 187 cmp<PDPint:isfx> %0,%1 188 cmp<PDPint:isfx> %0,%1 189 tst<PDPint:isfx> %0 190 cmp<PDPint:isfx> %0,%1 191 cmp<PDPint:isfx> %0,%1" 192 [(set_attr "length" "2,2,4,4,4,6")]) 193 194;; sob instruction - we need an assembler which can make this instruction 195;; valid under _all_ circumstances! 196 197(define_insn "" 198 [(set (pc) 199 (if_then_else 200 (ne (plus:HI (match_operand:HI 0 "register_operand" "+r") 201 (const_int -1)) 202 (const_int 0)) 203 (label_ref (match_operand 1 "" "")) 204 (pc))) 205 (set (match_dup 0) 206 (plus:HI (match_dup 0) 207 (const_int -1)))] 208 "TARGET_40_PLUS" 209 "* 210{ 211 static int labelcount = 0; 212 static char buf[1000]; 213 214 if (get_attr_length (insn) == 2) 215 return \"sob %0, %l1\"; 216 217 /* emulate sob */ 218 output_asm_insn (\"dec %0\", operands); 219 220 sprintf (buf, \"bge LONG_SOB%d\", labelcount); 221 output_asm_insn (buf, NULL); 222 223 output_asm_insn (\"jmp %l1\", operands); 224 225 sprintf (buf, \"LONG_SOB%d:\", labelcount++); 226 output_asm_insn (buf, NULL); 227 228 return \"\"; 229}" 230 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0) 231 (pc)) 232 (const_int MIN_SOB)) 233 (gt (minus (match_dup 0) 234 (pc)) 235 (const_int MAX_SOB))) 236 (const_int 8) 237 (const_int 2)))]) 238 239;; These control RTL generation for conditional jump insns 240;; and match them for register allocation. 241 242(define_expand "cbranchdf4" 243 [(set (cc0) 244 (compare (match_operand:DF 1 "general_operand") 245 (match_operand:DF 2 "register_or_const0_operand"))) 246 (set (pc) 247 (if_then_else (match_operator 0 "ordered_comparison_operator" 248 [(cc0) (const_int 0)]) 249 (label_ref (match_operand 3 "" "")) 250 (pc)))] 251 "TARGET_FPU" 252 "") 253 254(define_expand "cbranch<mode>4" 255 [(set (cc0) 256 (compare (match_operand:PDPint 1 "general_operand") 257 (match_operand:PDPint 2 "general_operand"))) 258 (set (pc) 259 (if_then_else (match_operator 0 "ordered_comparison_operator" 260 [(cc0) (const_int 0)]) 261 (label_ref (match_operand 3 "" "")) 262 (pc)))] 263 "" 264 "") 265 266;; problem with too short jump distance! we need an assembler which can 267;; make this valid for all jump distances! 268;; e.g. gas! 269 270;; these must be changed to check for CC_IN_FCCR if float is to be 271;; enabled 272 273(define_insn "*branch" 274 [(set (pc) 275 (if_then_else (match_operator 0 "ordered_comparison_operator" 276 [(cc0) (const_int 0)]) 277 (label_ref (match_operand 1 "" "")) 278 (pc)))] 279 "" 280 "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));" 281 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1) 282 (pc)) 283 (const_int MIN_BRANCH)) 284 (gt (minus (match_dup 1) 285 (pc)) 286 (const_int MAX_BRANCH))) 287 (const_int 6) 288 (const_int 2)))]) 289 290 291;; These match inverted jump insns for register allocation. 292 293(define_insn "*branch_inverted" 294 [(set (pc) 295 (if_then_else (match_operator 0 "ordered_comparison_operator" 296 [(cc0) (const_int 0)]) 297 (pc) 298 (label_ref (match_operand 1 "" ""))))] 299 "" 300 "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));" 301 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1) 302 (pc)) 303 (const_int MIN_BRANCH)) 304 (gt (minus (match_dup 1) 305 (pc)) 306 (const_int MAX_BRANCH))) 307 (const_int 6) 308 (const_int 2)))]) 309 310;; Move instructions 311 312(define_insn "movdi" 313 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g") 314 (match_operand:DI 1 "general_operand" "rN,g"))] 315 "" 316 "* return output_move_multiple (operands);" 317;; what's the mose expensive code - say twice movsi = 16 318 [(set_attr "length" "16,32")]) 319 320(define_insn "movsi" 321 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g") 322 (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))] 323 "" 324 "* return output_move_multiple (operands);" 325;; what's the most expensive code ? - I think 8! 326;; we could split it up and make several sub-cases... 327 [(set_attr "length" "4,6,8,16")]) 328 329(define_insn "mov<mode>" 330 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q") 331 (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))] 332 "" 333 "* 334{ 335 if (operands[1] == const0_rtx) 336 return \"clr<PDPint:isfx> %0\"; 337 338 return \"mov<PDPint:isfx> %1, %0\"; 339}" 340 [(set_attr "length" "2,4,4,6")]) 341 342(define_insn "movdf" 343 [(set (match_operand:DF 0 "float_nonimm_operand" "=a,fR,a,Q,g") 344 (match_operand:DF 1 "float_operand" "fR,a,FQ,a,g"))] 345 "TARGET_FPU" 346 "* if (which_alternative ==0 || which_alternative == 2) 347 return \"ldd %1, %0\"; 348 else if (which_alternative == 1 || which_alternative == 3) 349 return \"std %1, %0\"; 350 else 351 return output_move_multiple (operands); " 352;; last one is worst-case 353 [(set_attr "length" "2,2,4,4,24")]) 354 355(define_insn "movsf" 356 [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,g") 357 (match_operand:SF 1 "float_operand" "fR,a,FQ,a,g"))] 358 "TARGET_FPU" 359 "* if (which_alternative ==0 || which_alternative == 2) 360 return \"{ldcfd|movof} %1, %0\"; 361 else if (which_alternative == 1 || which_alternative == 3) 362 return \"{stcdf|movfo} %1, %0\"; 363 else 364 return output_move_multiple (operands); " 365;; last one is worst-case 366 [(set_attr "length" "2,2,4,4,12")]) 367 368;; maybe fiddle a bit with move_ratio, then 369;; let constraints only accept a register ... 370 371(define_expand "movmemhi" 372 [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g") 373 (match_operand:BLK 1 "general_operand" "g,g")) 374 (use (match_operand:HI 2 "general_operand" "n,mr")) 375 (use (match_operand:HI 3 "immediate_operand" "i,i")) 376 (clobber (match_scratch:HI 6 "=&r,X")) 377 (clobber (match_dup 4)) 378 (clobber (match_dup 5)) 379 (clobber (match_dup 2))])] 380 "(TARGET_BCOPY_BUILTIN)" 381 " 382{ 383 operands[0] 384 = replace_equiv_address (operands[0], 385 copy_to_mode_reg (Pmode, XEXP (operands[0], 0))); 386 operands[1] 387 = replace_equiv_address (operands[1], 388 copy_to_mode_reg (Pmode, XEXP (operands[1], 0))); 389 390 operands[4] = XEXP (operands[0], 0); 391 operands[5] = XEXP (operands[1], 0); 392}") 393 394 395(define_insn "movmemhi1" 396 [(set (mem:BLK (match_operand:HI 0 "register_operand" "r,r")) 397 (mem:BLK (match_operand:HI 1 "register_operand" "r,r"))) 398 (use (match_operand:HI 2 "general_operand" "n,r")) 399 (use (match_operand:HI 3 "immediate_operand" "i,i")) 400 (clobber (match_scratch:HI 4 "=&r,X")) 401 (clobber (match_dup 0)) 402 (clobber (match_dup 1)) 403 (clobber (match_dup 2))] 404 "(TARGET_BCOPY_BUILTIN)" 405 "* return output_block_move (operands);" 406;;; just a guess 407 [(set_attr "length" "80")]) 408 409 410 411;;- truncation instructions 412 413(define_insn "truncdfsf2" 414 [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q") 415 (float_truncate:SF (match_operand:DF 1 "register_operand" "f,a,a")))] 416 "TARGET_FPU" 417 "* if (which_alternative ==0) 418 { 419 return \"\"; 420 } 421 else if (which_alternative == 1) 422 return \"{stcdf|movfo} %1, %0\"; 423 else 424 return \"{stcdf|movfo} %1, %0\"; 425 " 426 [(set_attr "length" "0,2,4")]) 427 428 429(define_expand "truncsihi2" 430 [(set (match_operand:HI 0 "nonimmediate_operand" "=g") 431 (subreg:HI 432 (match_operand:SI 1 "general_operand" "or") 433 0))] 434 "" 435 "") 436 437 438;;- zero extension instructions 439 440(define_insn "zero_extendqihi2" 441 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q") 442 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))] 443 "" 444 "bic $0177400, %0" 445 [(set_attr "length" "4,6")]) 446 447(define_expand "zero_extendhisi2" 448 [(set (subreg:HI 449 (match_dup 0) 450 2) 451 (match_operand:HI 1 "register_operand" "r")) 452 (set (subreg:HI 453 (match_operand:SI 0 "register_operand" "=r") 454 0) 455 (const_int 0))] 456 "" 457 "/* operands[1] = make_safe_from (operands[1], operands[0]); */") 458 459 460;;- sign extension instructions 461 462(define_insn "extendsfdf2" 463 [(set (match_operand:DF 0 "register_operand" "=f,a,a") 464 (float_extend:DF (match_operand:SF 1 "float_operand" "f,R,Q")))] 465 "TARGET_FPU" 466 "@ 467 /* nothing */ 468 {ldcfd|movof} %1, %0 469 {ldcfd|movof} %1, %0" 470 [(set_attr "length" "0,2,4")]) 471 472;; does movb sign extend in register-to-register move? 473(define_insn "extendqihi2" 474 [(set (match_operand:HI 0 "register_operand" "=r,r") 475 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))] 476 "" 477 "movb %1, %0" 478 [(set_attr "length" "2,4")]) 479 480(define_insn "extendqisi2" 481 [(set (match_operand:SI 0 "register_operand" "=r,r") 482 (sign_extend:SI (match_operand:QI 1 "general_operand" "rR,Q")))] 483 "TARGET_40_PLUS" 484 "* 485{ 486 rtx latehalf[2]; 487 488 /* make register pair available */ 489 latehalf[0] = operands[0]; 490 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+ 1); 491 492 output_asm_insn(\"movb %1, %0\", operands); 493 output_asm_insn(\"sxt %0\", latehalf); 494 495 return \"\"; 496}" 497 [(set_attr "length" "4,6")]) 498 499;; maybe we have to use define_expand to say that we have the instruction, 500;; unconditionally, and then match dependent on CPU type: 501 502(define_expand "extendhisi2" 503 [(set (match_operand:SI 0 "nonimmediate_operand" "=g") 504 (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))] 505 "" 506 "") 507 508(define_insn "" ; "extendhisi2" 509 [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r") 510 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))] 511 "TARGET_40_PLUS" 512 "* 513{ 514 rtx latehalf[2]; 515 516 /* we don't want to mess with auto increment */ 517 518 switch (which_alternative) 519 { 520 case 0: 521 522 latehalf[0] = operands[0]; 523 operands[0] = adjust_address(operands[0], HImode, 2); 524 525 output_asm_insn(\"mov %1, %0\", operands); 526 output_asm_insn(\"sxt %0\", latehalf); 527 528 return \"\"; 529 530 case 1: 531 532 /* - auto-decrement - right direction ;-) */ 533 output_asm_insn(\"mov %1, %0\", operands); 534 output_asm_insn(\"sxt %0\", operands); 535 536 return \"\"; 537 538 case 2: 539 540 /* make register pair available */ 541 latehalf[0] = operands[0]; 542 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1); 543 544 output_asm_insn(\"mov %1, %0\", operands); 545 output_asm_insn(\"sxt %0\", latehalf); 546 547 return \"\"; 548 549 default: 550 551 gcc_unreachable (); 552 } 553}" 554 [(set_attr "length" "10,6,6")]) 555 556 557(define_insn "" 558 [(set (match_operand:SI 0 "register_operand" "=r") 559 (sign_extend:SI (match_operand:HI 1 "general_operand" "0")))] 560 "(! TARGET_40_PLUS)" 561 "* 562{ 563 static int count = 0; 564 char buf[100]; 565 rtx lateoperands[2]; 566 567 lateoperands[0] = operands[0]; 568 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1); 569 570 output_asm_insn(\"tst %0\", operands); 571 sprintf(buf, \"bge extendhisi%d\", count); 572 output_asm_insn(buf, NULL); 573 output_asm_insn(\"mov -1, %0\", lateoperands); 574 sprintf(buf, \"bne extendhisi%d\", count+1); 575 output_asm_insn(buf, NULL); 576 sprintf(buf, \"\\nextendhisi%d:\", count); 577 output_asm_insn(buf, NULL); 578 output_asm_insn(\"clr %0\", lateoperands); 579 sprintf(buf, \"\\nextendhisi%d:\", count+1); 580 output_asm_insn(buf, NULL); 581 582 count += 2; 583 584 return \"\"; 585}" 586 [(set_attr "length" "12")]) 587 588;; make float to int and vice versa 589;; using the cc_status.flag field we could probably cut down 590;; on seti and setl 591;; assume that we are normally in double and integer mode - 592;; what do pdp library routines do to fpu mode ? 593 594(define_insn "floatsidf2" 595 [(set (match_operand:DF 0 "register_operand" "=a,a,a") 596 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))] 597 "TARGET_FPU" 598 "* if (which_alternative ==0) 599 { 600 rtx latehalf[2]; 601 602 latehalf[0] = NULL; 603 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1); 604 output_asm_insn(\"mov %1, -(sp)\", latehalf); 605 output_asm_insn(\"mov %1, -(sp)\", operands); 606 607 output_asm_insn(\"setl\", operands); 608 output_asm_insn(\"{ldcld|movif} (sp)+, %0\", operands); 609 output_asm_insn(\"seti\", operands); 610 return \"\"; 611 } 612 else if (which_alternative == 1) 613 return \"setl\;{ldcld|movif} %1, %0\;seti\"; 614 else 615 return \"setl\;{ldcld|movif} %1, %0\;seti\"; 616 " 617 [(set_attr "length" "10,6,8")]) 618 619(define_insn "floathidf2" 620 [(set (match_operand:DF 0 "register_operand" "=a,a") 621 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))] 622 "TARGET_FPU" 623 "{ldcid|movif} %1, %0" 624 [(set_attr "length" "2,4")]) 625 626;; cut float to int 627(define_insn "fix_truncdfsi2" 628 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q") 629 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))] 630 "TARGET_FPU" 631 "* if (which_alternative ==0) 632 { 633 output_asm_insn(\"setl\", operands); 634 output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands); 635 output_asm_insn(\"seti\", operands); 636 output_asm_insn(\"mov (sp)+, %0\", operands); 637 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1); 638 output_asm_insn(\"mov (sp)+, %0\", operands); 639 return \"\"; 640 } 641 else if (which_alternative == 1) 642 return \"setl\;{stcdl|movfi} %1, %0\;seti\"; 643 else 644 return \"setl\;{stcdl|movfi} %1, %0\;seti\"; 645 " 646 [(set_attr "length" "10,6,8")]) 647 648(define_insn "fix_truncdfhi2" 649 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q") 650 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))] 651 "TARGET_FPU" 652 "{stcdi|movfi} %1, %0" 653 [(set_attr "length" "2,4")]) 654 655 656;;- arithmetic instructions 657;;- add instructions 658 659(define_insn "adddf3" 660 [(set (match_operand:DF 0 "register_operand" "=a,a") 661 (plus:DF (match_operand:DF 1 "register_operand" "%0,0") 662 (match_operand:DF 2 "general_operand" "fR,QF")))] 663 "TARGET_FPU" 664 "{addd|addf} %2, %0" 665 [(set_attr "length" "2,4")]) 666 667(define_insn "adddi3" 668 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o") 669 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0") 670 (match_operand:DI 2 "general_operand" "r,on,r,on")))] 671 "" 672 "* 673{ 674 rtx inops[2]; 675 rtx exops[4][2]; 676 677 inops[0] = operands[0]; 678 inops[1] = operands[2]; 679 pdp11_expand_operands (inops, exops, 2, NULL, either); 680 681 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0) 682 output_asm_insn (\"add %1, %0\", exops[0]); 683 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0) 684 { 685 output_asm_insn (\"add %1, %0\", exops[1]); 686 output_asm_insn (\"adc %0\", exops[0]); 687 } 688 if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0) 689 { 690 output_asm_insn (\"add %1, %0\", exops[2]); 691 output_asm_insn (\"adc %0\", exops[1]); 692 output_asm_insn (\"adc %0\", exops[0]); 693 } 694 if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0) 695 { 696 output_asm_insn (\"add %1, %0\", exops[3]); 697 output_asm_insn (\"adc %0\", exops[2]); 698 output_asm_insn (\"adc %0\", exops[1]); 699 output_asm_insn (\"adc %0\", exops[0]); 700 } 701 702 return \"\"; 703}" 704 [(set_attr "length" "20,28,40,48")]) 705 706;; Note that the register operand is not marked earlyclobber. 707;; The reason is that SI values go in register pairs, so they 708;; can't partially overlap. They can be either disjoint, or 709;; source and destination can be equal. The latter case is 710;; handled properly because of the ordering of the individual 711;; instructions used. Specifically, carry from the low to the 712;; high word is added at the end, so the adding of the high parts 713;; will always used the original high part and not a high part 714;; modified by carry (which would amount to double carry). 715(define_insn "addsi3" 716 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o") 717 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0") 718 (match_operand:SI 2 "general_operand" "r,on,r,on")))] 719 "" 720 "* 721{ 722 rtx inops[2]; 723 rtx exops[2][2]; 724 725 inops[0] = operands[0]; 726 inops[1] = operands[2]; 727 pdp11_expand_operands (inops, exops, 2, NULL, either); 728 729 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0) 730 output_asm_insn (\"add %1, %0\", exops[0]); 731 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0) 732 { 733 output_asm_insn (\"add %1, %0\", exops[1]); 734 output_asm_insn (\"adc %0\", exops[0]); 735 } 736 737 return \"\"; 738}" 739 [(set_attr "length" "6,10,12,16")]) 740 741(define_insn "addhi3" 742 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q") 743 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0") 744 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))] 745 "" 746 "* 747{ 748 if (GET_CODE (operands[2]) == CONST_INT) 749 { 750 if (INTVAL(operands[2]) == 1) 751 return \"inc %0\"; 752 else if (INTVAL(operands[2]) == -1) 753 return \"dec %0\"; 754 } 755 756 return \"add %2, %0\"; 757}" 758 [(set_attr "length" "2,4,4,6")]) 759 760 761;;- subtract instructions 762;; we don't have to care for constant second 763;; args, since they are canonical plus:xx now! 764;; also for minus:DF ?? 765 766(define_insn "subdf3" 767 [(set (match_operand:DF 0 "register_operand" "=a,a") 768 (minus:DF (match_operand:DF 1 "register_operand" "0,0") 769 (match_operand:DF 2 "general_operand" "fR,Q")))] 770 "TARGET_FPU" 771 "{subd|subf} %2, %0" 772 [(set_attr "length" "2,4")]) 773 774(define_insn "subdi3" 775 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o") 776 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0") 777 (match_operand:DI 2 "general_operand" "r,on,r,on")))] 778 "" 779 "* 780{ 781 rtx inops[2]; 782 rtx exops[4][2]; 783 784 inops[0] = operands[0]; 785 inops[1] = operands[2]; 786 pdp11_expand_operands (inops, exops, 2, NULL, either); 787 788 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0) 789 output_asm_insn (\"sub %1, %0\", exops[0]); 790 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0) 791 { 792 output_asm_insn (\"sub %1, %0\", exops[1]); 793 output_asm_insn (\"sbc %0\", exops[0]); 794 } 795 if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0) 796 { 797 output_asm_insn (\"sub %1, %0\", exops[2]); 798 output_asm_insn (\"sbc %0\", exops[1]); 799 output_asm_insn (\"sbc %0\", exops[0]); 800 } 801 if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0) 802 { 803 output_asm_insn (\"sub %1, %0\", exops[3]); 804 output_asm_insn (\"sbc %0\", exops[2]); 805 output_asm_insn (\"sbc %0\", exops[1]); 806 output_asm_insn (\"sbc %0\", exops[0]); 807 } 808 809 return \"\"; 810}" 811 [(set_attr "length" "20,28,40,48")]) 812 813(define_insn "subsi3" 814 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o") 815 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0") 816 (match_operand:SI 2 "general_operand" "r,on,r,on")))] 817 "" 818 "* 819{ 820 rtx inops[2]; 821 rtx exops[2][2]; 822 823 inops[0] = operands[0]; 824 inops[1] = operands[2]; 825 pdp11_expand_operands (inops, exops, 2, NULL, either); 826 827 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0) 828 output_asm_insn (\"sub %1, %0\", exops[0]); 829 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0) 830 { 831 output_asm_insn (\"sub %1, %0\", exops[1]); 832 output_asm_insn (\"sbc %0\", exops[0]); 833 } 834 835 return \"\"; 836}" 837 [(set_attr "length" "6,10,12,16")]) 838 839(define_insn "subhi3" 840 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q") 841 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0") 842 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))] 843 "" 844 "* 845{ 846 gcc_assert (GET_CODE (operands[2]) != CONST_INT); 847 848 return \"sub %2, %0\"; 849}" 850 [(set_attr "length" "2,4,4,6")]) 851 852;;;;- and instructions 853;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn. 854 855(define_expand "and<mode>3" 856 [(set (match_operand:PDPint 0 "nonimmediate_operand" "") 857 (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" "")) 858 (match_operand:PDPint 2 "general_operand" "")))] 859 "" 860 " 861{ 862 rtx op1 = operands[1]; 863 864 /* If there is a constant argument, complement that one. 865 Similarly, if one of the inputs is the same as the output, 866 complement the other input. */ 867 if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) || 868 rtx_equal_p (operands[0], operands[1])) 869 { 870 operands[1] = operands[2]; 871 operands[2] = op1; 872 op1 = operands[1]; 873 } 874 875 if (CONST_INT_P (op1)) 876 operands[1] = GEN_INT (~INTVAL (op1)); 877 else 878 operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1); 879}") 880 881(define_insn "*bic<mode>" 882 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q") 883 (and:PDPint 884 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi")) 885 (match_operand:PDPint 2 "general_operand" "0,0,0,0")))] 886 "" 887 "bic<PDPint:isfx> %1, %0" 888 [(set_attr "length" "2,4,4,6")]) 889 890;;- Bit set (inclusive or) instructions 891(define_insn "ior<mode>3" 892 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q") 893 (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0") 894 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))] 895 "" 896 "bis<PDPint:isfx> %2, %0" 897 [(set_attr "length" "2,4,4,6")]) 898 899;;- xor instructions 900(define_insn "xorhi3" 901 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q") 902 (xor:HI (match_operand:HI 1 "general_operand" "%0,0") 903 (match_operand:HI 2 "register_operand" "r,r")))] 904 "TARGET_40_PLUS" 905 "xor %2, %0" 906 [(set_attr "length" "2,4")]) 907 908;;- one complement instructions 909 910(define_insn "one_cmpl<mode>2" 911 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q") 912 (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))] 913 "" 914 "com<PDPint:isfx> %0" 915 [(set_attr "length" "2,4")]) 916 917;;- arithmetic shift instructions 918(define_insn "ashlsi3" 919 [(set (match_operand:SI 0 "register_operand" "=r,r") 920 (ashift:SI (match_operand:SI 1 "register_operand" "0,0") 921 (match_operand:HI 2 "general_operand" "rR,Qi")))] 922 "TARGET_40_PLUS" 923 "ashc %2,%0" 924 [(set_attr "length" "2,4")]) 925 926;; Arithmetic right shift on the pdp works by negating the shift count. 927(define_expand "ashrsi3" 928 [(set (match_operand:SI 0 "register_operand" "=r") 929 (ashift:SI (match_operand:SI 1 "register_operand" "0") 930 (match_operand:HI 2 "general_operand" "g")))] 931 "" 932 " 933{ 934 operands[2] = negate_rtx (HImode, operands[2]); 935}") 936 937;; define asl aslb asr asrb - ashc missing! 938 939;; asl 940(define_insn "" 941 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q") 942 (ashift:HI (match_operand:HI 1 "general_operand" "0,0") 943 (const_int 1)))] 944 "" 945 "asl %0" 946 [(set_attr "length" "2,4")]) 947 948;; and another possibility for asr is << -1 949;; might cause problems since -1 can also be encoded as 65535! 950;; not in gcc2 ??? 951 952;; asr 953(define_insn "" 954 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q") 955 (ashift:HI (match_operand:HI 1 "general_operand" "0,0") 956 (const_int -1)))] 957 "" 958 "asr %0" 959 [(set_attr "length" "2,4")]) 960 961;; lsr 962(define_insn "lsrhi1" 963 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q") 964 (lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0") 965 (const_int 1)))] 966 "" 967 "clc\;ror %0" 968 [(set_attr "length" "2,4")]) 969 970(define_insn "lsrsi1" 971 [(set (match_operand:SI 0 "register_operand" "=r") 972 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0") 973 (const_int 1)))] 974 "" 975{ 976 977 rtx lateoperands[2]; 978 979 lateoperands[0] = operands[0]; 980 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1); 981 982 lateoperands[1] = operands[1]; 983 operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1); 984 985 output_asm_insn (\"clc\", operands); 986 output_asm_insn (\"ror %0\", lateoperands); 987 output_asm_insn (\"ror %0\", operands); 988 989 return \"\"; 990} 991 [(set_attr "length" "10")]) 992 993(define_expand "lshrsi3" 994 [(match_operand:SI 0 "register_operand" "") 995 (match_operand:SI 1 "register_operand" "0") 996 (match_operand:HI 2 "general_operand" "")] 997 "" 998 " 999{ 1000 rtx r; 1001 1002 if (!TARGET_40_PLUS && 1003 (GET_CODE (operands[2]) != CONST_INT || 1004 (unsigned) INTVAL (operands[2]) > 3)) 1005 FAIL; 1006 emit_insn (gen_lsrsi1 (operands[0], operands[1])); 1007 if (GET_CODE (operands[2]) != CONST_INT) 1008 { 1009 r = gen_reg_rtx (HImode); 1010 emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1))); 1011 emit_insn (gen_ashrsi3 (operands[0], operands[0], r)); 1012 } 1013 else if ((unsigned) INTVAL (operands[2]) != 1) 1014 { 1015 emit_insn (gen_ashlsi3 (operands[0], operands[0], 1016 GEN_INT (1 - INTVAL (operands[2])))); 1017 } 1018 DONE; 1019} 1020" 1021) 1022 1023;; shift is by arbitrary count is expensive, 1024;; shift by one cheap - so let's do that, if 1025;; space doesn't matter 1026(define_insn "" 1027 [(set (match_operand:HI 0 "nonimmediate_operand" "=r") 1028 (ashift:HI (match_operand:HI 1 "general_operand" "0") 1029 (match_operand:HI 2 "expand_shift_operand" "O")))] 1030 "! optimize_size" 1031 "* 1032{ 1033 register int i; 1034 1035 for (i = 1; i <= abs(INTVAL(operands[2])); i++) 1036 if (INTVAL(operands[2]) < 0) 1037 output_asm_insn(\"asr %0\", operands); 1038 else 1039 output_asm_insn(\"asl %0\", operands); 1040 1041 return \"\"; 1042}" 1043;; longest is 4 1044 [(set (attr "length") (const_int 8))]) 1045 1046;; aslb 1047(define_insn "" 1048 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o") 1049 (ashift:QI (match_operand:QI 1 "general_operand" "0,0") 1050 (match_operand:HI 2 "const_int_operand" "n,n")))] 1051 "" 1052 "* 1053{ /* allowing predec or post_inc is possible, but hairy! */ 1054 int i, cnt; 1055 1056 cnt = INTVAL(operands[2]) & 0x0007; 1057 1058 for (i=0 ; i < cnt ; i++) 1059 output_asm_insn(\"aslb %0\", operands); 1060 1061 return \"\"; 1062}" 1063;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!! 1064 [(set_attr_alternative "length" 1065 [(const_int 14) 1066 (const_int 28)])]) 1067 1068;;; asr 1069;(define_insn "" 1070; [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q") 1071; (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0") 1072; (const_int 1)))] 1073; "" 1074; "asr %0" 1075; [(set_attr "length" "2,4")]) 1076 1077;; asrb 1078(define_insn "" 1079 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o") 1080 (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0") 1081 (match_operand:HI 2 "const_int_operand" "n,n")))] 1082 "" 1083 "* 1084{ /* allowing predec or post_inc is possible, but hairy! */ 1085 int i, cnt; 1086 1087 cnt = INTVAL(operands[2]) & 0x0007; 1088 1089 for (i=0 ; i < cnt ; i++) 1090 output_asm_insn(\"asrb %0\", operands); 1091 1092 return \"\"; 1093}" 1094 [(set_attr_alternative "length" 1095 [(const_int 14) 1096 (const_int 28)])]) 1097 1098;; the following is invalid - too complex!!! - just say 14 !!! 1099; [(set (attr "length") (plus (and (match_dup 2) 1100; (const_int 14)) 1101; (and (match_dup 2) 1102; (const_int 14))))]) 1103 1104 1105 1106;; can we get +-1 in the next pattern? should 1107;; have been caught by previous patterns! 1108 1109(define_insn "ashlhi3" 1110 [(set (match_operand:HI 0 "register_operand" "=r,r") 1111 (ashift:HI (match_operand:HI 1 "register_operand" "0,0") 1112 (match_operand:HI 2 "general_operand" "rR,Qi")))] 1113 "TARGET_40_PLUS" 1114 "* 1115{ 1116 if (GET_CODE(operands[2]) == CONST_INT) 1117 { 1118 if (INTVAL(operands[2]) == 1) 1119 return \"asl %0\"; 1120 else if (INTVAL(operands[2]) == -1) 1121 return \"asr %0\"; 1122 } 1123 1124 return \"ash %2,%0\"; 1125}" 1126 [(set_attr "length" "2,4")]) 1127 1128;; Arithmetic right shift on the pdp works by negating the shift count. 1129(define_expand "ashrhi3" 1130 [(set (match_operand:HI 0 "register_operand" "=r") 1131 (ashift:HI (match_operand:HI 1 "register_operand" "0") 1132 (match_operand:HI 2 "general_operand" "g")))] 1133 "" 1134 " 1135{ 1136 operands[2] = negate_rtx (HImode, operands[2]); 1137}") 1138 1139(define_expand "lshrhi3" 1140 [(match_operand:HI 0 "register_operand" "") 1141 (match_operand:HI 1 "register_operand" "") 1142 (match_operand:HI 2 "general_operand" "")] 1143 "" 1144 " 1145{ 1146 rtx r; 1147 1148 if (!TARGET_40_PLUS && 1149 (GET_CODE (operands[2]) != CONST_INT || 1150 (unsigned) INTVAL (operands[2]) > 3)) 1151 FAIL; 1152 emit_insn (gen_lsrhi1 (operands[0], operands[1])); 1153 if (GET_CODE (operands[2]) != CONST_INT) 1154 { 1155 r = gen_reg_rtx (HImode); 1156 emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1))); 1157 emit_insn (gen_ashrhi3 (operands[0], operands[0], r)); 1158 } 1159 else if ((unsigned) INTVAL (operands[2]) != 1) 1160 { 1161 emit_insn (gen_ashlhi3 (operands[0], operands[0], 1162 GEN_INT (1 - INTVAL (operands[2])))); 1163 } 1164 DONE; 1165} 1166" 1167) 1168 1169;; absolute 1170 1171(define_insn "absdf2" 1172 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q") 1173 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))] 1174 "TARGET_FPU" 1175 "{absd|absf} %0" 1176 [(set_attr "length" "2,4")]) 1177 1178 1179;; negate insns 1180 1181(define_insn "negdf2" 1182 [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,Q") 1183 (neg:DF (match_operand:DF 1 "register_operand" "0,0")))] 1184 "TARGET_FPU" 1185 "{negd|negf} %0" 1186 [(set_attr "length" "2,4")]) 1187 1188(define_insn "negdi2" 1189 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o") 1190 (neg:DI (match_operand:DI 1 "general_operand" "0,0")))] 1191 "" 1192{ 1193 rtx exops[4][2]; 1194 1195 pdp11_expand_operands (operands, exops, 1, NULL, either); 1196 1197 output_asm_insn (\"com %0\", exops[3]); 1198 output_asm_insn (\"com %0\", exops[2]); 1199 output_asm_insn (\"com %0\", exops[1]); 1200 output_asm_insn (\"com %0\", exops[0]); 1201 output_asm_insn (\"add $1, %0\", exops[3]); 1202 output_asm_insn (\"adc %0\", exops[2]); 1203 output_asm_insn (\"adc %0\", exops[1]); 1204 output_asm_insn (\"adc %0\", exops[0]); 1205 1206 return \"\"; 1207} 1208[(set_attr "length" "18,34")]) 1209 1210(define_insn "negsi2" 1211 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o") 1212 (neg:SI (match_operand:SI 1 "general_operand" "0,0")))] 1213 "" 1214{ 1215 rtx exops[2][2]; 1216 1217 pdp11_expand_operands (operands, exops, 1, NULL, either); 1218 1219 output_asm_insn (\"com %0\", exops[1]); 1220 output_asm_insn (\"com %0\", exops[0]); 1221 output_asm_insn (\"add $1, %0\", exops[1]); 1222 output_asm_insn (\"adc %0\", exops[0]); 1223 1224 return \"\"; 1225} 1226[(set_attr "length" "12,20")]) 1227 1228(define_insn "neg<mode>2" 1229 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q") 1230 (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))] 1231 "" 1232 "neg<isfx> %0" 1233 [(set_attr "length" "2,4")]) 1234 1235 1236;; Unconditional and other jump instructions 1237(define_insn "jump" 1238 [(set (pc) 1239 (label_ref (match_operand 0 "" "")))] 1240 "" 1241 "* 1242{ 1243 if (get_attr_length (insn) == 2) 1244 return \"br %l0\"; 1245 return \"jmp %l0\"; 1246}" 1247 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0) 1248 (pc)) 1249 (const_int MIN_BRANCH)) 1250 (gt (minus (match_dup 0) 1251 (pc)) 1252 (const_int MAX_BRANCH))) 1253 (const_int 4) 1254 (const_int 2)))]) 1255 1256(define_insn "" 1257 [(set (pc) 1258 (label_ref (match_operand 0 "" ""))) 1259 (clobber (const_int 1))] 1260 "" 1261 "jmp %l0" 1262 [(set_attr "length" "4")]) 1263 1264(define_insn "tablejump" 1265 [(set (pc) (match_operand:HI 0 "general_operand" "r,R,Q")) 1266 (use (label_ref (match_operand 1 "" "")))] 1267 "" 1268 "@ 1269 jmp (%0) 1270 jmp %@%0 1271 jmp %@%0" 1272 [(set_attr "length" "2,2,4")]) 1273 1274;; indirect jump - let's be conservative! 1275;; allow only register_operand, even though we could also 1276;; allow labels etc. 1277 1278(define_insn "indirect_jump" 1279 [(set (pc) (match_operand:HI 0 "register_operand" "r"))] 1280 "" 1281 "jmp (%0)") 1282 1283;;- jump to subroutine 1284 1285(define_insn "call" 1286 [(call (match_operand:HI 0 "general_operand" "rR,Q") 1287 (match_operand:HI 1 "general_operand" "g,g")) 1288;; (use (reg:HI 0)) what was that ??? 1289 ] 1290 ;;- Don't use operand 1 for most machines. 1291 "" 1292 "jsr pc, %0" 1293 [(set_attr "length" "2,4")]) 1294 1295;;- jump to subroutine 1296(define_insn "call_value" 1297 [(set (match_operand 0 "" "") 1298 (call (match_operand:HI 1 "general_operand" "rR,Q") 1299 (match_operand:HI 2 "general_operand" "g,g"))) 1300;; (use (reg:HI 0)) - what was that ???? 1301 ] 1302 ;;- Don't use operand 2 for most machines. 1303 "" 1304 "jsr pc, %1" 1305 [(set_attr "length" "2,4")]) 1306 1307;;- nop instruction 1308(define_insn "nop" 1309 [(const_int 0)] 1310 "" 1311 "nop") 1312 1313 1314;;- multiply 1315 1316(define_insn "muldf3" 1317 [(set (match_operand:DF 0 "register_operand" "=a,a") 1318 (mult:DF (match_operand:DF 1 "register_operand" "%0,0") 1319 (match_operand:DF 2 "float_operand" "fR,QF")))] 1320 "TARGET_FPU" 1321 "{muld|mulf} %2, %0" 1322 [(set_attr "length" "2,4")]) 1323 1324;; 16 bit result multiply: 1325;; currently we multiply only into odd registers, so we don't use two 1326;; registers - but this is a bit inefficient at times. If we define 1327;; a register class for each register, then we can specify properly 1328;; which register need which scratch register .... 1329 1330(define_insn "mulhi3" 1331 [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs 1332 (mult:HI (match_operand:HI 1 "register_operand" "%0,0") 1333 (match_operand:HI 2 "float_operand" "rR,Qi")))] 1334 "TARGET_40_PLUS" 1335 "mul %2, %0" 1336 [(set_attr "length" "2,4")]) 1337 1338;; 32 bit result 1339(define_expand "mulhisi3" 1340 [(set (match_dup 3) 1341 (match_operand:HI 1 "nonimmediate_operand" "g,g")) 1342 (set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered! 1343 (mult:SI (truncate:HI 1344 (match_dup 0)) 1345 (match_operand:HI 2 "general_operand" "rR,Qi")))] 1346 "TARGET_40_PLUS" 1347 "operands[3] = gen_lowpart(HImode, operands[1]);") 1348 1349(define_insn "" 1350 [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered! 1351 (mult:SI (truncate:HI 1352 (match_operand:SI 1 "register_operand" "%0,0")) 1353 (match_operand:HI 2 "general_operand" "rR,Qi")))] 1354 "TARGET_40_PLUS" 1355 "mul %2, %0" 1356 [(set_attr "length" "2,4")]) 1357 1358;(define_insn "mulhisi3" 1359; [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered! 1360; (mult:SI (truncate:HI 1361; (match_operand:SI 1 "register_operand" "%0,0")) 1362; (match_operand:HI 2 "general_operand" "rR,Qi")))] 1363; "TARGET_40_PLUS" 1364; "mul %2, %0" 1365; [(set_attr "length" "2,4")]) 1366 1367;;- divide 1368(define_insn "divdf3" 1369 [(set (match_operand:DF 0 "register_operand" "=a,a") 1370 (div:DF (match_operand:DF 1 "register_operand" "0,0") 1371 (match_operand:DF 2 "general_operand" "fR,QF")))] 1372 "TARGET_FPU" 1373 "{divd|divf} %2, %0" 1374 [(set_attr "length" "2,4")]) 1375 1376 1377(define_expand "divhi3" 1378 [(set (subreg:HI (match_dup 1) 0) 1379 (div:HI (match_operand:SI 1 "register_operand" "0") 1380 (match_operand:HI 2 "general_operand" "g"))) 1381 (set (match_operand:HI 0 "register_operand" "=r") 1382 (subreg:HI (match_dup 1) 0))] 1383 "TARGET_40_PLUS" 1384 "") 1385 1386(define_insn "" 1387 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0) 1388 (div:HI (match_operand:SI 1 "general_operand" "0") 1389 (match_operand:HI 2 "general_operand" "g")))] 1390 "TARGET_40_PLUS" 1391 "div %2,%0" 1392 [(set_attr "length" "4")]) 1393 1394(define_expand "modhi3" 1395 [(set (subreg:HI (match_dup 1) 2) 1396 (mod:HI (match_operand:SI 1 "register_operand" "0") 1397 (match_operand:HI 2 "general_operand" "g"))) 1398 (set (match_operand:HI 0 "register_operand" "=r") 1399 (subreg:HI (match_dup 1) 2))] 1400 "TARGET_40_PLUS" 1401 "") 1402 1403(define_insn "" 1404 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 2) 1405 (mod:HI (match_operand:SI 1 "general_operand" "0") 1406 (match_operand:HI 2 "general_operand" "g")))] 1407 "TARGET_40_PLUS" 1408 "div %2,%0" 1409 [(set_attr "length" "4")]) 1410 1411;(define_expand "divmodhi4" 1412; [(parallel [(set (subreg:HI (match_dup 1) 0) 1413; (div:HI (match_operand:SI 1 "register_operand" "0") 1414; (match_operand:HI 2 "general_operand" "g"))) 1415; (set (subreg:HI (match_dup 1) 2) 1416; (mod:HI (match_dup 1) 1417; (match_dup 2)))]) 1418; (set (match_operand:HI 3 "register_operand" "=r") 1419; (subreg:HI (match_dup 1) 2)) 1420; (set (match_operand:HI 0 "register_operand" "=r") 1421; (subreg:HI (match_dup 1) 0))] 1422; "TARGET_40_PLUS" 1423; "") 1424; 1425;(define_insn "" 1426; [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0) 1427; (div:HI (match_operand:SI 1 "general_operand" "0") 1428; (match_operand:HI 2 "general_operand" "g"))) 1429; (set (subreg:HI (match_dup 0) 2) 1430; (mod:HI (match_dup 1) 1431; (match_dup 2)))] 1432; "TARGET_40_PLUS" 1433; "div %2, %0") 1434; 1435 1436;; is rotate doing the right thing to be included here ???? 1437