optabs.c revision 70635
1/* Expand the basic unary and binary arithmetic operations, for GNU compiler. 2 Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc. 3 4This file is part of GNU CC. 5 6GNU CC is free software; you can redistribute it and/or modify 7it under the terms of the GNU General Public License as published by 8the Free Software Foundation; either version 2, or (at your option) 9any later version. 10 11GNU CC is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14GNU General Public License for more details. 15 16You should have received a copy of the GNU General Public License 17along with GNU CC; see the file COPYING. If not, write to 18the Free Software Foundation, 59 Temple Place - Suite 330, 19Boston, MA 02111-1307, USA. */ 20 21 22#include "config.h" 23#include "system.h" 24#include "toplev.h" 25 26/* Include insn-config.h before expr.h so that HAVE_conditional_move 27 is properly defined. */ 28#include "insn-config.h" 29#include "rtl.h" 30#include "tree.h" 31#include "flags.h" 32#include "insn-flags.h" 33#include "insn-codes.h" 34#include "expr.h" 35#include "recog.h" 36#include "reload.h" 37 38/* Each optab contains info on how this target machine 39 can perform a particular operation 40 for all sizes and kinds of operands. 41 42 The operation to be performed is often specified 43 by passing one of these optabs as an argument. 44 45 See expr.h for documentation of these optabs. */ 46 47optab add_optab; 48optab sub_optab; 49optab smul_optab; 50optab smul_highpart_optab; 51optab umul_highpart_optab; 52optab smul_widen_optab; 53optab umul_widen_optab; 54optab sdiv_optab; 55optab sdivmod_optab; 56optab udiv_optab; 57optab udivmod_optab; 58optab smod_optab; 59optab umod_optab; 60optab flodiv_optab; 61optab ftrunc_optab; 62optab and_optab; 63optab ior_optab; 64optab xor_optab; 65optab ashl_optab; 66optab lshr_optab; 67optab ashr_optab; 68optab rotl_optab; 69optab rotr_optab; 70optab smin_optab; 71optab smax_optab; 72optab umin_optab; 73optab umax_optab; 74 75optab mov_optab; 76optab movstrict_optab; 77 78optab neg_optab; 79optab abs_optab; 80optab one_cmpl_optab; 81optab ffs_optab; 82optab sqrt_optab; 83optab sin_optab; 84optab cos_optab; 85 86optab cmp_optab; 87optab ucmp_optab; /* Used only for libcalls for unsigned comparisons. */ 88optab tst_optab; 89 90optab strlen_optab; 91 92/* Tables of patterns for extending one integer mode to another. */ 93enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2]; 94 95/* Tables of patterns for converting between fixed and floating point. */ 96enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2]; 97enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2]; 98enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2]; 99 100/* Contains the optab used for each rtx code. */ 101optab code_to_optab[NUM_RTX_CODE + 1]; 102 103/* SYMBOL_REF rtx's for the library functions that are called 104 implicitly and not via optabs. */ 105 106rtx extendsfdf2_libfunc; 107rtx extendsfxf2_libfunc; 108rtx extendsftf2_libfunc; 109rtx extenddfxf2_libfunc; 110rtx extenddftf2_libfunc; 111 112rtx truncdfsf2_libfunc; 113rtx truncxfsf2_libfunc; 114rtx trunctfsf2_libfunc; 115rtx truncxfdf2_libfunc; 116rtx trunctfdf2_libfunc; 117 118rtx memcpy_libfunc; 119rtx bcopy_libfunc; 120rtx memcmp_libfunc; 121rtx bcmp_libfunc; 122rtx memset_libfunc; 123rtx bzero_libfunc; 124 125rtx throw_libfunc; 126rtx rethrow_libfunc; 127rtx sjthrow_libfunc; 128rtx sjpopnthrow_libfunc; 129rtx terminate_libfunc; 130rtx setjmp_libfunc; 131rtx longjmp_libfunc; 132rtx eh_rtime_match_libfunc; 133 134rtx eqhf2_libfunc; 135rtx nehf2_libfunc; 136rtx gthf2_libfunc; 137rtx gehf2_libfunc; 138rtx lthf2_libfunc; 139rtx lehf2_libfunc; 140 141rtx eqsf2_libfunc; 142rtx nesf2_libfunc; 143rtx gtsf2_libfunc; 144rtx gesf2_libfunc; 145rtx ltsf2_libfunc; 146rtx lesf2_libfunc; 147 148rtx eqdf2_libfunc; 149rtx nedf2_libfunc; 150rtx gtdf2_libfunc; 151rtx gedf2_libfunc; 152rtx ltdf2_libfunc; 153rtx ledf2_libfunc; 154 155rtx eqxf2_libfunc; 156rtx nexf2_libfunc; 157rtx gtxf2_libfunc; 158rtx gexf2_libfunc; 159rtx ltxf2_libfunc; 160rtx lexf2_libfunc; 161 162rtx eqtf2_libfunc; 163rtx netf2_libfunc; 164rtx gttf2_libfunc; 165rtx getf2_libfunc; 166rtx lttf2_libfunc; 167rtx letf2_libfunc; 168 169rtx floatsisf_libfunc; 170rtx floatdisf_libfunc; 171rtx floattisf_libfunc; 172 173rtx floatsidf_libfunc; 174rtx floatdidf_libfunc; 175rtx floattidf_libfunc; 176 177rtx floatsixf_libfunc; 178rtx floatdixf_libfunc; 179rtx floattixf_libfunc; 180 181rtx floatsitf_libfunc; 182rtx floatditf_libfunc; 183rtx floattitf_libfunc; 184 185rtx fixsfsi_libfunc; 186rtx fixsfdi_libfunc; 187rtx fixsfti_libfunc; 188 189rtx fixdfsi_libfunc; 190rtx fixdfdi_libfunc; 191rtx fixdfti_libfunc; 192 193rtx fixxfsi_libfunc; 194rtx fixxfdi_libfunc; 195rtx fixxfti_libfunc; 196 197rtx fixtfsi_libfunc; 198rtx fixtfdi_libfunc; 199rtx fixtfti_libfunc; 200 201rtx fixunssfsi_libfunc; 202rtx fixunssfdi_libfunc; 203rtx fixunssfti_libfunc; 204 205rtx fixunsdfsi_libfunc; 206rtx fixunsdfdi_libfunc; 207rtx fixunsdfti_libfunc; 208 209rtx fixunsxfsi_libfunc; 210rtx fixunsxfdi_libfunc; 211rtx fixunsxfti_libfunc; 212 213rtx fixunstfsi_libfunc; 214rtx fixunstfdi_libfunc; 215rtx fixunstfti_libfunc; 216 217rtx chkr_check_addr_libfunc; 218rtx chkr_set_right_libfunc; 219rtx chkr_copy_bitmap_libfunc; 220rtx chkr_check_exec_libfunc; 221rtx chkr_check_str_libfunc; 222 223rtx profile_function_entry_libfunc; 224rtx profile_function_exit_libfunc; 225 226/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...) 227 gives the gen_function to make a branch to test that condition. */ 228 229rtxfun bcc_gen_fctn[NUM_RTX_CODE]; 230 231/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...) 232 gives the insn code to make a store-condition insn 233 to test that condition. */ 234 235enum insn_code setcc_gen_code[NUM_RTX_CODE]; 236 237#ifdef HAVE_conditional_move 238/* Indexed by the machine mode, gives the insn code to make a conditional 239 move insn. This is not indexed by the rtx-code like bcc_gen_fctn and 240 setcc_gen_code to cut down on the number of named patterns. Consider a day 241 when a lot more rtx codes are conditional (eg: for the ARM). */ 242 243enum insn_code movcc_gen_code[NUM_MACHINE_MODES]; 244#endif 245 246static int add_equal_note PROTO((rtx, rtx, enum rtx_code, rtx, rtx)); 247static rtx widen_operand PROTO((rtx, enum machine_mode, 248 enum machine_mode, int, int)); 249static int expand_cmplxdiv_straight PROTO((rtx, rtx, rtx, rtx, 250 rtx, rtx, enum machine_mode, 251 int, enum optab_methods, 252 enum mode_class, optab)); 253static int expand_cmplxdiv_wide PROTO((rtx, rtx, rtx, rtx, 254 rtx, rtx, enum machine_mode, 255 int, enum optab_methods, 256 enum mode_class, optab)); 257static enum insn_code can_fix_p PROTO((enum machine_mode, enum machine_mode, 258 int, int *)); 259static enum insn_code can_float_p PROTO((enum machine_mode, enum machine_mode, 260 int)); 261static rtx ftruncify PROTO((rtx)); 262static optab init_optab PROTO((enum rtx_code)); 263static void init_libfuncs PROTO((optab, int, int, const char *, int)); 264static void init_integral_libfuncs PROTO((optab, const char *, int)); 265static void init_floating_libfuncs PROTO((optab, const char *, int)); 266#ifdef HAVE_conditional_trap 267static void init_traps PROTO((void)); 268#endif 269 270/* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to 271 the result of operation CODE applied to OP0 (and OP1 if it is a binary 272 operation). 273 274 If the last insn does not set TARGET, don't do anything, but return 1. 275 276 If a previous insn sets TARGET and TARGET is one of OP0 or OP1, 277 don't add the REG_EQUAL note but return 0. Our caller can then try 278 again, ensuring that TARGET is not one of the operands. */ 279 280static int 281add_equal_note (seq, target, code, op0, op1) 282 rtx seq; 283 rtx target; 284 enum rtx_code code; 285 rtx op0, op1; 286{ 287 rtx set; 288 int i; 289 rtx note; 290 291 if ((GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2' 292 && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<') 293 || GET_CODE (seq) != SEQUENCE 294 || (set = single_set (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))) == 0 295 || GET_CODE (target) == ZERO_EXTRACT 296 || (! rtx_equal_p (SET_DEST (set), target) 297 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the 298 SUBREG. */ 299 && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART 300 || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)), 301 target)))) 302 return 1; 303 304 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET 305 besides the last insn. */ 306 if (reg_overlap_mentioned_p (target, op0) 307 || (op1 && reg_overlap_mentioned_p (target, op1))) 308 for (i = XVECLEN (seq, 0) - 2; i >= 0; i--) 309 if (reg_set_p (target, XVECEXP (seq, 0, i))) 310 return 0; 311 312 if (GET_RTX_CLASS (code) == '1') 313 note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0)); 314 else 315 note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1)); 316 317 set_unique_reg_note (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1), REG_EQUAL, note); 318 319 return 1; 320} 321 322/* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP 323 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need 324 not actually do a sign-extend or zero-extend, but can leave the 325 higher-order bits of the result rtx undefined, for example, in the case 326 of logical operations, but not right shifts. */ 327 328static rtx 329widen_operand (op, mode, oldmode, unsignedp, no_extend) 330 rtx op; 331 enum machine_mode mode, oldmode; 332 int unsignedp; 333 int no_extend; 334{ 335 rtx result; 336 337 /* If we must extend do so. If OP is either a constant or a SUBREG 338 for a promoted object, also extend since it will be more efficient to 339 do so. */ 340 if (! no_extend 341 || GET_MODE (op) == VOIDmode 342 || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op))) 343 return convert_modes (mode, oldmode, op, unsignedp); 344 345 /* If MODE is no wider than a single word, we return a paradoxical 346 SUBREG. */ 347 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD) 348 return gen_rtx_SUBREG (mode, force_reg (GET_MODE (op), op), 0); 349 350 /* Otherwise, get an object of MODE, clobber it, and set the low-order 351 part to OP. */ 352 353 result = gen_reg_rtx (mode); 354 emit_insn (gen_rtx_CLOBBER (VOIDmode, result)); 355 emit_move_insn (gen_lowpart (GET_MODE (op), result), op); 356 return result; 357} 358 359/* Generate code to perform a straightforward complex divide. */ 360 361static int 362expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode, 363 unsignedp, methods, class, binoptab) 364 rtx real0, real1, imag0, imag1, realr, imagr; 365 enum machine_mode submode; 366 int unsignedp; 367 enum optab_methods methods; 368 enum mode_class class; 369 optab binoptab; 370{ 371 rtx divisor; 372 rtx real_t, imag_t; 373 rtx temp1, temp2; 374 rtx res; 375 376 /* Don't fetch these from memory more than once. */ 377 real0 = force_reg (submode, real0); 378 real1 = force_reg (submode, real1); 379 380 if (imag0 != 0) 381 imag0 = force_reg (submode, imag0); 382 383 imag1 = force_reg (submode, imag1); 384 385 /* Divisor: c*c + d*d. */ 386 temp1 = expand_binop (submode, smul_optab, real1, real1, 387 NULL_RTX, unsignedp, methods); 388 389 temp2 = expand_binop (submode, smul_optab, imag1, imag1, 390 NULL_RTX, unsignedp, methods); 391 392 if (temp1 == 0 || temp2 == 0) 393 return 0; 394 395 divisor = expand_binop (submode, add_optab, temp1, temp2, 396 NULL_RTX, unsignedp, methods); 397 if (divisor == 0) 398 return 0; 399 400 if (imag0 == 0) 401 { 402 /* Mathematically, ((a)(c-id))/divisor. */ 403 /* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)). */ 404 405 /* Calculate the dividend. */ 406 real_t = expand_binop (submode, smul_optab, real0, real1, 407 NULL_RTX, unsignedp, methods); 408 409 imag_t = expand_binop (submode, smul_optab, real0, imag1, 410 NULL_RTX, unsignedp, methods); 411 412 if (real_t == 0 || imag_t == 0) 413 return 0; 414 415 imag_t = expand_unop (submode, neg_optab, imag_t, 416 NULL_RTX, unsignedp); 417 } 418 else 419 { 420 /* Mathematically, ((a+ib)(c-id))/divider. */ 421 /* Calculate the dividend. */ 422 temp1 = expand_binop (submode, smul_optab, real0, real1, 423 NULL_RTX, unsignedp, methods); 424 425 temp2 = expand_binop (submode, smul_optab, imag0, imag1, 426 NULL_RTX, unsignedp, methods); 427 428 if (temp1 == 0 || temp2 == 0) 429 return 0; 430 431 real_t = expand_binop (submode, add_optab, temp1, temp2, 432 NULL_RTX, unsignedp, methods); 433 434 temp1 = expand_binop (submode, smul_optab, imag0, real1, 435 NULL_RTX, unsignedp, methods); 436 437 temp2 = expand_binop (submode, smul_optab, real0, imag1, 438 NULL_RTX, unsignedp, methods); 439 440 if (temp1 == 0 || temp2 == 0) 441 return 0; 442 443 imag_t = expand_binop (submode, sub_optab, temp1, temp2, 444 NULL_RTX, unsignedp, methods); 445 446 if (real_t == 0 || imag_t == 0) 447 return 0; 448 } 449 450 if (class == MODE_COMPLEX_FLOAT) 451 res = expand_binop (submode, binoptab, real_t, divisor, 452 realr, unsignedp, methods); 453 else 454 res = expand_divmod (0, TRUNC_DIV_EXPR, submode, 455 real_t, divisor, realr, unsignedp); 456 457 if (res == 0) 458 return 0; 459 460 if (res != realr) 461 emit_move_insn (realr, res); 462 463 if (class == MODE_COMPLEX_FLOAT) 464 res = expand_binop (submode, binoptab, imag_t, divisor, 465 imagr, unsignedp, methods); 466 else 467 res = expand_divmod (0, TRUNC_DIV_EXPR, submode, 468 imag_t, divisor, imagr, unsignedp); 469 470 if (res == 0) 471 return 0; 472 473 if (res != imagr) 474 emit_move_insn (imagr, res); 475 476 return 1; 477} 478 479/* Generate code to perform a wide-input-range-acceptable complex divide. */ 480 481static int 482expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode, 483 unsignedp, methods, class, binoptab) 484 rtx real0, real1, imag0, imag1, realr, imagr; 485 enum machine_mode submode; 486 int unsignedp; 487 enum optab_methods methods; 488 enum mode_class class; 489 optab binoptab; 490{ 491 rtx ratio, divisor; 492 rtx real_t, imag_t; 493 rtx temp1, temp2, lab1, lab2; 494 enum machine_mode mode; 495 int align; 496 rtx res; 497 498 /* Don't fetch these from memory more than once. */ 499 real0 = force_reg (submode, real0); 500 real1 = force_reg (submode, real1); 501 502 if (imag0 != 0) 503 imag0 = force_reg (submode, imag0); 504 505 imag1 = force_reg (submode, imag1); 506 507 /* XXX What's an "unsigned" complex number? */ 508 if (unsignedp) 509 { 510 temp1 = real1; 511 temp2 = imag1; 512 } 513 else 514 { 515 temp1 = expand_abs (submode, real1, NULL_RTX, 1); 516 temp2 = expand_abs (submode, imag1, NULL_RTX, 1); 517 } 518 519 if (temp1 == 0 || temp2 == 0) 520 return 0; 521 522 mode = GET_MODE (temp1); 523 align = GET_MODE_ALIGNMENT (mode); 524 lab1 = gen_label_rtx (); 525 emit_cmp_and_jump_insns (temp1, temp2, LT, NULL_RTX, 526 mode, unsignedp, align, lab1); 527 528 /* |c| >= |d|; use ratio d/c to scale dividend and divisor. */ 529 530 if (class == MODE_COMPLEX_FLOAT) 531 ratio = expand_binop (submode, binoptab, imag1, real1, 532 NULL_RTX, unsignedp, methods); 533 else 534 ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode, 535 imag1, real1, NULL_RTX, unsignedp); 536 537 if (ratio == 0) 538 return 0; 539 540 /* Calculate divisor. */ 541 542 temp1 = expand_binop (submode, smul_optab, imag1, ratio, 543 NULL_RTX, unsignedp, methods); 544 545 if (temp1 == 0) 546 return 0; 547 548 divisor = expand_binop (submode, add_optab, temp1, real1, 549 NULL_RTX, unsignedp, methods); 550 551 if (divisor == 0) 552 return 0; 553 554 /* Calculate dividend. */ 555 556 if (imag0 == 0) 557 { 558 real_t = real0; 559 560 /* Compute a / (c+id) as a / (c+d(d/c)) + i (-a(d/c)) / (c+d(d/c)). */ 561 562 imag_t = expand_binop (submode, smul_optab, real0, ratio, 563 NULL_RTX, unsignedp, methods); 564 565 if (imag_t == 0) 566 return 0; 567 568 imag_t = expand_unop (submode, neg_optab, imag_t, 569 NULL_RTX, unsignedp); 570 571 if (real_t == 0 || imag_t == 0) 572 return 0; 573 } 574 else 575 { 576 /* Compute (a+ib)/(c+id) as 577 (a+b(d/c))/(c+d(d/c) + i(b-a(d/c))/(c+d(d/c)). */ 578 579 temp1 = expand_binop (submode, smul_optab, imag0, ratio, 580 NULL_RTX, unsignedp, methods); 581 582 if (temp1 == 0) 583 return 0; 584 585 real_t = expand_binop (submode, add_optab, temp1, real0, 586 NULL_RTX, unsignedp, methods); 587 588 temp1 = expand_binop (submode, smul_optab, real0, ratio, 589 NULL_RTX, unsignedp, methods); 590 591 if (temp1 == 0) 592 return 0; 593 594 imag_t = expand_binop (submode, sub_optab, imag0, temp1, 595 NULL_RTX, unsignedp, methods); 596 597 if (real_t == 0 || imag_t == 0) 598 return 0; 599 } 600 601 if (class == MODE_COMPLEX_FLOAT) 602 res = expand_binop (submode, binoptab, real_t, divisor, 603 realr, unsignedp, methods); 604 else 605 res = expand_divmod (0, TRUNC_DIV_EXPR, submode, 606 real_t, divisor, realr, unsignedp); 607 608 if (res == 0) 609 return 0; 610 611 if (res != realr) 612 emit_move_insn (realr, res); 613 614 if (class == MODE_COMPLEX_FLOAT) 615 res = expand_binop (submode, binoptab, imag_t, divisor, 616 imagr, unsignedp, methods); 617 else 618 res = expand_divmod (0, TRUNC_DIV_EXPR, submode, 619 imag_t, divisor, imagr, unsignedp); 620 621 if (res == 0) 622 return 0; 623 624 if (res != imagr) 625 emit_move_insn (imagr, res); 626 627 lab2 = gen_label_rtx (); 628 emit_jump_insn (gen_jump (lab2)); 629 emit_barrier (); 630 631 emit_label (lab1); 632 633 /* |d| > |c|; use ratio c/d to scale dividend and divisor. */ 634 635 if (class == MODE_COMPLEX_FLOAT) 636 ratio = expand_binop (submode, binoptab, real1, imag1, 637 NULL_RTX, unsignedp, methods); 638 else 639 ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode, 640 real1, imag1, NULL_RTX, unsignedp); 641 642 if (ratio == 0) 643 return 0; 644 645 /* Calculate divisor. */ 646 647 temp1 = expand_binop (submode, smul_optab, real1, ratio, 648 NULL_RTX, unsignedp, methods); 649 650 if (temp1 == 0) 651 return 0; 652 653 divisor = expand_binop (submode, add_optab, temp1, imag1, 654 NULL_RTX, unsignedp, methods); 655 656 if (divisor == 0) 657 return 0; 658 659 /* Calculate dividend. */ 660 661 if (imag0 == 0) 662 { 663 /* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d). */ 664 665 real_t = expand_binop (submode, smul_optab, real0, ratio, 666 NULL_RTX, unsignedp, methods); 667 668 imag_t = expand_unop (submode, neg_optab, real0, 669 NULL_RTX, unsignedp); 670 671 if (real_t == 0 || imag_t == 0) 672 return 0; 673 } 674 else 675 { 676 /* Compute (a+ib)/(c+id) as 677 (a(c/d)+b)/(c(c/d)+d) + i (b(c/d)-a)/(c(c/d)+d). */ 678 679 temp1 = expand_binop (submode, smul_optab, real0, ratio, 680 NULL_RTX, unsignedp, methods); 681 682 if (temp1 == 0) 683 return 0; 684 685 real_t = expand_binop (submode, add_optab, temp1, imag0, 686 NULL_RTX, unsignedp, methods); 687 688 temp1 = expand_binop (submode, smul_optab, imag0, ratio, 689 NULL_RTX, unsignedp, methods); 690 691 if (temp1 == 0) 692 return 0; 693 694 imag_t = expand_binop (submode, sub_optab, temp1, real0, 695 NULL_RTX, unsignedp, methods); 696 697 if (real_t == 0 || imag_t == 0) 698 return 0; 699 } 700 701 if (class == MODE_COMPLEX_FLOAT) 702 res = expand_binop (submode, binoptab, real_t, divisor, 703 realr, unsignedp, methods); 704 else 705 res = expand_divmod (0, TRUNC_DIV_EXPR, submode, 706 real_t, divisor, realr, unsignedp); 707 708 if (res == 0) 709 return 0; 710 711 if (res != realr) 712 emit_move_insn (realr, res); 713 714 if (class == MODE_COMPLEX_FLOAT) 715 res = expand_binop (submode, binoptab, imag_t, divisor, 716 imagr, unsignedp, methods); 717 else 718 res = expand_divmod (0, TRUNC_DIV_EXPR, submode, 719 imag_t, divisor, imagr, unsignedp); 720 721 if (res == 0) 722 return 0; 723 724 if (res != imagr) 725 emit_move_insn (imagr, res); 726 727 emit_label (lab2); 728 729 return 1; 730} 731 732/* Generate code to perform an operation specified by BINOPTAB 733 on operands OP0 and OP1, with result having machine-mode MODE. 734 735 UNSIGNEDP is for the case where we have to widen the operands 736 to perform the operation. It says to use zero-extension. 737 738 If TARGET is nonzero, the value 739 is generated there, if it is convenient to do so. 740 In all cases an rtx is returned for the locus of the value; 741 this may or may not be TARGET. */ 742 743rtx 744expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) 745 enum machine_mode mode; 746 optab binoptab; 747 rtx op0, op1; 748 rtx target; 749 int unsignedp; 750 enum optab_methods methods; 751{ 752 enum optab_methods next_methods 753 = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN 754 ? OPTAB_WIDEN : methods); 755 enum mode_class class; 756 enum machine_mode wider_mode; 757 register rtx temp; 758 int commutative_op = 0; 759 int shift_op = (binoptab->code == ASHIFT 760 || binoptab->code == ASHIFTRT 761 || binoptab->code == LSHIFTRT 762 || binoptab->code == ROTATE 763 || binoptab->code == ROTATERT); 764 rtx entry_last = get_last_insn (); 765 rtx last; 766 767 class = GET_MODE_CLASS (mode); 768 769 op0 = protect_from_queue (op0, 0); 770 op1 = protect_from_queue (op1, 0); 771 if (target) 772 target = protect_from_queue (target, 1); 773 774 if (flag_force_mem) 775 { 776 op0 = force_not_mem (op0); 777 op1 = force_not_mem (op1); 778 } 779 780 /* If subtracting an integer constant, convert this into an addition of 781 the negated constant. */ 782 783 if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT) 784 { 785 op1 = negate_rtx (mode, op1); 786 binoptab = add_optab; 787 } 788 789 /* If we are inside an appropriately-short loop and one operand is an 790 expensive constant, force it into a register. */ 791 if (CONSTANT_P (op0) && preserve_subexpressions_p () 792 && rtx_cost (op0, binoptab->code) > 2) 793 op0 = force_reg (mode, op0); 794 795 if (CONSTANT_P (op1) && preserve_subexpressions_p () 796 && ! shift_op && rtx_cost (op1, binoptab->code) > 2) 797 op1 = force_reg (mode, op1); 798 799 /* Record where to delete back to if we backtrack. */ 800 last = get_last_insn (); 801 802 /* If operation is commutative, 803 try to make the first operand a register. 804 Even better, try to make it the same as the target. 805 Also try to make the last operand a constant. */ 806 if (GET_RTX_CLASS (binoptab->code) == 'c' 807 || binoptab == smul_widen_optab 808 || binoptab == umul_widen_optab 809 || binoptab == smul_highpart_optab 810 || binoptab == umul_highpart_optab) 811 { 812 commutative_op = 1; 813 814 if (((target == 0 || GET_CODE (target) == REG) 815 ? ((GET_CODE (op1) == REG 816 && GET_CODE (op0) != REG) 817 || target == op1) 818 : rtx_equal_p (op1, target)) 819 || GET_CODE (op0) == CONST_INT) 820 { 821 temp = op1; 822 op1 = op0; 823 op0 = temp; 824 } 825 } 826 827 /* If we can do it with a three-operand insn, do so. */ 828 829 if (methods != OPTAB_MUST_WIDEN 830 && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 831 { 832 int icode = (int) binoptab->handlers[(int) mode].insn_code; 833 enum machine_mode mode0 = insn_operand_mode[icode][1]; 834 enum machine_mode mode1 = insn_operand_mode[icode][2]; 835 rtx pat; 836 rtx xop0 = op0, xop1 = op1; 837 838 if (target) 839 temp = target; 840 else 841 temp = gen_reg_rtx (mode); 842 843 /* If it is a commutative operator and the modes would match 844 if we would swap the operands, we can save the conversions. */ 845 if (commutative_op) 846 { 847 if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1 848 && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0) 849 { 850 register rtx tmp; 851 852 tmp = op0; op0 = op1; op1 = tmp; 853 tmp = xop0; xop0 = xop1; xop1 = tmp; 854 } 855 } 856 857 /* In case the insn wants input operands in modes different from 858 the result, convert the operands. */ 859 860 if (GET_MODE (op0) != VOIDmode 861 && GET_MODE (op0) != mode0 862 && mode0 != VOIDmode) 863 xop0 = convert_to_mode (mode0, xop0, unsignedp); 864 865 if (GET_MODE (xop1) != VOIDmode 866 && GET_MODE (xop1) != mode1 867 && mode1 != VOIDmode) 868 xop1 = convert_to_mode (mode1, xop1, unsignedp); 869 870 /* Now, if insn's predicates don't allow our operands, put them into 871 pseudo regs. */ 872 873 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0) 874 && mode0 != VOIDmode) 875 xop0 = copy_to_mode_reg (mode0, xop0); 876 877 if (! (*insn_operand_predicate[icode][2]) (xop1, mode1) 878 && mode1 != VOIDmode) 879 xop1 = copy_to_mode_reg (mode1, xop1); 880 881 if (! (*insn_operand_predicate[icode][0]) (temp, mode)) 882 temp = gen_reg_rtx (mode); 883 884 pat = GEN_FCN (icode) (temp, xop0, xop1); 885 if (pat) 886 { 887 /* If PAT is a multi-insn sequence, try to add an appropriate 888 REG_EQUAL note to it. If we can't because TEMP conflicts with an 889 operand, call ourselves again, this time without a target. */ 890 if (GET_CODE (pat) == SEQUENCE 891 && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1)) 892 { 893 delete_insns_since (last); 894 return expand_binop (mode, binoptab, op0, op1, NULL_RTX, 895 unsignedp, methods); 896 } 897 898 emit_insn (pat); 899 return temp; 900 } 901 else 902 delete_insns_since (last); 903 } 904 905 /* If this is a multiply, see if we can do a widening operation that 906 takes operands of this mode and makes a wider mode. */ 907 908 if (binoptab == smul_optab && GET_MODE_WIDER_MODE (mode) != VOIDmode 909 && (((unsignedp ? umul_widen_optab : smul_widen_optab) 910 ->handlers[(int) GET_MODE_WIDER_MODE (mode)].insn_code) 911 != CODE_FOR_nothing)) 912 { 913 temp = expand_binop (GET_MODE_WIDER_MODE (mode), 914 unsignedp ? umul_widen_optab : smul_widen_optab, 915 op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT); 916 917 if (temp != 0) 918 { 919 if (GET_MODE_CLASS (mode) == MODE_INT) 920 return gen_lowpart (mode, temp); 921 else 922 return convert_to_mode (mode, temp, unsignedp); 923 } 924 } 925 926 /* Look for a wider mode of the same class for which we think we 927 can open-code the operation. Check for a widening multiply at the 928 wider mode as well. */ 929 930 if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) 931 && methods != OPTAB_DIRECT && methods != OPTAB_LIB) 932 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 933 wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 934 { 935 if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing 936 || (binoptab == smul_optab 937 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode 938 && (((unsignedp ? umul_widen_optab : smul_widen_optab) 939 ->handlers[(int) GET_MODE_WIDER_MODE (wider_mode)].insn_code) 940 != CODE_FOR_nothing))) 941 { 942 rtx xop0 = op0, xop1 = op1; 943 int no_extend = 0; 944 945 /* For certain integer operations, we need not actually extend 946 the narrow operands, as long as we will truncate 947 the results to the same narrowness. */ 948 949 if ((binoptab == ior_optab || binoptab == and_optab 950 || binoptab == xor_optab 951 || binoptab == add_optab || binoptab == sub_optab 952 || binoptab == smul_optab || binoptab == ashl_optab) 953 && class == MODE_INT) 954 no_extend = 1; 955 956 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend); 957 958 /* The second operand of a shift must always be extended. */ 959 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp, 960 no_extend && binoptab != ashl_optab); 961 962 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX, 963 unsignedp, OPTAB_DIRECT); 964 if (temp) 965 { 966 if (class != MODE_INT) 967 { 968 if (target == 0) 969 target = gen_reg_rtx (mode); 970 convert_move (target, temp, 0); 971 return target; 972 } 973 else 974 return gen_lowpart (mode, temp); 975 } 976 else 977 delete_insns_since (last); 978 } 979 } 980 981 /* These can be done a word at a time. */ 982 if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab) 983 && class == MODE_INT 984 && GET_MODE_SIZE (mode) > UNITS_PER_WORD 985 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing) 986 { 987 int i; 988 rtx insns; 989 rtx equiv_value; 990 991 /* If TARGET is the same as one of the operands, the REG_EQUAL note 992 won't be accurate, so use a new target. */ 993 if (target == 0 || target == op0 || target == op1) 994 target = gen_reg_rtx (mode); 995 996 start_sequence (); 997 998 /* Do the actual arithmetic. */ 999 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++) 1000 { 1001 rtx target_piece = operand_subword (target, i, 1, mode); 1002 rtx x = expand_binop (word_mode, binoptab, 1003 operand_subword_force (op0, i, mode), 1004 operand_subword_force (op1, i, mode), 1005 target_piece, unsignedp, next_methods); 1006 1007 if (x == 0) 1008 break; 1009 1010 if (target_piece != x) 1011 emit_move_insn (target_piece, x); 1012 } 1013 1014 insns = get_insns (); 1015 end_sequence (); 1016 1017 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD) 1018 { 1019 if (binoptab->code != UNKNOWN) 1020 equiv_value 1021 = gen_rtx_fmt_ee (binoptab->code, mode, 1022 copy_rtx (op0), copy_rtx (op1)); 1023 else 1024 equiv_value = 0; 1025 1026 emit_no_conflict_block (insns, target, op0, op1, equiv_value); 1027 return target; 1028 } 1029 } 1030 1031 /* Synthesize double word shifts from single word shifts. */ 1032 if ((binoptab == lshr_optab || binoptab == ashl_optab 1033 || binoptab == ashr_optab) 1034 && class == MODE_INT 1035 && GET_CODE (op1) == CONST_INT 1036 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD 1037 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing 1038 && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing 1039 && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing) 1040 { 1041 rtx insns, inter, equiv_value; 1042 rtx into_target, outof_target; 1043 rtx into_input, outof_input; 1044 int shift_count, left_shift, outof_word; 1045 1046 /* If TARGET is the same as one of the operands, the REG_EQUAL note 1047 won't be accurate, so use a new target. */ 1048 if (target == 0 || target == op0 || target == op1) 1049 target = gen_reg_rtx (mode); 1050 1051 start_sequence (); 1052 1053 shift_count = INTVAL (op1); 1054 1055 /* OUTOF_* is the word we are shifting bits away from, and 1056 INTO_* is the word that we are shifting bits towards, thus 1057 they differ depending on the direction of the shift and 1058 WORDS_BIG_ENDIAN. */ 1059 1060 left_shift = binoptab == ashl_optab; 1061 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN; 1062 1063 outof_target = operand_subword (target, outof_word, 1, mode); 1064 into_target = operand_subword (target, 1 - outof_word, 1, mode); 1065 1066 outof_input = operand_subword_force (op0, outof_word, mode); 1067 into_input = operand_subword_force (op0, 1 - outof_word, mode); 1068 1069 if (shift_count >= BITS_PER_WORD) 1070 { 1071 inter = expand_binop (word_mode, binoptab, 1072 outof_input, 1073 GEN_INT (shift_count - BITS_PER_WORD), 1074 into_target, unsignedp, next_methods); 1075 1076 if (inter != 0 && inter != into_target) 1077 emit_move_insn (into_target, inter); 1078 1079 /* For a signed right shift, we must fill the word we are shifting 1080 out of with copies of the sign bit. Otherwise it is zeroed. */ 1081 if (inter != 0 && binoptab != ashr_optab) 1082 inter = CONST0_RTX (word_mode); 1083 else if (inter != 0) 1084 inter = expand_binop (word_mode, binoptab, 1085 outof_input, 1086 GEN_INT (BITS_PER_WORD - 1), 1087 outof_target, unsignedp, next_methods); 1088 1089 if (inter != 0 && inter != outof_target) 1090 emit_move_insn (outof_target, inter); 1091 } 1092 else 1093 { 1094 rtx carries; 1095 optab reverse_unsigned_shift, unsigned_shift; 1096 1097 /* For a shift of less then BITS_PER_WORD, to compute the carry, 1098 we must do a logical shift in the opposite direction of the 1099 desired shift. */ 1100 1101 reverse_unsigned_shift = (left_shift ? lshr_optab : ashl_optab); 1102 1103 /* For a shift of less than BITS_PER_WORD, to compute the word 1104 shifted towards, we need to unsigned shift the orig value of 1105 that word. */ 1106 1107 unsigned_shift = (left_shift ? ashl_optab : lshr_optab); 1108 1109 carries = expand_binop (word_mode, reverse_unsigned_shift, 1110 outof_input, 1111 GEN_INT (BITS_PER_WORD - shift_count), 1112 0, unsignedp, next_methods); 1113 1114 if (carries == 0) 1115 inter = 0; 1116 else 1117 inter = expand_binop (word_mode, unsigned_shift, into_input, 1118 op1, 0, unsignedp, next_methods); 1119 1120 if (inter != 0) 1121 inter = expand_binop (word_mode, ior_optab, carries, inter, 1122 into_target, unsignedp, next_methods); 1123 1124 if (inter != 0 && inter != into_target) 1125 emit_move_insn (into_target, inter); 1126 1127 if (inter != 0) 1128 inter = expand_binop (word_mode, binoptab, outof_input, 1129 op1, outof_target, unsignedp, next_methods); 1130 1131 if (inter != 0 && inter != outof_target) 1132 emit_move_insn (outof_target, inter); 1133 } 1134 1135 insns = get_insns (); 1136 end_sequence (); 1137 1138 if (inter != 0) 1139 { 1140 if (binoptab->code != UNKNOWN) 1141 equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1); 1142 else 1143 equiv_value = 0; 1144 1145 emit_no_conflict_block (insns, target, op0, op1, equiv_value); 1146 return target; 1147 } 1148 } 1149 1150 /* Synthesize double word rotates from single word shifts. */ 1151 if ((binoptab == rotl_optab || binoptab == rotr_optab) 1152 && class == MODE_INT 1153 && GET_CODE (op1) == CONST_INT 1154 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD 1155 && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing 1156 && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing) 1157 { 1158 rtx insns, equiv_value; 1159 rtx into_target, outof_target; 1160 rtx into_input, outof_input; 1161 rtx inter; 1162 int shift_count, left_shift, outof_word; 1163 1164 /* If TARGET is the same as one of the operands, the REG_EQUAL note 1165 won't be accurate, so use a new target. */ 1166 if (target == 0 || target == op0 || target == op1) 1167 target = gen_reg_rtx (mode); 1168 1169 start_sequence (); 1170 1171 shift_count = INTVAL (op1); 1172 1173 /* OUTOF_* is the word we are shifting bits away from, and 1174 INTO_* is the word that we are shifting bits towards, thus 1175 they differ depending on the direction of the shift and 1176 WORDS_BIG_ENDIAN. */ 1177 1178 left_shift = (binoptab == rotl_optab); 1179 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN; 1180 1181 outof_target = operand_subword (target, outof_word, 1, mode); 1182 into_target = operand_subword (target, 1 - outof_word, 1, mode); 1183 1184 outof_input = operand_subword_force (op0, outof_word, mode); 1185 into_input = operand_subword_force (op0, 1 - outof_word, mode); 1186 1187 if (shift_count == BITS_PER_WORD) 1188 { 1189 /* This is just a word swap. */ 1190 emit_move_insn (outof_target, into_input); 1191 emit_move_insn (into_target, outof_input); 1192 inter = const0_rtx; 1193 } 1194 else 1195 { 1196 rtx into_temp1, into_temp2, outof_temp1, outof_temp2; 1197 rtx first_shift_count, second_shift_count; 1198 optab reverse_unsigned_shift, unsigned_shift; 1199 1200 reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD) 1201 ? lshr_optab : ashl_optab); 1202 1203 unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD) 1204 ? ashl_optab : lshr_optab); 1205 1206 if (shift_count > BITS_PER_WORD) 1207 { 1208 first_shift_count = GEN_INT (shift_count - BITS_PER_WORD); 1209 second_shift_count = GEN_INT (2*BITS_PER_WORD - shift_count); 1210 } 1211 else 1212 { 1213 first_shift_count = GEN_INT (BITS_PER_WORD - shift_count); 1214 second_shift_count = GEN_INT (shift_count); 1215 } 1216 1217 into_temp1 = expand_binop (word_mode, unsigned_shift, 1218 outof_input, first_shift_count, 1219 NULL_RTX, unsignedp, next_methods); 1220 into_temp2 = expand_binop (word_mode, reverse_unsigned_shift, 1221 into_input, second_shift_count, 1222 into_target, unsignedp, next_methods); 1223 1224 if (into_temp1 != 0 && into_temp2 != 0) 1225 inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2, 1226 into_target, unsignedp, next_methods); 1227 else 1228 inter = 0; 1229 1230 if (inter != 0 && inter != into_target) 1231 emit_move_insn (into_target, inter); 1232 1233 outof_temp1 = expand_binop (word_mode, unsigned_shift, 1234 into_input, first_shift_count, 1235 NULL_RTX, unsignedp, next_methods); 1236 outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift, 1237 outof_input, second_shift_count, 1238 outof_target, unsignedp, next_methods); 1239 1240 if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0) 1241 inter = expand_binop (word_mode, ior_optab, 1242 outof_temp1, outof_temp2, 1243 outof_target, unsignedp, next_methods); 1244 1245 if (inter != 0 && inter != outof_target) 1246 emit_move_insn (outof_target, inter); 1247 } 1248 1249 insns = get_insns (); 1250 end_sequence (); 1251 1252 if (inter != 0) 1253 { 1254 if (binoptab->code != UNKNOWN) 1255 equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1); 1256 else 1257 equiv_value = 0; 1258 1259 /* We can't make this a no conflict block if this is a word swap, 1260 because the word swap case fails if the input and output values 1261 are in the same register. */ 1262 if (shift_count != BITS_PER_WORD) 1263 emit_no_conflict_block (insns, target, op0, op1, equiv_value); 1264 else 1265 emit_insns (insns); 1266 1267 1268 return target; 1269 } 1270 } 1271 1272 /* These can be done a word at a time by propagating carries. */ 1273 if ((binoptab == add_optab || binoptab == sub_optab) 1274 && class == MODE_INT 1275 && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD 1276 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing) 1277 { 1278 int i; 1279 rtx carry_tmp = gen_reg_rtx (word_mode); 1280 optab otheroptab = binoptab == add_optab ? sub_optab : add_optab; 1281 int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD; 1282 rtx carry_in = NULL_RTX, carry_out = NULL_RTX; 1283 rtx xop0, xop1; 1284 1285 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG 1286 value is one of those, use it. Otherwise, use 1 since it is the 1287 one easiest to get. */ 1288#if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1 1289 int normalizep = STORE_FLAG_VALUE; 1290#else 1291 int normalizep = 1; 1292#endif 1293 1294 /* Prepare the operands. */ 1295 xop0 = force_reg (mode, op0); 1296 xop1 = force_reg (mode, op1); 1297 1298 if (target == 0 || GET_CODE (target) != REG 1299 || target == xop0 || target == xop1) 1300 target = gen_reg_rtx (mode); 1301 1302 /* Indicate for flow that the entire target reg is being set. */ 1303 if (GET_CODE (target) == REG) 1304 emit_insn (gen_rtx_CLOBBER (VOIDmode, target)); 1305 1306 /* Do the actual arithmetic. */ 1307 for (i = 0; i < nwords; i++) 1308 { 1309 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i); 1310 rtx target_piece = operand_subword (target, index, 1, mode); 1311 rtx op0_piece = operand_subword_force (xop0, index, mode); 1312 rtx op1_piece = operand_subword_force (xop1, index, mode); 1313 rtx x; 1314 1315 /* Main add/subtract of the input operands. */ 1316 x = expand_binop (word_mode, binoptab, 1317 op0_piece, op1_piece, 1318 target_piece, unsignedp, next_methods); 1319 if (x == 0) 1320 break; 1321 1322 if (i + 1 < nwords) 1323 { 1324 /* Store carry from main add/subtract. */ 1325 carry_out = gen_reg_rtx (word_mode); 1326 carry_out = emit_store_flag_force (carry_out, 1327 (binoptab == add_optab 1328 ? LTU : GTU), 1329 x, op0_piece, 1330 word_mode, 1, normalizep); 1331 } 1332 1333 if (i > 0) 1334 { 1335 /* Add/subtract previous carry to main result. */ 1336 x = expand_binop (word_mode, 1337 normalizep == 1 ? binoptab : otheroptab, 1338 x, carry_in, 1339 target_piece, 1, next_methods); 1340 if (x == 0) 1341 break; 1342 else if (target_piece != x) 1343 emit_move_insn (target_piece, x); 1344 1345 if (i + 1 < nwords) 1346 { 1347 /* THIS CODE HAS NOT BEEN TESTED. */ 1348 /* Get out carry from adding/subtracting carry in. */ 1349 carry_tmp = emit_store_flag_force (carry_tmp, 1350 binoptab == add_optab 1351 ? LTU : GTU, 1352 x, carry_in, 1353 word_mode, 1, normalizep); 1354 1355 /* Logical-ior the two poss. carry together. */ 1356 carry_out = expand_binop (word_mode, ior_optab, 1357 carry_out, carry_tmp, 1358 carry_out, 0, next_methods); 1359 if (carry_out == 0) 1360 break; 1361 } 1362 } 1363 1364 carry_in = carry_out; 1365 } 1366 1367 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD) 1368 { 1369 if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 1370 { 1371 rtx temp = emit_move_insn (target, target); 1372 1373 set_unique_reg_note (temp, 1374 REG_EQUAL, 1375 gen_rtx_fmt_ee (binoptab->code, mode, 1376 copy_rtx (xop0), 1377 copy_rtx (xop1))); 1378 } 1379 return target; 1380 } 1381 else 1382 delete_insns_since (last); 1383 } 1384 1385 /* If we want to multiply two two-word values and have normal and widening 1386 multiplies of single-word values, we can do this with three smaller 1387 multiplications. Note that we do not make a REG_NO_CONFLICT block here 1388 because we are not operating on one word at a time. 1389 1390 The multiplication proceeds as follows: 1391 _______________________ 1392 [__op0_high_|__op0_low__] 1393 _______________________ 1394 * [__op1_high_|__op1_low__] 1395 _______________________________________________ 1396 _______________________ 1397 (1) [__op0_low__*__op1_low__] 1398 _______________________ 1399 (2a) [__op0_low__*__op1_high_] 1400 _______________________ 1401 (2b) [__op0_high_*__op1_low__] 1402 _______________________ 1403 (3) [__op0_high_*__op1_high_] 1404 1405 1406 This gives a 4-word result. Since we are only interested in the 1407 lower 2 words, partial result (3) and the upper words of (2a) and 1408 (2b) don't need to be calculated. Hence (2a) and (2b) can be 1409 calculated using non-widening multiplication. 1410 1411 (1), however, needs to be calculated with an unsigned widening 1412 multiplication. If this operation is not directly supported we 1413 try using a signed widening multiplication and adjust the result. 1414 This adjustment works as follows: 1415 1416 If both operands are positive then no adjustment is needed. 1417 1418 If the operands have different signs, for example op0_low < 0 and 1419 op1_low >= 0, the instruction treats the most significant bit of 1420 op0_low as a sign bit instead of a bit with significance 1421 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low 1422 with 2**BITS_PER_WORD - op0_low, and two's complements the 1423 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to 1424 the result. 1425 1426 Similarly, if both operands are negative, we need to add 1427 (op0_low + op1_low) * 2**BITS_PER_WORD. 1428 1429 We use a trick to adjust quickly. We logically shift op0_low right 1430 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to 1431 op0_high (op1_high) before it is used to calculate 2b (2a). If no 1432 logical shift exists, we do an arithmetic right shift and subtract 1433 the 0 or -1. */ 1434 1435 if (binoptab == smul_optab 1436 && class == MODE_INT 1437 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD 1438 && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing 1439 && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing 1440 && ((umul_widen_optab->handlers[(int) mode].insn_code 1441 != CODE_FOR_nothing) 1442 || (smul_widen_optab->handlers[(int) mode].insn_code 1443 != CODE_FOR_nothing))) 1444 { 1445 int low = (WORDS_BIG_ENDIAN ? 1 : 0); 1446 int high = (WORDS_BIG_ENDIAN ? 0 : 1); 1447 rtx op0_high = operand_subword_force (op0, high, mode); 1448 rtx op0_low = operand_subword_force (op0, low, mode); 1449 rtx op1_high = operand_subword_force (op1, high, mode); 1450 rtx op1_low = operand_subword_force (op1, low, mode); 1451 rtx product = 0; 1452 rtx op0_xhigh = NULL_RTX; 1453 rtx op1_xhigh = NULL_RTX; 1454 1455 /* If the target is the same as one of the inputs, don't use it. This 1456 prevents problems with the REG_EQUAL note. */ 1457 if (target == op0 || target == op1 1458 || (target != 0 && GET_CODE (target) != REG)) 1459 target = 0; 1460 1461 /* Multiply the two lower words to get a double-word product. 1462 If unsigned widening multiplication is available, use that; 1463 otherwise use the signed form and compensate. */ 1464 1465 if (umul_widen_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 1466 { 1467 product = expand_binop (mode, umul_widen_optab, op0_low, op1_low, 1468 target, 1, OPTAB_DIRECT); 1469 1470 /* If we didn't succeed, delete everything we did so far. */ 1471 if (product == 0) 1472 delete_insns_since (last); 1473 else 1474 op0_xhigh = op0_high, op1_xhigh = op1_high; 1475 } 1476 1477 if (product == 0 1478 && smul_widen_optab->handlers[(int) mode].insn_code 1479 != CODE_FOR_nothing) 1480 { 1481 rtx wordm1 = GEN_INT (BITS_PER_WORD - 1); 1482 product = expand_binop (mode, smul_widen_optab, op0_low, op1_low, 1483 target, 1, OPTAB_DIRECT); 1484 op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1, 1485 NULL_RTX, 1, next_methods); 1486 if (op0_xhigh) 1487 op0_xhigh = expand_binop (word_mode, add_optab, op0_high, 1488 op0_xhigh, op0_xhigh, 0, next_methods); 1489 else 1490 { 1491 op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1, 1492 NULL_RTX, 0, next_methods); 1493 if (op0_xhigh) 1494 op0_xhigh = expand_binop (word_mode, sub_optab, op0_high, 1495 op0_xhigh, op0_xhigh, 0, 1496 next_methods); 1497 } 1498 1499 op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1, 1500 NULL_RTX, 1, next_methods); 1501 if (op1_xhigh) 1502 op1_xhigh = expand_binop (word_mode, add_optab, op1_high, 1503 op1_xhigh, op1_xhigh, 0, next_methods); 1504 else 1505 { 1506 op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1, 1507 NULL_RTX, 0, next_methods); 1508 if (op1_xhigh) 1509 op1_xhigh = expand_binop (word_mode, sub_optab, op1_high, 1510 op1_xhigh, op1_xhigh, 0, 1511 next_methods); 1512 } 1513 } 1514 1515 /* If we have been able to directly compute the product of the 1516 low-order words of the operands and perform any required adjustments 1517 of the operands, we proceed by trying two more multiplications 1518 and then computing the appropriate sum. 1519 1520 We have checked above that the required addition is provided. 1521 Full-word addition will normally always succeed, especially if 1522 it is provided at all, so we don't worry about its failure. The 1523 multiplication may well fail, however, so we do handle that. */ 1524 1525 if (product && op0_xhigh && op1_xhigh) 1526 { 1527 rtx product_high = operand_subword (product, high, 1, mode); 1528 rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh, 1529 NULL_RTX, 0, OPTAB_DIRECT); 1530 1531 if (temp != 0) 1532 temp = expand_binop (word_mode, add_optab, temp, product_high, 1533 product_high, 0, next_methods); 1534 1535 if (temp != 0 && temp != product_high) 1536 emit_move_insn (product_high, temp); 1537 1538 if (temp != 0) 1539 temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh, 1540 NULL_RTX, 0, OPTAB_DIRECT); 1541 1542 if (temp != 0) 1543 temp = expand_binop (word_mode, add_optab, temp, 1544 product_high, product_high, 1545 0, next_methods); 1546 1547 if (temp != 0 && temp != product_high) 1548 emit_move_insn (product_high, temp); 1549 1550 if (temp != 0) 1551 { 1552 if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 1553 { 1554 temp = emit_move_insn (product, product); 1555 set_unique_reg_note (temp, 1556 REG_EQUAL, 1557 gen_rtx_fmt_ee (MULT, mode, 1558 copy_rtx (op0), 1559 copy_rtx (op1))); 1560 } 1561 return product; 1562 } 1563 } 1564 1565 /* If we get here, we couldn't do it for some reason even though we 1566 originally thought we could. Delete anything we've emitted in 1567 trying to do it. */ 1568 1569 delete_insns_since (last); 1570 } 1571 1572 /* We need to open-code the complex type operations: '+, -, * and /' */ 1573 1574 /* At this point we allow operations between two similar complex 1575 numbers, and also if one of the operands is not a complex number 1576 but rather of MODE_FLOAT or MODE_INT. However, the caller 1577 must make sure that the MODE of the non-complex operand matches 1578 the SUBMODE of the complex operand. */ 1579 1580 if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT) 1581 { 1582 rtx real0 = 0, imag0 = 0; 1583 rtx real1 = 0, imag1 = 0; 1584 rtx realr, imagr, res; 1585 rtx seq; 1586 rtx equiv_value; 1587 int ok = 0; 1588 1589 /* Find the correct mode for the real and imaginary parts */ 1590 enum machine_mode submode 1591 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT, 1592 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT, 1593 0); 1594 1595 if (submode == BLKmode) 1596 abort (); 1597 1598 if (! target) 1599 target = gen_reg_rtx (mode); 1600 1601 start_sequence (); 1602 1603 realr = gen_realpart (submode, target); 1604 imagr = gen_imagpart (submode, target); 1605 1606 if (GET_MODE (op0) == mode) 1607 { 1608 real0 = gen_realpart (submode, op0); 1609 imag0 = gen_imagpart (submode, op0); 1610 } 1611 else 1612 real0 = op0; 1613 1614 if (GET_MODE (op1) == mode) 1615 { 1616 real1 = gen_realpart (submode, op1); 1617 imag1 = gen_imagpart (submode, op1); 1618 } 1619 else 1620 real1 = op1; 1621 1622 if (real0 == 0 || real1 == 0 || ! (imag0 != 0|| imag1 != 0)) 1623 abort (); 1624 1625 switch (binoptab->code) 1626 { 1627 case PLUS: 1628 /* (a+ib) + (c+id) = (a+c) + i(b+d) */ 1629 case MINUS: 1630 /* (a+ib) - (c+id) = (a-c) + i(b-d) */ 1631 res = expand_binop (submode, binoptab, real0, real1, 1632 realr, unsignedp, methods); 1633 1634 if (res == 0) 1635 break; 1636 else if (res != realr) 1637 emit_move_insn (realr, res); 1638 1639 if (imag0 && imag1) 1640 res = expand_binop (submode, binoptab, imag0, imag1, 1641 imagr, unsignedp, methods); 1642 else if (imag0) 1643 res = imag0; 1644 else if (binoptab->code == MINUS) 1645 res = expand_unop (submode, neg_optab, imag1, imagr, unsignedp); 1646 else 1647 res = imag1; 1648 1649 if (res == 0) 1650 break; 1651 else if (res != imagr) 1652 emit_move_insn (imagr, res); 1653 1654 ok = 1; 1655 break; 1656 1657 case MULT: 1658 /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */ 1659 1660 if (imag0 && imag1) 1661 { 1662 rtx temp1, temp2; 1663 1664 /* Don't fetch these from memory more than once. */ 1665 real0 = force_reg (submode, real0); 1666 real1 = force_reg (submode, real1); 1667 imag0 = force_reg (submode, imag0); 1668 imag1 = force_reg (submode, imag1); 1669 1670 temp1 = expand_binop (submode, binoptab, real0, real1, NULL_RTX, 1671 unsignedp, methods); 1672 1673 temp2 = expand_binop (submode, binoptab, imag0, imag1, NULL_RTX, 1674 unsignedp, methods); 1675 1676 if (temp1 == 0 || temp2 == 0) 1677 break; 1678 1679 res = expand_binop (submode, sub_optab, temp1, temp2, 1680 realr, unsignedp, methods); 1681 1682 if (res == 0) 1683 break; 1684 else if (res != realr) 1685 emit_move_insn (realr, res); 1686 1687 temp1 = expand_binop (submode, binoptab, real0, imag1, 1688 NULL_RTX, unsignedp, methods); 1689 1690 temp2 = expand_binop (submode, binoptab, real1, imag0, 1691 NULL_RTX, unsignedp, methods); 1692 1693 if (temp1 == 0 || temp2 == 0) 1694 break; 1695 1696 res = expand_binop (submode, add_optab, temp1, temp2, 1697 imagr, unsignedp, methods); 1698 1699 if (res == 0) 1700 break; 1701 else if (res != imagr) 1702 emit_move_insn (imagr, res); 1703 1704 ok = 1; 1705 } 1706 else 1707 { 1708 /* Don't fetch these from memory more than once. */ 1709 real0 = force_reg (submode, real0); 1710 real1 = force_reg (submode, real1); 1711 1712 res = expand_binop (submode, binoptab, real0, real1, 1713 realr, unsignedp, methods); 1714 if (res == 0) 1715 break; 1716 else if (res != realr) 1717 emit_move_insn (realr, res); 1718 1719 if (imag0 != 0) 1720 res = expand_binop (submode, binoptab, 1721 real1, imag0, imagr, unsignedp, methods); 1722 else 1723 res = expand_binop (submode, binoptab, 1724 real0, imag1, imagr, unsignedp, methods); 1725 1726 if (res == 0) 1727 break; 1728 else if (res != imagr) 1729 emit_move_insn (imagr, res); 1730 1731 ok = 1; 1732 } 1733 break; 1734 1735 case DIV: 1736 /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */ 1737 1738 if (imag1 == 0) 1739 { 1740 /* (a+ib) / (c+i0) = (a/c) + i(b/c) */ 1741 1742 /* Don't fetch these from memory more than once. */ 1743 real1 = force_reg (submode, real1); 1744 1745 /* Simply divide the real and imaginary parts by `c' */ 1746 if (class == MODE_COMPLEX_FLOAT) 1747 res = expand_binop (submode, binoptab, real0, real1, 1748 realr, unsignedp, methods); 1749 else 1750 res = expand_divmod (0, TRUNC_DIV_EXPR, submode, 1751 real0, real1, realr, unsignedp); 1752 1753 if (res == 0) 1754 break; 1755 else if (res != realr) 1756 emit_move_insn (realr, res); 1757 1758 if (class == MODE_COMPLEX_FLOAT) 1759 res = expand_binop (submode, binoptab, imag0, real1, 1760 imagr, unsignedp, methods); 1761 else 1762 res = expand_divmod (0, TRUNC_DIV_EXPR, submode, 1763 imag0, real1, imagr, unsignedp); 1764 1765 if (res == 0) 1766 break; 1767 else if (res != imagr) 1768 emit_move_insn (imagr, res); 1769 1770 ok = 1; 1771 } 1772 else 1773 { 1774 switch (flag_complex_divide_method) 1775 { 1776 case 0: 1777 ok = expand_cmplxdiv_straight (real0, real1, imag0, imag1, 1778 realr, imagr, submode, 1779 unsignedp, methods, 1780 class, binoptab); 1781 break; 1782 1783 case 1: 1784 ok = expand_cmplxdiv_wide (real0, real1, imag0, imag1, 1785 realr, imagr, submode, 1786 unsignedp, methods, 1787 class, binoptab); 1788 break; 1789 1790 default: 1791 abort (); 1792 } 1793 } 1794 break; 1795 1796 default: 1797 abort (); 1798 } 1799 1800 seq = get_insns (); 1801 end_sequence (); 1802 1803 if (ok) 1804 { 1805 if (binoptab->code != UNKNOWN) 1806 equiv_value 1807 = gen_rtx_fmt_ee (binoptab->code, mode, 1808 copy_rtx (op0), copy_rtx (op1)); 1809 else 1810 equiv_value = 0; 1811 1812 emit_no_conflict_block (seq, target, op0, op1, equiv_value); 1813 1814 return target; 1815 } 1816 } 1817 1818 /* It can't be open-coded in this mode. 1819 Use a library call if one is available and caller says that's ok. */ 1820 1821 if (binoptab->handlers[(int) mode].libfunc 1822 && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN)) 1823 { 1824 rtx insns; 1825 rtx op1x = op1; 1826 enum machine_mode op1_mode = mode; 1827 rtx value; 1828 1829 start_sequence (); 1830 1831 if (shift_op) 1832 { 1833 op1_mode = word_mode; 1834 /* Specify unsigned here, 1835 since negative shift counts are meaningless. */ 1836 op1x = convert_to_mode (word_mode, op1, 1); 1837 } 1838 1839 if (GET_MODE (op0) != VOIDmode 1840 && GET_MODE (op0) != mode) 1841 op0 = convert_to_mode (mode, op0, unsignedp); 1842 1843 /* Pass 1 for NO_QUEUE so we don't lose any increments 1844 if the libcall is cse'd or moved. */ 1845 value = emit_library_call_value (binoptab->handlers[(int) mode].libfunc, 1846 NULL_RTX, 1, mode, 2, 1847 op0, mode, op1x, op1_mode); 1848 1849 insns = get_insns (); 1850 end_sequence (); 1851 1852 target = gen_reg_rtx (mode); 1853 emit_libcall_block (insns, target, value, 1854 gen_rtx_fmt_ee (binoptab->code, mode, op0, op1)); 1855 1856 return target; 1857 } 1858 1859 delete_insns_since (last); 1860 1861 /* It can't be done in this mode. Can we do it in a wider mode? */ 1862 1863 if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN 1864 || methods == OPTAB_MUST_WIDEN)) 1865 { 1866 /* Caller says, don't even try. */ 1867 delete_insns_since (entry_last); 1868 return 0; 1869 } 1870 1871 /* Compute the value of METHODS to pass to recursive calls. 1872 Don't allow widening to be tried recursively. */ 1873 1874 methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT); 1875 1876 /* Look for a wider mode of the same class for which it appears we can do 1877 the operation. */ 1878 1879 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) 1880 { 1881 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 1882 wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 1883 { 1884 if ((binoptab->handlers[(int) wider_mode].insn_code 1885 != CODE_FOR_nothing) 1886 || (methods == OPTAB_LIB 1887 && binoptab->handlers[(int) wider_mode].libfunc)) 1888 { 1889 rtx xop0 = op0, xop1 = op1; 1890 int no_extend = 0; 1891 1892 /* For certain integer operations, we need not actually extend 1893 the narrow operands, as long as we will truncate 1894 the results to the same narrowness. */ 1895 1896 if ((binoptab == ior_optab || binoptab == and_optab 1897 || binoptab == xor_optab 1898 || binoptab == add_optab || binoptab == sub_optab 1899 || binoptab == smul_optab || binoptab == ashl_optab) 1900 && class == MODE_INT) 1901 no_extend = 1; 1902 1903 xop0 = widen_operand (xop0, wider_mode, mode, 1904 unsignedp, no_extend); 1905 1906 /* The second operand of a shift must always be extended. */ 1907 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp, 1908 no_extend && binoptab != ashl_optab); 1909 1910 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX, 1911 unsignedp, methods); 1912 if (temp) 1913 { 1914 if (class != MODE_INT) 1915 { 1916 if (target == 0) 1917 target = gen_reg_rtx (mode); 1918 convert_move (target, temp, 0); 1919 return target; 1920 } 1921 else 1922 return gen_lowpart (mode, temp); 1923 } 1924 else 1925 delete_insns_since (last); 1926 } 1927 } 1928 } 1929 1930 delete_insns_since (entry_last); 1931 return 0; 1932} 1933 1934/* Expand a binary operator which has both signed and unsigned forms. 1935 UOPTAB is the optab for unsigned operations, and SOPTAB is for 1936 signed operations. 1937 1938 If we widen unsigned operands, we may use a signed wider operation instead 1939 of an unsigned wider operation, since the result would be the same. */ 1940 1941rtx 1942sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods) 1943 enum machine_mode mode; 1944 optab uoptab, soptab; 1945 rtx op0, op1, target; 1946 int unsignedp; 1947 enum optab_methods methods; 1948{ 1949 register rtx temp; 1950 optab direct_optab = unsignedp ? uoptab : soptab; 1951 struct optab wide_soptab; 1952 1953 /* Do it without widening, if possible. */ 1954 temp = expand_binop (mode, direct_optab, op0, op1, target, 1955 unsignedp, OPTAB_DIRECT); 1956 if (temp || methods == OPTAB_DIRECT) 1957 return temp; 1958 1959 /* Try widening to a signed int. Make a fake signed optab that 1960 hides any signed insn for direct use. */ 1961 wide_soptab = *soptab; 1962 wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing; 1963 wide_soptab.handlers[(int) mode].libfunc = 0; 1964 1965 temp = expand_binop (mode, &wide_soptab, op0, op1, target, 1966 unsignedp, OPTAB_WIDEN); 1967 1968 /* For unsigned operands, try widening to an unsigned int. */ 1969 if (temp == 0 && unsignedp) 1970 temp = expand_binop (mode, uoptab, op0, op1, target, 1971 unsignedp, OPTAB_WIDEN); 1972 if (temp || methods == OPTAB_WIDEN) 1973 return temp; 1974 1975 /* Use the right width lib call if that exists. */ 1976 temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB); 1977 if (temp || methods == OPTAB_LIB) 1978 return temp; 1979 1980 /* Must widen and use a lib call, use either signed or unsigned. */ 1981 temp = expand_binop (mode, &wide_soptab, op0, op1, target, 1982 unsignedp, methods); 1983 if (temp != 0) 1984 return temp; 1985 if (unsignedp) 1986 return expand_binop (mode, uoptab, op0, op1, target, 1987 unsignedp, methods); 1988 return 0; 1989} 1990 1991/* Generate code to perform an operation specified by BINOPTAB 1992 on operands OP0 and OP1, with two results to TARG1 and TARG2. 1993 We assume that the order of the operands for the instruction 1994 is TARG0, OP0, OP1, TARG1, which would fit a pattern like 1995 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))]. 1996 1997 Either TARG0 or TARG1 may be zero, but what that means is that 1998 the result is not actually wanted. We will generate it into 1999 a dummy pseudo-reg and discard it. They may not both be zero. 2000 2001 Returns 1 if this operation can be performed; 0 if not. */ 2002 2003int 2004expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp) 2005 optab binoptab; 2006 rtx op0, op1; 2007 rtx targ0, targ1; 2008 int unsignedp; 2009{ 2010 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1); 2011 enum mode_class class; 2012 enum machine_mode wider_mode; 2013 rtx entry_last = get_last_insn (); 2014 rtx last; 2015 2016 class = GET_MODE_CLASS (mode); 2017 2018 op0 = protect_from_queue (op0, 0); 2019 op1 = protect_from_queue (op1, 0); 2020 2021 if (flag_force_mem) 2022 { 2023 op0 = force_not_mem (op0); 2024 op1 = force_not_mem (op1); 2025 } 2026 2027 /* If we are inside an appropriately-short loop and one operand is an 2028 expensive constant, force it into a register. */ 2029 if (CONSTANT_P (op0) && preserve_subexpressions_p () 2030 && rtx_cost (op0, binoptab->code) > 2) 2031 op0 = force_reg (mode, op0); 2032 2033 if (CONSTANT_P (op1) && preserve_subexpressions_p () 2034 && rtx_cost (op1, binoptab->code) > 2) 2035 op1 = force_reg (mode, op1); 2036 2037 if (targ0) 2038 targ0 = protect_from_queue (targ0, 1); 2039 else 2040 targ0 = gen_reg_rtx (mode); 2041 if (targ1) 2042 targ1 = protect_from_queue (targ1, 1); 2043 else 2044 targ1 = gen_reg_rtx (mode); 2045 2046 /* Record where to go back to if we fail. */ 2047 last = get_last_insn (); 2048 2049 if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 2050 { 2051 int icode = (int) binoptab->handlers[(int) mode].insn_code; 2052 enum machine_mode mode0 = insn_operand_mode[icode][1]; 2053 enum machine_mode mode1 = insn_operand_mode[icode][2]; 2054 rtx pat; 2055 rtx xop0 = op0, xop1 = op1; 2056 2057 /* In case this insn wants input operands in modes different from the 2058 result, convert the operands. */ 2059 if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode0) 2060 xop0 = convert_to_mode (mode0, xop0, unsignedp); 2061 2062 if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode1) 2063 xop1 = convert_to_mode (mode1, xop1, unsignedp); 2064 2065 /* Now, if insn doesn't accept these operands, put them into pseudos. */ 2066 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)) 2067 xop0 = copy_to_mode_reg (mode0, xop0); 2068 2069 if (! (*insn_operand_predicate[icode][2]) (xop1, mode1)) 2070 xop1 = copy_to_mode_reg (mode1, xop1); 2071 2072 /* We could handle this, but we should always be called with a pseudo 2073 for our targets and all insns should take them as outputs. */ 2074 if (! (*insn_operand_predicate[icode][0]) (targ0, mode) 2075 || ! (*insn_operand_predicate[icode][3]) (targ1, mode)) 2076 abort (); 2077 2078 pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1); 2079 if (pat) 2080 { 2081 emit_insn (pat); 2082 return 1; 2083 } 2084 else 2085 delete_insns_since (last); 2086 } 2087 2088 /* It can't be done in this mode. Can we do it in a wider mode? */ 2089 2090 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) 2091 { 2092 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 2093 wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 2094 { 2095 if (binoptab->handlers[(int) wider_mode].insn_code 2096 != CODE_FOR_nothing) 2097 { 2098 register rtx t0 = gen_reg_rtx (wider_mode); 2099 register rtx t1 = gen_reg_rtx (wider_mode); 2100 2101 if (expand_twoval_binop (binoptab, 2102 convert_modes (wider_mode, mode, op0, 2103 unsignedp), 2104 convert_modes (wider_mode, mode, op1, 2105 unsignedp), 2106 t0, t1, unsignedp)) 2107 { 2108 convert_move (targ0, t0, unsignedp); 2109 convert_move (targ1, t1, unsignedp); 2110 return 1; 2111 } 2112 else 2113 delete_insns_since (last); 2114 } 2115 } 2116 } 2117 2118 delete_insns_since (entry_last); 2119 return 0; 2120} 2121 2122/* Generate code to perform an operation specified by UNOPTAB 2123 on operand OP0, with result having machine-mode MODE. 2124 2125 UNSIGNEDP is for the case where we have to widen the operands 2126 to perform the operation. It says to use zero-extension. 2127 2128 If TARGET is nonzero, the value 2129 is generated there, if it is convenient to do so. 2130 In all cases an rtx is returned for the locus of the value; 2131 this may or may not be TARGET. */ 2132 2133rtx 2134expand_unop (mode, unoptab, op0, target, unsignedp) 2135 enum machine_mode mode; 2136 optab unoptab; 2137 rtx op0; 2138 rtx target; 2139 int unsignedp; 2140{ 2141 enum mode_class class; 2142 enum machine_mode wider_mode; 2143 register rtx temp; 2144 rtx last = get_last_insn (); 2145 rtx pat; 2146 2147 class = GET_MODE_CLASS (mode); 2148 2149 op0 = protect_from_queue (op0, 0); 2150 2151 if (flag_force_mem) 2152 { 2153 op0 = force_not_mem (op0); 2154 } 2155 2156 if (target) 2157 target = protect_from_queue (target, 1); 2158 2159 if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 2160 { 2161 int icode = (int) unoptab->handlers[(int) mode].insn_code; 2162 enum machine_mode mode0 = insn_operand_mode[icode][1]; 2163 rtx xop0 = op0; 2164 2165 if (target) 2166 temp = target; 2167 else 2168 temp = gen_reg_rtx (mode); 2169 2170 if (GET_MODE (xop0) != VOIDmode 2171 && GET_MODE (xop0) != mode0) 2172 xop0 = convert_to_mode (mode0, xop0, unsignedp); 2173 2174 /* Now, if insn doesn't accept our operand, put it into a pseudo. */ 2175 2176 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)) 2177 xop0 = copy_to_mode_reg (mode0, xop0); 2178 2179 if (! (*insn_operand_predicate[icode][0]) (temp, mode)) 2180 temp = gen_reg_rtx (mode); 2181 2182 pat = GEN_FCN (icode) (temp, xop0); 2183 if (pat) 2184 { 2185 if (GET_CODE (pat) == SEQUENCE 2186 && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX)) 2187 { 2188 delete_insns_since (last); 2189 return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp); 2190 } 2191 2192 emit_insn (pat); 2193 2194 return temp; 2195 } 2196 else 2197 delete_insns_since (last); 2198 } 2199 2200 /* It can't be done in this mode. Can we open-code it in a wider mode? */ 2201 2202 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) 2203 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 2204 wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 2205 { 2206 if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing) 2207 { 2208 rtx xop0 = op0; 2209 2210 /* For certain operations, we need not actually extend 2211 the narrow operand, as long as we will truncate the 2212 results to the same narrowness. */ 2213 2214 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, 2215 (unoptab == neg_optab 2216 || unoptab == one_cmpl_optab) 2217 && class == MODE_INT); 2218 2219 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX, 2220 unsignedp); 2221 2222 if (temp) 2223 { 2224 if (class != MODE_INT) 2225 { 2226 if (target == 0) 2227 target = gen_reg_rtx (mode); 2228 convert_move (target, temp, 0); 2229 return target; 2230 } 2231 else 2232 return gen_lowpart (mode, temp); 2233 } 2234 else 2235 delete_insns_since (last); 2236 } 2237 } 2238 2239 /* These can be done a word at a time. */ 2240 if (unoptab == one_cmpl_optab 2241 && class == MODE_INT 2242 && GET_MODE_SIZE (mode) > UNITS_PER_WORD 2243 && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing) 2244 { 2245 int i; 2246 rtx insns; 2247 2248 if (target == 0 || target == op0) 2249 target = gen_reg_rtx (mode); 2250 2251 start_sequence (); 2252 2253 /* Do the actual arithmetic. */ 2254 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++) 2255 { 2256 rtx target_piece = operand_subword (target, i, 1, mode); 2257 rtx x = expand_unop (word_mode, unoptab, 2258 operand_subword_force (op0, i, mode), 2259 target_piece, unsignedp); 2260 if (target_piece != x) 2261 emit_move_insn (target_piece, x); 2262 } 2263 2264 insns = get_insns (); 2265 end_sequence (); 2266 2267 emit_no_conflict_block (insns, target, op0, NULL_RTX, 2268 gen_rtx_fmt_e (unoptab->code, mode, 2269 copy_rtx (op0))); 2270 return target; 2271 } 2272 2273 /* Open-code the complex negation operation. */ 2274 else if (unoptab == neg_optab 2275 && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)) 2276 { 2277 rtx target_piece; 2278 rtx x; 2279 rtx seq; 2280 2281 /* Find the correct mode for the real and imaginary parts */ 2282 enum machine_mode submode 2283 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT, 2284 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT, 2285 0); 2286 2287 if (submode == BLKmode) 2288 abort (); 2289 2290 if (target == 0) 2291 target = gen_reg_rtx (mode); 2292 2293 start_sequence (); 2294 2295 target_piece = gen_imagpart (submode, target); 2296 x = expand_unop (submode, unoptab, 2297 gen_imagpart (submode, op0), 2298 target_piece, unsignedp); 2299 if (target_piece != x) 2300 emit_move_insn (target_piece, x); 2301 2302 target_piece = gen_realpart (submode, target); 2303 x = expand_unop (submode, unoptab, 2304 gen_realpart (submode, op0), 2305 target_piece, unsignedp); 2306 if (target_piece != x) 2307 emit_move_insn (target_piece, x); 2308 2309 seq = get_insns (); 2310 end_sequence (); 2311 2312 emit_no_conflict_block (seq, target, op0, 0, 2313 gen_rtx_fmt_e (unoptab->code, mode, 2314 copy_rtx (op0))); 2315 return target; 2316 } 2317 2318 /* Now try a library call in this mode. */ 2319 if (unoptab->handlers[(int) mode].libfunc) 2320 { 2321 rtx insns; 2322 rtx value; 2323 2324 start_sequence (); 2325 2326 /* Pass 1 for NO_QUEUE so we don't lose any increments 2327 if the libcall is cse'd or moved. */ 2328 value = emit_library_call_value (unoptab->handlers[(int) mode].libfunc, 2329 NULL_RTX, 1, mode, 1, op0, mode); 2330 insns = get_insns (); 2331 end_sequence (); 2332 2333 target = gen_reg_rtx (mode); 2334 emit_libcall_block (insns, target, value, 2335 gen_rtx_fmt_e (unoptab->code, mode, op0)); 2336 2337 return target; 2338 } 2339 2340 /* It can't be done in this mode. Can we do it in a wider mode? */ 2341 2342 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) 2343 { 2344 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 2345 wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 2346 { 2347 if ((unoptab->handlers[(int) wider_mode].insn_code 2348 != CODE_FOR_nothing) 2349 || unoptab->handlers[(int) wider_mode].libfunc) 2350 { 2351 rtx xop0 = op0; 2352 2353 /* For certain operations, we need not actually extend 2354 the narrow operand, as long as we will truncate the 2355 results to the same narrowness. */ 2356 2357 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, 2358 (unoptab == neg_optab 2359 || unoptab == one_cmpl_optab) 2360 && class == MODE_INT); 2361 2362 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX, 2363 unsignedp); 2364 2365 if (temp) 2366 { 2367 if (class != MODE_INT) 2368 { 2369 if (target == 0) 2370 target = gen_reg_rtx (mode); 2371 convert_move (target, temp, 0); 2372 return target; 2373 } 2374 else 2375 return gen_lowpart (mode, temp); 2376 } 2377 else 2378 delete_insns_since (last); 2379 } 2380 } 2381 } 2382 2383 /* If there is no negate operation, try doing a subtract from zero. 2384 The US Software GOFAST library needs this. */ 2385 if (unoptab == neg_optab) 2386 { 2387 rtx temp; 2388 temp = expand_binop (mode, sub_optab, CONST0_RTX (mode), op0, 2389 target, unsignedp, OPTAB_LIB_WIDEN); 2390 if (temp) 2391 return temp; 2392 } 2393 2394 return 0; 2395} 2396 2397/* Emit code to compute the absolute value of OP0, with result to 2398 TARGET if convenient. (TARGET may be 0.) The return value says 2399 where the result actually is to be found. 2400 2401 MODE is the mode of the operand; the mode of the result is 2402 different but can be deduced from MODE. 2403 2404 */ 2405 2406rtx 2407expand_abs (mode, op0, target, safe) 2408 enum machine_mode mode; 2409 rtx op0; 2410 rtx target; 2411 int safe; 2412{ 2413 rtx temp, op1; 2414 2415 /* First try to do it with a special abs instruction. */ 2416 temp = expand_unop (mode, abs_optab, op0, target, 0); 2417 if (temp != 0) 2418 return temp; 2419 2420 /* If this machine has expensive jumps, we can do integer absolute 2421 value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)), 2422 where W is the width of MODE. */ 2423 2424 if (GET_MODE_CLASS (mode) == MODE_INT && BRANCH_COST >= 2) 2425 { 2426 rtx extended = expand_shift (RSHIFT_EXPR, mode, op0, 2427 size_int (GET_MODE_BITSIZE (mode) - 1), 2428 NULL_RTX, 0); 2429 2430 temp = expand_binop (mode, xor_optab, extended, op0, target, 0, 2431 OPTAB_LIB_WIDEN); 2432 if (temp != 0) 2433 temp = expand_binop (mode, sub_optab, temp, extended, target, 0, 2434 OPTAB_LIB_WIDEN); 2435 2436 if (temp != 0) 2437 return temp; 2438 } 2439 2440 /* If that does not win, use conditional jump and negate. */ 2441 2442 /* It is safe to use the target if it is the same 2443 as the source if this is also a pseudo register */ 2444 if (op0 == target && GET_CODE (op0) == REG 2445 && REGNO (op0) >= FIRST_PSEUDO_REGISTER) 2446 safe = 1; 2447 2448 op1 = gen_label_rtx (); 2449 if (target == 0 || ! safe 2450 || GET_MODE (target) != mode 2451 || (GET_CODE (target) == MEM && MEM_VOLATILE_P (target)) 2452 || (GET_CODE (target) == REG 2453 && REGNO (target) < FIRST_PSEUDO_REGISTER)) 2454 target = gen_reg_rtx (mode); 2455 2456 emit_move_insn (target, op0); 2457 NO_DEFER_POP; 2458 2459 /* If this mode is an integer too wide to compare properly, 2460 compare word by word. Rely on CSE to optimize constant cases. */ 2461 if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode)) 2462 do_jump_by_parts_greater_rtx (mode, 0, target, const0_rtx, 2463 NULL_RTX, op1); 2464 else 2465 { 2466 temp = compare_from_rtx (target, CONST0_RTX (mode), GE, 0, mode, 2467 NULL_RTX, 0); 2468 if (temp == const1_rtx) 2469 return target; 2470 else if (temp != const0_rtx) 2471 { 2472 if (bcc_gen_fctn[(int) GET_CODE (temp)] != 0) 2473 emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (temp)]) (op1)); 2474 else 2475 abort (); 2476 } 2477 } 2478 2479 op0 = expand_unop (mode, neg_optab, target, target, 0); 2480 if (op0 != target) 2481 emit_move_insn (target, op0); 2482 emit_label (op1); 2483 OK_DEFER_POP; 2484 return target; 2485} 2486 2487/* Emit code to compute the absolute value of OP0, with result to 2488 TARGET if convenient. (TARGET may be 0.) The return value says 2489 where the result actually is to be found. 2490 2491 MODE is the mode of the operand; the mode of the result is 2492 different but can be deduced from MODE. 2493 2494 UNSIGNEDP is relevant for complex integer modes. */ 2495 2496rtx 2497expand_complex_abs (mode, op0, target, unsignedp) 2498 enum machine_mode mode; 2499 rtx op0; 2500 rtx target; 2501 int unsignedp; 2502{ 2503 enum mode_class class = GET_MODE_CLASS (mode); 2504 enum machine_mode wider_mode; 2505 register rtx temp; 2506 rtx entry_last = get_last_insn (); 2507 rtx last; 2508 rtx pat; 2509 2510 /* Find the correct mode for the real and imaginary parts. */ 2511 enum machine_mode submode 2512 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT, 2513 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT, 2514 0); 2515 2516 if (submode == BLKmode) 2517 abort (); 2518 2519 op0 = protect_from_queue (op0, 0); 2520 2521 if (flag_force_mem) 2522 { 2523 op0 = force_not_mem (op0); 2524 } 2525 2526 last = get_last_insn (); 2527 2528 if (target) 2529 target = protect_from_queue (target, 1); 2530 2531 if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 2532 { 2533 int icode = (int) abs_optab->handlers[(int) mode].insn_code; 2534 enum machine_mode mode0 = insn_operand_mode[icode][1]; 2535 rtx xop0 = op0; 2536 2537 if (target) 2538 temp = target; 2539 else 2540 temp = gen_reg_rtx (submode); 2541 2542 if (GET_MODE (xop0) != VOIDmode 2543 && GET_MODE (xop0) != mode0) 2544 xop0 = convert_to_mode (mode0, xop0, unsignedp); 2545 2546 /* Now, if insn doesn't accept our operand, put it into a pseudo. */ 2547 2548 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)) 2549 xop0 = copy_to_mode_reg (mode0, xop0); 2550 2551 if (! (*insn_operand_predicate[icode][0]) (temp, submode)) 2552 temp = gen_reg_rtx (submode); 2553 2554 pat = GEN_FCN (icode) (temp, xop0); 2555 if (pat) 2556 { 2557 if (GET_CODE (pat) == SEQUENCE 2558 && ! add_equal_note (pat, temp, abs_optab->code, xop0, NULL_RTX)) 2559 { 2560 delete_insns_since (last); 2561 return expand_unop (mode, abs_optab, op0, NULL_RTX, unsignedp); 2562 } 2563 2564 emit_insn (pat); 2565 2566 return temp; 2567 } 2568 else 2569 delete_insns_since (last); 2570 } 2571 2572 /* It can't be done in this mode. Can we open-code it in a wider mode? */ 2573 2574 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 2575 wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 2576 { 2577 if (abs_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing) 2578 { 2579 rtx xop0 = op0; 2580 2581 xop0 = convert_modes (wider_mode, mode, xop0, unsignedp); 2582 temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp); 2583 2584 if (temp) 2585 { 2586 if (class != MODE_COMPLEX_INT) 2587 { 2588 if (target == 0) 2589 target = gen_reg_rtx (submode); 2590 convert_move (target, temp, 0); 2591 return target; 2592 } 2593 else 2594 return gen_lowpart (submode, temp); 2595 } 2596 else 2597 delete_insns_since (last); 2598 } 2599 } 2600 2601 /* Open-code the complex absolute-value operation 2602 if we can open-code sqrt. Otherwise it's not worth while. */ 2603 if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing) 2604 { 2605 rtx real, imag, total; 2606 2607 real = gen_realpart (submode, op0); 2608 imag = gen_imagpart (submode, op0); 2609 2610 /* Square both parts. */ 2611 real = expand_mult (submode, real, real, NULL_RTX, 0); 2612 imag = expand_mult (submode, imag, imag, NULL_RTX, 0); 2613 2614 /* Sum the parts. */ 2615 total = expand_binop (submode, add_optab, real, imag, NULL_RTX, 2616 0, OPTAB_LIB_WIDEN); 2617 2618 /* Get sqrt in TARGET. Set TARGET to where the result is. */ 2619 target = expand_unop (submode, sqrt_optab, total, target, 0); 2620 if (target == 0) 2621 delete_insns_since (last); 2622 else 2623 return target; 2624 } 2625 2626 /* Now try a library call in this mode. */ 2627 if (abs_optab->handlers[(int) mode].libfunc) 2628 { 2629 rtx insns; 2630 rtx value; 2631 2632 start_sequence (); 2633 2634 /* Pass 1 for NO_QUEUE so we don't lose any increments 2635 if the libcall is cse'd or moved. */ 2636 value = emit_library_call_value (abs_optab->handlers[(int) mode].libfunc, 2637 NULL_RTX, 1, submode, 1, op0, mode); 2638 insns = get_insns (); 2639 end_sequence (); 2640 2641 target = gen_reg_rtx (submode); 2642 emit_libcall_block (insns, target, value, 2643 gen_rtx_fmt_e (abs_optab->code, mode, op0)); 2644 2645 return target; 2646 } 2647 2648 /* It can't be done in this mode. Can we do it in a wider mode? */ 2649 2650 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 2651 wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 2652 { 2653 if ((abs_optab->handlers[(int) wider_mode].insn_code 2654 != CODE_FOR_nothing) 2655 || abs_optab->handlers[(int) wider_mode].libfunc) 2656 { 2657 rtx xop0 = op0; 2658 2659 xop0 = convert_modes (wider_mode, mode, xop0, unsignedp); 2660 2661 temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp); 2662 2663 if (temp) 2664 { 2665 if (class != MODE_COMPLEX_INT) 2666 { 2667 if (target == 0) 2668 target = gen_reg_rtx (submode); 2669 convert_move (target, temp, 0); 2670 return target; 2671 } 2672 else 2673 return gen_lowpart (submode, temp); 2674 } 2675 else 2676 delete_insns_since (last); 2677 } 2678 } 2679 2680 delete_insns_since (entry_last); 2681 return 0; 2682} 2683 2684/* Generate an instruction whose insn-code is INSN_CODE, 2685 with two operands: an output TARGET and an input OP0. 2686 TARGET *must* be nonzero, and the output is always stored there. 2687 CODE is an rtx code such that (CODE OP0) is an rtx that describes 2688 the value that is stored into TARGET. */ 2689 2690void 2691emit_unop_insn (icode, target, op0, code) 2692 int icode; 2693 rtx target; 2694 rtx op0; 2695 enum rtx_code code; 2696{ 2697 register rtx temp; 2698 enum machine_mode mode0 = insn_operand_mode[icode][1]; 2699 rtx pat; 2700 2701 temp = target = protect_from_queue (target, 1); 2702 2703 op0 = protect_from_queue (op0, 0); 2704 2705 /* Sign and zero extension from memory is often done specially on 2706 RISC machines, so forcing into a register here can pessimize 2707 code. */ 2708 if (flag_force_mem && code != SIGN_EXTEND && code != ZERO_EXTEND) 2709 op0 = force_not_mem (op0); 2710 2711 /* Now, if insn does not accept our operands, put them into pseudos. */ 2712 2713 if (! (*insn_operand_predicate[icode][1]) (op0, mode0)) 2714 op0 = copy_to_mode_reg (mode0, op0); 2715 2716 if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp)) 2717 || (flag_force_mem && GET_CODE (temp) == MEM)) 2718 temp = gen_reg_rtx (GET_MODE (temp)); 2719 2720 pat = GEN_FCN (icode) (temp, op0); 2721 2722 if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN) 2723 add_equal_note (pat, temp, code, op0, NULL_RTX); 2724 2725 emit_insn (pat); 2726 2727 if (temp != target) 2728 emit_move_insn (target, temp); 2729} 2730 2731/* Emit code to perform a series of operations on a multi-word quantity, one 2732 word at a time. 2733 2734 Such a block is preceded by a CLOBBER of the output, consists of multiple 2735 insns, each setting one word of the output, and followed by a SET copying 2736 the output to itself. 2737 2738 Each of the insns setting words of the output receives a REG_NO_CONFLICT 2739 note indicating that it doesn't conflict with the (also multi-word) 2740 inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL 2741 notes. 2742 2743 INSNS is a block of code generated to perform the operation, not including 2744 the CLOBBER and final copy. All insns that compute intermediate values 2745 are first emitted, followed by the block as described above. 2746 2747 TARGET, OP0, and OP1 are the output and inputs of the operations, 2748 respectively. OP1 may be zero for a unary operation. 2749 2750 EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note 2751 on the last insn. 2752 2753 If TARGET is not a register, INSNS is simply emitted with no special 2754 processing. Likewise if anything in INSNS is not an INSN or if 2755 there is a libcall block inside INSNS. 2756 2757 The final insn emitted is returned. */ 2758 2759rtx 2760emit_no_conflict_block (insns, target, op0, op1, equiv) 2761 rtx insns; 2762 rtx target; 2763 rtx op0, op1; 2764 rtx equiv; 2765{ 2766 rtx prev, next, first, last, insn; 2767 2768 if (GET_CODE (target) != REG || reload_in_progress) 2769 return emit_insns (insns); 2770 else 2771 for (insn = insns; insn; insn = NEXT_INSN (insn)) 2772 if (GET_CODE (insn) != INSN 2773 || find_reg_note (insn, REG_LIBCALL, NULL_RTX)) 2774 return emit_insns (insns); 2775 2776 /* First emit all insns that do not store into words of the output and remove 2777 these from the list. */ 2778 for (insn = insns; insn; insn = next) 2779 { 2780 rtx set = 0; 2781 int i; 2782 2783 next = NEXT_INSN (insn); 2784 2785 if (GET_CODE (PATTERN (insn)) == SET) 2786 set = PATTERN (insn); 2787 else if (GET_CODE (PATTERN (insn)) == PARALLEL) 2788 { 2789 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) 2790 if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET) 2791 { 2792 set = XVECEXP (PATTERN (insn), 0, i); 2793 break; 2794 } 2795 } 2796 2797 if (set == 0) 2798 abort (); 2799 2800 if (! reg_overlap_mentioned_p (target, SET_DEST (set))) 2801 { 2802 if (PREV_INSN (insn)) 2803 NEXT_INSN (PREV_INSN (insn)) = next; 2804 else 2805 insns = next; 2806 2807 if (next) 2808 PREV_INSN (next) = PREV_INSN (insn); 2809 2810 add_insn (insn); 2811 } 2812 } 2813 2814 prev = get_last_insn (); 2815 2816 /* Now write the CLOBBER of the output, followed by the setting of each 2817 of the words, followed by the final copy. */ 2818 if (target != op0 && target != op1) 2819 emit_insn (gen_rtx_CLOBBER (VOIDmode, target)); 2820 2821 for (insn = insns; insn; insn = next) 2822 { 2823 next = NEXT_INSN (insn); 2824 add_insn (insn); 2825 2826 if (op1 && GET_CODE (op1) == REG) 2827 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op1, 2828 REG_NOTES (insn)); 2829 2830 if (op0 && GET_CODE (op0) == REG) 2831 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op0, 2832 REG_NOTES (insn)); 2833 } 2834 2835 if (mov_optab->handlers[(int) GET_MODE (target)].insn_code 2836 != CODE_FOR_nothing) 2837 { 2838 last = emit_move_insn (target, target); 2839 if (equiv) 2840 set_unique_reg_note (last, REG_EQUAL, equiv); 2841 } 2842 else 2843 last = get_last_insn (); 2844 2845 if (prev == 0) 2846 first = get_insns (); 2847 else 2848 first = NEXT_INSN (prev); 2849 2850 /* Encapsulate the block so it gets manipulated as a unit. */ 2851 REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, 2852 REG_NOTES (first)); 2853 REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last)); 2854 2855 return last; 2856} 2857 2858/* Emit code to make a call to a constant function or a library call. 2859 2860 INSNS is a list containing all insns emitted in the call. 2861 These insns leave the result in RESULT. Our block is to copy RESULT 2862 to TARGET, which is logically equivalent to EQUIV. 2863 2864 We first emit any insns that set a pseudo on the assumption that these are 2865 loading constants into registers; doing so allows them to be safely cse'ed 2866 between blocks. Then we emit all the other insns in the block, followed by 2867 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL 2868 note with an operand of EQUIV. 2869 2870 Moving assignments to pseudos outside of the block is done to improve 2871 the generated code, but is not required to generate correct code, 2872 hence being unable to move an assignment is not grounds for not making 2873 a libcall block. There are two reasons why it is safe to leave these 2874 insns inside the block: First, we know that these pseudos cannot be 2875 used in generated RTL outside the block since they are created for 2876 temporary purposes within the block. Second, CSE will not record the 2877 values of anything set inside a libcall block, so we know they must 2878 be dead at the end of the block. 2879 2880 Except for the first group of insns (the ones setting pseudos), the 2881 block is delimited by REG_RETVAL and REG_LIBCALL notes. */ 2882 2883void 2884emit_libcall_block (insns, target, result, equiv) 2885 rtx insns; 2886 rtx target; 2887 rtx result; 2888 rtx equiv; 2889{ 2890 rtx final_dest = target; 2891 rtx prev, next, first, last, insn; 2892 2893 /* If this is a reg with REG_USERVAR_P set, then it could possibly turn 2894 into a MEM later. Protect the libcall block from this change. */ 2895 if (! REG_P (target) || REG_USERVAR_P (target)) 2896 target = gen_reg_rtx (GET_MODE (target)); 2897 2898 /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION 2899 reg note to indicate that this call cannot throw. (Unless there is 2900 already a REG_EH_REGION note.) */ 2901 2902 for (insn = insns; insn; insn = NEXT_INSN (insn)) 2903 { 2904 if (GET_CODE (insn) == CALL_INSN) 2905 { 2906 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX); 2907 if (note == NULL_RTX) 2908 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (-1), 2909 REG_NOTES (insn)); 2910 } 2911 } 2912 2913 /* First emit all insns that set pseudos. Remove them from the list as 2914 we go. Avoid insns that set pseudos which were referenced in previous 2915 insns. These can be generated by move_by_pieces, for example, 2916 to update an address. Similarly, avoid insns that reference things 2917 set in previous insns. */ 2918 2919 for (insn = insns; insn; insn = next) 2920 { 2921 rtx set = single_set (insn); 2922 2923 next = NEXT_INSN (insn); 2924 2925 if (set != 0 && GET_CODE (SET_DEST (set)) == REG 2926 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER 2927 && (insn == insns 2928 || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns)) 2929 && ! reg_used_between_p (SET_DEST (set), insns, insn) 2930 && ! modified_in_p (SET_SRC (set), insns) 2931 && ! modified_between_p (SET_SRC (set), insns, insn)))) 2932 { 2933 if (PREV_INSN (insn)) 2934 NEXT_INSN (PREV_INSN (insn)) = next; 2935 else 2936 insns = next; 2937 2938 if (next) 2939 PREV_INSN (next) = PREV_INSN (insn); 2940 2941 add_insn (insn); 2942 } 2943 } 2944 2945 prev = get_last_insn (); 2946 2947 /* Write the remaining insns followed by the final copy. */ 2948 2949 for (insn = insns; insn; insn = next) 2950 { 2951 next = NEXT_INSN (insn); 2952 2953 add_insn (insn); 2954 } 2955 2956 last = emit_move_insn (target, result); 2957 if (mov_optab->handlers[(int) GET_MODE (target)].insn_code 2958 != CODE_FOR_nothing) 2959 set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv)); 2960 2961 if (final_dest != target) 2962 emit_move_insn (final_dest, target); 2963 2964 if (prev == 0) 2965 first = get_insns (); 2966 else 2967 first = NEXT_INSN (prev); 2968 2969 /* Encapsulate the block so it gets manipulated as a unit. */ 2970 REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, 2971 REG_NOTES (first)); 2972 REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last)); 2973} 2974 2975/* Generate code to store zero in X. */ 2976 2977void 2978emit_clr_insn (x) 2979 rtx x; 2980{ 2981 emit_move_insn (x, const0_rtx); 2982} 2983 2984/* Generate code to store 1 in X 2985 assuming it contains zero beforehand. */ 2986 2987void 2988emit_0_to_1_insn (x) 2989 rtx x; 2990{ 2991 emit_move_insn (x, const1_rtx); 2992} 2993 2994/* Generate code to compare X with Y 2995 so that the condition codes are set. 2996 2997 MODE is the mode of the inputs (in case they are const_int). 2998 UNSIGNEDP nonzero says that X and Y are unsigned; 2999 this matters if they need to be widened. 3000 3001 If they have mode BLKmode, then SIZE specifies the size of both X and Y, 3002 and ALIGN specifies the known shared alignment of X and Y. 3003 3004 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). 3005 It is ignored for fixed-point and block comparisons; 3006 it is used only for floating-point comparisons. */ 3007 3008void 3009emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align) 3010 rtx x, y; 3011 enum rtx_code comparison; 3012 rtx size; 3013 enum machine_mode mode; 3014 int unsignedp; 3015 int align; 3016{ 3017 enum mode_class class; 3018 enum machine_mode wider_mode; 3019 3020 class = GET_MODE_CLASS (mode); 3021 3022 /* They could both be VOIDmode if both args are immediate constants, 3023 but we should fold that at an earlier stage. 3024 With no special code here, this will call abort, 3025 reminding the programmer to implement such folding. */ 3026 3027 if (mode != BLKmode && flag_force_mem) 3028 { 3029 x = force_not_mem (x); 3030 y = force_not_mem (y); 3031 } 3032 3033 /* If we are inside an appropriately-short loop and one operand is an 3034 expensive constant, force it into a register. */ 3035 if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2) 3036 x = force_reg (mode, x); 3037 3038 if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2) 3039 y = force_reg (mode, y); 3040 3041#ifdef HAVE_cc0 3042 /* Abort if we have a non-canonical comparison. The RTL documentation 3043 states that canonical comparisons are required only for targets which 3044 have cc0. */ 3045 if (CONSTANT_P (x) && ! CONSTANT_P (y)) 3046 abort(); 3047#endif 3048 3049 /* Don't let both operands fail to indicate the mode. */ 3050 if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode) 3051 x = force_reg (mode, x); 3052 3053 /* Handle all BLKmode compares. */ 3054 3055 if (mode == BLKmode) 3056 { 3057 emit_queue (); 3058 x = protect_from_queue (x, 0); 3059 y = protect_from_queue (y, 0); 3060 3061 if (size == 0) 3062 abort (); 3063#ifdef HAVE_cmpstrqi 3064 if (HAVE_cmpstrqi 3065 && GET_CODE (size) == CONST_INT 3066 && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode))) 3067 { 3068 enum machine_mode result_mode 3069 = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0]; 3070 rtx result = gen_reg_rtx (result_mode); 3071 emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align))); 3072 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX, 3073 result_mode, 0, 0); 3074 } 3075 else 3076#endif 3077#ifdef HAVE_cmpstrhi 3078 if (HAVE_cmpstrhi 3079 && GET_CODE (size) == CONST_INT 3080 && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode))) 3081 { 3082 enum machine_mode result_mode 3083 = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0]; 3084 rtx result = gen_reg_rtx (result_mode); 3085 emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align))); 3086 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX, 3087 result_mode, 0, 0); 3088 } 3089 else 3090#endif 3091#ifdef HAVE_cmpstrsi 3092 if (HAVE_cmpstrsi) 3093 { 3094 enum machine_mode result_mode 3095 = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0]; 3096 rtx result = gen_reg_rtx (result_mode); 3097 size = protect_from_queue (size, 0); 3098 emit_insn (gen_cmpstrsi (result, x, y, 3099 convert_to_mode (SImode, size, 1), 3100 GEN_INT (align))); 3101 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX, 3102 result_mode, 0, 0); 3103 } 3104 else 3105#endif 3106 { 3107 rtx result; 3108 3109#ifdef TARGET_MEM_FUNCTIONS 3110 emit_library_call (memcmp_libfunc, 0, 3111 TYPE_MODE (integer_type_node), 3, 3112 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, 3113 convert_to_mode (TYPE_MODE (sizetype), size, 3114 TREE_UNSIGNED (sizetype)), 3115 TYPE_MODE (sizetype)); 3116#else 3117 emit_library_call (bcmp_libfunc, 0, 3118 TYPE_MODE (integer_type_node), 3, 3119 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, 3120 convert_to_mode (TYPE_MODE (integer_type_node), 3121 size, 3122 TREE_UNSIGNED (integer_type_node)), 3123 TYPE_MODE (integer_type_node)); 3124#endif 3125 3126 /* Immediately move the result of the libcall into a pseudo 3127 register so reload doesn't clobber the value if it needs 3128 the return register for a spill reg. */ 3129 result = gen_reg_rtx (TYPE_MODE (integer_type_node)); 3130 emit_move_insn (result, 3131 hard_libcall_value (TYPE_MODE (integer_type_node))); 3132 emit_cmp_insn (result, 3133 const0_rtx, comparison, NULL_RTX, 3134 TYPE_MODE (integer_type_node), 0, 0); 3135 } 3136 return; 3137 } 3138 3139 /* Handle some compares against zero. */ 3140 3141 if (y == CONST0_RTX (mode) 3142 && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 3143 { 3144 int icode = (int) tst_optab->handlers[(int) mode].insn_code; 3145 3146 emit_queue (); 3147 x = protect_from_queue (x, 0); 3148 y = protect_from_queue (y, 0); 3149 3150 /* Now, if insn does accept these operands, put them into pseudos. */ 3151 if (! (*insn_operand_predicate[icode][0]) 3152 (x, insn_operand_mode[icode][0])) 3153 x = copy_to_mode_reg (insn_operand_mode[icode][0], x); 3154 3155 emit_insn (GEN_FCN (icode) (x)); 3156 return; 3157 } 3158 3159 /* Handle compares for which there is a directly suitable insn. */ 3160 3161 if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 3162 { 3163 int icode = (int) cmp_optab->handlers[(int) mode].insn_code; 3164 3165 emit_queue (); 3166 x = protect_from_queue (x, 0); 3167 y = protect_from_queue (y, 0); 3168 3169 /* Now, if insn doesn't accept these operands, put them into pseudos. */ 3170 if (! (*insn_operand_predicate[icode][0]) 3171 (x, insn_operand_mode[icode][0])) 3172 x = copy_to_mode_reg (insn_operand_mode[icode][0], x); 3173 3174 if (! (*insn_operand_predicate[icode][1]) 3175 (y, insn_operand_mode[icode][1])) 3176 y = copy_to_mode_reg (insn_operand_mode[icode][1], y); 3177 3178 emit_insn (GEN_FCN (icode) (x, y)); 3179 return; 3180 } 3181 3182 /* Try widening if we can find a direct insn that way. */ 3183 3184 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) 3185 { 3186 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 3187 wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 3188 { 3189 if (cmp_optab->handlers[(int) wider_mode].insn_code 3190 != CODE_FOR_nothing) 3191 { 3192 x = protect_from_queue (x, 0); 3193 y = protect_from_queue (y, 0); 3194 x = convert_modes (wider_mode, mode, x, unsignedp); 3195 y = convert_modes (wider_mode, mode, y, unsignedp); 3196 emit_cmp_insn (x, y, comparison, NULL_RTX, 3197 wider_mode, unsignedp, align); 3198 return; 3199 } 3200 } 3201 } 3202 3203 /* Handle a lib call just for the mode we are using. */ 3204 3205 if (cmp_optab->handlers[(int) mode].libfunc 3206 && class != MODE_FLOAT) 3207 { 3208 rtx libfunc = cmp_optab->handlers[(int) mode].libfunc; 3209 rtx result; 3210 3211 /* If we want unsigned, and this mode has a distinct unsigned 3212 comparison routine, use that. */ 3213 if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc) 3214 libfunc = ucmp_optab->handlers[(int) mode].libfunc; 3215 3216 emit_library_call (libfunc, 1, 3217 word_mode, 2, x, mode, y, mode); 3218 3219 /* Immediately move the result of the libcall into a pseudo 3220 register so reload doesn't clobber the value if it needs 3221 the return register for a spill reg. */ 3222 result = gen_reg_rtx (word_mode); 3223 emit_move_insn (result, hard_libcall_value (word_mode)); 3224 3225 /* Integer comparison returns a result that must be compared against 1, 3226 so that even if we do an unsigned compare afterward, 3227 there is still a value that can represent the result "less than". */ 3228 emit_cmp_insn (result, const1_rtx, 3229 comparison, NULL_RTX, word_mode, unsignedp, 0); 3230 return; 3231 } 3232 3233 if (class == MODE_FLOAT) 3234 emit_float_lib_cmp (x, y, comparison); 3235 3236 else 3237 abort (); 3238} 3239 3240/* Generate code to compare X with Y so that the condition codes are 3241 set and to jump to LABEL if the condition is true. If X is a 3242 constant and Y is not a constant, then the comparison is swapped to 3243 ensure that the comparison RTL has the canonical form. 3244 3245 UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they 3246 need to be widened by emit_cmp_insn. UNSIGNEDP is also used to select 3247 the proper branch condition code. 3248 3249 If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y, 3250 and ALIGN specifies the known shared alignment of X and Y. 3251 3252 MODE is the mode of the inputs (in case they are const_int). 3253 3254 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). It will 3255 be passed unchanged to emit_cmp_insn, then potentially converted into an 3256 unsigned variant based on UNSIGNEDP to select a proper jump instruction. */ 3257 3258void 3259emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, label) 3260 rtx x, y; 3261 enum rtx_code comparison; 3262 rtx size; 3263 enum machine_mode mode; 3264 int unsignedp; 3265 int align; 3266 rtx label; 3267{ 3268 rtx op0; 3269 rtx op1; 3270 3271 if (CONSTANT_P (x)) 3272 { 3273 /* Swap operands and condition to ensure canonical RTL. */ 3274 op0 = y; 3275 op1 = x; 3276 comparison = swap_condition (comparison); 3277 } 3278 else 3279 { 3280 op0 = x; 3281 op1 = y; 3282 } 3283 3284#ifdef HAVE_cc0 3285 /* If OP0 is still a constant, then both X and Y must be constants. Force 3286 X into a register to avoid aborting in emit_cmp_insn due to non-canonical 3287 RTL. */ 3288 if (CONSTANT_P (op0)) 3289 op0 = force_reg (mode, op0); 3290#endif 3291 3292 emit_cmp_insn (op0, op1, comparison, size, mode, unsignedp, align); 3293 3294 if (unsignedp) 3295 comparison = unsigned_condition (comparison); 3296 emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label)); 3297} 3298 3299 3300/* Nonzero if a compare of mode MODE can be done straightforwardly 3301 (without splitting it into pieces). */ 3302 3303int 3304can_compare_p (mode) 3305 enum machine_mode mode; 3306{ 3307 do 3308 { 3309 if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing) 3310 return 1; 3311 mode = GET_MODE_WIDER_MODE (mode); 3312 } while (mode != VOIDmode); 3313 3314 return 0; 3315} 3316 3317/* Emit a library call comparison between floating point X and Y. 3318 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */ 3319 3320void 3321emit_float_lib_cmp (x, y, comparison) 3322 rtx x, y; 3323 enum rtx_code comparison; 3324{ 3325 enum machine_mode mode = GET_MODE (x); 3326 rtx libfunc = 0; 3327 rtx result; 3328 3329 if (mode == HFmode) 3330 switch (comparison) 3331 { 3332 case EQ: 3333 libfunc = eqhf2_libfunc; 3334 break; 3335 3336 case NE: 3337 libfunc = nehf2_libfunc; 3338 break; 3339 3340 case GT: 3341 libfunc = gthf2_libfunc; 3342 break; 3343 3344 case GE: 3345 libfunc = gehf2_libfunc; 3346 break; 3347 3348 case LT: 3349 libfunc = lthf2_libfunc; 3350 break; 3351 3352 case LE: 3353 libfunc = lehf2_libfunc; 3354 break; 3355 3356 default: 3357 break; 3358 } 3359 else if (mode == SFmode) 3360 switch (comparison) 3361 { 3362 case EQ: 3363 libfunc = eqsf2_libfunc; 3364 break; 3365 3366 case NE: 3367 libfunc = nesf2_libfunc; 3368 break; 3369 3370 case GT: 3371 libfunc = gtsf2_libfunc; 3372 break; 3373 3374 case GE: 3375 libfunc = gesf2_libfunc; 3376 break; 3377 3378 case LT: 3379 libfunc = ltsf2_libfunc; 3380 break; 3381 3382 case LE: 3383 libfunc = lesf2_libfunc; 3384 break; 3385 3386 default: 3387 break; 3388 } 3389 else if (mode == DFmode) 3390 switch (comparison) 3391 { 3392 case EQ: 3393 libfunc = eqdf2_libfunc; 3394 break; 3395 3396 case NE: 3397 libfunc = nedf2_libfunc; 3398 break; 3399 3400 case GT: 3401 libfunc = gtdf2_libfunc; 3402 break; 3403 3404 case GE: 3405 libfunc = gedf2_libfunc; 3406 break; 3407 3408 case LT: 3409 libfunc = ltdf2_libfunc; 3410 break; 3411 3412 case LE: 3413 libfunc = ledf2_libfunc; 3414 break; 3415 3416 default: 3417 break; 3418 } 3419 else if (mode == XFmode) 3420 switch (comparison) 3421 { 3422 case EQ: 3423 libfunc = eqxf2_libfunc; 3424 break; 3425 3426 case NE: 3427 libfunc = nexf2_libfunc; 3428 break; 3429 3430 case GT: 3431 libfunc = gtxf2_libfunc; 3432 break; 3433 3434 case GE: 3435 libfunc = gexf2_libfunc; 3436 break; 3437 3438 case LT: 3439 libfunc = ltxf2_libfunc; 3440 break; 3441 3442 case LE: 3443 libfunc = lexf2_libfunc; 3444 break; 3445 3446 default: 3447 break; 3448 } 3449 else if (mode == TFmode) 3450 switch (comparison) 3451 { 3452 case EQ: 3453 libfunc = eqtf2_libfunc; 3454 break; 3455 3456 case NE: 3457 libfunc = netf2_libfunc; 3458 break; 3459 3460 case GT: 3461 libfunc = gttf2_libfunc; 3462 break; 3463 3464 case GE: 3465 libfunc = getf2_libfunc; 3466 break; 3467 3468 case LT: 3469 libfunc = lttf2_libfunc; 3470 break; 3471 3472 case LE: 3473 libfunc = letf2_libfunc; 3474 break; 3475 3476 default: 3477 break; 3478 } 3479 else 3480 { 3481 enum machine_mode wider_mode; 3482 3483 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 3484 wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 3485 { 3486 if ((cmp_optab->handlers[(int) wider_mode].insn_code 3487 != CODE_FOR_nothing) 3488 || (cmp_optab->handlers[(int) wider_mode].libfunc != 0)) 3489 { 3490 x = protect_from_queue (x, 0); 3491 y = protect_from_queue (y, 0); 3492 x = convert_to_mode (wider_mode, x, 0); 3493 y = convert_to_mode (wider_mode, y, 0); 3494 emit_float_lib_cmp (x, y, comparison); 3495 return; 3496 } 3497 } 3498 abort (); 3499 } 3500 3501 if (libfunc == 0) 3502 abort (); 3503 3504 emit_library_call (libfunc, 1, 3505 word_mode, 2, x, mode, y, mode); 3506 3507 /* Immediately move the result of the libcall into a pseudo 3508 register so reload doesn't clobber the value if it needs 3509 the return register for a spill reg. */ 3510 result = gen_reg_rtx (word_mode); 3511 emit_move_insn (result, hard_libcall_value (word_mode)); 3512 3513 emit_cmp_insn (result, const0_rtx, comparison, 3514 NULL_RTX, word_mode, 0, 0); 3515} 3516 3517/* Generate code to indirectly jump to a location given in the rtx LOC. */ 3518 3519void 3520emit_indirect_jump (loc) 3521 rtx loc; 3522{ 3523 if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0]) 3524 (loc, Pmode))) 3525 loc = copy_to_mode_reg (Pmode, loc); 3526 3527 emit_jump_insn (gen_indirect_jump (loc)); 3528 emit_barrier (); 3529} 3530 3531#ifdef HAVE_conditional_move 3532 3533/* Emit a conditional move instruction if the machine supports one for that 3534 condition and machine mode. 3535 3536 OP0 and OP1 are the operands that should be compared using CODE. CMODE is 3537 the mode to use should they be constants. If it is VOIDmode, they cannot 3538 both be constants. 3539 3540 OP2 should be stored in TARGET if the comparison is true, otherwise OP3 3541 should be stored there. MODE is the mode to use should they be constants. 3542 If it is VOIDmode, they cannot both be constants. 3543 3544 The result is either TARGET (perhaps modified) or NULL_RTX if the operation 3545 is not supported. */ 3546 3547rtx 3548emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode, 3549 unsignedp) 3550 rtx target; 3551 enum rtx_code code; 3552 rtx op0, op1; 3553 enum machine_mode cmode; 3554 rtx op2, op3; 3555 enum machine_mode mode; 3556 int unsignedp; 3557{ 3558 rtx tem, subtarget, comparison, insn; 3559 enum insn_code icode; 3560 3561 /* If one operand is constant, make it the second one. Only do this 3562 if the other operand is not constant as well. */ 3563 3564 if ((CONSTANT_P (op0) && ! CONSTANT_P (op1)) 3565 || (GET_CODE (op0) == CONST_INT && GET_CODE (op1) != CONST_INT)) 3566 { 3567 tem = op0; 3568 op0 = op1; 3569 op1 = tem; 3570 code = swap_condition (code); 3571 } 3572 3573 if (cmode == VOIDmode) 3574 cmode = GET_MODE (op0); 3575 3576 if (((CONSTANT_P (op2) && ! CONSTANT_P (op3)) 3577 || (GET_CODE (op2) == CONST_INT && GET_CODE (op3) != CONST_INT)) 3578 && (GET_MODE_CLASS (GET_MODE (op1)) != MODE_FLOAT 3579 || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT || flag_fast_math)) 3580 { 3581 tem = op2; 3582 op2 = op3; 3583 op3 = tem; 3584 code = reverse_condition (code); 3585 } 3586 3587 if (mode == VOIDmode) 3588 mode = GET_MODE (op2); 3589 3590 icode = movcc_gen_code[mode]; 3591 3592 if (icode == CODE_FOR_nothing) 3593 return 0; 3594 3595 if (flag_force_mem) 3596 { 3597 op2 = force_not_mem (op2); 3598 op3 = force_not_mem (op3); 3599 } 3600 3601 if (target) 3602 target = protect_from_queue (target, 1); 3603 else 3604 target = gen_reg_rtx (mode); 3605 3606 subtarget = target; 3607 3608 emit_queue (); 3609 3610 op2 = protect_from_queue (op2, 0); 3611 op3 = protect_from_queue (op3, 0); 3612 3613 /* If the insn doesn't accept these operands, put them in pseudos. */ 3614 3615 if (! (*insn_operand_predicate[icode][0]) 3616 (subtarget, insn_operand_mode[icode][0])) 3617 subtarget = gen_reg_rtx (insn_operand_mode[icode][0]); 3618 3619 if (! (*insn_operand_predicate[icode][2]) 3620 (op2, insn_operand_mode[icode][2])) 3621 op2 = copy_to_mode_reg (insn_operand_mode[icode][2], op2); 3622 3623 if (! (*insn_operand_predicate[icode][3]) 3624 (op3, insn_operand_mode[icode][3])) 3625 op3 = copy_to_mode_reg (insn_operand_mode[icode][3], op3); 3626 3627 /* Everything should now be in the suitable form, so emit the compare insn 3628 and then the conditional move. */ 3629 3630 comparison 3631 = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX, 0); 3632 3633 /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)? */ 3634 if (GET_CODE (comparison) != code) 3635 /* This shouldn't happen. */ 3636 abort (); 3637 3638 insn = GEN_FCN (icode) (subtarget, comparison, op2, op3); 3639 3640 /* If that failed, then give up. */ 3641 if (insn == 0) 3642 return 0; 3643 3644 emit_insn (insn); 3645 3646 if (subtarget != target) 3647 convert_move (target, subtarget, 0); 3648 3649 return target; 3650} 3651 3652/* Return non-zero if a conditional move of mode MODE is supported. 3653 3654 This function is for combine so it can tell whether an insn that looks 3655 like a conditional move is actually supported by the hardware. If we 3656 guess wrong we lose a bit on optimization, but that's it. */ 3657/* ??? sparc64 supports conditionally moving integers values based on fp 3658 comparisons, and vice versa. How do we handle them? */ 3659 3660int 3661can_conditionally_move_p (mode) 3662 enum machine_mode mode; 3663{ 3664 if (movcc_gen_code[mode] != CODE_FOR_nothing) 3665 return 1; 3666 3667 return 0; 3668} 3669 3670#endif /* HAVE_conditional_move */ 3671 3672/* These three functions generate an insn body and return it 3673 rather than emitting the insn. 3674 3675 They do not protect from queued increments, 3676 because they may be used 1) in protect_from_queue itself 3677 and 2) in other passes where there is no queue. */ 3678 3679/* Generate and return an insn body to add Y to X. */ 3680 3681rtx 3682gen_add2_insn (x, y) 3683 rtx x, y; 3684{ 3685 int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code; 3686 3687 if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0]) 3688 || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1]) 3689 || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2])) 3690 abort (); 3691 3692 return (GEN_FCN (icode) (x, x, y)); 3693} 3694 3695int 3696have_add2_insn (mode) 3697 enum machine_mode mode; 3698{ 3699 return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing; 3700} 3701 3702/* Generate and return an insn body to subtract Y from X. */ 3703 3704rtx 3705gen_sub2_insn (x, y) 3706 rtx x, y; 3707{ 3708 int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code; 3709 3710 if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0]) 3711 || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1]) 3712 || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2])) 3713 abort (); 3714 3715 return (GEN_FCN (icode) (x, x, y)); 3716} 3717 3718int 3719have_sub2_insn (mode) 3720 enum machine_mode mode; 3721{ 3722 return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing; 3723} 3724 3725/* Generate the body of an instruction to copy Y into X. 3726 It may be a SEQUENCE, if one insn isn't enough. */ 3727 3728rtx 3729gen_move_insn (x, y) 3730 rtx x, y; 3731{ 3732 register enum machine_mode mode = GET_MODE (x); 3733 enum insn_code insn_code; 3734 rtx seq; 3735 3736 if (mode == VOIDmode) 3737 mode = GET_MODE (y); 3738 3739 insn_code = mov_optab->handlers[(int) mode].insn_code; 3740 3741 /* Handle MODE_CC modes: If we don't have a special move insn for this mode, 3742 find a mode to do it in. If we have a movcc, use it. Otherwise, 3743 find the MODE_INT mode of the same width. */ 3744 3745 if (GET_MODE_CLASS (mode) == MODE_CC && insn_code == CODE_FOR_nothing) 3746 { 3747 enum machine_mode tmode = VOIDmode; 3748 rtx x1 = x, y1 = y; 3749 3750 if (mode != CCmode 3751 && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing) 3752 tmode = CCmode; 3753 else 3754 for (tmode = QImode; tmode != VOIDmode; 3755 tmode = GET_MODE_WIDER_MODE (tmode)) 3756 if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode)) 3757 break; 3758 3759 if (tmode == VOIDmode) 3760 abort (); 3761 3762 /* Get X and Y in TMODE. We can't use gen_lowpart here because it 3763 may call change_address which is not appropriate if we were 3764 called when a reload was in progress. We don't have to worry 3765 about changing the address since the size in bytes is supposed to 3766 be the same. Copy the MEM to change the mode and move any 3767 substitutions from the old MEM to the new one. */ 3768 3769 if (reload_in_progress) 3770 { 3771 x = gen_lowpart_common (tmode, x1); 3772 if (x == 0 && GET_CODE (x1) == MEM) 3773 { 3774 x = gen_rtx_MEM (tmode, XEXP (x1, 0)); 3775 RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1); 3776 MEM_COPY_ATTRIBUTES (x, x1); 3777 copy_replacements (x1, x); 3778 } 3779 3780 y = gen_lowpart_common (tmode, y1); 3781 if (y == 0 && GET_CODE (y1) == MEM) 3782 { 3783 y = gen_rtx_MEM (tmode, XEXP (y1, 0)); 3784 RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1); 3785 MEM_COPY_ATTRIBUTES (y, y1); 3786 copy_replacements (y1, y); 3787 } 3788 } 3789 else 3790 { 3791 x = gen_lowpart (tmode, x); 3792 y = gen_lowpart (tmode, y); 3793 } 3794 3795 insn_code = mov_optab->handlers[(int) tmode].insn_code; 3796 return (GEN_FCN (insn_code) (x, y)); 3797 } 3798 3799 start_sequence (); 3800 emit_move_insn_1 (x, y); 3801 seq = gen_sequence (); 3802 end_sequence (); 3803 return seq; 3804} 3805 3806/* Return the insn code used to extend FROM_MODE to TO_MODE. 3807 UNSIGNEDP specifies zero-extension instead of sign-extension. If 3808 no such operation exists, CODE_FOR_nothing will be returned. */ 3809 3810enum insn_code 3811can_extend_p (to_mode, from_mode, unsignedp) 3812 enum machine_mode to_mode, from_mode; 3813 int unsignedp; 3814{ 3815 return extendtab[(int) to_mode][(int) from_mode][unsignedp]; 3816} 3817 3818/* Generate the body of an insn to extend Y (with mode MFROM) 3819 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */ 3820 3821rtx 3822gen_extend_insn (x, y, mto, mfrom, unsignedp) 3823 rtx x, y; 3824 enum machine_mode mto, mfrom; 3825 int unsignedp; 3826{ 3827 return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y)); 3828} 3829 3830/* can_fix_p and can_float_p say whether the target machine 3831 can directly convert a given fixed point type to 3832 a given floating point type, or vice versa. 3833 The returned value is the CODE_FOR_... value to use, 3834 or CODE_FOR_nothing if these modes cannot be directly converted. 3835 3836 *TRUNCP_PTR is set to 1 if it is necessary to output 3837 an explicit FTRUNC insn before the fix insn; otherwise 0. */ 3838 3839static enum insn_code 3840can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr) 3841 enum machine_mode fltmode, fixmode; 3842 int unsignedp; 3843 int *truncp_ptr; 3844{ 3845 *truncp_ptr = 0; 3846 if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing) 3847 return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp]; 3848 3849 if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing) 3850 { 3851 *truncp_ptr = 1; 3852 return fixtab[(int) fltmode][(int) fixmode][unsignedp]; 3853 } 3854 return CODE_FOR_nothing; 3855} 3856 3857static enum insn_code 3858can_float_p (fltmode, fixmode, unsignedp) 3859 enum machine_mode fixmode, fltmode; 3860 int unsignedp; 3861{ 3862 return floattab[(int) fltmode][(int) fixmode][unsignedp]; 3863} 3864 3865/* Generate code to convert FROM to floating point 3866 and store in TO. FROM must be fixed point and not VOIDmode. 3867 UNSIGNEDP nonzero means regard FROM as unsigned. 3868 Normally this is done by correcting the final value 3869 if it is negative. */ 3870 3871void 3872expand_float (to, from, unsignedp) 3873 rtx to, from; 3874 int unsignedp; 3875{ 3876 enum insn_code icode; 3877 register rtx target = to; 3878 enum machine_mode fmode, imode; 3879 3880 /* Crash now, because we won't be able to decide which mode to use. */ 3881 if (GET_MODE (from) == VOIDmode) 3882 abort (); 3883 3884 /* Look for an insn to do the conversion. Do it in the specified 3885 modes if possible; otherwise convert either input, output or both to 3886 wider mode. If the integer mode is wider than the mode of FROM, 3887 we can do the conversion signed even if the input is unsigned. */ 3888 3889 for (imode = GET_MODE (from); imode != VOIDmode; 3890 imode = GET_MODE_WIDER_MODE (imode)) 3891 for (fmode = GET_MODE (to); fmode != VOIDmode; 3892 fmode = GET_MODE_WIDER_MODE (fmode)) 3893 { 3894 int doing_unsigned = unsignedp; 3895 3896 icode = can_float_p (fmode, imode, unsignedp); 3897 if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp) 3898 icode = can_float_p (fmode, imode, 0), doing_unsigned = 0; 3899 3900 if (icode != CODE_FOR_nothing) 3901 { 3902 to = protect_from_queue (to, 1); 3903 from = protect_from_queue (from, 0); 3904 3905 if (imode != GET_MODE (from)) 3906 from = convert_to_mode (imode, from, unsignedp); 3907 3908 if (fmode != GET_MODE (to)) 3909 target = gen_reg_rtx (fmode); 3910 3911 emit_unop_insn (icode, target, from, 3912 doing_unsigned ? UNSIGNED_FLOAT : FLOAT); 3913 3914 if (target != to) 3915 convert_move (to, target, 0); 3916 return; 3917 } 3918 } 3919 3920#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) 3921 3922 /* Unsigned integer, and no way to convert directly. 3923 Convert as signed, then conditionally adjust the result. */ 3924 if (unsignedp) 3925 { 3926 rtx label = gen_label_rtx (); 3927 rtx temp; 3928 REAL_VALUE_TYPE offset; 3929 3930 emit_queue (); 3931 3932 to = protect_from_queue (to, 1); 3933 from = protect_from_queue (from, 0); 3934 3935 if (flag_force_mem) 3936 from = force_not_mem (from); 3937 3938 /* Look for a usable floating mode FMODE wider than the source and at 3939 least as wide as the target. Using FMODE will avoid rounding woes 3940 with unsigned values greater than the signed maximum value. */ 3941 3942 for (fmode = GET_MODE (to); fmode != VOIDmode; 3943 fmode = GET_MODE_WIDER_MODE (fmode)) 3944 if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode) 3945 && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing) 3946 break; 3947 3948 if (fmode == VOIDmode) 3949 { 3950 /* There is no such mode. Pretend the target is wide enough. */ 3951 fmode = GET_MODE (to); 3952 3953 /* Avoid double-rounding when TO is narrower than FROM. */ 3954 if ((significand_size (fmode) + 1) 3955 < GET_MODE_BITSIZE (GET_MODE (from))) 3956 { 3957 rtx temp1; 3958 rtx neglabel = gen_label_rtx (); 3959 3960 /* Don't use TARGET if it isn't a register, is a hard register, 3961 or is the wrong mode. */ 3962 if (GET_CODE (target) != REG 3963 || REGNO (target) < FIRST_PSEUDO_REGISTER 3964 || GET_MODE (target) != fmode) 3965 target = gen_reg_rtx (fmode); 3966 3967 imode = GET_MODE (from); 3968 do_pending_stack_adjust (); 3969 3970 /* Test whether the sign bit is set. */ 3971 emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, imode, 0, 0); 3972 emit_jump_insn (gen_blt (neglabel)); 3973 3974 /* The sign bit is not set. Convert as signed. */ 3975 expand_float (target, from, 0); 3976 emit_jump_insn (gen_jump (label)); 3977 emit_barrier (); 3978 3979 /* The sign bit is set. 3980 Convert to a usable (positive signed) value by shifting right 3981 one bit, while remembering if a nonzero bit was shifted 3982 out; i.e., compute (from & 1) | (from >> 1). */ 3983 3984 emit_label (neglabel); 3985 temp = expand_binop (imode, and_optab, from, const1_rtx, 3986 NULL_RTX, 1, OPTAB_LIB_WIDEN); 3987 temp1 = expand_shift (RSHIFT_EXPR, imode, from, integer_one_node, 3988 NULL_RTX, 1); 3989 temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1, 3990 OPTAB_LIB_WIDEN); 3991 expand_float (target, temp, 0); 3992 3993 /* Multiply by 2 to undo the shift above. */ 3994 temp = expand_binop (fmode, add_optab, target, target, 3995 target, 0, OPTAB_LIB_WIDEN); 3996 if (temp != target) 3997 emit_move_insn (target, temp); 3998 3999 do_pending_stack_adjust (); 4000 emit_label (label); 4001 goto done; 4002 } 4003 } 4004 4005 /* If we are about to do some arithmetic to correct for an 4006 unsigned operand, do it in a pseudo-register. */ 4007 4008 if (GET_MODE (to) != fmode 4009 || GET_CODE (to) != REG || REGNO (to) < FIRST_PSEUDO_REGISTER) 4010 target = gen_reg_rtx (fmode); 4011 4012 /* Convert as signed integer to floating. */ 4013 expand_float (target, from, 0); 4014 4015 /* If FROM is negative (and therefore TO is negative), 4016 correct its value by 2**bitwidth. */ 4017 4018 do_pending_stack_adjust (); 4019 emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from), 4020 0, 0, label); 4021 4022 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1). 4023 Rather than setting up a dconst_dot_5, let's hope SCO 4024 fixes the bug. */ 4025 offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from))); 4026 temp = expand_binop (fmode, add_optab, target, 4027 CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode), 4028 target, 0, OPTAB_LIB_WIDEN); 4029 if (temp != target) 4030 emit_move_insn (target, temp); 4031 4032 do_pending_stack_adjust (); 4033 emit_label (label); 4034 goto done; 4035 } 4036#endif 4037 4038 /* No hardware instruction available; call a library routine to convert from 4039 SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */ 4040 { 4041 rtx libfcn; 4042 rtx insns; 4043 rtx value; 4044 4045 to = protect_from_queue (to, 1); 4046 from = protect_from_queue (from, 0); 4047 4048 if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode)) 4049 from = convert_to_mode (SImode, from, unsignedp); 4050 4051 if (flag_force_mem) 4052 from = force_not_mem (from); 4053 4054 if (GET_MODE (to) == SFmode) 4055 { 4056 if (GET_MODE (from) == SImode) 4057 libfcn = floatsisf_libfunc; 4058 else if (GET_MODE (from) == DImode) 4059 libfcn = floatdisf_libfunc; 4060 else if (GET_MODE (from) == TImode) 4061 libfcn = floattisf_libfunc; 4062 else 4063 abort (); 4064 } 4065 else if (GET_MODE (to) == DFmode) 4066 { 4067 if (GET_MODE (from) == SImode) 4068 libfcn = floatsidf_libfunc; 4069 else if (GET_MODE (from) == DImode) 4070 libfcn = floatdidf_libfunc; 4071 else if (GET_MODE (from) == TImode) 4072 libfcn = floattidf_libfunc; 4073 else 4074 abort (); 4075 } 4076 else if (GET_MODE (to) == XFmode) 4077 { 4078 if (GET_MODE (from) == SImode) 4079 libfcn = floatsixf_libfunc; 4080 else if (GET_MODE (from) == DImode) 4081 libfcn = floatdixf_libfunc; 4082 else if (GET_MODE (from) == TImode) 4083 libfcn = floattixf_libfunc; 4084 else 4085 abort (); 4086 } 4087 else if (GET_MODE (to) == TFmode) 4088 { 4089 if (GET_MODE (from) == SImode) 4090 libfcn = floatsitf_libfunc; 4091 else if (GET_MODE (from) == DImode) 4092 libfcn = floatditf_libfunc; 4093 else if (GET_MODE (from) == TImode) 4094 libfcn = floattitf_libfunc; 4095 else 4096 abort (); 4097 } 4098 else 4099 abort (); 4100 4101 start_sequence (); 4102 4103 value = emit_library_call_value (libfcn, NULL_RTX, 1, 4104 GET_MODE (to), 4105 1, from, GET_MODE (from)); 4106 insns = get_insns (); 4107 end_sequence (); 4108 4109 emit_libcall_block (insns, target, value, 4110 gen_rtx_FLOAT (GET_MODE (to), from)); 4111 } 4112 4113 done: 4114 4115 /* Copy result to requested destination 4116 if we have been computing in a temp location. */ 4117 4118 if (target != to) 4119 { 4120 if (GET_MODE (target) == GET_MODE (to)) 4121 emit_move_insn (to, target); 4122 else 4123 convert_move (to, target, 0); 4124 } 4125} 4126 4127/* expand_fix: generate code to convert FROM to fixed point 4128 and store in TO. FROM must be floating point. */ 4129 4130static rtx 4131ftruncify (x) 4132 rtx x; 4133{ 4134 rtx temp = gen_reg_rtx (GET_MODE (x)); 4135 return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0); 4136} 4137 4138void 4139expand_fix (to, from, unsignedp) 4140 register rtx to, from; 4141 int unsignedp; 4142{ 4143 enum insn_code icode; 4144 register rtx target = to; 4145 enum machine_mode fmode, imode; 4146 int must_trunc = 0; 4147 rtx libfcn = 0; 4148 4149 /* We first try to find a pair of modes, one real and one integer, at 4150 least as wide as FROM and TO, respectively, in which we can open-code 4151 this conversion. If the integer mode is wider than the mode of TO, 4152 we can do the conversion either signed or unsigned. */ 4153 4154 for (imode = GET_MODE (to); imode != VOIDmode; 4155 imode = GET_MODE_WIDER_MODE (imode)) 4156 for (fmode = GET_MODE (from); fmode != VOIDmode; 4157 fmode = GET_MODE_WIDER_MODE (fmode)) 4158 { 4159 int doing_unsigned = unsignedp; 4160 4161 icode = can_fix_p (imode, fmode, unsignedp, &must_trunc); 4162 if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp) 4163 icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0; 4164 4165 if (icode != CODE_FOR_nothing) 4166 { 4167 to = protect_from_queue (to, 1); 4168 from = protect_from_queue (from, 0); 4169 4170 if (fmode != GET_MODE (from)) 4171 from = convert_to_mode (fmode, from, 0); 4172 4173 if (must_trunc) 4174 from = ftruncify (from); 4175 4176 if (imode != GET_MODE (to)) 4177 target = gen_reg_rtx (imode); 4178 4179 emit_unop_insn (icode, target, from, 4180 doing_unsigned ? UNSIGNED_FIX : FIX); 4181 if (target != to) 4182 convert_move (to, target, unsignedp); 4183 return; 4184 } 4185 } 4186 4187#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) 4188 /* For an unsigned conversion, there is one more way to do it. 4189 If we have a signed conversion, we generate code that compares 4190 the real value to the largest representable positive number. If if 4191 is smaller, the conversion is done normally. Otherwise, subtract 4192 one plus the highest signed number, convert, and add it back. 4193 4194 We only need to check all real modes, since we know we didn't find 4195 anything with a wider integer mode. */ 4196 4197 if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT) 4198 for (fmode = GET_MODE (from); fmode != VOIDmode; 4199 fmode = GET_MODE_WIDER_MODE (fmode)) 4200 /* Make sure we won't lose significant bits doing this. */ 4201 if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to)) 4202 && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0, 4203 &must_trunc)) 4204 { 4205 int bitsize; 4206 REAL_VALUE_TYPE offset; 4207 rtx limit, lab1, lab2, insn; 4208 4209 bitsize = GET_MODE_BITSIZE (GET_MODE (to)); 4210 offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1); 4211 limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode); 4212 lab1 = gen_label_rtx (); 4213 lab2 = gen_label_rtx (); 4214 4215 emit_queue (); 4216 to = protect_from_queue (to, 1); 4217 from = protect_from_queue (from, 0); 4218 4219 if (flag_force_mem) 4220 from = force_not_mem (from); 4221 4222 if (fmode != GET_MODE (from)) 4223 from = convert_to_mode (fmode, from, 0); 4224 4225 /* See if we need to do the subtraction. */ 4226 do_pending_stack_adjust (); 4227 emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from), 4228 0, 0, lab1); 4229 4230 /* If not, do the signed "fix" and branch around fixup code. */ 4231 expand_fix (to, from, 0); 4232 emit_jump_insn (gen_jump (lab2)); 4233 emit_barrier (); 4234 4235 /* Otherwise, subtract 2**(N-1), convert to signed number, 4236 then add 2**(N-1). Do the addition using XOR since this 4237 will often generate better code. */ 4238 emit_label (lab1); 4239 target = expand_binop (GET_MODE (from), sub_optab, from, limit, 4240 NULL_RTX, 0, OPTAB_LIB_WIDEN); 4241 expand_fix (to, target, 0); 4242 target = expand_binop (GET_MODE (to), xor_optab, to, 4243 GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)), 4244 to, 1, OPTAB_LIB_WIDEN); 4245 4246 if (target != to) 4247 emit_move_insn (to, target); 4248 4249 emit_label (lab2); 4250 4251 if (mov_optab->handlers[(int) GET_MODE (to)].insn_code 4252 != CODE_FOR_nothing) 4253 { 4254 /* Make a place for a REG_NOTE and add it. */ 4255 insn = emit_move_insn (to, to); 4256 set_unique_reg_note (insn, 4257 REG_EQUAL, 4258 gen_rtx_fmt_e (UNSIGNED_FIX, 4259 GET_MODE (to), 4260 copy_rtx (from))); 4261 } 4262 return; 4263 } 4264#endif 4265 4266 /* We can't do it with an insn, so use a library call. But first ensure 4267 that the mode of TO is at least as wide as SImode, since those are the 4268 only library calls we know about. */ 4269 4270 if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode)) 4271 { 4272 target = gen_reg_rtx (SImode); 4273 4274 expand_fix (target, from, unsignedp); 4275 } 4276 else if (GET_MODE (from) == SFmode) 4277 { 4278 if (GET_MODE (to) == SImode) 4279 libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc; 4280 else if (GET_MODE (to) == DImode) 4281 libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc; 4282 else if (GET_MODE (to) == TImode) 4283 libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc; 4284 else 4285 abort (); 4286 } 4287 else if (GET_MODE (from) == DFmode) 4288 { 4289 if (GET_MODE (to) == SImode) 4290 libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc; 4291 else if (GET_MODE (to) == DImode) 4292 libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc; 4293 else if (GET_MODE (to) == TImode) 4294 libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc; 4295 else 4296 abort (); 4297 } 4298 else if (GET_MODE (from) == XFmode) 4299 { 4300 if (GET_MODE (to) == SImode) 4301 libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc; 4302 else if (GET_MODE (to) == DImode) 4303 libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc; 4304 else if (GET_MODE (to) == TImode) 4305 libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc; 4306 else 4307 abort (); 4308 } 4309 else if (GET_MODE (from) == TFmode) 4310 { 4311 if (GET_MODE (to) == SImode) 4312 libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc; 4313 else if (GET_MODE (to) == DImode) 4314 libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc; 4315 else if (GET_MODE (to) == TImode) 4316 libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc; 4317 else 4318 abort (); 4319 } 4320 else 4321 abort (); 4322 4323 if (libfcn) 4324 { 4325 rtx insns; 4326 rtx value; 4327 4328 to = protect_from_queue (to, 1); 4329 from = protect_from_queue (from, 0); 4330 4331 if (flag_force_mem) 4332 from = force_not_mem (from); 4333 4334 start_sequence (); 4335 4336 value = emit_library_call_value (libfcn, NULL_RTX, 1, GET_MODE (to), 4337 4338 1, from, GET_MODE (from)); 4339 insns = get_insns (); 4340 end_sequence (); 4341 4342 emit_libcall_block (insns, target, value, 4343 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX, 4344 GET_MODE (to), from)); 4345 } 4346 4347 if (target != to) 4348 { 4349 if (GET_MODE (to) == GET_MODE (target)) 4350 emit_move_insn (to, target); 4351 else 4352 convert_move (to, target, 0); 4353 } 4354} 4355 4356static optab 4357init_optab (code) 4358 enum rtx_code code; 4359{ 4360 int i; 4361 optab op = (optab) xmalloc (sizeof (struct optab)); 4362 op->code = code; 4363 for (i = 0; i < NUM_MACHINE_MODES; i++) 4364 { 4365 op->handlers[i].insn_code = CODE_FOR_nothing; 4366 op->handlers[i].libfunc = 0; 4367 } 4368 4369 if (code != UNKNOWN) 4370 code_to_optab[(int) code] = op; 4371 4372 return op; 4373} 4374 4375/* Initialize the libfunc fields of an entire group of entries in some 4376 optab. Each entry is set equal to a string consisting of a leading 4377 pair of underscores followed by a generic operation name followed by 4378 a mode name (downshifted to lower case) followed by a single character 4379 representing the number of operands for the given operation (which is 4380 usually one of the characters '2', '3', or '4'). 4381 4382 OPTABLE is the table in which libfunc fields are to be initialized. 4383 FIRST_MODE is the first machine mode index in the given optab to 4384 initialize. 4385 LAST_MODE is the last machine mode index in the given optab to 4386 initialize. 4387 OPNAME is the generic (string) name of the operation. 4388 SUFFIX is the character which specifies the number of operands for 4389 the given generic operation. 4390*/ 4391 4392static void 4393init_libfuncs (optable, first_mode, last_mode, opname, suffix) 4394 register optab optable; 4395 register int first_mode; 4396 register int last_mode; 4397 register const char *opname; 4398 register int suffix; 4399{ 4400 register int mode; 4401 register unsigned opname_len = strlen (opname); 4402 4403 for (mode = first_mode; (int) mode <= (int) last_mode; 4404 mode = (enum machine_mode) ((int) mode + 1)) 4405 { 4406 register char *mname = mode_name[(int) mode]; 4407 register unsigned mname_len = strlen (mname); 4408 register char *libfunc_name 4409 = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1); 4410 register char *p; 4411 register const char *q; 4412 4413 p = libfunc_name; 4414 *p++ = '_'; 4415 *p++ = '_'; 4416 for (q = opname; *q; ) 4417 *p++ = *q++; 4418 for (q = mname; *q; q++) 4419 *p++ = tolower ((unsigned char)*q); 4420 *p++ = suffix; 4421 *p++ = '\0'; 4422 optable->handlers[(int) mode].libfunc 4423 = gen_rtx_SYMBOL_REF (Pmode, libfunc_name); 4424 } 4425} 4426 4427/* Initialize the libfunc fields of an entire group of entries in some 4428 optab which correspond to all integer mode operations. The parameters 4429 have the same meaning as similarly named ones for the `init_libfuncs' 4430 routine. (See above). */ 4431 4432static void 4433init_integral_libfuncs (optable, opname, suffix) 4434 register optab optable; 4435 register const char *opname; 4436 register int suffix; 4437{ 4438 init_libfuncs (optable, SImode, TImode, opname, suffix); 4439} 4440 4441/* Initialize the libfunc fields of an entire group of entries in some 4442 optab which correspond to all real mode operations. The parameters 4443 have the same meaning as similarly named ones for the `init_libfuncs' 4444 routine. (See above). */ 4445 4446static void 4447init_floating_libfuncs (optable, opname, suffix) 4448 register optab optable; 4449 register const char *opname; 4450 register int suffix; 4451{ 4452 init_libfuncs (optable, SFmode, TFmode, opname, suffix); 4453} 4454 4455 4456/* Call this once to initialize the contents of the optabs 4457 appropriately for the current target machine. */ 4458 4459void 4460init_optabs () 4461{ 4462 int i; 4463#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC 4464 int j; 4465#endif 4466 4467 enum insn_code *p; 4468 4469 /* Start by initializing all tables to contain CODE_FOR_nothing. */ 4470 4471 for (p = fixtab[0][0]; 4472 p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]); 4473 p++) 4474 *p = CODE_FOR_nothing; 4475 4476 for (p = fixtrunctab[0][0]; 4477 p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]); 4478 p++) 4479 *p = CODE_FOR_nothing; 4480 4481 for (p = floattab[0][0]; 4482 p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]); 4483 p++) 4484 *p = CODE_FOR_nothing; 4485 4486 for (p = extendtab[0][0]; 4487 p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0]; 4488 p++) 4489 *p = CODE_FOR_nothing; 4490 4491 for (i = 0; i < NUM_RTX_CODE; i++) 4492 setcc_gen_code[i] = CODE_FOR_nothing; 4493 4494#ifdef HAVE_conditional_move 4495 for (i = 0; i < NUM_MACHINE_MODES; i++) 4496 movcc_gen_code[i] = CODE_FOR_nothing; 4497#endif 4498 4499 add_optab = init_optab (PLUS); 4500 sub_optab = init_optab (MINUS); 4501 smul_optab = init_optab (MULT); 4502 smul_highpart_optab = init_optab (UNKNOWN); 4503 umul_highpart_optab = init_optab (UNKNOWN); 4504 smul_widen_optab = init_optab (UNKNOWN); 4505 umul_widen_optab = init_optab (UNKNOWN); 4506 sdiv_optab = init_optab (DIV); 4507 sdivmod_optab = init_optab (UNKNOWN); 4508 udiv_optab = init_optab (UDIV); 4509 udivmod_optab = init_optab (UNKNOWN); 4510 smod_optab = init_optab (MOD); 4511 umod_optab = init_optab (UMOD); 4512 flodiv_optab = init_optab (DIV); 4513 ftrunc_optab = init_optab (UNKNOWN); 4514 and_optab = init_optab (AND); 4515 ior_optab = init_optab (IOR); 4516 xor_optab = init_optab (XOR); 4517 ashl_optab = init_optab (ASHIFT); 4518 ashr_optab = init_optab (ASHIFTRT); 4519 lshr_optab = init_optab (LSHIFTRT); 4520 rotl_optab = init_optab (ROTATE); 4521 rotr_optab = init_optab (ROTATERT); 4522 smin_optab = init_optab (SMIN); 4523 smax_optab = init_optab (SMAX); 4524 umin_optab = init_optab (UMIN); 4525 umax_optab = init_optab (UMAX); 4526 mov_optab = init_optab (UNKNOWN); 4527 movstrict_optab = init_optab (UNKNOWN); 4528 cmp_optab = init_optab (UNKNOWN); 4529 ucmp_optab = init_optab (UNKNOWN); 4530 tst_optab = init_optab (UNKNOWN); 4531 neg_optab = init_optab (NEG); 4532 abs_optab = init_optab (ABS); 4533 one_cmpl_optab = init_optab (NOT); 4534 ffs_optab = init_optab (FFS); 4535 sqrt_optab = init_optab (SQRT); 4536 sin_optab = init_optab (UNKNOWN); 4537 cos_optab = init_optab (UNKNOWN); 4538 strlen_optab = init_optab (UNKNOWN); 4539 4540 for (i = 0; i < NUM_MACHINE_MODES; i++) 4541 { 4542 movstr_optab[i] = CODE_FOR_nothing; 4543 clrstr_optab[i] = CODE_FOR_nothing; 4544 4545#ifdef HAVE_SECONDARY_RELOADS 4546 reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing; 4547#endif 4548 } 4549 4550 /* Fill in the optabs with the insns we support. */ 4551 init_all_optabs (); 4552 4553#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC 4554 /* This flag says the same insns that convert to a signed fixnum 4555 also convert validly to an unsigned one. */ 4556 for (i = 0; i < NUM_MACHINE_MODES; i++) 4557 for (j = 0; j < NUM_MACHINE_MODES; j++) 4558 fixtrunctab[i][j][1] = fixtrunctab[i][j][0]; 4559#endif 4560 4561#ifdef EXTRA_CC_MODES 4562 init_mov_optab (); 4563#endif 4564 4565 /* Initialize the optabs with the names of the library functions. */ 4566 init_integral_libfuncs (add_optab, "add", '3'); 4567 init_floating_libfuncs (add_optab, "add", '3'); 4568 init_integral_libfuncs (sub_optab, "sub", '3'); 4569 init_floating_libfuncs (sub_optab, "sub", '3'); 4570 init_integral_libfuncs (smul_optab, "mul", '3'); 4571 init_floating_libfuncs (smul_optab, "mul", '3'); 4572 init_integral_libfuncs (sdiv_optab, "div", '3'); 4573 init_integral_libfuncs (udiv_optab, "udiv", '3'); 4574 init_integral_libfuncs (sdivmod_optab, "divmod", '4'); 4575 init_integral_libfuncs (udivmod_optab, "udivmod", '4'); 4576 init_integral_libfuncs (smod_optab, "mod", '3'); 4577 init_integral_libfuncs (umod_optab, "umod", '3'); 4578 init_floating_libfuncs (flodiv_optab, "div", '3'); 4579 init_floating_libfuncs (ftrunc_optab, "ftrunc", '2'); 4580 init_integral_libfuncs (and_optab, "and", '3'); 4581 init_integral_libfuncs (ior_optab, "ior", '3'); 4582 init_integral_libfuncs (xor_optab, "xor", '3'); 4583 init_integral_libfuncs (ashl_optab, "ashl", '3'); 4584 init_integral_libfuncs (ashr_optab, "ashr", '3'); 4585 init_integral_libfuncs (lshr_optab, "lshr", '3'); 4586 init_integral_libfuncs (smin_optab, "min", '3'); 4587 init_floating_libfuncs (smin_optab, "min", '3'); 4588 init_integral_libfuncs (smax_optab, "max", '3'); 4589 init_floating_libfuncs (smax_optab, "max", '3'); 4590 init_integral_libfuncs (umin_optab, "umin", '3'); 4591 init_integral_libfuncs (umax_optab, "umax", '3'); 4592 init_integral_libfuncs (neg_optab, "neg", '2'); 4593 init_floating_libfuncs (neg_optab, "neg", '2'); 4594 init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2'); 4595 init_integral_libfuncs (ffs_optab, "ffs", '2'); 4596 4597 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */ 4598 init_integral_libfuncs (cmp_optab, "cmp", '2'); 4599 init_integral_libfuncs (ucmp_optab, "ucmp", '2'); 4600 init_floating_libfuncs (cmp_optab, "cmp", '2'); 4601 4602#ifdef MULSI3_LIBCALL 4603 smul_optab->handlers[(int) SImode].libfunc 4604 = gen_rtx_SYMBOL_REF (Pmode, MULSI3_LIBCALL); 4605#endif 4606#ifdef MULDI3_LIBCALL 4607 smul_optab->handlers[(int) DImode].libfunc 4608 = gen_rtx_SYMBOL_REF (Pmode, MULDI3_LIBCALL); 4609#endif 4610 4611#ifdef DIVSI3_LIBCALL 4612 sdiv_optab->handlers[(int) SImode].libfunc 4613 = gen_rtx_SYMBOL_REF (Pmode, DIVSI3_LIBCALL); 4614#endif 4615#ifdef DIVDI3_LIBCALL 4616 sdiv_optab->handlers[(int) DImode].libfunc 4617 = gen_rtx_SYMBOL_REF (Pmode, DIVDI3_LIBCALL); 4618#endif 4619 4620#ifdef UDIVSI3_LIBCALL 4621 udiv_optab->handlers[(int) SImode].libfunc 4622 = gen_rtx_SYMBOL_REF (Pmode, UDIVSI3_LIBCALL); 4623#endif 4624#ifdef UDIVDI3_LIBCALL 4625 udiv_optab->handlers[(int) DImode].libfunc 4626 = gen_rtx_SYMBOL_REF (Pmode, UDIVDI3_LIBCALL); 4627#endif 4628 4629#ifdef MODSI3_LIBCALL 4630 smod_optab->handlers[(int) SImode].libfunc 4631 = gen_rtx_SYMBOL_REF (Pmode, MODSI3_LIBCALL); 4632#endif 4633#ifdef MODDI3_LIBCALL 4634 smod_optab->handlers[(int) DImode].libfunc 4635 = gen_rtx_SYMBOL_REF (Pmode, MODDI3_LIBCALL); 4636#endif 4637 4638#ifdef UMODSI3_LIBCALL 4639 umod_optab->handlers[(int) SImode].libfunc 4640 = gen_rtx_SYMBOL_REF (Pmode, UMODSI3_LIBCALL); 4641#endif 4642#ifdef UMODDI3_LIBCALL 4643 umod_optab->handlers[(int) DImode].libfunc 4644 = gen_rtx_SYMBOL_REF (Pmode, UMODDI3_LIBCALL); 4645#endif 4646 4647 /* Use cabs for DC complex abs, since systems generally have cabs. 4648 Don't define any libcall for SCmode, so that cabs will be used. */ 4649 abs_optab->handlers[(int) DCmode].libfunc 4650 = gen_rtx_SYMBOL_REF (Pmode, "cabs"); 4651 4652 /* The ffs function operates on `int'. */ 4653#ifndef INT_TYPE_SIZE 4654#define INT_TYPE_SIZE BITS_PER_WORD 4655#endif 4656 ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)] .libfunc 4657 = gen_rtx_SYMBOL_REF (Pmode, "ffs"); 4658 4659 extendsfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsfdf2"); 4660 extendsfxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsfxf2"); 4661 extendsftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsftf2"); 4662 extenddfxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extenddfxf2"); 4663 extenddftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extenddftf2"); 4664 4665 truncdfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncdfsf2"); 4666 truncxfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncxfsf2"); 4667 trunctfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__trunctfsf2"); 4668 truncxfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncxfdf2"); 4669 trunctfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__trunctfdf2"); 4670 4671 memcpy_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memcpy"); 4672 bcopy_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bcopy"); 4673 memcmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memcmp"); 4674 bcmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gcc_bcmp"); 4675 memset_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memset"); 4676 bzero_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bzero"); 4677 4678 throw_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__throw"); 4679 rethrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__rethrow"); 4680 sjthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjthrow"); 4681 sjpopnthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjpopnthrow"); 4682 terminate_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__terminate"); 4683 eh_rtime_match_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eh_rtime_match"); 4684#ifndef DONT_USE_BUILTIN_SETJMP 4685 setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_setjmp"); 4686 longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_longjmp"); 4687#else 4688 setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "setjmp"); 4689 longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "longjmp"); 4690#endif 4691 4692 eqhf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqhf2"); 4693 nehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nehf2"); 4694 gthf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gthf2"); 4695 gehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gehf2"); 4696 lthf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lthf2"); 4697 lehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lehf2"); 4698 4699 eqsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqsf2"); 4700 nesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nesf2"); 4701 gtsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtsf2"); 4702 gesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gesf2"); 4703 ltsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltsf2"); 4704 lesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lesf2"); 4705 4706 eqdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqdf2"); 4707 nedf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nedf2"); 4708 gtdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtdf2"); 4709 gedf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gedf2"); 4710 ltdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltdf2"); 4711 ledf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ledf2"); 4712 4713 eqxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqxf2"); 4714 nexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nexf2"); 4715 gtxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtxf2"); 4716 gexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gexf2"); 4717 ltxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltxf2"); 4718 lexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lexf2"); 4719 4720 eqtf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqtf2"); 4721 netf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__netf2"); 4722 gttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gttf2"); 4723 getf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__getf2"); 4724 lttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lttf2"); 4725 letf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__letf2"); 4726 4727 floatsisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsisf"); 4728 floatdisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdisf"); 4729 floattisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattisf"); 4730 4731 floatsidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsidf"); 4732 floatdidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdidf"); 4733 floattidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattidf"); 4734 4735 floatsixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsixf"); 4736 floatdixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdixf"); 4737 floattixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattixf"); 4738 4739 floatsitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsitf"); 4740 floatditf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatditf"); 4741 floattitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattitf"); 4742 4743 fixsfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfsi"); 4744 fixsfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfdi"); 4745 fixsfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfti"); 4746 4747 fixdfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfsi"); 4748 fixdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfdi"); 4749 fixdfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfti"); 4750 4751 fixxfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfsi"); 4752 fixxfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfdi"); 4753 fixxfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfti"); 4754 4755 fixtfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfsi"); 4756 fixtfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfdi"); 4757 fixtfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfti"); 4758 4759 fixunssfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfsi"); 4760 fixunssfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfdi"); 4761 fixunssfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfti"); 4762 4763 fixunsdfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfsi"); 4764 fixunsdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfdi"); 4765 fixunsdfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfti"); 4766 4767 fixunsxfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfsi"); 4768 fixunsxfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfdi"); 4769 fixunsxfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfti"); 4770 4771 fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfsi"); 4772 fixunstfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfdi"); 4773 fixunstfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfti"); 4774 4775 /* For check-memory-usage. */ 4776 chkr_check_addr_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_addr"); 4777 chkr_set_right_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_set_right"); 4778 chkr_copy_bitmap_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_copy_bitmap"); 4779 chkr_check_exec_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_exec"); 4780 chkr_check_str_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_str"); 4781 4782 /* For function entry/exit instrumentation. */ 4783 profile_function_entry_libfunc 4784 = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_enter"); 4785 profile_function_exit_libfunc 4786 = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_exit"); 4787 4788#ifdef HAVE_conditional_trap 4789 init_traps (); 4790#endif 4791 4792#ifdef INIT_TARGET_OPTABS 4793 /* Allow the target to add more libcalls or rename some, etc. */ 4794 INIT_TARGET_OPTABS; 4795#endif 4796} 4797 4798#ifdef BROKEN_LDEXP 4799 4800/* SCO 3.2 apparently has a broken ldexp. */ 4801 4802double 4803ldexp(x,n) 4804 double x; 4805 int n; 4806{ 4807 if (n > 0) 4808 while (n--) 4809 x *= 2; 4810 4811 return x; 4812} 4813#endif /* BROKEN_LDEXP */ 4814 4815#ifdef HAVE_conditional_trap 4816/* The insn generating function can not take an rtx_code argument. 4817 TRAP_RTX is used as an rtx argument. Its code is replaced with 4818 the code to be used in the trap insn and all other fields are 4819 ignored. 4820 4821 ??? Will need to change to support garbage collection. */ 4822static rtx trap_rtx; 4823 4824static void 4825init_traps () 4826{ 4827 if (HAVE_conditional_trap) 4828 trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX); 4829} 4830#endif 4831 4832/* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition 4833 CODE. Return 0 on failure. */ 4834 4835rtx 4836gen_cond_trap (code, op1, op2, tcode) 4837 enum rtx_code code ATTRIBUTE_UNUSED; 4838 rtx op1, op2 ATTRIBUTE_UNUSED, tcode ATTRIBUTE_UNUSED; 4839{ 4840 enum machine_mode mode = GET_MODE (op1); 4841 4842 if (mode == VOIDmode) 4843 return 0; 4844 4845#ifdef HAVE_conditional_trap 4846 if (HAVE_conditional_trap 4847 && cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 4848 { 4849 rtx insn; 4850 emit_insn (GEN_FCN (cmp_optab->handlers[(int) mode].insn_code) (op1, op2)); 4851 PUT_CODE (trap_rtx, code); 4852 insn = gen_conditional_trap (trap_rtx, tcode); 4853 if (insn) 4854 return insn; 4855 } 4856#endif 4857 4858 return 0; 4859} 4860