optabs.c revision 52284
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 prev, next, first, last, insn; 2891 2892 /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION 2893 reg note to indicate that this call cannot throw. (Unless there is 2894 already a REG_EH_REGION note.) */ 2895 2896 for (insn = insns; insn; insn = NEXT_INSN (insn)) 2897 { 2898 if (GET_CODE (insn) == CALL_INSN) 2899 { 2900 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX); 2901 if (note == NULL_RTX) 2902 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (-1), 2903 REG_NOTES (insn)); 2904 } 2905 } 2906 2907 /* First emit all insns that set pseudos. Remove them from the list as 2908 we go. Avoid insns that set pseudos which were referenced in previous 2909 insns. These can be generated by move_by_pieces, for example, 2910 to update an address. Similarly, avoid insns that reference things 2911 set in previous insns. */ 2912 2913 for (insn = insns; insn; insn = next) 2914 { 2915 rtx set = single_set (insn); 2916 2917 next = NEXT_INSN (insn); 2918 2919 if (set != 0 && GET_CODE (SET_DEST (set)) == REG 2920 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER 2921 && (insn == insns 2922 || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns)) 2923 && ! reg_used_between_p (SET_DEST (set), insns, insn) 2924 && ! modified_in_p (SET_SRC (set), insns) 2925 && ! modified_between_p (SET_SRC (set), insns, insn)))) 2926 { 2927 if (PREV_INSN (insn)) 2928 NEXT_INSN (PREV_INSN (insn)) = next; 2929 else 2930 insns = next; 2931 2932 if (next) 2933 PREV_INSN (next) = PREV_INSN (insn); 2934 2935 add_insn (insn); 2936 } 2937 } 2938 2939 prev = get_last_insn (); 2940 2941 /* Write the remaining insns followed by the final copy. */ 2942 2943 for (insn = insns; insn; insn = next) 2944 { 2945 next = NEXT_INSN (insn); 2946 2947 add_insn (insn); 2948 } 2949 2950 last = emit_move_insn (target, result); 2951 if (mov_optab->handlers[(int) GET_MODE (target)].insn_code 2952 != CODE_FOR_nothing) 2953 set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv)); 2954 2955 if (prev == 0) 2956 first = get_insns (); 2957 else 2958 first = NEXT_INSN (prev); 2959 2960 /* Encapsulate the block so it gets manipulated as a unit. */ 2961 REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, 2962 REG_NOTES (first)); 2963 REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last)); 2964} 2965 2966/* Generate code to store zero in X. */ 2967 2968void 2969emit_clr_insn (x) 2970 rtx x; 2971{ 2972 emit_move_insn (x, const0_rtx); 2973} 2974 2975/* Generate code to store 1 in X 2976 assuming it contains zero beforehand. */ 2977 2978void 2979emit_0_to_1_insn (x) 2980 rtx x; 2981{ 2982 emit_move_insn (x, const1_rtx); 2983} 2984 2985/* Generate code to compare X with Y 2986 so that the condition codes are set. 2987 2988 MODE is the mode of the inputs (in case they are const_int). 2989 UNSIGNEDP nonzero says that X and Y are unsigned; 2990 this matters if they need to be widened. 2991 2992 If they have mode BLKmode, then SIZE specifies the size of both X and Y, 2993 and ALIGN specifies the known shared alignment of X and Y. 2994 2995 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). 2996 It is ignored for fixed-point and block comparisons; 2997 it is used only for floating-point comparisons. */ 2998 2999void 3000emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align) 3001 rtx x, y; 3002 enum rtx_code comparison; 3003 rtx size; 3004 enum machine_mode mode; 3005 int unsignedp; 3006 int align; 3007{ 3008 enum mode_class class; 3009 enum machine_mode wider_mode; 3010 3011 class = GET_MODE_CLASS (mode); 3012 3013 /* They could both be VOIDmode if both args are immediate constants, 3014 but we should fold that at an earlier stage. 3015 With no special code here, this will call abort, 3016 reminding the programmer to implement such folding. */ 3017 3018 if (mode != BLKmode && flag_force_mem) 3019 { 3020 x = force_not_mem (x); 3021 y = force_not_mem (y); 3022 } 3023 3024 /* If we are inside an appropriately-short loop and one operand is an 3025 expensive constant, force it into a register. */ 3026 if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2) 3027 x = force_reg (mode, x); 3028 3029 if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2) 3030 y = force_reg (mode, y); 3031 3032#ifdef HAVE_cc0 3033 /* Abort if we have a non-canonical comparison. The RTL documentation 3034 states that canonical comparisons are required only for targets which 3035 have cc0. */ 3036 if (CONSTANT_P (x) && ! CONSTANT_P (y)) 3037 abort(); 3038#endif 3039 3040 /* Don't let both operands fail to indicate the mode. */ 3041 if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode) 3042 x = force_reg (mode, x); 3043 3044 /* Handle all BLKmode compares. */ 3045 3046 if (mode == BLKmode) 3047 { 3048 emit_queue (); 3049 x = protect_from_queue (x, 0); 3050 y = protect_from_queue (y, 0); 3051 3052 if (size == 0) 3053 abort (); 3054#ifdef HAVE_cmpstrqi 3055 if (HAVE_cmpstrqi 3056 && GET_CODE (size) == CONST_INT 3057 && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode))) 3058 { 3059 enum machine_mode result_mode 3060 = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0]; 3061 rtx result = gen_reg_rtx (result_mode); 3062 emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align))); 3063 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX, 3064 result_mode, 0, 0); 3065 } 3066 else 3067#endif 3068#ifdef HAVE_cmpstrhi 3069 if (HAVE_cmpstrhi 3070 && GET_CODE (size) == CONST_INT 3071 && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode))) 3072 { 3073 enum machine_mode result_mode 3074 = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0]; 3075 rtx result = gen_reg_rtx (result_mode); 3076 emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align))); 3077 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX, 3078 result_mode, 0, 0); 3079 } 3080 else 3081#endif 3082#ifdef HAVE_cmpstrsi 3083 if (HAVE_cmpstrsi) 3084 { 3085 enum machine_mode result_mode 3086 = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0]; 3087 rtx result = gen_reg_rtx (result_mode); 3088 size = protect_from_queue (size, 0); 3089 emit_insn (gen_cmpstrsi (result, x, y, 3090 convert_to_mode (SImode, size, 1), 3091 GEN_INT (align))); 3092 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX, 3093 result_mode, 0, 0); 3094 } 3095 else 3096#endif 3097 { 3098 rtx result; 3099 3100#ifdef TARGET_MEM_FUNCTIONS 3101 emit_library_call (memcmp_libfunc, 0, 3102 TYPE_MODE (integer_type_node), 3, 3103 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, 3104 convert_to_mode (TYPE_MODE (sizetype), size, 3105 TREE_UNSIGNED (sizetype)), 3106 TYPE_MODE (sizetype)); 3107#else 3108 emit_library_call (bcmp_libfunc, 0, 3109 TYPE_MODE (integer_type_node), 3, 3110 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, 3111 convert_to_mode (TYPE_MODE (integer_type_node), 3112 size, 3113 TREE_UNSIGNED (integer_type_node)), 3114 TYPE_MODE (integer_type_node)); 3115#endif 3116 3117 /* Immediately move the result of the libcall into a pseudo 3118 register so reload doesn't clobber the value if it needs 3119 the return register for a spill reg. */ 3120 result = gen_reg_rtx (TYPE_MODE (integer_type_node)); 3121 emit_move_insn (result, 3122 hard_libcall_value (TYPE_MODE (integer_type_node))); 3123 emit_cmp_insn (result, 3124 const0_rtx, comparison, NULL_RTX, 3125 TYPE_MODE (integer_type_node), 0, 0); 3126 } 3127 return; 3128 } 3129 3130 /* Handle some compares against zero. */ 3131 3132 if (y == CONST0_RTX (mode) 3133 && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 3134 { 3135 int icode = (int) tst_optab->handlers[(int) mode].insn_code; 3136 3137 emit_queue (); 3138 x = protect_from_queue (x, 0); 3139 y = protect_from_queue (y, 0); 3140 3141 /* Now, if insn does accept these operands, put them into pseudos. */ 3142 if (! (*insn_operand_predicate[icode][0]) 3143 (x, insn_operand_mode[icode][0])) 3144 x = copy_to_mode_reg (insn_operand_mode[icode][0], x); 3145 3146 emit_insn (GEN_FCN (icode) (x)); 3147 return; 3148 } 3149 3150 /* Handle compares for which there is a directly suitable insn. */ 3151 3152 if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 3153 { 3154 int icode = (int) cmp_optab->handlers[(int) mode].insn_code; 3155 3156 emit_queue (); 3157 x = protect_from_queue (x, 0); 3158 y = protect_from_queue (y, 0); 3159 3160 /* Now, if insn doesn't accept these operands, put them into pseudos. */ 3161 if (! (*insn_operand_predicate[icode][0]) 3162 (x, insn_operand_mode[icode][0])) 3163 x = copy_to_mode_reg (insn_operand_mode[icode][0], x); 3164 3165 if (! (*insn_operand_predicate[icode][1]) 3166 (y, insn_operand_mode[icode][1])) 3167 y = copy_to_mode_reg (insn_operand_mode[icode][1], y); 3168 3169 emit_insn (GEN_FCN (icode) (x, y)); 3170 return; 3171 } 3172 3173 /* Try widening if we can find a direct insn that way. */ 3174 3175 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) 3176 { 3177 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 3178 wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 3179 { 3180 if (cmp_optab->handlers[(int) wider_mode].insn_code 3181 != CODE_FOR_nothing) 3182 { 3183 x = protect_from_queue (x, 0); 3184 y = protect_from_queue (y, 0); 3185 x = convert_modes (wider_mode, mode, x, unsignedp); 3186 y = convert_modes (wider_mode, mode, y, unsignedp); 3187 emit_cmp_insn (x, y, comparison, NULL_RTX, 3188 wider_mode, unsignedp, align); 3189 return; 3190 } 3191 } 3192 } 3193 3194 /* Handle a lib call just for the mode we are using. */ 3195 3196 if (cmp_optab->handlers[(int) mode].libfunc 3197 && class != MODE_FLOAT) 3198 { 3199 rtx libfunc = cmp_optab->handlers[(int) mode].libfunc; 3200 rtx result; 3201 3202 /* If we want unsigned, and this mode has a distinct unsigned 3203 comparison routine, use that. */ 3204 if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc) 3205 libfunc = ucmp_optab->handlers[(int) mode].libfunc; 3206 3207 emit_library_call (libfunc, 1, 3208 word_mode, 2, x, mode, y, mode); 3209 3210 /* Immediately move the result of the libcall into a pseudo 3211 register so reload doesn't clobber the value if it needs 3212 the return register for a spill reg. */ 3213 result = gen_reg_rtx (word_mode); 3214 emit_move_insn (result, hard_libcall_value (word_mode)); 3215 3216 /* Integer comparison returns a result that must be compared against 1, 3217 so that even if we do an unsigned compare afterward, 3218 there is still a value that can represent the result "less than". */ 3219 emit_cmp_insn (result, const1_rtx, 3220 comparison, NULL_RTX, word_mode, unsignedp, 0); 3221 return; 3222 } 3223 3224 if (class == MODE_FLOAT) 3225 emit_float_lib_cmp (x, y, comparison); 3226 3227 else 3228 abort (); 3229} 3230 3231/* Generate code to compare X with Y so that the condition codes are 3232 set and to jump to LABEL if the condition is true. If X is a 3233 constant and Y is not a constant, then the comparison is swapped to 3234 ensure that the comparison RTL has the canonical form. 3235 3236 UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they 3237 need to be widened by emit_cmp_insn. UNSIGNEDP is also used to select 3238 the proper branch condition code. 3239 3240 If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y, 3241 and ALIGN specifies the known shared alignment of X and Y. 3242 3243 MODE is the mode of the inputs (in case they are const_int). 3244 3245 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). It will 3246 be passed unchanged to emit_cmp_insn, then potentially converted into an 3247 unsigned variant based on UNSIGNEDP to select a proper jump instruction. */ 3248 3249void 3250emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, label) 3251 rtx x, y; 3252 enum rtx_code comparison; 3253 rtx size; 3254 enum machine_mode mode; 3255 int unsignedp; 3256 int align; 3257 rtx label; 3258{ 3259 rtx op0; 3260 rtx op1; 3261 3262 if (CONSTANT_P (x)) 3263 { 3264 /* Swap operands and condition to ensure canonical RTL. */ 3265 op0 = y; 3266 op1 = x; 3267 comparison = swap_condition (comparison); 3268 } 3269 else 3270 { 3271 op0 = x; 3272 op1 = y; 3273 } 3274 3275#ifdef HAVE_cc0 3276 /* If OP0 is still a constant, then both X and Y must be constants. Force 3277 X into a register to avoid aborting in emit_cmp_insn due to non-canonical 3278 RTL. */ 3279 if (CONSTANT_P (op0)) 3280 op0 = force_reg (mode, op0); 3281#endif 3282 3283 emit_cmp_insn (op0, op1, comparison, size, mode, unsignedp, align); 3284 3285 if (unsignedp) 3286 comparison = unsigned_condition (comparison); 3287 emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label)); 3288} 3289 3290 3291/* Nonzero if a compare of mode MODE can be done straightforwardly 3292 (without splitting it into pieces). */ 3293 3294int 3295can_compare_p (mode) 3296 enum machine_mode mode; 3297{ 3298 do 3299 { 3300 if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing) 3301 return 1; 3302 mode = GET_MODE_WIDER_MODE (mode); 3303 } while (mode != VOIDmode); 3304 3305 return 0; 3306} 3307 3308/* Emit a library call comparison between floating point X and Y. 3309 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */ 3310 3311void 3312emit_float_lib_cmp (x, y, comparison) 3313 rtx x, y; 3314 enum rtx_code comparison; 3315{ 3316 enum machine_mode mode = GET_MODE (x); 3317 rtx libfunc = 0; 3318 rtx result; 3319 3320 if (mode == HFmode) 3321 switch (comparison) 3322 { 3323 case EQ: 3324 libfunc = eqhf2_libfunc; 3325 break; 3326 3327 case NE: 3328 libfunc = nehf2_libfunc; 3329 break; 3330 3331 case GT: 3332 libfunc = gthf2_libfunc; 3333 break; 3334 3335 case GE: 3336 libfunc = gehf2_libfunc; 3337 break; 3338 3339 case LT: 3340 libfunc = lthf2_libfunc; 3341 break; 3342 3343 case LE: 3344 libfunc = lehf2_libfunc; 3345 break; 3346 3347 default: 3348 break; 3349 } 3350 else if (mode == SFmode) 3351 switch (comparison) 3352 { 3353 case EQ: 3354 libfunc = eqsf2_libfunc; 3355 break; 3356 3357 case NE: 3358 libfunc = nesf2_libfunc; 3359 break; 3360 3361 case GT: 3362 libfunc = gtsf2_libfunc; 3363 break; 3364 3365 case GE: 3366 libfunc = gesf2_libfunc; 3367 break; 3368 3369 case LT: 3370 libfunc = ltsf2_libfunc; 3371 break; 3372 3373 case LE: 3374 libfunc = lesf2_libfunc; 3375 break; 3376 3377 default: 3378 break; 3379 } 3380 else if (mode == DFmode) 3381 switch (comparison) 3382 { 3383 case EQ: 3384 libfunc = eqdf2_libfunc; 3385 break; 3386 3387 case NE: 3388 libfunc = nedf2_libfunc; 3389 break; 3390 3391 case GT: 3392 libfunc = gtdf2_libfunc; 3393 break; 3394 3395 case GE: 3396 libfunc = gedf2_libfunc; 3397 break; 3398 3399 case LT: 3400 libfunc = ltdf2_libfunc; 3401 break; 3402 3403 case LE: 3404 libfunc = ledf2_libfunc; 3405 break; 3406 3407 default: 3408 break; 3409 } 3410 else if (mode == XFmode) 3411 switch (comparison) 3412 { 3413 case EQ: 3414 libfunc = eqxf2_libfunc; 3415 break; 3416 3417 case NE: 3418 libfunc = nexf2_libfunc; 3419 break; 3420 3421 case GT: 3422 libfunc = gtxf2_libfunc; 3423 break; 3424 3425 case GE: 3426 libfunc = gexf2_libfunc; 3427 break; 3428 3429 case LT: 3430 libfunc = ltxf2_libfunc; 3431 break; 3432 3433 case LE: 3434 libfunc = lexf2_libfunc; 3435 break; 3436 3437 default: 3438 break; 3439 } 3440 else if (mode == TFmode) 3441 switch (comparison) 3442 { 3443 case EQ: 3444 libfunc = eqtf2_libfunc; 3445 break; 3446 3447 case NE: 3448 libfunc = netf2_libfunc; 3449 break; 3450 3451 case GT: 3452 libfunc = gttf2_libfunc; 3453 break; 3454 3455 case GE: 3456 libfunc = getf2_libfunc; 3457 break; 3458 3459 case LT: 3460 libfunc = lttf2_libfunc; 3461 break; 3462 3463 case LE: 3464 libfunc = letf2_libfunc; 3465 break; 3466 3467 default: 3468 break; 3469 } 3470 else 3471 { 3472 enum machine_mode wider_mode; 3473 3474 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 3475 wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 3476 { 3477 if ((cmp_optab->handlers[(int) wider_mode].insn_code 3478 != CODE_FOR_nothing) 3479 || (cmp_optab->handlers[(int) wider_mode].libfunc != 0)) 3480 { 3481 x = protect_from_queue (x, 0); 3482 y = protect_from_queue (y, 0); 3483 x = convert_to_mode (wider_mode, x, 0); 3484 y = convert_to_mode (wider_mode, y, 0); 3485 emit_float_lib_cmp (x, y, comparison); 3486 return; 3487 } 3488 } 3489 abort (); 3490 } 3491 3492 if (libfunc == 0) 3493 abort (); 3494 3495 emit_library_call (libfunc, 1, 3496 word_mode, 2, x, mode, y, mode); 3497 3498 /* Immediately move the result of the libcall into a pseudo 3499 register so reload doesn't clobber the value if it needs 3500 the return register for a spill reg. */ 3501 result = gen_reg_rtx (word_mode); 3502 emit_move_insn (result, hard_libcall_value (word_mode)); 3503 3504 emit_cmp_insn (result, const0_rtx, comparison, 3505 NULL_RTX, word_mode, 0, 0); 3506} 3507 3508/* Generate code to indirectly jump to a location given in the rtx LOC. */ 3509 3510void 3511emit_indirect_jump (loc) 3512 rtx loc; 3513{ 3514 if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0]) 3515 (loc, Pmode))) 3516 loc = copy_to_mode_reg (Pmode, loc); 3517 3518 emit_jump_insn (gen_indirect_jump (loc)); 3519 emit_barrier (); 3520} 3521 3522#ifdef HAVE_conditional_move 3523 3524/* Emit a conditional move instruction if the machine supports one for that 3525 condition and machine mode. 3526 3527 OP0 and OP1 are the operands that should be compared using CODE. CMODE is 3528 the mode to use should they be constants. If it is VOIDmode, they cannot 3529 both be constants. 3530 3531 OP2 should be stored in TARGET if the comparison is true, otherwise OP3 3532 should be stored there. MODE is the mode to use should they be constants. 3533 If it is VOIDmode, they cannot both be constants. 3534 3535 The result is either TARGET (perhaps modified) or NULL_RTX if the operation 3536 is not supported. */ 3537 3538rtx 3539emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode, 3540 unsignedp) 3541 rtx target; 3542 enum rtx_code code; 3543 rtx op0, op1; 3544 enum machine_mode cmode; 3545 rtx op2, op3; 3546 enum machine_mode mode; 3547 int unsignedp; 3548{ 3549 rtx tem, subtarget, comparison, insn; 3550 enum insn_code icode; 3551 3552 /* If one operand is constant, make it the second one. Only do this 3553 if the other operand is not constant as well. */ 3554 3555 if ((CONSTANT_P (op0) && ! CONSTANT_P (op1)) 3556 || (GET_CODE (op0) == CONST_INT && GET_CODE (op1) != CONST_INT)) 3557 { 3558 tem = op0; 3559 op0 = op1; 3560 op1 = tem; 3561 code = swap_condition (code); 3562 } 3563 3564 if (cmode == VOIDmode) 3565 cmode = GET_MODE (op0); 3566 3567 if (((CONSTANT_P (op2) && ! CONSTANT_P (op3)) 3568 || (GET_CODE (op2) == CONST_INT && GET_CODE (op3) != CONST_INT)) 3569 && (GET_MODE_CLASS (GET_MODE (op1)) != MODE_FLOAT 3570 || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT || flag_fast_math)) 3571 { 3572 tem = op2; 3573 op2 = op3; 3574 op3 = tem; 3575 code = reverse_condition (code); 3576 } 3577 3578 if (mode == VOIDmode) 3579 mode = GET_MODE (op2); 3580 3581 icode = movcc_gen_code[mode]; 3582 3583 if (icode == CODE_FOR_nothing) 3584 return 0; 3585 3586 if (flag_force_mem) 3587 { 3588 op2 = force_not_mem (op2); 3589 op3 = force_not_mem (op3); 3590 } 3591 3592 if (target) 3593 target = protect_from_queue (target, 1); 3594 else 3595 target = gen_reg_rtx (mode); 3596 3597 subtarget = target; 3598 3599 emit_queue (); 3600 3601 op2 = protect_from_queue (op2, 0); 3602 op3 = protect_from_queue (op3, 0); 3603 3604 /* If the insn doesn't accept these operands, put them in pseudos. */ 3605 3606 if (! (*insn_operand_predicate[icode][0]) 3607 (subtarget, insn_operand_mode[icode][0])) 3608 subtarget = gen_reg_rtx (insn_operand_mode[icode][0]); 3609 3610 if (! (*insn_operand_predicate[icode][2]) 3611 (op2, insn_operand_mode[icode][2])) 3612 op2 = copy_to_mode_reg (insn_operand_mode[icode][2], op2); 3613 3614 if (! (*insn_operand_predicate[icode][3]) 3615 (op3, insn_operand_mode[icode][3])) 3616 op3 = copy_to_mode_reg (insn_operand_mode[icode][3], op3); 3617 3618 /* Everything should now be in the suitable form, so emit the compare insn 3619 and then the conditional move. */ 3620 3621 comparison 3622 = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX, 0); 3623 3624 /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)? */ 3625 if (GET_CODE (comparison) != code) 3626 /* This shouldn't happen. */ 3627 abort (); 3628 3629 insn = GEN_FCN (icode) (subtarget, comparison, op2, op3); 3630 3631 /* If that failed, then give up. */ 3632 if (insn == 0) 3633 return 0; 3634 3635 emit_insn (insn); 3636 3637 if (subtarget != target) 3638 convert_move (target, subtarget, 0); 3639 3640 return target; 3641} 3642 3643/* Return non-zero if a conditional move of mode MODE is supported. 3644 3645 This function is for combine so it can tell whether an insn that looks 3646 like a conditional move is actually supported by the hardware. If we 3647 guess wrong we lose a bit on optimization, but that's it. */ 3648/* ??? sparc64 supports conditionally moving integers values based on fp 3649 comparisons, and vice versa. How do we handle them? */ 3650 3651int 3652can_conditionally_move_p (mode) 3653 enum machine_mode mode; 3654{ 3655 if (movcc_gen_code[mode] != CODE_FOR_nothing) 3656 return 1; 3657 3658 return 0; 3659} 3660 3661#endif /* HAVE_conditional_move */ 3662 3663/* These three functions generate an insn body and return it 3664 rather than emitting the insn. 3665 3666 They do not protect from queued increments, 3667 because they may be used 1) in protect_from_queue itself 3668 and 2) in other passes where there is no queue. */ 3669 3670/* Generate and return an insn body to add Y to X. */ 3671 3672rtx 3673gen_add2_insn (x, y) 3674 rtx x, y; 3675{ 3676 int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code; 3677 3678 if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0]) 3679 || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1]) 3680 || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2])) 3681 abort (); 3682 3683 return (GEN_FCN (icode) (x, x, y)); 3684} 3685 3686int 3687have_add2_insn (mode) 3688 enum machine_mode mode; 3689{ 3690 return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing; 3691} 3692 3693/* Generate and return an insn body to subtract Y from X. */ 3694 3695rtx 3696gen_sub2_insn (x, y) 3697 rtx x, y; 3698{ 3699 int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code; 3700 3701 if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0]) 3702 || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1]) 3703 || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2])) 3704 abort (); 3705 3706 return (GEN_FCN (icode) (x, x, y)); 3707} 3708 3709int 3710have_sub2_insn (mode) 3711 enum machine_mode mode; 3712{ 3713 return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing; 3714} 3715 3716/* Generate the body of an instruction to copy Y into X. 3717 It may be a SEQUENCE, if one insn isn't enough. */ 3718 3719rtx 3720gen_move_insn (x, y) 3721 rtx x, y; 3722{ 3723 register enum machine_mode mode = GET_MODE (x); 3724 enum insn_code insn_code; 3725 rtx seq; 3726 3727 if (mode == VOIDmode) 3728 mode = GET_MODE (y); 3729 3730 insn_code = mov_optab->handlers[(int) mode].insn_code; 3731 3732 /* Handle MODE_CC modes: If we don't have a special move insn for this mode, 3733 find a mode to do it in. If we have a movcc, use it. Otherwise, 3734 find the MODE_INT mode of the same width. */ 3735 3736 if (GET_MODE_CLASS (mode) == MODE_CC && insn_code == CODE_FOR_nothing) 3737 { 3738 enum machine_mode tmode = VOIDmode; 3739 rtx x1 = x, y1 = y; 3740 3741 if (mode != CCmode 3742 && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing) 3743 tmode = CCmode; 3744 else 3745 for (tmode = QImode; tmode != VOIDmode; 3746 tmode = GET_MODE_WIDER_MODE (tmode)) 3747 if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode)) 3748 break; 3749 3750 if (tmode == VOIDmode) 3751 abort (); 3752 3753 /* Get X and Y in TMODE. We can't use gen_lowpart here because it 3754 may call change_address which is not appropriate if we were 3755 called when a reload was in progress. We don't have to worry 3756 about changing the address since the size in bytes is supposed to 3757 be the same. Copy the MEM to change the mode and move any 3758 substitutions from the old MEM to the new one. */ 3759 3760 if (reload_in_progress) 3761 { 3762 x = gen_lowpart_common (tmode, x1); 3763 if (x == 0 && GET_CODE (x1) == MEM) 3764 { 3765 x = gen_rtx_MEM (tmode, XEXP (x1, 0)); 3766 RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1); 3767 MEM_COPY_ATTRIBUTES (x, x1); 3768 copy_replacements (x1, x); 3769 } 3770 3771 y = gen_lowpart_common (tmode, y1); 3772 if (y == 0 && GET_CODE (y1) == MEM) 3773 { 3774 y = gen_rtx_MEM (tmode, XEXP (y1, 0)); 3775 RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1); 3776 MEM_COPY_ATTRIBUTES (y, y1); 3777 copy_replacements (y1, y); 3778 } 3779 } 3780 else 3781 { 3782 x = gen_lowpart (tmode, x); 3783 y = gen_lowpart (tmode, y); 3784 } 3785 3786 insn_code = mov_optab->handlers[(int) tmode].insn_code; 3787 return (GEN_FCN (insn_code) (x, y)); 3788 } 3789 3790 start_sequence (); 3791 emit_move_insn_1 (x, y); 3792 seq = gen_sequence (); 3793 end_sequence (); 3794 return seq; 3795} 3796 3797/* Return the insn code used to extend FROM_MODE to TO_MODE. 3798 UNSIGNEDP specifies zero-extension instead of sign-extension. If 3799 no such operation exists, CODE_FOR_nothing will be returned. */ 3800 3801enum insn_code 3802can_extend_p (to_mode, from_mode, unsignedp) 3803 enum machine_mode to_mode, from_mode; 3804 int unsignedp; 3805{ 3806 return extendtab[(int) to_mode][(int) from_mode][unsignedp]; 3807} 3808 3809/* Generate the body of an insn to extend Y (with mode MFROM) 3810 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */ 3811 3812rtx 3813gen_extend_insn (x, y, mto, mfrom, unsignedp) 3814 rtx x, y; 3815 enum machine_mode mto, mfrom; 3816 int unsignedp; 3817{ 3818 return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y)); 3819} 3820 3821/* can_fix_p and can_float_p say whether the target machine 3822 can directly convert a given fixed point type to 3823 a given floating point type, or vice versa. 3824 The returned value is the CODE_FOR_... value to use, 3825 or CODE_FOR_nothing if these modes cannot be directly converted. 3826 3827 *TRUNCP_PTR is set to 1 if it is necessary to output 3828 an explicit FTRUNC insn before the fix insn; otherwise 0. */ 3829 3830static enum insn_code 3831can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr) 3832 enum machine_mode fltmode, fixmode; 3833 int unsignedp; 3834 int *truncp_ptr; 3835{ 3836 *truncp_ptr = 0; 3837 if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing) 3838 return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp]; 3839 3840 if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing) 3841 { 3842 *truncp_ptr = 1; 3843 return fixtab[(int) fltmode][(int) fixmode][unsignedp]; 3844 } 3845 return CODE_FOR_nothing; 3846} 3847 3848static enum insn_code 3849can_float_p (fltmode, fixmode, unsignedp) 3850 enum machine_mode fixmode, fltmode; 3851 int unsignedp; 3852{ 3853 return floattab[(int) fltmode][(int) fixmode][unsignedp]; 3854} 3855 3856/* Generate code to convert FROM to floating point 3857 and store in TO. FROM must be fixed point and not VOIDmode. 3858 UNSIGNEDP nonzero means regard FROM as unsigned. 3859 Normally this is done by correcting the final value 3860 if it is negative. */ 3861 3862void 3863expand_float (to, from, unsignedp) 3864 rtx to, from; 3865 int unsignedp; 3866{ 3867 enum insn_code icode; 3868 register rtx target = to; 3869 enum machine_mode fmode, imode; 3870 3871 /* Crash now, because we won't be able to decide which mode to use. */ 3872 if (GET_MODE (from) == VOIDmode) 3873 abort (); 3874 3875 /* Look for an insn to do the conversion. Do it in the specified 3876 modes if possible; otherwise convert either input, output or both to 3877 wider mode. If the integer mode is wider than the mode of FROM, 3878 we can do the conversion signed even if the input is unsigned. */ 3879 3880 for (imode = GET_MODE (from); imode != VOIDmode; 3881 imode = GET_MODE_WIDER_MODE (imode)) 3882 for (fmode = GET_MODE (to); fmode != VOIDmode; 3883 fmode = GET_MODE_WIDER_MODE (fmode)) 3884 { 3885 int doing_unsigned = unsignedp; 3886 3887 icode = can_float_p (fmode, imode, unsignedp); 3888 if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp) 3889 icode = can_float_p (fmode, imode, 0), doing_unsigned = 0; 3890 3891 if (icode != CODE_FOR_nothing) 3892 { 3893 to = protect_from_queue (to, 1); 3894 from = protect_from_queue (from, 0); 3895 3896 if (imode != GET_MODE (from)) 3897 from = convert_to_mode (imode, from, unsignedp); 3898 3899 if (fmode != GET_MODE (to)) 3900 target = gen_reg_rtx (fmode); 3901 3902 emit_unop_insn (icode, target, from, 3903 doing_unsigned ? UNSIGNED_FLOAT : FLOAT); 3904 3905 if (target != to) 3906 convert_move (to, target, 0); 3907 return; 3908 } 3909 } 3910 3911#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) 3912 3913 /* Unsigned integer, and no way to convert directly. 3914 Convert as signed, then conditionally adjust the result. */ 3915 if (unsignedp) 3916 { 3917 rtx label = gen_label_rtx (); 3918 rtx temp; 3919 REAL_VALUE_TYPE offset; 3920 3921 emit_queue (); 3922 3923 to = protect_from_queue (to, 1); 3924 from = protect_from_queue (from, 0); 3925 3926 if (flag_force_mem) 3927 from = force_not_mem (from); 3928 3929 /* Look for a usable floating mode FMODE wider than the source and at 3930 least as wide as the target. Using FMODE will avoid rounding woes 3931 with unsigned values greater than the signed maximum value. */ 3932 3933 for (fmode = GET_MODE (to); fmode != VOIDmode; 3934 fmode = GET_MODE_WIDER_MODE (fmode)) 3935 if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode) 3936 && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing) 3937 break; 3938 3939 if (fmode == VOIDmode) 3940 { 3941 /* There is no such mode. Pretend the target is wide enough. */ 3942 fmode = GET_MODE (to); 3943 3944 /* Avoid double-rounding when TO is narrower than FROM. */ 3945 if ((significand_size (fmode) + 1) 3946 < GET_MODE_BITSIZE (GET_MODE (from))) 3947 { 3948 rtx temp1; 3949 rtx neglabel = gen_label_rtx (); 3950 3951 /* Don't use TARGET if it isn't a register, is a hard register, 3952 or is the wrong mode. */ 3953 if (GET_CODE (target) != REG 3954 || REGNO (target) < FIRST_PSEUDO_REGISTER 3955 || GET_MODE (target) != fmode) 3956 target = gen_reg_rtx (fmode); 3957 3958 imode = GET_MODE (from); 3959 do_pending_stack_adjust (); 3960 3961 /* Test whether the sign bit is set. */ 3962 emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, imode, 0, 0); 3963 emit_jump_insn (gen_blt (neglabel)); 3964 3965 /* The sign bit is not set. Convert as signed. */ 3966 expand_float (target, from, 0); 3967 emit_jump_insn (gen_jump (label)); 3968 emit_barrier (); 3969 3970 /* The sign bit is set. 3971 Convert to a usable (positive signed) value by shifting right 3972 one bit, while remembering if a nonzero bit was shifted 3973 out; i.e., compute (from & 1) | (from >> 1). */ 3974 3975 emit_label (neglabel); 3976 temp = expand_binop (imode, and_optab, from, const1_rtx, 3977 NULL_RTX, 1, OPTAB_LIB_WIDEN); 3978 temp1 = expand_shift (RSHIFT_EXPR, imode, from, integer_one_node, 3979 NULL_RTX, 1); 3980 temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1, 3981 OPTAB_LIB_WIDEN); 3982 expand_float (target, temp, 0); 3983 3984 /* Multiply by 2 to undo the shift above. */ 3985 temp = expand_binop (fmode, add_optab, target, target, 3986 target, 0, OPTAB_LIB_WIDEN); 3987 if (temp != target) 3988 emit_move_insn (target, temp); 3989 3990 do_pending_stack_adjust (); 3991 emit_label (label); 3992 goto done; 3993 } 3994 } 3995 3996 /* If we are about to do some arithmetic to correct for an 3997 unsigned operand, do it in a pseudo-register. */ 3998 3999 if (GET_MODE (to) != fmode 4000 || GET_CODE (to) != REG || REGNO (to) < FIRST_PSEUDO_REGISTER) 4001 target = gen_reg_rtx (fmode); 4002 4003 /* Convert as signed integer to floating. */ 4004 expand_float (target, from, 0); 4005 4006 /* If FROM is negative (and therefore TO is negative), 4007 correct its value by 2**bitwidth. */ 4008 4009 do_pending_stack_adjust (); 4010 emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from), 4011 0, 0, label); 4012 4013 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1). 4014 Rather than setting up a dconst_dot_5, let's hope SCO 4015 fixes the bug. */ 4016 offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from))); 4017 temp = expand_binop (fmode, add_optab, target, 4018 CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode), 4019 target, 0, OPTAB_LIB_WIDEN); 4020 if (temp != target) 4021 emit_move_insn (target, temp); 4022 4023 do_pending_stack_adjust (); 4024 emit_label (label); 4025 goto done; 4026 } 4027#endif 4028 4029 /* No hardware instruction available; call a library routine to convert from 4030 SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */ 4031 { 4032 rtx libfcn; 4033 rtx insns; 4034 rtx value; 4035 4036 to = protect_from_queue (to, 1); 4037 from = protect_from_queue (from, 0); 4038 4039 if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode)) 4040 from = convert_to_mode (SImode, from, unsignedp); 4041 4042 if (flag_force_mem) 4043 from = force_not_mem (from); 4044 4045 if (GET_MODE (to) == SFmode) 4046 { 4047 if (GET_MODE (from) == SImode) 4048 libfcn = floatsisf_libfunc; 4049 else if (GET_MODE (from) == DImode) 4050 libfcn = floatdisf_libfunc; 4051 else if (GET_MODE (from) == TImode) 4052 libfcn = floattisf_libfunc; 4053 else 4054 abort (); 4055 } 4056 else if (GET_MODE (to) == DFmode) 4057 { 4058 if (GET_MODE (from) == SImode) 4059 libfcn = floatsidf_libfunc; 4060 else if (GET_MODE (from) == DImode) 4061 libfcn = floatdidf_libfunc; 4062 else if (GET_MODE (from) == TImode) 4063 libfcn = floattidf_libfunc; 4064 else 4065 abort (); 4066 } 4067 else if (GET_MODE (to) == XFmode) 4068 { 4069 if (GET_MODE (from) == SImode) 4070 libfcn = floatsixf_libfunc; 4071 else if (GET_MODE (from) == DImode) 4072 libfcn = floatdixf_libfunc; 4073 else if (GET_MODE (from) == TImode) 4074 libfcn = floattixf_libfunc; 4075 else 4076 abort (); 4077 } 4078 else if (GET_MODE (to) == TFmode) 4079 { 4080 if (GET_MODE (from) == SImode) 4081 libfcn = floatsitf_libfunc; 4082 else if (GET_MODE (from) == DImode) 4083 libfcn = floatditf_libfunc; 4084 else if (GET_MODE (from) == TImode) 4085 libfcn = floattitf_libfunc; 4086 else 4087 abort (); 4088 } 4089 else 4090 abort (); 4091 4092 start_sequence (); 4093 4094 value = emit_library_call_value (libfcn, NULL_RTX, 1, 4095 GET_MODE (to), 4096 1, from, GET_MODE (from)); 4097 insns = get_insns (); 4098 end_sequence (); 4099 4100 emit_libcall_block (insns, target, value, 4101 gen_rtx_FLOAT (GET_MODE (to), from)); 4102 } 4103 4104 done: 4105 4106 /* Copy result to requested destination 4107 if we have been computing in a temp location. */ 4108 4109 if (target != to) 4110 { 4111 if (GET_MODE (target) == GET_MODE (to)) 4112 emit_move_insn (to, target); 4113 else 4114 convert_move (to, target, 0); 4115 } 4116} 4117 4118/* expand_fix: generate code to convert FROM to fixed point 4119 and store in TO. FROM must be floating point. */ 4120 4121static rtx 4122ftruncify (x) 4123 rtx x; 4124{ 4125 rtx temp = gen_reg_rtx (GET_MODE (x)); 4126 return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0); 4127} 4128 4129void 4130expand_fix (to, from, unsignedp) 4131 register rtx to, from; 4132 int unsignedp; 4133{ 4134 enum insn_code icode; 4135 register rtx target = to; 4136 enum machine_mode fmode, imode; 4137 int must_trunc = 0; 4138 rtx libfcn = 0; 4139 4140 /* We first try to find a pair of modes, one real and one integer, at 4141 least as wide as FROM and TO, respectively, in which we can open-code 4142 this conversion. If the integer mode is wider than the mode of TO, 4143 we can do the conversion either signed or unsigned. */ 4144 4145 for (imode = GET_MODE (to); imode != VOIDmode; 4146 imode = GET_MODE_WIDER_MODE (imode)) 4147 for (fmode = GET_MODE (from); fmode != VOIDmode; 4148 fmode = GET_MODE_WIDER_MODE (fmode)) 4149 { 4150 int doing_unsigned = unsignedp; 4151 4152 icode = can_fix_p (imode, fmode, unsignedp, &must_trunc); 4153 if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp) 4154 icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0; 4155 4156 if (icode != CODE_FOR_nothing) 4157 { 4158 to = protect_from_queue (to, 1); 4159 from = protect_from_queue (from, 0); 4160 4161 if (fmode != GET_MODE (from)) 4162 from = convert_to_mode (fmode, from, 0); 4163 4164 if (must_trunc) 4165 from = ftruncify (from); 4166 4167 if (imode != GET_MODE (to)) 4168 target = gen_reg_rtx (imode); 4169 4170 emit_unop_insn (icode, target, from, 4171 doing_unsigned ? UNSIGNED_FIX : FIX); 4172 if (target != to) 4173 convert_move (to, target, unsignedp); 4174 return; 4175 } 4176 } 4177 4178#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) 4179 /* For an unsigned conversion, there is one more way to do it. 4180 If we have a signed conversion, we generate code that compares 4181 the real value to the largest representable positive number. If if 4182 is smaller, the conversion is done normally. Otherwise, subtract 4183 one plus the highest signed number, convert, and add it back. 4184 4185 We only need to check all real modes, since we know we didn't find 4186 anything with a wider integer mode. */ 4187 4188 if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT) 4189 for (fmode = GET_MODE (from); fmode != VOIDmode; 4190 fmode = GET_MODE_WIDER_MODE (fmode)) 4191 /* Make sure we won't lose significant bits doing this. */ 4192 if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to)) 4193 && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0, 4194 &must_trunc)) 4195 { 4196 int bitsize; 4197 REAL_VALUE_TYPE offset; 4198 rtx limit, lab1, lab2, insn; 4199 4200 bitsize = GET_MODE_BITSIZE (GET_MODE (to)); 4201 offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1); 4202 limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode); 4203 lab1 = gen_label_rtx (); 4204 lab2 = gen_label_rtx (); 4205 4206 emit_queue (); 4207 to = protect_from_queue (to, 1); 4208 from = protect_from_queue (from, 0); 4209 4210 if (flag_force_mem) 4211 from = force_not_mem (from); 4212 4213 if (fmode != GET_MODE (from)) 4214 from = convert_to_mode (fmode, from, 0); 4215 4216 /* See if we need to do the subtraction. */ 4217 do_pending_stack_adjust (); 4218 emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from), 4219 0, 0, lab1); 4220 4221 /* If not, do the signed "fix" and branch around fixup code. */ 4222 expand_fix (to, from, 0); 4223 emit_jump_insn (gen_jump (lab2)); 4224 emit_barrier (); 4225 4226 /* Otherwise, subtract 2**(N-1), convert to signed number, 4227 then add 2**(N-1). Do the addition using XOR since this 4228 will often generate better code. */ 4229 emit_label (lab1); 4230 target = expand_binop (GET_MODE (from), sub_optab, from, limit, 4231 NULL_RTX, 0, OPTAB_LIB_WIDEN); 4232 expand_fix (to, target, 0); 4233 target = expand_binop (GET_MODE (to), xor_optab, to, 4234 GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)), 4235 to, 1, OPTAB_LIB_WIDEN); 4236 4237 if (target != to) 4238 emit_move_insn (to, target); 4239 4240 emit_label (lab2); 4241 4242 if (mov_optab->handlers[(int) GET_MODE (to)].insn_code 4243 != CODE_FOR_nothing) 4244 { 4245 /* Make a place for a REG_NOTE and add it. */ 4246 insn = emit_move_insn (to, to); 4247 set_unique_reg_note (insn, 4248 REG_EQUAL, 4249 gen_rtx_fmt_e (UNSIGNED_FIX, 4250 GET_MODE (to), 4251 copy_rtx (from))); 4252 } 4253 return; 4254 } 4255#endif 4256 4257 /* We can't do it with an insn, so use a library call. But first ensure 4258 that the mode of TO is at least as wide as SImode, since those are the 4259 only library calls we know about. */ 4260 4261 if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode)) 4262 { 4263 target = gen_reg_rtx (SImode); 4264 4265 expand_fix (target, from, unsignedp); 4266 } 4267 else if (GET_MODE (from) == SFmode) 4268 { 4269 if (GET_MODE (to) == SImode) 4270 libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc; 4271 else if (GET_MODE (to) == DImode) 4272 libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc; 4273 else if (GET_MODE (to) == TImode) 4274 libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc; 4275 else 4276 abort (); 4277 } 4278 else if (GET_MODE (from) == DFmode) 4279 { 4280 if (GET_MODE (to) == SImode) 4281 libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc; 4282 else if (GET_MODE (to) == DImode) 4283 libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc; 4284 else if (GET_MODE (to) == TImode) 4285 libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc; 4286 else 4287 abort (); 4288 } 4289 else if (GET_MODE (from) == XFmode) 4290 { 4291 if (GET_MODE (to) == SImode) 4292 libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc; 4293 else if (GET_MODE (to) == DImode) 4294 libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc; 4295 else if (GET_MODE (to) == TImode) 4296 libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc; 4297 else 4298 abort (); 4299 } 4300 else if (GET_MODE (from) == TFmode) 4301 { 4302 if (GET_MODE (to) == SImode) 4303 libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc; 4304 else if (GET_MODE (to) == DImode) 4305 libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc; 4306 else if (GET_MODE (to) == TImode) 4307 libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc; 4308 else 4309 abort (); 4310 } 4311 else 4312 abort (); 4313 4314 if (libfcn) 4315 { 4316 rtx insns; 4317 rtx value; 4318 4319 to = protect_from_queue (to, 1); 4320 from = protect_from_queue (from, 0); 4321 4322 if (flag_force_mem) 4323 from = force_not_mem (from); 4324 4325 start_sequence (); 4326 4327 value = emit_library_call_value (libfcn, NULL_RTX, 1, GET_MODE (to), 4328 4329 1, from, GET_MODE (from)); 4330 insns = get_insns (); 4331 end_sequence (); 4332 4333 emit_libcall_block (insns, target, value, 4334 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX, 4335 GET_MODE (to), from)); 4336 } 4337 4338 if (target != to) 4339 { 4340 if (GET_MODE (to) == GET_MODE (target)) 4341 emit_move_insn (to, target); 4342 else 4343 convert_move (to, target, 0); 4344 } 4345} 4346 4347static optab 4348init_optab (code) 4349 enum rtx_code code; 4350{ 4351 int i; 4352 optab op = (optab) xmalloc (sizeof (struct optab)); 4353 op->code = code; 4354 for (i = 0; i < NUM_MACHINE_MODES; i++) 4355 { 4356 op->handlers[i].insn_code = CODE_FOR_nothing; 4357 op->handlers[i].libfunc = 0; 4358 } 4359 4360 if (code != UNKNOWN) 4361 code_to_optab[(int) code] = op; 4362 4363 return op; 4364} 4365 4366/* Initialize the libfunc fields of an entire group of entries in some 4367 optab. Each entry is set equal to a string consisting of a leading 4368 pair of underscores followed by a generic operation name followed by 4369 a mode name (downshifted to lower case) followed by a single character 4370 representing the number of operands for the given operation (which is 4371 usually one of the characters '2', '3', or '4'). 4372 4373 OPTABLE is the table in which libfunc fields are to be initialized. 4374 FIRST_MODE is the first machine mode index in the given optab to 4375 initialize. 4376 LAST_MODE is the last machine mode index in the given optab to 4377 initialize. 4378 OPNAME is the generic (string) name of the operation. 4379 SUFFIX is the character which specifies the number of operands for 4380 the given generic operation. 4381*/ 4382 4383static void 4384init_libfuncs (optable, first_mode, last_mode, opname, suffix) 4385 register optab optable; 4386 register int first_mode; 4387 register int last_mode; 4388 register const char *opname; 4389 register int suffix; 4390{ 4391 register int mode; 4392 register unsigned opname_len = strlen (opname); 4393 4394 for (mode = first_mode; (int) mode <= (int) last_mode; 4395 mode = (enum machine_mode) ((int) mode + 1)) 4396 { 4397 register char *mname = mode_name[(int) mode]; 4398 register unsigned mname_len = strlen (mname); 4399 register char *libfunc_name 4400 = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1); 4401 register char *p; 4402 register const char *q; 4403 4404 p = libfunc_name; 4405 *p++ = '_'; 4406 *p++ = '_'; 4407 for (q = opname; *q; ) 4408 *p++ = *q++; 4409 for (q = mname; *q; q++) 4410 *p++ = tolower ((unsigned char)*q); 4411 *p++ = suffix; 4412 *p++ = '\0'; 4413 optable->handlers[(int) mode].libfunc 4414 = gen_rtx_SYMBOL_REF (Pmode, libfunc_name); 4415 } 4416} 4417 4418/* Initialize the libfunc fields of an entire group of entries in some 4419 optab which correspond to all integer mode operations. The parameters 4420 have the same meaning as similarly named ones for the `init_libfuncs' 4421 routine. (See above). */ 4422 4423static void 4424init_integral_libfuncs (optable, opname, suffix) 4425 register optab optable; 4426 register const char *opname; 4427 register int suffix; 4428{ 4429 init_libfuncs (optable, SImode, TImode, opname, suffix); 4430} 4431 4432/* Initialize the libfunc fields of an entire group of entries in some 4433 optab which correspond to all real mode operations. The parameters 4434 have the same meaning as similarly named ones for the `init_libfuncs' 4435 routine. (See above). */ 4436 4437static void 4438init_floating_libfuncs (optable, opname, suffix) 4439 register optab optable; 4440 register const char *opname; 4441 register int suffix; 4442{ 4443 init_libfuncs (optable, SFmode, TFmode, opname, suffix); 4444} 4445 4446 4447/* Call this once to initialize the contents of the optabs 4448 appropriately for the current target machine. */ 4449 4450void 4451init_optabs () 4452{ 4453 int i; 4454#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC 4455 int j; 4456#endif 4457 4458 enum insn_code *p; 4459 4460 /* Start by initializing all tables to contain CODE_FOR_nothing. */ 4461 4462 for (p = fixtab[0][0]; 4463 p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]); 4464 p++) 4465 *p = CODE_FOR_nothing; 4466 4467 for (p = fixtrunctab[0][0]; 4468 p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]); 4469 p++) 4470 *p = CODE_FOR_nothing; 4471 4472 for (p = floattab[0][0]; 4473 p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]); 4474 p++) 4475 *p = CODE_FOR_nothing; 4476 4477 for (p = extendtab[0][0]; 4478 p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0]; 4479 p++) 4480 *p = CODE_FOR_nothing; 4481 4482 for (i = 0; i < NUM_RTX_CODE; i++) 4483 setcc_gen_code[i] = CODE_FOR_nothing; 4484 4485#ifdef HAVE_conditional_move 4486 for (i = 0; i < NUM_MACHINE_MODES; i++) 4487 movcc_gen_code[i] = CODE_FOR_nothing; 4488#endif 4489 4490 add_optab = init_optab (PLUS); 4491 sub_optab = init_optab (MINUS); 4492 smul_optab = init_optab (MULT); 4493 smul_highpart_optab = init_optab (UNKNOWN); 4494 umul_highpart_optab = init_optab (UNKNOWN); 4495 smul_widen_optab = init_optab (UNKNOWN); 4496 umul_widen_optab = init_optab (UNKNOWN); 4497 sdiv_optab = init_optab (DIV); 4498 sdivmod_optab = init_optab (UNKNOWN); 4499 udiv_optab = init_optab (UDIV); 4500 udivmod_optab = init_optab (UNKNOWN); 4501 smod_optab = init_optab (MOD); 4502 umod_optab = init_optab (UMOD); 4503 flodiv_optab = init_optab (DIV); 4504 ftrunc_optab = init_optab (UNKNOWN); 4505 and_optab = init_optab (AND); 4506 ior_optab = init_optab (IOR); 4507 xor_optab = init_optab (XOR); 4508 ashl_optab = init_optab (ASHIFT); 4509 ashr_optab = init_optab (ASHIFTRT); 4510 lshr_optab = init_optab (LSHIFTRT); 4511 rotl_optab = init_optab (ROTATE); 4512 rotr_optab = init_optab (ROTATERT); 4513 smin_optab = init_optab (SMIN); 4514 smax_optab = init_optab (SMAX); 4515 umin_optab = init_optab (UMIN); 4516 umax_optab = init_optab (UMAX); 4517 mov_optab = init_optab (UNKNOWN); 4518 movstrict_optab = init_optab (UNKNOWN); 4519 cmp_optab = init_optab (UNKNOWN); 4520 ucmp_optab = init_optab (UNKNOWN); 4521 tst_optab = init_optab (UNKNOWN); 4522 neg_optab = init_optab (NEG); 4523 abs_optab = init_optab (ABS); 4524 one_cmpl_optab = init_optab (NOT); 4525 ffs_optab = init_optab (FFS); 4526 sqrt_optab = init_optab (SQRT); 4527 sin_optab = init_optab (UNKNOWN); 4528 cos_optab = init_optab (UNKNOWN); 4529 strlen_optab = init_optab (UNKNOWN); 4530 4531 for (i = 0; i < NUM_MACHINE_MODES; i++) 4532 { 4533 movstr_optab[i] = CODE_FOR_nothing; 4534 clrstr_optab[i] = CODE_FOR_nothing; 4535 4536#ifdef HAVE_SECONDARY_RELOADS 4537 reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing; 4538#endif 4539 } 4540 4541 /* Fill in the optabs with the insns we support. */ 4542 init_all_optabs (); 4543 4544#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC 4545 /* This flag says the same insns that convert to a signed fixnum 4546 also convert validly to an unsigned one. */ 4547 for (i = 0; i < NUM_MACHINE_MODES; i++) 4548 for (j = 0; j < NUM_MACHINE_MODES; j++) 4549 fixtrunctab[i][j][1] = fixtrunctab[i][j][0]; 4550#endif 4551 4552#ifdef EXTRA_CC_MODES 4553 init_mov_optab (); 4554#endif 4555 4556 /* Initialize the optabs with the names of the library functions. */ 4557 init_integral_libfuncs (add_optab, "add", '3'); 4558 init_floating_libfuncs (add_optab, "add", '3'); 4559 init_integral_libfuncs (sub_optab, "sub", '3'); 4560 init_floating_libfuncs (sub_optab, "sub", '3'); 4561 init_integral_libfuncs (smul_optab, "mul", '3'); 4562 init_floating_libfuncs (smul_optab, "mul", '3'); 4563 init_integral_libfuncs (sdiv_optab, "div", '3'); 4564 init_integral_libfuncs (udiv_optab, "udiv", '3'); 4565 init_integral_libfuncs (sdivmod_optab, "divmod", '4'); 4566 init_integral_libfuncs (udivmod_optab, "udivmod", '4'); 4567 init_integral_libfuncs (smod_optab, "mod", '3'); 4568 init_integral_libfuncs (umod_optab, "umod", '3'); 4569 init_floating_libfuncs (flodiv_optab, "div", '3'); 4570 init_floating_libfuncs (ftrunc_optab, "ftrunc", '2'); 4571 init_integral_libfuncs (and_optab, "and", '3'); 4572 init_integral_libfuncs (ior_optab, "ior", '3'); 4573 init_integral_libfuncs (xor_optab, "xor", '3'); 4574 init_integral_libfuncs (ashl_optab, "ashl", '3'); 4575 init_integral_libfuncs (ashr_optab, "ashr", '3'); 4576 init_integral_libfuncs (lshr_optab, "lshr", '3'); 4577 init_integral_libfuncs (smin_optab, "min", '3'); 4578 init_floating_libfuncs (smin_optab, "min", '3'); 4579 init_integral_libfuncs (smax_optab, "max", '3'); 4580 init_floating_libfuncs (smax_optab, "max", '3'); 4581 init_integral_libfuncs (umin_optab, "umin", '3'); 4582 init_integral_libfuncs (umax_optab, "umax", '3'); 4583 init_integral_libfuncs (neg_optab, "neg", '2'); 4584 init_floating_libfuncs (neg_optab, "neg", '2'); 4585 init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2'); 4586 init_integral_libfuncs (ffs_optab, "ffs", '2'); 4587 4588 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */ 4589 init_integral_libfuncs (cmp_optab, "cmp", '2'); 4590 init_integral_libfuncs (ucmp_optab, "ucmp", '2'); 4591 init_floating_libfuncs (cmp_optab, "cmp", '2'); 4592 4593#ifdef MULSI3_LIBCALL 4594 smul_optab->handlers[(int) SImode].libfunc 4595 = gen_rtx_SYMBOL_REF (Pmode, MULSI3_LIBCALL); 4596#endif 4597#ifdef MULDI3_LIBCALL 4598 smul_optab->handlers[(int) DImode].libfunc 4599 = gen_rtx_SYMBOL_REF (Pmode, MULDI3_LIBCALL); 4600#endif 4601 4602#ifdef DIVSI3_LIBCALL 4603 sdiv_optab->handlers[(int) SImode].libfunc 4604 = gen_rtx_SYMBOL_REF (Pmode, DIVSI3_LIBCALL); 4605#endif 4606#ifdef DIVDI3_LIBCALL 4607 sdiv_optab->handlers[(int) DImode].libfunc 4608 = gen_rtx_SYMBOL_REF (Pmode, DIVDI3_LIBCALL); 4609#endif 4610 4611#ifdef UDIVSI3_LIBCALL 4612 udiv_optab->handlers[(int) SImode].libfunc 4613 = gen_rtx_SYMBOL_REF (Pmode, UDIVSI3_LIBCALL); 4614#endif 4615#ifdef UDIVDI3_LIBCALL 4616 udiv_optab->handlers[(int) DImode].libfunc 4617 = gen_rtx_SYMBOL_REF (Pmode, UDIVDI3_LIBCALL); 4618#endif 4619 4620#ifdef MODSI3_LIBCALL 4621 smod_optab->handlers[(int) SImode].libfunc 4622 = gen_rtx_SYMBOL_REF (Pmode, MODSI3_LIBCALL); 4623#endif 4624#ifdef MODDI3_LIBCALL 4625 smod_optab->handlers[(int) DImode].libfunc 4626 = gen_rtx_SYMBOL_REF (Pmode, MODDI3_LIBCALL); 4627#endif 4628 4629#ifdef UMODSI3_LIBCALL 4630 umod_optab->handlers[(int) SImode].libfunc 4631 = gen_rtx_SYMBOL_REF (Pmode, UMODSI3_LIBCALL); 4632#endif 4633#ifdef UMODDI3_LIBCALL 4634 umod_optab->handlers[(int) DImode].libfunc 4635 = gen_rtx_SYMBOL_REF (Pmode, UMODDI3_LIBCALL); 4636#endif 4637 4638 /* Use cabs for DC complex abs, since systems generally have cabs. 4639 Don't define any libcall for SCmode, so that cabs will be used. */ 4640 abs_optab->handlers[(int) DCmode].libfunc 4641 = gen_rtx_SYMBOL_REF (Pmode, "cabs"); 4642 4643 /* The ffs function operates on `int'. */ 4644#ifndef INT_TYPE_SIZE 4645#define INT_TYPE_SIZE BITS_PER_WORD 4646#endif 4647 ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)] .libfunc 4648 = gen_rtx_SYMBOL_REF (Pmode, "ffs"); 4649 4650 extendsfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsfdf2"); 4651 extendsfxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsfxf2"); 4652 extendsftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsftf2"); 4653 extenddfxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extenddfxf2"); 4654 extenddftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extenddftf2"); 4655 4656 truncdfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncdfsf2"); 4657 truncxfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncxfsf2"); 4658 trunctfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__trunctfsf2"); 4659 truncxfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncxfdf2"); 4660 trunctfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__trunctfdf2"); 4661 4662 memcpy_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memcpy"); 4663 bcopy_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bcopy"); 4664 memcmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memcmp"); 4665 bcmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gcc_bcmp"); 4666 memset_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memset"); 4667 bzero_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bzero"); 4668 4669 throw_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__throw"); 4670 rethrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__rethrow"); 4671 sjthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjthrow"); 4672 sjpopnthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjpopnthrow"); 4673 terminate_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__terminate"); 4674 eh_rtime_match_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eh_rtime_match"); 4675#ifndef DONT_USE_BUILTIN_SETJMP 4676 setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_setjmp"); 4677 longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_longjmp"); 4678#else 4679 setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "setjmp"); 4680 longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "longjmp"); 4681#endif 4682 4683 eqhf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqhf2"); 4684 nehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nehf2"); 4685 gthf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gthf2"); 4686 gehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gehf2"); 4687 lthf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lthf2"); 4688 lehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lehf2"); 4689 4690 eqsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqsf2"); 4691 nesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nesf2"); 4692 gtsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtsf2"); 4693 gesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gesf2"); 4694 ltsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltsf2"); 4695 lesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lesf2"); 4696 4697 eqdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqdf2"); 4698 nedf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nedf2"); 4699 gtdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtdf2"); 4700 gedf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gedf2"); 4701 ltdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltdf2"); 4702 ledf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ledf2"); 4703 4704 eqxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqxf2"); 4705 nexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nexf2"); 4706 gtxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtxf2"); 4707 gexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gexf2"); 4708 ltxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltxf2"); 4709 lexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lexf2"); 4710 4711 eqtf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqtf2"); 4712 netf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__netf2"); 4713 gttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gttf2"); 4714 getf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__getf2"); 4715 lttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lttf2"); 4716 letf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__letf2"); 4717 4718 floatsisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsisf"); 4719 floatdisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdisf"); 4720 floattisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattisf"); 4721 4722 floatsidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsidf"); 4723 floatdidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdidf"); 4724 floattidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattidf"); 4725 4726 floatsixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsixf"); 4727 floatdixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdixf"); 4728 floattixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattixf"); 4729 4730 floatsitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsitf"); 4731 floatditf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatditf"); 4732 floattitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattitf"); 4733 4734 fixsfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfsi"); 4735 fixsfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfdi"); 4736 fixsfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfti"); 4737 4738 fixdfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfsi"); 4739 fixdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfdi"); 4740 fixdfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfti"); 4741 4742 fixxfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfsi"); 4743 fixxfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfdi"); 4744 fixxfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfti"); 4745 4746 fixtfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfsi"); 4747 fixtfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfdi"); 4748 fixtfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfti"); 4749 4750 fixunssfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfsi"); 4751 fixunssfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfdi"); 4752 fixunssfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfti"); 4753 4754 fixunsdfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfsi"); 4755 fixunsdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfdi"); 4756 fixunsdfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfti"); 4757 4758 fixunsxfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfsi"); 4759 fixunsxfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfdi"); 4760 fixunsxfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfti"); 4761 4762 fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfsi"); 4763 fixunstfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfdi"); 4764 fixunstfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfti"); 4765 4766 /* For check-memory-usage. */ 4767 chkr_check_addr_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_addr"); 4768 chkr_set_right_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_set_right"); 4769 chkr_copy_bitmap_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_copy_bitmap"); 4770 chkr_check_exec_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_exec"); 4771 chkr_check_str_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_str"); 4772 4773 /* For function entry/exit instrumentation. */ 4774 profile_function_entry_libfunc 4775 = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_enter"); 4776 profile_function_exit_libfunc 4777 = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_exit"); 4778 4779#ifdef HAVE_conditional_trap 4780 init_traps (); 4781#endif 4782 4783#ifdef INIT_TARGET_OPTABS 4784 /* Allow the target to add more libcalls or rename some, etc. */ 4785 INIT_TARGET_OPTABS; 4786#endif 4787} 4788 4789#ifdef BROKEN_LDEXP 4790 4791/* SCO 3.2 apparently has a broken ldexp. */ 4792 4793double 4794ldexp(x,n) 4795 double x; 4796 int n; 4797{ 4798 if (n > 0) 4799 while (n--) 4800 x *= 2; 4801 4802 return x; 4803} 4804#endif /* BROKEN_LDEXP */ 4805 4806#ifdef HAVE_conditional_trap 4807/* The insn generating function can not take an rtx_code argument. 4808 TRAP_RTX is used as an rtx argument. Its code is replaced with 4809 the code to be used in the trap insn and all other fields are 4810 ignored. 4811 4812 ??? Will need to change to support garbage collection. */ 4813static rtx trap_rtx; 4814 4815static void 4816init_traps () 4817{ 4818 if (HAVE_conditional_trap) 4819 trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX); 4820} 4821#endif 4822 4823/* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition 4824 CODE. Return 0 on failure. */ 4825 4826rtx 4827gen_cond_trap (code, op1, op2, tcode) 4828 enum rtx_code code ATTRIBUTE_UNUSED; 4829 rtx op1, op2 ATTRIBUTE_UNUSED, tcode ATTRIBUTE_UNUSED; 4830{ 4831 enum machine_mode mode = GET_MODE (op1); 4832 4833 if (mode == VOIDmode) 4834 return 0; 4835 4836#ifdef HAVE_conditional_trap 4837 if (HAVE_conditional_trap 4838 && cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 4839 { 4840 rtx insn; 4841 emit_insn (GEN_FCN (cmp_optab->handlers[(int) mode].insn_code) (op1, op2)); 4842 PUT_CODE (trap_rtx, code); 4843 insn = gen_conditional_trap (trap_rtx, tcode); 4844 if (insn) 4845 return insn; 4846 } 4847#endif 4848 4849 return 0; 4850} 4851