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