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