1;; GCC machine description for Intel 80386. 2;; Copyright (C) 1988 Free Software Foundation, Inc. 3;; Mostly by William Schelter. 4 5;; This file is part of GNU CC. 6 7;; GNU CC 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 2, or (at your option) 10;; any later version. 11 12;; GNU CC 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 GNU CC; see the file COPYING. If not, write to 19;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 20 21 22;; The original PO technology requires these to be ordered by speed, 23;; so that assigner will pick the fastest. 24 25;; See file "rtl.def" for documentation on define_insn, match_*, et. al. 26 27;; Macro #define NOTICE_UPDATE_CC in file i386.h handles condition code 28;; updates for most instructions. 29 30;; Macro REG_CLASS_FROM_LETTER in file i386.h defines the register 31;; constraint letters. 32 33;; the special asm out single letter directives following a '%' are: 34;; 'z' mov%z1 would be movl, movw, or movb depending on the mode of 35;; operands[1]. 36;; 'L' Print the opcode suffix for a 32-bit integer opcode. 37;; 'W' Print the opcode suffix for a 16-bit integer opcode. 38;; 'B' Print the opcode suffix for an 8-bit integer opcode. 39;; 'S' Print the opcode suffix for a 32-bit float opcode. 40;; 'Q' Print the opcode suffix for a 64-bit float opcode. 41 42;; 'b' Print the QImode name of the register for the indicated operand. 43;; %b0 would print %al if operands[0] is reg 0. 44;; 'w' Likewise, print the HImode name of the register. 45;; 'k' Likewise, print the SImode name of the register. 46;; 'h' Print the QImode name for a "high" register, either ah, bh, ch or dh. 47;; 'y' Print "st(0)" instead of "st" as a register. 48 49;; UNSPEC usage: 50;; 0 This is a `scas' operation. The mode of the UNSPEC is always SImode. 51;; operand 0 is the memory address to scan. 52;; operand 1 is a register containing the value to scan for. The mode 53;; of the scas opcode will be the same as the mode of this operand. 54;; operand 2 is the known alignment of operand 0. 55;; 1 This is a `sin' operation. The mode of the UNSPEC is MODE_FLOAT. 56;; operand 0 is the argument for `sin'. 57;; 2 This is a `cos' operation. The mode of the UNSPEC is MODE_FLOAT. 58;; operand 0 is the argument for `cos'. 59 60;; "movl MEM,REG / testl REG,REG" is faster on a 486 than "cmpl $0,MEM". 61;; But restricting MEM here would mean that gcc could not remove a redundant 62;; test in cases like "incl MEM / je TARGET". 63;; 64;; We don't want to allow a constant operand for test insns because 65;; (set (cc0) (const_int foo)) has no mode information. Such insns will 66;; be folded while optimizing anyway. 67 68;; All test insns have expanders that save the operands away without 69;; actually generating RTL. The bCOND or sCOND (emitted immediately 70;; after the tstM or cmp) will actually emit the tstM or cmpM. 71 72(define_insn "tstsi_1" 73 [(set (cc0) 74 (match_operand:SI 0 "nonimmediate_operand" "rm"))] 75 "" 76 "* 77{ 78 if (REG_P (operands[0])) 79 return AS2 (test%L0,%0,%0); 80 81 operands[1] = const0_rtx; 82 return AS2 (cmp%L0,%1,%0); 83}") 84 85(define_expand "tstsi" 86 [(set (cc0) 87 (match_operand:SI 0 "nonimmediate_operand" ""))] 88 "" 89 " 90{ 91 i386_compare_gen = gen_tstsi_1; 92 i386_compare_op0 = operands[0]; 93 DONE; 94}") 95 96(define_insn "tsthi_1" 97 [(set (cc0) 98 (match_operand:HI 0 "nonimmediate_operand" "rm"))] 99 "" 100 "* 101{ 102 if (REG_P (operands[0])) 103 return AS2 (test%W0,%0,%0); 104 105 operands[1] = const0_rtx; 106 return AS2 (cmp%W0,%1,%0); 107}") 108 109(define_expand "tsthi" 110 [(set (cc0) 111 (match_operand:HI 0 "nonimmediate_operand" ""))] 112 "" 113 " 114{ 115 i386_compare_gen = gen_tsthi_1; 116 i386_compare_op0 = operands[0]; 117 DONE; 118}") 119 120(define_insn "tstqi_1" 121 [(set (cc0) 122 (match_operand:QI 0 "nonimmediate_operand" "qm"))] 123 "" 124 "* 125{ 126 if (REG_P (operands[0])) 127 return AS2 (test%B0,%0,%0); 128 129 operands[1] = const0_rtx; 130 return AS2 (cmp%B0,%1,%0); 131}") 132 133(define_expand "tstqi" 134 [(set (cc0) 135 (match_operand:QI 0 "nonimmediate_operand" ""))] 136 "" 137 " 138{ 139 i386_compare_gen = gen_tstqi_1; 140 i386_compare_op0 = operands[0]; 141 DONE; 142}") 143 144(define_insn "tstsf_cc" 145 [(set (cc0) 146 (match_operand:SF 0 "register_operand" "f")) 147 (clobber (match_scratch:HI 1 "=a"))] 148 "TARGET_80387 && ! TARGET_IEEE_FP" 149 "* 150{ 151 if (! STACK_TOP_P (operands[0])) 152 abort (); 153 154 output_asm_insn (\"ftst\", operands); 155 156 if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) 157 output_asm_insn (AS1 (fstp,%y0), operands); 158 159 return (char *) output_fp_cc0_set (insn); 160}") 161 162;; Don't generate tstsf if generating IEEE code, since the `ftst' opcode 163;; isn't IEEE compliant. 164 165(define_expand "tstsf" 166 [(parallel [(set (cc0) 167 (match_operand:SF 0 "register_operand" "")) 168 (clobber (match_scratch:HI 1 ""))])] 169 "TARGET_80387 && ! TARGET_IEEE_FP" 170 " 171{ 172 i386_compare_gen = gen_tstsf_cc; 173 i386_compare_op0 = operands[0]; 174 DONE; 175}") 176 177(define_insn "tstdf_cc" 178 [(set (cc0) 179 (match_operand:DF 0 "register_operand" "f")) 180 (clobber (match_scratch:HI 1 "=a"))] 181 "TARGET_80387 && ! TARGET_IEEE_FP" 182 "* 183{ 184 if (! STACK_TOP_P (operands[0])) 185 abort (); 186 187 output_asm_insn (\"ftst\", operands); 188 189 if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) 190 output_asm_insn (AS1 (fstp,%y0), operands); 191 192 return (char *) output_fp_cc0_set (insn); 193}") 194 195;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode 196;; isn't IEEE compliant. 197 198(define_expand "tstdf" 199 [(parallel [(set (cc0) 200 (match_operand:DF 0 "register_operand" "")) 201 (clobber (match_scratch:HI 1 ""))])] 202 "TARGET_80387 && ! TARGET_IEEE_FP" 203 " 204{ 205 i386_compare_gen = gen_tstdf_cc; 206 i386_compare_op0 = operands[0]; 207 DONE; 208}") 209 210;;- compare instructions. See comments above tstM patterns about 211;; expansion of these insns. 212 213(define_insn "cmpsi_1" 214 [(set (cc0) 215 (compare (match_operand:SI 0 "nonimmediate_operand" "mr,r") 216 (match_operand:SI 1 "general_operand" "ri,mr")))] 217 "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" 218 "* 219{ 220 if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM) 221 { 222 cc_status.flags |= CC_REVERSED; 223 return AS2 (cmp%L0,%0,%1); 224 } 225 return AS2 (cmp%L0,%1,%0); 226}") 227 228(define_expand "cmpsi" 229 [(set (cc0) 230 (compare (match_operand:SI 0 "nonimmediate_operand" "") 231 (match_operand:SI 1 "general_operand" "")))] 232 "" 233 " 234{ 235 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) 236 operands[0] = force_reg (SImode, operands[0]); 237 238 i386_compare_gen = gen_cmpsi_1; 239 i386_compare_op0 = operands[0]; 240 i386_compare_op1 = operands[1]; 241 DONE; 242}") 243 244(define_insn "cmphi_1" 245 [(set (cc0) 246 (compare (match_operand:HI 0 "nonimmediate_operand" "mr,r") 247 (match_operand:HI 1 "general_operand" "ri,mr")))] 248 "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" 249 "* 250{ 251 if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM) 252 { 253 cc_status.flags |= CC_REVERSED; 254 return AS2 (cmp%W0,%0,%1); 255 } 256 return AS2 (cmp%W0,%1,%0); 257}") 258 259(define_expand "cmphi" 260 [(set (cc0) 261 (compare (match_operand:HI 0 "nonimmediate_operand" "") 262 (match_operand:HI 1 "general_operand" "")))] 263 "" 264 " 265{ 266 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) 267 operands[0] = force_reg (HImode, operands[0]); 268 269 i386_compare_gen = gen_cmphi_1; 270 i386_compare_op0 = operands[0]; 271 i386_compare_op1 = operands[1]; 272 DONE; 273}") 274 275(define_insn "cmpqi_1" 276 [(set (cc0) 277 (compare (match_operand:QI 0 "nonimmediate_operand" "q,mq") 278 (match_operand:QI 1 "general_operand" "qm,nq")))] 279 "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" 280 "* 281{ 282 if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM) 283 { 284 cc_status.flags |= CC_REVERSED; 285 return AS2 (cmp%B0,%0,%1); 286 } 287 return AS2 (cmp%B0,%1,%0); 288}") 289 290(define_expand "cmpqi" 291 [(set (cc0) 292 (compare (match_operand:QI 0 "nonimmediate_operand" "") 293 (match_operand:QI 1 "general_operand" "")))] 294 "" 295 " 296{ 297 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) 298 operands[0] = force_reg (QImode, operands[0]); 299 300 i386_compare_gen = gen_cmpqi_1; 301 i386_compare_op0 = operands[0]; 302 i386_compare_op1 = operands[1]; 303 DONE; 304}") 305 306;; These implement float point compares. For each of DFmode and 307;; SFmode, there is the normal insn, and an insn where the second operand 308;; is converted to the desired mode. 309 310(define_insn "" 311 [(set (cc0) 312 (match_operator 2 "VOIDmode_compare_op" 313 [(match_operand:DF 0 "nonimmediate_operand" "f,fm") 314 (match_operand:DF 1 "nonimmediate_operand" "fm,f")])) 315 (clobber (match_scratch:HI 3 "=a,a"))] 316 "TARGET_80387 317 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" 318 "* return (char *) output_float_compare (insn, operands);") 319 320(define_insn "" 321 [(set (cc0) 322 (match_operator 2 "VOIDmode_compare_op" 323 [(match_operand:DF 0 "register_operand" "f") 324 (float:DF 325 (match_operand:SI 1 "nonimmediate_operand" "rm"))])) 326 (clobber (match_scratch:HI 3 "=a"))] 327 "TARGET_80387" 328 "* return (char *) output_float_compare (insn, operands);") 329 330(define_insn "" 331 [(set (cc0) 332 (match_operator 2 "VOIDmode_compare_op" 333 [(float:DF 334 (match_operand:SI 0 "nonimmediate_operand" "rm")) 335 (match_operand:DF 1 "register_operand" "f")])) 336 (clobber (match_scratch:HI 3 "=a"))] 337 "TARGET_80387" 338 "* return (char *) output_float_compare (insn, operands);") 339 340(define_insn "" 341 [(set (cc0) 342 (match_operator 2 "VOIDmode_compare_op" 343 [(match_operand:DF 0 "register_operand" "f") 344 (float_extend:DF 345 (match_operand:SF 1 "nonimmediate_operand" "fm"))])) 346 (clobber (match_scratch:HI 3 "=a"))] 347 "TARGET_80387" 348 "* return (char *) output_float_compare (insn, operands);") 349 350(define_insn "" 351 [(set (cc0) 352 (match_operator 2 "VOIDmode_compare_op" 353 [(float_extend:DF 354 (match_operand:SF 0 "nonimmediate_operand" "fm")) 355 (match_operand:DF 1 "register_operand" "f")])) 356 (clobber (match_scratch:HI 3 "=a"))] 357 "TARGET_80387" 358 "* return (char *) output_float_compare (insn, operands);") 359 360(define_insn "" 361 [(set (cc0) 362 (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f") 363 (match_operand:DF 1 "register_operand" "f"))) 364 (clobber (match_scratch:HI 2 "=a"))] 365 "TARGET_80387" 366 "* return (char *) output_float_compare (insn, operands);") 367 368;; These two insns will never be generated by combine due to the mode of 369;; the COMPARE. 370;(define_insn "" 371; [(set (cc0) 372; (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f") 373; (float_extend:DF 374; (match_operand:SF 1 "register_operand" "f")))) 375; (clobber (match_scratch:HI 2 "=a"))] 376; "TARGET_80387" 377; "* return (char *) output_float_compare (insn, operands);") 378; 379;(define_insn "" 380; [(set (cc0) 381; (compare:CCFPEQ (float_extend:DF 382; (match_operand:SF 0 "register_operand" "f")) 383; (match_operand:DF 1 "register_operand" "f"))) 384; (clobber (match_scratch:HI 2 "=a"))] 385; "TARGET_80387" 386; "* return (char *) output_float_compare (insn, operands);") 387 388(define_insn "cmpsf_cc_1" 389 [(set (cc0) 390 (match_operator 2 "VOIDmode_compare_op" 391 [(match_operand:SF 0 "nonimmediate_operand" "f,fm") 392 (match_operand:SF 1 "nonimmediate_operand" "fm,f")])) 393 (clobber (match_scratch:HI 3 "=a,a"))] 394 "TARGET_80387 395 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" 396 "* return (char *) output_float_compare (insn, operands);") 397 398(define_insn "" 399 [(set (cc0) 400 (match_operator 2 "VOIDmode_compare_op" 401 [(match_operand:SF 0 "register_operand" "f") 402 (float:SF 403 (match_operand:SI 1 "nonimmediate_operand" "rm"))])) 404 (clobber (match_scratch:HI 3 "=a"))] 405 "TARGET_80387" 406 "* return (char *) output_float_compare (insn, operands);") 407 408(define_insn "" 409 [(set (cc0) 410 (match_operator 2 "VOIDmode_compare_op" 411 [(float:SF 412 (match_operand:SI 0 "nonimmediate_operand" "rm")) 413 (match_operand:SF 1 "register_operand" "f")])) 414 (clobber (match_scratch:HI 3 "=a"))] 415 "TARGET_80387" 416 "* return (char *) output_float_compare (insn, operands);") 417 418(define_insn "" 419 [(set (cc0) 420 (compare:CCFPEQ (match_operand:SF 0 "register_operand" "f") 421 (match_operand:SF 1 "register_operand" "f"))) 422 (clobber (match_scratch:HI 2 "=a"))] 423 "TARGET_80387" 424 "* return (char *) output_float_compare (insn, operands);") 425 426(define_expand "cmpdf" 427 [(set (cc0) 428 (compare (match_operand:DF 0 "register_operand" "") 429 (match_operand:DF 1 "nonimmediate_operand" "")))] 430 "TARGET_80387" 431 " 432{ 433 i386_compare_gen = gen_cmpdf_cc; 434 i386_compare_gen_eq = gen_cmpdf_ccfpeq; 435 i386_compare_op0 = operands[0]; 436 i386_compare_op1 = operands[1]; 437 DONE; 438}") 439 440(define_expand "cmpsf" 441 [(set (cc0) 442 (compare (match_operand:SF 0 "register_operand" "") 443 (match_operand:SF 1 "nonimmediate_operand" "")))] 444 "TARGET_80387" 445 " 446{ 447 i386_compare_gen = gen_cmpsf_cc; 448 i386_compare_gen_eq = gen_cmpsf_ccfpeq; 449 i386_compare_op0 = operands[0]; 450 i386_compare_op1 = operands[1]; 451 DONE; 452}") 453 454(define_expand "cmpdf_cc" 455 [(parallel [(set (cc0) 456 (compare (match_operand:DF 0 "register_operand" "") 457 (match_operand:DF 1 "register_operand" ""))) 458 (clobber (match_scratch:HI 2 ""))])] 459 "TARGET_80387" 460 "") 461 462(define_expand "cmpdf_ccfpeq" 463 [(parallel [(set (cc0) 464 (compare:CCFPEQ (match_operand:DF 0 "register_operand" "") 465 (match_operand:DF 1 "register_operand" ""))) 466 (clobber (match_scratch:HI 2 ""))])] 467 "TARGET_80387" 468 " 469{ 470 if (! register_operand (operands[1], DFmode)) 471 operands[1] = copy_to_mode_reg (DFmode, operands[1]); 472}") 473 474(define_expand "cmpsf_cc" 475 [(parallel [(set (cc0) 476 (compare (match_operand:SF 0 "register_operand" "") 477 (match_operand:SF 1 "register_operand" ""))) 478 (clobber (match_scratch:HI 2 ""))])] 479 "TARGET_80387" 480 "") 481 482(define_expand "cmpsf_ccfpeq" 483 [(parallel [(set (cc0) 484 (compare:CCFPEQ (match_operand:SF 0 "register_operand" "") 485 (match_operand:SF 1 "register_operand" ""))) 486 (clobber (match_scratch:HI 2 ""))])] 487 "TARGET_80387" 488 " 489{ 490 if (! register_operand (operands[1], SFmode)) 491 operands[1] = copy_to_mode_reg (SFmode, operands[1]); 492}") 493 494;; logical compare 495 496(define_insn "" 497 [(set (cc0) 498 (and:SI (match_operand:SI 0 "general_operand" "%ro") 499 (match_operand:SI 1 "general_operand" "ri")))] 500 "" 501 "* 502{ 503 /* For small integers, we may actually use testb. */ 504 if (GET_CODE (operands[1]) == CONST_INT 505 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) 506 && (! REG_P (operands[0]) || QI_REG_P (operands[0]))) 507 { 508 /* We may set the sign bit spuriously. */ 509 510 if ((INTVAL (operands[1]) & ~0xff) == 0) 511 { 512 cc_status.flags |= CC_NOT_NEGATIVE; 513 return AS2 (test%B0,%1,%b0); 514 } 515 516 if ((INTVAL (operands[1]) & ~0xff00) == 0) 517 { 518 cc_status.flags |= CC_NOT_NEGATIVE; 519 operands[1] = GEN_INT (INTVAL (operands[1]) >> 8); 520 521 if (QI_REG_P (operands[0])) 522 return AS2 (test%B0,%1,%h0); 523 else 524 { 525 operands[0] = adj_offsettable_operand (operands[0], 1); 526 return AS2 (test%B0,%1,%b0); 527 } 528 } 529 530 if (GET_CODE (operands[0]) == MEM 531 && (INTVAL (operands[1]) & ~0xff0000) == 0) 532 { 533 cc_status.flags |= CC_NOT_NEGATIVE; 534 operands[1] = GEN_INT (INTVAL (operands[1]) >> 16); 535 operands[0] = adj_offsettable_operand (operands[0], 2); 536 return AS2 (test%B0,%1,%b0); 537 } 538 539 if (GET_CODE (operands[0]) == MEM 540 && (INTVAL (operands[1]) & ~0xff000000) == 0) 541 { 542 operands[1] = GEN_INT ((INTVAL (operands[1]) >> 24) & 0xff); 543 operands[0] = adj_offsettable_operand (operands[0], 3); 544 return AS2 (test%B0,%1,%b0); 545 } 546 } 547 548 if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) 549 return AS2 (test%L0,%1,%0); 550 551 return AS2 (test%L1,%0,%1); 552}") 553 554(define_insn "" 555 [(set (cc0) 556 (and:HI (match_operand:HI 0 "general_operand" "%ro") 557 (match_operand:HI 1 "general_operand" "ri")))] 558 "" 559 "* 560{ 561 if (GET_CODE (operands[1]) == CONST_INT 562 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) 563 && (! REG_P (operands[0]) || QI_REG_P (operands[0]))) 564 { 565 if ((INTVAL (operands[1]) & 0xff00) == 0) 566 { 567 /* ??? This might not be necessary. */ 568 if (INTVAL (operands[1]) & 0xffff0000) 569 operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff); 570 571 /* We may set the sign bit spuriously. */ 572 cc_status.flags |= CC_NOT_NEGATIVE; 573 return AS2 (test%B0,%1,%b0); 574 } 575 576 if ((INTVAL (operands[1]) & 0xff) == 0) 577 { 578 operands[1] = GEN_INT ((INTVAL (operands[1]) >> 8) & 0xff); 579 580 if (QI_REG_P (operands[0])) 581 return AS2 (test%B0,%1,%h0); 582 else 583 { 584 operands[0] = adj_offsettable_operand (operands[0], 1); 585 return AS2 (test%B0,%1,%b0); 586 } 587 } 588 } 589 590 if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) 591 return AS2 (test%W0,%1,%0); 592 593 return AS2 (test%W1,%0,%1); 594}") 595 596(define_insn "" 597 [(set (cc0) 598 (and:QI (match_operand:QI 0 "general_operand" "%qm") 599 (match_operand:QI 1 "general_operand" "qi")))] 600 "" 601 "* 602{ 603 if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) 604 return AS2 (test%B0,%1,%0); 605 606 return AS2 (test%B1,%0,%1); 607}") 608 609;; move instructions. 610;; There is one for each machine mode, 611;; and each is preceded by a corresponding push-insn pattern 612;; (since pushes are not general_operands on the 386). 613 614(define_insn "" 615 [(set (match_operand:SI 0 "push_operand" "=<") 616 (match_operand:SI 1 "general_operand" "g"))] 617 "! TARGET_486" 618 "push%L0 %1") 619 620;; On a 486, it is faster to move MEM to a REG and then push, rather than 621;; push MEM directly. 622 623(define_insn "" 624 [(set (match_operand:SI 0 "push_operand" "=<") 625 (match_operand:SI 1 "general_operand" "ri"))] 626 "TARGET_486" 627 "push%L0 %1") 628 629;; General case of fullword move. 630 631;; If generating PIC code and operands[1] is a symbolic CONST, emit a 632;; move to get the address of the symbolic object from the GOT. 633 634(define_expand "movsi" 635 [(set (match_operand:SI 0 "general_operand" "") 636 (match_operand:SI 1 "general_operand" ""))] 637 "" 638 " 639{ 640 extern int flag_pic; 641 642 if (flag_pic && SYMBOLIC_CONST (operands[1])) 643 emit_pic_move (operands, SImode); 644}") 645 646;; On i486, incl reg is faster than movl $1,reg. 647 648(define_insn "" 649 [(set (match_operand:SI 0 "general_operand" "=g,r") 650 (match_operand:SI 1 "general_operand" "ri,m"))] 651 "" 652 "* 653{ 654 rtx link; 655 if (operands[1] == const0_rtx && REG_P (operands[0])) 656 return AS2 (xor%L0,%0,%0); 657 658 if (operands[1] == const1_rtx 659 && (link = find_reg_note (insn, REG_WAS_0, 0)) 660 /* Make sure the insn that stored the 0 is still present. */ 661 && ! INSN_DELETED_P (XEXP (link, 0)) 662 && GET_CODE (XEXP (link, 0)) != NOTE 663 /* Make sure cross jumping didn't happen here. */ 664 && no_labels_between_p (XEXP (link, 0), insn) 665 /* Make sure the reg hasn't been clobbered. */ 666 && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) 667 /* Fastest way to change a 0 to a 1. */ 668 return AS1 (inc%L0,%0); 669 670 return AS2 (mov%L0,%1,%0); 671}") 672 673(define_insn "" 674 [(set (match_operand:HI 0 "push_operand" "=<") 675 (match_operand:HI 1 "general_operand" "g"))] 676 "" 677 "push%W0 %1") 678 679;; On i486, an incl and movl are both faster than incw and movw. 680 681(define_insn "movhi" 682 [(set (match_operand:HI 0 "general_operand" "=g,r") 683 (match_operand:HI 1 "general_operand" "ri,m"))] 684 "" 685 "* 686{ 687 rtx link; 688 if (REG_P (operands[0]) && operands[1] == const0_rtx) 689 return AS2 (xor%L0,%k0,%k0); 690 691 if (REG_P (operands[0]) && operands[1] == const1_rtx 692 && (link = find_reg_note (insn, REG_WAS_0, 0)) 693 /* Make sure the insn that stored the 0 is still present. */ 694 && ! INSN_DELETED_P (XEXP (link, 0)) 695 && GET_CODE (XEXP (link, 0)) != NOTE 696 /* Make sure cross jumping didn't happen here. */ 697 && no_labels_between_p (XEXP (link, 0), insn) 698 /* Make sure the reg hasn't been clobbered. */ 699 && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) 700 /* Fastest way to change a 0 to a 1. */ 701 return AS1 (inc%L0,%k0); 702 703 if (REG_P (operands[0])) 704 { 705 if (REG_P (operands[1])) 706 return AS2 (mov%L0,%k1,%k0); 707 else if (CONSTANT_P (operands[1])) 708 return AS2 (mov%L0,%1,%k0); 709 } 710 711 return AS2 (mov%W0,%1,%0); 712}") 713 714(define_insn "movstricthi" 715 [(set (strict_low_part (match_operand:HI 0 "general_operand" "+g,r")) 716 (match_operand:HI 1 "general_operand" "ri,m"))] 717 "" 718 "* 719{ 720 rtx link; 721 if (operands[1] == const0_rtx && REG_P (operands[0])) 722 return AS2 (xor%W0,%0,%0); 723 724 if (operands[1] == const1_rtx 725 && (link = find_reg_note (insn, REG_WAS_0, 0)) 726 /* Make sure the insn that stored the 0 is still present. */ 727 && ! INSN_DELETED_P (XEXP (link, 0)) 728 && GET_CODE (XEXP (link, 0)) != NOTE 729 /* Make sure cross jumping didn't happen here. */ 730 && no_labels_between_p (XEXP (link, 0), insn) 731 /* Make sure the reg hasn't been clobbered. */ 732 && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) 733 /* Fastest way to change a 0 to a 1. */ 734 return AS1 (inc%W0,%0); 735 736 return AS2 (mov%W0,%1,%0); 737}") 738 739;; emit_push_insn when it calls move_by_pieces 740;; requires an insn to "push a byte". 741;; But actually we use pushw, which has the effect of rounding 742;; the amount pushed up to a halfword. 743(define_insn "" 744 [(set (match_operand:QI 0 "push_operand" "=<") 745 (match_operand:QI 1 "general_operand" "q"))] 746 "" 747 "* 748{ 749 operands[1] = gen_rtx (REG, HImode, REGNO (operands[1])); 750 return AS1 (push%W0,%1); 751}") 752 753;; On i486, incb reg is faster than movb $1,reg. 754 755;; ??? Do a recognizer for zero_extract that looks just like this, but reads 756;; or writes %ah, %bh, %ch, %dh. 757 758(define_insn "movqi" 759 [(set (match_operand:QI 0 "general_operand" "=q,*r,qm") 760 (match_operand:QI 1 "general_operand" "*g,q,qn"))] 761 "" 762 "* 763{ 764 rtx link; 765 if (operands[1] == const0_rtx && REG_P (operands[0])) 766 return AS2 (xor%B0,%0,%0); 767 768 if (operands[1] == const1_rtx 769 && (link = find_reg_note (insn, REG_WAS_0, 0)) 770 /* Make sure the insn that stored the 0 is still present. */ 771 && ! INSN_DELETED_P (XEXP (link, 0)) 772 && GET_CODE (XEXP (link, 0)) != NOTE 773 /* Make sure cross jumping didn't happen here. */ 774 && no_labels_between_p (XEXP (link, 0), insn) 775 /* Make sure the reg hasn't been clobbered. */ 776 && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) 777 /* Fastest way to change a 0 to a 1. */ 778 return AS1 (inc%B0,%0); 779 780 /* If mov%B0 isn't allowed for one of these regs, use mov%L0. */ 781 if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1])) 782 return (AS2 (mov%L0,%k1,%k0)); 783 784 return (AS2 (mov%B0,%1,%0)); 785}") 786 787;; If it becomes necessary to support movstrictqi into %esi or %edi, 788;; use the insn sequence: 789;; 790;; shrdl $8,srcreg,dstreg 791;; rorl $24,dstreg 792;; 793;; If operands[1] is a constant, then an andl/orl sequence would be 794;; faster. 795 796(define_insn "movstrictqi" 797 [(set (strict_low_part (match_operand:QI 0 "general_operand" "+q,qm")) 798 (match_operand:QI 1 "general_operand" "*g,qn"))] 799 "" 800 "* 801{ 802 rtx link; 803 if (operands[1] == const0_rtx && REG_P (operands[0])) 804 return AS2 (xor%B0,%0,%0); 805 806 if (operands[1] == const1_rtx 807 && (link = find_reg_note (insn, REG_WAS_0, 0)) 808 /* Make sure the insn that stored the 0 is still present. */ 809 && ! INSN_DELETED_P (XEXP (link, 0)) 810 && GET_CODE (XEXP (link, 0)) != NOTE 811 /* Make sure cross jumping didn't happen here. */ 812 && no_labels_between_p (XEXP (link, 0), insn) 813 /* Make sure the reg hasn't been clobbered. */ 814 && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) 815 /* Fastest way to change a 0 to a 1. */ 816 return AS1 (inc%B0,%0); 817 818 /* If mov%B0 isn't allowed for one of these regs, use mov%W0. */ 819 if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1])) 820 { 821 abort (); 822 return (AS2 (mov%L0,%k1,%k0)); 823 } 824 825 return AS2 (mov%B0,%1,%0); 826}") 827 828(define_insn "" 829 [(set (match_operand:SF 0 "push_operand" "=<,<") 830 (match_operand:SF 1 "general_operand" "gF,f"))] 831 "" 832 "* 833{ 834 if (STACK_REG_P (operands[1])) 835 { 836 rtx xops[3]; 837 838 if (! STACK_TOP_P (operands[1])) 839 abort (); 840 841 xops[0] = AT_SP (SFmode); 842 xops[1] = GEN_INT (4); 843 xops[2] = stack_pointer_rtx; 844 845 output_asm_insn (AS2 (sub%L2,%1,%2), xops); 846 847 if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) 848 output_asm_insn (AS1 (fstp%S0,%0), xops); 849 else 850 output_asm_insn (AS1 (fst%S0,%0), xops); 851 RET; 852 } 853 return AS1 (push%L1,%1); 854}") 855 856;; Allow MEM-MEM moves before reload. The reload class for such a 857;; move will be ALL_REGS. PREFERRED_RELOAD_CLASS will narrow this to 858;; GENERAL_REGS. For the purposes of regclass, prefer FLOAT_REGS. 859 860(define_insn "movsf" 861 [(set (match_operand:SF 0 "general_operand" "=*rfm,*rf,f,!*rm") 862 (match_operand:SF 1 "general_operand" "*rf,*rfm,fG,fF"))] 863 "" 864 "* 865{ 866 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 867 868 /* First handle a `pop' insn or a `fld %st(0)' */ 869 870 if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1])) 871 { 872 if (stack_top_dies) 873 return AS1 (fstp,%y0); 874 else 875 return AS1 (fld,%y0); 876 } 877 878 /* Handle a transfer between the 387 and a 386 register */ 879 880 if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1])) 881 { 882 output_op_from_reg (operands[1], AS1 (fld%z0,%y1)); 883 RET; 884 } 885 886 if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0])) 887 { 888 output_to_reg (operands[0], stack_top_dies); 889 RET; 890 } 891 892 /* Handle other kinds of writes from the 387 */ 893 894 if (STACK_TOP_P (operands[1])) 895 { 896 if (stack_top_dies) 897 return AS1 (fstp%z0,%y0); 898 else 899 return AS1 (fst%z0,%y0); 900 } 901 902 /* Handle other kinds of reads to the 387 */ 903 904 if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE) 905 return (char *) output_move_const_single (operands); 906 907 if (STACK_TOP_P (operands[0])) 908 return AS1 (fld%z1,%y1); 909 910 /* Handle all SFmode moves not involving the 387 */ 911 912 return (char *) singlemove_string (operands); 913}") 914 915;;should change to handle the memory operands[1] without doing df push.. 916(define_insn "" 917 [(set (match_operand:DF 0 "push_operand" "=<,<") 918 (match_operand:DF 1 "general_operand" "gF,f"))] 919 "" 920 "* 921{ 922 if (STACK_REG_P (operands[1])) 923 { 924 rtx xops[3]; 925 926 xops[0] = AT_SP (SFmode); 927 xops[1] = GEN_INT (8); 928 xops[2] = stack_pointer_rtx; 929 930 output_asm_insn (AS2 (sub%L2,%1,%2), xops); 931 932 if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) 933 output_asm_insn (AS1 (fstp%Q0,%0), xops); 934 else 935 output_asm_insn (AS1 (fst%Q0,%0), xops); 936 937 RET; 938 } 939 else 940 return (char *) output_move_double (operands); 941}") 942 943(define_insn "swapdf" 944 [(set (match_operand:DF 0 "register_operand" "f") 945 (match_operand:DF 1 "register_operand" "f")) 946 (set (match_dup 1) 947 (match_dup 0))] 948 "" 949 "* 950{ 951 if (STACK_TOP_P (operands[0])) 952 return AS1 (fxch,%1); 953 else 954 return AS1 (fxch,%0); 955}") 956 957;; Allow MEM-MEM moves before reload. The reload class for such a 958;; move will be ALL_REGS. PREFERRED_RELOAD_CLASS will narrow this to 959;; GENERAL_REGS. For the purposes of regclass, prefer FLOAT_REGS. 960 961(define_insn "movdf" 962 [(set (match_operand:DF 0 "general_operand" "=*rfm,*rf,f,!*rm") 963 (match_operand:DF 1 "general_operand" "*rf,*rfm,fG,fF"))] 964 "" 965 "* 966{ 967 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 968 969 /* First handle a `pop' insn or a `fld %st(0)' */ 970 971 if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1])) 972 { 973 if (stack_top_dies) 974 return AS1 (fstp,%y0); 975 else 976 return AS1 (fld,%y0); 977 } 978 979 /* Handle a transfer between the 387 and a 386 register */ 980 981 if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1])) 982 { 983 output_op_from_reg (operands[1], AS1 (fld%z0,%y1)); 984 RET; 985 } 986 987 if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0])) 988 { 989 output_to_reg (operands[0], stack_top_dies); 990 RET; 991 } 992 993 /* Handle other kinds of writes from the 387 */ 994 995 if (STACK_TOP_P (operands[1])) 996 { 997 if (stack_top_dies) 998 return AS1 (fstp%z0,%y0); 999 else 1000 return AS1 (fst%z0,%y0); 1001 } 1002 1003 /* Handle other kinds of reads to the 387 */ 1004 1005 if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE) 1006 return (char *) output_move_const_single (operands); 1007 1008 if (STACK_TOP_P (operands[0])) 1009 return AS1 (fld%z1,%y1); 1010 1011 /* Handle all DFmode moves not involving the 387 */ 1012 1013 return (char *) output_move_double (operands); 1014}") 1015 1016(define_insn "" 1017 [(set (match_operand:DI 0 "push_operand" "=<") 1018 (match_operand:DI 1 "general_operand" "roiF"))] 1019 "" 1020 "* 1021{ 1022 return (char *) output_move_double (operands); 1023}") 1024 1025(define_insn "movdi" 1026 [(set (match_operand:DI 0 "general_operand" "=r,rm") 1027 (match_operand:DI 1 "general_operand" "m,riF"))] 1028 "" 1029 "* 1030{ 1031 return (char *) output_move_double (operands); 1032}") 1033 1034;;- conversion instructions 1035;;- NONE 1036 1037;;- zero extension instructions 1038;; See comments by `andsi' for when andl is faster than movzx. 1039 1040(define_insn "zero_extendhisi2" 1041 [(set (match_operand:SI 0 "general_operand" "=r") 1042 (zero_extend:SI 1043 (match_operand:HI 1 "nonimmediate_operand" "rm")))] 1044 "" 1045 "* 1046{ 1047 if ((TARGET_486 || REGNO (operands[0]) == 0) 1048 && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])) 1049 { 1050 rtx xops[2]; 1051 xops[0] = operands[0]; 1052 xops[1] = GEN_INT (0xffff); 1053 output_asm_insn (AS2 (and%L0,%1,%k0), xops); 1054 RET; 1055 } 1056 1057#ifdef INTEL_SYNTAX 1058 return AS2 (movzx,%1,%0); 1059#else 1060 return AS2 (movz%W0%L0,%1,%0); 1061#endif 1062}") 1063 1064(define_insn "zero_extendqihi2" 1065 [(set (match_operand:HI 0 "general_operand" "=r") 1066 (zero_extend:HI 1067 (match_operand:QI 1 "nonimmediate_operand" "qm")))] 1068 "" 1069 "* 1070{ 1071 if ((TARGET_486 || REGNO (operands[0]) == 0) 1072 && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])) 1073 { 1074 rtx xops[2]; 1075 xops[0] = operands[0]; 1076 xops[1] = GEN_INT (0xff); 1077 output_asm_insn (AS2 (and%L0,%1,%k0), xops); 1078 RET; 1079 } 1080 1081#ifdef INTEL_SYNTAX 1082 return AS2 (movzx,%1,%0); 1083#else 1084 return AS2 (movz%B0%W0,%1,%0); 1085#endif 1086}") 1087 1088(define_insn "zero_extendqisi2" 1089 [(set (match_operand:SI 0 "general_operand" "=r") 1090 (zero_extend:SI 1091 (match_operand:QI 1 "nonimmediate_operand" "qm")))] 1092 "" 1093 "* 1094{ 1095 if ((TARGET_486 || REGNO (operands[0]) == 0) 1096 && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])) 1097 { 1098 rtx xops[2]; 1099 xops[0] = operands[0]; 1100 xops[1] = GEN_INT (0xff); 1101 output_asm_insn (AS2 (and%L0,%1,%k0), xops); 1102 RET; 1103 } 1104 1105#ifdef INTEL_SYNTAX 1106 return AS2 (movzx,%1,%0); 1107#else 1108 return AS2 (movz%B0%L0,%1,%0); 1109#endif 1110}") 1111 1112(define_insn "zero_extendsidi2" 1113 [(set (match_operand:DI 0 "register_operand" "=r") 1114 (zero_extend:DI 1115 (match_operand:SI 1 "register_operand" "0")))] 1116 "" 1117 "* 1118{ 1119 operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); 1120 return AS2 (xor%L0,%0,%0); 1121}") 1122 1123;;- sign extension instructions 1124 1125(define_insn "extendsidi2" 1126 [(set (match_operand:DI 0 "register_operand" "=r") 1127 (sign_extend:DI 1128 (match_operand:SI 1 "register_operand" "0")))] 1129 "" 1130 "* 1131{ 1132 if (REGNO (operands[0]) == 0) 1133 { 1134 /* This used to be cwtl, but that extends HI to SI somehow. */ 1135#ifdef INTEL_SYNTAX 1136 return \"cdq\"; 1137#else 1138 return \"cltd\"; 1139#endif 1140 } 1141 1142 operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); 1143 output_asm_insn (AS2 (mov%L0,%0,%1), operands); 1144 1145 operands[0] = GEN_INT (31); 1146 return AS2 (sar%L1,%0,%1); 1147}") 1148 1149;; Note that the i386 programmers' manual says that the opcodes 1150;; are named movsx..., but the assembler on Unix does not accept that. 1151;; We use what the Unix assembler expects. 1152 1153(define_insn "extendhisi2" 1154 [(set (match_operand:SI 0 "general_operand" "=r") 1155 (sign_extend:SI 1156 (match_operand:HI 1 "nonimmediate_operand" "rm")))] 1157 "" 1158 "* 1159{ 1160 if (REGNO (operands[0]) == 0 1161 && REG_P (operands[1]) && REGNO (operands[1]) == 0) 1162#ifdef INTEL_SYNTAX 1163 return \"cwde\"; 1164#else 1165 return \"cwtl\"; 1166#endif 1167 1168#ifdef INTEL_SYNTAX 1169 return AS2 (movsx,%1,%0); 1170#else 1171 return AS2 (movs%W0%L0,%1,%0); 1172#endif 1173}") 1174 1175(define_insn "extendqihi2" 1176 [(set (match_operand:HI 0 "general_operand" "=r") 1177 (sign_extend:HI 1178 (match_operand:QI 1 "nonimmediate_operand" "qm")))] 1179 "" 1180 "* 1181{ 1182 if (REGNO (operands[0]) == 0 1183 && REG_P (operands[1]) && REGNO (operands[1]) == 0) 1184 return \"cbtw\"; 1185 1186#ifdef INTEL_SYNTAX 1187 return AS2 (movsx,%1,%0); 1188#else 1189 return AS2 (movs%B0%W0,%1,%0); 1190#endif 1191}") 1192 1193(define_insn "extendqisi2" 1194 [(set (match_operand:SI 0 "general_operand" "=r") 1195 (sign_extend:SI 1196 (match_operand:QI 1 "nonimmediate_operand" "qm")))] 1197 "" 1198 "* 1199{ 1200#ifdef INTEL_SYNTAX 1201 return AS2 (movsx,%1,%0); 1202#else 1203 return AS2 (movs%B0%L0,%1,%0); 1204#endif 1205}") 1206 1207;; Conversions between float and double. 1208 1209(define_insn "extendsfdf2" 1210 [(set (match_operand:DF 0 "general_operand" "=fm,f") 1211 (float_extend:DF 1212 (match_operand:SF 1 "general_operand" "f,fm")))] 1213 "TARGET_80387" 1214 "* 1215{ 1216 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 1217 1218 if (NON_STACK_REG_P (operands[1])) 1219 { 1220 output_op_from_reg (operands[1], AS1 (fld%z0,%y1)); 1221 RET; 1222 } 1223 1224 if (NON_STACK_REG_P (operands[0])) 1225 { 1226 output_to_reg (operands[0], stack_top_dies); 1227 RET; 1228 } 1229 1230 if (STACK_TOP_P (operands[0])) 1231 return AS1 (fld%z1,%y1); 1232 1233 if (GET_CODE (operands[0]) == MEM) 1234 { 1235 if (stack_top_dies) 1236 return AS1 (fstp%z0,%y0); 1237 else 1238 return AS1 (fst%z0,%y0); 1239 } 1240 1241 abort (); 1242}") 1243 1244(define_expand "truncdfsf2" 1245 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "") 1246 (float_truncate:SF 1247 (match_operand:DF 1 "register_operand" ""))) 1248 (clobber (match_dup 2))])] 1249 "TARGET_80387" 1250 " 1251{ 1252 operands[2] = (rtx) assign_386_stack_local (SFmode, 0); 1253}") 1254 1255;; This cannot output into an f-reg because there is no way to be sure 1256;; of truncating in that case. Otherwise this is just like a simple move 1257;; insn. So we pretend we can output to a reg in order to get better 1258;; register preferencing, but we really use a stack slot. 1259 1260(define_insn "" 1261 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m") 1262 (float_truncate:SF 1263 (match_operand:DF 1 "register_operand" "0,f"))) 1264 (clobber (match_operand:SF 2 "memory_operand" "m,m"))] 1265 "TARGET_80387" 1266 "* 1267{ 1268 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 1269 1270 if (GET_CODE (operands[0]) == MEM) 1271 { 1272 if (stack_top_dies) 1273 return AS1 (fstp%z0,%0); 1274 else 1275 return AS1 (fst%z0,%0); 1276 } 1277 else if (STACK_TOP_P (operands[0])) 1278 { 1279 output_asm_insn (AS1 (fstp%z2,%y2), operands); 1280 return AS1 (fld%z2,%y2); 1281 } 1282 else 1283 abort (); 1284}") 1285 1286;; The 387 requires that the stack top dies after converting to DImode. 1287 1288;; Represent an unsigned conversion from SImode to MODE_FLOAT by first 1289;; doing a signed conversion to DImode, and then taking just the low 1290;; part. 1291 1292(define_expand "fixuns_truncdfsi2" 1293 [(set (match_dup 4) 1294 (match_operand:DF 1 "register_operand" "")) 1295 (parallel [(set (match_dup 2) 1296 (fix:DI (fix:DF (match_dup 4)))) 1297 (clobber (match_dup 4)) 1298 (clobber (match_dup 5)) 1299 (clobber (match_dup 6)) 1300 (clobber (match_scratch:SI 7 ""))]) 1301 (set (match_operand:SI 0 "general_operand" "") 1302 (match_dup 3))] 1303 "TARGET_80387" 1304 " 1305{ 1306 operands[2] = gen_reg_rtx (DImode); 1307 operands[3] = gen_lowpart (SImode, operands[2]); 1308 operands[4] = gen_reg_rtx (DFmode); 1309 operands[5] = (rtx) assign_386_stack_local (SImode, 0); 1310 operands[6] = (rtx) assign_386_stack_local (SImode, 1); 1311}") 1312 1313(define_expand "fixuns_truncsfsi2" 1314 [(set (match_dup 4) 1315 (match_operand:SF 1 "register_operand" "")) 1316 (parallel [(set (match_dup 2) 1317 (fix:DI (fix:SF (match_dup 4)))) 1318 (clobber (match_dup 4)) 1319 (clobber (match_dup 5)) 1320 (clobber (match_dup 6)) 1321 (clobber (match_scratch:SI 7 ""))]) 1322 (set (match_operand:SI 0 "general_operand" "") 1323 (match_dup 3))] 1324 "TARGET_80387" 1325 " 1326{ 1327 operands[2] = gen_reg_rtx (DImode); 1328 operands[3] = gen_lowpart (SImode, operands[2]); 1329 operands[4] = gen_reg_rtx (SFmode); 1330 operands[5] = (rtx) assign_386_stack_local (SImode, 0); 1331 operands[6] = (rtx) assign_386_stack_local (SImode, 1); 1332}") 1333 1334;; Signed conversion to DImode. 1335 1336(define_expand "fix_truncdfdi2" 1337 [(set (match_dup 2) 1338 (match_operand:DF 1 "register_operand" "")) 1339 (parallel [(set (match_operand:DI 0 "general_operand" "") 1340 (fix:DI (fix:DF (match_dup 2)))) 1341 (clobber (match_dup 2)) 1342 (clobber (match_dup 3)) 1343 (clobber (match_dup 4)) 1344 (clobber (match_scratch:SI 5 ""))])] 1345 "TARGET_80387" 1346 " 1347{ 1348 operands[1] = copy_to_mode_reg (DFmode, operands[1]); 1349 operands[2] = gen_reg_rtx (DFmode); 1350 operands[3] = (rtx) assign_386_stack_local (SImode, 0); 1351 operands[4] = (rtx) assign_386_stack_local (SImode, 1); 1352}") 1353 1354(define_expand "fix_truncsfdi2" 1355 [(set (match_dup 2) 1356 (match_operand:SF 1 "register_operand" "")) 1357 (parallel [(set (match_operand:DI 0 "general_operand" "") 1358 (fix:DI (fix:SF (match_dup 2)))) 1359 (clobber (match_dup 2)) 1360 (clobber (match_dup 3)) 1361 (clobber (match_dup 4)) 1362 (clobber (match_scratch:SI 5 ""))])] 1363 "TARGET_80387" 1364 " 1365{ 1366 operands[1] = copy_to_mode_reg (SFmode, operands[1]); 1367 operands[2] = gen_reg_rtx (SFmode); 1368 operands[3] = (rtx) assign_386_stack_local (SImode, 0); 1369 operands[4] = (rtx) assign_386_stack_local (SImode, 1); 1370}") 1371 1372;; These match a signed conversion of either DFmode or SFmode to DImode. 1373 1374(define_insn "" 1375 [(set (match_operand:DI 0 "general_operand" "=rm") 1376 (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f")))) 1377 (clobber (match_dup 1)) 1378 (clobber (match_operand:SI 2 "memory_operand" "m")) 1379 (clobber (match_operand:SI 3 "memory_operand" "m")) 1380 (clobber (match_scratch:SI 4 "=&q"))] 1381 "TARGET_80387" 1382 "* return (char *) output_fix_trunc (insn, operands);") 1383 1384(define_insn "" 1385 [(set (match_operand:DI 0 "general_operand" "=rm") 1386 (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f")))) 1387 (clobber (match_dup 1)) 1388 (clobber (match_operand:SI 2 "memory_operand" "m")) 1389 (clobber (match_operand:SI 3 "memory_operand" "m")) 1390 (clobber (match_scratch:SI 4 "=&q"))] 1391 "TARGET_80387" 1392 "* return (char *) output_fix_trunc (insn, operands);") 1393 1394;; Signed MODE_FLOAT conversion to SImode. 1395 1396(define_expand "fix_truncdfsi2" 1397 [(parallel [(set (match_operand:SI 0 "general_operand" "") 1398 (fix:SI 1399 (fix:DF (match_operand:DF 1 "register_operand" "")))) 1400 (clobber (match_dup 2)) 1401 (clobber (match_dup 3)) 1402 (clobber (match_scratch:SI 4 ""))])] 1403 "TARGET_80387" 1404 " 1405{ 1406 operands[2] = (rtx) assign_386_stack_local (SImode, 0); 1407 operands[3] = (rtx) assign_386_stack_local (SImode, 1); 1408}") 1409 1410(define_expand "fix_truncsfsi2" 1411 [(parallel [(set (match_operand:SI 0 "general_operand" "") 1412 (fix:SI 1413 (fix:SF (match_operand:SF 1 "register_operand" "")))) 1414 (clobber (match_dup 2)) 1415 (clobber (match_dup 3)) 1416 (clobber (match_scratch:SI 4 ""))])] 1417 "TARGET_80387" 1418 " 1419{ 1420 operands[2] = (rtx) assign_386_stack_local (SImode, 0); 1421 operands[3] = (rtx) assign_386_stack_local (SImode, 1); 1422}") 1423 1424(define_insn "" 1425 [(set (match_operand:SI 0 "general_operand" "=rm") 1426 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f")))) 1427 (clobber (match_operand:SI 2 "memory_operand" "m")) 1428 (clobber (match_operand:SI 3 "memory_operand" "m")) 1429 (clobber (match_scratch:SI 4 "=&q"))] 1430 "TARGET_80387" 1431 "* return (char *) output_fix_trunc (insn, operands);") 1432 1433(define_insn "" 1434 [(set (match_operand:SI 0 "general_operand" "=rm") 1435 (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f")))) 1436 (clobber (match_operand:SI 2 "memory_operand" "m")) 1437 (clobber (match_operand:SI 3 "memory_operand" "m")) 1438 (clobber (match_scratch:SI 4 "=&q"))] 1439 "TARGET_80387" 1440 "* return (char *) output_fix_trunc (insn, operands);") 1441 1442;; Conversion between fixed point and floating point. 1443;; The actual pattern that matches these is at the end of this file. 1444 1445;; ??? Possibly represent floatunssidf2 here in gcc2. 1446 1447(define_expand "floatsisf2" 1448 [(set (match_operand:SF 0 "register_operand" "") 1449 (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))] 1450 "TARGET_80387" 1451 "") 1452 1453(define_expand "floatdisf2" 1454 [(set (match_operand:SF 0 "register_operand" "") 1455 (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))] 1456 "TARGET_80387" 1457 "") 1458 1459(define_expand "floatsidf2" 1460 [(set (match_operand:DF 0 "register_operand" "") 1461 (float:DF (match_operand:SI 1 "nonimmediate_operand" "")))] 1462 "TARGET_80387" 1463 "") 1464 1465(define_expand "floatdidf2" 1466 [(set (match_operand:DF 0 "register_operand" "") 1467 (float:DF (match_operand:DI 1 "nonimmediate_operand" "")))] 1468 "TARGET_80387" 1469 "") 1470 1471;; This will convert from SImode or DImode to MODE_FLOAT. 1472 1473(define_insn "" 1474 [(set (match_operand:DF 0 "register_operand" "=f") 1475 (float:DF (match_operand:DI 1 "nonimmediate_operand" "rm")))] 1476 "TARGET_80387" 1477 "* 1478{ 1479 if (NON_STACK_REG_P (operands[1])) 1480 { 1481 output_op_from_reg (operands[1], AS1 (fild%z0,%1)); 1482 RET; 1483 } 1484 else if (GET_CODE (operands[1]) == MEM) 1485 return AS1 (fild%z1,%1); 1486 else 1487 abort (); 1488}") 1489 1490(define_insn "" 1491 [(set (match_operand:SF 0 "register_operand" "=f") 1492 (float:SF (match_operand:DI 1 "nonimmediate_operand" "rm")))] 1493 "TARGET_80387" 1494 "* 1495{ 1496 if (NON_STACK_REG_P (operands[1])) 1497 { 1498 output_op_from_reg (operands[1], AS1 (fild%z0,%1)); 1499 RET; 1500 } 1501 else if (GET_CODE (operands[1]) == MEM) 1502 return AS1 (fild%z1,%1); 1503 else 1504 abort (); 1505}") 1506 1507(define_insn "" 1508 [(set (match_operand:DF 0 "register_operand" "=f") 1509 (float:DF (match_operand:SI 1 "nonimmediate_operand" "rm")))] 1510 "TARGET_80387" 1511 "* 1512{ 1513 if (NON_STACK_REG_P (operands[1])) 1514 { 1515 output_op_from_reg (operands[1], AS1 (fild%z0,%1)); 1516 RET; 1517 } 1518 else if (GET_CODE (operands[1]) == MEM) 1519 return AS1 (fild%z1,%1); 1520 else 1521 abort (); 1522}") 1523 1524(define_insn "" 1525 [(set (match_operand:SF 0 "register_operand" "=f") 1526 (float:SF (match_operand:SI 1 "nonimmediate_operand" "rm")))] 1527 "TARGET_80387" 1528 "* 1529{ 1530 if (NON_STACK_REG_P (operands[1])) 1531 { 1532 output_op_from_reg (operands[1], AS1 (fild%z0,%1)); 1533 RET; 1534 } 1535 else if (GET_CODE (operands[1]) == MEM) 1536 return AS1 (fild%z1,%1); 1537 else 1538 abort (); 1539}") 1540 1541;;- add instructions 1542 1543(define_insn "adddi3" 1544 [(set (match_operand:DI 0 "general_operand" "=&r,ro") 1545 (plus:DI (match_operand:DI 1 "general_operand" "%0,0") 1546 (match_operand:DI 2 "general_operand" "o,riF")))] 1547 "" 1548 "* 1549{ 1550 rtx low[3], high[3]; 1551 1552 CC_STATUS_INIT; 1553 1554 split_di (operands, 3, low, high); 1555 1556 if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0) 1557 { 1558 output_asm_insn (AS2 (add%L0,%2,%0), low); 1559 output_asm_insn (AS2 (adc%L0,%2,%0), high); 1560 } 1561 else 1562 output_asm_insn (AS2 (add%L0,%2,%0), high); 1563 RET; 1564}") 1565 1566;; On a 486, it is faster to do movl/addl than to do a single leal if 1567;; operands[1] and operands[2] are both registers. 1568 1569(define_insn "addsi3" 1570 [(set (match_operand:SI 0 "general_operand" "=?r,rm,r") 1571 (plus:SI (match_operand:SI 1 "general_operand" "%r,0,0") 1572 (match_operand:SI 2 "general_operand" "ri,ri,rm")))] 1573 "" 1574 "* 1575{ 1576 if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1])) 1577 { 1578 if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2])) 1579 return AS2 (add%L0,%1,%0); 1580 1581 if (! TARGET_486 || ! REG_P (operands[2])) 1582 { 1583 CC_STATUS_INIT; 1584 1585 if (operands[2] == stack_pointer_rtx) 1586 { 1587 rtx temp; 1588 1589 temp = operands[1]; 1590 operands[1] = operands[2]; 1591 operands[2] = temp; 1592 } 1593 if (operands[2] != stack_pointer_rtx) 1594 { 1595 operands[1] = SET_SRC (PATTERN (insn)); 1596 return AS2 (lea%L0,%a1,%0); 1597 } 1598 } 1599 1600 output_asm_insn (AS2 (mov%L0,%1,%0), operands); 1601 } 1602 1603 if (operands[2] == const1_rtx) 1604 return AS1 (inc%L0,%0); 1605 1606 if (operands[2] == constm1_rtx) 1607 return AS1 (dec%L0,%0); 1608 1609 return AS2 (add%L0,%2,%0); 1610}") 1611 1612;; ??? `lea' here, for three operand add? If leaw is used, only %bx, 1613;; %si and %di can appear in SET_SRC, and output_asm_insn might not be 1614;; able to handle the operand. But leal always works? 1615 1616(define_insn "addhi3" 1617 [(set (match_operand:HI 0 "general_operand" "=rm,r") 1618 (plus:HI (match_operand:HI 1 "general_operand" "%0,0") 1619 (match_operand:HI 2 "general_operand" "ri,rm")))] 1620 "" 1621 "* 1622{ 1623 if (operands[2] == const1_rtx) 1624 return AS1 (inc%W0,%0); 1625 1626 if (operands[2] == constm1_rtx) 1627 return AS1 (dec%W0,%0); 1628 1629 return AS2 (add%W0,%2,%0); 1630}") 1631 1632(define_insn "addqi3" 1633 [(set (match_operand:QI 0 "general_operand" "=qm,q") 1634 (plus:QI (match_operand:QI 1 "general_operand" "%0,0") 1635 (match_operand:QI 2 "general_operand" "qn,qmn")))] 1636 "" 1637 "* 1638{ 1639 if (operands[2] == const1_rtx) 1640 return AS1 (inc%B0,%0); 1641 1642 if (operands[2] == constm1_rtx) 1643 return AS1 (dec%B0,%0); 1644 1645 return AS2 (add%B0,%2,%0); 1646}") 1647 1648;Lennart Augustsson <augustss@cs.chalmers.se> 1649;says this pattern just makes slower code: 1650; pushl %ebp 1651; addl $-80,(%esp) 1652;instead of 1653; leal -80(%ebp),%eax 1654; pushl %eax 1655; 1656;(define_insn "" 1657; [(set (match_operand:SI 0 "push_operand" "=<") 1658; (plus:SI (match_operand:SI 1 "general_operand" "%r") 1659; (match_operand:SI 2 "general_operand" "ri")))] 1660; "" 1661; "* 1662;{ 1663; rtx xops[4]; 1664; xops[0] = operands[0]; 1665; xops[1] = operands[1]; 1666; xops[2] = operands[2]; 1667; xops[3] = gen_rtx (MEM, SImode, stack_pointer_rtx); 1668; output_asm_insn (\"push%z1 %1\", xops); 1669; output_asm_insn (AS2 (add%z3,%2,%3), xops); 1670; RET; 1671;}") 1672 1673;; addsi3 is faster, so put this after. 1674 1675(define_insn "" 1676 [(set (match_operand:SI 0 "register_operand" "=r") 1677 (match_operand:QI 1 "address_operand" "p"))] 1678 "" 1679 "* 1680{ 1681 CC_STATUS_INIT; 1682 /* Adding a constant to a register is faster with an add. */ 1683 /* ??? can this ever happen? */ 1684 if (GET_CODE (operands[1]) == PLUS 1685 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT 1686 && rtx_equal_p (operands[0], XEXP (operands[1], 0))) 1687 { 1688 operands[1] = XEXP (operands[1], 1); 1689 1690 if (operands[1] == const1_rtx) 1691 return AS1 (inc%L0,%0); 1692 1693 if (operands[1] == constm1_rtx) 1694 return AS1 (dec%L0,%0); 1695 1696 return AS2 (add%L0,%1,%0); 1697 } 1698 return AS2 (lea%L0,%a1,%0); 1699}") 1700 1701;; The patterns that match these are at the end of this file. 1702 1703(define_expand "adddf3" 1704 [(set (match_operand:DF 0 "register_operand" "") 1705 (plus:DF (match_operand:DF 1 "nonimmediate_operand" "") 1706 (match_operand:DF 2 "nonimmediate_operand" "")))] 1707 "TARGET_80387" 1708 "") 1709 1710(define_expand "addsf3" 1711 [(set (match_operand:SF 0 "register_operand" "") 1712 (plus:SF (match_operand:SF 1 "nonimmediate_operand" "") 1713 (match_operand:SF 2 "nonimmediate_operand" "")))] 1714 "TARGET_80387" 1715 "") 1716 1717;;- subtract instructions 1718 1719(define_insn "subdi3" 1720 [(set (match_operand:DI 0 "general_operand" "=&r,ro") 1721 (minus:DI (match_operand:DI 1 "general_operand" "0,0") 1722 (match_operand:DI 2 "general_operand" "o,riF")))] 1723 "" 1724 "* 1725{ 1726 rtx low[3], high[3]; 1727 1728 CC_STATUS_INIT; 1729 1730 split_di (operands, 3, low, high); 1731 1732 if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0) 1733 { 1734 output_asm_insn (AS2 (sub%L0,%2,%0), low); 1735 output_asm_insn (AS2 (sbb%L0,%2,%0), high); 1736 } 1737 else 1738 output_asm_insn (AS2 (sub%L0,%2,%0), high); 1739 1740 RET; 1741}") 1742 1743(define_insn "subsi3" 1744 [(set (match_operand:SI 0 "general_operand" "=rm,r") 1745 (minus:SI (match_operand:SI 1 "general_operand" "0,0") 1746 (match_operand:SI 2 "general_operand" "ri,rm")))] 1747 "" 1748 "* return AS2 (sub%L0,%2,%0);") 1749 1750(define_insn "subhi3" 1751 [(set (match_operand:HI 0 "general_operand" "=rm,r") 1752 (minus:HI (match_operand:HI 1 "general_operand" "0,0") 1753 (match_operand:HI 2 "general_operand" "ri,rm")))] 1754 "" 1755 "* return AS2 (sub%W0,%2,%0);") 1756 1757(define_insn "subqi3" 1758 [(set (match_operand:QI 0 "general_operand" "=qm,q") 1759 (minus:QI (match_operand:QI 1 "general_operand" "0,0") 1760 (match_operand:QI 2 "general_operand" "qn,qmn")))] 1761 "" 1762 "* return AS2 (sub%B0,%2,%0);") 1763 1764;; The patterns that match these are at the end of this file. 1765 1766(define_expand "subdf3" 1767 [(set (match_operand:DF 0 "register_operand" "") 1768 (minus:DF (match_operand:DF 1 "nonimmediate_operand" "") 1769 (match_operand:DF 2 "nonimmediate_operand" "")))] 1770 "TARGET_80387" 1771 "") 1772 1773(define_expand "subsf3" 1774 [(set (match_operand:SF 0 "register_operand" "") 1775 (minus:SF (match_operand:SF 1 "nonimmediate_operand" "") 1776 (match_operand:SF 2 "nonimmediate_operand" "")))] 1777 "TARGET_80387" 1778 "") 1779 1780;;- multiply instructions 1781 1782;(define_insn "mulqi3" 1783; [(set (match_operand:QI 0 "general_operand" "=a") 1784; (mult:QI (match_operand:QI 1 "general_operand" "%0") 1785; (match_operand:QI 2 "general_operand" "qm")))] 1786; "" 1787; "imul%B0 %2,%0") 1788 1789(define_insn "" 1790 [(set (match_operand:HI 0 "general_operand" "=r") 1791 (mult:SI (match_operand:HI 1 "general_operand" "%0") 1792 (match_operand:HI 2 "general_operand" "r")))] 1793 "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80" 1794 "* return AS2 (imul%W0,%2,%0);") 1795 1796(define_insn "mulhi3" 1797 [(set (match_operand:HI 0 "general_operand" "=r,r") 1798 (mult:SI (match_operand:HI 1 "general_operand" "%0,rm") 1799 (match_operand:HI 2 "general_operand" "g,i")))] 1800 "" 1801 "* 1802{ 1803 if (GET_CODE (operands[1]) == REG 1804 && REGNO (operands[1]) == REGNO (operands[0]) 1805 && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG)) 1806 /* Assembler has weird restrictions. */ 1807 return AS2 (imul%W0,%2,%0); 1808 return AS3 (imul%W0,%2,%1,%0); 1809}") 1810 1811(define_insn "" 1812 [(set (match_operand:SI 0 "general_operand" "=r") 1813 (mult:SI (match_operand:SI 1 "general_operand" "%0") 1814 (match_operand:SI 2 "general_operand" "r")))] 1815 "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80" 1816 "* return AS2 (imul%L0,%2,%0);") 1817 1818(define_insn "mulsi3" 1819 [(set (match_operand:SI 0 "general_operand" "=r,r") 1820 (mult:SI (match_operand:SI 1 "general_operand" "%0,rm") 1821 (match_operand:SI 2 "general_operand" "g,i")))] 1822 "" 1823 "* 1824{ 1825 if (GET_CODE (operands[1]) == REG 1826 && REGNO (operands[1]) == REGNO (operands[0]) 1827 && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG)) 1828 /* Assembler has weird restrictions. */ 1829 return AS2 (imul%L0,%2,%0); 1830 return AS3 (imul%L0,%2,%1,%0); 1831}") 1832 1833(define_insn "" 1834 [(set (match_operand:HI 0 "general_operand" "=a") 1835 (mult:SI (zero_extend:HI 1836 (match_operand:QI 1 "nonimmediate_operand" "%0")) 1837 (zero_extend:HI 1838 (match_operand:QI 2 "nonimmediate_operand" "qm"))))] 1839 "" 1840 "mul%B0 %2") 1841 1842;; The patterns that match these are at the end of this file. 1843 1844(define_expand "muldf3" 1845 [(set (match_operand:DF 0 "register_operand" "") 1846 (mult:DF (match_operand:DF 1 "nonimmediate_operand" "") 1847 (match_operand:DF 2 "nonimmediate_operand" "")))] 1848 "TARGET_80387" 1849 "") 1850 1851(define_expand "mulsf3" 1852 [(set (match_operand:SF 0 "register_operand" "") 1853 (mult:SF (match_operand:SF 1 "nonimmediate_operand" "") 1854 (match_operand:SF 2 "nonimmediate_operand" "")))] 1855 "TARGET_80387" 1856 "") 1857 1858;;- divide instructions 1859 1860(define_insn "divqi3" 1861 [(set (match_operand:QI 0 "general_operand" "=a") 1862 (div:QI (match_operand:HI 1 "general_operand" "0") 1863 (match_operand:QI 2 "general_operand" "qm")))] 1864 "" 1865 "idiv%B0 %2") 1866 1867(define_insn "udivqi3" 1868 [(set (match_operand:QI 0 "general_operand" "=a") 1869 (udiv:QI (match_operand:HI 1 "general_operand" "0") 1870 (match_operand:QI 2 "general_operand" "qm")))] 1871 "" 1872 "div%B0 %2") 1873 1874;; The patterns that match these are at the end of this file. 1875 1876(define_expand "divdf3" 1877 [(set (match_operand:DF 0 "register_operand" "") 1878 (div:DF (match_operand:DF 1 "nonimmediate_operand" "") 1879 (match_operand:DF 2 "nonimmediate_operand" "")))] 1880 "TARGET_80387" 1881 "") 1882 1883(define_expand "divsf3" 1884 [(set (match_operand:SF 0 "register_operand" "") 1885 (div:SF (match_operand:SF 1 "nonimmediate_operand" "") 1886 (match_operand:SF 2 "nonimmediate_operand" "")))] 1887 "TARGET_80387" 1888 "") 1889 1890;; Remainder instructions. 1891 1892(define_insn "divmodsi4" 1893 [(set (match_operand:SI 0 "register_operand" "=a") 1894 (div:SI (match_operand:SI 1 "register_operand" "0") 1895 (match_operand:SI 2 "general_operand" "rm"))) 1896 (set (match_operand:SI 3 "register_operand" "=&d") 1897 (mod:SI (match_dup 1) (match_dup 2)))] 1898 "" 1899 "* 1900{ 1901#ifdef INTEL_SYNTAX 1902 output_asm_insn (\"cdq\", operands); 1903#else 1904 output_asm_insn (\"cltd\", operands); 1905#endif 1906 return AS1 (idiv%L0,%2); 1907}") 1908 1909(define_insn "divmodhi4" 1910 [(set (match_operand:HI 0 "register_operand" "=a") 1911 (div:HI (match_operand:HI 1 "register_operand" "0") 1912 (match_operand:HI 2 "general_operand" "rm"))) 1913 (set (match_operand:HI 3 "register_operand" "=&d") 1914 (mod:HI (match_dup 1) (match_dup 2)))] 1915 "" 1916 "cwtd\;idiv%W0 %2") 1917 1918;; ??? Can we make gcc zero extend operand[0]? 1919(define_insn "udivmodsi4" 1920 [(set (match_operand:SI 0 "register_operand" "=a") 1921 (udiv:SI (match_operand:SI 1 "register_operand" "0") 1922 (match_operand:SI 2 "general_operand" "rm"))) 1923 (set (match_operand:SI 3 "register_operand" "=&d") 1924 (umod:SI (match_dup 1) (match_dup 2)))] 1925 "" 1926 "* 1927{ 1928 output_asm_insn (AS2 (xor%L3,%3,%3), operands); 1929 return AS1 (div%L0,%2); 1930}") 1931 1932;; ??? Can we make gcc zero extend operand[0]? 1933(define_insn "udivmodhi4" 1934 [(set (match_operand:HI 0 "register_operand" "=a") 1935 (udiv:HI (match_operand:HI 1 "register_operand" "0") 1936 (match_operand:HI 2 "general_operand" "rm"))) 1937 (set (match_operand:HI 3 "register_operand" "=&d") 1938 (umod:HI (match_dup 1) (match_dup 2)))] 1939 "" 1940 "* 1941{ 1942 output_asm_insn (AS2 (xor%W0,%3,%3), operands); 1943 return AS1 (div%W0,%2); 1944}") 1945 1946/* 1947;;this should be a valid double division which we may want to add 1948 1949(define_insn "" 1950 [(set (match_operand:SI 0 "register_operand" "=a") 1951 (udiv:DI (match_operand:DI 1 "register_operand" "a") 1952 (match_operand:SI 2 "general_operand" "rm"))) 1953 (set (match_operand:SI 3 "register_operand" "=d") 1954 (umod:SI (match_dup 1) (match_dup 2)))] 1955 "" 1956 "div%L0 %2,%0") 1957*/ 1958 1959;;- and instructions 1960 1961;; On i386, 1962;; movzbl %bl,%ebx 1963;; is faster than 1964;; andl $255,%ebx 1965;; 1966;; but if the reg is %eax, then the "andl" is faster. 1967;; 1968;; On i486, the "andl" is always faster than the "movzbl". 1969;; 1970;; On both i386 and i486, a three operand AND is as fast with movzbl or 1971;; movzwl as with andl, if operands[0] != operands[1]. 1972 1973;; The `r' in `rm' for operand 3 looks redundant, but it causes 1974;; optional reloads to be generated if op 3 is a pseudo in a stack slot. 1975 1976;; ??? What if we only change one byte of an offsettable memory reference? 1977(define_insn "andsi3" 1978 [(set (match_operand:SI 0 "general_operand" "=r,r,rm,r") 1979 (and:SI (match_operand:SI 1 "general_operand" "%rm,qm,0,0") 1980 (match_operand:SI 2 "general_operand" "L,K,ri,rm")))] 1981 "" 1982 "* 1983{ 1984 if (GET_CODE (operands[2]) == CONST_INT 1985 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) 1986 { 1987 if (INTVAL (operands[2]) == 0xffff && REG_P (operands[0]) 1988 && (! REG_P (operands[1]) 1989 || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0) 1990 && (! TARGET_486 || ! rtx_equal_p (operands[0], operands[1]))) 1991 { 1992 /* ??? tege: Should forget CC_STATUS only if we clobber a 1993 remembered operand. Fix that later. */ 1994 CC_STATUS_INIT; 1995#ifdef INTEL_SYNTAX 1996 return AS2 (movzx,%w1,%0); 1997#else 1998 return AS2 (movz%W0%L0,%w1,%0); 1999#endif 2000 } 2001 2002 if (INTVAL (operands[2]) == 0xff && REG_P (operands[0]) 2003 && !(REG_P (operands[1]) && NON_QI_REG_P (operands[1])) 2004 && (! REG_P (operands[1]) 2005 || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0) 2006 && (! TARGET_486 || ! rtx_equal_p (operands[0], operands[1]))) 2007 { 2008 /* ??? tege: Should forget CC_STATUS only if we clobber a 2009 remembered operand. Fix that later. */ 2010 CC_STATUS_INIT; 2011#ifdef INTEL_SYNTAX 2012 return AS2 (movzx,%b1,%0); 2013#else 2014 return AS2 (movz%B0%L0,%b1,%0); 2015#endif 2016 } 2017 2018 if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff) == 0) 2019 { 2020 CC_STATUS_INIT; 2021 2022 if (INTVAL (operands[2]) == 0xffffff00) 2023 { 2024 operands[2] = const0_rtx; 2025 return AS2 (mov%B0,%2,%b0); 2026 } 2027 2028 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff); 2029 return AS2 (and%B0,%2,%b0); 2030 } 2031 2032 if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff00) == 0) 2033 { 2034 CC_STATUS_INIT; 2035 2036 if (INTVAL (operands[2]) == 0xffff00ff) 2037 { 2038 operands[2] = const0_rtx; 2039 return AS2 (mov%B0,%2,%h0); 2040 } 2041 2042 operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); 2043 return AS2 (and%B0,%2,%h0); 2044 } 2045 2046 if (GET_CODE (operands[0]) == MEM && INTVAL (operands[2]) == 0xffff0000) 2047 { 2048 operands[2] = const0_rtx; 2049 return AS2 (mov%W0,%2,%w0); 2050 } 2051 } 2052 2053 return AS2 (and%L0,%2,%0); 2054}") 2055 2056(define_insn "andhi3" 2057 [(set (match_operand:HI 0 "general_operand" "=rm,r") 2058 (and:HI (match_operand:HI 1 "general_operand" "%0,0") 2059 (match_operand:HI 2 "general_operand" "ri,rm")))] 2060 "" 2061 "* 2062{ 2063 if (GET_CODE (operands[2]) == CONST_INT 2064 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) 2065 { 2066 /* Can we ignore the upper byte? */ 2067 if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) 2068 && (INTVAL (operands[2]) & 0xff00) == 0xff00) 2069 { 2070 CC_STATUS_INIT; 2071 2072 if ((INTVAL (operands[2]) & 0xff) == 0) 2073 { 2074 operands[2] = const0_rtx; 2075 return AS2 (mov%B0,%2,%b0); 2076 } 2077 2078 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff); 2079 return AS2 (and%B0,%2,%b0); 2080 } 2081 2082 /* Can we ignore the lower byte? */ 2083 /* ??? what about offsettable memory references? */ 2084 if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & 0xff) == 0xff) 2085 { 2086 CC_STATUS_INIT; 2087 2088 if ((INTVAL (operands[2]) & 0xff00) == 0) 2089 { 2090 operands[2] = const0_rtx; 2091 return AS2 (mov%B0,%2,%h0); 2092 } 2093 2094 operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); 2095 return AS2 (and%B0,%2,%h0); 2096 } 2097 } 2098 2099 return AS2 (and%W0,%2,%0); 2100}") 2101 2102(define_insn "andqi3" 2103 [(set (match_operand:QI 0 "general_operand" "=qm,q") 2104 (and:QI (match_operand:QI 1 "general_operand" "%0,0") 2105 (match_operand:QI 2 "general_operand" "qn,qmn")))] 2106 "" 2107 "* return AS2 (and%B0,%2,%0);") 2108 2109/* I am nervous about these two.. add them later.. 2110;I presume this means that we have something in say op0= eax which is small 2111;and we want to and it with memory so we can do this by just an 2112;andb m,%al and have success. 2113(define_insn "" 2114 [(set (match_operand:SI 0 "general_operand" "=r") 2115 (and:SI (zero_extend:SI 2116 (match_operand:HI 1 "nonimmediate_operand" "rm")) 2117 (match_operand:SI 2 "general_operand" "0")))] 2118 "GET_CODE (operands[2]) == CONST_INT 2119 && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (HImode))" 2120 "and%W0 %1,%0") 2121 2122(define_insn "" 2123 [(set (match_operand:SI 0 "general_operand" "=q") 2124 (and:SI 2125 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")) 2126 (match_operand:SI 2 "general_operand" "0")))] 2127 "GET_CODE (operands[2]) == CONST_INT 2128 && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))" 2129 "and%L0 %1,%0") 2130 2131*/ 2132 2133;;- Bit set (inclusive or) instructions 2134 2135;; ??? What if we only change one byte of an offsettable memory reference? 2136(define_insn "iorsi3" 2137 [(set (match_operand:SI 0 "general_operand" "=rm,r") 2138 (ior:SI (match_operand:SI 1 "general_operand" "%0,0") 2139 (match_operand:SI 2 "general_operand" "ri,rm")))] 2140 "" 2141 "* 2142{ 2143 if (GET_CODE (operands[2]) == CONST_INT 2144 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) 2145 { 2146 if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) 2147 && (INTVAL (operands[2]) & ~0xff) == 0) 2148 { 2149 CC_STATUS_INIT; 2150 2151 if (INTVAL (operands[2]) == 0xff) 2152 return AS2 (mov%B0,%2,%b0); 2153 2154 return AS2 (or%B0,%2,%b0); 2155 } 2156 2157 if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0) 2158 { 2159 CC_STATUS_INIT; 2160 operands[2] = GEN_INT (INTVAL (operands[2]) >> 8); 2161 2162 if (INTVAL (operands[2]) == 0xff) 2163 return AS2 (mov%B0,%2,%h0); 2164 2165 return AS2 (or%B0,%2,%h0); 2166 } 2167 } 2168 2169 return AS2 (or%L0,%2,%0); 2170}") 2171 2172(define_insn "iorhi3" 2173 [(set (match_operand:HI 0 "general_operand" "=rm,r") 2174 (ior:HI (match_operand:HI 1 "general_operand" "%0,0") 2175 (match_operand:HI 2 "general_operand" "ri,rm")))] 2176 "" 2177 "* 2178{ 2179 if (GET_CODE (operands[2]) == CONST_INT 2180 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) 2181 { 2182 /* Can we ignore the upper byte? */ 2183 if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) 2184 && (INTVAL (operands[2]) & 0xff00) == 0) 2185 { 2186 CC_STATUS_INIT; 2187 if (INTVAL (operands[2]) & 0xffff0000) 2188 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff); 2189 2190 if (INTVAL (operands[2]) == 0xff) 2191 return AS2 (mov%B0,%2,%b0); 2192 2193 return AS2 (or%B0,%2,%b0); 2194 } 2195 2196 /* Can we ignore the lower byte? */ 2197 /* ??? what about offsettable memory references? */ 2198 if (QI_REG_P (operands[0]) 2199 && (INTVAL (operands[2]) & 0xff) == 0) 2200 { 2201 CC_STATUS_INIT; 2202 operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); 2203 2204 if (INTVAL (operands[2]) == 0xff) 2205 return AS2 (mov%B0,%2,%h0); 2206 2207 return AS2 (or%B0,%2,%h0); 2208 } 2209 } 2210 2211 return AS2 (or%W0,%2,%0); 2212}") 2213 2214(define_insn "iorqi3" 2215 [(set (match_operand:QI 0 "general_operand" "=qm,q") 2216 (ior:QI (match_operand:QI 1 "general_operand" "%0,0") 2217 (match_operand:QI 2 "general_operand" "qn,qmn")))] 2218 "" 2219 "* return AS2 (or%B0,%2,%0);") 2220 2221;;- xor instructions 2222 2223;; ??? What if we only change one byte of an offsettable memory reference? 2224(define_insn "xorsi3" 2225 [(set (match_operand:SI 0 "general_operand" "=rm,r") 2226 (xor:SI (match_operand:SI 1 "general_operand" "%0,0") 2227 (match_operand:SI 2 "general_operand" "ri,rm")))] 2228 "" 2229 "* 2230{ 2231 if (GET_CODE (operands[2]) == CONST_INT 2232 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) 2233 { 2234 if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) 2235 && (INTVAL (operands[2]) & ~0xff) == 0) 2236 { 2237 CC_STATUS_INIT; 2238 2239 if (INTVAL (operands[2]) == 0xff) 2240 return AS1 (not%B0,%b0); 2241 2242 return AS2 (xor%B0,%2,%b0); 2243 } 2244 2245 if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0) 2246 { 2247 CC_STATUS_INIT; 2248 operands[2] = GEN_INT (INTVAL (operands[2]) >> 8); 2249 2250 if (INTVAL (operands[2]) == 0xff) 2251 return AS1 (not%B0,%h0); 2252 2253 return AS2 (xor%B0,%2,%h0); 2254 } 2255 } 2256 2257 return AS2 (xor%L0,%2,%0); 2258}") 2259 2260(define_insn "xorhi3" 2261 [(set (match_operand:HI 0 "general_operand" "=rm,r") 2262 (xor:HI (match_operand:HI 1 "general_operand" "%0,0") 2263 (match_operand:HI 2 "general_operand" "ri,rm")))] 2264 "" 2265 "* 2266{ 2267 if (GET_CODE (operands[2]) == CONST_INT 2268 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) 2269 { 2270 /* Can we ignore the upper byte? */ 2271 if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) 2272 && (INTVAL (operands[2]) & 0xff00) == 0) 2273 { 2274 CC_STATUS_INIT; 2275 if (INTVAL (operands[2]) & 0xffff0000) 2276 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff); 2277 2278 if (INTVAL (operands[2]) == 0xff) 2279 return AS1 (not%B0,%b0); 2280 2281 return AS2 (xor%B0,%2,%b0); 2282 } 2283 2284 /* Can we ignore the lower byte? */ 2285 /* ??? what about offsettable memory references? */ 2286 if (QI_REG_P (operands[0]) 2287 && (INTVAL (operands[2]) & 0xff) == 0) 2288 { 2289 CC_STATUS_INIT; 2290 operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); 2291 2292 if (INTVAL (operands[2]) == 0xff) 2293 return AS1 (not%B0,%h0); 2294 2295 return AS2 (xor%B0,%2,%h0); 2296 } 2297 } 2298 2299 return AS2 (xor%W0,%2,%0); 2300}") 2301 2302(define_insn "xorqi3" 2303 [(set (match_operand:QI 0 "general_operand" "=qm,q") 2304 (xor:QI (match_operand:QI 1 "general_operand" "%0,0") 2305 (match_operand:QI 2 "general_operand" "qn,qm")))] 2306 "" 2307 "* return AS2 (xor%B0,%2,%0);") 2308 2309;;- negation instructions 2310 2311(define_insn "negdi2" 2312 [(set (match_operand:DI 0 "general_operand" "=&ro") 2313 (neg:DI (match_operand:DI 1 "general_operand" "0")))] 2314 "" 2315 "* 2316{ 2317 rtx xops[2], low[1], high[1]; 2318 2319 CC_STATUS_INIT; 2320 2321 split_di (operands, 1, low, high); 2322 xops[0] = const0_rtx; 2323 xops[1] = high[0]; 2324 2325 output_asm_insn (AS1 (neg%L0,%0), low); 2326 output_asm_insn (AS2 (adc%L1,%0,%1), xops); 2327 output_asm_insn (AS1 (neg%L0,%0), high); 2328 RET; 2329}") 2330 2331(define_insn "negsi2" 2332 [(set (match_operand:SI 0 "general_operand" "=rm") 2333 (neg:SI (match_operand:SI 1 "general_operand" "0")))] 2334 "" 2335 "neg%L0 %0") 2336 2337(define_insn "neghi2" 2338 [(set (match_operand:HI 0 "general_operand" "=rm") 2339 (neg:HI (match_operand:HI 1 "general_operand" "0")))] 2340 "" 2341 "neg%W0 %0") 2342 2343(define_insn "negqi2" 2344 [(set (match_operand:QI 0 "general_operand" "=qm") 2345 (neg:QI (match_operand:QI 1 "general_operand" "0")))] 2346 "" 2347 "neg%B0 %0") 2348 2349(define_insn "negsf2" 2350 [(set (match_operand:SF 0 "register_operand" "=f") 2351 (neg:SF (match_operand:SF 1 "general_operand" "0")))] 2352 "TARGET_80387" 2353 "fchs") 2354 2355(define_insn "negdf2" 2356 [(set (match_operand:DF 0 "register_operand" "=f") 2357 (neg:DF (match_operand:DF 1 "general_operand" "0")))] 2358 "TARGET_80387" 2359 "fchs") 2360 2361(define_insn "" 2362 [(set (match_operand:DF 0 "register_operand" "=f") 2363 (neg:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))] 2364 "TARGET_80387" 2365 "fchs") 2366 2367;; Absolute value instructions 2368 2369(define_insn "abssf2" 2370 [(set (match_operand:SF 0 "register_operand" "=f") 2371 (abs:SF (match_operand:SF 1 "general_operand" "0")))] 2372 "TARGET_80387" 2373 "fabs") 2374 2375(define_insn "absdf2" 2376 [(set (match_operand:DF 0 "register_operand" "=f") 2377 (abs:DF (match_operand:DF 1 "general_operand" "0")))] 2378 "TARGET_80387" 2379 "fabs") 2380 2381(define_insn "" 2382 [(set (match_operand:DF 0 "register_operand" "=f") 2383 (abs:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))] 2384 "TARGET_80387" 2385 "fabs") 2386 2387(define_insn "sqrtsf2" 2388 [(set (match_operand:SF 0 "register_operand" "=f") 2389 (sqrt:SF (match_operand:SF 1 "general_operand" "0")))] 2390 "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" 2391 "fsqrt") 2392 2393(define_insn "sqrtdf2" 2394 [(set (match_operand:DF 0 "register_operand" "=f") 2395 (sqrt:DF (match_operand:DF 1 "general_operand" "0")))] 2396 "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" 2397 "fsqrt") 2398 2399(define_insn "" 2400 [(set (match_operand:DF 0 "register_operand" "=f") 2401 (sqrt:DF (float_extend:DF 2402 (match_operand:SF 1 "general_operand" "0"))))] 2403 "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" 2404 "fsqrt") 2405 2406(define_insn "sindf2" 2407 [(set (match_operand:DF 0 "register_operand" "=f") 2408 (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))] 2409 "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" 2410 "fsin") 2411 2412(define_insn "sinsf2" 2413 [(set (match_operand:SF 0 "register_operand" "=f") 2414 (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))] 2415 "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" 2416 "fsin") 2417 2418(define_insn "" 2419 [(set (match_operand:DF 0 "register_operand" "=f") 2420 (unspec:DF [(float_extend:DF 2421 (match_operand:SF 1 "register_operand" "0"))] 1))] 2422 "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" 2423 "fsin") 2424 2425(define_insn "cosdf2" 2426 [(set (match_operand:DF 0 "register_operand" "=f") 2427 (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))] 2428 "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" 2429 "fcos") 2430 2431(define_insn "cossf2" 2432 [(set (match_operand:SF 0 "register_operand" "=f") 2433 (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))] 2434 "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" 2435 "fcos") 2436 2437(define_insn "" 2438 [(set (match_operand:DF 0 "register_operand" "=f") 2439 (unspec:DF [(float_extend:DF 2440 (match_operand:SF 1 "register_operand" "0"))] 2))] 2441 "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" 2442 "fcos") 2443 2444;;- one complement instructions 2445 2446(define_insn "one_cmplsi2" 2447 [(set (match_operand:SI 0 "general_operand" "=rm") 2448 (not:SI (match_operand:SI 1 "general_operand" "0")))] 2449 "" 2450 "not%L0 %0") 2451 2452(define_insn "one_cmplhi2" 2453 [(set (match_operand:HI 0 "general_operand" "=rm") 2454 (not:HI (match_operand:HI 1 "general_operand" "0")))] 2455 "" 2456 "not%W0 %0") 2457 2458(define_insn "one_cmplqi2" 2459 [(set (match_operand:QI 0 "general_operand" "=qm") 2460 (not:QI (match_operand:QI 1 "general_operand" "0")))] 2461 "" 2462 "not%B0 %0") 2463 2464;;- arithmetic shift instructions 2465 2466;; DImode shifts are implemented using the i386 "shift double" opcode, 2467;; which is written as "sh[lr]d[lw] imm,reg,reg/mem". If the shift count 2468;; is variable, then the count is in %cl and the "imm" operand is dropped 2469;; from the assembler input. 2470 2471;; This instruction shifts the target reg/mem as usual, but instead of 2472;; shifting in zeros, bits are shifted in from reg operand. If the insn 2473;; is a left shift double, bits are taken from the high order bits of 2474;; reg, else if the insn is a shift right double, bits are taken from the 2475;; low order bits of reg. So if %eax is "1234" and %edx is "5678", 2476;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345". 2477 2478;; Since sh[lr]d does not change the `reg' operand, that is done 2479;; separately, making all shifts emit pairs of shift double and normal 2480;; shift. Since sh[lr]d does not shift more than 31 bits, and we wish to 2481;; support a 63 bit shift, each shift where the count is in a reg expands 2482;; to three pairs. If the overall shift is by N bits, then the first two 2483;; pairs shift by N / 2 and the last pair by N & 1. 2484 2485;; If the shift count is a constant, we need never emit more than one 2486;; shift pair, instead using moves and sign extension for counts greater 2487;; than 31. 2488 2489(define_expand "ashldi3" 2490 [(set (match_operand:DI 0 "register_operand" "") 2491 (ashift:DI (match_operand:DI 1 "register_operand" "") 2492 (match_operand:QI 2 "nonmemory_operand" "")))] 2493 "" 2494 " 2495{ 2496 if (GET_CODE (operands[2]) != CONST_INT 2497 || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')) 2498 { 2499 operands[2] = copy_to_mode_reg (QImode, operands[2]); 2500 emit_insn (gen_ashldi3_non_const_int (operands[0], operands[1], 2501 operands[2])); 2502 } 2503 else 2504 emit_insn (gen_ashldi3_const_int (operands[0], operands[1], operands[2])); 2505 2506 DONE; 2507}") 2508 2509(define_insn "ashldi3_const_int" 2510 [(set (match_operand:DI 0 "register_operand" "=&r") 2511 (ashift:DI (match_operand:DI 1 "register_operand" "0") 2512 (match_operand:QI 2 "const_int_operand" "J")))] 2513 "" 2514 "* 2515{ 2516 rtx xops[4], low[1], high[1]; 2517 2518 CC_STATUS_INIT; 2519 2520 split_di (operands, 1, low, high); 2521 xops[0] = operands[2]; 2522 xops[1] = const1_rtx; 2523 xops[2] = low[0]; 2524 xops[3] = high[0]; 2525 2526 if (INTVAL (xops[0]) > 31) 2527 { 2528 output_asm_insn (AS2 (mov%L3,%2,%3), xops); /* Fast shift by 32 */ 2529 output_asm_insn (AS2 (xor%L2,%2,%2), xops); 2530 2531 if (INTVAL (xops[0]) > 32) 2532 { 2533 xops[0] = GEN_INT (INTVAL (xops[0]) - 32); 2534 output_asm_insn (AS2 (sal%L3,%0,%3), xops); /* Remaining shift */ 2535 } 2536 } 2537 else 2538 { 2539 output_asm_insn (AS3 (shld%L3,%0,%2,%3), xops); 2540 output_asm_insn (AS2 (sal%L2,%0,%2), xops); 2541 } 2542 RET; 2543}") 2544 2545(define_insn "ashldi3_non_const_int" 2546 [(set (match_operand:DI 0 "register_operand" "=&r") 2547 (ashift:DI (match_operand:DI 1 "register_operand" "0") 2548 (match_operand:QI 2 "register_operand" "c"))) 2549 (clobber (match_dup 2))] 2550 "" 2551 "* 2552{ 2553 rtx xops[4], low[1], high[1]; 2554 2555 CC_STATUS_INIT; 2556 2557 split_di (operands, 1, low, high); 2558 xops[0] = operands[2]; 2559 xops[1] = const1_rtx; 2560 xops[2] = low[0]; 2561 xops[3] = high[0]; 2562 2563 output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */ 2564 2565 output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops); 2566 output_asm_insn (AS2 (sal%L2,%0,%2), xops); 2567 output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops); 2568 output_asm_insn (AS2 (sal%L2,%0,%2), xops); 2569 2570 xops[1] = GEN_INT (7); /* shift count & 1 */ 2571 2572 output_asm_insn (AS2 (shr%B0,%1,%0), xops); 2573 2574 output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops); 2575 output_asm_insn (AS2 (sal%L2,%0,%2), xops); 2576 2577 RET; 2578}") 2579 2580;; On i386 and i486, "addl reg,reg" is faster than "sall $1,reg" 2581;; On i486, movl/sall appears slightly faster than leal, but the leal 2582;; is smaller - use leal for now unless the shift count is 1. 2583 2584(define_insn "ashlsi3" 2585 [(set (match_operand:SI 0 "general_operand" "=r,rm") 2586 (ashift:SI (match_operand:SI 1 "general_operand" "r,0") 2587 (match_operand:SI 2 "nonmemory_operand" "M,cI")))] 2588 "" 2589 "* 2590{ 2591 if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1])) 2592 { 2593 if (TARGET_486 && INTVAL (operands[2]) == 1) 2594 { 2595 output_asm_insn (AS2 (mov%L0,%1,%0), operands); 2596 return AS2 (add%L0,%1,%0); 2597 } 2598 else 2599 { 2600 CC_STATUS_INIT; 2601 2602 if (operands[1] == stack_pointer_rtx) 2603 { 2604 output_asm_insn (AS2 (mov%L0,%1,%0), operands); 2605 operands[1] = operands[0]; 2606 } 2607 operands[1] = gen_rtx (MULT, SImode, operands[1], 2608 GEN_INT (1 << INTVAL (operands[2]))); 2609 return AS2 (lea%L0,%a1,%0); 2610 } 2611 } 2612 2613 if (REG_P (operands[2])) 2614 return AS2 (sal%L0,%b2,%0); 2615 2616 if (REG_P (operands[0]) && operands[2] == const1_rtx) 2617 return AS2 (add%L0,%0,%0); 2618 2619 return AS2 (sal%L0,%2,%0); 2620}") 2621 2622(define_insn "ashlhi3" 2623 [(set (match_operand:HI 0 "general_operand" "=rm") 2624 (ashift:HI (match_operand:HI 1 "general_operand" "0") 2625 (match_operand:HI 2 "nonmemory_operand" "cI")))] 2626 "" 2627 "* 2628{ 2629 if (REG_P (operands[2])) 2630 return AS2 (sal%W0,%b2,%0); 2631 2632 if (REG_P (operands[0]) && operands[2] == const1_rtx) 2633 return AS2 (add%W0,%0,%0); 2634 2635 return AS2 (sal%W0,%2,%0); 2636}") 2637 2638(define_insn "ashlqi3" 2639 [(set (match_operand:QI 0 "general_operand" "=qm") 2640 (ashift:QI (match_operand:QI 1 "general_operand" "0") 2641 (match_operand:QI 2 "nonmemory_operand" "cI")))] 2642 "" 2643 "* 2644{ 2645 if (REG_P (operands[2])) 2646 return AS2 (sal%B0,%b2,%0); 2647 2648 if (REG_P (operands[0]) && operands[2] == const1_rtx) 2649 return AS2 (add%B0,%0,%0); 2650 2651 return AS2 (sal%B0,%2,%0); 2652}") 2653 2654;; See comment above `ashldi3' about how this works. 2655 2656(define_expand "ashrdi3" 2657 [(set (match_operand:DI 0 "register_operand" "") 2658 (ashiftrt:DI (match_operand:DI 1 "register_operand" "") 2659 (match_operand:QI 2 "nonmemory_operand" "")))] 2660 "" 2661 " 2662{ 2663 if (GET_CODE (operands[2]) != CONST_INT 2664 || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')) 2665 { 2666 operands[2] = copy_to_mode_reg (QImode, operands[2]); 2667 emit_insn (gen_ashrdi3_non_const_int (operands[0], operands[1], 2668 operands[2])); 2669 } 2670 else 2671 emit_insn (gen_ashrdi3_const_int (operands[0], operands[1], operands[2])); 2672 2673 DONE; 2674}") 2675 2676(define_insn "ashrdi3_const_int" 2677 [(set (match_operand:DI 0 "register_operand" "=&r") 2678 (ashiftrt:DI (match_operand:DI 1 "register_operand" "0") 2679 (match_operand:QI 2 "const_int_operand" "J")))] 2680 "" 2681 "* 2682{ 2683 rtx xops[4], low[1], high[1]; 2684 2685 CC_STATUS_INIT; 2686 2687 split_di (operands, 1, low, high); 2688 xops[0] = operands[2]; 2689 xops[1] = const1_rtx; 2690 xops[2] = low[0]; 2691 xops[3] = high[0]; 2692 2693 if (INTVAL (xops[0]) > 31) 2694 { 2695 xops[1] = GEN_INT (31); 2696 output_asm_insn (AS2 (mov%L2,%3,%2), xops); 2697 output_asm_insn (AS2 (sar%L3,%1,%3), xops); /* shift by 32 */ 2698 2699 if (INTVAL (xops[0]) > 32) 2700 { 2701 xops[0] = GEN_INT (INTVAL (xops[0]) - 32); 2702 output_asm_insn (AS2 (sar%L2,%0,%2), xops); /* Remaining shift */ 2703 } 2704 } 2705 else 2706 { 2707 output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops); 2708 output_asm_insn (AS2 (sar%L3,%0,%3), xops); 2709 } 2710 2711 RET; 2712}") 2713 2714(define_insn "ashrdi3_non_const_int" 2715 [(set (match_operand:DI 0 "register_operand" "=&r") 2716 (ashiftrt:DI (match_operand:DI 1 "register_operand" "0") 2717 (match_operand:QI 2 "register_operand" "c"))) 2718 (clobber (match_dup 2))] 2719 "" 2720 "* 2721{ 2722 rtx xops[4], low[1], high[1]; 2723 2724 CC_STATUS_INIT; 2725 2726 split_di (operands, 1, low, high); 2727 xops[0] = operands[2]; 2728 xops[1] = const1_rtx; 2729 xops[2] = low[0]; 2730 xops[3] = high[0]; 2731 2732 output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */ 2733 2734 output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); 2735 output_asm_insn (AS2 (sar%L3,%0,%3), xops); 2736 output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); 2737 output_asm_insn (AS2 (sar%L3,%0,%3), xops); 2738 2739 xops[1] = GEN_INT (7); /* shift count & 1 */ 2740 2741 output_asm_insn (AS2 (shr%B0,%1,%0), xops); 2742 2743 output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); 2744 output_asm_insn (AS2 (sar%L3,%0,%3), xops); 2745 2746 RET; 2747}") 2748 2749(define_insn "ashrsi3" 2750 [(set (match_operand:SI 0 "general_operand" "=rm") 2751 (ashiftrt:SI (match_operand:SI 1 "general_operand" "0") 2752 (match_operand:SI 2 "nonmemory_operand" "cI")))] 2753 "" 2754 "* 2755{ 2756 if (REG_P (operands[2])) 2757 return AS2 (sar%L0,%b2,%0); 2758 else 2759 return AS2 (sar%L0,%2,%0); 2760}") 2761 2762(define_insn "ashrhi3" 2763 [(set (match_operand:HI 0 "general_operand" "=rm") 2764 (ashiftrt:HI (match_operand:HI 1 "general_operand" "0") 2765 (match_operand:HI 2 "nonmemory_operand" "cI")))] 2766 "" 2767 "* 2768{ 2769 if (REG_P (operands[2])) 2770 return AS2 (sar%W0,%b2,%0); 2771 else 2772 return AS2 (sar%W0,%2,%0); 2773}") 2774 2775(define_insn "ashrqi3" 2776 [(set (match_operand:QI 0 "general_operand" "=qm") 2777 (ashiftrt:QI (match_operand:QI 1 "general_operand" "0") 2778 (match_operand:QI 2 "nonmemory_operand" "cI")))] 2779 "" 2780 "* 2781{ 2782 if (REG_P (operands[2])) 2783 return AS2 (sar%B0,%b2,%0); 2784 else 2785 return AS2 (sar%B0,%2,%0); 2786}") 2787 2788;;- logical shift instructions 2789 2790;; See comment above `ashldi3' about how this works. 2791 2792(define_expand "lshrdi3" 2793 [(set (match_operand:DI 0 "register_operand" "") 2794 (lshiftrt:DI (match_operand:DI 1 "register_operand" "") 2795 (match_operand:QI 2 "nonmemory_operand" "")))] 2796 "" 2797 " 2798{ 2799 if (GET_CODE (operands[2]) != CONST_INT 2800 || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')) 2801 { 2802 operands[2] = copy_to_mode_reg (QImode, operands[2]); 2803 emit_insn (gen_lshrdi3_non_const_int (operands[0], operands[1], 2804 operands[2])); 2805 } 2806 else 2807 emit_insn (gen_lshrdi3_const_int (operands[0], operands[1], operands[2])); 2808 2809 DONE; 2810}") 2811 2812(define_insn "lshrdi3_const_int" 2813 [(set (match_operand:DI 0 "register_operand" "=&r") 2814 (lshiftrt:DI (match_operand:DI 1 "register_operand" "0") 2815 (match_operand:QI 2 "const_int_operand" "J")))] 2816 "" 2817 "* 2818{ 2819 rtx xops[4], low[1], high[1]; 2820 2821 CC_STATUS_INIT; 2822 2823 split_di (operands, 1, low, high); 2824 xops[0] = operands[2]; 2825 xops[1] = const1_rtx; 2826 xops[2] = low[0]; 2827 xops[3] = high[0]; 2828 2829 if (INTVAL (xops[0]) > 31) 2830 { 2831 output_asm_insn (AS2 (mov%L2,%3,%2), xops); /* Fast shift by 32 */ 2832 output_asm_insn (AS2 (xor%L3,%3,%3), xops); 2833 2834 if (INTVAL (xops[0]) > 32) 2835 { 2836 xops[0] = GEN_INT (INTVAL (xops[0]) - 32); 2837 output_asm_insn (AS2 (shr%L2,%0,%2), xops); /* Remaining shift */ 2838 } 2839 } 2840 else 2841 { 2842 output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops); 2843 output_asm_insn (AS2 (shr%L3,%0,%3), xops); 2844 } 2845 2846 RET; 2847}") 2848 2849(define_insn "lshrdi3_non_const_int" 2850 [(set (match_operand:DI 0 "register_operand" "=&r") 2851 (lshiftrt:DI (match_operand:DI 1 "register_operand" "0") 2852 (match_operand:QI 2 "register_operand" "c"))) 2853 (clobber (match_dup 2))] 2854 "" 2855 "* 2856{ 2857 rtx xops[4], low[1], high[1]; 2858 2859 CC_STATUS_INIT; 2860 2861 split_di (operands, 1, low, high); 2862 xops[0] = operands[2]; 2863 xops[1] = const1_rtx; 2864 xops[2] = low[0]; 2865 xops[3] = high[0]; 2866 2867 output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */ 2868 2869 output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); 2870 output_asm_insn (AS2 (shr%L3,%0,%3), xops); 2871 output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); 2872 output_asm_insn (AS2 (shr%L3,%0,%3), xops); 2873 2874 xops[1] = GEN_INT (7); /* shift count & 1 */ 2875 2876 output_asm_insn (AS2 (shr%B0,%1,%0), xops); 2877 2878 output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); 2879 output_asm_insn (AS2 (shr%L3,%0,%3), xops); 2880 2881 RET; 2882}") 2883 2884(define_insn "lshrsi3" 2885 [(set (match_operand:SI 0 "general_operand" "=rm") 2886 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0") 2887 (match_operand:SI 2 "nonmemory_operand" "cI")))] 2888 "" 2889 "* 2890{ 2891 if (REG_P (operands[2])) 2892 return AS2 (shr%L0,%b2,%0); 2893 else 2894 return AS2 (shr%L0,%2,%1); 2895}") 2896 2897(define_insn "lshrhi3" 2898 [(set (match_operand:HI 0 "general_operand" "=rm") 2899 (lshiftrt:HI (match_operand:HI 1 "general_operand" "0") 2900 (match_operand:HI 2 "nonmemory_operand" "cI")))] 2901 "" 2902 "* 2903{ 2904 if (REG_P (operands[2])) 2905 return AS2 (shr%W0,%b2,%0); 2906 else 2907 return AS2 (shr%W0,%2,%0); 2908}") 2909 2910(define_insn "lshrqi3" 2911 [(set (match_operand:QI 0 "general_operand" "=qm") 2912 (lshiftrt:QI (match_operand:QI 1 "general_operand" "0") 2913 (match_operand:QI 2 "nonmemory_operand" "cI")))] 2914 "" 2915 "* 2916{ 2917 if (REG_P (operands[2])) 2918 return AS2 (shr%B0,%b2,%0); 2919 else 2920 return AS2 (shr%B0,%2,%0); 2921}") 2922 2923;;- rotate instructions 2924 2925(define_insn "rotlsi3" 2926 [(set (match_operand:SI 0 "general_operand" "=rm") 2927 (rotate:SI (match_operand:SI 1 "general_operand" "0") 2928 (match_operand:SI 2 "nonmemory_operand" "cI")))] 2929 "" 2930 "* 2931{ 2932 if (REG_P (operands[2])) 2933 return AS2 (rol%L0,%b2,%0); 2934 else 2935 return AS2 (rol%L0,%2,%0); 2936}") 2937 2938(define_insn "rotlhi3" 2939 [(set (match_operand:HI 0 "general_operand" "=rm") 2940 (rotate:HI (match_operand:HI 1 "general_operand" "0") 2941 (match_operand:HI 2 "nonmemory_operand" "cI")))] 2942 "" 2943 "* 2944{ 2945 if (REG_P (operands[2])) 2946 return AS2 (rol%W0,%b2,%0); 2947 else 2948 return AS2 (rol%W0,%2,%0); 2949}") 2950 2951(define_insn "rotlqi3" 2952 [(set (match_operand:QI 0 "general_operand" "=qm") 2953 (rotate:QI (match_operand:QI 1 "general_operand" "0") 2954 (match_operand:QI 2 "nonmemory_operand" "cI")))] 2955 "" 2956 "* 2957{ 2958 if (REG_P (operands[2])) 2959 return AS2 (rol%B0,%b2,%0); 2960 else 2961 return AS2 (rol%B0,%2,%0); 2962}") 2963 2964(define_insn "rotrsi3" 2965 [(set (match_operand:SI 0 "general_operand" "=rm") 2966 (rotatert:SI (match_operand:SI 1 "general_operand" "0") 2967 (match_operand:SI 2 "nonmemory_operand" "cI")))] 2968 "" 2969 "* 2970{ 2971 if (REG_P (operands[2])) 2972 return AS2 (ror%L0,%b2,%0); 2973 else 2974 return AS2 (ror%L0,%2,%0); 2975}") 2976 2977(define_insn "rotrhi3" 2978 [(set (match_operand:HI 0 "general_operand" "=rm") 2979 (rotatert:HI (match_operand:HI 1 "general_operand" "0") 2980 (match_operand:HI 2 "nonmemory_operand" "cI")))] 2981 "" 2982 "* 2983{ 2984 if (REG_P (operands[2])) 2985 return AS2 (ror%W0,%b2,%0); 2986 else 2987 return AS2 (ror%W0,%2,%0); 2988}") 2989 2990(define_insn "rotrqi3" 2991 [(set (match_operand:QI 0 "general_operand" "=qm") 2992 (rotatert:QI (match_operand:QI 1 "general_operand" "0") 2993 (match_operand:QI 2 "nonmemory_operand" "cI")))] 2994 "" 2995 "* 2996{ 2997 if (REG_P (operands[2])) 2998 return AS2 (ror%B0,%b2,%0); 2999 else 3000 return AS2 (ror%B0,%2,%0); 3001}") 3002 3003/* 3004;; This usually looses. But try a define_expand to recognize a few case 3005;; we can do efficiently, such as accessing the "high" QImode registers, 3006;; %ah, %bh, %ch, %dh. 3007(define_insn "insv" 3008 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+&r") 3009 (match_operand:SI 1 "general_operand" "i") 3010 (match_operand:SI 2 "general_operand" "i")) 3011 (match_operand:SI 3 "general_operand" "ri"))] 3012 "" 3013 "* 3014{ 3015 if (INTVAL (operands[1]) + INTVAL (operands[2]) > GET_MODE_BITSIZE (SImode)) 3016 abort (); 3017 if (GET_CODE (operands[3]) == CONST_INT) 3018 { 3019 unsigned int mask = (1 << INTVAL (operands[1])) - 1; 3020 operands[1] = GEN_INT (~(mask << INTVAL (operands[2]))); 3021 output_asm_insn (AS2 (and%L0,%1,%0), operands); 3022 operands[3] = GEN_INT (INTVAL (operands[3]) << INTVAL (operands[2])); 3023 output_asm_insn (AS2 (or%L0,%3,%0), operands); 3024 } 3025 else 3026 { 3027 operands[0] = gen_rtx (REG, SImode, REGNO (operands[0])); 3028 if (INTVAL (operands[2])) 3029 output_asm_insn (AS2 (ror%L0,%2,%0), operands); 3030 output_asm_insn (AS3 (shrd%L0,%1,%3,%0), operands); 3031 operands[2] = GEN_INT (BITS_PER_WORD 3032 - INTVAL (operands[1]) - INTVAL (operands[2])); 3033 if (INTVAL (operands[2])) 3034 output_asm_insn (AS2 (ror%L0,%2,%0), operands); 3035 } 3036 RET; 3037}") 3038*/ 3039/* 3040;; ??? There are problems with the mode of operand[3]. The point of this 3041;; is to represent an HImode move to a "high byte" register. 3042 3043(define_expand "insv" 3044 [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "") 3045 (match_operand:SI 1 "immediate_operand" "") 3046 (match_operand:SI 2 "immediate_operand" "")) 3047 (match_operand:QI 3 "general_operand" "ri"))] 3048 "" 3049 " 3050{ 3051 if (GET_CODE (operands[1]) != CONST_INT 3052 || GET_CODE (operands[2]) != CONST_INT) 3053 FAIL; 3054 3055 if (! (INTVAL (operands[1]) == 8 3056 && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 0)) 3057 && ! INTVAL (operands[1]) == 1) 3058 FAIL; 3059}") 3060 3061;; ??? Are these constraints right? 3062(define_insn "" 3063 [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+&qo") 3064 (const_int 8) 3065 (const_int 8)) 3066 (match_operand:QI 1 "general_operand" "qn"))] 3067 "" 3068 "* 3069{ 3070 if (REG_P (operands[0])) 3071 return AS2 (mov%B0,%1,%h0); 3072 3073 operands[0] = adj_offsettable_operand (operands[0], 1); 3074 return AS2 (mov%B0,%1,%0); 3075}") 3076*/ 3077 3078;; On i386, the register count for a bit operation is *not* truncated, 3079;; so SHIFT_COUNT_TRUNCATED must not be defined. 3080 3081;; On i486, the shift & or/and code is faster than bts or btr. If 3082;; operands[0] is a MEM, the bt[sr] is half as fast as the normal code. 3083 3084;; On i386, bts is a little faster if operands[0] is a reg, and a 3085;; little slower if operands[0] is a MEM, than the shift & or/and code. 3086;; Use bts & btr, since they reload better. 3087 3088;; General bit set and clear. 3089(define_insn "" 3090 [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+rm") 3091 (const_int 1) 3092 (match_operand:SI 2 "general_operand" "r")) 3093 (match_operand:SI 3 "const_int_operand" "n"))] 3094 "! TARGET_486 && GET_CODE (operands[2]) != CONST_INT" 3095 "* 3096{ 3097 CC_STATUS_INIT; 3098 3099 if (INTVAL (operands[3]) == 1) 3100 return AS2 (bts%L0,%2,%0); 3101 else 3102 return AS2 (btr%L0,%2,%0); 3103}") 3104 3105;; Bit complement. See comments on previous pattern. 3106;; ??? Is this really worthwhile? 3107(define_insn "" 3108 [(set (match_operand:SI 0 "general_operand" "=rm") 3109 (xor:SI (ashift:SI (const_int 1) 3110 (match_operand:SI 1 "general_operand" "r")) 3111 (match_operand:SI 2 "general_operand" "0")))] 3112 "! TARGET_486 && GET_CODE (operands[1]) != CONST_INT" 3113 "* 3114{ 3115 CC_STATUS_INIT; 3116 3117 return AS2 (btc%L0,%1,%0); 3118}") 3119 3120(define_insn "" 3121 [(set (match_operand:SI 0 "general_operand" "=rm") 3122 (xor:SI (match_operand:SI 1 "general_operand" "0") 3123 (ashift:SI (const_int 1) 3124 (match_operand:SI 2 "general_operand" "r"))))] 3125 "! TARGET_486 && GET_CODE (operands[2]) != CONST_INT" 3126 "* 3127{ 3128 CC_STATUS_INIT; 3129 3130 return AS2 (btc%L0,%2,%0); 3131}") 3132 3133;; Recognizers for bit-test instructions. 3134 3135;; The bt opcode allows a MEM in operands[0]. But on both i386 and 3136;; i486, it is faster to copy a MEM to REG and then use bt, than to use 3137;; bt on the MEM directly. 3138 3139;; ??? The first argument of a zero_extract must not be reloaded, so 3140;; don't allow a MEM in the operand predicate without allowing it in the 3141;; constraint. 3142 3143(define_insn "" 3144 [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r") 3145 (const_int 1) 3146 (match_operand:SI 1 "general_operand" "r")))] 3147 "GET_CODE (operands[1]) != CONST_INT" 3148 "* 3149{ 3150 cc_status.flags |= CC_Z_IN_NOT_C; 3151 return AS2 (bt%L0,%1,%0); 3152}") 3153 3154(define_insn "" 3155 [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r") 3156 (match_operand:SI 1 "const_int_operand" "n") 3157 (match_operand:SI 2 "const_int_operand" "n")))] 3158 "" 3159 "* 3160{ 3161 unsigned int mask; 3162 3163 mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]); 3164 operands[1] = GEN_INT (mask); 3165 3166 if (QI_REG_P (operands[0])) 3167 { 3168 if ((mask & ~0xff) == 0) 3169 { 3170 cc_status.flags |= CC_NOT_NEGATIVE; 3171 return AS2 (test%B0,%1,%b0); 3172 } 3173 3174 if ((mask & ~0xff00) == 0) 3175 { 3176 cc_status.flags |= CC_NOT_NEGATIVE; 3177 operands[1] = GEN_INT (mask >> 8); 3178 return AS2 (test%B0,%1,%h0); 3179 } 3180 } 3181 3182 return AS2 (test%L0,%1,%0); 3183}") 3184 3185;; ??? All bets are off if operand 0 is a volatile MEM reference. 3186;; The CPU may access unspecified bytes around the actual target byte. 3187 3188(define_insn "" 3189 [(set (cc0) (zero_extract (match_operand:QI 0 "general_operand" "rm") 3190 (match_operand:SI 1 "const_int_operand" "n") 3191 (match_operand:SI 2 "const_int_operand" "n")))] 3192 "GET_CODE (operands[0]) != MEM || ! MEM_VOLATILE_P (operands[0])" 3193 "* 3194{ 3195 unsigned int mask; 3196 3197 mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]); 3198 operands[1] = GEN_INT (mask); 3199 3200 if (! REG_P (operands[0]) || QI_REG_P (operands[0])) 3201 { 3202 if ((mask & ~0xff) == 0) 3203 { 3204 cc_status.flags |= CC_NOT_NEGATIVE; 3205 return AS2 (test%B0,%1,%b0); 3206 } 3207 3208 if ((mask & ~0xff00) == 0) 3209 { 3210 cc_status.flags |= CC_NOT_NEGATIVE; 3211 operands[1] = GEN_INT (mask >> 8); 3212 3213 if (QI_REG_P (operands[0])) 3214 return AS2 (test%B0,%1,%h0); 3215 else 3216 { 3217 operands[0] = adj_offsettable_operand (operands[0], 1); 3218 return AS2 (test%B0,%1,%b0); 3219 } 3220 } 3221 3222 if (GET_CODE (operands[0]) == MEM && (mask & ~0xff0000) == 0) 3223 { 3224 cc_status.flags |= CC_NOT_NEGATIVE; 3225 operands[1] = GEN_INT (mask >> 16); 3226 operands[0] = adj_offsettable_operand (operands[0], 2); 3227 return AS2 (test%B0,%1,%b0); 3228 } 3229 3230 if (GET_CODE (operands[0]) == MEM && (mask & ~0xff000000) == 0) 3231 { 3232 cc_status.flags |= CC_NOT_NEGATIVE; 3233 operands[1] = GEN_INT (mask >> 24); 3234 operands[0] = adj_offsettable_operand (operands[0], 3); 3235 return AS2 (test%B0,%1,%b0); 3236 } 3237 } 3238 3239 if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) 3240 return AS2 (test%L0,%1,%0); 3241 3242 return AS2 (test%L1,%0,%1); 3243}") 3244 3245;; Store-flag instructions. 3246 3247;; For all sCOND expanders, also expand the compare or test insn that 3248;; generates cc0. Generate an equality comparison if `seq' or `sne'. 3249 3250;; The 386 sCOND opcodes can write to memory. But a gcc sCOND insn may 3251;; not have any input reloads. A MEM write might need an input reload 3252;; for the address of the MEM. So don't allow MEM as the SET_DEST. 3253 3254(define_expand "seq" 3255 [(match_dup 1) 3256 (set (match_operand:QI 0 "register_operand" "") 3257 (eq:QI (cc0) (const_int 0)))] 3258 "" 3259 " 3260{ 3261 if (TARGET_IEEE_FP 3262 && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT) 3263 operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1); 3264 else 3265 operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1); 3266}") 3267 3268(define_insn "" 3269 [(set (match_operand:QI 0 "register_operand" "=q") 3270 (eq:QI (cc0) (const_int 0)))] 3271 "" 3272 "* 3273{ 3274 if (cc_prev_status.flags & CC_Z_IN_NOT_C) 3275 return AS1 (setnb,%0); 3276 else 3277 return AS1 (sete,%0); 3278}") 3279 3280(define_expand "sne" 3281 [(match_dup 1) 3282 (set (match_operand:QI 0 "register_operand" "") 3283 (ne:QI (cc0) (const_int 0)))] 3284 "" 3285 " 3286{ 3287 if (TARGET_IEEE_FP 3288 && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT) 3289 operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1); 3290 else 3291 operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1); 3292}") 3293 3294(define_insn "" 3295 [(set (match_operand:QI 0 "register_operand" "=q") 3296 (ne:QI (cc0) (const_int 0)))] 3297 "" 3298 "* 3299{ 3300 if (cc_prev_status.flags & CC_Z_IN_NOT_C) 3301 return AS1 (setb,%0); 3302 else 3303 return AS1 (setne,%0); 3304} 3305") 3306 3307(define_expand "sgt" 3308 [(match_dup 1) 3309 (set (match_operand:QI 0 "register_operand" "") 3310 (gt:QI (cc0) (const_int 0)))] 3311 "" 3312 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 3313 3314(define_insn "" 3315 [(set (match_operand:QI 0 "register_operand" "=q") 3316 (gt:QI (cc0) (const_int 0)))] 3317 "" 3318 "* 3319{ 3320 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 3321 return AS1 (sete,%0); 3322 3323 OUTPUT_JUMP (\"setg %0\", \"seta %0\", NULL_PTR); 3324}") 3325 3326(define_expand "sgtu" 3327 [(match_dup 1) 3328 (set (match_operand:QI 0 "register_operand" "") 3329 (gtu:QI (cc0) (const_int 0)))] 3330 "" 3331 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 3332 3333(define_insn "" 3334 [(set (match_operand:QI 0 "register_operand" "=q") 3335 (gtu:QI (cc0) (const_int 0)))] 3336 "" 3337 "* return \"seta %0\"; ") 3338 3339(define_expand "slt" 3340 [(match_dup 1) 3341 (set (match_operand:QI 0 "register_operand" "") 3342 (lt:QI (cc0) (const_int 0)))] 3343 "" 3344 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 3345 3346(define_insn "" 3347 [(set (match_operand:QI 0 "register_operand" "=q") 3348 (lt:QI (cc0) (const_int 0)))] 3349 "" 3350 "* 3351{ 3352 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 3353 return AS1 (sete,%0); 3354 3355 OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\"); 3356}") 3357 3358(define_expand "sltu" 3359 [(match_dup 1) 3360 (set (match_operand:QI 0 "register_operand" "") 3361 (ltu:QI (cc0) (const_int 0)))] 3362 "" 3363 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 3364 3365(define_insn "" 3366 [(set (match_operand:QI 0 "register_operand" "=q") 3367 (ltu:QI (cc0) (const_int 0)))] 3368 "" 3369 "* return \"setb %0\"; ") 3370 3371(define_expand "sge" 3372 [(match_dup 1) 3373 (set (match_operand:QI 0 "register_operand" "") 3374 (ge:QI (cc0) (const_int 0)))] 3375 "" 3376 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 3377 3378(define_insn "" 3379 [(set (match_operand:QI 0 "register_operand" "=q") 3380 (ge:QI (cc0) (const_int 0)))] 3381 "" 3382 "* 3383{ 3384 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 3385 return AS1 (sete,%0); 3386 3387 OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\"); 3388}") 3389 3390(define_expand "sgeu" 3391 [(match_dup 1) 3392 (set (match_operand:QI 0 "register_operand" "") 3393 (geu:QI (cc0) (const_int 0)))] 3394 "" 3395 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 3396 3397(define_insn "" 3398 [(set (match_operand:QI 0 "register_operand" "=q") 3399 (geu:QI (cc0) (const_int 0)))] 3400 "" 3401 "* return \"setae %0\"; ") 3402 3403(define_expand "sle" 3404 [(match_dup 1) 3405 (set (match_operand:QI 0 "register_operand" "") 3406 (le:QI (cc0) (const_int 0)))] 3407 "" 3408 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 3409 3410(define_insn "" 3411 [(set (match_operand:QI 0 "register_operand" "=q") 3412 (le:QI (cc0) (const_int 0)))] 3413 "" 3414 "* 3415{ 3416 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 3417 return AS1 (setb,%0); 3418 3419 OUTPUT_JUMP (\"setle %0\", \"setbe %0\", NULL_PTR); 3420}") 3421 3422(define_expand "sleu" 3423 [(match_dup 1) 3424 (set (match_operand:QI 0 "register_operand" "") 3425 (leu:QI (cc0) (const_int 0)))] 3426 "" 3427 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 3428 3429(define_insn "" 3430 [(set (match_operand:QI 0 "register_operand" "=q") 3431 (leu:QI (cc0) (const_int 0)))] 3432 "" 3433 "* return \"setbe %0\"; ") 3434 3435;; Basic conditional jump instructions. 3436;; We ignore the overflow flag for signed branch instructions. 3437 3438;; For all bCOND expanders, also expand the compare or test insn that 3439;; generates cc0. Generate an equality comparison if `beq' or `bne'. 3440 3441(define_expand "beq" 3442 [(match_dup 1) 3443 (set (pc) 3444 (if_then_else (eq (cc0) 3445 (const_int 0)) 3446 (label_ref (match_operand 0 "" "")) 3447 (pc)))] 3448 "" 3449 " 3450{ 3451 if (TARGET_IEEE_FP 3452 && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT) 3453 operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1); 3454 else 3455 operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1); 3456}") 3457 3458(define_insn "" 3459 [(set (pc) 3460 (if_then_else (eq (cc0) 3461 (const_int 0)) 3462 (label_ref (match_operand 0 "" "")) 3463 (pc)))] 3464 "" 3465 "* 3466{ 3467 if (cc_prev_status.flags & CC_Z_IN_NOT_C) 3468 return \"jnc %l0\"; 3469 else 3470 return \"je %l0\"; 3471}") 3472 3473(define_expand "bne" 3474 [(match_dup 1) 3475 (set (pc) 3476 (if_then_else (ne (cc0) 3477 (const_int 0)) 3478 (label_ref (match_operand 0 "" "")) 3479 (pc)))] 3480 "" 3481 " 3482{ 3483 if (TARGET_IEEE_FP 3484 && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT) 3485 operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1); 3486 else 3487 operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1); 3488}") 3489 3490(define_insn "" 3491 [(set (pc) 3492 (if_then_else (ne (cc0) 3493 (const_int 0)) 3494 (label_ref (match_operand 0 "" "")) 3495 (pc)))] 3496 "" 3497 "* 3498{ 3499 if (cc_prev_status.flags & CC_Z_IN_NOT_C) 3500 return \"jc %l0\"; 3501 else 3502 return \"jne %l0\"; 3503}") 3504 3505(define_expand "bgt" 3506 [(match_dup 1) 3507 (set (pc) 3508 (if_then_else (gt (cc0) 3509 (const_int 0)) 3510 (label_ref (match_operand 0 "" "")) 3511 (pc)))] 3512 "" 3513 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 3514 3515(define_insn "" 3516 [(set (pc) 3517 (if_then_else (gt (cc0) 3518 (const_int 0)) 3519 (label_ref (match_operand 0 "" "")) 3520 (pc)))] 3521 "" 3522 "* 3523{ 3524 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 3525 return AS1 (je,%l0); 3526 3527 OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR); 3528}") 3529 3530(define_expand "bgtu" 3531 [(match_dup 1) 3532 (set (pc) 3533 (if_then_else (gtu (cc0) 3534 (const_int 0)) 3535 (label_ref (match_operand 0 "" "")) 3536 (pc)))] 3537 "" 3538 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 3539 3540(define_insn "" 3541 [(set (pc) 3542 (if_then_else (gtu (cc0) 3543 (const_int 0)) 3544 (label_ref (match_operand 0 "" "")) 3545 (pc)))] 3546 "" 3547 "ja %l0") 3548 3549(define_expand "blt" 3550 [(match_dup 1) 3551 (set (pc) 3552 (if_then_else (lt (cc0) 3553 (const_int 0)) 3554 (label_ref (match_operand 0 "" "")) 3555 (pc)))] 3556 "" 3557 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 3558 3559(define_insn "" 3560 [(set (pc) 3561 (if_then_else (lt (cc0) 3562 (const_int 0)) 3563 (label_ref (match_operand 0 "" "")) 3564 (pc)))] 3565 "" 3566 "* 3567{ 3568 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 3569 return AS1 (je,%l0); 3570 3571 OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\"); 3572}") 3573 3574(define_expand "bltu" 3575 [(match_dup 1) 3576 (set (pc) 3577 (if_then_else (ltu (cc0) 3578 (const_int 0)) 3579 (label_ref (match_operand 0 "" "")) 3580 (pc)))] 3581 "" 3582 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 3583 3584(define_insn "" 3585 [(set (pc) 3586 (if_then_else (ltu (cc0) 3587 (const_int 0)) 3588 (label_ref (match_operand 0 "" "")) 3589 (pc)))] 3590 "" 3591 "jb %l0") 3592 3593(define_expand "bge" 3594 [(match_dup 1) 3595 (set (pc) 3596 (if_then_else (ge (cc0) 3597 (const_int 0)) 3598 (label_ref (match_operand 0 "" "")) 3599 (pc)))] 3600 "" 3601 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 3602 3603(define_insn "" 3604 [(set (pc) 3605 (if_then_else (ge (cc0) 3606 (const_int 0)) 3607 (label_ref (match_operand 0 "" "")) 3608 (pc)))] 3609 "" 3610 "* 3611{ 3612 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 3613 return AS1 (je,%l0); 3614 3615 OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\"); 3616}") 3617 3618(define_expand "bgeu" 3619 [(match_dup 1) 3620 (set (pc) 3621 (if_then_else (geu (cc0) 3622 (const_int 0)) 3623 (label_ref (match_operand 0 "" "")) 3624 (pc)))] 3625 "" 3626 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 3627 3628(define_insn "" 3629 [(set (pc) 3630 (if_then_else (geu (cc0) 3631 (const_int 0)) 3632 (label_ref (match_operand 0 "" "")) 3633 (pc)))] 3634 "" 3635 "jae %l0") 3636 3637(define_expand "ble" 3638 [(match_dup 1) 3639 (set (pc) 3640 (if_then_else (le (cc0) 3641 (const_int 0)) 3642 (label_ref (match_operand 0 "" "")) 3643 (pc)))] 3644 "" 3645 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 3646 3647(define_insn "" 3648 [(set (pc) 3649 (if_then_else (le (cc0) 3650 (const_int 0)) 3651 (label_ref (match_operand 0 "" "")) 3652 (pc)))] 3653 "" 3654 "* 3655{ 3656 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 3657 return AS1 (jb,%l0); 3658 3659 OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR); 3660}") 3661 3662(define_expand "bleu" 3663 [(match_dup 1) 3664 (set (pc) 3665 (if_then_else (leu (cc0) 3666 (const_int 0)) 3667 (label_ref (match_operand 0 "" "")) 3668 (pc)))] 3669 "" 3670 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 3671 3672(define_insn "" 3673 [(set (pc) 3674 (if_then_else (leu (cc0) 3675 (const_int 0)) 3676 (label_ref (match_operand 0 "" "")) 3677 (pc)))] 3678 "" 3679 "jbe %l0") 3680 3681;; Negated conditional jump instructions. 3682 3683(define_insn "" 3684 [(set (pc) 3685 (if_then_else (eq (cc0) 3686 (const_int 0)) 3687 (pc) 3688 (label_ref (match_operand 0 "" ""))))] 3689 "" 3690 "* 3691{ 3692 if (cc_prev_status.flags & CC_Z_IN_NOT_C) 3693 return \"jc %l0\"; 3694 else 3695 return \"jne %l0\"; 3696}") 3697 3698(define_insn "" 3699 [(set (pc) 3700 (if_then_else (ne (cc0) 3701 (const_int 0)) 3702 (pc) 3703 (label_ref (match_operand 0 "" ""))))] 3704 "" 3705 "* 3706{ 3707 if (cc_prev_status.flags & CC_Z_IN_NOT_C) 3708 return \"jnc %l0\"; 3709 else 3710 return \"je %l0\"; 3711}") 3712 3713(define_insn "" 3714 [(set (pc) 3715 (if_then_else (gt (cc0) 3716 (const_int 0)) 3717 (pc) 3718 (label_ref (match_operand 0 "" ""))))] 3719 "" 3720 "* 3721{ 3722 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 3723 return AS1 (jne,%l0); 3724 3725 OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR); 3726}") 3727 3728(define_insn "" 3729 [(set (pc) 3730 (if_then_else (gtu (cc0) 3731 (const_int 0)) 3732 (pc) 3733 (label_ref (match_operand 0 "" ""))))] 3734 "" 3735 "jbe %l0") 3736 3737(define_insn "" 3738 [(set (pc) 3739 (if_then_else (lt (cc0) 3740 (const_int 0)) 3741 (pc) 3742 (label_ref (match_operand 0 "" ""))))] 3743 "" 3744 "* 3745{ 3746 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 3747 return AS1 (jne,%l0); 3748 3749 OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\"); 3750}") 3751 3752(define_insn "" 3753 [(set (pc) 3754 (if_then_else (ltu (cc0) 3755 (const_int 0)) 3756 (pc) 3757 (label_ref (match_operand 0 "" ""))))] 3758 "" 3759 "jae %l0") 3760 3761(define_insn "" 3762 [(set (pc) 3763 (if_then_else (ge (cc0) 3764 (const_int 0)) 3765 (pc) 3766 (label_ref (match_operand 0 "" ""))))] 3767 "" 3768 "* 3769{ 3770 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 3771 return AS1 (jne,%l0); 3772 3773 OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\"); 3774}") 3775 3776(define_insn "" 3777 [(set (pc) 3778 (if_then_else (geu (cc0) 3779 (const_int 0)) 3780 (pc) 3781 (label_ref (match_operand 0 "" ""))))] 3782 "" 3783 "jb %l0") 3784 3785(define_insn "" 3786 [(set (pc) 3787 (if_then_else (le (cc0) 3788 (const_int 0)) 3789 (pc) 3790 (label_ref (match_operand 0 "" ""))))] 3791 "" 3792 "* 3793{ 3794 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 3795 return AS1 (jae,%l0); 3796 3797 OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR); 3798}") 3799 3800(define_insn "" 3801 [(set (pc) 3802 (if_then_else (leu (cc0) 3803 (const_int 0)) 3804 (pc) 3805 (label_ref (match_operand 0 "" ""))))] 3806 "" 3807 "ja %l0") 3808 3809;; Unconditional and other jump instructions 3810 3811(define_insn "jump" 3812 [(set (pc) 3813 (label_ref (match_operand 0 "" "")))] 3814 "" 3815 "jmp %l0") 3816 3817(define_insn "indirect_jump" 3818 [(set (pc) (match_operand:SI 0 "general_operand" "rm"))] 3819 "" 3820 "* 3821{ 3822 CC_STATUS_INIT; 3823 3824 return AS1 (jmp,%*%0); 3825}") 3826 3827;; Implement switch statements when generating PIC code. Switches are 3828;; implemented by `tablejump' when not using -fpic. 3829 3830;; Emit code here to do the range checking and make the index zero based. 3831 3832(define_expand "casesi" 3833 [(set (match_dup 5) 3834 (minus:SI (match_operand:SI 0 "general_operand" "") 3835 (match_operand:SI 1 "general_operand" ""))) 3836 (set (cc0) 3837 (compare:CC (match_dup 5) 3838 (match_operand:SI 2 "general_operand" ""))) 3839 (set (pc) 3840 (if_then_else (gtu (cc0) 3841 (const_int 0)) 3842 (label_ref (match_operand 4 "" "")) 3843 (pc))) 3844 (parallel 3845 [(set (pc) 3846 (minus:SI (reg:SI 3) 3847 (mem:SI (plus:SI (mult:SI (match_dup 5) 3848 (const_int 4)) 3849 (label_ref (match_operand 3 "" "")))))) 3850 (clobber (match_scratch:SI 6 ""))])] 3851 "flag_pic" 3852 " 3853{ 3854 operands[5] = gen_reg_rtx (SImode); 3855 current_function_uses_pic_offset_table = 1; 3856}") 3857 3858;; Implement a casesi insn. 3859 3860;; Each entry in the "addr_diff_vec" looks like this as the result of the 3861;; two rules below: 3862;; 3863;; .long _GLOBAL_OFFSET_TABLE_+[.-.L2] 3864;; 3865;; 1. An expression involving an external reference may only use the 3866;; addition operator, and only with an assembly-time constant. 3867;; The example above satisfies this because ".-.L2" is a constant. 3868;; 3869;; 2. The symbol _GLOBAL_OFFSET_TABLE_ is magic, and at link time is 3870;; given the value of "GOT - .", where GOT is the actual address of 3871;; the Global Offset Table. Therefore, the .long above actually 3872;; stores the value "( GOT - . ) + [ . - .L2 ]", or "GOT - .L2". The 3873;; expression "GOT - .L2" by itself would generate an error from as(1). 3874;; 3875;; The pattern below emits code that looks like this: 3876;; 3877;; movl %ebx,reg 3878;; subl TABLE@GOTOFF(%ebx,index,4),reg 3879;; jmp reg 3880;; 3881;; The addr_diff_vec contents may be directly referenced with @GOTOFF, since 3882;; the addr_diff_vec is known to be part of this module. 3883;; 3884;; The subl above calculates "GOT - (( GOT - . ) + [ . - .L2 ])", which 3885;; evaluates to just ".L2". 3886 3887(define_insn "" 3888 [(set (pc) 3889 (minus:SI (reg:SI 3) 3890 (mem:SI (plus:SI 3891 (mult:SI (match_operand:SI 0 "register_operand" "r") 3892 (const_int 4)) 3893 (label_ref (match_operand 1 "" "")))))) 3894 (clobber (match_scratch:SI 2 "=&r"))] 3895 "" 3896 "* 3897{ 3898 rtx xops[4]; 3899 3900 xops[0] = operands[0]; 3901 xops[1] = operands[1]; 3902 xops[2] = operands[2]; 3903 xops[3] = pic_offset_table_rtx; 3904 3905 output_asm_insn (AS2 (mov%L2,%3,%2), xops); 3906 output_asm_insn (\"sub%L2 %l1@GOTOFF(%3,%0,4),%2\", xops); 3907 output_asm_insn (AS1 (jmp,%*%2), xops); 3908 ASM_OUTPUT_ALIGN_CODE (asm_out_file); 3909 RET; 3910}") 3911 3912(define_insn "tablejump" 3913 [(set (pc) (match_operand:SI 0 "general_operand" "rm")) 3914 (use (label_ref (match_operand 1 "" "")))] 3915 "" 3916 "* 3917{ 3918 CC_STATUS_INIT; 3919 3920 return AS1 (jmp,%*%0); 3921}") 3922 3923;; Call insns. 3924 3925;; If generating PIC code, the predicate indirect_operand will fail 3926;; for operands[0] containing symbolic references on all of the named 3927;; call* patterns. Each named pattern is followed by an unnamed pattern 3928;; that matches any call to a symbolic CONST (ie, a symbol_ref). The 3929;; unnamed patterns are only used while generating PIC code, because 3930;; otherwise the named patterns match. 3931 3932;; Call subroutine returning no value. 3933 3934(define_expand "call_pop" 3935 [(parallel [(call (match_operand:QI 0 "indirect_operand" "") 3936 (match_operand:SI 1 "general_operand" "")) 3937 (set (reg:SI 7) 3938 (plus:SI (reg:SI 7) 3939 (match_operand:SI 3 "immediate_operand" "")))])] 3940 "" 3941 " 3942{ 3943 rtx addr; 3944 3945 if (flag_pic) 3946 current_function_uses_pic_offset_table = 1; 3947 3948 /* With half-pic, force the address into a register. */ 3949 addr = XEXP (operands[0], 0); 3950 if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) 3951 XEXP (operands[0], 0) = force_reg (Pmode, addr); 3952 3953 if (! expander_call_insn_operand (operands[0], QImode)) 3954 operands[0] 3955 = change_address (operands[0], VOIDmode, 3956 copy_to_mode_reg (Pmode, XEXP (operands[0], 0))); 3957}") 3958 3959(define_insn "" 3960 [(call (match_operand:QI 0 "call_insn_operand" "m") 3961 (match_operand:SI 1 "general_operand" "g")) 3962 (set (reg:SI 7) (plus:SI (reg:SI 7) 3963 (match_operand:SI 3 "immediate_operand" "i")))] 3964 "" 3965 "* 3966{ 3967 if (GET_CODE (operands[0]) == MEM 3968 && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) 3969 { 3970 operands[0] = XEXP (operands[0], 0); 3971 return AS1 (call,%*%0); 3972 } 3973 else 3974 return AS1 (call,%P0); 3975}") 3976 3977(define_insn "" 3978 [(call (mem:QI (match_operand:SI 0 "symbolic_operand" "")) 3979 (match_operand:SI 1 "general_operand" "g")) 3980 (set (reg:SI 7) (plus:SI (reg:SI 7) 3981 (match_operand:SI 3 "immediate_operand" "i")))] 3982 "!HALF_PIC_P ()" 3983 "call %P0") 3984 3985(define_expand "call" 3986 [(call (match_operand:QI 0 "indirect_operand" "") 3987 (match_operand:SI 1 "general_operand" ""))] 3988 ;; Operand 1 not used on the i386. 3989 "" 3990 " 3991{ 3992 rtx addr; 3993 3994 if (flag_pic) 3995 current_function_uses_pic_offset_table = 1; 3996 3997 /* With half-pic, force the address into a register. */ 3998 addr = XEXP (operands[0], 0); 3999 if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) 4000 XEXP (operands[0], 0) = force_reg (Pmode, addr); 4001 4002 if (! expander_call_insn_operand (operands[0], QImode)) 4003 operands[0] 4004 = change_address (operands[0], VOIDmode, 4005 copy_to_mode_reg (Pmode, XEXP (operands[0], 0))); 4006}") 4007 4008(define_insn "" 4009 [(call (match_operand:QI 0 "call_insn_operand" "m") 4010 (match_operand:SI 1 "general_operand" "g"))] 4011 ;; Operand 1 not used on the i386. 4012 "" 4013 "* 4014{ 4015 if (GET_CODE (operands[0]) == MEM 4016 && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) 4017 { 4018 operands[0] = XEXP (operands[0], 0); 4019 return AS1 (call,%*%0); 4020 } 4021 else 4022 return AS1 (call,%P0); 4023}") 4024 4025(define_insn "" 4026 [(call (mem:QI (match_operand:SI 0 "symbolic_operand" "")) 4027 (match_operand:SI 1 "general_operand" "g"))] 4028 ;; Operand 1 not used on the i386. 4029 "!HALF_PIC_P ()" 4030 "call %P0") 4031 4032;; Call subroutine, returning value in operand 0 4033;; (which must be a hard register). 4034 4035(define_expand "call_value_pop" 4036 [(parallel [(set (match_operand 0 "" "") 4037 (call (match_operand:QI 1 "indirect_operand" "") 4038 (match_operand:SI 2 "general_operand" ""))) 4039 (set (reg:SI 7) 4040 (plus:SI (reg:SI 7) 4041 (match_operand:SI 4 "immediate_operand" "")))])] 4042 "" 4043 " 4044{ 4045 rtx addr; 4046 4047 if (flag_pic) 4048 current_function_uses_pic_offset_table = 1; 4049 4050 /* With half-pic, force the address into a register. */ 4051 addr = XEXP (operands[1], 0); 4052 if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) 4053 XEXP (operands[1], 0) = force_reg (Pmode, addr); 4054 4055 if (! expander_call_insn_operand (operands[1], QImode)) 4056 operands[1] 4057 = change_address (operands[1], VOIDmode, 4058 copy_to_mode_reg (Pmode, XEXP (operands[1], 0))); 4059}") 4060 4061(define_insn "" 4062 [(set (match_operand 0 "" "=rf") 4063 (call (match_operand:QI 1 "call_insn_operand" "m") 4064 (match_operand:SI 2 "general_operand" "g"))) 4065 (set (reg:SI 7) (plus:SI (reg:SI 7) 4066 (match_operand:SI 4 "immediate_operand" "i")))] 4067 "" 4068 "* 4069{ 4070 if (GET_CODE (operands[1]) == MEM 4071 && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) 4072 { 4073 operands[1] = XEXP (operands[1], 0); 4074 output_asm_insn (AS1 (call,%*%1), operands); 4075 } 4076 else 4077 output_asm_insn (AS1 (call,%P1), operands); 4078 4079 RET; 4080}") 4081 4082(define_insn "" 4083 [(set (match_operand 0 "" "=rf") 4084 (call (mem:QI (match_operand:SI 1 "symbolic_operand" "")) 4085 (match_operand:SI 2 "general_operand" "g"))) 4086 (set (reg:SI 7) (plus:SI (reg:SI 7) 4087 (match_operand:SI 4 "immediate_operand" "i")))] 4088 "!HALF_PIC_P ()" 4089 "call %P1") 4090 4091(define_expand "call_value" 4092 [(set (match_operand 0 "" "") 4093 (call (match_operand:QI 1 "indirect_operand" "") 4094 (match_operand:SI 2 "general_operand" "")))] 4095 ;; Operand 2 not used on the i386. 4096 "" 4097 " 4098{ 4099 rtx addr; 4100 4101 if (flag_pic) 4102 current_function_uses_pic_offset_table = 1; 4103 4104 /* With half-pic, force the address into a register. */ 4105 addr = XEXP (operands[1], 0); 4106 if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) 4107 XEXP (operands[1], 0) = force_reg (Pmode, addr); 4108 4109 if (! expander_call_insn_operand (operands[1], QImode)) 4110 operands[1] 4111 = change_address (operands[1], VOIDmode, 4112 copy_to_mode_reg (Pmode, XEXP (operands[1], 0))); 4113}") 4114 4115(define_insn "" 4116 [(set (match_operand 0 "" "=rf") 4117 (call (match_operand:QI 1 "call_insn_operand" "m") 4118 (match_operand:SI 2 "general_operand" "g")))] 4119 ;; Operand 2 not used on the i386. 4120 "" 4121 "* 4122{ 4123 if (GET_CODE (operands[1]) == MEM 4124 && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) 4125 { 4126 operands[1] = XEXP (operands[1], 0); 4127 output_asm_insn (AS1 (call,%*%1), operands); 4128 } 4129 else 4130 output_asm_insn (AS1 (call,%P1), operands); 4131 4132 RET; 4133}") 4134 4135(define_insn "" 4136 [(set (match_operand 0 "" "=rf") 4137 (call (mem:QI (match_operand:SI 1 "symbolic_operand" "")) 4138 (match_operand:SI 2 "general_operand" "g")))] 4139 ;; Operand 2 not used on the i386. 4140 "!HALF_PIC_P ()" 4141 "call %P1") 4142 4143(define_expand "untyped_call" 4144 [(parallel [(call (match_operand:QI 0 "indirect_operand" "") 4145 (const_int 0)) 4146 (match_operand:BLK 1 "memory_operand" "") 4147 (match_operand 2 "" "")])] 4148 "" 4149 " 4150{ 4151 rtx addr; 4152 4153 if (flag_pic) 4154 current_function_uses_pic_offset_table = 1; 4155 4156 /* With half-pic, force the address into a register. */ 4157 addr = XEXP (operands[0], 0); 4158 if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) 4159 XEXP (operands[0], 0) = force_reg (Pmode, addr); 4160 4161 operands[1] = change_address (operands[1], DImode, XEXP (operands[1], 0)); 4162 if (! expander_call_insn_operand (operands[1], QImode)) 4163 operands[1] 4164 = change_address (operands[1], VOIDmode, 4165 copy_to_mode_reg (Pmode, XEXP (operands[1], 0))); 4166}") 4167 4168(define_insn "" 4169 [(call (match_operand:QI 0 "call_insn_operand" "m") 4170 (const_int 0)) 4171 (match_operand:DI 1 "memory_operand" "o") 4172 (match_operand 2 "" "")] 4173 "" 4174 "* 4175{ 4176 rtx addr = operands[1]; 4177 4178 if (GET_CODE (operands[0]) == MEM 4179 && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) 4180 { 4181 operands[0] = XEXP (operands[0], 0); 4182 output_asm_insn (AS1 (call,%*%0), operands); 4183 } 4184 else 4185 output_asm_insn (AS1 (call,%P0), operands); 4186 4187 operands[2] = gen_rtx (REG, SImode, 0); 4188 output_asm_insn (AS2 (mov%L2,%2,%1), operands); 4189 4190 operands[2] = gen_rtx (REG, SImode, 1); 4191 operands[1] = adj_offsettable_operand (addr, 4); 4192 output_asm_insn (AS2 (mov%L2,%2,%1), operands); 4193 4194 operands[1] = adj_offsettable_operand (addr, 8); 4195 return AS1 (fnsave,%1); 4196}") 4197 4198(define_insn "" 4199 [(call (mem:QI (match_operand:SI 0 "symbolic_operand" "")) 4200 (const_int 0)) 4201 (match_operand:DI 1 "memory_operand" "o") 4202 (match_operand 2 "" "")] 4203 "!HALF_PIC_P ()" 4204 "* 4205{ 4206 rtx addr = operands[1]; 4207 4208 output_asm_insn (AS1 (call,%P0), operands); 4209 4210 operands[2] = gen_rtx (REG, SImode, 0); 4211 output_asm_insn (AS2 (mov%L2,%2,%1), operands); 4212 4213 operands[2] = gen_rtx (REG, SImode, 1); 4214 operands[1] = adj_offsettable_operand (addr, 4); 4215 output_asm_insn (AS2 (mov%L2,%2,%1), operands); 4216 4217 operands[1] = adj_offsettable_operand (addr, 8); 4218 return AS1 (fnsave,%1); 4219}") 4220 4221;; We use fnsave and frstor to save and restore the floating point result. 4222;; These are expensive instructions and require a large space to save the 4223;; FPU state. An more complicated alternative is to use fnstenv to store 4224;; the FPU environment and test whether the stack top is valid. Store the 4225;; result of the test, and if it is valid, pop and save the value. The 4226;; untyped_return would check the test and optionally push the saved value. 4227 4228(define_expand "untyped_return" 4229 [(match_operand:BLK 0 "memory_operand" "") 4230 (match_operand 1 "" "")] 4231 "" 4232 " 4233{ 4234 rtx valreg1 = gen_rtx (REG, SImode, 0); 4235 rtx valreg2 = gen_rtx (REG, SImode, 1); 4236 rtx result = operands[0]; 4237 4238 /* Restore the FPU state. */ 4239 emit_insn (gen_update_return (change_address (result, SImode, 4240 plus_constant (XEXP (result, 0), 4241 8)))); 4242 4243 /* Reload the function value registers. */ 4244 emit_move_insn (valreg1, change_address (result, SImode, XEXP (result, 0))); 4245 emit_move_insn (valreg2, 4246 change_address (result, SImode, 4247 plus_constant (XEXP (result, 0), 4))); 4248 4249 /* Put USE insns before the return. */ 4250 emit_insn (gen_rtx (USE, VOIDmode, valreg1)); 4251 emit_insn (gen_rtx (USE, VOIDmode, valreg2)); 4252 4253 /* Construct the return. */ 4254 expand_null_return (); 4255 4256 DONE; 4257}") 4258 4259(define_insn "update_return" 4260 [(unspec:SI [(match_operand:SI 0 "memory_operand" "m")] 0)] 4261 "" 4262 "frstor %0") 4263 4264;; Insn emitted into the body of a function to return from a function. 4265;; This is only done if the function's epilogue is known to be simple. 4266;; See comments for simple_386_epilogue in i386.c. 4267 4268(define_insn "return" 4269 [(return)] 4270 "simple_386_epilogue ()" 4271 "* 4272{ 4273 function_epilogue (asm_out_file, get_frame_size ()); 4274 RET; 4275}") 4276 4277(define_insn "nop" 4278 [(const_int 0)] 4279 "" 4280 "nop") 4281 4282(define_expand "movstrsi" 4283 [(parallel [(set (match_operand:BLK 0 "memory_operand" "") 4284 (match_operand:BLK 1 "memory_operand" "")) 4285 (use (match_operand:SI 2 "const_int_operand" "")) 4286 (use (match_operand:SI 3 "const_int_operand" "")) 4287 (clobber (match_scratch:SI 4 "")) 4288 (clobber (match_dup 5)) 4289 (clobber (match_dup 6))])] 4290 "" 4291 " 4292{ 4293 rtx addr0, addr1; 4294 4295 if (GET_CODE (operands[2]) != CONST_INT) 4296 FAIL; 4297 4298 addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); 4299 addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); 4300 4301 operands[5] = addr0; 4302 operands[6] = addr1; 4303 4304 operands[0] = gen_rtx (MEM, BLKmode, addr0); 4305 operands[1] = gen_rtx (MEM, BLKmode, addr1); 4306}") 4307 4308;; It might seem that operands 0 & 1 could use predicate register_operand. 4309;; But strength reduction might offset the MEM expression. So we let 4310;; reload put the address into %edi & %esi. 4311 4312(define_insn "" 4313 [(set (mem:BLK (match_operand:SI 0 "address_operand" "D")) 4314 (mem:BLK (match_operand:SI 1 "address_operand" "S"))) 4315 (use (match_operand:SI 2 "const_int_operand" "n")) 4316 (use (match_operand:SI 3 "immediate_operand" "i")) 4317 (clobber (match_scratch:SI 4 "=&c")) 4318 (clobber (match_dup 0)) 4319 (clobber (match_dup 1))] 4320 "" 4321 "* 4322{ 4323 rtx xops[2]; 4324 4325 output_asm_insn (\"cld\", operands); 4326 if (GET_CODE (operands[2]) == CONST_INT) 4327 { 4328 if (INTVAL (operands[2]) & ~0x03) 4329 { 4330 xops[0] = GEN_INT ((INTVAL (operands[2]) >> 2) & 0x3fffffff); 4331 xops[1] = operands[4]; 4332 4333 output_asm_insn (AS2 (mov%L1,%0,%1), xops); 4334#ifdef INTEL_SYNTAX 4335 output_asm_insn (\"rep movsd\", xops); 4336#else 4337 output_asm_insn (\"rep\;movsl\", xops); 4338#endif 4339 } 4340 if (INTVAL (operands[2]) & 0x02) 4341 output_asm_insn (\"movsw\", operands); 4342 if (INTVAL (operands[2]) & 0x01) 4343 output_asm_insn (\"movsb\", operands); 4344 } 4345 else 4346 abort (); 4347 RET; 4348}") 4349 4350(define_expand "cmpstrsi" 4351 [(parallel [(set (match_operand:SI 0 "general_operand" "") 4352 (compare:SI (match_operand:BLK 1 "general_operand" "") 4353 (match_operand:BLK 2 "general_operand" ""))) 4354 (use (match_operand:SI 3 "general_operand" "")) 4355 (use (match_operand:SI 4 "immediate_operand" "")) 4356 (clobber (match_dup 5)) 4357 (clobber (match_dup 6)) 4358 (clobber (match_dup 3))])] 4359 "" 4360 " 4361{ 4362 rtx addr1, addr2; 4363 4364 addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); 4365 addr2 = copy_to_mode_reg (Pmode, XEXP (operands[2], 0)); 4366 operands[3] = copy_to_mode_reg (SImode, operands[3]); 4367 4368 operands[5] = addr1; 4369 operands[6] = addr2; 4370 4371 operands[1] = gen_rtx (MEM, BLKmode, addr1); 4372 operands[2] = gen_rtx (MEM, BLKmode, addr2); 4373 4374}") 4375 4376;; memcmp recognizers. The `cmpsb' opcode does nothing if the count is 4377;; zero. Emit extra code to make sure that a zero-length compare is EQ. 4378 4379;; It might seem that operands 0 & 1 could use predicate register_operand. 4380;; But strength reduction might offset the MEM expression. So we let 4381;; reload put the address into %edi & %esi. 4382 4383;; ??? Most comparisons have a constant length, and it's therefore 4384;; possible to know that the length is non-zero, and to avoid the extra 4385;; code to handle zero-length compares. 4386 4387(define_insn "" 4388 [(set (match_operand:SI 0 "general_operand" "=&r") 4389 (compare:SI (mem:BLK (match_operand:SI 1 "address_operand" "S")) 4390 (mem:BLK (match_operand:SI 2 "address_operand" "D")))) 4391 (use (match_operand:SI 3 "register_operand" "c")) 4392 (use (match_operand:SI 4 "immediate_operand" "i")) 4393 (clobber (match_dup 1)) 4394 (clobber (match_dup 2)) 4395 (clobber (match_dup 3))] 4396 "" 4397 "* 4398{ 4399 rtx xops[4], label; 4400 4401 label = gen_label_rtx (); 4402 4403 output_asm_insn (\"cld\", operands); 4404 output_asm_insn (AS2 (xor%L0,%0,%0), operands); 4405 output_asm_insn (\"repz\;cmps%B2\", operands); 4406 output_asm_insn (\"je %l0\", &label); 4407 4408 xops[0] = operands[0]; 4409 xops[1] = gen_rtx (MEM, QImode, 4410 gen_rtx (PLUS, SImode, operands[1], constm1_rtx)); 4411 xops[2] = gen_rtx (MEM, QImode, 4412 gen_rtx (PLUS, SImode, operands[2], constm1_rtx)); 4413 xops[3] = operands[3]; 4414 4415 output_asm_insn (AS2 (movz%B1%L0,%1,%0), xops); 4416 output_asm_insn (AS2 (movz%B2%L3,%2,%3), xops); 4417 4418 output_asm_insn (AS2 (sub%L0,%3,%0), xops); 4419 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label)); 4420 RET; 4421}") 4422 4423(define_insn "" 4424 [(set (cc0) 4425 (compare:SI (mem:BLK (match_operand:SI 0 "address_operand" "S")) 4426 (mem:BLK (match_operand:SI 1 "address_operand" "D")))) 4427 (use (match_operand:SI 2 "register_operand" "c")) 4428 (use (match_operand:SI 3 "immediate_operand" "i")) 4429 (clobber (match_dup 0)) 4430 (clobber (match_dup 1)) 4431 (clobber (match_dup 2))] 4432 "" 4433 "* 4434{ 4435 rtx xops[2]; 4436 4437 cc_status.flags |= CC_NOT_SIGNED; 4438 4439 xops[0] = gen_rtx (REG, QImode, 0); 4440 xops[1] = CONST0_RTX (QImode); 4441 4442 output_asm_insn (\"cld\", operands); 4443 output_asm_insn (AS2 (test%B0,%1,%0), xops); 4444 return \"repz\;cmps%B2\"; 4445}") 4446 4447(define_expand "ffssi2" 4448 [(set (match_dup 2) 4449 (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" "")) 4450 (const_int -1))) 4451 (set (match_operand:SI 0 "general_operand" "") 4452 (plus:SI (match_dup 2) (const_int 1)))] 4453 "" 4454 "operands[2] = gen_reg_rtx (SImode);") 4455 4456(define_insn "" 4457 [(set (match_operand:SI 0 "general_operand" "=&r") 4458 (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" "rm")) 4459 (const_int -1)))] 4460 "" 4461 "* 4462{ 4463 rtx xops[2]; 4464 4465 xops[0] = operands[0]; 4466 xops[1] = constm1_rtx; 4467 output_asm_insn (AS2 (mov%L0,%1,%0), xops); 4468 return AS2 (bsf%L0,%1,%0); 4469}") 4470 4471(define_expand "ffshi2" 4472 [(set (match_dup 2) 4473 (plus:HI (ffs:HI (match_operand:HI 1 "general_operand" "")) 4474 (const_int -1))) 4475 (set (match_operand:HI 0 "general_operand" "") 4476 (plus:HI (match_dup 2) (const_int 1)))] 4477 "" 4478 "operands[2] = gen_reg_rtx (HImode);") 4479 4480(define_insn "" 4481 [(set (match_operand:HI 0 "general_operand" "=&r") 4482 (plus:HI (ffs:HI (match_operand:SI 1 "general_operand" "rm")) 4483 (const_int -1)))] 4484 "" 4485 "* 4486{ 4487 rtx xops[2]; 4488 4489 xops[0] = operands[0]; 4490 xops[1] = constm1_rtx; 4491 output_asm_insn (AS2 (mov%W0,%1,%0), xops); 4492 return AS2 (bsf%W0,%1,%0); 4493}") 4494 4495;; These patterns match the binary 387 instructions for addM3, subM3, 4496;; mulM3 and divM3. There are three patterns for each of DFmode and 4497;; SFmode. The first is the normal insn, the second the same insn but 4498;; with one operand a conversion, and the third the same insn but with 4499;; the other operand a conversion. The conversion may be SFmode or 4500;; SImode if the target mode DFmode, but only SImode if the target mode 4501;; is SFmode. 4502 4503(define_insn "" 4504 [(set (match_operand:DF 0 "register_operand" "=f,f") 4505 (match_operator:DF 3 "binary_387_op" 4506 [(match_operand:DF 1 "nonimmediate_operand" "0,fm") 4507 (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))] 4508 "TARGET_80387" 4509 "* return (char *) output_387_binary_op (insn, operands);") 4510 4511(define_insn "" 4512 [(set (match_operand:DF 0 "register_operand" "=f") 4513 (match_operator:DF 3 "binary_387_op" 4514 [(float:DF (match_operand:SI 1 "general_operand" "rm")) 4515 (match_operand:DF 2 "general_operand" "0")]))] 4516 "TARGET_80387" 4517 "* return (char *) output_387_binary_op (insn, operands);") 4518 4519(define_insn "" 4520 [(set (match_operand:DF 0 "register_operand" "=f,f") 4521 (match_operator:DF 3 "binary_387_op" 4522 [(float_extend:DF (match_operand:SF 1 "general_operand" "fm,0")) 4523 (match_operand:DF 2 "general_operand" "0,f")]))] 4524 "TARGET_80387" 4525 "* return (char *) output_387_binary_op (insn, operands);") 4526 4527(define_insn "" 4528 [(set (match_operand:DF 0 "register_operand" "=f") 4529 (match_operator:DF 3 "binary_387_op" 4530 [(match_operand:DF 1 "general_operand" "0") 4531 (float:DF (match_operand:SI 2 "general_operand" "rm"))]))] 4532 "TARGET_80387" 4533 "* return (char *) output_387_binary_op (insn, operands);") 4534 4535(define_insn "" 4536 [(set (match_operand:DF 0 "register_operand" "=f,f") 4537 (match_operator:DF 3 "binary_387_op" 4538 [(match_operand:DF 1 "general_operand" "0,f") 4539 (float_extend:DF 4540 (match_operand:SF 2 "general_operand" "fm,0"))]))] 4541 "TARGET_80387" 4542 "* return (char *) output_387_binary_op (insn, operands);") 4543 4544(define_insn "" 4545 [(set (match_operand:SF 0 "register_operand" "=f,f") 4546 (match_operator:SF 3 "binary_387_op" 4547 [(match_operand:SF 1 "nonimmediate_operand" "0,fm") 4548 (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))] 4549 "TARGET_80387" 4550 "* return (char *) output_387_binary_op (insn, operands);") 4551 4552(define_insn "" 4553 [(set (match_operand:SF 0 "register_operand" "=f") 4554 (match_operator:SF 3 "binary_387_op" 4555 [(float:SF (match_operand:SI 1 "general_operand" "rm")) 4556 (match_operand:SF 2 "general_operand" "0")]))] 4557 "TARGET_80387" 4558 "* return (char *) output_387_binary_op (insn, operands);") 4559 4560(define_insn "" 4561 [(set (match_operand:SF 0 "register_operand" "=f") 4562 (match_operator:SF 3 "binary_387_op" 4563 [(match_operand:SF 1 "general_operand" "0") 4564 (float:SF (match_operand:SI 2 "general_operand" "rm"))]))] 4565 "TARGET_80387" 4566 "* return (char *) output_387_binary_op (insn, operands);") 4567 4568(define_expand "strlensi" 4569 [(parallel [(set (match_dup 4) 4570 (unspec:SI [(mem:BLK (match_operand:BLK 1 "general_operand" "")) 4571 (match_operand:QI 2 "register_operand" "") 4572 (match_operand:SI 3 "immediate_operand" "")] 0)) 4573 (clobber (match_dup 1))]) 4574 (set (match_dup 5) 4575 (not:SI (match_dup 4))) 4576 (set (match_operand:SI 0 "register_operand" "") 4577 (minus:SI (match_dup 5) 4578 (const_int 1)))] 4579 "" 4580 " 4581{ 4582 operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); 4583 operands[4] = gen_reg_rtx (SImode); 4584 operands[5] = gen_reg_rtx (SImode); 4585}") 4586 4587;; It might seem that operands 0 & 1 could use predicate register_operand. 4588;; But strength reduction might offset the MEM expression. So we let 4589;; reload put the address into %edi. 4590 4591(define_insn "" 4592 [(set (match_operand:SI 0 "register_operand" "=&c") 4593 (unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "D")) 4594 (match_operand:QI 2 "register_operand" "a") 4595 (match_operand:SI 3 "immediate_operand" "i")] 0)) 4596 (clobber (match_dup 1))] 4597 "" 4598 "* 4599{ 4600 rtx xops[2]; 4601 4602 xops[0] = operands[0]; 4603 xops[1] = constm1_rtx; 4604 output_asm_insn (\"cld\", operands); 4605 output_asm_insn (AS2 (mov%L0,%1,%0), xops); 4606 return \"repnz\;scas%B2\"; 4607}") 4608