i386.md revision 18334
1264095Semaste;; GCC machine description for Intel X86. 2264095Semaste;; Copyright (C) 1988, 1994, 1995 Free Software Foundation, Inc. 3264095Semaste;; Mostly by William Schelter. 4264095Semaste 5264095Semaste;; This file is part of GNU CC. 6264095Semaste 7264095Semaste;; GNU CC is free software; you can redistribute it and/or modify 8264095Semaste;; it under the terms of the GNU General Public License as published by 9264095Semaste;; the Free Software Foundation; either version 2, or (at your option) 10264095Semaste;; any later version. 11264095Semaste 12264095Semaste;; GNU CC is distributed in the hope that it will be useful, 13264095Semaste;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14264095Semaste;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15264095Semaste;; GNU General Public License for more details. 16264095Semaste 17264095Semaste;; You should have received a copy of the GNU General Public License 18264095Semaste;; along with GNU CC; see the file COPYING. If not, write to 19264095Semaste;; the Free Software Foundation, 59 Temple Place - Suite 330, 20264095Semaste;; Boston, MA 02111-1307, USA. 21264095Semaste 22264095Semaste 23264095Semaste;; The original PO technology requires these to be ordered by speed, 24264095Semaste;; so that assigner will pick the fastest. 25264095Semaste 26264095Semaste;; See file "rtl.def" for documentation on define_insn, match_*, et. al. 27264095Semaste 28264095Semaste;; Macro #define NOTICE_UPDATE_CC in file i386.h handles condition code 29264095Semaste;; updates for most instructions. 30264095Semaste 31280950Sandrew;; Macro REG_CLASS_FROM_LETTER in file i386.h defines the register 32280950Sandrew;; constraint letters. 33264095Semaste 34293724Ssmh;; the special asm out single letter directives following a '%' are: 35293724Ssmh;; 'z' mov%z1 would be movl, movw, or movb depending on the mode of 36280950Sandrew;; operands[1]. 37264095Semaste;; 'L' Print the opcode suffix for a 32-bit integer opcode. 38280950Sandrew;; 'W' Print the opcode suffix for a 16-bit integer opcode. 39280950Sandrew;; 'B' Print the opcode suffix for an 8-bit integer opcode. 40280950Sandrew;; 'S' Print the opcode suffix for a 32-bit float opcode. 41264095Semaste;; 'Q' Print the opcode suffix for a 64-bit float opcode. 42280950Sandrew;; 'T' Print the opcode suffix for an 80-bit extended real XFmode float opcode. 43264095Semaste;; 'J' Print the appropriate jump operand. 44280950Sandrew 45280950Sandrew;; 'b' Print the QImode name of the register for the indicated operand. 46280950Sandrew;; %b0 would print %al if operands[0] is reg 0. 47280950Sandrew;; 'w' Likewise, print the HImode name of the register. 48264095Semaste;; 'k' Likewise, print the SImode name of the register. 49280950Sandrew;; 'h' Print the QImode name for a "high" register, either ah, bh, ch or dh. 50280950Sandrew;; 'y' Print "st(0)" instead of "st" as a register. 51280950Sandrew 52;; UNSPEC usage: 53;; 0 This is a `scas' operation. The mode of the UNSPEC is always SImode. 54;; operand 0 is the memory address to scan. 55;; operand 1 is a register containing the value to scan for. The mode 56;; of the scas opcode will be the same as the mode of this operand. 57;; operand 2 is the known alignment of operand 0. 58;; 1 This is a `sin' operation. The mode of the UNSPEC is MODE_FLOAT. 59;; operand 0 is the argument for `sin'. 60;; 2 This is a `cos' operation. The mode of the UNSPEC is MODE_FLOAT. 61;; operand 0 is the argument for `cos'. 62 63;; "movl MEM,REG / testl REG,REG" is faster on a 486 than "cmpl $0,MEM". 64;; But restricting MEM here would mean that gcc could not remove a redundant 65;; test in cases like "incl MEM / je TARGET". 66;; 67;; We don't want to allow a constant operand for test insns because 68;; (set (cc0) (const_int foo)) has no mode information. Such insns will 69;; be folded while optimizing anyway. 70 71;; All test insns have expanders that save the operands away without 72;; actually generating RTL. The bCOND or sCOND (emitted immediately 73;; after the tstM or cmp) will actually emit the tstM or cmpM. 74 75(define_insn "tstsi_1" 76 [(set (cc0) 77 (match_operand:SI 0 "nonimmediate_operand" "rm"))] 78 "" 79 "* 80{ 81 if (REG_P (operands[0])) 82 return AS2 (test%L0,%0,%0); 83 84 operands[1] = const0_rtx; 85 return AS2 (cmp%L0,%1,%0); 86}") 87 88(define_expand "tstsi" 89 [(set (cc0) 90 (match_operand:SI 0 "nonimmediate_operand" ""))] 91 "" 92 " 93{ 94 i386_compare_gen = gen_tstsi_1; 95 i386_compare_op0 = operands[0]; 96 DONE; 97}") 98 99(define_insn "tsthi_1" 100 [(set (cc0) 101 (match_operand:HI 0 "nonimmediate_operand" "rm"))] 102 "" 103 "* 104{ 105 if (REG_P (operands[0])) 106 return AS2 (test%W0,%0,%0); 107 108 operands[1] = const0_rtx; 109 return AS2 (cmp%W0,%1,%0); 110}") 111 112(define_expand "tsthi" 113 [(set (cc0) 114 (match_operand:HI 0 "nonimmediate_operand" ""))] 115 "" 116 " 117{ 118 i386_compare_gen = gen_tsthi_1; 119 i386_compare_op0 = operands[0]; 120 DONE; 121}") 122 123(define_insn "tstqi_1" 124 [(set (cc0) 125 (match_operand:QI 0 "nonimmediate_operand" "qm"))] 126 "" 127 "* 128{ 129 if (REG_P (operands[0])) 130 return AS2 (test%B0,%0,%0); 131 132 operands[1] = const0_rtx; 133 return AS2 (cmp%B0,%1,%0); 134}") 135 136(define_expand "tstqi" 137 [(set (cc0) 138 (match_operand:QI 0 "nonimmediate_operand" ""))] 139 "" 140 " 141{ 142 i386_compare_gen = gen_tstqi_1; 143 i386_compare_op0 = operands[0]; 144 DONE; 145}") 146 147(define_insn "tstsf_cc" 148 [(set (cc0) 149 (match_operand:SF 0 "register_operand" "f")) 150 (clobber (match_scratch:HI 1 "=a"))] 151 "TARGET_80387 && ! TARGET_IEEE_FP" 152 "* 153{ 154 if (! STACK_TOP_P (operands[0])) 155 abort (); 156 157 output_asm_insn (\"ftst\", operands); 158 159 if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) 160 output_asm_insn (AS1 (fstp,%y0), operands); 161 162 return output_fp_cc0_set (insn); 163}") 164 165;; Don't generate tstsf if generating IEEE code, since the `ftst' opcode 166;; isn't IEEE compliant. 167 168(define_expand "tstsf" 169 [(parallel [(set (cc0) 170 (match_operand:SF 0 "register_operand" "")) 171 (clobber (match_scratch:HI 1 ""))])] 172 "TARGET_80387 && ! TARGET_IEEE_FP" 173 " 174{ 175 i386_compare_gen = gen_tstsf_cc; 176 i386_compare_op0 = operands[0]; 177 DONE; 178}") 179 180(define_insn "tstdf_cc" 181 [(set (cc0) 182 (match_operand:DF 0 "register_operand" "f")) 183 (clobber (match_scratch:HI 1 "=a"))] 184 "TARGET_80387 && ! TARGET_IEEE_FP" 185 "* 186{ 187 if (! STACK_TOP_P (operands[0])) 188 abort (); 189 190 output_asm_insn (\"ftst\", operands); 191 192 if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) 193 output_asm_insn (AS1 (fstp,%y0), operands); 194 195 return output_fp_cc0_set (insn); 196}") 197 198;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode 199;; isn't IEEE compliant. 200 201(define_expand "tstdf" 202 [(parallel [(set (cc0) 203 (match_operand:DF 0 "register_operand" "")) 204 (clobber (match_scratch:HI 1 ""))])] 205 "TARGET_80387 && ! TARGET_IEEE_FP" 206 " 207{ 208 i386_compare_gen = gen_tstdf_cc; 209 i386_compare_op0 = operands[0]; 210 DONE; 211}") 212 213(define_insn "tstxf_cc" 214 [(set (cc0) 215 (match_operand:XF 0 "register_operand" "f")) 216 (clobber (match_scratch:HI 1 "=a"))] 217 "TARGET_80387 && ! TARGET_IEEE_FP" 218 "* 219{ 220 if (! STACK_TOP_P (operands[0])) 221 abort (); 222 223 output_asm_insn (\"ftst\", operands); 224 225 if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) 226 output_asm_insn (AS1 (fstp,%y0), operands); 227 228 return output_fp_cc0_set (insn); 229}") 230 231;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode 232;; isn't IEEE compliant. 233 234(define_expand "tstxf" 235 [(parallel [(set (cc0) 236 (match_operand:XF 0 "register_operand" "")) 237 (clobber (match_scratch:HI 1 ""))])] 238 "TARGET_80387 && ! TARGET_IEEE_FP" 239 " 240{ 241 i386_compare_gen = gen_tstxf_cc; 242 i386_compare_op0 = operands[0]; 243 DONE; 244}") 245 246;;- compare instructions. See comments above tstM patterns about 247;; expansion of these insns. 248 249(define_insn "cmpsi_1" 250 [(set (cc0) 251 (compare (match_operand:SI 0 "nonimmediate_operand" "mr,r") 252 (match_operand:SI 1 "general_operand" "ri,mr")))] 253 "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" 254 "* 255{ 256 if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM) 257 { 258 cc_status.flags |= CC_REVERSED; 259 return AS2 (cmp%L0,%0,%1); 260 } 261 return AS2 (cmp%L0,%1,%0); 262}") 263 264(define_expand "cmpsi" 265 [(set (cc0) 266 (compare (match_operand:SI 0 "nonimmediate_operand" "") 267 (match_operand:SI 1 "general_operand" "")))] 268 "" 269 " 270{ 271 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) 272 operands[0] = force_reg (SImode, operands[0]); 273 274 i386_compare_gen = gen_cmpsi_1; 275 i386_compare_op0 = operands[0]; 276 i386_compare_op1 = operands[1]; 277 DONE; 278}") 279 280(define_insn "cmphi_1" 281 [(set (cc0) 282 (compare (match_operand:HI 0 "nonimmediate_operand" "mr,r") 283 (match_operand:HI 1 "general_operand" "ri,mr")))] 284 "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" 285 "* 286{ 287 if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM) 288 { 289 cc_status.flags |= CC_REVERSED; 290 return AS2 (cmp%W0,%0,%1); 291 } 292 return AS2 (cmp%W0,%1,%0); 293}") 294 295(define_expand "cmphi" 296 [(set (cc0) 297 (compare (match_operand:HI 0 "nonimmediate_operand" "") 298 (match_operand:HI 1 "general_operand" "")))] 299 "" 300 " 301{ 302 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) 303 operands[0] = force_reg (HImode, operands[0]); 304 305 i386_compare_gen = gen_cmphi_1; 306 i386_compare_op0 = operands[0]; 307 i386_compare_op1 = operands[1]; 308 DONE; 309}") 310 311(define_insn "cmpqi_1" 312 [(set (cc0) 313 (compare (match_operand:QI 0 "nonimmediate_operand" "q,mq") 314 (match_operand:QI 1 "general_operand" "qm,nq")))] 315 "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" 316 "* 317{ 318 if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM) 319 { 320 cc_status.flags |= CC_REVERSED; 321 return AS2 (cmp%B0,%0,%1); 322 } 323 return AS2 (cmp%B0,%1,%0); 324}") 325 326(define_expand "cmpqi" 327 [(set (cc0) 328 (compare (match_operand:QI 0 "nonimmediate_operand" "") 329 (match_operand:QI 1 "general_operand" "")))] 330 "" 331 " 332{ 333 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) 334 operands[0] = force_reg (QImode, operands[0]); 335 336 i386_compare_gen = gen_cmpqi_1; 337 i386_compare_op0 = operands[0]; 338 i386_compare_op1 = operands[1]; 339 DONE; 340}") 341 342;; These implement float point compares. For each of DFmode and 343;; SFmode, there is the normal insn, and an insn where the second operand 344;; is converted to the desired mode. 345 346(define_insn "" 347 [(set (cc0) 348 (match_operator 2 "VOIDmode_compare_op" 349 [(match_operand:XF 0 "nonimmediate_operand" "f") 350 (match_operand:XF 1 "nonimmediate_operand" "f")])) 351 (clobber (match_scratch:HI 3 "=a"))] 352 "TARGET_80387 353 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" 354 "* return output_float_compare (insn, operands);") 355 356(define_insn "" 357 [(set (cc0) 358 (match_operator 2 "VOIDmode_compare_op" 359 [(match_operand:XF 0 "register_operand" "f") 360 (float:XF 361 (match_operand:SI 1 "nonimmediate_operand" "rm"))])) 362 (clobber (match_scratch:HI 3 "=a"))] 363 "TARGET_80387" 364 "* return output_float_compare (insn, operands);") 365 366(define_insn "" 367 [(set (cc0) 368 (match_operator 2 "VOIDmode_compare_op" 369 [(float:XF 370 (match_operand:SI 0 "nonimmediate_operand" "rm")) 371 (match_operand:XF 1 "register_operand" "f")])) 372 (clobber (match_scratch:HI 3 "=a"))] 373 "TARGET_80387" 374 "* return output_float_compare (insn, operands);") 375 376(define_insn "" 377 [(set (cc0) 378 (match_operator 2 "VOIDmode_compare_op" 379 [(match_operand:XF 0 "register_operand" "f") 380 (float_extend:XF 381 (match_operand:DF 1 "nonimmediate_operand" "fm"))])) 382 (clobber (match_scratch:HI 3 "=a"))] 383 "TARGET_80387" 384 "* return output_float_compare (insn, operands);") 385 386(define_insn "" 387 [(set (cc0) 388 (match_operator 2 "VOIDmode_compare_op" 389 [(match_operand:XF 0 "register_operand" "f") 390 (float_extend:XF 391 (match_operand:SF 1 "nonimmediate_operand" "fm"))])) 392 (clobber (match_scratch:HI 3 "=a"))] 393 "TARGET_80387" 394 "* return output_float_compare (insn, operands);") 395 396(define_insn "" 397 [(set (cc0) 398 (compare:CCFPEQ (match_operand:XF 0 "register_operand" "f") 399 (match_operand:XF 1 "register_operand" "f"))) 400 (clobber (match_scratch:HI 2 "=a"))] 401 "TARGET_80387" 402 "* return output_float_compare (insn, operands);") 403 404(define_insn "" 405 [(set (cc0) 406 (match_operator 2 "VOIDmode_compare_op" 407 [(match_operand:DF 0 "nonimmediate_operand" "f,fm") 408 (match_operand:DF 1 "nonimmediate_operand" "fm,f")])) 409 (clobber (match_scratch:HI 3 "=a,a"))] 410 "TARGET_80387 411 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" 412 "* return output_float_compare (insn, operands);") 413 414(define_insn "" 415 [(set (cc0) 416 (match_operator 2 "VOIDmode_compare_op" 417 [(match_operand:DF 0 "register_operand" "f") 418 (float:DF 419 (match_operand:SI 1 "nonimmediate_operand" "rm"))])) 420 (clobber (match_scratch:HI 3 "=a"))] 421 "TARGET_80387" 422 "* return output_float_compare (insn, operands);") 423 424(define_insn "" 425 [(set (cc0) 426 (match_operator 2 "VOIDmode_compare_op" 427 [(float:DF 428 (match_operand:SI 0 "nonimmediate_operand" "rm")) 429 (match_operand:DF 1 "register_operand" "f")])) 430 (clobber (match_scratch:HI 3 "=a"))] 431 "TARGET_80387" 432 "* return output_float_compare (insn, operands);") 433 434(define_insn "" 435 [(set (cc0) 436 (match_operator 2 "VOIDmode_compare_op" 437 [(match_operand:DF 0 "register_operand" "f") 438 (float_extend:DF 439 (match_operand:SF 1 "nonimmediate_operand" "fm"))])) 440 (clobber (match_scratch:HI 3 "=a"))] 441 "TARGET_80387" 442 "* return output_float_compare (insn, operands);") 443 444(define_insn "" 445 [(set (cc0) 446 (match_operator 2 "VOIDmode_compare_op" 447 [(float_extend:DF 448 (match_operand:SF 0 "nonimmediate_operand" "fm")) 449 (match_operand:DF 1 "register_operand" "f")])) 450 (clobber (match_scratch:HI 3 "=a"))] 451 "TARGET_80387" 452 "* return output_float_compare (insn, operands);") 453 454(define_insn "" 455 [(set (cc0) 456 (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f") 457 (match_operand:DF 1 "register_operand" "f"))) 458 (clobber (match_scratch:HI 2 "=a"))] 459 "TARGET_80387" 460 "* return output_float_compare (insn, operands);") 461 462;; These two insns will never be generated by combine due to the mode of 463;; the COMPARE. 464;(define_insn "" 465; [(set (cc0) 466; (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f") 467; (float_extend:DF 468; (match_operand:SF 1 "register_operand" "f")))) 469; (clobber (match_scratch:HI 2 "=a"))] 470; "TARGET_80387" 471; "* return output_float_compare (insn, operands);") 472; 473;(define_insn "" 474; [(set (cc0) 475; (compare:CCFPEQ (float_extend:DF 476; (match_operand:SF 0 "register_operand" "f")) 477; (match_operand:DF 1 "register_operand" "f"))) 478; (clobber (match_scratch:HI 2 "=a"))] 479; "TARGET_80387" 480; "* return output_float_compare (insn, operands);") 481 482(define_insn "cmpsf_cc_1" 483 [(set (cc0) 484 (match_operator 2 "VOIDmode_compare_op" 485 [(match_operand:SF 0 "nonimmediate_operand" "f,fm") 486 (match_operand:SF 1 "nonimmediate_operand" "fm,f")])) 487 (clobber (match_scratch:HI 3 "=a,a"))] 488 "TARGET_80387 489 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" 490 "* return output_float_compare (insn, operands);") 491 492(define_insn "" 493 [(set (cc0) 494 (match_operator 2 "VOIDmode_compare_op" 495 [(match_operand:SF 0 "register_operand" "f") 496 (float:SF 497 (match_operand:SI 1 "nonimmediate_operand" "rm"))])) 498 (clobber (match_scratch:HI 3 "=a"))] 499 "TARGET_80387" 500 "* return output_float_compare (insn, operands);") 501 502(define_insn "" 503 [(set (cc0) 504 (match_operator 2 "VOIDmode_compare_op" 505 [(float:SF 506 (match_operand:SI 0 "nonimmediate_operand" "rm")) 507 (match_operand:SF 1 "register_operand" "f")])) 508 (clobber (match_scratch:HI 3 "=a"))] 509 "TARGET_80387" 510 "* return output_float_compare (insn, operands);") 511 512(define_insn "" 513 [(set (cc0) 514 (compare:CCFPEQ (match_operand:SF 0 "register_operand" "f") 515 (match_operand:SF 1 "register_operand" "f"))) 516 (clobber (match_scratch:HI 2 "=a"))] 517 "TARGET_80387" 518 "* return output_float_compare (insn, operands);") 519 520(define_expand "cmpxf" 521 [(set (cc0) 522 (compare (match_operand:XF 0 "register_operand" "") 523 (match_operand:XF 1 "nonimmediate_operand" "")))] 524 "TARGET_80387" 525 " 526{ 527 i386_compare_gen = gen_cmpxf_cc; 528 i386_compare_gen_eq = gen_cmpxf_ccfpeq; 529 i386_compare_op0 = operands[0]; 530 i386_compare_op1 = operands[1]; 531 DONE; 532}") 533 534(define_expand "cmpdf" 535 [(set (cc0) 536 (compare (match_operand:DF 0 "register_operand" "") 537 (match_operand:DF 1 "nonimmediate_operand" "")))] 538 "TARGET_80387" 539 " 540{ 541 i386_compare_gen = gen_cmpdf_cc; 542 i386_compare_gen_eq = gen_cmpdf_ccfpeq; 543 i386_compare_op0 = operands[0]; 544 i386_compare_op1 = operands[1]; 545 DONE; 546}") 547 548(define_expand "cmpsf" 549 [(set (cc0) 550 (compare (match_operand:SF 0 "register_operand" "") 551 (match_operand:SF 1 "nonimmediate_operand" "")))] 552 "TARGET_80387" 553 " 554{ 555 i386_compare_gen = gen_cmpsf_cc; 556 i386_compare_gen_eq = gen_cmpsf_ccfpeq; 557 i386_compare_op0 = operands[0]; 558 i386_compare_op1 = operands[1]; 559 DONE; 560}") 561 562(define_expand "cmpxf_cc" 563 [(parallel [(set (cc0) 564 (compare (match_operand:XF 0 "register_operand" "") 565 (match_operand:XF 1 "register_operand" ""))) 566 (clobber (match_scratch:HI 2 ""))])] 567 "TARGET_80387" 568 "") 569 570(define_expand "cmpxf_ccfpeq" 571 [(parallel [(set (cc0) 572 (compare:CCFPEQ (match_operand:XF 0 "register_operand" "") 573 (match_operand:XF 1 "register_operand" ""))) 574 (clobber (match_scratch:HI 2 ""))])] 575 "TARGET_80387" 576 " 577{ 578 if (! register_operand (operands[1], XFmode)) 579 operands[1] = copy_to_mode_reg (XFmode, operands[1]); 580}") 581 582(define_expand "cmpdf_cc" 583 [(parallel [(set (cc0) 584 (compare (match_operand:DF 0 "register_operand" "") 585 (match_operand:DF 1 "register_operand" ""))) 586 (clobber (match_scratch:HI 2 ""))])] 587 "TARGET_80387" 588 "") 589 590(define_expand "cmpdf_ccfpeq" 591 [(parallel [(set (cc0) 592 (compare:CCFPEQ (match_operand:DF 0 "register_operand" "") 593 (match_operand:DF 1 "register_operand" ""))) 594 (clobber (match_scratch:HI 2 ""))])] 595 "TARGET_80387" 596 " 597{ 598 if (! register_operand (operands[1], DFmode)) 599 operands[1] = copy_to_mode_reg (DFmode, operands[1]); 600}") 601 602(define_expand "cmpsf_cc" 603 [(parallel [(set (cc0) 604 (compare (match_operand:SF 0 "register_operand" "") 605 (match_operand:SF 1 "register_operand" ""))) 606 (clobber (match_scratch:HI 2 ""))])] 607 "TARGET_80387" 608 "") 609 610(define_expand "cmpsf_ccfpeq" 611 [(parallel [(set (cc0) 612 (compare:CCFPEQ (match_operand:SF 0 "register_operand" "") 613 (match_operand:SF 1 "register_operand" ""))) 614 (clobber (match_scratch:HI 2 ""))])] 615 "TARGET_80387" 616 " 617{ 618 if (! register_operand (operands[1], SFmode)) 619 operands[1] = copy_to_mode_reg (SFmode, operands[1]); 620}") 621 622;; logical compare 623 624(define_insn "" 625 [(set (cc0) 626 (and:SI (match_operand:SI 0 "general_operand" "%ro") 627 (match_operand:SI 1 "general_operand" "ri")))] 628 "" 629 "* 630{ 631 /* For small integers, we may actually use testb. */ 632 if (GET_CODE (operands[1]) == CONST_INT 633 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) 634 && (! REG_P (operands[0]) || QI_REG_P (operands[0]))) 635 { 636 /* We may set the sign bit spuriously. */ 637 638 if ((INTVAL (operands[1]) & ~0xff) == 0) 639 { 640 cc_status.flags |= CC_NOT_NEGATIVE; 641 return AS2 (test%B0,%1,%b0); 642 } 643 644 if ((INTVAL (operands[1]) & ~0xff00) == 0) 645 { 646 cc_status.flags |= CC_NOT_NEGATIVE; 647 operands[1] = GEN_INT (INTVAL (operands[1]) >> 8); 648 649 if (QI_REG_P (operands[0])) 650 return AS2 (test%B0,%1,%h0); 651 else 652 { 653 operands[0] = adj_offsettable_operand (operands[0], 1); 654 return AS2 (test%B0,%1,%b0); 655 } 656 } 657 658 if (GET_CODE (operands[0]) == MEM 659 && (INTVAL (operands[1]) & ~0xff0000) == 0) 660 { 661 cc_status.flags |= CC_NOT_NEGATIVE; 662 operands[1] = GEN_INT (INTVAL (operands[1]) >> 16); 663 operands[0] = adj_offsettable_operand (operands[0], 2); 664 return AS2 (test%B0,%1,%b0); 665 } 666 667 if (GET_CODE (operands[0]) == MEM 668 && (INTVAL (operands[1]) & ~0xff000000) == 0) 669 { 670 operands[1] = GEN_INT ((INTVAL (operands[1]) >> 24) & 0xff); 671 operands[0] = adj_offsettable_operand (operands[0], 3); 672 return AS2 (test%B0,%1,%b0); 673 } 674 } 675 676 if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) 677 return AS2 (test%L0,%1,%0); 678 679 return AS2 (test%L1,%0,%1); 680}") 681 682(define_insn "" 683 [(set (cc0) 684 (and:HI (match_operand:HI 0 "general_operand" "%ro") 685 (match_operand:HI 1 "general_operand" "ri")))] 686 "" 687 "* 688{ 689 if (GET_CODE (operands[1]) == CONST_INT 690 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) 691 && (! REG_P (operands[0]) || QI_REG_P (operands[0]))) 692 { 693 if ((INTVAL (operands[1]) & 0xff00) == 0) 694 { 695 /* ??? This might not be necessary. */ 696 if (INTVAL (operands[1]) & 0xffff0000) 697 operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff); 698 699 /* We may set the sign bit spuriously. */ 700 cc_status.flags |= CC_NOT_NEGATIVE; 701 return AS2 (test%B0,%1,%b0); 702 } 703 704 if ((INTVAL (operands[1]) & 0xff) == 0) 705 { 706 operands[1] = GEN_INT ((INTVAL (operands[1]) >> 8) & 0xff); 707 708 if (QI_REG_P (operands[0])) 709 return AS2 (test%B0,%1,%h0); 710 else 711 { 712 operands[0] = adj_offsettable_operand (operands[0], 1); 713 return AS2 (test%B0,%1,%b0); 714 } 715 } 716 } 717 718 if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) 719 return AS2 (test%W0,%1,%0); 720 721 return AS2 (test%W1,%0,%1); 722}") 723 724(define_insn "" 725 [(set (cc0) 726 (and:QI (match_operand:QI 0 "general_operand" "%qm") 727 (match_operand:QI 1 "general_operand" "qi")))] 728 "" 729 "* 730{ 731 if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) 732 return AS2 (test%B0,%1,%0); 733 734 return AS2 (test%B1,%0,%1); 735}") 736 737;; move instructions. 738;; There is one for each machine mode, 739;; and each is preceded by a corresponding push-insn pattern 740;; (since pushes are not general_operands on the 386). 741 742(define_insn "" 743 [(set (match_operand:SI 0 "push_operand" "=<") 744 (match_operand:SI 1 "general_operand" "g"))] 745 "TARGET_386" 746 "push%L0 %1") 747 748;; On a 486, it is faster to move MEM to a REG and then push, rather than 749;; push MEM directly. 750 751(define_insn "" 752 [(set (match_operand:SI 0 "push_operand" "=<") 753 (match_operand:SI 1 "nonmemory_operand" "ri"))] 754 "!TARGET_386 && TARGET_MOVE" 755 "push%L0 %1") 756 757(define_insn "" 758 [(set (match_operand:SI 0 "push_operand" "=<") 759 (match_operand:SI 1 "general_operand" "ri"))] 760 "!TARGET_386 && !TARGET_MOVE" 761 "push%L0 %1") 762 763;; General case of fullword move. 764 765;; If generating PIC code and operands[1] is a symbolic CONST, emit a 766;; move to get the address of the symbolic object from the GOT. 767 768(define_expand "movsi" 769 [(set (match_operand:SI 0 "general_operand" "") 770 (match_operand:SI 1 "general_operand" ""))] 771 "" 772 " 773{ 774 extern int flag_pic; 775 776 if (flag_pic && SYMBOLIC_CONST (operands[1])) 777 emit_pic_move (operands, SImode); 778 779 /* Don't generate memory->memory moves, go through a register */ 780 else if (TARGET_MOVE 781 && (reload_in_progress | reload_completed) == 0 782 && GET_CODE (operands[0]) == MEM 783 && GET_CODE (operands[1]) == MEM) 784 { 785 operands[1] = force_reg (SImode, operands[1]); 786 } 787}") 788 789;; On i486, incl reg is faster than movl $1,reg. 790 791(define_insn "" 792 [(set (match_operand:SI 0 "general_operand" "=g,r") 793 (match_operand:SI 1 "general_operand" "ri,m"))] 794 "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" 795 "* 796{ 797 rtx link; 798 if (operands[1] == const0_rtx && REG_P (operands[0])) 799 return AS2 (xor%L0,%0,%0); 800 801 if (operands[1] == const1_rtx 802 && (link = find_reg_note (insn, REG_WAS_0, 0)) 803 /* Make sure the insn that stored the 0 is still present. */ 804 && ! INSN_DELETED_P (XEXP (link, 0)) 805 && GET_CODE (XEXP (link, 0)) != NOTE 806 /* Make sure cross jumping didn't happen here. */ 807 && no_labels_between_p (XEXP (link, 0), insn) 808 /* Make sure the reg hasn't been clobbered. */ 809 && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) 810 /* Fastest way to change a 0 to a 1. */ 811 return AS1 (inc%L0,%0); 812 813 if (flag_pic && SYMBOLIC_CONST (operands[1])) 814 return AS2 (lea%L0,%a1,%0); 815 816 return AS2 (mov%L0,%1,%0); 817}") 818 819(define_insn "" 820 [(set (match_operand:HI 0 "push_operand" "=<") 821 (match_operand:HI 1 "general_operand" "g"))] 822 "TARGET_386" 823 "push%W0 %1") 824 825(define_insn "" 826 [(set (match_operand:HI 0 "push_operand" "=<") 827 (match_operand:HI 1 "nonmemory_operand" "ri"))] 828 "!TARGET_386 && TARGET_MOVE" 829 "push%W0 %1") 830 831(define_insn "" 832 [(set (match_operand:HI 0 "push_operand" "=<") 833 (match_operand:HI 1 "general_operand" "ri"))] 834 "!TARGET_386 && !TARGET_MOVE" 835 "push%W0 %1") 836 837;; On i486, an incl and movl are both faster than incw and movw. 838 839(define_expand "movhi" 840 [(set (match_operand:HI 0 "general_operand" "") 841 (match_operand:HI 1 "general_operand" ""))] 842 "" 843 " 844{ 845 /* Don't generate memory->memory moves, go through a register */ 846 if (TARGET_MOVE 847 && (reload_in_progress | reload_completed) == 0 848 && GET_CODE (operands[0]) == MEM 849 && GET_CODE (operands[1]) == MEM) 850 { 851 operands[1] = force_reg (HImode, operands[1]); 852 } 853}") 854 855(define_insn "" 856 [(set (match_operand:HI 0 "general_operand" "=g,r") 857 (match_operand:HI 1 "general_operand" "ri,m"))] 858 "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" 859 "* 860{ 861 rtx link; 862 if (REG_P (operands[0]) && operands[1] == const0_rtx) 863 return AS2 (xor%L0,%k0,%k0); 864 865 if (REG_P (operands[0]) && operands[1] == const1_rtx 866 && (link = find_reg_note (insn, REG_WAS_0, 0)) 867 /* Make sure the insn that stored the 0 is still present. */ 868 && ! INSN_DELETED_P (XEXP (link, 0)) 869 && GET_CODE (XEXP (link, 0)) != NOTE 870 /* Make sure cross jumping didn't happen here. */ 871 && no_labels_between_p (XEXP (link, 0), insn) 872 /* Make sure the reg hasn't been clobbered. */ 873 && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) 874 /* Fastest way to change a 0 to a 1. */ 875 return AS1 (inc%L0,%k0); 876 877 if (REG_P (operands[0])) 878 { 879 if (REG_P (operands[1])) 880 return AS2 (mov%L0,%k1,%k0); 881 else if (CONSTANT_P (operands[1])) 882 return AS2 (mov%L0,%1,%k0); 883 } 884 885 return AS2 (mov%W0,%1,%0); 886}") 887 888(define_expand "movstricthi" 889 [(set (strict_low_part (match_operand:HI 0 "general_operand" "")) 890 (match_operand:HI 1 "general_operand" ""))] 891 "" 892 " 893{ 894 /* Don't generate memory->memory moves, go through a register */ 895 if (TARGET_MOVE 896 && (reload_in_progress | reload_completed) == 0 897 && GET_CODE (operands[0]) == MEM 898 && GET_CODE (operands[1]) == MEM) 899 { 900 operands[1] = force_reg (HImode, operands[1]); 901 } 902}") 903 904(define_insn "" 905 [(set (strict_low_part (match_operand:HI 0 "general_operand" "+g,r")) 906 (match_operand:HI 1 "general_operand" "ri,m"))] 907 "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" 908 "* 909{ 910 rtx link; 911 if (operands[1] == const0_rtx && REG_P (operands[0])) 912 return AS2 (xor%W0,%0,%0); 913 914 if (operands[1] == const1_rtx 915 && (link = find_reg_note (insn, REG_WAS_0, 0)) 916 /* Make sure the insn that stored the 0 is still present. */ 917 && ! INSN_DELETED_P (XEXP (link, 0)) 918 && GET_CODE (XEXP (link, 0)) != NOTE 919 /* Make sure cross jumping didn't happen here. */ 920 && no_labels_between_p (XEXP (link, 0), insn) 921 /* Make sure the reg hasn't been clobbered. */ 922 && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) 923 /* Fastest way to change a 0 to a 1. */ 924 return AS1 (inc%W0,%0); 925 926 return AS2 (mov%W0,%1,%0); 927}") 928 929;; emit_push_insn when it calls move_by_pieces 930;; requires an insn to "push a byte". 931;; But actually we use pushw, which has the effect of rounding 932;; the amount pushed up to a halfword. 933(define_insn "" 934 [(set (match_operand:QI 0 "push_operand" "=<") 935 (match_operand:QI 1 "immediate_operand" "n"))] 936 "" 937 "* return AS1 (push%W0,%1);") 938 939(define_insn "" 940 [(set (match_operand:QI 0 "push_operand" "=<") 941 (match_operand:QI 1 "nonimmediate_operand" "q"))] 942 "!TARGET_MOVE" 943 "* 944{ 945 operands[1] = gen_rtx (REG, HImode, REGNO (operands[1])); 946 return AS1 (push%W0,%1); 947}") 948 949(define_insn "" 950 [(set (match_operand:QI 0 "push_operand" "=<") 951 (match_operand:QI 1 "register_operand" "q"))] 952 "TARGET_MOVE" 953 "* 954{ 955 operands[1] = gen_rtx (REG, HImode, REGNO (operands[1])); 956 return AS1 (push%W0,%1); 957}") 958 959;; On i486, incb reg is faster than movb $1,reg. 960 961;; ??? Do a recognizer for zero_extract that looks just like this, but reads 962;; or writes %ah, %bh, %ch, %dh. 963 964(define_expand "movqi" 965 [(set (match_operand:QI 0 "general_operand" "") 966 (match_operand:QI 1 "general_operand" ""))] 967 "" 968 " 969{ 970 /* Don't generate memory->memory moves, go through a register */ 971 if (TARGET_MOVE 972 && (reload_in_progress | reload_completed) == 0 973 && GET_CODE (operands[0]) == MEM 974 && GET_CODE (operands[1]) == MEM) 975 { 976 operands[1] = force_reg (QImode, operands[1]); 977 } 978}") 979 980(define_insn "" 981 [(set (match_operand:QI 0 "general_operand" "=q,*r,qm") 982 (match_operand:QI 1 "general_operand" "*g,q,qn"))] 983 "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" 984 "* 985{ 986 rtx link; 987 if (operands[1] == const0_rtx && REG_P (operands[0])) 988 return AS2 (xor%B0,%0,%0); 989 990 if (operands[1] == const1_rtx 991 && (link = find_reg_note (insn, REG_WAS_0, 0)) 992 /* Make sure the insn that stored the 0 is still present. */ 993 && ! INSN_DELETED_P (XEXP (link, 0)) 994 && GET_CODE (XEXP (link, 0)) != NOTE 995 /* Make sure cross jumping didn't happen here. */ 996 && no_labels_between_p (XEXP (link, 0), insn) 997 /* Make sure the reg hasn't been clobbered. */ 998 && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) 999 /* Fastest way to change a 0 to a 1. */ 1000 return AS1 (inc%B0,%0); 1001 1002 /* If mov%B0 isn't allowed for one of these regs, use mov%L0. */ 1003 if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1])) 1004 return (AS2 (mov%L0,%k1,%k0)); 1005 1006 return (AS2 (mov%B0,%1,%0)); 1007}") 1008 1009;; If it becomes necessary to support movstrictqi into %esi or %edi, 1010;; use the insn sequence: 1011;; 1012;; shrdl $8,srcreg,dstreg 1013;; rorl $24,dstreg 1014;; 1015;; If operands[1] is a constant, then an andl/orl sequence would be 1016;; faster. 1017 1018(define_expand "movstrictqi" 1019 [(set (strict_low_part (match_operand:QI 0 "general_operand" "")) 1020 (match_operand:QI 1 "general_operand" ""))] 1021 "" 1022 " 1023{ 1024 /* Don't generate memory->memory moves, go through a register */ 1025 if (TARGET_MOVE 1026 && (reload_in_progress | reload_completed) == 0 1027 && GET_CODE (operands[0]) == MEM 1028 && GET_CODE (operands[1]) == MEM) 1029 { 1030 operands[1] = force_reg (QImode, operands[1]); 1031 } 1032}") 1033 1034(define_insn "" 1035 [(set (strict_low_part (match_operand:QI 0 "general_operand" "+qm,q")) 1036 (match_operand:QI 1 "general_operand" "*qn,m"))] 1037 "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" 1038 "* 1039{ 1040 rtx link; 1041 if (operands[1] == const0_rtx && REG_P (operands[0])) 1042 return AS2 (xor%B0,%0,%0); 1043 1044 if (operands[1] == const1_rtx 1045 && (link = find_reg_note (insn, REG_WAS_0, 0)) 1046 /* Make sure the insn that stored the 0 is still present. */ 1047 && ! INSN_DELETED_P (XEXP (link, 0)) 1048 && GET_CODE (XEXP (link, 0)) != NOTE 1049 /* Make sure cross jumping didn't happen here. */ 1050 && no_labels_between_p (XEXP (link, 0), insn) 1051 /* Make sure the reg hasn't been clobbered. */ 1052 && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) 1053 /* Fastest way to change a 0 to a 1. */ 1054 return AS1 (inc%B0,%0); 1055 1056 /* If mov%B0 isn't allowed for one of these regs, use mov%L0. */ 1057 if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1])) 1058 { 1059 abort (); 1060 return (AS2 (mov%L0,%k1,%k0)); 1061 } 1062 1063 return AS2 (mov%B0,%1,%0); 1064}") 1065 1066(define_expand "movsf" 1067 [(set (match_operand:SF 0 "general_operand" "") 1068 (match_operand:SF 1 "general_operand" ""))] 1069 "" 1070 " 1071{ 1072 /* Special case memory->memory moves and pushes */ 1073 if (TARGET_MOVE 1074 && (reload_in_progress | reload_completed) == 0 1075 && GET_CODE (operands[0]) == MEM 1076 && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], SFmode))) 1077 { 1078 rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], SFmode)) 1079 ? gen_movsf_push 1080 : gen_movsf_mem; 1081 1082 emit_insn ((*genfunc) (operands[0], operands[1])); 1083 DONE; 1084 } 1085 1086 /* If we are loading a floating point constant that isn't 0 or 1 into a register, 1087 indicate we need the pic register loaded. This could be optimized into stores 1088 of constants if the target eventually moves to memory, but better safe than 1089 sorry. */ 1090 if (flag_pic 1091 && GET_CODE (operands[0]) != MEM 1092 && GET_CODE (operands[1]) == CONST_DOUBLE 1093 && !standard_80387_constant_p (operands[1])) 1094 { 1095 current_function_uses_pic_offset_table = 1; 1096 } 1097}") 1098 1099(define_insn "movsf_push_nomove" 1100 [(set (match_operand:SF 0 "push_operand" "=<,<") 1101 (match_operand:SF 1 "general_operand" "gF,f"))] 1102 "!TARGET_MOVE" 1103 "* 1104{ 1105 if (STACK_REG_P (operands[1])) 1106 { 1107 rtx xops[3]; 1108 1109 if (! STACK_TOP_P (operands[1])) 1110 abort (); 1111 1112 xops[0] = AT_SP (SFmode); 1113 xops[1] = GEN_INT (4); 1114 xops[2] = stack_pointer_rtx; 1115 1116 output_asm_insn (AS2 (sub%L2,%1,%2), xops); 1117 1118 if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) 1119 output_asm_insn (AS1 (fstp%S0,%0), xops); 1120 else 1121 output_asm_insn (AS1 (fst%S0,%0), xops); 1122 RET; 1123 } 1124 return AS1 (push%L1,%1); 1125}") 1126 1127(define_insn "movsf_push" 1128 [(set (match_operand:SF 0 "push_operand" "=<,<,<,<") 1129 (match_operand:SF 1 "general_operand" "rF,f,m,m")) 1130 (clobber (match_scratch:SI 2 "=X,X,r,X"))] 1131 "" 1132 "* 1133{ 1134 if (STACK_REG_P (operands[1])) 1135 { 1136 rtx xops[3]; 1137 1138 if (! STACK_TOP_P (operands[1])) 1139 abort (); 1140 1141 xops[0] = AT_SP (SFmode); 1142 xops[1] = GEN_INT (4); 1143 xops[2] = stack_pointer_rtx; 1144 1145 output_asm_insn (AS2 (sub%L2,%1,%2), xops); 1146 1147 if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) 1148 output_asm_insn (AS1 (fstp%S0,%0), xops); 1149 else 1150 output_asm_insn (AS1 (fst%S0,%0), xops); 1151 RET; 1152 } 1153 1154 else if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != REG) 1155 return AS1 (push%L1,%1); 1156 1157 else 1158 { 1159 output_asm_insn (AS2 (mov%L2,%1,%2), operands); 1160 return AS1 (push%L2,%2); 1161 } 1162}") 1163 1164;; Special memory<->memory pattern that combine will recreate from the 1165;; moves to pseudos. 1166(define_insn "movsf_mem" 1167 [(set (match_operand:SF 0 "memory_operand" "=m") 1168 (match_operand:SF 1 "memory_operand" "m")) 1169 (clobber (match_scratch:SI 2 "=&r"))] 1170 "" 1171 "* 1172{ 1173 output_asm_insn (AS2 (mov%L2,%1,%2), operands); 1174 return AS2 (mov%L0,%2,%0); 1175}") 1176 1177;; For the purposes of regclass, prefer FLOAT_REGS. 1178(define_insn "movsf_normal" 1179 [(set (match_operand:SF 0 "general_operand" "=*rfm,*rf,f,!*rm") 1180 (match_operand:SF 1 "general_operand" "*rf,*rfm,fG,fF"))] 1181 "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" 1182 "* 1183{ 1184 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 1185 1186 /* First handle a `pop' insn or a `fld %st(0)' */ 1187 1188 if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1])) 1189 { 1190 if (stack_top_dies) 1191 return AS1 (fstp,%y0); 1192 else 1193 return AS1 (fld,%y0); 1194 } 1195 1196 /* Handle a transfer between the 387 and a 386 register */ 1197 1198 if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1])) 1199 { 1200 output_op_from_reg (operands[1], AS1 (fld%z0,%y1)); 1201 RET; 1202 } 1203 1204 if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0])) 1205 { 1206 output_to_reg (operands[0], stack_top_dies); 1207 RET; 1208 } 1209 1210 /* Handle other kinds of writes from the 387 */ 1211 1212 if (STACK_TOP_P (operands[1])) 1213 { 1214 if (stack_top_dies) 1215 return AS1 (fstp%z0,%y0); 1216 else 1217 return AS1 (fst%z0,%y0); 1218 } 1219 1220 /* Handle other kinds of reads to the 387 */ 1221 1222 if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE) 1223 return output_move_const_single (operands); 1224 1225 if (STACK_TOP_P (operands[0])) 1226 return AS1 (fld%z1,%y1); 1227 1228 /* Handle all SFmode moves not involving the 387 */ 1229 1230 return singlemove_string (operands); 1231}") 1232 1233(define_insn "swapsf" 1234 [(set (match_operand:SF 0 "register_operand" "f") 1235 (match_operand:SF 1 "register_operand" "f")) 1236 (set (match_dup 1) 1237 (match_dup 0))] 1238 "" 1239 "* 1240{ 1241 if (STACK_TOP_P (operands[0])) 1242 return AS1 (fxch,%1); 1243 else 1244 return AS1 (fxch,%0); 1245}") 1246 1247(define_expand "movdf" 1248 [(set (match_operand:DF 0 "general_operand" "") 1249 (match_operand:DF 1 "general_operand" ""))] 1250 "" 1251 " 1252{ 1253 /* Special case memory->memory moves and pushes */ 1254 if (TARGET_MOVE 1255 && (reload_in_progress | reload_completed) == 0 1256 && GET_CODE (operands[0]) == MEM 1257 && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], DFmode))) 1258 { 1259 rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], DFmode)) 1260 ? gen_movdf_push 1261 : gen_movdf_mem; 1262 1263 emit_insn ((*genfunc) (operands[0], operands[1])); 1264 DONE; 1265 } 1266 1267 /* If we are loading a floating point constant that isn't 0 or 1 into a register, 1268 indicate we need the pic register loaded. This could be optimized into stores 1269 of constants if the target eventually moves to memory, but better safe than 1270 sorry. */ 1271 if (flag_pic 1272 && GET_CODE (operands[0]) != MEM 1273 && GET_CODE (operands[1]) == CONST_DOUBLE 1274 && !standard_80387_constant_p (operands[1])) 1275 { 1276 current_function_uses_pic_offset_table = 1; 1277 } 1278}") 1279 1280(define_insn "movdf_push_nomove" 1281 [(set (match_operand:DF 0 "push_operand" "=<,<") 1282 (match_operand:DF 1 "general_operand" "gF,f"))] 1283 "!TARGET_MOVE" 1284 "* 1285{ 1286 if (STACK_REG_P (operands[1])) 1287 { 1288 rtx xops[3]; 1289 1290 xops[0] = AT_SP (SFmode); 1291 xops[1] = GEN_INT (8); 1292 xops[2] = stack_pointer_rtx; 1293 1294 output_asm_insn (AS2 (sub%L2,%1,%2), xops); 1295 1296 if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) 1297 output_asm_insn (AS1 (fstp%Q0,%0), xops); 1298 else 1299 output_asm_insn (AS1 (fst%Q0,%0), xops); 1300 1301 RET; 1302 } 1303 else 1304 return output_move_double (operands); 1305}") 1306 1307(define_insn "movdf_push" 1308 [(set (match_operand:DF 0 "push_operand" "=<,<,<,<,<") 1309 (match_operand:DF 1 "general_operand" "rF,f,o,o,o")) 1310 (clobber (match_scratch:SI 2 "=X,X,&r,&r,X")) 1311 (clobber (match_scratch:SI 3 "=X,X,&r,X,X"))] 1312 "" 1313 "* 1314{ 1315 if (STACK_REG_P (operands[1])) 1316 { 1317 rtx xops[3]; 1318 1319 xops[0] = AT_SP (SFmode); 1320 xops[1] = GEN_INT (8); 1321 xops[2] = stack_pointer_rtx; 1322 1323 output_asm_insn (AS2 (sub%L2,%1,%2), xops); 1324 1325 if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) 1326 output_asm_insn (AS1 (fstp%Q0,%0), xops); 1327 else 1328 output_asm_insn (AS1 (fst%Q0,%0), xops); 1329 1330 RET; 1331 } 1332 1333 else if (GET_CODE (operands[1]) != MEM) 1334 return output_move_double (operands); 1335 1336 else 1337 return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 2, 4); 1338}") 1339 1340(define_insn "movdf_mem" 1341 [(set (match_operand:DF 0 "memory_operand" "=o,o") 1342 (match_operand:DF 1 "memory_operand" "o,o")) 1343 (clobber (match_scratch:SI 2 "=&r,&r")) 1344 (clobber (match_scratch:SI 3 "=&r,X"))] 1345 "" 1346 "* return output_move_memory (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);") 1347 1348;; For the purposes of regclass, prefer FLOAT_REGS. 1349(define_insn "movdf_normal" 1350 [(set (match_operand:DF 0 "general_operand" "=f,fm,!*rf,!*rm") 1351 (match_operand:DF 1 "general_operand" "fmG,f,*rfm,*rfF"))] 1352 "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" 1353 "* 1354{ 1355 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 1356 1357 /* First handle a `pop' insn or a `fld %st(0)' */ 1358 1359 if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1])) 1360 { 1361 if (stack_top_dies) 1362 return AS1 (fstp,%y0); 1363 else 1364 return AS1 (fld,%y0); 1365 } 1366 1367 /* Handle a transfer between the 387 and a 386 register */ 1368 1369 if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1])) 1370 { 1371 output_op_from_reg (operands[1], AS1 (fld%z0,%y1)); 1372 RET; 1373 } 1374 1375 if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0])) 1376 { 1377 output_to_reg (operands[0], stack_top_dies); 1378 RET; 1379 } 1380 1381 /* Handle other kinds of writes from the 387 */ 1382 1383 if (STACK_TOP_P (operands[1])) 1384 { 1385 if (stack_top_dies) 1386 return AS1 (fstp%z0,%y0); 1387 else 1388 return AS1 (fst%z0,%y0); 1389 } 1390 1391 /* Handle other kinds of reads to the 387 */ 1392 1393 if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE) 1394 return output_move_const_single (operands); 1395 1396 if (STACK_TOP_P (operands[0])) 1397 return AS1 (fld%z1,%y1); 1398 1399 /* Handle all DFmode moves not involving the 387 */ 1400 1401 return output_move_double (operands); 1402}") 1403 1404(define_insn "swapdf" 1405 [(set (match_operand:DF 0 "register_operand" "f") 1406 (match_operand:DF 1 "register_operand" "f")) 1407 (set (match_dup 1) 1408 (match_dup 0))] 1409 "" 1410 "* 1411{ 1412 if (STACK_TOP_P (operands[0])) 1413 return AS1 (fxch,%1); 1414 else 1415 return AS1 (fxch,%0); 1416}") 1417 1418(define_expand "movxf" 1419 [(set (match_operand:XF 0 "general_operand" "") 1420 (match_operand:XF 1 "general_operand" ""))] 1421 "" 1422 " 1423{ 1424 /* Special case memory->memory moves and pushes */ 1425 if (TARGET_MOVE 1426 && (reload_in_progress | reload_completed) == 0 1427 && GET_CODE (operands[0]) == MEM 1428 && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], XFmode))) 1429 { 1430 rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], XFmode)) 1431 ? gen_movxf_push 1432 : gen_movxf_mem; 1433 1434 emit_insn ((*genfunc) (operands[0], operands[1])); 1435 DONE; 1436 } 1437 1438 /* If we are loading a floating point constant that isn't 0 or 1 into a register, 1439 indicate we need the pic register loaded. This could be optimized into stores 1440 of constants if the target eventually moves to memory, but better safe than 1441 sorry. */ 1442 if (flag_pic 1443 && GET_CODE (operands[0]) != MEM 1444 && GET_CODE (operands[1]) == CONST_DOUBLE 1445 && !standard_80387_constant_p (operands[1])) 1446 { 1447 current_function_uses_pic_offset_table = 1; 1448 } 1449}") 1450 1451 1452(define_insn "movxf_push_nomove" 1453 [(set (match_operand:XF 0 "push_operand" "=<,<") 1454 (match_operand:XF 1 "general_operand" "gF,f"))] 1455 "!TARGET_MOVE" 1456 "* 1457{ 1458 if (STACK_REG_P (operands[1])) 1459 { 1460 rtx xops[3]; 1461 1462 xops[0] = AT_SP (SFmode); 1463 xops[1] = GEN_INT (12); 1464 xops[2] = stack_pointer_rtx; 1465 1466 output_asm_insn (AS2 (sub%L2,%1,%2), xops); 1467 output_asm_insn (AS1 (fstp%T0,%0), xops); 1468 if (! find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) 1469 output_asm_insn (AS1 (fld%T0,%0), xops); 1470 1471 RET; 1472 } 1473 else 1474 return output_move_double (operands); 1475 }") 1476 1477(define_insn "movxf_push" 1478 [(set (match_operand:XF 0 "push_operand" "=<,<,<,<,<") 1479 (match_operand:XF 1 "general_operand" "rF,f,o,o,o")) 1480 (clobber (match_scratch:SI 2 "=X,X,&r,&r,X")) 1481 (clobber (match_scratch:SI 3 "=X,X,&r,X,X"))] 1482 "" 1483 "* 1484{ 1485 if (STACK_REG_P (operands[1])) 1486 { 1487 rtx xops[3]; 1488 1489 xops[0] = AT_SP (SFmode); 1490 xops[1] = GEN_INT (12); 1491 xops[2] = stack_pointer_rtx; 1492 1493 output_asm_insn (AS2 (sub%L2,%1,%2), xops); 1494 output_asm_insn (AS1 (fstp%T0,%0), xops); 1495 if (! find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) 1496 output_asm_insn (AS1 (fld%T0,%0), xops); 1497 1498 RET; 1499 } 1500 1501 else if (GET_CODE (operands[1]) != MEM 1502 || GET_CODE (operands[2]) != REG) 1503 return output_move_double (operands); 1504 1505 else 1506 return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 2, 4); 1507}") 1508 1509(define_insn "movxf_mem" 1510 [(set (match_operand:XF 0 "memory_operand" "=o,o") 1511 (match_operand:XF 1 "memory_operand" "o,o")) 1512 (clobber (match_scratch:SI 2 "=&r,&r")) 1513 (clobber (match_scratch:SI 3 "=&r,X"))] 1514 "" 1515 "* return output_move_memory (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);") 1516 1517(define_insn "movxf_normal" 1518 [(set (match_operand:XF 0 "general_operand" "=f,fm,!*rf,!*rm") 1519 (match_operand:XF 1 "general_operand" "fmG,f,*rfm,*rfF"))] 1520 "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" 1521 "* 1522{ 1523 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 1524 1525 /* First handle a `pop' insn or a `fld %st(0)' */ 1526 1527 if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1])) 1528 { 1529 if (stack_top_dies) 1530 return AS1 (fstp,%y0); 1531 else 1532 return AS1 (fld,%y0); 1533 } 1534 1535 /* Handle a transfer between the 387 and a 386 register */ 1536 1537 if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1])) 1538 { 1539 output_op_from_reg (operands[1], AS1 (fld%z0,%y1)); 1540 RET; 1541 } 1542 1543 if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0])) 1544 { 1545 output_to_reg (operands[0], stack_top_dies); 1546 RET; 1547 } 1548 1549 /* Handle other kinds of writes from the 387 */ 1550 1551 if (STACK_TOP_P (operands[1])) 1552 { 1553 output_asm_insn (AS1 (fstp%z0,%y0), operands); 1554 if (! stack_top_dies) 1555 return AS1 (fld%z0,%y0); 1556 1557 RET; 1558 } 1559 1560 /* Handle other kinds of reads to the 387 */ 1561 1562 if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE) 1563 return output_move_const_single (operands); 1564 1565 if (STACK_TOP_P (operands[0])) 1566 return AS1 (fld%z1,%y1); 1567 1568 /* Handle all XFmode moves not involving the 387 */ 1569 1570 return output_move_double (operands); 1571}") 1572 1573(define_insn "swapxf" 1574 [(set (match_operand:XF 0 "register_operand" "f") 1575 (match_operand:XF 1 "register_operand" "f")) 1576 (set (match_dup 1) 1577 (match_dup 0))] 1578 "" 1579 "* 1580{ 1581 if (STACK_TOP_P (operands[0])) 1582 return AS1 (fxch,%1); 1583 else 1584 return AS1 (fxch,%0); 1585}") 1586 1587(define_insn "" 1588 [(set (match_operand:DI 0 "push_operand" "=<,<,<,<") 1589 (match_operand:DI 1 "general_operand" "riF,o,o,o")) 1590 (clobber (match_scratch:SI 2 "=X,&r,&r,X")) 1591 (clobber (match_scratch:SI 3 "=X,&r,X,X"))] 1592 "" 1593 "* 1594{ 1595 if (GET_CODE (operands[1]) != MEM) 1596 return output_move_double (operands); 1597 1598 else 1599 return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode), 2, 4); 1600}") 1601 1602(define_insn "movdi" 1603 [(set (match_operand:DI 0 "general_operand" "=o,o,r,rm") 1604 (match_operand:DI 1 "general_operand" "o,o,m,riF")) 1605 (clobber (match_scratch:SI 2 "=&r,&r,X,X")) 1606 (clobber (match_scratch:SI 3 "=&r,X,X,X"))] 1607 "" 1608 "* 1609{ 1610 rtx low[2], high[2], xop[6]; 1611 1612 if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) 1613 return output_move_double (operands); 1614 else 1615 return output_move_memory (operands, insn, GET_MODE_SIZE (DImode), 2, 4); 1616}") 1617 1618 1619;;- conversion instructions 1620;;- NONE 1621 1622;;- zero extension instructions 1623;; See comments by `andsi' for when andl is faster than movzx. 1624 1625(define_insn "zero_extendhisi2" 1626 [(set (match_operand:SI 0 "general_operand" "=r") 1627 (zero_extend:SI 1628 (match_operand:HI 1 "nonimmediate_operand" "rm")))] 1629 "" 1630 "* 1631{ 1632 if ((!TARGET_386 || REGNO (operands[0]) == 0) 1633 && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])) 1634 { 1635 rtx xops[2]; 1636 xops[0] = operands[0]; 1637 xops[1] = GEN_INT (0xffff); 1638 output_asm_insn (AS2 (and%L0,%1,%k0), xops); 1639 RET; 1640 } 1641 1642#ifdef INTEL_SYNTAX 1643 return AS2 (movzx,%1,%0); 1644#else 1645 return AS2 (movz%W0%L0,%1,%0); 1646#endif 1647}") 1648 1649(define_insn "zero_extendqihi2" 1650 [(set (match_operand:HI 0 "general_operand" "=r") 1651 (zero_extend:HI 1652 (match_operand:QI 1 "nonimmediate_operand" "qm")))] 1653 "" 1654 "* 1655{ 1656 if ((!TARGET_386 || REGNO (operands[0]) == 0) 1657 && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])) 1658 { 1659 rtx xops[2]; 1660 xops[0] = operands[0]; 1661 xops[1] = GEN_INT (0xff); 1662 output_asm_insn (AS2 (and%L0,%1,%k0), xops); 1663 RET; 1664 } 1665 1666#ifdef INTEL_SYNTAX 1667 return AS2 (movzx,%1,%0); 1668#else 1669 return AS2 (movz%B0%W0,%1,%0); 1670#endif 1671}") 1672 1673(define_insn "zero_extendqisi2" 1674 [(set (match_operand:SI 0 "general_operand" "=r") 1675 (zero_extend:SI 1676 (match_operand:QI 1 "nonimmediate_operand" "qm")))] 1677 "" 1678 "* 1679{ 1680 if ((!TARGET_386 || REGNO (operands[0]) == 0) 1681 && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])) 1682 { 1683 rtx xops[2]; 1684 xops[0] = operands[0]; 1685 xops[1] = GEN_INT (0xff); 1686 output_asm_insn (AS2 (and%L0,%1,%k0), xops); 1687 RET; 1688 } 1689 1690#ifdef INTEL_SYNTAX 1691 return AS2 (movzx,%1,%0); 1692#else 1693 return AS2 (movz%B0%L0,%1,%0); 1694#endif 1695}") 1696 1697(define_insn "zero_extendsidi2" 1698 [(set (match_operand:DI 0 "register_operand" "=r") 1699 (zero_extend:DI 1700 (match_operand:SI 1 "register_operand" "0")))] 1701 "" 1702 "* 1703{ 1704 operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); 1705 return AS2 (xor%L0,%0,%0); 1706}") 1707 1708;;- sign extension instructions 1709 1710(define_insn "extendsidi2" 1711 [(set (match_operand:DI 0 "register_operand" "=r") 1712 (sign_extend:DI 1713 (match_operand:SI 1 "register_operand" "0")))] 1714 "" 1715 "* 1716{ 1717 if (REGNO (operands[0]) == 0) 1718 { 1719 /* This used to be cwtl, but that extends HI to SI somehow. */ 1720#ifdef INTEL_SYNTAX 1721 return \"cdq\"; 1722#else 1723 return \"cltd\"; 1724#endif 1725 } 1726 1727 operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); 1728 output_asm_insn (AS2 (mov%L0,%0,%1), operands); 1729 1730 operands[0] = GEN_INT (31); 1731 return AS2 (sar%L1,%0,%1); 1732}") 1733 1734;; Note that the i386 programmers' manual says that the opcodes 1735;; are named movsx..., but the assembler on Unix does not accept that. 1736;; We use what the Unix assembler expects. 1737 1738(define_insn "extendhisi2" 1739 [(set (match_operand:SI 0 "general_operand" "=r") 1740 (sign_extend:SI 1741 (match_operand:HI 1 "nonimmediate_operand" "rm")))] 1742 "" 1743 "* 1744{ 1745 if (REGNO (operands[0]) == 0 1746 && REG_P (operands[1]) && REGNO (operands[1]) == 0) 1747#ifdef INTEL_SYNTAX 1748 return \"cwde\"; 1749#else 1750 return \"cwtl\"; 1751#endif 1752 1753#ifdef INTEL_SYNTAX 1754 return AS2 (movsx,%1,%0); 1755#else 1756 return AS2 (movs%W0%L0,%1,%0); 1757#endif 1758}") 1759 1760(define_insn "extendqihi2" 1761 [(set (match_operand:HI 0 "general_operand" "=r") 1762 (sign_extend:HI 1763 (match_operand:QI 1 "nonimmediate_operand" "qm")))] 1764 "" 1765 "* 1766{ 1767 if (REGNO (operands[0]) == 0 1768 && REG_P (operands[1]) && REGNO (operands[1]) == 0) 1769 return \"cbtw\"; 1770 1771#ifdef INTEL_SYNTAX 1772 return AS2 (movsx,%1,%0); 1773#else 1774 return AS2 (movs%B0%W0,%1,%0); 1775#endif 1776}") 1777 1778(define_insn "extendqisi2" 1779 [(set (match_operand:SI 0 "general_operand" "=r") 1780 (sign_extend:SI 1781 (match_operand:QI 1 "nonimmediate_operand" "qm")))] 1782 "" 1783 "* 1784{ 1785#ifdef INTEL_SYNTAX 1786 return AS2 (movsx,%1,%0); 1787#else 1788 return AS2 (movs%B0%L0,%1,%0); 1789#endif 1790}") 1791 1792;; Conversions between float and double. 1793 1794(define_insn "extendsfdf2" 1795 [(set (match_operand:DF 0 "general_operand" "=fm,f") 1796 (float_extend:DF 1797 (match_operand:SF 1 "general_operand" "f,fm")))] 1798 "TARGET_80387" 1799 "* 1800{ 1801 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 1802 1803 if (NON_STACK_REG_P (operands[1])) 1804 { 1805 output_op_from_reg (operands[1], AS1 (fld%z0,%y1)); 1806 RET; 1807 } 1808 1809 if (NON_STACK_REG_P (operands[0])) 1810 { 1811 output_to_reg (operands[0], stack_top_dies); 1812 RET; 1813 } 1814 1815 if (STACK_TOP_P (operands[0])) 1816 return AS1 (fld%z1,%y1); 1817 1818 if (GET_CODE (operands[0]) == MEM) 1819 { 1820 if (stack_top_dies) 1821 return AS1 (fstp%z0,%y0); 1822 else 1823 return AS1 (fst%z0,%y0); 1824 } 1825 1826 abort (); 1827}") 1828 1829(define_insn "extenddfxf2" 1830 [(set (match_operand:XF 0 "general_operand" "=fm,f,f,!*r") 1831 (float_extend:XF 1832 (match_operand:DF 1 "general_operand" "f,fm,!*r,f")))] 1833 "TARGET_80387" 1834 "* 1835{ 1836 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 1837 1838 if (NON_STACK_REG_P (operands[1])) 1839 { 1840 output_op_from_reg (operands[1], AS1 (fld%z0,%y1)); 1841 RET; 1842 } 1843 1844 if (NON_STACK_REG_P (operands[0])) 1845 { 1846 output_to_reg (operands[0], stack_top_dies); 1847 RET; 1848 } 1849 1850 if (STACK_TOP_P (operands[0])) 1851 return AS1 (fld%z1,%y1); 1852 1853 if (GET_CODE (operands[0]) == MEM) 1854 { 1855 output_asm_insn (AS1 (fstp%z0,%y0), operands); 1856 if (! stack_top_dies) 1857 return AS1 (fld%z0,%y0); 1858 RET; 1859 } 1860 1861 abort (); 1862}") 1863 1864(define_insn "extendsfxf2" 1865 [(set (match_operand:XF 0 "general_operand" "=fm,f,f,!*r") 1866 (float_extend:XF 1867 (match_operand:SF 1 "general_operand" "f,fm,!*r,f")))] 1868 "TARGET_80387" 1869 "* 1870{ 1871 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 1872 1873 if (NON_STACK_REG_P (operands[1])) 1874 { 1875 output_op_from_reg (operands[1], AS1 (fld%z0,%y1)); 1876 RET; 1877 } 1878 1879 if (NON_STACK_REG_P (operands[0])) 1880 { 1881 output_to_reg (operands[0], stack_top_dies); 1882 RET; 1883 } 1884 1885 if (STACK_TOP_P (operands[0])) 1886 return AS1 (fld%z1,%y1); 1887 1888 if (GET_CODE (operands[0]) == MEM) 1889 { 1890 output_asm_insn (AS1 (fstp%z0,%y0), operands); 1891 if (! stack_top_dies) 1892 return AS1 (fld%z0,%y0); 1893 RET; 1894 } 1895 1896 abort (); 1897}") 1898 1899(define_expand "truncdfsf2" 1900 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "") 1901 (float_truncate:SF 1902 (match_operand:DF 1 "register_operand" ""))) 1903 (clobber (match_dup 2))])] 1904 "TARGET_80387" 1905 " 1906{ 1907 operands[2] = (rtx) assign_386_stack_local (SFmode, 0); 1908}") 1909 1910;; This cannot output into an f-reg because there is no way to be sure 1911;; of truncating in that case. Otherwise this is just like a simple move 1912;; insn. So we pretend we can output to a reg in order to get better 1913;; register preferencing, but we really use a stack slot. 1914 1915(define_insn "" 1916 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m") 1917 (float_truncate:SF 1918 (match_operand:DF 1 "register_operand" "0,f"))) 1919 (clobber (match_operand:SF 2 "memory_operand" "m,m"))] 1920 "TARGET_80387" 1921 "* 1922{ 1923 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 1924 1925 if (GET_CODE (operands[0]) == MEM) 1926 { 1927 if (stack_top_dies) 1928 return AS1 (fstp%z0,%0); 1929 else 1930 return AS1 (fst%z0,%0); 1931 } 1932 else if (STACK_TOP_P (operands[0])) 1933 { 1934 output_asm_insn (AS1 (fstp%z2,%y2), operands); 1935 return AS1 (fld%z2,%y2); 1936 } 1937 else 1938 abort (); 1939}") 1940 1941(define_insn "truncxfsf2" 1942 [(set (match_operand:SF 0 "general_operand" "=m,!*r") 1943 (float_truncate:SF 1944 (match_operand:XF 1 "register_operand" "f,f")))] 1945 "TARGET_80387" 1946 "* 1947{ 1948 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 1949 1950 if (NON_STACK_REG_P (operands[0])) 1951 { 1952 if (stack_top_dies == 0) 1953 { 1954 output_asm_insn (AS1 (fld,%y1), operands); 1955 stack_top_dies = 1; 1956 } 1957 output_to_reg (operands[0], stack_top_dies); 1958 RET; 1959 } 1960 else if (GET_CODE (operands[0]) == MEM) 1961 { 1962 if (stack_top_dies) 1963 return AS1 (fstp%z0,%0); 1964 else 1965 { 1966 output_asm_insn (AS1 (fld,%y1), operands); 1967 return AS1 (fstp%z0,%0); 1968 } 1969 } 1970 else 1971 abort (); 1972}") 1973 1974(define_insn "truncxfdf2" 1975 [(set (match_operand:DF 0 "general_operand" "=m,!*r") 1976 (float_truncate:DF 1977 (match_operand:XF 1 "register_operand" "f,f")))] 1978 "TARGET_80387" 1979 "* 1980{ 1981 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 1982 1983 if (NON_STACK_REG_P (operands[0])) 1984 { 1985 if (stack_top_dies == 0) 1986 { 1987 output_asm_insn (AS1 (fld,%y1), operands); 1988 stack_top_dies = 1; 1989 } 1990 output_to_reg (operands[0], stack_top_dies); 1991 RET; 1992 } 1993 else if (GET_CODE (operands[0]) == MEM) 1994 { 1995 if (stack_top_dies) 1996 return AS1 (fstp%z0,%0); 1997 else 1998 { 1999 output_asm_insn (AS1 (fld,%y1), operands); 2000 return AS1 (fstp%z0,%0); 2001 } 2002 } 2003 else 2004 abort (); 2005}") 2006 2007 2008;; The 387 requires that the stack top dies after converting to DImode. 2009 2010;; Represent an unsigned conversion from SImode to MODE_FLOAT by first 2011;; doing a signed conversion to DImode, and then taking just the low 2012;; part. 2013 2014(define_expand "fixuns_truncxfsi2" 2015 [(set (match_dup 4) 2016 (match_operand:XF 1 "register_operand" "")) 2017 (parallel [(set (match_dup 2) 2018 (fix:DI (fix:XF (match_dup 4)))) 2019 (clobber (match_dup 4)) 2020 (clobber (match_dup 5)) 2021 (clobber (match_dup 6)) 2022 (clobber (match_scratch:SI 7 ""))]) 2023 (set (match_operand:SI 0 "general_operand" "") 2024 (match_dup 3))] 2025 "TARGET_80387" 2026 " 2027{ 2028 operands[2] = gen_reg_rtx (DImode); 2029 operands[3] = gen_lowpart (SImode, operands[2]); 2030 operands[4] = gen_reg_rtx (XFmode); 2031 operands[5] = (rtx) assign_386_stack_local (SImode, 0); 2032 operands[6] = (rtx) assign_386_stack_local (SImode, 1); 2033}") 2034 2035(define_expand "fixuns_truncdfsi2" 2036 [(set (match_dup 4) 2037 (match_operand:DF 1 "register_operand" "")) 2038 (parallel [(set (match_dup 2) 2039 (fix:DI (fix:DF (match_dup 4)))) 2040 (clobber (match_dup 4)) 2041 (clobber (match_dup 5)) 2042 (clobber (match_dup 6)) 2043 (clobber (match_scratch:SI 7 ""))]) 2044 (set (match_operand:SI 0 "general_operand" "") 2045 (match_dup 3))] 2046 "TARGET_80387" 2047 " 2048{ 2049 operands[2] = gen_reg_rtx (DImode); 2050 operands[3] = gen_lowpart (SImode, operands[2]); 2051 operands[4] = gen_reg_rtx (DFmode); 2052 operands[5] = (rtx) assign_386_stack_local (SImode, 0); 2053 operands[6] = (rtx) assign_386_stack_local (SImode, 1); 2054}") 2055 2056(define_expand "fixuns_truncsfsi2" 2057 [(set (match_dup 4) 2058 (match_operand:SF 1 "register_operand" "")) 2059 (parallel [(set (match_dup 2) 2060 (fix:DI (fix:SF (match_dup 4)))) 2061 (clobber (match_dup 4)) 2062 (clobber (match_dup 5)) 2063 (clobber (match_dup 6)) 2064 (clobber (match_scratch:SI 7 ""))]) 2065 (set (match_operand:SI 0 "general_operand" "") 2066 (match_dup 3))] 2067 "TARGET_80387" 2068 " 2069{ 2070 operands[2] = gen_reg_rtx (DImode); 2071 operands[3] = gen_lowpart (SImode, operands[2]); 2072 operands[4] = gen_reg_rtx (SFmode); 2073 operands[5] = (rtx) assign_386_stack_local (SImode, 0); 2074 operands[6] = (rtx) assign_386_stack_local (SImode, 1); 2075}") 2076 2077;; Signed conversion to DImode. 2078 2079(define_expand "fix_truncxfdi2" 2080 [(set (match_dup 2) 2081 (match_operand:XF 1 "register_operand" "")) 2082 (parallel [(set (match_operand:DI 0 "general_operand" "") 2083 (fix:DI (fix:XF (match_dup 2)))) 2084 (clobber (match_dup 2)) 2085 (clobber (match_dup 3)) 2086 (clobber (match_dup 4)) 2087 (clobber (match_scratch:SI 5 ""))])] 2088 "TARGET_80387" 2089 " 2090{ 2091 operands[1] = copy_to_mode_reg (XFmode, operands[1]); 2092 operands[2] = gen_reg_rtx (XFmode); 2093 operands[3] = (rtx) assign_386_stack_local (SImode, 0); 2094 operands[4] = (rtx) assign_386_stack_local (SImode, 1); 2095}") 2096 2097(define_expand "fix_truncdfdi2" 2098 [(set (match_dup 2) 2099 (match_operand:DF 1 "register_operand" "")) 2100 (parallel [(set (match_operand:DI 0 "general_operand" "") 2101 (fix:DI (fix:DF (match_dup 2)))) 2102 (clobber (match_dup 2)) 2103 (clobber (match_dup 3)) 2104 (clobber (match_dup 4)) 2105 (clobber (match_scratch:SI 5 ""))])] 2106 "TARGET_80387" 2107 " 2108{ 2109 operands[1] = copy_to_mode_reg (DFmode, operands[1]); 2110 operands[2] = gen_reg_rtx (DFmode); 2111 operands[3] = (rtx) assign_386_stack_local (SImode, 0); 2112 operands[4] = (rtx) assign_386_stack_local (SImode, 1); 2113}") 2114 2115(define_expand "fix_truncsfdi2" 2116 [(set (match_dup 2) 2117 (match_operand:SF 1 "register_operand" "")) 2118 (parallel [(set (match_operand:DI 0 "general_operand" "") 2119 (fix:DI (fix:SF (match_dup 2)))) 2120 (clobber (match_dup 2)) 2121 (clobber (match_dup 3)) 2122 (clobber (match_dup 4)) 2123 (clobber (match_scratch:SI 5 ""))])] 2124 "TARGET_80387" 2125 " 2126{ 2127 operands[1] = copy_to_mode_reg (SFmode, operands[1]); 2128 operands[2] = gen_reg_rtx (SFmode); 2129 operands[3] = (rtx) assign_386_stack_local (SImode, 0); 2130 operands[4] = (rtx) assign_386_stack_local (SImode, 1); 2131}") 2132 2133;; These match a signed conversion of either DFmode or SFmode to DImode. 2134 2135(define_insn "" 2136 [(set (match_operand:DI 0 "general_operand" "=rm") 2137 (fix:DI (fix:XF (match_operand:XF 1 "register_operand" "f")))) 2138 (clobber (match_dup 1)) 2139 (clobber (match_operand:SI 2 "memory_operand" "m")) 2140 (clobber (match_operand:SI 3 "memory_operand" "m")) 2141 (clobber (match_scratch:SI 4 "=&q"))] 2142 "TARGET_80387" 2143 "* return output_fix_trunc (insn, operands);") 2144 2145(define_insn "" 2146 [(set (match_operand:DI 0 "general_operand" "=rm") 2147 (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f")))) 2148 (clobber (match_dup 1)) 2149 (clobber (match_operand:SI 2 "memory_operand" "m")) 2150 (clobber (match_operand:SI 3 "memory_operand" "m")) 2151 (clobber (match_scratch:SI 4 "=&q"))] 2152 "TARGET_80387" 2153 "* return output_fix_trunc (insn, operands);") 2154 2155(define_insn "" 2156 [(set (match_operand:DI 0 "general_operand" "=rm") 2157 (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f")))) 2158 (clobber (match_dup 1)) 2159 (clobber (match_operand:SI 2 "memory_operand" "m")) 2160 (clobber (match_operand:SI 3 "memory_operand" "m")) 2161 (clobber (match_scratch:SI 4 "=&q"))] 2162 "TARGET_80387" 2163 "* return output_fix_trunc (insn, operands);") 2164 2165;; Signed MODE_FLOAT conversion to SImode. 2166 2167(define_expand "fix_truncxfsi2" 2168 [(parallel [(set (match_operand:SI 0 "general_operand" "") 2169 (fix:SI 2170 (fix:XF (match_operand:XF 1 "register_operand" "")))) 2171 (clobber (match_dup 2)) 2172 (clobber (match_dup 3)) 2173 (clobber (match_scratch:SI 4 ""))])] 2174 "TARGET_80387" 2175 " 2176{ 2177 operands[2] = (rtx) assign_386_stack_local (SImode, 0); 2178 operands[3] = (rtx) assign_386_stack_local (SImode, 1); 2179}") 2180 2181(define_expand "fix_truncdfsi2" 2182 [(parallel [(set (match_operand:SI 0 "general_operand" "") 2183 (fix:SI 2184 (fix:DF (match_operand:DF 1 "register_operand" "")))) 2185 (clobber (match_dup 2)) 2186 (clobber (match_dup 3)) 2187 (clobber (match_scratch:SI 4 ""))])] 2188 "TARGET_80387" 2189 " 2190{ 2191 operands[2] = (rtx) assign_386_stack_local (SImode, 0); 2192 operands[3] = (rtx) assign_386_stack_local (SImode, 1); 2193}") 2194 2195(define_expand "fix_truncsfsi2" 2196 [(parallel [(set (match_operand:SI 0 "general_operand" "") 2197 (fix:SI 2198 (fix:SF (match_operand:SF 1 "register_operand" "")))) 2199 (clobber (match_dup 2)) 2200 (clobber (match_dup 3)) 2201 (clobber (match_scratch:SI 4 ""))])] 2202 "TARGET_80387" 2203 " 2204{ 2205 operands[2] = (rtx) assign_386_stack_local (SImode, 0); 2206 operands[3] = (rtx) assign_386_stack_local (SImode, 1); 2207}") 2208 2209(define_insn "" 2210 [(set (match_operand:SI 0 "general_operand" "=rm") 2211 (fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f")))) 2212 (clobber (match_operand:SI 2 "memory_operand" "m")) 2213 (clobber (match_operand:SI 3 "memory_operand" "m")) 2214 (clobber (match_scratch:SI 4 "=&q"))] 2215 "TARGET_80387" 2216 "* return output_fix_trunc (insn, operands);") 2217 2218(define_insn "" 2219 [(set (match_operand:SI 0 "general_operand" "=rm") 2220 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f")))) 2221 (clobber (match_operand:SI 2 "memory_operand" "m")) 2222 (clobber (match_operand:SI 3 "memory_operand" "m")) 2223 (clobber (match_scratch:SI 4 "=&q"))] 2224 "TARGET_80387" 2225 "* return output_fix_trunc (insn, operands);") 2226 2227(define_insn "" 2228 [(set (match_operand:SI 0 "general_operand" "=rm") 2229 (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f")))) 2230 (clobber (match_operand:SI 2 "memory_operand" "m")) 2231 (clobber (match_operand:SI 3 "memory_operand" "m")) 2232 (clobber (match_scratch:SI 4 "=&q"))] 2233 "TARGET_80387" 2234 "* return output_fix_trunc (insn, operands);") 2235 2236;; Conversion between fixed point and floating point. 2237;; The actual pattern that matches these is at the end of this file. 2238 2239;; ??? Possibly represent floatunssidf2 here in gcc2. 2240 2241(define_expand "floatsisf2" 2242 [(set (match_operand:SF 0 "register_operand" "") 2243 (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))] 2244 "TARGET_80387" 2245 "") 2246 2247(define_expand "floatdisf2" 2248 [(set (match_operand:SF 0 "register_operand" "") 2249 (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))] 2250 "TARGET_80387" 2251 "") 2252 2253(define_expand "floatsidf2" 2254 [(set (match_operand:DF 0 "register_operand" "") 2255 (float:DF (match_operand:SI 1 "nonimmediate_operand" "")))] 2256 "TARGET_80387" 2257 "") 2258 2259(define_expand "floatdidf2" 2260 [(set (match_operand:DF 0 "register_operand" "") 2261 (float:DF (match_operand:DI 1 "nonimmediate_operand" "")))] 2262 "TARGET_80387" 2263 "") 2264 2265(define_expand "floatsixf2" 2266 [(set (match_operand:XF 0 "register_operand" "") 2267 (float:XF (match_operand:SI 1 "nonimmediate_operand" "")))] 2268 "TARGET_80387" 2269 "") 2270 2271(define_expand "floatdixf2" 2272 [(set (match_operand:XF 0 "register_operand" "") 2273 (float:XF (match_operand:DI 1 "nonimmediate_operand" "")))] 2274 "TARGET_80387" 2275 "") 2276 2277;; This will convert from SImode or DImode to MODE_FLOAT. 2278 2279(define_insn "" 2280 [(set (match_operand:XF 0 "register_operand" "=f") 2281 (float:XF (match_operand:DI 1 "general_operand" "rm")))] 2282 "TARGET_80387" 2283 "* 2284{ 2285 if (NON_STACK_REG_P (operands[1])) 2286 { 2287 output_op_from_reg (operands[1], AS1 (fild%z0,%1)); 2288 RET; 2289 } 2290 else if (GET_CODE (operands[1]) == MEM) 2291 return AS1 (fild%z1,%1); 2292 else 2293 abort (); 2294}") 2295 2296(define_insn "" 2297 [(set (match_operand:DF 0 "register_operand" "=f") 2298 (float:DF (match_operand:DI 1 "nonimmediate_operand" "rm")))] 2299 "TARGET_80387" 2300 "* 2301{ 2302 if (NON_STACK_REG_P (operands[1])) 2303 { 2304 output_op_from_reg (operands[1], AS1 (fild%z0,%1)); 2305 RET; 2306 } 2307 else if (GET_CODE (operands[1]) == MEM) 2308 return AS1 (fild%z1,%1); 2309 else 2310 abort (); 2311}") 2312 2313(define_insn "" 2314 [(set (match_operand:SF 0 "register_operand" "=f") 2315 (float:SF (match_operand:DI 1 "nonimmediate_operand" "rm")))] 2316 "TARGET_80387" 2317 "* 2318{ 2319 if (NON_STACK_REG_P (operands[1])) 2320 { 2321 output_op_from_reg (operands[1], AS1 (fild%z0,%1)); 2322 RET; 2323 } 2324 else if (GET_CODE (operands[1]) == MEM) 2325 return AS1 (fild%z1,%1); 2326 else 2327 abort (); 2328}") 2329 2330(define_insn "" 2331 [(set (match_operand:DF 0 "register_operand" "=f") 2332 (float:DF (match_operand:SI 1 "nonimmediate_operand" "rm")))] 2333 "TARGET_80387" 2334 "* 2335{ 2336 if (NON_STACK_REG_P (operands[1])) 2337 { 2338 output_op_from_reg (operands[1], AS1 (fild%z0,%1)); 2339 RET; 2340 } 2341 else if (GET_CODE (operands[1]) == MEM) 2342 return AS1 (fild%z1,%1); 2343 else 2344 abort (); 2345}") 2346 2347(define_insn "" 2348 [(set (match_operand:XF 0 "register_operand" "=f,f") 2349 (float:XF (match_operand:SI 1 "general_operand" "m,!*r")))] 2350 "TARGET_80387" 2351 "* 2352{ 2353 if (NON_STACK_REG_P (operands[1])) 2354 { 2355 output_op_from_reg (operands[1], AS1 (fild%z0,%1)); 2356 RET; 2357 } 2358 else if (GET_CODE (operands[1]) == MEM) 2359 return AS1 (fild%z1,%1); 2360 else 2361 abort (); 2362}") 2363 2364(define_insn "" 2365 [(set (match_operand:SF 0 "register_operand" "=f") 2366 (float:SF (match_operand:SI 1 "nonimmediate_operand" "rm")))] 2367 "TARGET_80387" 2368 "* 2369{ 2370 if (NON_STACK_REG_P (operands[1])) 2371 { 2372 output_op_from_reg (operands[1], AS1 (fild%z0,%1)); 2373 RET; 2374 } 2375 else if (GET_CODE (operands[1]) == MEM) 2376 return AS1 (fild%z1,%1); 2377 else 2378 abort (); 2379}") 2380 2381;;- add instructions 2382 2383(define_insn "adddi3" 2384 [(set (match_operand:DI 0 "general_operand" "=&r,ro,o,&r,ro,o,&r,o,o,o") 2385 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,o,riF,o,or,riF,riF,o") 2386 (match_operand:DI 2 "general_operand" "o,riF,o,0,0,0,oriF,riF,o,o"))) 2387 (clobber (match_scratch:SI 3 "=X,X,&r,X,&r,&r,X,&r,&r,&r"))] 2388 "" 2389 "* 2390{ 2391 rtx low[3], high[3], xops[7], temp; 2392 2393 CC_STATUS_INIT; 2394 2395 if (rtx_equal_p (operands[0], operands[2])) 2396 { 2397 temp = operands[1]; 2398 operands[1] = operands[2]; 2399 operands[2] = temp; 2400 } 2401 2402 split_di (operands, 3, low, high); 2403 if (!rtx_equal_p (operands[0], operands[1])) 2404 { 2405 xops[0] = high[0]; 2406 xops[1] = low[0]; 2407 xops[2] = high[1]; 2408 xops[3] = low[1]; 2409 2410 if (GET_CODE (operands[0]) != MEM) 2411 { 2412 output_asm_insn (AS2 (mov%L1,%3,%1), xops); 2413 output_asm_insn (AS2 (mov%L0,%2,%0), xops); 2414 } 2415 else 2416 { 2417 xops[4] = high[2]; 2418 xops[5] = low[2]; 2419 xops[6] = operands[3]; 2420 output_asm_insn (AS2 (mov%L6,%3,%6), xops); 2421 output_asm_insn (AS2 (add%L6,%5,%6), xops); 2422 output_asm_insn (AS2 (mov%L1,%6,%1), xops); 2423 output_asm_insn (AS2 (mov%L6,%2,%6), xops); 2424 output_asm_insn (AS2 (adc%L6,%4,%6), xops); 2425 output_asm_insn (AS2 (mov%L0,%6,%0), xops); 2426 RET; 2427 } 2428 } 2429 2430 if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG) 2431 { 2432 xops[0] = high[0]; 2433 xops[1] = low[0]; 2434 xops[2] = high[2]; 2435 xops[3] = low[2]; 2436 xops[4] = operands[3]; 2437 2438 output_asm_insn (AS2 (mov%L4,%3,%4), xops); 2439 output_asm_insn (AS2 (add%L1,%4,%1), xops); 2440 output_asm_insn (AS2 (mov%L4,%2,%4), xops); 2441 output_asm_insn (AS2 (adc%L0,%4,%0), xops); 2442 } 2443 2444 else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0) 2445 { 2446 output_asm_insn (AS2 (add%L0,%2,%0), low); 2447 output_asm_insn (AS2 (adc%L0,%2,%0), high); 2448 } 2449 2450 else 2451 output_asm_insn (AS2 (add%L0,%2,%0), high); 2452 2453 RET; 2454}") 2455 2456;; On a 486, it is faster to do movl/addl than to do a single leal if 2457;; operands[1] and operands[2] are both registers. 2458 2459(define_insn "addsi3" 2460 [(set (match_operand:SI 0 "general_operand" "=?r,rm,r") 2461 (plus:SI (match_operand:SI 1 "general_operand" "%r,0,0") 2462 (match_operand:SI 2 "general_operand" "ri,ri,rm")))] 2463 "" 2464 "* 2465{ 2466 if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1])) 2467 { 2468 if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2])) 2469 return AS2 (add%L0,%1,%0); 2470 2471 if (operands[2] == stack_pointer_rtx) 2472 { 2473 rtx temp; 2474 2475 temp = operands[1]; 2476 operands[1] = operands[2]; 2477 operands[2] = temp; 2478 } 2479 2480 if (operands[2] != stack_pointer_rtx) 2481 { 2482 CC_STATUS_INIT; 2483 operands[1] = SET_SRC (PATTERN (insn)); 2484 return AS2 (lea%L0,%a1,%0); 2485 } 2486 2487 output_asm_insn (AS2 (mov%L0,%1,%0), operands); 2488 } 2489 2490 if (operands[2] == const1_rtx) 2491 return AS1 (inc%L0,%0); 2492 2493 if (operands[2] == constm1_rtx) 2494 return AS1 (dec%L0,%0); 2495 2496 return AS2 (add%L0,%2,%0); 2497}") 2498 2499;; ??? `lea' here, for three operand add? If leaw is used, only %bx, 2500;; %si and %di can appear in SET_SRC, and output_asm_insn might not be 2501;; able to handle the operand. But leal always works? 2502 2503(define_insn "addhi3" 2504 [(set (match_operand:HI 0 "general_operand" "=rm,r") 2505 (plus:HI (match_operand:HI 1 "general_operand" "%0,0") 2506 (match_operand:HI 2 "general_operand" "ri,rm")))] 2507 "" 2508 "* 2509{ 2510 /* ??? what about offsettable memory references? */ 2511 if (QI_REG_P (operands[0]) 2512 && GET_CODE (operands[2]) == CONST_INT 2513 && (INTVAL (operands[2]) & 0xff) == 0) 2514 { 2515 int byteval = (INTVAL (operands[2]) >> 8) & 0xff; 2516 CC_STATUS_INIT; 2517 2518 if (byteval == 1) 2519 return AS1 (inc%B0,%h0); 2520 else if (byteval == 255) 2521 return AS1 (dec%B0,%h0); 2522 2523 operands[2] = GEN_INT (byteval); 2524 return AS2 (add%B0,%2,%h0); 2525 } 2526 2527 if (operands[2] == const1_rtx) 2528 return AS1 (inc%W0,%0); 2529 2530 if (operands[2] == constm1_rtx 2531 || (GET_CODE (operands[2]) == CONST_INT 2532 && INTVAL (operands[2]) == 65535)) 2533 return AS1 (dec%W0,%0); 2534 2535 return AS2 (add%W0,%2,%0); 2536}") 2537 2538(define_insn "addqi3" 2539 [(set (match_operand:QI 0 "general_operand" "=qm,q") 2540 (plus:QI (match_operand:QI 1 "general_operand" "%0,0") 2541 (match_operand:QI 2 "general_operand" "qn,qmn")))] 2542 "" 2543 "* 2544{ 2545 if (operands[2] == const1_rtx) 2546 return AS1 (inc%B0,%0); 2547 2548 if (operands[2] == constm1_rtx 2549 || (GET_CODE (operands[2]) == CONST_INT 2550 && INTVAL (operands[2]) == 255)) 2551 return AS1 (dec%B0,%0); 2552 2553 return AS2 (add%B0,%2,%0); 2554}") 2555 2556;Lennart Augustsson <augustss@cs.chalmers.se> 2557;says this pattern just makes slower code: 2558; pushl %ebp 2559; addl $-80,(%esp) 2560;instead of 2561; leal -80(%ebp),%eax 2562; pushl %eax 2563; 2564;(define_insn "" 2565; [(set (match_operand:SI 0 "push_operand" "=<") 2566; (plus:SI (match_operand:SI 1 "general_operand" "%r") 2567; (match_operand:SI 2 "general_operand" "ri")))] 2568; "" 2569; "* 2570;{ 2571; rtx xops[4]; 2572; xops[0] = operands[0]; 2573; xops[1] = operands[1]; 2574; xops[2] = operands[2]; 2575; xops[3] = gen_rtx (MEM, SImode, stack_pointer_rtx); 2576; output_asm_insn (\"push%z1 %1\", xops); 2577; output_asm_insn (AS2 (add%z3,%2,%3), xops); 2578; RET; 2579;}") 2580 2581;; addsi3 is faster, so put this after. 2582 2583(define_insn "movsi_lea" 2584 [(set (match_operand:SI 0 "register_operand" "=r") 2585 (match_operand:QI 1 "address_operand" "p"))] 2586 "" 2587 "* 2588{ 2589 CC_STATUS_INIT; 2590 /* Adding a constant to a register is faster with an add. */ 2591 /* ??? can this ever happen? */ 2592 if (GET_CODE (operands[1]) == PLUS 2593 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT 2594 && rtx_equal_p (operands[0], XEXP (operands[1], 0))) 2595 { 2596 operands[1] = XEXP (operands[1], 1); 2597 2598 if (operands[1] == const1_rtx) 2599 return AS1 (inc%L0,%0); 2600 2601 if (operands[1] == constm1_rtx) 2602 return AS1 (dec%L0,%0); 2603 2604 return AS2 (add%L0,%1,%0); 2605 } 2606 return AS2 (lea%L0,%a1,%0); 2607}") 2608 2609;; The patterns that match these are at the end of this file. 2610 2611(define_expand "addxf3" 2612 [(set (match_operand:XF 0 "register_operand" "") 2613 (plus:XF (match_operand:XF 1 "nonimmediate_operand" "") 2614 (match_operand:XF 2 "nonimmediate_operand" "")))] 2615 "TARGET_80387" 2616 "") 2617 2618(define_expand "adddf3" 2619 [(set (match_operand:DF 0 "register_operand" "") 2620 (plus:DF (match_operand:DF 1 "nonimmediate_operand" "") 2621 (match_operand:DF 2 "nonimmediate_operand" "")))] 2622 "TARGET_80387" 2623 "") 2624 2625(define_expand "addsf3" 2626 [(set (match_operand:SF 0 "register_operand" "") 2627 (plus:SF (match_operand:SF 1 "nonimmediate_operand" "") 2628 (match_operand:SF 2 "nonimmediate_operand" "")))] 2629 "TARGET_80387" 2630 "") 2631 2632;;- subtract instructions 2633 2634(define_insn "subdi3" 2635 [(set (match_operand:DI 0 "general_operand" "=&r,ro,&r,o,o") 2636 (minus:DI (match_operand:DI 1 "general_operand" "0,0,roiF,riF,o") 2637 (match_operand:DI 2 "general_operand" "o,riF,roiF,riF,o"))) 2638 (clobber (match_scratch:SI 3 "=X,X,X,&r,&r"))] 2639 "" 2640 "* 2641{ 2642 rtx low[3], high[3], xops[7]; 2643 2644 CC_STATUS_INIT; 2645 2646 split_di (operands, 3, low, high); 2647 2648 if (!rtx_equal_p (operands[0], operands[1])) 2649 { 2650 xops[0] = high[0]; 2651 xops[1] = low[0]; 2652 xops[2] = high[1]; 2653 xops[3] = low[1]; 2654 2655 if (GET_CODE (operands[0]) != MEM) 2656 { 2657 output_asm_insn (AS2 (mov%L1,%3,%1), xops); 2658 output_asm_insn (AS2 (mov%L0,%2,%0), xops); 2659 } 2660 else 2661 { 2662 xops[4] = high[2]; 2663 xops[5] = low[2]; 2664 xops[6] = operands[3]; 2665 output_asm_insn (AS2 (mov%L6,%3,%6), xops); 2666 output_asm_insn (AS2 (sub%L6,%5,%6), xops); 2667 output_asm_insn (AS2 (mov%L1,%6,%1), xops); 2668 output_asm_insn (AS2 (mov%L6,%2,%6), xops); 2669 output_asm_insn (AS2 (sbb%L6,%4,%6), xops); 2670 output_asm_insn (AS2 (mov%L0,%6,%0), xops); 2671 RET; 2672 } 2673 } 2674 2675 if (GET_CODE (operands[3]) == REG) 2676 { 2677 xops[0] = high[0]; 2678 xops[1] = low[0]; 2679 xops[2] = high[2]; 2680 xops[3] = low[2]; 2681 xops[4] = operands[3]; 2682 2683 output_asm_insn (AS2 (mov%L4,%3,%4), xops); 2684 output_asm_insn (AS2 (sub%L1,%4,%1), xops); 2685 output_asm_insn (AS2 (mov%L4,%2,%4), xops); 2686 output_asm_insn (AS2 (sbb%L0,%4,%0), xops); 2687 } 2688 2689 else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0) 2690 { 2691 output_asm_insn (AS2 (sub%L0,%2,%0), low); 2692 output_asm_insn (AS2 (sbb%L0,%2,%0), high); 2693 } 2694 2695 else 2696 output_asm_insn (AS2 (sub%L0,%2,%0), high); 2697 2698 RET; 2699}") 2700 2701(define_insn "subsi3" 2702 [(set (match_operand:SI 0 "general_operand" "=rm,r") 2703 (minus:SI (match_operand:SI 1 "general_operand" "0,0") 2704 (match_operand:SI 2 "general_operand" "ri,rm")))] 2705 "" 2706 "* return AS2 (sub%L0,%2,%0);") 2707 2708(define_insn "subhi3" 2709 [(set (match_operand:HI 0 "general_operand" "=rm,r") 2710 (minus:HI (match_operand:HI 1 "general_operand" "0,0") 2711 (match_operand:HI 2 "general_operand" "ri,rm")))] 2712 "" 2713 "* return AS2 (sub%W0,%2,%0);") 2714 2715(define_insn "subqi3" 2716 [(set (match_operand:QI 0 "general_operand" "=qm,q") 2717 (minus:QI (match_operand:QI 1 "general_operand" "0,0") 2718 (match_operand:QI 2 "general_operand" "qn,qmn")))] 2719 "" 2720 "* return AS2 (sub%B0,%2,%0);") 2721 2722;; The patterns that match these are at the end of this file. 2723 2724(define_expand "subxf3" 2725 [(set (match_operand:XF 0 "register_operand" "") 2726 (minus:XF (match_operand:XF 1 "nonimmediate_operand" "") 2727 (match_operand:XF 2 "nonimmediate_operand" "")))] 2728 "TARGET_80387" 2729 "") 2730 2731(define_expand "subdf3" 2732 [(set (match_operand:DF 0 "register_operand" "") 2733 (minus:DF (match_operand:DF 1 "nonimmediate_operand" "") 2734 (match_operand:DF 2 "nonimmediate_operand" "")))] 2735 "TARGET_80387" 2736 "") 2737 2738(define_expand "subsf3" 2739 [(set (match_operand:SF 0 "register_operand" "") 2740 (minus:SF (match_operand:SF 1 "nonimmediate_operand" "") 2741 (match_operand:SF 2 "nonimmediate_operand" "")))] 2742 "TARGET_80387" 2743 "") 2744 2745;;- multiply instructions 2746 2747;(define_insn "mulqi3" 2748; [(set (match_operand:QI 0 "general_operand" "=a") 2749; (mult:QI (match_operand:QI 1 "general_operand" "%0") 2750; (match_operand:QI 2 "general_operand" "qm")))] 2751; "" 2752; "imul%B0 %2,%0") 2753 2754(define_insn "" 2755 [(set (match_operand:HI 0 "general_operand" "=r") 2756 (mult:HI (match_operand:HI 1 "general_operand" "%0") 2757 (match_operand:HI 2 "general_operand" "r")))] 2758 "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80" 2759 "* return AS2 (imul%W0,%2,%0);") 2760 2761(define_insn "mulhi3" 2762 [(set (match_operand:HI 0 "general_operand" "=r,r") 2763 (mult:HI (match_operand:HI 1 "general_operand" "%0,rm") 2764 (match_operand:HI 2 "general_operand" "g,i")))] 2765 "" 2766 "* 2767{ 2768 if (GET_CODE (operands[1]) == REG 2769 && REGNO (operands[1]) == REGNO (operands[0]) 2770 && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG)) 2771 /* Assembler has weird restrictions. */ 2772 return AS2 (imul%W0,%2,%0); 2773 return AS3 (imul%W0,%2,%1,%0); 2774}") 2775 2776(define_insn "" 2777 [(set (match_operand:SI 0 "general_operand" "=r") 2778 (mult:SI (match_operand:SI 1 "general_operand" "%0") 2779 (match_operand:SI 2 "general_operand" "r")))] 2780 "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80" 2781 "* return AS2 (imul%L0,%2,%0);") 2782 2783(define_insn "mulsi3" 2784 [(set (match_operand:SI 0 "general_operand" "=r,r") 2785 (mult:SI (match_operand:SI 1 "general_operand" "%0,rm") 2786 (match_operand:SI 2 "general_operand" "g,i")))] 2787 "" 2788 "* 2789{ 2790 if (GET_CODE (operands[1]) == REG 2791 && REGNO (operands[1]) == REGNO (operands[0]) 2792 && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG)) 2793 /* Assembler has weird restrictions. */ 2794 return AS2 (imul%L0,%2,%0); 2795 return AS3 (imul%L0,%2,%1,%0); 2796}") 2797 2798(define_insn "umulqihi3" 2799 [(set (match_operand:HI 0 "general_operand" "=a") 2800 (mult:HI (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0")) 2801 (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))] 2802 "" 2803 "mul%B0 %2") 2804 2805(define_insn "mulqihi3" 2806 [(set (match_operand:HI 0 "general_operand" "=a") 2807 (mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0")) 2808 (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))] 2809 "" 2810 "imul%B0 %2") 2811 2812(define_insn "umulsidi3" 2813 [(set (match_operand:DI 0 "register_operand" "=A") 2814 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) 2815 (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))] 2816 "TARGET_WIDE_MULTIPLY" 2817 "mul%L0 %2") 2818 2819(define_insn "mulsidi3" 2820 [(set (match_operand:DI 0 "register_operand" "=A") 2821 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0")) 2822 (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))] 2823 "TARGET_WIDE_MULTIPLY" 2824 "imul%L0 %2") 2825 2826(define_insn "umulsi3_highpart" 2827 [(set (match_operand:SI 0 "register_operand" "=d") 2828 (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%a")) 2829 (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))) 2830 (const_int 32)))) 2831 (clobber (match_scratch:SI 3 "=a"))] 2832 "TARGET_WIDE_MULTIPLY" 2833 "mul%L0 %2") 2834 2835(define_insn "smulsi3_highpart" 2836 [(set (match_operand:SI 0 "register_operand" "=d") 2837 (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%a")) 2838 (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))) 2839 (const_int 32)))) 2840 (clobber (match_scratch:SI 3 "=a"))] 2841 "TARGET_WIDE_MULTIPLY" 2842 "imul%L0 %2") 2843 2844;; The patterns that match these are at the end of this file. 2845 2846(define_expand "mulxf3" 2847 [(set (match_operand:XF 0 "register_operand" "") 2848 (mult:XF (match_operand:XF 1 "nonimmediate_operand" "") 2849 (match_operand:XF 2 "nonimmediate_operand" "")))] 2850 "TARGET_80387" 2851 "") 2852 2853(define_expand "muldf3" 2854 [(set (match_operand:DF 0 "register_operand" "") 2855 (mult:DF (match_operand:DF 1 "nonimmediate_operand" "") 2856 (match_operand:DF 2 "nonimmediate_operand" "")))] 2857 "TARGET_80387" 2858 "") 2859 2860(define_expand "mulsf3" 2861 [(set (match_operand:SF 0 "register_operand" "") 2862 (mult:SF (match_operand:SF 1 "nonimmediate_operand" "") 2863 (match_operand:SF 2 "nonimmediate_operand" "")))] 2864 "TARGET_80387" 2865 "") 2866 2867;;- divide instructions 2868 2869(define_insn "divqi3" 2870 [(set (match_operand:QI 0 "general_operand" "=a") 2871 (div:QI (match_operand:HI 1 "general_operand" "0") 2872 (match_operand:QI 2 "general_operand" "qm")))] 2873 "" 2874 "idiv%B0 %2") 2875 2876(define_insn "udivqi3" 2877 [(set (match_operand:QI 0 "general_operand" "=a") 2878 (udiv:QI (match_operand:HI 1 "general_operand" "0") 2879 (match_operand:QI 2 "general_operand" "qm")))] 2880 "" 2881 "div%B0 %2") 2882 2883;; The patterns that match these are at the end of this file. 2884 2885(define_expand "divxf3" 2886 [(set (match_operand:XF 0 "register_operand" "") 2887 (div:XF (match_operand:XF 1 "nonimmediate_operand" "") 2888 (match_operand:XF 2 "nonimmediate_operand" "")))] 2889 "TARGET_80387" 2890 "") 2891 2892(define_expand "divdf3" 2893 [(set (match_operand:DF 0 "register_operand" "") 2894 (div:DF (match_operand:DF 1 "nonimmediate_operand" "") 2895 (match_operand:DF 2 "nonimmediate_operand" "")))] 2896 "TARGET_80387" 2897 "") 2898 2899(define_expand "divsf3" 2900 [(set (match_operand:SF 0 "register_operand" "") 2901 (div:SF (match_operand:SF 1 "nonimmediate_operand" "") 2902 (match_operand:SF 2 "nonimmediate_operand" "")))] 2903 "TARGET_80387" 2904 "") 2905 2906;; Remainder instructions. 2907 2908(define_insn "divmodsi4" 2909 [(set (match_operand:SI 0 "register_operand" "=a") 2910 (div:SI (match_operand:SI 1 "register_operand" "0") 2911 (match_operand:SI 2 "general_operand" "rm"))) 2912 (set (match_operand:SI 3 "register_operand" "=&d") 2913 (mod:SI (match_dup 1) (match_dup 2)))] 2914 "" 2915 "* 2916{ 2917#ifdef INTEL_SYNTAX 2918 output_asm_insn (\"cdq\", operands); 2919#else 2920 output_asm_insn (\"cltd\", operands); 2921#endif 2922 return AS1 (idiv%L0,%2); 2923}") 2924 2925(define_insn "divmodhi4" 2926 [(set (match_operand:HI 0 "register_operand" "=a") 2927 (div:HI (match_operand:HI 1 "register_operand" "0") 2928 (match_operand:HI 2 "general_operand" "rm"))) 2929 (set (match_operand:HI 3 "register_operand" "=&d") 2930 (mod:HI (match_dup 1) (match_dup 2)))] 2931 "" 2932 "cwtd\;idiv%W0 %2") 2933 2934;; ??? Can we make gcc zero extend operand[0]? 2935(define_insn "udivmodsi4" 2936 [(set (match_operand:SI 0 "register_operand" "=a") 2937 (udiv:SI (match_operand:SI 1 "register_operand" "0") 2938 (match_operand:SI 2 "general_operand" "rm"))) 2939 (set (match_operand:SI 3 "register_operand" "=&d") 2940 (umod:SI (match_dup 1) (match_dup 2)))] 2941 "" 2942 "* 2943{ 2944 output_asm_insn (AS2 (xor%L3,%3,%3), operands); 2945 return AS1 (div%L0,%2); 2946}") 2947 2948;; ??? Can we make gcc zero extend operand[0]? 2949(define_insn "udivmodhi4" 2950 [(set (match_operand:HI 0 "register_operand" "=a") 2951 (udiv:HI (match_operand:HI 1 "register_operand" "0") 2952 (match_operand:HI 2 "general_operand" "rm"))) 2953 (set (match_operand:HI 3 "register_operand" "=&d") 2954 (umod:HI (match_dup 1) (match_dup 2)))] 2955 "" 2956 "* 2957{ 2958 output_asm_insn (AS2 (xor%W0,%3,%3), operands); 2959 return AS1 (div%W0,%2); 2960}") 2961 2962/* 2963;;this should be a valid double division which we may want to add 2964 2965(define_insn "" 2966 [(set (match_operand:SI 0 "register_operand" "=a") 2967 (udiv:DI (match_operand:DI 1 "register_operand" "a") 2968 (match_operand:SI 2 "general_operand" "rm"))) 2969 (set (match_operand:SI 3 "register_operand" "=d") 2970 (umod:SI (match_dup 1) (match_dup 2)))] 2971 "" 2972 "div%L0 %2,%0") 2973*/ 2974 2975;;- and instructions 2976 2977;; On i386, 2978;; movzbl %bl,%ebx 2979;; is faster than 2980;; andl $255,%ebx 2981;; 2982;; but if the reg is %eax, then the "andl" is faster. 2983;; 2984;; On i486, the "andl" is always faster than the "movzbl". 2985;; 2986;; On both i386 and i486, a three operand AND is as fast with movzbl or 2987;; movzwl as with andl, if operands[0] != operands[1]. 2988 2989;; The `r' in `rm' for operand 3 looks redundant, but it causes 2990;; optional reloads to be generated if op 3 is a pseudo in a stack slot. 2991 2992;; ??? What if we only change one byte of an offsettable memory reference? 2993(define_insn "andsi3" 2994 [(set (match_operand:SI 0 "general_operand" "=r,r,rm,r") 2995 (and:SI (match_operand:SI 1 "general_operand" "%rm,qm,0,0") 2996 (match_operand:SI 2 "general_operand" "L,K,ri,rm")))] 2997 "" 2998 "* 2999{ 3000 if (GET_CODE (operands[2]) == CONST_INT 3001 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) 3002 { 3003 if (INTVAL (operands[2]) == 0xffff && REG_P (operands[0]) 3004 && (! REG_P (operands[1]) 3005 || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0) 3006 && (TARGET_386 || ! rtx_equal_p (operands[0], operands[1]))) 3007 { 3008 /* ??? tege: Should forget CC_STATUS only if we clobber a 3009 remembered operand. Fix that later. */ 3010 CC_STATUS_INIT; 3011#ifdef INTEL_SYNTAX 3012 return AS2 (movzx,%w1,%0); 3013#else 3014 return AS2 (movz%W0%L0,%w1,%0); 3015#endif 3016 } 3017 3018 if (INTVAL (operands[2]) == 0xff && REG_P (operands[0]) 3019 && !(REG_P (operands[1]) && NON_QI_REG_P (operands[1])) 3020 && (! REG_P (operands[1]) 3021 || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0) 3022 && (TARGET_386 || ! rtx_equal_p (operands[0], operands[1]))) 3023 { 3024 /* ??? tege: Should forget CC_STATUS only if we clobber a 3025 remembered operand. Fix that later. */ 3026 CC_STATUS_INIT; 3027#ifdef INTEL_SYNTAX 3028 return AS2 (movzx,%b1,%0); 3029#else 3030 return AS2 (movz%B0%L0,%b1,%0); 3031#endif 3032 } 3033 3034 if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff) == 0) 3035 { 3036 CC_STATUS_INIT; 3037 3038 if (INTVAL (operands[2]) == 0xffffff00) 3039 { 3040 operands[2] = const0_rtx; 3041 return AS2 (mov%B0,%2,%b0); 3042 } 3043 3044 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff); 3045 return AS2 (and%B0,%2,%b0); 3046 } 3047 3048 if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff00) == 0) 3049 { 3050 CC_STATUS_INIT; 3051 3052 if (INTVAL (operands[2]) == 0xffff00ff) 3053 { 3054 operands[2] = const0_rtx; 3055 return AS2 (mov%B0,%2,%h0); 3056 } 3057 3058 operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); 3059 return AS2 (and%B0,%2,%h0); 3060 } 3061 3062 if (GET_CODE (operands[0]) == MEM && INTVAL (operands[2]) == 0xffff0000) 3063 { 3064 operands[2] = const0_rtx; 3065 return AS2 (mov%W0,%2,%w0); 3066 } 3067 } 3068 3069 return AS2 (and%L0,%2,%0); 3070}") 3071 3072(define_insn "andhi3" 3073 [(set (match_operand:HI 0 "general_operand" "=rm,r") 3074 (and:HI (match_operand:HI 1 "general_operand" "%0,0") 3075 (match_operand:HI 2 "general_operand" "ri,rm")))] 3076 "" 3077 "* 3078{ 3079 if (GET_CODE (operands[2]) == CONST_INT 3080 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) 3081 { 3082 /* Can we ignore the upper byte? */ 3083 if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) 3084 && (INTVAL (operands[2]) & 0xff00) == 0xff00) 3085 { 3086 CC_STATUS_INIT; 3087 3088 if ((INTVAL (operands[2]) & 0xff) == 0) 3089 { 3090 operands[2] = const0_rtx; 3091 return AS2 (mov%B0,%2,%b0); 3092 } 3093 3094 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff); 3095 return AS2 (and%B0,%2,%b0); 3096 } 3097 3098 /* Can we ignore the lower byte? */ 3099 /* ??? what about offsettable memory references? */ 3100 if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & 0xff) == 0xff) 3101 { 3102 CC_STATUS_INIT; 3103 3104 if ((INTVAL (operands[2]) & 0xff00) == 0) 3105 { 3106 operands[2] = const0_rtx; 3107 return AS2 (mov%B0,%2,%h0); 3108 } 3109 3110 operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); 3111 return AS2 (and%B0,%2,%h0); 3112 } 3113 } 3114 3115 return AS2 (and%W0,%2,%0); 3116}") 3117 3118(define_insn "andqi3" 3119 [(set (match_operand:QI 0 "general_operand" "=qm,q") 3120 (and:QI (match_operand:QI 1 "general_operand" "%0,0") 3121 (match_operand:QI 2 "general_operand" "qn,qmn")))] 3122 "" 3123 "* return AS2 (and%B0,%2,%0);") 3124 3125/* I am nervous about these two.. add them later.. 3126;I presume this means that we have something in say op0= eax which is small 3127;and we want to and it with memory so we can do this by just an 3128;andb m,%al and have success. 3129(define_insn "" 3130 [(set (match_operand:SI 0 "general_operand" "=r") 3131 (and:SI (zero_extend:SI 3132 (match_operand:HI 1 "nonimmediate_operand" "rm")) 3133 (match_operand:SI 2 "general_operand" "0")))] 3134 "GET_CODE (operands[2]) == CONST_INT 3135 && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (HImode))" 3136 "and%W0 %1,%0") 3137 3138(define_insn "" 3139 [(set (match_operand:SI 0 "general_operand" "=q") 3140 (and:SI 3141 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")) 3142 (match_operand:SI 2 "general_operand" "0")))] 3143 "GET_CODE (operands[2]) == CONST_INT 3144 && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))" 3145 "and%L0 %1,%0") 3146 3147*/ 3148 3149;;- Bit set (inclusive or) instructions 3150 3151;; ??? What if we only change one byte of an offsettable memory reference? 3152(define_insn "iorsi3" 3153 [(set (match_operand:SI 0 "general_operand" "=rm,r") 3154 (ior:SI (match_operand:SI 1 "general_operand" "%0,0") 3155 (match_operand:SI 2 "general_operand" "ri,rm")))] 3156 "" 3157 "* 3158{ 3159 if (GET_CODE (operands[2]) == CONST_INT 3160 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) 3161 { 3162 if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) 3163 && (INTVAL (operands[2]) & ~0xff) == 0) 3164 { 3165 CC_STATUS_INIT; 3166 3167 if (INTVAL (operands[2]) == 0xff) 3168 return AS2 (mov%B0,%2,%b0); 3169 3170 return AS2 (or%B0,%2,%b0); 3171 } 3172 3173 if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0) 3174 { 3175 CC_STATUS_INIT; 3176 operands[2] = GEN_INT (INTVAL (operands[2]) >> 8); 3177 3178 if (INTVAL (operands[2]) == 0xff) 3179 return AS2 (mov%B0,%2,%h0); 3180 3181 return AS2 (or%B0,%2,%h0); 3182 } 3183 } 3184 3185 return AS2 (or%L0,%2,%0); 3186}") 3187 3188(define_insn "iorhi3" 3189 [(set (match_operand:HI 0 "general_operand" "=rm,r") 3190 (ior:HI (match_operand:HI 1 "general_operand" "%0,0") 3191 (match_operand:HI 2 "general_operand" "ri,rm")))] 3192 "" 3193 "* 3194{ 3195 if (GET_CODE (operands[2]) == CONST_INT 3196 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) 3197 { 3198 /* Can we ignore the upper byte? */ 3199 if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) 3200 && (INTVAL (operands[2]) & 0xff00) == 0) 3201 { 3202 CC_STATUS_INIT; 3203 if (INTVAL (operands[2]) & 0xffff0000) 3204 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff); 3205 3206 if (INTVAL (operands[2]) == 0xff) 3207 return AS2 (mov%B0,%2,%b0); 3208 3209 return AS2 (or%B0,%2,%b0); 3210 } 3211 3212 /* Can we ignore the lower byte? */ 3213 /* ??? what about offsettable memory references? */ 3214 if (QI_REG_P (operands[0]) 3215 && (INTVAL (operands[2]) & 0xff) == 0) 3216 { 3217 CC_STATUS_INIT; 3218 operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); 3219 3220 if (INTVAL (operands[2]) == 0xff) 3221 return AS2 (mov%B0,%2,%h0); 3222 3223 return AS2 (or%B0,%2,%h0); 3224 } 3225 } 3226 3227 return AS2 (or%W0,%2,%0); 3228}") 3229 3230(define_insn "iorqi3" 3231 [(set (match_operand:QI 0 "general_operand" "=qm,q") 3232 (ior:QI (match_operand:QI 1 "general_operand" "%0,0") 3233 (match_operand:QI 2 "general_operand" "qn,qmn")))] 3234 "" 3235 "* return AS2 (or%B0,%2,%0);") 3236 3237;;- xor instructions 3238 3239;; ??? What if we only change one byte of an offsettable memory reference? 3240(define_insn "xorsi3" 3241 [(set (match_operand:SI 0 "general_operand" "=rm,r") 3242 (xor:SI (match_operand:SI 1 "general_operand" "%0,0") 3243 (match_operand:SI 2 "general_operand" "ri,rm")))] 3244 "" 3245 "* 3246{ 3247 if (GET_CODE (operands[2]) == CONST_INT 3248 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) 3249 { 3250 if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) 3251 && (INTVAL (operands[2]) & ~0xff) == 0) 3252 { 3253 CC_STATUS_INIT; 3254 3255 if (INTVAL (operands[2]) == 0xff) 3256 return AS1 (not%B0,%b0); 3257 3258 return AS2 (xor%B0,%2,%b0); 3259 } 3260 3261 if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0) 3262 { 3263 CC_STATUS_INIT; 3264 operands[2] = GEN_INT (INTVAL (operands[2]) >> 8); 3265 3266 if (INTVAL (operands[2]) == 0xff) 3267 return AS1 (not%B0,%h0); 3268 3269 return AS2 (xor%B0,%2,%h0); 3270 } 3271 } 3272 3273 return AS2 (xor%L0,%2,%0); 3274}") 3275 3276(define_insn "xorhi3" 3277 [(set (match_operand:HI 0 "general_operand" "=rm,r") 3278 (xor:HI (match_operand:HI 1 "general_operand" "%0,0") 3279 (match_operand:HI 2 "general_operand" "ri,rm")))] 3280 "" 3281 "* 3282{ 3283 if (GET_CODE (operands[2]) == CONST_INT 3284 && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) 3285 { 3286 /* Can we ignore the upper byte? */ 3287 if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) 3288 && (INTVAL (operands[2]) & 0xff00) == 0) 3289 { 3290 CC_STATUS_INIT; 3291 if (INTVAL (operands[2]) & 0xffff0000) 3292 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff); 3293 3294 if (INTVAL (operands[2]) == 0xff) 3295 return AS1 (not%B0,%b0); 3296 3297 return AS2 (xor%B0,%2,%b0); 3298 } 3299 3300 /* Can we ignore the lower byte? */ 3301 /* ??? what about offsettable memory references? */ 3302 if (QI_REG_P (operands[0]) 3303 && (INTVAL (operands[2]) & 0xff) == 0) 3304 { 3305 CC_STATUS_INIT; 3306 operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); 3307 3308 if (INTVAL (operands[2]) == 0xff) 3309 return AS1 (not%B0,%h0); 3310 3311 return AS2 (xor%B0,%2,%h0); 3312 } 3313 } 3314 3315 return AS2 (xor%W0,%2,%0); 3316}") 3317 3318(define_insn "xorqi3" 3319 [(set (match_operand:QI 0 "general_operand" "=qm,q") 3320 (xor:QI (match_operand:QI 1 "general_operand" "%0,0") 3321 (match_operand:QI 2 "general_operand" "qn,qm")))] 3322 "" 3323 "* return AS2 (xor%B0,%2,%0);") 3324 3325;;- negation instructions 3326 3327(define_insn "negdi2" 3328 [(set (match_operand:DI 0 "general_operand" "=&ro") 3329 (neg:DI (match_operand:DI 1 "general_operand" "0")))] 3330 "" 3331 "* 3332{ 3333 rtx xops[2], low[1], high[1]; 3334 3335 CC_STATUS_INIT; 3336 3337 split_di (operands, 1, low, high); 3338 xops[0] = const0_rtx; 3339 xops[1] = high[0]; 3340 3341 output_asm_insn (AS1 (neg%L0,%0), low); 3342 output_asm_insn (AS2 (adc%L1,%0,%1), xops); 3343 output_asm_insn (AS1 (neg%L0,%0), high); 3344 RET; 3345}") 3346 3347(define_insn "negsi2" 3348 [(set (match_operand:SI 0 "general_operand" "=rm") 3349 (neg:SI (match_operand:SI 1 "general_operand" "0")))] 3350 "" 3351 "neg%L0 %0") 3352 3353(define_insn "neghi2" 3354 [(set (match_operand:HI 0 "general_operand" "=rm") 3355 (neg:HI (match_operand:HI 1 "general_operand" "0")))] 3356 "" 3357 "neg%W0 %0") 3358 3359(define_insn "negqi2" 3360 [(set (match_operand:QI 0 "general_operand" "=qm") 3361 (neg:QI (match_operand:QI 1 "general_operand" "0")))] 3362 "" 3363 "neg%B0 %0") 3364 3365(define_insn "negsf2" 3366 [(set (match_operand:SF 0 "register_operand" "=f") 3367 (neg:SF (match_operand:SF 1 "general_operand" "0")))] 3368 "TARGET_80387" 3369 "fchs") 3370 3371(define_insn "negdf2" 3372 [(set (match_operand:DF 0 "register_operand" "=f") 3373 (neg:DF (match_operand:DF 1 "general_operand" "0")))] 3374 "TARGET_80387" 3375 "fchs") 3376 3377(define_insn "" 3378 [(set (match_operand:DF 0 "register_operand" "=f") 3379 (neg:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))] 3380 "TARGET_80387" 3381 "fchs") 3382 3383(define_insn "negxf2" 3384 [(set (match_operand:XF 0 "register_operand" "=f") 3385 (neg:XF (match_operand:XF 1 "general_operand" "0")))] 3386 "TARGET_80387" 3387 "fchs") 3388 3389(define_insn "" 3390 [(set (match_operand:XF 0 "register_operand" "=f") 3391 (neg:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))] 3392 "TARGET_80387" 3393 "fchs") 3394 3395;; Absolute value instructions 3396 3397(define_insn "abssf2" 3398 [(set (match_operand:SF 0 "register_operand" "=f") 3399 (abs:SF (match_operand:SF 1 "general_operand" "0")))] 3400 "TARGET_80387" 3401 "fabs") 3402 3403(define_insn "absdf2" 3404 [(set (match_operand:DF 0 "register_operand" "=f") 3405 (abs:DF (match_operand:DF 1 "general_operand" "0")))] 3406 "TARGET_80387" 3407 "fabs") 3408 3409(define_insn "" 3410 [(set (match_operand:DF 0 "register_operand" "=f") 3411 (abs:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))] 3412 "TARGET_80387" 3413 "fabs") 3414 3415(define_insn "absxf2" 3416 [(set (match_operand:XF 0 "register_operand" "=f") 3417 (abs:XF (match_operand:XF 1 "general_operand" "0")))] 3418 "TARGET_80387" 3419 "fabs") 3420 3421(define_insn "" 3422 [(set (match_operand:XF 0 "register_operand" "=f") 3423 (abs:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))] 3424 "TARGET_80387" 3425 "fabs") 3426 3427(define_insn "sqrtsf2" 3428 [(set (match_operand:SF 0 "register_operand" "=f") 3429 (sqrt:SF (match_operand:SF 1 "general_operand" "0")))] 3430 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 3431 && (TARGET_IEEE_FP || flag_fast_math) " 3432 "fsqrt") 3433 3434(define_insn "sqrtdf2" 3435 [(set (match_operand:DF 0 "register_operand" "=f") 3436 (sqrt:DF (match_operand:DF 1 "general_operand" "0")))] 3437 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 3438 && (TARGET_IEEE_FP || flag_fast_math) " 3439 "fsqrt") 3440 3441(define_insn "" 3442 [(set (match_operand:DF 0 "register_operand" "=f") 3443 (sqrt:DF (float_extend:DF 3444 (match_operand:SF 1 "general_operand" "0"))))] 3445 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 3446 && (TARGET_IEEE_FP || flag_fast_math) " 3447 "fsqrt") 3448 3449(define_insn "sqrtxf2" 3450 [(set (match_operand:XF 0 "register_operand" "=f") 3451 (sqrt:XF (match_operand:XF 1 "general_operand" "0")))] 3452 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 3453 && (TARGET_IEEE_FP || flag_fast_math) " 3454 "fsqrt") 3455 3456(define_insn "" 3457 [(set (match_operand:XF 0 "register_operand" "=f") 3458 (sqrt:XF (float_extend:XF 3459 (match_operand:DF 1 "general_operand" "0"))))] 3460 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 3461 && (TARGET_IEEE_FP || flag_fast_math) " 3462 "fsqrt") 3463 3464(define_insn "" 3465 [(set (match_operand:XF 0 "register_operand" "=f") 3466 (sqrt:XF (float_extend:XF 3467 (match_operand:SF 1 "general_operand" "0"))))] 3468 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 3469 && (TARGET_IEEE_FP || flag_fast_math) " 3470 "fsqrt") 3471 3472(define_insn "sindf2" 3473 [(set (match_operand:DF 0 "register_operand" "=f") 3474 (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))] 3475 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 3476 && (TARGET_IEEE_FP || flag_fast_math) " 3477 "fsin") 3478 3479(define_insn "sinsf2" 3480 [(set (match_operand:SF 0 "register_operand" "=f") 3481 (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))] 3482 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 3483 && (TARGET_IEEE_FP || flag_fast_math) " 3484 "fsin") 3485 3486(define_insn "" 3487 [(set (match_operand:DF 0 "register_operand" "=f") 3488 (unspec:DF [(float_extend:DF 3489 (match_operand:SF 1 "register_operand" "0"))] 1))] 3490 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 3491 && (TARGET_IEEE_FP || flag_fast_math) " 3492 "fsin") 3493 3494(define_insn "sinxf2" 3495 [(set (match_operand:XF 0 "register_operand" "=f") 3496 (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 1))] 3497 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 3498 && (TARGET_IEEE_FP || flag_fast_math) " 3499 "fsin") 3500 3501(define_insn "cosdf2" 3502 [(set (match_operand:DF 0 "register_operand" "=f") 3503 (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))] 3504 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 3505 && (TARGET_IEEE_FP || flag_fast_math) " 3506 "fcos") 3507 3508(define_insn "cossf2" 3509 [(set (match_operand:SF 0 "register_operand" "=f") 3510 (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))] 3511 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 3512 && (TARGET_IEEE_FP || flag_fast_math) " 3513 "fcos") 3514 3515(define_insn "" 3516 [(set (match_operand:DF 0 "register_operand" "=f") 3517 (unspec:DF [(float_extend:DF 3518 (match_operand:SF 1 "register_operand" "0"))] 2))] 3519 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 3520 && (TARGET_IEEE_FP || flag_fast_math) " 3521 "fcos") 3522 3523(define_insn "cosxf2" 3524 [(set (match_operand:XF 0 "register_operand" "=f") 3525 (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 2))] 3526 "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 3527 && (TARGET_IEEE_FP || flag_fast_math) " 3528 "fcos") 3529 3530;;- one complement instructions 3531 3532(define_insn "one_cmplsi2" 3533 [(set (match_operand:SI 0 "general_operand" "=rm") 3534 (not:SI (match_operand:SI 1 "general_operand" "0")))] 3535 "" 3536 "not%L0 %0") 3537 3538(define_insn "one_cmplhi2" 3539 [(set (match_operand:HI 0 "general_operand" "=rm") 3540 (not:HI (match_operand:HI 1 "general_operand" "0")))] 3541 "" 3542 "not%W0 %0") 3543 3544(define_insn "one_cmplqi2" 3545 [(set (match_operand:QI 0 "general_operand" "=qm") 3546 (not:QI (match_operand:QI 1 "general_operand" "0")))] 3547 "" 3548 "not%B0 %0") 3549 3550;;- arithmetic shift instructions 3551 3552;; DImode shifts are implemented using the i386 "shift double" opcode, 3553;; which is written as "sh[lr]d[lw] imm,reg,reg/mem". If the shift count 3554;; is variable, then the count is in %cl and the "imm" operand is dropped 3555;; from the assembler input. 3556 3557;; This instruction shifts the target reg/mem as usual, but instead of 3558;; shifting in zeros, bits are shifted in from reg operand. If the insn 3559;; is a left shift double, bits are taken from the high order bits of 3560;; reg, else if the insn is a shift right double, bits are taken from the 3561;; low order bits of reg. So if %eax is "1234" and %edx is "5678", 3562;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345". 3563 3564;; Since sh[lr]d does not change the `reg' operand, that is done 3565;; separately, making all shifts emit pairs of shift double and normal 3566;; shift. Since sh[lr]d does not shift more than 31 bits, and we wish to 3567;; support a 63 bit shift, each shift where the count is in a reg expands 3568;; to three pairs. If the overall shift is by N bits, then the first two 3569;; pairs shift by N / 2 and the last pair by N & 1. 3570 3571;; If the shift count is a constant, we need never emit more than one 3572;; shift pair, instead using moves and sign extension for counts greater 3573;; than 31. 3574 3575(define_expand "ashldi3" 3576 [(set (match_operand:DI 0 "register_operand" "") 3577 (ashift:DI (match_operand:DI 1 "register_operand" "") 3578 (match_operand:QI 2 "nonmemory_operand" "")))] 3579 "" 3580 " 3581{ 3582 if (GET_CODE (operands[2]) != CONST_INT 3583 || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')) 3584 { 3585 operands[2] = copy_to_mode_reg (QImode, operands[2]); 3586 emit_insn (gen_ashldi3_non_const_int (operands[0], operands[1], 3587 operands[2])); 3588 } 3589 else 3590 emit_insn (gen_ashldi3_const_int (operands[0], operands[1], operands[2])); 3591 3592 DONE; 3593}") 3594 3595(define_insn "ashldi3_const_int" 3596 [(set (match_operand:DI 0 "register_operand" "=&r") 3597 (ashift:DI (match_operand:DI 1 "register_operand" "0") 3598 (match_operand:QI 2 "const_int_operand" "J")))] 3599 "" 3600 "* 3601{ 3602 rtx xops[4], low[1], high[1]; 3603 3604 CC_STATUS_INIT; 3605 3606 split_di (operands, 1, low, high); 3607 xops[0] = operands[2]; 3608 xops[1] = const1_rtx; 3609 xops[2] = low[0]; 3610 xops[3] = high[0]; 3611 3612 if (INTVAL (xops[0]) > 31) 3613 { 3614 output_asm_insn (AS2 (mov%L3,%2,%3), xops); /* Fast shift by 32 */ 3615 output_asm_insn (AS2 (xor%L2,%2,%2), xops); 3616 3617 if (INTVAL (xops[0]) > 32) 3618 { 3619 xops[0] = GEN_INT (INTVAL (xops[0]) - 32); 3620 output_asm_insn (AS2 (sal%L3,%0,%3), xops); /* Remaining shift */ 3621 } 3622 } 3623 else 3624 { 3625 output_asm_insn (AS3 (shld%L3,%0,%2,%3), xops); 3626 output_asm_insn (AS2 (sal%L2,%0,%2), xops); 3627 } 3628 RET; 3629}") 3630 3631(define_insn "ashldi3_non_const_int" 3632 [(set (match_operand:DI 0 "register_operand" "=&r") 3633 (ashift:DI (match_operand:DI 1 "register_operand" "0") 3634 (match_operand:QI 2 "register_operand" "c"))) 3635 (clobber (match_dup 2))] 3636 "" 3637 "* 3638{ 3639 rtx xops[4], low[1], high[1]; 3640 3641 CC_STATUS_INIT; 3642 3643 split_di (operands, 1, low, high); 3644 xops[0] = operands[2]; 3645 xops[1] = const1_rtx; 3646 xops[2] = low[0]; 3647 xops[3] = high[0]; 3648 3649 output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */ 3650 3651 output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops); 3652 output_asm_insn (AS2 (sal%L2,%0,%2), xops); 3653 output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops); 3654 output_asm_insn (AS2 (sal%L2,%0,%2), xops); 3655 3656 xops[1] = GEN_INT (7); /* shift count & 1 */ 3657 3658 output_asm_insn (AS2 (shr%B0,%1,%0), xops); 3659 3660 output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops); 3661 output_asm_insn (AS2 (sal%L2,%0,%2), xops); 3662 3663 RET; 3664}") 3665 3666;; On i386 and i486, "addl reg,reg" is faster than "sall $1,reg" 3667;; On i486, movl/sall appears slightly faster than leal, but the leal 3668;; is smaller - use leal for now unless the shift count is 1. 3669 3670(define_insn "ashlsi3" 3671 [(set (match_operand:SI 0 "general_operand" "=r,rm") 3672 (ashift:SI (match_operand:SI 1 "general_operand" "r,0") 3673 (match_operand:SI 2 "nonmemory_operand" "M,cI")))] 3674 "" 3675 "* 3676{ 3677 if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1])) 3678 { 3679 if (!TARGET_386 && INTVAL (operands[2]) == 1) 3680 { 3681 output_asm_insn (AS2 (mov%L0,%1,%0), operands); 3682 return AS2 (add%L0,%1,%0); 3683 } 3684 else 3685 { 3686 CC_STATUS_INIT; 3687 3688 if (operands[1] == stack_pointer_rtx) 3689 { 3690 output_asm_insn (AS2 (mov%L0,%1,%0), operands); 3691 operands[1] = operands[0]; 3692 } 3693 operands[1] = gen_rtx (MULT, SImode, operands[1], 3694 GEN_INT (1 << INTVAL (operands[2]))); 3695 return AS2 (lea%L0,%a1,%0); 3696 } 3697 } 3698 3699 if (REG_P (operands[2])) 3700 return AS2 (sal%L0,%b2,%0); 3701 3702 if (REG_P (operands[0]) && operands[2] == const1_rtx) 3703 return AS2 (add%L0,%0,%0); 3704 3705 return AS2 (sal%L0,%2,%0); 3706}") 3707 3708(define_insn "ashlhi3" 3709 [(set (match_operand:HI 0 "general_operand" "=rm") 3710 (ashift:HI (match_operand:HI 1 "general_operand" "0") 3711 (match_operand:HI 2 "nonmemory_operand" "cI")))] 3712 "" 3713 "* 3714{ 3715 if (REG_P (operands[2])) 3716 return AS2 (sal%W0,%b2,%0); 3717 3718 if (REG_P (operands[0]) && operands[2] == const1_rtx) 3719 return AS2 (add%W0,%0,%0); 3720 3721 return AS2 (sal%W0,%2,%0); 3722}") 3723 3724(define_insn "ashlqi3" 3725 [(set (match_operand:QI 0 "general_operand" "=qm") 3726 (ashift:QI (match_operand:QI 1 "general_operand" "0") 3727 (match_operand:QI 2 "nonmemory_operand" "cI")))] 3728 "" 3729 "* 3730{ 3731 if (REG_P (operands[2])) 3732 return AS2 (sal%B0,%b2,%0); 3733 3734 if (REG_P (operands[0]) && operands[2] == const1_rtx) 3735 return AS2 (add%B0,%0,%0); 3736 3737 return AS2 (sal%B0,%2,%0); 3738}") 3739 3740;; See comment above `ashldi3' about how this works. 3741 3742(define_expand "ashrdi3" 3743 [(set (match_operand:DI 0 "register_operand" "") 3744 (ashiftrt:DI (match_operand:DI 1 "register_operand" "") 3745 (match_operand:QI 2 "nonmemory_operand" "")))] 3746 "" 3747 " 3748{ 3749 if (GET_CODE (operands[2]) != CONST_INT 3750 || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')) 3751 { 3752 operands[2] = copy_to_mode_reg (QImode, operands[2]); 3753 emit_insn (gen_ashrdi3_non_const_int (operands[0], operands[1], 3754 operands[2])); 3755 } 3756 else 3757 emit_insn (gen_ashrdi3_const_int (operands[0], operands[1], operands[2])); 3758 3759 DONE; 3760}") 3761 3762(define_insn "ashrdi3_const_int" 3763 [(set (match_operand:DI 0 "register_operand" "=&r") 3764 (ashiftrt:DI (match_operand:DI 1 "register_operand" "0") 3765 (match_operand:QI 2 "const_int_operand" "J")))] 3766 "" 3767 "* 3768{ 3769 rtx xops[4], low[1], high[1]; 3770 3771 CC_STATUS_INIT; 3772 3773 split_di (operands, 1, low, high); 3774 xops[0] = operands[2]; 3775 xops[1] = const1_rtx; 3776 xops[2] = low[0]; 3777 xops[3] = high[0]; 3778 3779 if (INTVAL (xops[0]) > 31) 3780 { 3781 xops[1] = GEN_INT (31); 3782 output_asm_insn (AS2 (mov%L2,%3,%2), xops); 3783 output_asm_insn (AS2 (sar%L3,%1,%3), xops); /* shift by 32 */ 3784 3785 if (INTVAL (xops[0]) > 32) 3786 { 3787 xops[0] = GEN_INT (INTVAL (xops[0]) - 32); 3788 output_asm_insn (AS2 (sar%L2,%0,%2), xops); /* Remaining shift */ 3789 } 3790 } 3791 else 3792 { 3793 output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops); 3794 output_asm_insn (AS2 (sar%L3,%0,%3), xops); 3795 } 3796 3797 RET; 3798}") 3799 3800(define_insn "ashrdi3_non_const_int" 3801 [(set (match_operand:DI 0 "register_operand" "=&r") 3802 (ashiftrt:DI (match_operand:DI 1 "register_operand" "0") 3803 (match_operand:QI 2 "register_operand" "c"))) 3804 (clobber (match_dup 2))] 3805 "" 3806 "* 3807{ 3808 rtx xops[4], low[1], high[1]; 3809 3810 CC_STATUS_INIT; 3811 3812 split_di (operands, 1, low, high); 3813 xops[0] = operands[2]; 3814 xops[1] = const1_rtx; 3815 xops[2] = low[0]; 3816 xops[3] = high[0]; 3817 3818 output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */ 3819 3820 output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); 3821 output_asm_insn (AS2 (sar%L3,%0,%3), xops); 3822 output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); 3823 output_asm_insn (AS2 (sar%L3,%0,%3), xops); 3824 3825 xops[1] = GEN_INT (7); /* shift count & 1 */ 3826 3827 output_asm_insn (AS2 (shr%B0,%1,%0), xops); 3828 3829 output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); 3830 output_asm_insn (AS2 (sar%L3,%0,%3), xops); 3831 3832 RET; 3833}") 3834 3835(define_insn "ashrsi3" 3836 [(set (match_operand:SI 0 "general_operand" "=rm") 3837 (ashiftrt:SI (match_operand:SI 1 "general_operand" "0") 3838 (match_operand:SI 2 "nonmemory_operand" "cI")))] 3839 "" 3840 "* 3841{ 3842 if (REG_P (operands[2])) 3843 return AS2 (sar%L0,%b2,%0); 3844 else 3845 return AS2 (sar%L0,%2,%0); 3846}") 3847 3848(define_insn "ashrhi3" 3849 [(set (match_operand:HI 0 "general_operand" "=rm") 3850 (ashiftrt:HI (match_operand:HI 1 "general_operand" "0") 3851 (match_operand:HI 2 "nonmemory_operand" "cI")))] 3852 "" 3853 "* 3854{ 3855 if (REG_P (operands[2])) 3856 return AS2 (sar%W0,%b2,%0); 3857 else 3858 return AS2 (sar%W0,%2,%0); 3859}") 3860 3861(define_insn "ashrqi3" 3862 [(set (match_operand:QI 0 "general_operand" "=qm") 3863 (ashiftrt:QI (match_operand:QI 1 "general_operand" "0") 3864 (match_operand:QI 2 "nonmemory_operand" "cI")))] 3865 "" 3866 "* 3867{ 3868 if (REG_P (operands[2])) 3869 return AS2 (sar%B0,%b2,%0); 3870 else 3871 return AS2 (sar%B0,%2,%0); 3872}") 3873 3874;;- logical shift instructions 3875 3876;; See comment above `ashldi3' about how this works. 3877 3878(define_expand "lshrdi3" 3879 [(set (match_operand:DI 0 "register_operand" "") 3880 (lshiftrt:DI (match_operand:DI 1 "register_operand" "") 3881 (match_operand:QI 2 "nonmemory_operand" "")))] 3882 "" 3883 " 3884{ 3885 if (GET_CODE (operands[2]) != CONST_INT 3886 || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')) 3887 { 3888 operands[2] = copy_to_mode_reg (QImode, operands[2]); 3889 emit_insn (gen_lshrdi3_non_const_int (operands[0], operands[1], 3890 operands[2])); 3891 } 3892 else 3893 emit_insn (gen_lshrdi3_const_int (operands[0], operands[1], operands[2])); 3894 3895 DONE; 3896}") 3897 3898(define_insn "lshrdi3_const_int" 3899 [(set (match_operand:DI 0 "register_operand" "=&r") 3900 (lshiftrt:DI (match_operand:DI 1 "register_operand" "0") 3901 (match_operand:QI 2 "const_int_operand" "J")))] 3902 "" 3903 "* 3904{ 3905 rtx xops[4], low[1], high[1]; 3906 3907 CC_STATUS_INIT; 3908 3909 split_di (operands, 1, low, high); 3910 xops[0] = operands[2]; 3911 xops[1] = const1_rtx; 3912 xops[2] = low[0]; 3913 xops[3] = high[0]; 3914 3915 if (INTVAL (xops[0]) > 31) 3916 { 3917 output_asm_insn (AS2 (mov%L2,%3,%2), xops); /* Fast shift by 32 */ 3918 output_asm_insn (AS2 (xor%L3,%3,%3), xops); 3919 3920 if (INTVAL (xops[0]) > 32) 3921 { 3922 xops[0] = GEN_INT (INTVAL (xops[0]) - 32); 3923 output_asm_insn (AS2 (shr%L2,%0,%2), xops); /* Remaining shift */ 3924 } 3925 } 3926 else 3927 { 3928 output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops); 3929 output_asm_insn (AS2 (shr%L3,%0,%3), xops); 3930 } 3931 3932 RET; 3933}") 3934 3935(define_insn "lshrdi3_non_const_int" 3936 [(set (match_operand:DI 0 "register_operand" "=&r") 3937 (lshiftrt:DI (match_operand:DI 1 "register_operand" "0") 3938 (match_operand:QI 2 "register_operand" "c"))) 3939 (clobber (match_dup 2))] 3940 "" 3941 "* 3942{ 3943 rtx xops[4], low[1], high[1]; 3944 3945 CC_STATUS_INIT; 3946 3947 split_di (operands, 1, low, high); 3948 xops[0] = operands[2]; 3949 xops[1] = const1_rtx; 3950 xops[2] = low[0]; 3951 xops[3] = high[0]; 3952 3953 output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */ 3954 3955 output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); 3956 output_asm_insn (AS2 (shr%L3,%0,%3), xops); 3957 output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); 3958 output_asm_insn (AS2 (shr%L3,%0,%3), xops); 3959 3960 xops[1] = GEN_INT (7); /* shift count & 1 */ 3961 3962 output_asm_insn (AS2 (shr%B0,%1,%0), xops); 3963 3964 output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); 3965 output_asm_insn (AS2 (shr%L3,%0,%3), xops); 3966 3967 RET; 3968}") 3969 3970(define_insn "lshrsi3" 3971 [(set (match_operand:SI 0 "general_operand" "=rm") 3972 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0") 3973 (match_operand:SI 2 "nonmemory_operand" "cI")))] 3974 "" 3975 "* 3976{ 3977 if (REG_P (operands[2])) 3978 return AS2 (shr%L0,%b2,%0); 3979 else 3980 return AS2 (shr%L0,%2,%1); 3981}") 3982 3983(define_insn "lshrhi3" 3984 [(set (match_operand:HI 0 "general_operand" "=rm") 3985 (lshiftrt:HI (match_operand:HI 1 "general_operand" "0") 3986 (match_operand:HI 2 "nonmemory_operand" "cI")))] 3987 "" 3988 "* 3989{ 3990 if (REG_P (operands[2])) 3991 return AS2 (shr%W0,%b2,%0); 3992 else 3993 return AS2 (shr%W0,%2,%0); 3994}") 3995 3996(define_insn "lshrqi3" 3997 [(set (match_operand:QI 0 "general_operand" "=qm") 3998 (lshiftrt:QI (match_operand:QI 1 "general_operand" "0") 3999 (match_operand:QI 2 "nonmemory_operand" "cI")))] 4000 "" 4001 "* 4002{ 4003 if (REG_P (operands[2])) 4004 return AS2 (shr%B0,%b2,%0); 4005 else 4006 return AS2 (shr%B0,%2,%0); 4007}") 4008 4009;;- rotate instructions 4010 4011(define_insn "rotlsi3" 4012 [(set (match_operand:SI 0 "general_operand" "=rm") 4013 (rotate:SI (match_operand:SI 1 "general_operand" "0") 4014 (match_operand:SI 2 "nonmemory_operand" "cI")))] 4015 "" 4016 "* 4017{ 4018 if (REG_P (operands[2])) 4019 return AS2 (rol%L0,%b2,%0); 4020 else 4021 return AS2 (rol%L0,%2,%0); 4022}") 4023 4024(define_insn "rotlhi3" 4025 [(set (match_operand:HI 0 "general_operand" "=rm") 4026 (rotate:HI (match_operand:HI 1 "general_operand" "0") 4027 (match_operand:HI 2 "nonmemory_operand" "cI")))] 4028 "" 4029 "* 4030{ 4031 if (REG_P (operands[2])) 4032 return AS2 (rol%W0,%b2,%0); 4033 else 4034 return AS2 (rol%W0,%2,%0); 4035}") 4036 4037(define_insn "rotlqi3" 4038 [(set (match_operand:QI 0 "general_operand" "=qm") 4039 (rotate:QI (match_operand:QI 1 "general_operand" "0") 4040 (match_operand:QI 2 "nonmemory_operand" "cI")))] 4041 "" 4042 "* 4043{ 4044 if (REG_P (operands[2])) 4045 return AS2 (rol%B0,%b2,%0); 4046 else 4047 return AS2 (rol%B0,%2,%0); 4048}") 4049 4050(define_insn "rotrsi3" 4051 [(set (match_operand:SI 0 "general_operand" "=rm") 4052 (rotatert:SI (match_operand:SI 1 "general_operand" "0") 4053 (match_operand:SI 2 "nonmemory_operand" "cI")))] 4054 "" 4055 "* 4056{ 4057 if (REG_P (operands[2])) 4058 return AS2 (ror%L0,%b2,%0); 4059 else 4060 return AS2 (ror%L0,%2,%0); 4061}") 4062 4063(define_insn "rotrhi3" 4064 [(set (match_operand:HI 0 "general_operand" "=rm") 4065 (rotatert:HI (match_operand:HI 1 "general_operand" "0") 4066 (match_operand:HI 2 "nonmemory_operand" "cI")))] 4067 "" 4068 "* 4069{ 4070 if (REG_P (operands[2])) 4071 return AS2 (ror%W0,%b2,%0); 4072 else 4073 return AS2 (ror%W0,%2,%0); 4074}") 4075 4076(define_insn "rotrqi3" 4077 [(set (match_operand:QI 0 "general_operand" "=qm") 4078 (rotatert:QI (match_operand:QI 1 "general_operand" "0") 4079 (match_operand:QI 2 "nonmemory_operand" "cI")))] 4080 "" 4081 "* 4082{ 4083 if (REG_P (operands[2])) 4084 return AS2 (ror%B0,%b2,%0); 4085 else 4086 return AS2 (ror%B0,%2,%0); 4087}") 4088 4089/* 4090;; This usually looses. But try a define_expand to recognize a few case 4091;; we can do efficiently, such as accessing the "high" QImode registers, 4092;; %ah, %bh, %ch, %dh. 4093(define_insn "insv" 4094 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+&r") 4095 (match_operand:SI 1 "general_operand" "i") 4096 (match_operand:SI 2 "general_operand" "i")) 4097 (match_operand:SI 3 "general_operand" "ri"))] 4098 "" 4099 "* 4100{ 4101 if (INTVAL (operands[1]) + INTVAL (operands[2]) > GET_MODE_BITSIZE (SImode)) 4102 abort (); 4103 if (GET_CODE (operands[3]) == CONST_INT) 4104 { 4105 unsigned int mask = (1 << INTVAL (operands[1])) - 1; 4106 operands[1] = GEN_INT (~(mask << INTVAL (operands[2]))); 4107 output_asm_insn (AS2 (and%L0,%1,%0), operands); 4108 operands[3] = GEN_INT (INTVAL (operands[3]) << INTVAL (operands[2])); 4109 output_asm_insn (AS2 (or%L0,%3,%0), operands); 4110 } 4111 else 4112 { 4113 operands[0] = gen_rtx (REG, SImode, REGNO (operands[0])); 4114 if (INTVAL (operands[2])) 4115 output_asm_insn (AS2 (ror%L0,%2,%0), operands); 4116 output_asm_insn (AS3 (shrd%L0,%1,%3,%0), operands); 4117 operands[2] = GEN_INT (BITS_PER_WORD 4118 - INTVAL (operands[1]) - INTVAL (operands[2])); 4119 if (INTVAL (operands[2])) 4120 output_asm_insn (AS2 (ror%L0,%2,%0), operands); 4121 } 4122 RET; 4123}") 4124*/ 4125/* 4126;; ??? There are problems with the mode of operand[3]. The point of this 4127;; is to represent an HImode move to a "high byte" register. 4128 4129(define_expand "insv" 4130 [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "") 4131 (match_operand:SI 1 "immediate_operand" "") 4132 (match_operand:SI 2 "immediate_operand" "")) 4133 (match_operand:QI 3 "general_operand" "ri"))] 4134 "" 4135 " 4136{ 4137 if (GET_CODE (operands[1]) != CONST_INT 4138 || GET_CODE (operands[2]) != CONST_INT) 4139 FAIL; 4140 4141 if (! (INTVAL (operands[1]) == 8 4142 && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 0)) 4143 && ! INTVAL (operands[1]) == 1) 4144 FAIL; 4145}") 4146 4147;; ??? Are these constraints right? 4148(define_insn "" 4149 [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+&qo") 4150 (const_int 8) 4151 (const_int 8)) 4152 (match_operand:QI 1 "general_operand" "qn"))] 4153 "" 4154 "* 4155{ 4156 if (REG_P (operands[0])) 4157 return AS2 (mov%B0,%1,%h0); 4158 4159 operands[0] = adj_offsettable_operand (operands[0], 1); 4160 return AS2 (mov%B0,%1,%0); 4161}") 4162*/ 4163 4164;; On i386, the register count for a bit operation is *not* truncated, 4165;; so SHIFT_COUNT_TRUNCATED must not be defined. 4166 4167;; On i486, the shift & or/and code is faster than bts or btr. If 4168;; operands[0] is a MEM, the bt[sr] is half as fast as the normal code. 4169 4170;; On i386, bts is a little faster if operands[0] is a reg, and a 4171;; little slower if operands[0] is a MEM, than the shift & or/and code. 4172;; Use bts & btr, since they reload better. 4173 4174;; General bit set and clear. 4175(define_insn "" 4176 [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+rm") 4177 (const_int 1) 4178 (match_operand:SI 2 "general_operand" "r")) 4179 (match_operand:SI 3 "const_int_operand" "n"))] 4180 "TARGET_386 && GET_CODE (operands[2]) != CONST_INT" 4181 "* 4182{ 4183 CC_STATUS_INIT; 4184 4185 if (INTVAL (operands[3]) == 1) 4186 return AS2 (bts%L0,%2,%0); 4187 else 4188 return AS2 (btr%L0,%2,%0); 4189}") 4190 4191;; Bit complement. See comments on previous pattern. 4192;; ??? Is this really worthwhile? 4193(define_insn "" 4194 [(set (match_operand:SI 0 "general_operand" "=rm") 4195 (xor:SI (ashift:SI (const_int 1) 4196 (match_operand:SI 1 "general_operand" "r")) 4197 (match_operand:SI 2 "general_operand" "0")))] 4198 "TARGET_386 && GET_CODE (operands[1]) != CONST_INT" 4199 "* 4200{ 4201 CC_STATUS_INIT; 4202 4203 return AS2 (btc%L0,%1,%0); 4204}") 4205 4206(define_insn "" 4207 [(set (match_operand:SI 0 "general_operand" "=rm") 4208 (xor:SI (match_operand:SI 1 "general_operand" "0") 4209 (ashift:SI (const_int 1) 4210 (match_operand:SI 2 "general_operand" "r"))))] 4211 "TARGET_386 && GET_CODE (operands[2]) != CONST_INT" 4212 "* 4213{ 4214 CC_STATUS_INIT; 4215 4216 return AS2 (btc%L0,%2,%0); 4217}") 4218 4219;; Recognizers for bit-test instructions. 4220 4221;; The bt opcode allows a MEM in operands[0]. But on both i386 and 4222;; i486, it is faster to copy a MEM to REG and then use bt, than to use 4223;; bt on the MEM directly. 4224 4225;; ??? The first argument of a zero_extract must not be reloaded, so 4226;; don't allow a MEM in the operand predicate without allowing it in the 4227;; constraint. 4228 4229(define_insn "" 4230 [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r") 4231 (const_int 1) 4232 (match_operand:SI 1 "general_operand" "r")))] 4233 "GET_CODE (operands[1]) != CONST_INT" 4234 "* 4235{ 4236 cc_status.flags |= CC_Z_IN_NOT_C; 4237 return AS2 (bt%L0,%1,%0); 4238}") 4239 4240(define_insn "" 4241 [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r") 4242 (match_operand:SI 1 "const_int_operand" "n") 4243 (match_operand:SI 2 "const_int_operand" "n")))] 4244 "" 4245 "* 4246{ 4247 unsigned int mask; 4248 4249 mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]); 4250 operands[1] = GEN_INT (mask); 4251 4252 if (QI_REG_P (operands[0])) 4253 { 4254 if ((mask & ~0xff) == 0) 4255 { 4256 cc_status.flags |= CC_NOT_NEGATIVE; 4257 return AS2 (test%B0,%1,%b0); 4258 } 4259 4260 if ((mask & ~0xff00) == 0) 4261 { 4262 cc_status.flags |= CC_NOT_NEGATIVE; 4263 operands[1] = GEN_INT (mask >> 8); 4264 return AS2 (test%B0,%1,%h0); 4265 } 4266 } 4267 4268 return AS2 (test%L0,%1,%0); 4269}") 4270 4271;; ??? All bets are off if operand 0 is a volatile MEM reference. 4272;; The CPU may access unspecified bytes around the actual target byte. 4273 4274(define_insn "" 4275 [(set (cc0) (zero_extract (match_operand:QI 0 "general_operand" "rm") 4276 (match_operand:SI 1 "const_int_operand" "n") 4277 (match_operand:SI 2 "const_int_operand" "n")))] 4278 "GET_CODE (operands[0]) != MEM || ! MEM_VOLATILE_P (operands[0])" 4279 "* 4280{ 4281 unsigned int mask; 4282 4283 mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]); 4284 operands[1] = GEN_INT (mask); 4285 4286 if (! REG_P (operands[0]) || QI_REG_P (operands[0])) 4287 { 4288 if ((mask & ~0xff) == 0) 4289 { 4290 cc_status.flags |= CC_NOT_NEGATIVE; 4291 return AS2 (test%B0,%1,%b0); 4292 } 4293 4294 if ((mask & ~0xff00) == 0) 4295 { 4296 cc_status.flags |= CC_NOT_NEGATIVE; 4297 operands[1] = GEN_INT (mask >> 8); 4298 4299 if (QI_REG_P (operands[0])) 4300 return AS2 (test%B0,%1,%h0); 4301 else 4302 { 4303 operands[0] = adj_offsettable_operand (operands[0], 1); 4304 return AS2 (test%B0,%1,%b0); 4305 } 4306 } 4307 4308 if (GET_CODE (operands[0]) == MEM && (mask & ~0xff0000) == 0) 4309 { 4310 cc_status.flags |= CC_NOT_NEGATIVE; 4311 operands[1] = GEN_INT (mask >> 16); 4312 operands[0] = adj_offsettable_operand (operands[0], 2); 4313 return AS2 (test%B0,%1,%b0); 4314 } 4315 4316 if (GET_CODE (operands[0]) == MEM && (mask & ~0xff000000) == 0) 4317 { 4318 cc_status.flags |= CC_NOT_NEGATIVE; 4319 operands[1] = GEN_INT (mask >> 24); 4320 operands[0] = adj_offsettable_operand (operands[0], 3); 4321 return AS2 (test%B0,%1,%b0); 4322 } 4323 } 4324 4325 if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) 4326 return AS2 (test%L0,%1,%0); 4327 4328 return AS2 (test%L1,%0,%1); 4329}") 4330 4331;; Store-flag instructions. 4332 4333;; For all sCOND expanders, also expand the compare or test insn that 4334;; generates cc0. Generate an equality comparison if `seq' or `sne'. 4335 4336;; The 386 sCOND opcodes can write to memory. But a gcc sCOND insn may 4337;; not have any input reloads. A MEM write might need an input reload 4338;; for the address of the MEM. So don't allow MEM as the SET_DEST. 4339 4340(define_expand "seq" 4341 [(match_dup 1) 4342 (set (match_operand:QI 0 "register_operand" "") 4343 (eq:QI (cc0) (const_int 0)))] 4344 "" 4345 " 4346{ 4347 if (TARGET_IEEE_FP 4348 && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT) 4349 operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1); 4350 else 4351 operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1); 4352}") 4353 4354(define_insn "" 4355 [(set (match_operand:QI 0 "register_operand" "=q") 4356 (eq:QI (cc0) (const_int 0)))] 4357 "" 4358 "* 4359{ 4360 if (cc_prev_status.flags & CC_Z_IN_NOT_C) 4361 return AS1 (setnb,%0); 4362 else 4363 return AS1 (sete,%0); 4364}") 4365 4366(define_expand "sne" 4367 [(match_dup 1) 4368 (set (match_operand:QI 0 "register_operand" "") 4369 (ne:QI (cc0) (const_int 0)))] 4370 "" 4371 " 4372{ 4373 if (TARGET_IEEE_FP 4374 && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT) 4375 operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1); 4376 else 4377 operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1); 4378}") 4379 4380(define_insn "" 4381 [(set (match_operand:QI 0 "register_operand" "=q") 4382 (ne:QI (cc0) (const_int 0)))] 4383 "" 4384 "* 4385{ 4386 if (cc_prev_status.flags & CC_Z_IN_NOT_C) 4387 return AS1 (setb,%0); 4388 else 4389 return AS1 (setne,%0); 4390} 4391") 4392 4393(define_expand "sgt" 4394 [(match_dup 1) 4395 (set (match_operand:QI 0 "register_operand" "") 4396 (gt:QI (cc0) (const_int 0)))] 4397 "" 4398 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 4399 4400(define_insn "" 4401 [(set (match_operand:QI 0 "register_operand" "=q") 4402 (gt:QI (cc0) (const_int 0)))] 4403 "" 4404 "* 4405{ 4406 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 4407 return AS1 (sete,%0); 4408 4409 OUTPUT_JUMP (\"setg %0\", \"seta %0\", NULL_PTR); 4410}") 4411 4412(define_expand "sgtu" 4413 [(match_dup 1) 4414 (set (match_operand:QI 0 "register_operand" "") 4415 (gtu:QI (cc0) (const_int 0)))] 4416 "" 4417 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 4418 4419(define_insn "" 4420 [(set (match_operand:QI 0 "register_operand" "=q") 4421 (gtu:QI (cc0) (const_int 0)))] 4422 "" 4423 "* return \"seta %0\"; ") 4424 4425(define_expand "slt" 4426 [(match_dup 1) 4427 (set (match_operand:QI 0 "register_operand" "") 4428 (lt:QI (cc0) (const_int 0)))] 4429 "" 4430 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 4431 4432(define_insn "" 4433 [(set (match_operand:QI 0 "register_operand" "=q") 4434 (lt:QI (cc0) (const_int 0)))] 4435 "" 4436 "* 4437{ 4438 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 4439 return AS1 (sete,%0); 4440 4441 OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\"); 4442}") 4443 4444(define_expand "sltu" 4445 [(match_dup 1) 4446 (set (match_operand:QI 0 "register_operand" "") 4447 (ltu:QI (cc0) (const_int 0)))] 4448 "" 4449 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 4450 4451(define_insn "" 4452 [(set (match_operand:QI 0 "register_operand" "=q") 4453 (ltu:QI (cc0) (const_int 0)))] 4454 "" 4455 "* return \"setb %0\"; ") 4456 4457(define_expand "sge" 4458 [(match_dup 1) 4459 (set (match_operand:QI 0 "register_operand" "") 4460 (ge:QI (cc0) (const_int 0)))] 4461 "" 4462 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 4463 4464(define_insn "" 4465 [(set (match_operand:QI 0 "register_operand" "=q") 4466 (ge:QI (cc0) (const_int 0)))] 4467 "" 4468 "* 4469{ 4470 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 4471 return AS1 (sete,%0); 4472 4473 OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\"); 4474}") 4475 4476(define_expand "sgeu" 4477 [(match_dup 1) 4478 (set (match_operand:QI 0 "register_operand" "") 4479 (geu:QI (cc0) (const_int 0)))] 4480 "" 4481 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 4482 4483(define_insn "" 4484 [(set (match_operand:QI 0 "register_operand" "=q") 4485 (geu:QI (cc0) (const_int 0)))] 4486 "" 4487 "* return \"setae %0\"; ") 4488 4489(define_expand "sle" 4490 [(match_dup 1) 4491 (set (match_operand:QI 0 "register_operand" "") 4492 (le:QI (cc0) (const_int 0)))] 4493 "" 4494 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 4495 4496(define_insn "" 4497 [(set (match_operand:QI 0 "register_operand" "=q") 4498 (le:QI (cc0) (const_int 0)))] 4499 "" 4500 "* 4501{ 4502 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 4503 return AS1 (setb,%0); 4504 4505 OUTPUT_JUMP (\"setle %0\", \"setbe %0\", NULL_PTR); 4506}") 4507 4508(define_expand "sleu" 4509 [(match_dup 1) 4510 (set (match_operand:QI 0 "register_operand" "") 4511 (leu:QI (cc0) (const_int 0)))] 4512 "" 4513 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 4514 4515(define_insn "" 4516 [(set (match_operand:QI 0 "register_operand" "=q") 4517 (leu:QI (cc0) (const_int 0)))] 4518 "" 4519 "* return \"setbe %0\"; ") 4520 4521;; Basic conditional jump instructions. 4522;; We ignore the overflow flag for signed branch instructions. 4523 4524;; For all bCOND expanders, also expand the compare or test insn that 4525;; generates cc0. Generate an equality comparison if `beq' or `bne'. 4526 4527(define_expand "beq" 4528 [(match_dup 1) 4529 (set (pc) 4530 (if_then_else (eq (cc0) 4531 (const_int 0)) 4532 (label_ref (match_operand 0 "" "")) 4533 (pc)))] 4534 "" 4535 " 4536{ 4537 if (TARGET_IEEE_FP 4538 && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT) 4539 operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1); 4540 else 4541 operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1); 4542}") 4543 4544(define_insn "" 4545 [(set (pc) 4546 (if_then_else (eq (cc0) 4547 (const_int 0)) 4548 (label_ref (match_operand 0 "" "")) 4549 (pc)))] 4550 "" 4551 "* 4552{ 4553 if (cc_prev_status.flags & CC_Z_IN_NOT_C) 4554 return \"jnc %l0\"; 4555 else 4556 return \"je %l0\"; 4557}") 4558 4559(define_expand "bne" 4560 [(match_dup 1) 4561 (set (pc) 4562 (if_then_else (ne (cc0) 4563 (const_int 0)) 4564 (label_ref (match_operand 0 "" "")) 4565 (pc)))] 4566 "" 4567 " 4568{ 4569 if (TARGET_IEEE_FP 4570 && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT) 4571 operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1); 4572 else 4573 operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1); 4574}") 4575 4576(define_insn "" 4577 [(set (pc) 4578 (if_then_else (ne (cc0) 4579 (const_int 0)) 4580 (label_ref (match_operand 0 "" "")) 4581 (pc)))] 4582 "" 4583 "* 4584{ 4585 if (cc_prev_status.flags & CC_Z_IN_NOT_C) 4586 return \"jc %l0\"; 4587 else 4588 return \"jne %l0\"; 4589}") 4590 4591(define_expand "bgt" 4592 [(match_dup 1) 4593 (set (pc) 4594 (if_then_else (gt (cc0) 4595 (const_int 0)) 4596 (label_ref (match_operand 0 "" "")) 4597 (pc)))] 4598 "" 4599 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 4600 4601(define_insn "" 4602 [(set (pc) 4603 (if_then_else (gt (cc0) 4604 (const_int 0)) 4605 (label_ref (match_operand 0 "" "")) 4606 (pc)))] 4607 "" 4608 "* 4609{ 4610 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 4611 return AS1 (je,%l0); 4612 4613 OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR); 4614}") 4615 4616(define_expand "bgtu" 4617 [(match_dup 1) 4618 (set (pc) 4619 (if_then_else (gtu (cc0) 4620 (const_int 0)) 4621 (label_ref (match_operand 0 "" "")) 4622 (pc)))] 4623 "" 4624 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 4625 4626(define_insn "" 4627 [(set (pc) 4628 (if_then_else (gtu (cc0) 4629 (const_int 0)) 4630 (label_ref (match_operand 0 "" "")) 4631 (pc)))] 4632 "" 4633 "ja %l0") 4634 4635(define_expand "blt" 4636 [(match_dup 1) 4637 (set (pc) 4638 (if_then_else (lt (cc0) 4639 (const_int 0)) 4640 (label_ref (match_operand 0 "" "")) 4641 (pc)))] 4642 "" 4643 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 4644 4645(define_insn "" 4646 [(set (pc) 4647 (if_then_else (lt (cc0) 4648 (const_int 0)) 4649 (label_ref (match_operand 0 "" "")) 4650 (pc)))] 4651 "" 4652 "* 4653{ 4654 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 4655 return AS1 (je,%l0); 4656 4657 OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\"); 4658}") 4659 4660(define_expand "bltu" 4661 [(match_dup 1) 4662 (set (pc) 4663 (if_then_else (ltu (cc0) 4664 (const_int 0)) 4665 (label_ref (match_operand 0 "" "")) 4666 (pc)))] 4667 "" 4668 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 4669 4670(define_insn "" 4671 [(set (pc) 4672 (if_then_else (ltu (cc0) 4673 (const_int 0)) 4674 (label_ref (match_operand 0 "" "")) 4675 (pc)))] 4676 "" 4677 "jb %l0") 4678 4679(define_expand "bge" 4680 [(match_dup 1) 4681 (set (pc) 4682 (if_then_else (ge (cc0) 4683 (const_int 0)) 4684 (label_ref (match_operand 0 "" "")) 4685 (pc)))] 4686 "" 4687 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 4688 4689(define_insn "" 4690 [(set (pc) 4691 (if_then_else (ge (cc0) 4692 (const_int 0)) 4693 (label_ref (match_operand 0 "" "")) 4694 (pc)))] 4695 "" 4696 "* 4697{ 4698 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 4699 return AS1 (je,%l0); 4700 4701 OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\"); 4702}") 4703 4704(define_expand "bgeu" 4705 [(match_dup 1) 4706 (set (pc) 4707 (if_then_else (geu (cc0) 4708 (const_int 0)) 4709 (label_ref (match_operand 0 "" "")) 4710 (pc)))] 4711 "" 4712 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 4713 4714(define_insn "" 4715 [(set (pc) 4716 (if_then_else (geu (cc0) 4717 (const_int 0)) 4718 (label_ref (match_operand 0 "" "")) 4719 (pc)))] 4720 "" 4721 "jae %l0") 4722 4723(define_expand "ble" 4724 [(match_dup 1) 4725 (set (pc) 4726 (if_then_else (le (cc0) 4727 (const_int 0)) 4728 (label_ref (match_operand 0 "" "")) 4729 (pc)))] 4730 "" 4731 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 4732 4733(define_insn "" 4734 [(set (pc) 4735 (if_then_else (le (cc0) 4736 (const_int 0)) 4737 (label_ref (match_operand 0 "" "")) 4738 (pc)))] 4739 "" 4740 "* 4741{ 4742 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 4743 return AS1 (jb,%l0); 4744 4745 OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR); 4746}") 4747 4748(define_expand "bleu" 4749 [(match_dup 1) 4750 (set (pc) 4751 (if_then_else (leu (cc0) 4752 (const_int 0)) 4753 (label_ref (match_operand 0 "" "")) 4754 (pc)))] 4755 "" 4756 "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") 4757 4758(define_insn "" 4759 [(set (pc) 4760 (if_then_else (leu (cc0) 4761 (const_int 0)) 4762 (label_ref (match_operand 0 "" "")) 4763 (pc)))] 4764 "" 4765 "jbe %l0") 4766 4767;; Negated conditional jump instructions. 4768 4769(define_insn "" 4770 [(set (pc) 4771 (if_then_else (eq (cc0) 4772 (const_int 0)) 4773 (pc) 4774 (label_ref (match_operand 0 "" ""))))] 4775 "" 4776 "* 4777{ 4778 if (cc_prev_status.flags & CC_Z_IN_NOT_C) 4779 return \"jc %l0\"; 4780 else 4781 return \"jne %l0\"; 4782}") 4783 4784(define_insn "" 4785 [(set (pc) 4786 (if_then_else (ne (cc0) 4787 (const_int 0)) 4788 (pc) 4789 (label_ref (match_operand 0 "" ""))))] 4790 "" 4791 "* 4792{ 4793 if (cc_prev_status.flags & CC_Z_IN_NOT_C) 4794 return \"jnc %l0\"; 4795 else 4796 return \"je %l0\"; 4797}") 4798 4799(define_insn "" 4800 [(set (pc) 4801 (if_then_else (gt (cc0) 4802 (const_int 0)) 4803 (pc) 4804 (label_ref (match_operand 0 "" ""))))] 4805 "" 4806 "* 4807{ 4808 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 4809 return AS1 (jne,%l0); 4810 4811 OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR); 4812}") 4813 4814(define_insn "" 4815 [(set (pc) 4816 (if_then_else (gtu (cc0) 4817 (const_int 0)) 4818 (pc) 4819 (label_ref (match_operand 0 "" ""))))] 4820 "" 4821 "jbe %l0") 4822 4823(define_insn "" 4824 [(set (pc) 4825 (if_then_else (lt (cc0) 4826 (const_int 0)) 4827 (pc) 4828 (label_ref (match_operand 0 "" ""))))] 4829 "" 4830 "* 4831{ 4832 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 4833 return AS1 (jne,%l0); 4834 4835 OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\"); 4836}") 4837 4838(define_insn "" 4839 [(set (pc) 4840 (if_then_else (ltu (cc0) 4841 (const_int 0)) 4842 (pc) 4843 (label_ref (match_operand 0 "" ""))))] 4844 "" 4845 "jae %l0") 4846 4847(define_insn "" 4848 [(set (pc) 4849 (if_then_else (ge (cc0) 4850 (const_int 0)) 4851 (pc) 4852 (label_ref (match_operand 0 "" ""))))] 4853 "" 4854 "* 4855{ 4856 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 4857 return AS1 (jne,%l0); 4858 4859 OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\"); 4860}") 4861 4862(define_insn "" 4863 [(set (pc) 4864 (if_then_else (geu (cc0) 4865 (const_int 0)) 4866 (pc) 4867 (label_ref (match_operand 0 "" ""))))] 4868 "" 4869 "jb %l0") 4870 4871(define_insn "" 4872 [(set (pc) 4873 (if_then_else (le (cc0) 4874 (const_int 0)) 4875 (pc) 4876 (label_ref (match_operand 0 "" ""))))] 4877 "" 4878 "* 4879{ 4880 if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) 4881 return AS1 (jae,%l0); 4882 4883 OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR); 4884}") 4885 4886(define_insn "" 4887 [(set (pc) 4888 (if_then_else (leu (cc0) 4889 (const_int 0)) 4890 (pc) 4891 (label_ref (match_operand 0 "" ""))))] 4892 "" 4893 "ja %l0") 4894 4895;; Unconditional and other jump instructions 4896 4897(define_insn "jump" 4898 [(set (pc) 4899 (label_ref (match_operand 0 "" "")))] 4900 "" 4901 "jmp %l0") 4902 4903(define_insn "indirect_jump" 4904 [(set (pc) (match_operand:SI 0 "general_operand" "rm"))] 4905 "" 4906 "* 4907{ 4908 CC_STATUS_INIT; 4909 4910 return AS1 (jmp,%*%0); 4911}") 4912 4913;; ??? could transform while(--i > 0) S; to if (--i > 0) do S; while(--i); 4914;; if S does not change i 4915 4916(define_expand "decrement_and_branch_until_zero" 4917 [(parallel [(set (pc) 4918 (if_then_else (ge (plus:SI (match_operand:SI 0 "general_operand" "") 4919 (const_int -1)) 4920 (const_int 0)) 4921 (label_ref (match_operand 1 "" "")) 4922 (pc))) 4923 (set (match_dup 0) 4924 (plus:SI (match_dup 0) 4925 (const_int -1)))])] 4926 "" 4927 "") 4928 4929(define_insn "" 4930 [(set (pc) 4931 (if_then_else (match_operator 0 "arithmetic_comparison_operator" 4932 [(plus:SI (match_operand:SI 1 "general_operand" "+r,m") 4933 (match_operand:SI 2 "general_operand" "rmi,ri")) 4934 (const_int 0)]) 4935 (label_ref (match_operand 3 "" "")) 4936 (pc))) 4937 (set (match_dup 1) 4938 (plus:SI (match_dup 1) 4939 (match_dup 2)))] 4940 "" 4941 "* 4942{ 4943 CC_STATUS_INIT; 4944 if (operands[2] == constm1_rtx) 4945 output_asm_insn (AS1 (dec%L1,%1), operands); 4946 4947 else if (operands[1] == const1_rtx) 4948 output_asm_insn (AS1 (inc%L1,%1), operands); 4949 4950 else 4951 output_asm_insn (AS2 (add%L1,%2,%1), operands); 4952 4953 return AS1 (%J0,%l3); 4954}") 4955 4956(define_insn "" 4957 [(set (pc) 4958 (if_then_else (match_operator 0 "arithmetic_comparison_operator" 4959 [(minus:SI (match_operand:SI 1 "general_operand" "+r,m") 4960 (match_operand:SI 2 "general_operand" "rmi,ri")) 4961 (const_int 0)]) 4962 (label_ref (match_operand 3 "" "")) 4963 (pc))) 4964 (set (match_dup 1) 4965 (minus:SI (match_dup 1) 4966 (match_dup 2)))] 4967 "" 4968 "* 4969{ 4970 CC_STATUS_INIT; 4971 if (operands[2] == const1_rtx) 4972 output_asm_insn (AS1 (dec%L1,%1), operands); 4973 4974 else if (operands[1] == constm1_rtx) 4975 output_asm_insn (AS1 (inc%L1,%1), operands); 4976 4977 else 4978 output_asm_insn (AS2 (sub%L1,%2,%1), operands); 4979 4980 return AS1 (%J0,%l3); 4981}") 4982 4983;; Implement switch statements when generating PIC code. Switches are 4984;; implemented by `tablejump' when not using -fpic. 4985 4986;; Emit code here to do the range checking and make the index zero based. 4987 4988(define_expand "casesi" 4989 [(set (match_dup 5) 4990 (minus:SI (match_operand:SI 0 "general_operand" "") 4991 (match_operand:SI 1 "general_operand" ""))) 4992 (set (cc0) 4993 (compare:CC (match_dup 5) 4994 (match_operand:SI 2 "general_operand" ""))) 4995 (set (pc) 4996 (if_then_else (gtu (cc0) 4997 (const_int 0)) 4998 (label_ref (match_operand 4 "" "")) 4999 (pc))) 5000 (parallel 5001 [(set (pc) 5002 (minus:SI (reg:SI 3) 5003 (mem:SI (plus:SI (mult:SI (match_dup 5) 5004 (const_int 4)) 5005 (label_ref (match_operand 3 "" "")))))) 5006 (clobber (match_scratch:SI 6 ""))])] 5007 "flag_pic" 5008 " 5009{ 5010 operands[5] = gen_reg_rtx (SImode); 5011 current_function_uses_pic_offset_table = 1; 5012}") 5013 5014;; Implement a casesi insn. 5015 5016;; Each entry in the "addr_diff_vec" looks like this as the result of the 5017;; two rules below: 5018;; 5019;; .long _GLOBAL_OFFSET_TABLE_+[.-.L2] 5020;; 5021;; 1. An expression involving an external reference may only use the 5022;; addition operator, and only with an assembly-time constant. 5023;; The example above satisfies this because ".-.L2" is a constant. 5024;; 5025;; 2. The symbol _GLOBAL_OFFSET_TABLE_ is magic, and at link time is 5026;; given the value of "GOT - .", where GOT is the actual address of 5027;; the Global Offset Table. Therefore, the .long above actually 5028;; stores the value "( GOT - . ) + [ . - .L2 ]", or "GOT - .L2". The 5029;; expression "GOT - .L2" by itself would generate an error from as(1). 5030;; 5031;; The pattern below emits code that looks like this: 5032;; 5033;; movl %ebx,reg 5034;; subl TABLE@GOTOFF(%ebx,index,4),reg 5035;; jmp reg 5036;; 5037;; The addr_diff_vec contents may be directly referenced with @GOTOFF, since 5038;; the addr_diff_vec is known to be part of this module. 5039;; 5040;; The subl above calculates "GOT - (( GOT - . ) + [ . - .L2 ])", which 5041;; evaluates to just ".L2". 5042 5043(define_insn "" 5044 [(set (pc) 5045 (minus:SI (reg:SI 3) 5046 (mem:SI (plus:SI 5047 (mult:SI (match_operand:SI 0 "register_operand" "r") 5048 (const_int 4)) 5049 (label_ref (match_operand 1 "" "")))))) 5050 (clobber (match_scratch:SI 2 "=&r"))] 5051 "" 5052 "* 5053{ 5054 rtx xops[4]; 5055 5056 xops[0] = operands[0]; 5057 xops[1] = operands[1]; 5058 xops[2] = operands[2]; 5059 xops[3] = pic_offset_table_rtx; 5060 5061 output_asm_insn (AS2 (mov%L2,%3,%2), xops); 5062 output_asm_insn (\"sub%L2 %l1@GOTOFF(%3,%0,4),%2\", xops); 5063 output_asm_insn (AS1 (jmp,%*%2), xops); 5064 ASM_OUTPUT_ALIGN_CODE (asm_out_file); 5065 RET; 5066}") 5067 5068(define_insn "tablejump" 5069 [(set (pc) (match_operand:SI 0 "general_operand" "rm")) 5070 (use (label_ref (match_operand 1 "" "")))] 5071 "" 5072 "* 5073{ 5074 CC_STATUS_INIT; 5075 5076 return AS1 (jmp,%*%0); 5077}") 5078 5079;; Call insns. 5080 5081;; If generating PIC code, the predicate indirect_operand will fail 5082;; for operands[0] containing symbolic references on all of the named 5083;; call* patterns. Each named pattern is followed by an unnamed pattern 5084;; that matches any call to a symbolic CONST (ie, a symbol_ref). The 5085;; unnamed patterns are only used while generating PIC code, because 5086;; otherwise the named patterns match. 5087 5088;; Call subroutine returning no value. 5089 5090(define_expand "call_pop" 5091 [(parallel [(call (match_operand:QI 0 "indirect_operand" "") 5092 (match_operand:SI 1 "general_operand" "")) 5093 (set (reg:SI 7) 5094 (plus:SI (reg:SI 7) 5095 (match_operand:SI 3 "immediate_operand" "")))])] 5096 "" 5097 " 5098{ 5099 rtx addr; 5100 5101 if (flag_pic) 5102 current_function_uses_pic_offset_table = 1; 5103 5104 /* With half-pic, force the address into a register. */ 5105 addr = XEXP (operands[0], 0); 5106 if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) 5107 XEXP (operands[0], 0) = force_reg (Pmode, addr); 5108 5109 if (! expander_call_insn_operand (operands[0], QImode)) 5110 operands[0] 5111 = change_address (operands[0], VOIDmode, 5112 copy_to_mode_reg (Pmode, XEXP (operands[0], 0))); 5113}") 5114 5115(define_insn "" 5116 [(call (match_operand:QI 0 "call_insn_operand" "m") 5117 (match_operand:SI 1 "general_operand" "g")) 5118 (set (reg:SI 7) (plus:SI (reg:SI 7) 5119 (match_operand:SI 3 "immediate_operand" "i")))] 5120 "" 5121 "* 5122{ 5123 if (GET_CODE (operands[0]) == MEM 5124 && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) 5125 { 5126 operands[0] = XEXP (operands[0], 0); 5127 return AS1 (call,%*%0); 5128 } 5129 else 5130 return AS1 (call,%P0); 5131}") 5132 5133(define_insn "" 5134 [(call (mem:QI (match_operand:SI 0 "symbolic_operand" "")) 5135 (match_operand:SI 1 "general_operand" "g")) 5136 (set (reg:SI 7) (plus:SI (reg:SI 7) 5137 (match_operand:SI 3 "immediate_operand" "i")))] 5138 "!HALF_PIC_P ()" 5139 "call %P0") 5140 5141(define_expand "call" 5142 [(call (match_operand:QI 0 "indirect_operand" "") 5143 (match_operand:SI 1 "general_operand" ""))] 5144 ;; Operand 1 not used on the i386. 5145 "" 5146 " 5147{ 5148 rtx addr; 5149 5150 if (flag_pic) 5151 current_function_uses_pic_offset_table = 1; 5152 5153 /* With half-pic, force the address into a register. */ 5154 addr = XEXP (operands[0], 0); 5155 if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) 5156 XEXP (operands[0], 0) = force_reg (Pmode, addr); 5157 5158 if (! expander_call_insn_operand (operands[0], QImode)) 5159 operands[0] 5160 = change_address (operands[0], VOIDmode, 5161 copy_to_mode_reg (Pmode, XEXP (operands[0], 0))); 5162}") 5163 5164(define_insn "" 5165 [(call (match_operand:QI 0 "call_insn_operand" "m") 5166 (match_operand:SI 1 "general_operand" "g"))] 5167 ;; Operand 1 not used on the i386. 5168 "" 5169 "* 5170{ 5171 if (GET_CODE (operands[0]) == MEM 5172 && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) 5173 { 5174 operands[0] = XEXP (operands[0], 0); 5175 return AS1 (call,%*%0); 5176 } 5177 else 5178 return AS1 (call,%P0); 5179}") 5180 5181(define_insn "" 5182 [(call (mem:QI (match_operand:SI 0 "symbolic_operand" "")) 5183 (match_operand:SI 1 "general_operand" "g"))] 5184 ;; Operand 1 not used on the i386. 5185 "!HALF_PIC_P ()" 5186 "call %P0") 5187 5188;; Call subroutine, returning value in operand 0 5189;; (which must be a hard register). 5190 5191(define_expand "call_value_pop" 5192 [(parallel [(set (match_operand 0 "" "") 5193 (call (match_operand:QI 1 "indirect_operand" "") 5194 (match_operand:SI 2 "general_operand" ""))) 5195 (set (reg:SI 7) 5196 (plus:SI (reg:SI 7) 5197 (match_operand:SI 4 "immediate_operand" "")))])] 5198 "" 5199 " 5200{ 5201 rtx addr; 5202 5203 if (flag_pic) 5204 current_function_uses_pic_offset_table = 1; 5205 5206 /* With half-pic, force the address into a register. */ 5207 addr = XEXP (operands[1], 0); 5208 if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) 5209 XEXP (operands[1], 0) = force_reg (Pmode, addr); 5210 5211 if (! expander_call_insn_operand (operands[1], QImode)) 5212 operands[1] 5213 = change_address (operands[1], VOIDmode, 5214 copy_to_mode_reg (Pmode, XEXP (operands[1], 0))); 5215}") 5216 5217(define_insn "" 5218 [(set (match_operand 0 "" "=rf") 5219 (call (match_operand:QI 1 "call_insn_operand" "m") 5220 (match_operand:SI 2 "general_operand" "g"))) 5221 (set (reg:SI 7) (plus:SI (reg:SI 7) 5222 (match_operand:SI 4 "immediate_operand" "i")))] 5223 "" 5224 "* 5225{ 5226 if (GET_CODE (operands[1]) == MEM 5227 && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) 5228 { 5229 operands[1] = XEXP (operands[1], 0); 5230 output_asm_insn (AS1 (call,%*%1), operands); 5231 } 5232 else 5233 output_asm_insn (AS1 (call,%P1), operands); 5234 5235 RET; 5236}") 5237 5238(define_insn "" 5239 [(set (match_operand 0 "" "=rf") 5240 (call (mem:QI (match_operand:SI 1 "symbolic_operand" "")) 5241 (match_operand:SI 2 "general_operand" "g"))) 5242 (set (reg:SI 7) (plus:SI (reg:SI 7) 5243 (match_operand:SI 4 "immediate_operand" "i")))] 5244 "!HALF_PIC_P ()" 5245 "call %P1") 5246 5247(define_expand "call_value" 5248 [(set (match_operand 0 "" "") 5249 (call (match_operand:QI 1 "indirect_operand" "") 5250 (match_operand:SI 2 "general_operand" "")))] 5251 ;; Operand 2 not used on the i386. 5252 "" 5253 " 5254{ 5255 rtx addr; 5256 5257 if (flag_pic) 5258 current_function_uses_pic_offset_table = 1; 5259 5260 /* With half-pic, force the address into a register. */ 5261 addr = XEXP (operands[1], 0); 5262 if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) 5263 XEXP (operands[1], 0) = force_reg (Pmode, addr); 5264 5265 if (! expander_call_insn_operand (operands[1], QImode)) 5266 operands[1] 5267 = change_address (operands[1], VOIDmode, 5268 copy_to_mode_reg (Pmode, XEXP (operands[1], 0))); 5269}") 5270 5271(define_insn "" 5272 [(set (match_operand 0 "" "=rf") 5273 (call (match_operand:QI 1 "call_insn_operand" "m") 5274 (match_operand:SI 2 "general_operand" "g")))] 5275 ;; Operand 2 not used on the i386. 5276 "" 5277 "* 5278{ 5279 if (GET_CODE (operands[1]) == MEM 5280 && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) 5281 { 5282 operands[1] = XEXP (operands[1], 0); 5283 output_asm_insn (AS1 (call,%*%1), operands); 5284 } 5285 else 5286 output_asm_insn (AS1 (call,%P1), operands); 5287 5288 RET; 5289}") 5290 5291(define_insn "" 5292 [(set (match_operand 0 "" "=rf") 5293 (call (mem:QI (match_operand:SI 1 "symbolic_operand" "")) 5294 (match_operand:SI 2 "general_operand" "g")))] 5295 ;; Operand 2 not used on the i386. 5296 "!HALF_PIC_P ()" 5297 "call %P1") 5298 5299;; Call subroutine returning any type. 5300 5301(define_expand "untyped_call" 5302 [(parallel [(call (match_operand 0 "" "") 5303 (const_int 0)) 5304 (match_operand 1 "" "") 5305 (match_operand 2 "" "")])] 5306 "" 5307 " 5308{ 5309 int i; 5310 5311 /* In order to give reg-stack an easier job in validating two 5312 coprocessor registers as containing a possible return value, 5313 simply pretend the untyped call returns a complex long double 5314 value. */ 5315 emit_call_insn (TARGET_80387 5316 ? gen_call_value (gen_rtx (REG, XCmode, FIRST_FLOAT_REG), 5317 operands[0], const0_rtx) 5318 : gen_call (operands[0], const0_rtx)); 5319 5320 for (i = 0; i < XVECLEN (operands[2], 0); i++) 5321 { 5322 rtx set = XVECEXP (operands[2], 0, i); 5323 emit_move_insn (SET_DEST (set), SET_SRC (set)); 5324 } 5325 5326 /* The optimizer does not know that the call sets the function value 5327 registers we stored in the result block. We avoid problems by 5328 claiming that all hard registers are used and clobbered at this 5329 point. */ 5330 emit_insn (gen_blockage ()); 5331 5332 DONE; 5333}") 5334 5335;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and 5336;; all of memory. This blocks insns from being moved across this point. 5337 5338(define_insn "blockage" 5339 [(unspec_volatile [(const_int 0)] 0)] 5340 "" 5341 "") 5342 5343;; Insn emitted into the body of a function to return from a function. 5344;; This is only done if the function's epilogue is known to be simple. 5345;; See comments for simple_386_epilogue in i386.c. 5346 5347(define_insn "return" 5348 [(return)] 5349 "simple_386_epilogue ()" 5350 "* 5351{ 5352 function_epilogue (asm_out_file, get_frame_size ()); 5353 RET; 5354}") 5355 5356(define_insn "nop" 5357 [(const_int 0)] 5358 "" 5359 "nop") 5360 5361(define_expand "movstrsi" 5362 [(parallel [(set (match_operand:BLK 0 "memory_operand" "") 5363 (match_operand:BLK 1 "memory_operand" "")) 5364 (use (match_operand:SI 2 "const_int_operand" "")) 5365 (use (match_operand:SI 3 "const_int_operand" "")) 5366 (clobber (match_scratch:SI 4 "")) 5367 (clobber (match_dup 5)) 5368 (clobber (match_dup 6))])] 5369 "" 5370 " 5371{ 5372 rtx addr0, addr1; 5373 5374 if (GET_CODE (operands[2]) != CONST_INT) 5375 FAIL; 5376 5377 addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); 5378 addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); 5379 5380 operands[5] = addr0; 5381 operands[6] = addr1; 5382 5383 operands[0] = gen_rtx (MEM, BLKmode, addr0); 5384 operands[1] = gen_rtx (MEM, BLKmode, addr1); 5385}") 5386 5387;; It might seem that operands 0 & 1 could use predicate register_operand. 5388;; But strength reduction might offset the MEM expression. So we let 5389;; reload put the address into %edi & %esi. 5390 5391(define_insn "" 5392 [(set (mem:BLK (match_operand:SI 0 "address_operand" "D")) 5393 (mem:BLK (match_operand:SI 1 "address_operand" "S"))) 5394 (use (match_operand:SI 2 "const_int_operand" "n")) 5395 (use (match_operand:SI 3 "immediate_operand" "i")) 5396 (clobber (match_scratch:SI 4 "=&c")) 5397 (clobber (match_dup 0)) 5398 (clobber (match_dup 1))] 5399 "" 5400 "* 5401{ 5402 rtx xops[2]; 5403 5404 output_asm_insn (\"cld\", operands); 5405 if (GET_CODE (operands[2]) == CONST_INT) 5406 { 5407 if (INTVAL (operands[2]) & ~0x03) 5408 { 5409 xops[0] = GEN_INT ((INTVAL (operands[2]) >> 2) & 0x3fffffff); 5410 xops[1] = operands[4]; 5411 5412 output_asm_insn (AS2 (mov%L1,%0,%1), xops); 5413#ifdef INTEL_SYNTAX 5414 output_asm_insn (\"rep movsd\", xops); 5415#else 5416 output_asm_insn (\"rep\;movsl\", xops); 5417#endif 5418 } 5419 if (INTVAL (operands[2]) & 0x02) 5420 output_asm_insn (\"movsw\", operands); 5421 if (INTVAL (operands[2]) & 0x01) 5422 output_asm_insn (\"movsb\", operands); 5423 } 5424 else 5425 abort (); 5426 RET; 5427}") 5428 5429(define_expand "cmpstrsi" 5430 [(parallel [(set (match_operand:SI 0 "general_operand" "") 5431 (compare:SI (match_operand:BLK 1 "general_operand" "") 5432 (match_operand:BLK 2 "general_operand" ""))) 5433 (use (match_operand:SI 3 "general_operand" "")) 5434 (use (match_operand:SI 4 "immediate_operand" "")) 5435 (clobber (match_dup 5)) 5436 (clobber (match_dup 6)) 5437 (clobber (match_dup 3))])] 5438 "" 5439 " 5440{ 5441 rtx addr1, addr2; 5442 5443 addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); 5444 addr2 = copy_to_mode_reg (Pmode, XEXP (operands[2], 0)); 5445 operands[3] = copy_to_mode_reg (SImode, operands[3]); 5446 5447 operands[5] = addr1; 5448 operands[6] = addr2; 5449 5450 operands[1] = gen_rtx (MEM, BLKmode, addr1); 5451 operands[2] = gen_rtx (MEM, BLKmode, addr2); 5452 5453}") 5454 5455;; memcmp recognizers. The `cmpsb' opcode does nothing if the count is 5456;; zero. Emit extra code to make sure that a zero-length compare is EQ. 5457 5458;; It might seem that operands 0 & 1 could use predicate register_operand. 5459;; But strength reduction might offset the MEM expression. So we let 5460;; reload put the address into %edi & %esi. 5461 5462;; ??? Most comparisons have a constant length, and it's therefore 5463;; possible to know that the length is non-zero, and to avoid the extra 5464;; code to handle zero-length compares. 5465 5466(define_insn "" 5467 [(set (match_operand:SI 0 "general_operand" "=&r") 5468 (compare:SI (mem:BLK (match_operand:SI 1 "address_operand" "S")) 5469 (mem:BLK (match_operand:SI 2 "address_operand" "D")))) 5470 (use (match_operand:SI 3 "register_operand" "c")) 5471 (use (match_operand:SI 4 "immediate_operand" "i")) 5472 (clobber (match_dup 1)) 5473 (clobber (match_dup 2)) 5474 (clobber (match_dup 3))] 5475 "" 5476 "* 5477{ 5478 rtx xops[4], label; 5479 5480 label = gen_label_rtx (); 5481 5482 output_asm_insn (\"cld\", operands); 5483 output_asm_insn (AS2 (xor%L0,%0,%0), operands); 5484 output_asm_insn (\"repz\;cmps%B2\", operands); 5485 output_asm_insn (\"je %l0\", &label); 5486 5487 xops[0] = operands[0]; 5488 xops[1] = gen_rtx (MEM, QImode, 5489 gen_rtx (PLUS, SImode, operands[1], constm1_rtx)); 5490 xops[2] = gen_rtx (MEM, QImode, 5491 gen_rtx (PLUS, SImode, operands[2], constm1_rtx)); 5492 xops[3] = operands[3]; 5493 5494 output_asm_insn (AS2 (movz%B1%L0,%1,%0), xops); 5495 output_asm_insn (AS2 (movz%B2%L3,%2,%3), xops); 5496 5497 output_asm_insn (AS2 (sub%L0,%3,%0), xops); 5498 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label)); 5499 RET; 5500}") 5501 5502(define_insn "" 5503 [(set (cc0) 5504 (compare:SI (mem:BLK (match_operand:SI 0 "address_operand" "S")) 5505 (mem:BLK (match_operand:SI 1 "address_operand" "D")))) 5506 (use (match_operand:SI 2 "register_operand" "c")) 5507 (use (match_operand:SI 3 "immediate_operand" "i")) 5508 (clobber (match_dup 0)) 5509 (clobber (match_dup 1)) 5510 (clobber (match_dup 2))] 5511 "" 5512 "* 5513{ 5514 rtx xops[2]; 5515 5516 cc_status.flags |= CC_NOT_SIGNED; 5517 5518 xops[0] = gen_rtx (REG, QImode, 0); 5519 xops[1] = CONST0_RTX (QImode); 5520 5521 output_asm_insn (\"cld\", operands); 5522 output_asm_insn (AS2 (test%B0,%1,%0), xops); 5523 return \"repz\;cmps%B2\"; 5524}") 5525 5526(define_expand "ffssi2" 5527 [(set (match_dup 2) 5528 (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" "")) 5529 (const_int -1))) 5530 (set (match_operand:SI 0 "general_operand" "") 5531 (plus:SI (match_dup 2) (const_int 1)))] 5532 "" 5533 "operands[2] = gen_reg_rtx (SImode);") 5534 5535;; Note, you cannot optimize away the branch following the bsfl by assuming 5536;; that the destination is not modified if the input is 0, since not all 5537;; x86 implementations do this. 5538 5539(define_insn "" 5540 [(set (match_operand:SI 0 "general_operand" "=&r") 5541 (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" "rm")) 5542 (const_int -1)))] 5543 "" 5544 "* 5545{ 5546 rtx xops[3]; 5547 static int ffssi_label_number; 5548 char buffer[30]; 5549 5550 xops[0] = operands[0]; 5551 xops[1] = operands[1]; 5552 xops[2] = constm1_rtx; 5553 output_asm_insn (AS2 (bsf%L0,%1,%0), xops); 5554#ifdef LOCAL_LABEL_PREFIX 5555 sprintf (buffer, \"jnz %sLFFSSI%d\", 5556 LOCAL_LABEL_PREFIX, ffssi_label_number); 5557#else 5558 sprintf (buffer, \"jnz %sLFFSSI%d\", 5559 \"\", ffssi_label_number); 5560#endif 5561 output_asm_insn (buffer, xops); 5562 output_asm_insn (AS2 (mov%L0,%2,%0), xops); 5563#ifdef LOCAL_LABEL_PREFIX 5564 sprintf (buffer, \"%sLFFSSI%d:\", 5565 LOCAL_LABEL_PREFIX, ffssi_label_number); 5566#else 5567 sprintf (buffer, \"%sLFFSSI%d:\", 5568 \"\", ffssi_label_number); 5569#endif 5570 output_asm_insn (buffer, xops); 5571 5572 ffssi_label_number++; 5573 return \"\"; 5574}") 5575 5576(define_expand "ffshi2" 5577 [(set (match_dup 2) 5578 (plus:HI (ffs:HI (match_operand:HI 1 "general_operand" "")) 5579 (const_int -1))) 5580 (set (match_operand:HI 0 "general_operand" "") 5581 (plus:HI (match_dup 2) (const_int 1)))] 5582 "" 5583 "operands[2] = gen_reg_rtx (HImode);") 5584 5585(define_insn "" 5586 [(set (match_operand:HI 0 "general_operand" "=&r") 5587 (plus:HI (ffs:HI (match_operand:SI 1 "general_operand" "rm")) 5588 (const_int -1)))] 5589 "" 5590 "* 5591{ 5592 rtx xops[3]; 5593 static int ffshi_label_number; 5594 char buffer[30]; 5595 5596 xops[0] = operands[0]; 5597 xops[1] = operands[1]; 5598 xops[2] = constm1_rtx; 5599 output_asm_insn (AS2 (bsf%W0,%1,%0), xops); 5600#ifdef LOCAL_LABEL_PREFIX 5601 sprintf (buffer, \"jnz %sLFFSHI%d\", 5602 LOCAL_LABEL_PREFIX, ffshi_label_number); 5603#else 5604 sprintf (buffer, \"jnz %sLFFSHI%d\", 5605 \"\", ffshi_label_number); 5606#endif 5607 output_asm_insn (buffer, xops); 5608 output_asm_insn (AS2 (mov%W0,%2,%0), xops); 5609#ifdef LOCAL_LABEL_PREFIX 5610 sprintf (buffer, \"%sLFFSHI%d:\", 5611 LOCAL_LABEL_PREFIX, ffshi_label_number); 5612#else 5613 sprintf (buffer, \"%sLFFSHI%d:\", 5614 \"\", ffshi_label_number); 5615#endif 5616 output_asm_insn (buffer, xops); 5617 5618 ffshi_label_number++; 5619 return \"\"; 5620}") 5621 5622;; These patterns match the binary 387 instructions for addM3, subM3, 5623;; mulM3 and divM3. There are three patterns for each of DFmode and 5624;; SFmode. The first is the normal insn, the second the same insn but 5625;; with one operand a conversion, and the third the same insn but with 5626;; the other operand a conversion. The conversion may be SFmode or 5627;; SImode if the target mode DFmode, but only SImode if the target mode 5628;; is SFmode. 5629 5630(define_insn "" 5631 [(set (match_operand:DF 0 "register_operand" "=f,f") 5632 (match_operator:DF 3 "binary_387_op" 5633 [(match_operand:DF 1 "nonimmediate_operand" "0,fm") 5634 (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))] 5635 "TARGET_80387" 5636 "* return output_387_binary_op (insn, operands);") 5637 5638(define_insn "" 5639 [(set (match_operand:DF 0 "register_operand" "=f") 5640 (match_operator:DF 3 "binary_387_op" 5641 [(float:DF (match_operand:SI 1 "general_operand" "rm")) 5642 (match_operand:DF 2 "general_operand" "0")]))] 5643 "TARGET_80387" 5644 "* return output_387_binary_op (insn, operands);") 5645 5646(define_insn "" 5647 [(set (match_operand:XF 0 "register_operand" "=f,f") 5648 (match_operator:XF 3 "binary_387_op" 5649 [(match_operand:XF 1 "nonimmediate_operand" "0,f") 5650 (match_operand:XF 2 "nonimmediate_operand" "f,0")]))] 5651 "TARGET_80387" 5652 "* return output_387_binary_op (insn, operands);") 5653 5654(define_insn "" 5655 [(set (match_operand:XF 0 "register_operand" "=f") 5656 (match_operator:XF 3 "binary_387_op" 5657 [(float:XF (match_operand:SI 1 "general_operand" "rm")) 5658 (match_operand:XF 2 "general_operand" "0")]))] 5659 "TARGET_80387" 5660 "* return output_387_binary_op (insn, operands);") 5661 5662(define_insn "" 5663 [(set (match_operand:XF 0 "register_operand" "=f,f") 5664 (match_operator:XF 3 "binary_387_op" 5665 [(float_extend:XF (match_operand:SF 1 "general_operand" "fm,0")) 5666 (match_operand:XF 2 "general_operand" "0,f")]))] 5667 "TARGET_80387" 5668 "* return output_387_binary_op (insn, operands);") 5669 5670(define_insn "" 5671 [(set (match_operand:XF 0 "register_operand" "=f") 5672 (match_operator:XF 3 "binary_387_op" 5673 [(match_operand:XF 1 "general_operand" "0") 5674 (float:XF (match_operand:SI 2 "general_operand" "rm"))]))] 5675 "TARGET_80387" 5676 "* return output_387_binary_op (insn, operands);") 5677 5678(define_insn "" 5679 [(set (match_operand:XF 0 "register_operand" "=f,f") 5680 (match_operator:XF 3 "binary_387_op" 5681 [(match_operand:XF 1 "general_operand" "0,f") 5682 (float_extend:XF 5683 (match_operand:SF 2 "general_operand" "fm,0"))]))] 5684 "TARGET_80387" 5685 "* return output_387_binary_op (insn, operands);") 5686 5687(define_insn "" 5688 [(set (match_operand:DF 0 "register_operand" "=f,f") 5689 (match_operator:DF 3 "binary_387_op" 5690 [(float_extend:DF (match_operand:SF 1 "general_operand" "fm,0")) 5691 (match_operand:DF 2 "general_operand" "0,f")]))] 5692 "TARGET_80387" 5693 "* return output_387_binary_op (insn, operands);") 5694 5695(define_insn "" 5696 [(set (match_operand:DF 0 "register_operand" "=f") 5697 (match_operator:DF 3 "binary_387_op" 5698 [(match_operand:DF 1 "general_operand" "0") 5699 (float:DF (match_operand:SI 2 "general_operand" "rm"))]))] 5700 "TARGET_80387" 5701 "* return output_387_binary_op (insn, operands);") 5702 5703(define_insn "" 5704 [(set (match_operand:DF 0 "register_operand" "=f,f") 5705 (match_operator:DF 3 "binary_387_op" 5706 [(match_operand:DF 1 "general_operand" "0,f") 5707 (float_extend:DF 5708 (match_operand:SF 2 "general_operand" "fm,0"))]))] 5709 "TARGET_80387" 5710 "* return output_387_binary_op (insn, operands);") 5711 5712(define_insn "" 5713 [(set (match_operand:SF 0 "register_operand" "=f,f") 5714 (match_operator:SF 3 "binary_387_op" 5715 [(match_operand:SF 1 "nonimmediate_operand" "0,fm") 5716 (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))] 5717 "TARGET_80387" 5718 "* return output_387_binary_op (insn, operands);") 5719 5720(define_insn "" 5721 [(set (match_operand:SF 0 "register_operand" "=f") 5722 (match_operator:SF 3 "binary_387_op" 5723 [(float:SF (match_operand:SI 1 "general_operand" "rm")) 5724 (match_operand:SF 2 "general_operand" "0")]))] 5725 "TARGET_80387" 5726 "* return output_387_binary_op (insn, operands);") 5727 5728(define_insn "" 5729 [(set (match_operand:SF 0 "register_operand" "=f") 5730 (match_operator:SF 3 "binary_387_op" 5731 [(match_operand:SF 1 "general_operand" "0") 5732 (float:SF (match_operand:SI 2 "general_operand" "rm"))]))] 5733 "TARGET_80387" 5734 "* return output_387_binary_op (insn, operands);") 5735 5736(define_expand "strlensi" 5737 [(parallel [(set (match_dup 4) 5738 (unspec:SI [(mem:BLK (match_operand:BLK 1 "general_operand" "")) 5739 (match_operand:QI 2 "register_operand" "") 5740 (match_operand:SI 3 "immediate_operand" "")] 0)) 5741 (clobber (match_dup 1))]) 5742 (set (match_dup 5) 5743 (not:SI (match_dup 4))) 5744 (set (match_operand:SI 0 "register_operand" "") 5745 (minus:SI (match_dup 5) 5746 (const_int 1)))] 5747 "" 5748 " 5749{ 5750 operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); 5751 operands[4] = gen_reg_rtx (SImode); 5752 operands[5] = gen_reg_rtx (SImode); 5753}") 5754 5755;; It might seem that operands 0 & 1 could use predicate register_operand. 5756;; But strength reduction might offset the MEM expression. So we let 5757;; reload put the address into %edi. 5758 5759(define_insn "" 5760 [(set (match_operand:SI 0 "register_operand" "=&c") 5761 (unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "D")) 5762 (match_operand:QI 2 "register_operand" "a") 5763 (match_operand:SI 3 "immediate_operand" "i")] 0)) 5764 (clobber (match_dup 1))] 5765 "" 5766 "* 5767{ 5768 rtx xops[2]; 5769 5770 xops[0] = operands[0]; 5771 xops[1] = constm1_rtx; 5772 output_asm_insn (\"cld\", operands); 5773 output_asm_insn (AS2 (mov%L0,%1,%0), xops); 5774 return \"repnz\;scas%B2\"; 5775}") 5776