00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "config.h"
00029 #include "system.h"
00030 #include "toplev.h"
00031 #include "rtl.h"
00032 #include "tree.h"
00033 #include "tm_p.h"
00034 #include "flags.h"
00035 #include "insn-config.h"
00036 #include "expr.h"
00037 #include "optabs.h"
00038 #include "real.h"
00039 #include "recog.h"
00040 #include "langhooks.h"
00041
00042 static void store_fixed_bit_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
00043 unsigned HOST_WIDE_INT,
00044 unsigned HOST_WIDE_INT, rtx));
00045 static void store_split_bit_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
00046 unsigned HOST_WIDE_INT, rtx));
00047 static rtx extract_fixed_bit_field PARAMS ((enum machine_mode, rtx,
00048 unsigned HOST_WIDE_INT,
00049 unsigned HOST_WIDE_INT,
00050 unsigned HOST_WIDE_INT,
00051 rtx, int));
00052 static rtx mask_rtx PARAMS ((enum machine_mode, int,
00053 int, int));
00054 static rtx lshift_value PARAMS ((enum machine_mode, rtx,
00055 int, int));
00056 static rtx extract_split_bit_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
00057 unsigned HOST_WIDE_INT, int));
00058 static void do_cmp_and_jump PARAMS ((rtx, rtx, enum rtx_code,
00059 enum machine_mode, rtx));
00060
00061
00062
00063
00064
00065
00066 static int sdiv_pow2_cheap, smod_pow2_cheap;
00067
00068 #ifndef SLOW_UNALIGNED_ACCESS
00069 #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
00070 #endif
00071
00072
00073
00074
00075
00076 #ifndef MAX_BITS_PER_WORD
00077 #define MAX_BITS_PER_WORD BITS_PER_WORD
00078 #endif
00079
00080
00081 #ifndef HAVE_insv
00082 #define HAVE_insv 0
00083 #define CODE_FOR_insv CODE_FOR_nothing
00084 #define gen_insv(a,b,c,d) NULL_RTX
00085 #endif
00086 #ifndef HAVE_extv
00087 #define HAVE_extv 0
00088 #define CODE_FOR_extv CODE_FOR_nothing
00089 #define gen_extv(a,b,c,d) NULL_RTX
00090 #endif
00091 #ifndef HAVE_extzv
00092 #define HAVE_extzv 0
00093 #define CODE_FOR_extzv CODE_FOR_nothing
00094 #define gen_extzv(a,b,c,d) NULL_RTX
00095 #endif
00096
00097
00098
00099 static int add_cost, negate_cost, zero_cost;
00100 static int shift_cost[MAX_BITS_PER_WORD];
00101 static int shiftadd_cost[MAX_BITS_PER_WORD];
00102 static int shiftsub_cost[MAX_BITS_PER_WORD];
00103 static int mul_cost[NUM_MACHINE_MODES];
00104 static int div_cost[NUM_MACHINE_MODES];
00105 static int mul_widen_cost[NUM_MACHINE_MODES];
00106 static int mul_highpart_cost[NUM_MACHINE_MODES];
00107
00108 void
00109 init_expmed ()
00110 {
00111 rtx reg, shift_insn, shiftadd_insn, shiftsub_insn;
00112 int dummy;
00113 int m;
00114 enum machine_mode mode, wider_mode;
00115
00116 start_sequence ();
00117
00118
00119
00120 reg = gen_rtx_REG (word_mode, 10000);
00121
00122 zero_cost = rtx_cost (const0_rtx, 0);
00123 add_cost = rtx_cost (gen_rtx_PLUS (word_mode, reg, reg), SET);
00124
00125 shift_insn = emit_insn (gen_rtx_SET (VOIDmode, reg,
00126 gen_rtx_ASHIFT (word_mode, reg,
00127 const0_rtx)));
00128
00129 shiftadd_insn
00130 = emit_insn (gen_rtx_SET (VOIDmode, reg,
00131 gen_rtx_PLUS (word_mode,
00132 gen_rtx_MULT (word_mode,
00133 reg, const0_rtx),
00134 reg)));
00135
00136 shiftsub_insn
00137 = emit_insn (gen_rtx_SET (VOIDmode, reg,
00138 gen_rtx_MINUS (word_mode,
00139 gen_rtx_MULT (word_mode,
00140 reg, const0_rtx),
00141 reg)));
00142
00143 init_recog ();
00144
00145 shift_cost[0] = 0;
00146 shiftadd_cost[0] = shiftsub_cost[0] = add_cost;
00147
00148 for (m = 1; m < MAX_BITS_PER_WORD; m++)
00149 {
00150 rtx c_int = GEN_INT ((HOST_WIDE_INT) 1 << m);
00151 shift_cost[m] = shiftadd_cost[m] = shiftsub_cost[m] = 32000;
00152
00153 XEXP (SET_SRC (PATTERN (shift_insn)), 1) = GEN_INT (m);
00154 if (recog (PATTERN (shift_insn), shift_insn, &dummy) >= 0)
00155 shift_cost[m] = rtx_cost (SET_SRC (PATTERN (shift_insn)), SET);
00156
00157 XEXP (XEXP (SET_SRC (PATTERN (shiftadd_insn)), 0), 1) = c_int;
00158 if (recog (PATTERN (shiftadd_insn), shiftadd_insn, &dummy) >= 0)
00159 shiftadd_cost[m] = rtx_cost (SET_SRC (PATTERN (shiftadd_insn)), SET);
00160
00161 XEXP (XEXP (SET_SRC (PATTERN (shiftsub_insn)), 0), 1) = c_int;
00162 if (recog (PATTERN (shiftsub_insn), shiftsub_insn, &dummy) >= 0)
00163 shiftsub_cost[m] = rtx_cost (SET_SRC (PATTERN (shiftsub_insn)), SET);
00164 }
00165
00166 negate_cost = rtx_cost (gen_rtx_NEG (word_mode, reg), SET);
00167
00168 sdiv_pow2_cheap
00169 = (rtx_cost (gen_rtx_DIV (word_mode, reg, GEN_INT (32)), SET)
00170 <= 2 * add_cost);
00171 smod_pow2_cheap
00172 = (rtx_cost (gen_rtx_MOD (word_mode, reg, GEN_INT (32)), SET)
00173 <= 2 * add_cost);
00174
00175 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
00176 mode != VOIDmode;
00177 mode = GET_MODE_WIDER_MODE (mode))
00178 {
00179 reg = gen_rtx_REG (mode, 10000);
00180 div_cost[(int) mode] = rtx_cost (gen_rtx_UDIV (mode, reg, reg), SET);
00181 mul_cost[(int) mode] = rtx_cost (gen_rtx_MULT (mode, reg, reg), SET);
00182 wider_mode = GET_MODE_WIDER_MODE (mode);
00183 if (wider_mode != VOIDmode)
00184 {
00185 mul_widen_cost[(int) wider_mode]
00186 = rtx_cost (gen_rtx_MULT (wider_mode,
00187 gen_rtx_ZERO_EXTEND (wider_mode, reg),
00188 gen_rtx_ZERO_EXTEND (wider_mode, reg)),
00189 SET);
00190 mul_highpart_cost[(int) mode]
00191 = rtx_cost (gen_rtx_TRUNCATE
00192 (mode,
00193 gen_rtx_LSHIFTRT (wider_mode,
00194 gen_rtx_MULT (wider_mode,
00195 gen_rtx_ZERO_EXTEND
00196 (wider_mode, reg),
00197 gen_rtx_ZERO_EXTEND
00198 (wider_mode, reg)),
00199 GEN_INT (GET_MODE_BITSIZE (mode)))),
00200 SET);
00201 }
00202 }
00203
00204 end_sequence ();
00205 }
00206
00207
00208
00209
00210
00211 rtx
00212 negate_rtx (mode, x)
00213 enum machine_mode mode;
00214 rtx x;
00215 {
00216 rtx result = simplify_unary_operation (NEG, mode, x, mode);
00217
00218 if (result == 0)
00219 result = expand_unop (mode, neg_optab, x, NULL_RTX, 0);
00220
00221 return result;
00222 }
00223
00224
00225
00226
00227
00228 enum machine_mode
00229 mode_for_extraction (pattern, opno)
00230 enum extraction_pattern pattern;
00231 int opno;
00232 {
00233 const struct insn_data *data;
00234
00235 switch (pattern)
00236 {
00237 case EP_insv:
00238 if (HAVE_insv)
00239 {
00240 data = &insn_data[CODE_FOR_insv];
00241 break;
00242 }
00243 return MAX_MACHINE_MODE;
00244
00245 case EP_extv:
00246 if (HAVE_extv)
00247 {
00248 data = &insn_data[CODE_FOR_extv];
00249 break;
00250 }
00251 return MAX_MACHINE_MODE;
00252
00253 case EP_extzv:
00254 if (HAVE_extzv)
00255 {
00256 data = &insn_data[CODE_FOR_extzv];
00257 break;
00258 }
00259 return MAX_MACHINE_MODE;
00260
00261 default:
00262 abort ();
00263 }
00264
00265 if (opno == -1)
00266 return VOIDmode;
00267
00268
00269
00270 if (data->operand[opno].mode == VOIDmode)
00271 return word_mode;
00272 return data->operand[opno].mode;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 rtx
00292 store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, total_size)
00293 rtx str_rtx;
00294 unsigned HOST_WIDE_INT bitsize;
00295 unsigned HOST_WIDE_INT bitnum;
00296 enum machine_mode fieldmode;
00297 rtx value;
00298 HOST_WIDE_INT total_size;
00299 {
00300 unsigned int unit
00301 = (GET_CODE (str_rtx) == MEM) ? BITS_PER_UNIT : BITS_PER_WORD;
00302 unsigned HOST_WIDE_INT offset = bitnum / unit;
00303 unsigned HOST_WIDE_INT bitpos = bitnum % unit;
00304 rtx op0 = str_rtx;
00305 int byte_offset;
00306
00307 enum machine_mode op_mode = mode_for_extraction (EP_insv, 3);
00308
00309
00310
00311 if (total_size >= 0)
00312 total_size -= (bitpos / BIGGEST_ALIGNMENT
00313 * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
00314
00315 while (GET_CODE (op0) == SUBREG)
00316 {
00317
00318
00319
00320
00321
00322 offset += (SUBREG_BYTE (op0) / UNITS_PER_WORD);
00323
00324
00325 op0 = SUBREG_REG (op0);
00326 }
00327
00328 value = protect_from_queue (value, 0);
00329
00330 if (flag_force_mem)
00331 {
00332 int old_generating_concat_p = generating_concat_p;
00333 generating_concat_p = 0;
00334 value = force_not_mem (value);
00335 generating_concat_p = old_generating_concat_p;
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345 byte_offset = (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
00346 + (offset * UNITS_PER_WORD);
00347
00348 if (bitpos == 0
00349 && bitsize == GET_MODE_BITSIZE (fieldmode)
00350 && (GET_CODE (op0) != MEM
00351 ? ((GET_MODE_SIZE (fieldmode) >= UNITS_PER_WORD
00352 || GET_MODE_SIZE (GET_MODE (op0)) == GET_MODE_SIZE (fieldmode))
00353 && byte_offset % GET_MODE_SIZE (fieldmode) == 0)
00354 : (! SLOW_UNALIGNED_ACCESS (fieldmode, MEM_ALIGN (op0))
00355 || (offset * BITS_PER_UNIT % bitsize == 0
00356 && MEM_ALIGN (op0) % GET_MODE_BITSIZE (fieldmode) == 0))))
00357 {
00358 if (GET_MODE (op0) != fieldmode)
00359 {
00360 if (GET_CODE (op0) == SUBREG)
00361 {
00362 if (GET_MODE (SUBREG_REG (op0)) == fieldmode
00363 || GET_MODE_CLASS (fieldmode) == MODE_INT
00364 || GET_MODE_CLASS (fieldmode) == MODE_PARTIAL_INT)
00365 op0 = SUBREG_REG (op0);
00366 else
00367
00368
00369
00370 abort ();
00371 }
00372 if (GET_CODE (op0) == REG)
00373 op0 = gen_rtx_SUBREG (fieldmode, op0, byte_offset);
00374 else
00375 op0 = adjust_address (op0, fieldmode, offset);
00376 }
00377 emit_move_insn (op0, value);
00378 return value;
00379 }
00380
00381
00382
00383
00384
00385 {
00386 enum machine_mode imode = int_mode_for_mode (GET_MODE (op0));
00387 if (imode != GET_MODE (op0))
00388 {
00389 if (GET_CODE (op0) == MEM)
00390 op0 = adjust_address (op0, imode, 0);
00391 else if (imode != BLKmode)
00392 op0 = gen_lowpart (imode, op0);
00393 else
00394 abort ();
00395 }
00396 }
00397
00398
00399
00400 if (GET_CODE (op0) == MEM)
00401 {
00402 op0 = shallow_copy_rtx (op0);
00403 set_mem_alias_set (op0, 0);
00404 set_mem_expr (op0, 0);
00405 }
00406
00407
00408
00409
00410 if (BYTES_BIG_ENDIAN
00411 && GET_CODE (op0) != MEM
00412 && unit > GET_MODE_BITSIZE (GET_MODE (op0)))
00413 bitpos += unit - GET_MODE_BITSIZE (GET_MODE (op0));
00414
00415
00416
00417
00418 if (GET_CODE (op0) != MEM
00419 && (BYTES_BIG_ENDIAN ? bitpos + bitsize == unit : bitpos == 0)
00420 && bitsize == GET_MODE_BITSIZE (fieldmode)
00421 && (movstrict_optab->handlers[(int) fieldmode].insn_code
00422 != CODE_FOR_nothing))
00423 {
00424 int icode = movstrict_optab->handlers[(int) fieldmode].insn_code;
00425
00426
00427 if (GET_CODE (value) == CONST_INT || GET_CODE (value) == REG)
00428 value = gen_lowpart (fieldmode, value);
00429 else if (!(GET_CODE (value) == SYMBOL_REF
00430 || GET_CODE (value) == LABEL_REF
00431 || GET_CODE (value) == CONST))
00432 value = convert_to_mode (fieldmode, value, 0);
00433
00434 if (! (*insn_data[icode].operand[1].predicate) (value, fieldmode))
00435 value = copy_to_mode_reg (fieldmode, value);
00436
00437 if (GET_CODE (op0) == SUBREG)
00438 {
00439 if (GET_MODE (SUBREG_REG (op0)) == fieldmode
00440 || GET_MODE_CLASS (fieldmode) == MODE_INT
00441 || GET_MODE_CLASS (fieldmode) == MODE_PARTIAL_INT)
00442 op0 = SUBREG_REG (op0);
00443 else
00444
00445
00446
00447 abort ();
00448 }
00449
00450 emit_insn (GEN_FCN (icode)
00451 (gen_rtx_SUBREG (fieldmode, op0,
00452 (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
00453 + (offset * UNITS_PER_WORD)),
00454 value));
00455
00456 return value;
00457 }
00458
00459
00460
00461 if (bitsize > BITS_PER_WORD)
00462 {
00463
00464
00465
00466
00467
00468
00469 unsigned int backwards = WORDS_BIG_ENDIAN && fieldmode != BLKmode;
00470 unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
00471 unsigned int i;
00472
00473
00474
00475
00476
00477
00478 fieldmode = smallest_mode_for_size (nwords * BITS_PER_WORD, MODE_INT);
00479
00480 for (i = 0; i < nwords; i++)
00481 {
00482
00483
00484 unsigned int wordnum = (backwards ? nwords - i - 1 : i);
00485 unsigned int bit_offset = (backwards
00486 ? MAX ((int) bitsize - ((int) i + 1)
00487 * BITS_PER_WORD,
00488 0)
00489 : (int) i * BITS_PER_WORD);
00490
00491 store_bit_field (op0, MIN (BITS_PER_WORD,
00492 bitsize - i * BITS_PER_WORD),
00493 bitnum + bit_offset, word_mode,
00494 operand_subword_force (value, wordnum,
00495 (GET_MODE (value) == VOIDmode
00496 ? fieldmode
00497 : GET_MODE (value))),
00498 total_size);
00499 }
00500 return value;
00501 }
00502
00503
00504
00505
00506
00507
00508
00509 if (GET_CODE (op0) != MEM)
00510 {
00511 if (offset != 0
00512 || GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD)
00513 {
00514 if (GET_CODE (op0) != REG)
00515 {
00516
00517
00518
00519
00520 if (GET_CODE (op0) == SUBREG
00521 && (GET_MODE_SIZE (GET_MODE (op0))
00522 == GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
00523 op0 = SUBREG_REG (op0);
00524 else
00525 abort ();
00526 }
00527 op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
00528 op0, (offset * UNITS_PER_WORD));
00529 }
00530 offset = 0;
00531 }
00532 else
00533 op0 = protect_from_queue (op0, 1);
00534
00535
00536
00537
00538
00539 if (GET_MODE_CLASS (GET_MODE (value)) != MODE_INT
00540 && GET_MODE_CLASS (GET_MODE (value)) != MODE_PARTIAL_INT)
00541 value = gen_lowpart ((GET_MODE (value) == VOIDmode
00542 ? word_mode : int_mode_for_mode (GET_MODE (value))),
00543 value);
00544
00545
00546
00547
00548 if (HAVE_insv
00549 && GET_MODE (value) != BLKmode
00550 && !(bitsize == 1 && GET_CODE (value) == CONST_INT)
00551
00552 && (GET_MODE_BITSIZE (op_mode) >= bitsize)
00553 && ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
00554 && (bitsize + bitpos > GET_MODE_BITSIZE (op_mode))))
00555 {
00556 int xbitpos = bitpos;
00557 rtx value1;
00558 rtx xop0 = op0;
00559 rtx last = get_last_insn ();
00560 rtx pat;
00561 enum machine_mode maxmode = mode_for_extraction (EP_insv, 3);
00562 int save_volatile_ok = volatile_ok;
00563
00564 volatile_ok = 1;
00565
00566
00567
00568
00569
00570 if (GET_CODE (op0) == MEM
00571 && ! ((*insn_data[(int) CODE_FOR_insv].operand[0].predicate)
00572 (op0, VOIDmode)))
00573 {
00574 rtx tempreg;
00575 enum machine_mode bestmode;
00576
00577
00578
00579
00580
00581
00582 if (GET_MODE (op0) == BLKmode
00583 || GET_MODE_SIZE (GET_MODE (op0)) > GET_MODE_SIZE (maxmode))
00584 bestmode
00585 = get_best_mode (bitsize, bitnum, MEM_ALIGN (op0), maxmode,
00586 MEM_VOLATILE_P (op0));
00587 else
00588 bestmode = GET_MODE (op0);
00589
00590 if (bestmode == VOIDmode
00591 || (SLOW_UNALIGNED_ACCESS (bestmode, MEM_ALIGN (op0))
00592 && GET_MODE_BITSIZE (bestmode) > MEM_ALIGN (op0)))
00593 goto insv_loses;
00594
00595
00596
00597 unit = GET_MODE_BITSIZE (bestmode);
00598 offset = (bitnum / unit) * GET_MODE_SIZE (bestmode);
00599 bitpos = bitnum % unit;
00600 op0 = adjust_address (op0, bestmode, offset);
00601
00602
00603
00604 tempreg = copy_to_reg (op0);
00605 store_bit_field (tempreg, bitsize, bitpos, fieldmode, value,
00606 total_size);
00607 emit_move_insn (op0, tempreg);
00608 return value;
00609 }
00610 volatile_ok = save_volatile_ok;
00611
00612
00613 if (GET_CODE (xop0) == MEM)
00614 xop0 = adjust_address (xop0, byte_mode, offset);
00615
00616
00617
00618 if (GET_CODE (xop0) == SUBREG)
00619
00620
00621 xop0 = gen_rtx_SUBREG (maxmode, SUBREG_REG (xop0), SUBREG_BYTE (xop0));
00622 if (GET_CODE (xop0) == REG && GET_MODE (xop0) != maxmode)
00623 xop0 = gen_rtx_SUBREG (maxmode, xop0, 0);
00624
00625
00626
00627
00628 if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
00629 xbitpos = unit - bitsize - xbitpos;
00630
00631
00632
00633 if (BITS_BIG_ENDIAN && GET_CODE (xop0) != MEM)
00634 xbitpos += GET_MODE_BITSIZE (maxmode) - unit;
00635
00636 unit = GET_MODE_BITSIZE (maxmode);
00637
00638
00639 value1 = value;
00640 if (GET_MODE (value) != maxmode)
00641 {
00642 if (GET_MODE_BITSIZE (GET_MODE (value)) >= bitsize)
00643 {
00644
00645
00646
00647
00648 if (GET_MODE_SIZE (GET_MODE (value)) < GET_MODE_SIZE (maxmode))
00649 {
00650 rtx tmp;
00651
00652 tmp = simplify_subreg (maxmode, value1, GET_MODE (value), 0);
00653 if (! tmp)
00654 tmp = simplify_gen_subreg (maxmode,
00655 force_reg (GET_MODE (value),
00656 value1),
00657 GET_MODE (value), 0);
00658 value1 = tmp;
00659 }
00660 else
00661 value1 = gen_lowpart (maxmode, value1);
00662 }
00663 else if (GET_CODE (value) == CONST_INT)
00664 value1 = gen_int_mode (INTVAL (value), maxmode);
00665 else if (!CONSTANT_P (value))
00666
00667
00668
00669
00670 abort ();
00671 }
00672
00673
00674
00675 if (! ((*insn_data[(int) CODE_FOR_insv].operand[3].predicate)
00676 (value1, maxmode)))
00677 value1 = force_reg (maxmode, value1);
00678
00679 pat = gen_insv (xop0, GEN_INT (bitsize), GEN_INT (xbitpos), value1);
00680 if (pat)
00681 emit_insn (pat);
00682 else
00683 {
00684 delete_insns_since (last);
00685 store_fixed_bit_field (op0, offset, bitsize, bitpos, value);
00686 }
00687 }
00688 else
00689 insv_loses:
00690
00691 store_fixed_bit_field (op0, offset, bitsize, bitpos, value);
00692 return value;
00693 }
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 static void
00707 store_fixed_bit_field (op0, offset, bitsize, bitpos, value)
00708 rtx op0;
00709 unsigned HOST_WIDE_INT offset, bitsize, bitpos;
00710 rtx value;
00711 {
00712 enum machine_mode mode;
00713 unsigned int total_bits = BITS_PER_WORD;
00714 rtx subtarget, temp;
00715 int all_zero = 0;
00716 int all_one = 0;
00717
00718
00719
00720
00721
00722
00723
00724
00725 if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
00726 {
00727 if (offset != 0)
00728 abort ();
00729
00730 if (bitsize + bitpos > BITS_PER_WORD)
00731 {
00732 store_split_bit_field (op0, bitsize, bitpos, value);
00733 return;
00734 }
00735 }
00736 else
00737 {
00738
00739
00740
00741
00742
00743 mode = GET_MODE (op0);
00744 if (GET_MODE_BITSIZE (mode) == 0
00745 || GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (word_mode))
00746 mode = word_mode;
00747 mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
00748 MEM_ALIGN (op0), mode, MEM_VOLATILE_P (op0));
00749
00750 if (mode == VOIDmode)
00751 {
00752
00753
00754 store_split_bit_field (op0, bitsize, bitpos + offset * BITS_PER_UNIT,
00755 value);
00756 return;
00757 }
00758
00759 total_bits = GET_MODE_BITSIZE (mode);
00760
00761
00762
00763
00764 if (bitpos >= total_bits)
00765 {
00766 offset += (bitpos / total_bits) * (total_bits / BITS_PER_UNIT);
00767 bitpos -= ((bitpos / total_bits) * (total_bits / BITS_PER_UNIT)
00768 * BITS_PER_UNIT);
00769 }
00770
00771
00772
00773
00774
00775 bitpos += (offset % (total_bits / BITS_PER_UNIT)) * BITS_PER_UNIT;
00776 offset -= (offset % (total_bits / BITS_PER_UNIT));
00777 op0 = adjust_address (op0, mode, offset);
00778 }
00779
00780 mode = GET_MODE (op0);
00781
00782
00783
00784
00785
00786
00787
00788 if (BYTES_BIG_ENDIAN)
00789
00790
00791
00792 bitpos = total_bits - bitsize - bitpos;
00793
00794
00795
00796
00797
00798
00799
00800 if (GET_CODE (value) == CONST_INT)
00801 {
00802 HOST_WIDE_INT v = INTVAL (value);
00803
00804 if (bitsize < HOST_BITS_PER_WIDE_INT)
00805 v &= ((HOST_WIDE_INT) 1 << bitsize) - 1;
00806
00807 if (v == 0)
00808 all_zero = 1;
00809 else if ((bitsize < HOST_BITS_PER_WIDE_INT
00810 && v == ((HOST_WIDE_INT) 1 << bitsize) - 1)
00811 || (bitsize == HOST_BITS_PER_WIDE_INT && v == -1))
00812 all_one = 1;
00813
00814 value = lshift_value (mode, value, bitpos, bitsize);
00815 }
00816 else
00817 {
00818 int must_and = (GET_MODE_BITSIZE (GET_MODE (value)) != bitsize
00819 && bitpos + bitsize != GET_MODE_BITSIZE (mode));
00820
00821 if (GET_MODE (value) != mode)
00822 {
00823 if ((GET_CODE (value) == REG || GET_CODE (value) == SUBREG)
00824 && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (value)))
00825 value = gen_lowpart (mode, value);
00826 else
00827 value = convert_to_mode (mode, value, 1);
00828 }
00829
00830 if (must_and)
00831 value = expand_binop (mode, and_optab, value,
00832 mask_rtx (mode, 0, bitsize, 0),
00833 NULL_RTX, 1, OPTAB_LIB_WIDEN);
00834 if (bitpos > 0)
00835 value = expand_shift (LSHIFT_EXPR, mode, value,
00836 build_int_2 (bitpos, 0), NULL_RTX, 1);
00837 }
00838
00839
00840
00841
00842 subtarget = (GET_CODE (op0) == REG || ! flag_force_mem) ? op0 : 0;
00843
00844 if (! all_one)
00845 {
00846 temp = expand_binop (mode, and_optab, op0,
00847 mask_rtx (mode, bitpos, bitsize, 1),
00848 subtarget, 1, OPTAB_LIB_WIDEN);
00849 subtarget = temp;
00850 }
00851 else
00852 temp = op0;
00853
00854
00855
00856 if (! all_zero)
00857 temp = expand_binop (mode, ior_optab, temp, value,
00858 subtarget, 1, OPTAB_LIB_WIDEN);
00859 if (op0 != temp)
00860 emit_move_insn (op0, temp);
00861 }
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872 static void
00873 store_split_bit_field (op0, bitsize, bitpos, value)
00874 rtx op0;
00875 unsigned HOST_WIDE_INT bitsize, bitpos;
00876 rtx value;
00877 {
00878 unsigned int unit;
00879 unsigned int bitsdone = 0;
00880
00881
00882
00883 if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
00884 unit = BITS_PER_WORD;
00885 else
00886 unit = MIN (MEM_ALIGN (op0), BITS_PER_WORD);
00887
00888 #ifdef SGI_MONGOOSE
00889 if (unit == 0)
00890 return;
00891 #endif
00892
00893
00894
00895
00896 if (CONSTANT_P (value) && GET_CODE (value) != CONST_INT)
00897 {
00898 rtx word = gen_lowpart_common (word_mode, value);
00899
00900 if (word && (value != word))
00901 value = word;
00902 else
00903 value = gen_lowpart_common (word_mode,
00904 force_reg (GET_MODE (value) != VOIDmode
00905 ? GET_MODE (value)
00906 : word_mode, value));
00907 }
00908 else if (GET_CODE (value) == ADDRESSOF)
00909 value = copy_to_reg (value);
00910
00911 while (bitsdone < bitsize)
00912 {
00913 unsigned HOST_WIDE_INT thissize;
00914 rtx part, word;
00915 unsigned HOST_WIDE_INT thispos;
00916 unsigned HOST_WIDE_INT offset;
00917
00918 offset = (bitpos + bitsdone) / unit;
00919 thispos = (bitpos + bitsdone) % unit;
00920
00921
00922
00923
00924 thissize = MIN (bitsize - bitsdone, BITS_PER_WORD);
00925 thissize = MIN (thissize, unit - thispos);
00926
00927 if (BYTES_BIG_ENDIAN)
00928 {
00929 int total_bits;
00930
00931
00932
00933
00934 if (GET_CODE (value) != MEM || GET_MODE (value) == BLKmode)
00935 total_bits = BITS_PER_WORD;
00936 else
00937 total_bits = GET_MODE_BITSIZE (GET_MODE (value));
00938
00939
00940 if (GET_CODE (value) == CONST_INT)
00941 part = GEN_INT (((unsigned HOST_WIDE_INT) (INTVAL (value))
00942 >> (bitsize - bitsdone - thissize))
00943 & (((HOST_WIDE_INT) 1 << thissize) - 1));
00944 else
00945
00946
00947
00948 part = extract_fixed_bit_field (word_mode, value, 0, thissize,
00949 total_bits - bitsize + bitsdone,
00950 NULL_RTX, 1);
00951 }
00952 else
00953 {
00954
00955 if (GET_CODE (value) == CONST_INT)
00956 part = GEN_INT (((unsigned HOST_WIDE_INT) (INTVAL (value))
00957 >> bitsdone)
00958 & (((HOST_WIDE_INT) 1 << thissize) - 1));
00959 else
00960 part = extract_fixed_bit_field (word_mode, value, 0, thissize,
00961 bitsdone, NULL_RTX, 1);
00962 }
00963
00964
00965
00966
00967
00968
00969
00970 if (GET_CODE (op0) == SUBREG)
00971 {
00972 int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset;
00973 word = operand_subword_force (SUBREG_REG (op0), word_offset,
00974 GET_MODE (SUBREG_REG (op0)));
00975 offset = 0;
00976 }
00977 else if (GET_CODE (op0) == REG)
00978 {
00979 word = operand_subword_force (op0, offset, GET_MODE (op0));
00980 offset = 0;
00981 }
00982 else
00983 word = op0;
00984
00985
00986
00987 store_fixed_bit_field (word, offset * unit / BITS_PER_UNIT, thissize,
00988 thispos, part);
00989 bitsdone += thissize;
00990 }
00991 }
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013 rtx
01014 extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
01015 target, mode, tmode, total_size)
01016 rtx str_rtx;
01017 unsigned HOST_WIDE_INT bitsize;
01018 unsigned HOST_WIDE_INT bitnum;
01019 int unsignedp;
01020 rtx target;
01021 enum machine_mode mode, tmode;
01022 HOST_WIDE_INT total_size;
01023 {
01024 unsigned int unit
01025 = (GET_CODE (str_rtx) == MEM) ? BITS_PER_UNIT : BITS_PER_WORD;
01026 unsigned HOST_WIDE_INT offset = bitnum / unit;
01027 unsigned HOST_WIDE_INT bitpos = bitnum % unit;
01028 rtx op0 = str_rtx;
01029 rtx spec_target = target;
01030 rtx spec_target_subreg = 0;
01031 enum machine_mode int_mode;
01032 enum machine_mode extv_mode = mode_for_extraction (EP_extv, 0);
01033 enum machine_mode extzv_mode = mode_for_extraction (EP_extzv, 0);
01034 enum machine_mode mode1;
01035 int byte_offset;
01036
01037
01038
01039 if (total_size >= 0)
01040 total_size -= (bitpos / BIGGEST_ALIGNMENT
01041 * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
01042
01043 if (tmode == VOIDmode)
01044 tmode = mode;
01045
01046 while (GET_CODE (op0) == SUBREG)
01047 {
01048 bitpos += SUBREG_BYTE (op0) * BITS_PER_UNIT;
01049 if (bitpos > unit)
01050 {
01051 offset += (bitpos / unit);
01052 bitpos %= unit;
01053 }
01054 op0 = SUBREG_REG (op0);
01055 }
01056
01057 if (GET_CODE (op0) == REG
01058 && mode == GET_MODE (op0)
01059 && bitnum == 0
01060 && bitsize == GET_MODE_BITSIZE (GET_MODE (op0)))
01061 {
01062
01063 return op0;
01064 }
01065
01066
01067
01068 {
01069 enum machine_mode imode = int_mode_for_mode (GET_MODE (op0));
01070 if (imode != GET_MODE (op0))
01071 {
01072 if (GET_CODE (op0) == MEM)
01073 op0 = adjust_address (op0, imode, 0);
01074 else if (imode != BLKmode)
01075 op0 = gen_lowpart (imode, op0);
01076 else
01077 abort ();
01078 }
01079 }
01080
01081
01082
01083 if (GET_CODE (op0) == MEM)
01084 {
01085 op0 = shallow_copy_rtx (op0);
01086 set_mem_alias_set (op0, 0);
01087 set_mem_expr (op0, 0);
01088 }
01089
01090
01091
01092
01093
01094
01095
01096 byte_offset = bitpos / BITS_PER_UNIT + offset * UNITS_PER_WORD;
01097
01098
01099
01100
01101 if (BYTES_BIG_ENDIAN
01102 && GET_CODE (op0) != MEM
01103 && unit > GET_MODE_BITSIZE (GET_MODE (op0)))
01104 bitpos += unit - GET_MODE_BITSIZE (GET_MODE (op0));
01105
01106
01107
01108
01109
01110 mode1 = (VECTOR_MODE_P (tmode)
01111 ? mode
01112 : mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0));
01113
01114 if (((GET_CODE (op0) != MEM
01115 && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
01116 GET_MODE_BITSIZE (GET_MODE (op0)))
01117 && GET_MODE_SIZE (mode1) != 0
01118 && byte_offset % GET_MODE_SIZE (mode1) == 0)
01119 || (GET_CODE (op0) == MEM
01120 && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (op0))
01121 || (offset * BITS_PER_UNIT % bitsize == 0
01122 && MEM_ALIGN (op0) % bitsize == 0))))
01123 && ((bitsize >= BITS_PER_WORD && bitsize == GET_MODE_BITSIZE (mode)
01124 && bitpos % BITS_PER_WORD == 0)
01125 || (mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0) != BLKmode
01126
01127
01128
01129
01130 && (BYTES_BIG_ENDIAN
01131 ? bitpos + bitsize == BITS_PER_WORD
01132 : bitpos == 0))))
01133 {
01134 if (mode1 != GET_MODE (op0))
01135 {
01136 if (GET_CODE (op0) == SUBREG)
01137 {
01138 if (GET_MODE (SUBREG_REG (op0)) == mode1
01139 || GET_MODE_CLASS (mode1) == MODE_INT
01140 || GET_MODE_CLASS (mode1) == MODE_PARTIAL_INT)
01141 op0 = SUBREG_REG (op0);
01142 else
01143
01144
01145
01146 goto no_subreg_mode_swap;
01147 }
01148 if (GET_CODE (op0) == REG)
01149 op0 = gen_rtx_SUBREG (mode1, op0, byte_offset);
01150 else
01151 op0 = adjust_address (op0, mode1, offset);
01152 }
01153 if (mode1 != mode)
01154 return convert_to_mode (tmode, op0, unsignedp);
01155 return op0;
01156 }
01157 no_subreg_mode_swap:
01158
01159
01160
01161 if (bitsize > BITS_PER_WORD)
01162 {
01163
01164
01165
01166
01167
01168 unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
01169 unsigned int i;
01170
01171 if (target == 0 || GET_CODE (target) != REG)
01172 target = gen_reg_rtx (mode);
01173
01174
01175 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
01176
01177 for (i = 0; i < nwords; i++)
01178 {
01179
01180
01181
01182 unsigned int wordnum
01183 = (WORDS_BIG_ENDIAN
01184 ? GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD - i - 1
01185 : i);
01186
01187 unsigned int bit_offset = (WORDS_BIG_ENDIAN
01188 ? MAX (0, ((int) bitsize - ((int) i + 1)
01189 * (int) BITS_PER_WORD))
01190 : (int) i * BITS_PER_WORD);
01191 rtx target_part = operand_subword (target, wordnum, 1, VOIDmode);
01192 rtx result_part
01193 = extract_bit_field (op0, MIN (BITS_PER_WORD,
01194 bitsize - i * BITS_PER_WORD),
01195 bitnum + bit_offset, 1, target_part, mode,
01196 word_mode, total_size);
01197
01198 if (target_part == 0)
01199 abort ();
01200
01201 if (result_part != target_part)
01202 emit_move_insn (target_part, result_part);
01203 }
01204
01205 if (unsignedp)
01206 {
01207
01208
01209 if (GET_MODE_SIZE (GET_MODE (target)) > nwords * UNITS_PER_WORD)
01210 {
01211 unsigned int i, total_words;
01212
01213 total_words = GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD;
01214 for (i = nwords; i < total_words; i++)
01215 emit_move_insn
01216 (operand_subword (target,
01217 WORDS_BIG_ENDIAN ? total_words - i - 1 : i,
01218 1, VOIDmode),
01219 const0_rtx);
01220 }
01221 return target;
01222 }
01223
01224
01225 target = expand_shift (LSHIFT_EXPR, mode, target,
01226 build_int_2 (GET_MODE_BITSIZE (mode) - bitsize, 0),
01227 NULL_RTX, 0);
01228 return expand_shift (RSHIFT_EXPR, mode, target,
01229 build_int_2 (GET_MODE_BITSIZE (mode) - bitsize, 0),
01230 NULL_RTX, 0);
01231 }
01232
01233
01234
01235
01236
01237
01238
01239
01240 int_mode = int_mode_for_mode (tmode);
01241 if (int_mode == BLKmode)
01242 int_mode = int_mode_for_mode (mode);
01243 if (int_mode == BLKmode)
01244 abort ();
01245
01246
01247
01248
01249
01250 if (GET_CODE (op0) != MEM)
01251 {
01252 if (offset != 0
01253 || GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD)
01254 {
01255 if (GET_CODE (op0) != REG)
01256 op0 = copy_to_reg (op0);
01257 op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
01258 op0, (offset * UNITS_PER_WORD));
01259 }
01260 offset = 0;
01261 }
01262 else
01263 op0 = protect_from_queue (str_rtx, 1);
01264
01265
01266
01267 if (unsignedp)
01268 {
01269 if (HAVE_extzv
01270 && (GET_MODE_BITSIZE (extzv_mode) >= bitsize)
01271 && ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
01272 && (bitsize + bitpos > GET_MODE_BITSIZE (extzv_mode))))
01273 {
01274 unsigned HOST_WIDE_INT xbitpos = bitpos, xoffset = offset;
01275 rtx bitsize_rtx, bitpos_rtx;
01276 rtx last = get_last_insn ();
01277 rtx xop0 = op0;
01278 rtx xtarget = target;
01279 rtx xspec_target = spec_target;
01280 rtx xspec_target_subreg = spec_target_subreg;
01281 rtx pat;
01282 enum machine_mode maxmode = mode_for_extraction (EP_extzv, 0);
01283
01284 if (GET_CODE (xop0) == MEM)
01285 {
01286 int save_volatile_ok = volatile_ok;
01287 volatile_ok = 1;
01288
01289
01290 if (! ((*insn_data[(int) CODE_FOR_extzv].operand[1].predicate)
01291 (xop0, GET_MODE (xop0))))
01292 {
01293
01294 enum machine_mode bestmode;
01295
01296
01297
01298
01299
01300
01301
01302 if (GET_MODE (xop0) == BLKmode
01303 || (GET_MODE_SIZE (GET_MODE (op0))
01304 > GET_MODE_SIZE (maxmode)))
01305 bestmode = get_best_mode (bitsize, bitnum,
01306 MEM_ALIGN (xop0), maxmode,
01307 MEM_VOLATILE_P (xop0));
01308 else
01309 bestmode = GET_MODE (xop0);
01310
01311 if (bestmode == VOIDmode
01312 || (SLOW_UNALIGNED_ACCESS (bestmode, MEM_ALIGN (xop0))
01313 && GET_MODE_BITSIZE (bestmode) > MEM_ALIGN (xop0)))
01314 goto extzv_loses;
01315
01316
01317
01318 unit = GET_MODE_BITSIZE (bestmode);
01319 xoffset = (bitnum / unit) * GET_MODE_SIZE (bestmode);
01320 xbitpos = bitnum % unit;
01321 xop0 = adjust_address (xop0, bestmode, xoffset);
01322
01323
01324 xop0 = force_reg (bestmode, xop0);
01325
01326
01327 }
01328 else
01329
01330 xop0 = adjust_address (xop0, byte_mode, xoffset);
01331
01332 volatile_ok = save_volatile_ok;
01333 }
01334
01335
01336
01337 if (GET_CODE (xop0) == SUBREG && GET_MODE (xop0) != maxmode)
01338 goto extzv_loses;
01339 if (GET_CODE (xop0) == REG && GET_MODE (xop0) != maxmode)
01340 xop0 = gen_rtx_SUBREG (maxmode, xop0, 0);
01341
01342
01343
01344 if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
01345 xbitpos = unit - bitsize - xbitpos;
01346
01347
01348 if (BITS_BIG_ENDIAN && GET_CODE (xop0) != MEM)
01349 xbitpos += GET_MODE_BITSIZE (maxmode) - unit;
01350
01351 unit = GET_MODE_BITSIZE (maxmode);
01352
01353 if (xtarget == 0
01354 || (flag_force_mem && GET_CODE (xtarget) == MEM))
01355 xtarget = xspec_target = gen_reg_rtx (tmode);
01356
01357 if (GET_MODE (xtarget) != maxmode)
01358 {
01359 if (GET_CODE (xtarget) == REG)
01360 {
01361 int wider = (GET_MODE_SIZE (maxmode)
01362 > GET_MODE_SIZE (GET_MODE (xtarget)));
01363 xtarget = gen_lowpart (maxmode, xtarget);
01364 if (wider)
01365 xspec_target_subreg = xtarget;
01366 }
01367 else
01368 xtarget = gen_reg_rtx (maxmode);
01369 }
01370
01371
01372
01373 if (! ((*insn_data[(int) CODE_FOR_extzv].operand[0].predicate)
01374 (xtarget, maxmode)))
01375 xtarget = gen_reg_rtx (maxmode);
01376
01377 bitsize_rtx = GEN_INT (bitsize);
01378 bitpos_rtx = GEN_INT (xbitpos);
01379
01380 pat = gen_extzv (protect_from_queue (xtarget, 1),
01381 xop0, bitsize_rtx, bitpos_rtx);
01382 if (pat)
01383 {
01384 emit_insn (pat);
01385 target = xtarget;
01386 spec_target = xspec_target;
01387 spec_target_subreg = xspec_target_subreg;
01388 }
01389 else
01390 {
01391 delete_insns_since (last);
01392 target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
01393 bitpos, target, 1);
01394 }
01395 }
01396 else
01397 extzv_loses:
01398 target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
01399 bitpos, target, 1);
01400 }
01401 else
01402 {
01403 if (HAVE_extv
01404 && (GET_MODE_BITSIZE (extv_mode) >= bitsize)
01405 && ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
01406 && (bitsize + bitpos > GET_MODE_BITSIZE (extv_mode))))
01407 {
01408 int xbitpos = bitpos, xoffset = offset;
01409 rtx bitsize_rtx, bitpos_rtx;
01410 rtx last = get_last_insn ();
01411 rtx xop0 = op0, xtarget = target;
01412 rtx xspec_target = spec_target;
01413 rtx xspec_target_subreg = spec_target_subreg;
01414 rtx pat;
01415 enum machine_mode maxmode = mode_for_extraction (EP_extv, 0);
01416
01417 if (GET_CODE (xop0) == MEM)
01418 {
01419
01420 if (! ((*insn_data[(int) CODE_FOR_extv].operand[1].predicate)
01421 (xop0, GET_MODE (xop0))))
01422 {
01423
01424 enum machine_mode bestmode;
01425
01426
01427
01428
01429
01430
01431
01432 if (GET_MODE (xop0) == BLKmode
01433 || (GET_MODE_SIZE (GET_MODE (op0))
01434 > GET_MODE_SIZE (maxmode)))
01435 bestmode = get_best_mode (bitsize, bitnum,
01436 MEM_ALIGN (xop0), maxmode,
01437 MEM_VOLATILE_P (xop0));
01438 else
01439 bestmode = GET_MODE (xop0);
01440
01441 if (bestmode == VOIDmode
01442 || (SLOW_UNALIGNED_ACCESS (bestmode, MEM_ALIGN (xop0))
01443 && GET_MODE_BITSIZE (bestmode) > MEM_ALIGN (xop0)))
01444 goto extv_loses;
01445
01446
01447
01448 unit = GET_MODE_BITSIZE (bestmode);
01449 xoffset = (bitnum / unit) * GET_MODE_SIZE (bestmode);
01450 xbitpos = bitnum % unit;
01451 xop0 = adjust_address (xop0, bestmode, xoffset);
01452
01453
01454 xop0 = force_reg (bestmode, xop0);
01455
01456
01457 }
01458 else
01459
01460 xop0 = adjust_address (xop0, byte_mode, xoffset);
01461 }
01462
01463
01464
01465 if (GET_CODE (xop0) == SUBREG && GET_MODE (xop0) != maxmode)
01466 goto extv_loses;
01467 if (GET_CODE (xop0) == REG && GET_MODE (xop0) != maxmode)
01468 xop0 = gen_rtx_SUBREG (maxmode, xop0, 0);
01469
01470
01471
01472 if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
01473 xbitpos = unit - bitsize - xbitpos;
01474
01475
01476
01477 if (BITS_BIG_ENDIAN && GET_CODE (xop0) != MEM)
01478 xbitpos += (GET_MODE_BITSIZE (maxmode) - unit);
01479
01480 unit = GET_MODE_BITSIZE (maxmode);
01481
01482 if (xtarget == 0
01483 || (flag_force_mem && GET_CODE (xtarget) == MEM))
01484 xtarget = xspec_target = gen_reg_rtx (tmode);
01485
01486 if (GET_MODE (xtarget) != maxmode)
01487 {
01488 if (GET_CODE (xtarget) == REG)
01489 {
01490 int wider = (GET_MODE_SIZE (maxmode)
01491 > GET_MODE_SIZE (GET_MODE (xtarget)));
01492 xtarget = gen_lowpart (maxmode, xtarget);
01493 if (wider)
01494 xspec_target_subreg = xtarget;
01495 }
01496 else
01497 xtarget = gen_reg_rtx (maxmode);
01498 }
01499
01500
01501
01502 if (! ((*insn_data[(int) CODE_FOR_extv].operand[0].predicate)
01503 (xtarget, maxmode)))
01504 xtarget = gen_reg_rtx (maxmode);
01505
01506 bitsize_rtx = GEN_INT (bitsize);
01507 bitpos_rtx = GEN_INT (xbitpos);
01508
01509 pat = gen_extv (protect_from_queue (xtarget, 1),
01510 xop0, bitsize_rtx, bitpos_rtx);
01511 if (pat)
01512 {
01513 emit_insn (pat);
01514 target = xtarget;
01515 spec_target = xspec_target;
01516 spec_target_subreg = xspec_target_subreg;
01517 }
01518 else
01519 {
01520 delete_insns_since (last);
01521 target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
01522 bitpos, target, 0);
01523 }
01524 }
01525 else
01526 extv_loses:
01527 target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
01528 bitpos, target, 0);
01529 }
01530 if (target == spec_target)
01531 return target;
01532 if (target == spec_target_subreg)
01533 return spec_target;
01534 if (GET_MODE (target) != tmode && GET_MODE (target) != mode)
01535 {
01536
01537
01538
01539 if (GET_MODE_CLASS (tmode) != MODE_INT
01540 && GET_MODE_CLASS (tmode) != MODE_PARTIAL_INT)
01541 {
01542 target = convert_to_mode (mode_for_size (GET_MODE_BITSIZE (tmode),
01543 MODE_INT, 0),
01544 target, unsignedp);
01545 return gen_lowpart (tmode, target);
01546 }
01547 else
01548 return convert_to_mode (tmode, target, unsignedp);
01549 }
01550 return target;
01551 }
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569 static rtx
01570 extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos,
01571 target, unsignedp)
01572 enum machine_mode tmode;
01573 rtx op0, target;
01574 unsigned HOST_WIDE_INT offset, bitsize, bitpos;
01575 int unsignedp;
01576 {
01577 unsigned int total_bits = BITS_PER_WORD;
01578 enum machine_mode mode;
01579
01580 if (GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG)
01581 {
01582
01583 if (bitsize + bitpos > BITS_PER_WORD)
01584 return extract_split_bit_field (op0, bitsize, bitpos, unsignedp);
01585 }
01586 else
01587 {
01588
01589
01590
01591
01592 mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
01593 MEM_ALIGN (op0), word_mode, MEM_VOLATILE_P (op0));
01594
01595 if (mode == VOIDmode)
01596
01597
01598 return extract_split_bit_field (op0, bitsize,
01599 bitpos + offset * BITS_PER_UNIT,
01600 unsignedp);
01601
01602 total_bits = GET_MODE_BITSIZE (mode);
01603
01604
01605
01606
01607 if (bitpos >= total_bits)
01608 {
01609 offset += (bitpos / total_bits) * (total_bits / BITS_PER_UNIT);
01610 bitpos -= ((bitpos / total_bits) * (total_bits / BITS_PER_UNIT)
01611 * BITS_PER_UNIT);
01612 }
01613
01614
01615
01616
01617
01618 bitpos += (offset % (total_bits / BITS_PER_UNIT)) * BITS_PER_UNIT;
01619 offset -= (offset % (total_bits / BITS_PER_UNIT));
01620 op0 = adjust_address (op0, mode, offset);
01621 }
01622
01623 mode = GET_MODE (op0);
01624
01625 if (BYTES_BIG_ENDIAN)
01626
01627
01628 bitpos = total_bits - bitsize - bitpos;
01629
01630
01631
01632
01633 if (unsignedp)
01634 {
01635 if (bitpos)
01636 {
01637
01638
01639 tree amount = build_int_2 (bitpos, 0);
01640
01641
01642 rtx subtarget = (target != 0 && GET_CODE (target) == REG
01643 && !REG_FUNCTION_VALUE_P (target)
01644 ? target : 0);
01645 if (tmode != mode) subtarget = 0;
01646 op0 = expand_shift (RSHIFT_EXPR, mode, op0, amount, subtarget, 1);
01647 }
01648
01649 if (mode != tmode)
01650 op0 = convert_to_mode (tmode, op0, 1);
01651
01652
01653
01654
01655 if (GET_MODE_BITSIZE (mode) != bitpos + bitsize)
01656 return expand_binop (GET_MODE (op0), and_optab, op0,
01657 mask_rtx (GET_MODE (op0), 0, bitsize, 0),
01658 target, 1, OPTAB_LIB_WIDEN);
01659 return op0;
01660 }
01661
01662
01663
01664 op0 = force_reg (mode, op0);
01665 if (mode != tmode)
01666 target = 0;
01667
01668
01669
01670 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
01671 mode = GET_MODE_WIDER_MODE (mode))
01672 if (GET_MODE_BITSIZE (mode) >= bitsize + bitpos)
01673 {
01674 op0 = convert_to_mode (mode, op0, 0);
01675 break;
01676 }
01677
01678 if (GET_MODE_BITSIZE (mode) != (bitsize + bitpos))
01679 {
01680 tree amount
01681 = build_int_2 (GET_MODE_BITSIZE (mode) - (bitsize + bitpos), 0);
01682
01683
01684 rtx subtarget = (target != 0 && GET_CODE (target) == REG
01685 && ! REG_FUNCTION_VALUE_P (target)
01686 ? target : 0);
01687 op0 = expand_shift (LSHIFT_EXPR, mode, op0, amount, subtarget, 1);
01688 }
01689
01690 return expand_shift (RSHIFT_EXPR, mode, op0,
01691 build_int_2 (GET_MODE_BITSIZE (mode) - bitsize, 0),
01692 target, 0);
01693 }
01694
01695
01696
01697
01698
01699
01700
01701 static rtx
01702 mask_rtx (mode, bitpos, bitsize, complement)
01703 enum machine_mode mode;
01704 int bitpos, bitsize, complement;
01705 {
01706 HOST_WIDE_INT masklow, maskhigh;
01707
01708 if (bitpos < HOST_BITS_PER_WIDE_INT)
01709 masklow = (HOST_WIDE_INT) -1 << bitpos;
01710 else
01711 masklow = 0;
01712
01713 if (bitpos + bitsize < HOST_BITS_PER_WIDE_INT)
01714 masklow &= ((unsigned HOST_WIDE_INT) -1
01715 >> (HOST_BITS_PER_WIDE_INT - bitpos - bitsize));
01716
01717 if (bitpos <= HOST_BITS_PER_WIDE_INT)
01718 maskhigh = -1;
01719 else
01720 maskhigh = (HOST_WIDE_INT) -1 << (bitpos - HOST_BITS_PER_WIDE_INT);
01721
01722 if (bitpos + bitsize > HOST_BITS_PER_WIDE_INT)
01723 maskhigh &= ((unsigned HOST_WIDE_INT) -1
01724 >> (2 * HOST_BITS_PER_WIDE_INT - bitpos - bitsize));
01725 else
01726 maskhigh = 0;
01727
01728 if (complement)
01729 {
01730 maskhigh = ~maskhigh;
01731 masklow = ~masklow;
01732 }
01733
01734 return immed_double_const (masklow, maskhigh, mode);
01735 }
01736
01737
01738
01739
01740 static rtx
01741 lshift_value (mode, value, bitpos, bitsize)
01742 enum machine_mode mode;
01743 rtx value;
01744 int bitpos, bitsize;
01745 {
01746 unsigned HOST_WIDE_INT v = INTVAL (value);
01747 HOST_WIDE_INT low, high;
01748
01749 if (bitsize < HOST_BITS_PER_WIDE_INT)
01750 v &= ~((HOST_WIDE_INT) -1 << bitsize);
01751
01752 if (bitpos < HOST_BITS_PER_WIDE_INT)
01753 {
01754 low = v << bitpos;
01755 high = (bitpos > 0 ? (v >> (HOST_BITS_PER_WIDE_INT - bitpos)) : 0);
01756 }
01757 else
01758 {
01759 low = 0;
01760 high = v << (bitpos - HOST_BITS_PER_WIDE_INT);
01761 }
01762
01763 return immed_double_const (low, high, mode);
01764 }
01765
01766
01767
01768
01769
01770
01771
01772
01773 static rtx
01774 extract_split_bit_field (op0, bitsize, bitpos, unsignedp)
01775 rtx op0;
01776 unsigned HOST_WIDE_INT bitsize, bitpos;
01777 int unsignedp;
01778 {
01779 unsigned int unit;
01780 unsigned int bitsdone = 0;
01781 rtx result = NULL_RTX;
01782 int first = 1;
01783
01784
01785
01786 if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
01787 unit = BITS_PER_WORD;
01788 else
01789 unit = MIN (MEM_ALIGN (op0), BITS_PER_WORD);
01790
01791 while (bitsdone < bitsize)
01792 {
01793 unsigned HOST_WIDE_INT thissize;
01794 rtx part, word;
01795 unsigned HOST_WIDE_INT thispos;
01796 unsigned HOST_WIDE_INT offset;
01797
01798 offset = (bitpos + bitsdone) / unit;
01799 thispos = (bitpos + bitsdone) % unit;
01800
01801
01802
01803
01804 thissize = MIN (bitsize - bitsdone, BITS_PER_WORD);
01805 thissize = MIN (thissize, unit - thispos);
01806
01807
01808
01809
01810
01811
01812
01813 if (GET_CODE (op0) == SUBREG)
01814 {
01815 int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset;
01816 word = operand_subword_force (SUBREG_REG (op0), word_offset,
01817 GET_MODE (SUBREG_REG (op0)));
01818 offset = 0;
01819 }
01820 else if (GET_CODE (op0) == REG)
01821 {
01822 word = operand_subword_force (op0, offset, GET_MODE (op0));
01823 offset = 0;
01824 }
01825 else
01826 word = op0;
01827
01828
01829
01830
01831
01832 part = extract_fixed_bit_field (word_mode, word,
01833 offset * unit / BITS_PER_UNIT,
01834 thissize, thispos, 0, 1);
01835 bitsdone += thissize;
01836
01837
01838 if (BYTES_BIG_ENDIAN)
01839 {
01840 if (bitsize != bitsdone)
01841 part = expand_shift (LSHIFT_EXPR, word_mode, part,
01842 build_int_2 (bitsize - bitsdone, 0), 0, 1);
01843 }
01844 else
01845 {
01846 if (bitsdone != thissize)
01847 part = expand_shift (LSHIFT_EXPR, word_mode, part,
01848 build_int_2 (bitsdone - thissize, 0), 0, 1);
01849 }
01850
01851 if (first)
01852 result = part;
01853 else
01854
01855
01856 result = expand_binop (word_mode, ior_optab, part, result, NULL_RTX, 1,
01857 OPTAB_LIB_WIDEN);
01858
01859 first = 0;
01860 }
01861
01862
01863 if (unsignedp)
01864 return result;
01865
01866 result = expand_shift (LSHIFT_EXPR, word_mode, result,
01867 build_int_2 (BITS_PER_WORD - bitsize, 0),
01868 NULL_RTX, 0);
01869 return expand_shift (RSHIFT_EXPR, word_mode, result,
01870 build_int_2 (BITS_PER_WORD - bitsize, 0), NULL_RTX, 0);
01871 }
01872
01873
01874
01875 void
01876 expand_inc (target, inc)
01877 rtx target, inc;
01878 {
01879 rtx value = expand_binop (GET_MODE (target), add_optab,
01880 target, inc,
01881 target, 0, OPTAB_LIB_WIDEN);
01882 if (value != target)
01883 emit_move_insn (target, value);
01884 }
01885
01886
01887
01888 void
01889 expand_dec (target, dec)
01890 rtx target, dec;
01891 {
01892 rtx value = expand_binop (GET_MODE (target), sub_optab,
01893 target, dec,
01894 target, 0, OPTAB_LIB_WIDEN);
01895 if (value != target)
01896 emit_move_insn (target, value);
01897 }
01898
01899
01900
01901
01902
01903
01904
01905
01906 rtx
01907 expand_shift (code, mode, shifted, amount, target, unsignedp)
01908 enum tree_code code;
01909 enum machine_mode mode;
01910 rtx shifted;
01911 tree amount;
01912 rtx target;
01913 int unsignedp;
01914 {
01915 rtx op1, temp = 0;
01916 int left = (code == LSHIFT_EXPR || code == LROTATE_EXPR);
01917 int rotate = (code == LROTATE_EXPR || code == RROTATE_EXPR);
01918 int try;
01919
01920
01921
01922
01923
01924 op1 = expand_expr (amount, NULL_RTX, VOIDmode, 0);
01925
01926 #ifdef SHIFT_COUNT_TRUNCATED
01927 if (SHIFT_COUNT_TRUNCATED)
01928 {
01929 if (GET_CODE (op1) == CONST_INT
01930 && ((unsigned HOST_WIDE_INT) INTVAL (op1) >=
01931 (unsigned HOST_WIDE_INT) GET_MODE_BITSIZE (mode)))
01932 op1 = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (op1)
01933 % GET_MODE_BITSIZE (mode));
01934 else if (GET_CODE (op1) == SUBREG
01935 && subreg_lowpart_p (op1))
01936 op1 = SUBREG_REG (op1);
01937 }
01938 #endif
01939
01940 if (op1 == const0_rtx)
01941 return shifted;
01942
01943 for (try = 0; temp == 0 && try < 3; try++)
01944 {
01945 enum optab_methods methods;
01946
01947 if (try == 0)
01948 methods = OPTAB_DIRECT;
01949 else if (try == 1)
01950 methods = OPTAB_WIDEN;
01951 else
01952 methods = OPTAB_LIB_WIDEN;
01953
01954 if (rotate)
01955 {
01956
01957 if (methods == OPTAB_WIDEN)
01958 continue;
01959 else if (methods == OPTAB_LIB_WIDEN)
01960 {
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973 rtx subtarget = target == shifted ? 0 : target;
01974 rtx temp1;
01975 tree type = TREE_TYPE (amount);
01976 tree new_amount = make_tree (type, op1);
01977 tree other_amount
01978 = fold (build (MINUS_EXPR, type,
01979 convert (type,
01980 build_int_2 (GET_MODE_BITSIZE (mode),
01981 0)),
01982 amount));
01983
01984 shifted = force_reg (mode, shifted);
01985
01986 temp = expand_shift (left ? LSHIFT_EXPR : RSHIFT_EXPR,
01987 mode, shifted, new_amount, subtarget, 1);
01988 temp1 = expand_shift (left ? RSHIFT_EXPR : LSHIFT_EXPR,
01989 mode, shifted, other_amount, 0, 1);
01990 return expand_binop (mode, ior_optab, temp, temp1, target,
01991 unsignedp, methods);
01992 }
01993
01994 temp = expand_binop (mode,
01995 left ? rotl_optab : rotr_optab,
01996 shifted, op1, target, unsignedp, methods);
01997
01998
01999
02000
02001 if (temp == 0 && GET_CODE (op1) == CONST_INT
02002 && INTVAL (op1) > 0
02003 && (unsigned int) INTVAL (op1) < GET_MODE_BITSIZE (mode))
02004 temp = expand_binop (mode,
02005 left ? rotr_optab : rotl_optab,
02006 shifted,
02007 GEN_INT (GET_MODE_BITSIZE (mode)
02008 - INTVAL (op1)),
02009 target, unsignedp, methods);
02010 }
02011 else if (unsignedp)
02012 temp = expand_binop (mode,
02013 left ? ashl_optab : lshr_optab,
02014 shifted, op1, target, unsignedp, methods);
02015
02016
02017
02018
02019 if (temp == 0 && ! rotate
02020 && (! unsignedp || (! left && methods == OPTAB_WIDEN)))
02021 {
02022 enum optab_methods methods1 = methods;
02023
02024
02025
02026 if (unsignedp)
02027 methods1 = OPTAB_MUST_WIDEN;
02028
02029
02030
02031 temp = expand_binop (mode,
02032 left ? ashl_optab : ashr_optab,
02033 shifted, op1, target, unsignedp, methods1);
02034 }
02035
02036
02037
02038
02039
02040 }
02041
02042 if (temp == 0)
02043 abort ();
02044 return temp;
02045 }
02046
02047 enum alg_code { alg_zero, alg_m, alg_shift,
02048 alg_add_t_m2, alg_sub_t_m2,
02049 alg_add_factor, alg_sub_factor,
02050 alg_add_t2_m, alg_sub_t2_m,
02051 alg_add, alg_subtract, alg_factor, alg_shiftop };
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072 struct algorithm
02073 {
02074 short cost;
02075 short ops;
02076
02077
02078
02079
02080
02081 enum alg_code op[MAX_BITS_PER_WORD];
02082 char log[MAX_BITS_PER_WORD];
02083 };
02084
02085 static void synth_mult PARAMS ((struct algorithm *,
02086 unsigned HOST_WIDE_INT,
02087 int));
02088 static unsigned HOST_WIDE_INT choose_multiplier PARAMS ((unsigned HOST_WIDE_INT,
02089 int, int,
02090 unsigned HOST_WIDE_INT *,
02091 int *, int *));
02092 static unsigned HOST_WIDE_INT invert_mod2n PARAMS ((unsigned HOST_WIDE_INT,
02093 int));
02094
02095
02096
02097
02098
02099 static void
02100 synth_mult (alg_out, t, cost_limit)
02101 struct algorithm *alg_out;
02102 unsigned HOST_WIDE_INT t;
02103 int cost_limit;
02104 {
02105 int m;
02106 struct algorithm *alg_in, *best_alg;
02107 int cost;
02108 unsigned HOST_WIDE_INT q;
02109
02110
02111
02112 alg_out->cost = cost_limit;
02113
02114 if (cost_limit <= 0)
02115 return;
02116
02117
02118 if (t == 1)
02119 {
02120 alg_out->ops = 1;
02121 alg_out->cost = 0;
02122 alg_out->op[0] = alg_m;
02123 return;
02124 }
02125
02126
02127
02128 if (t == 0)
02129 {
02130 if (zero_cost >= cost_limit)
02131 return;
02132 else
02133 {
02134 alg_out->ops = 1;
02135 alg_out->cost = zero_cost;
02136 alg_out->op[0] = alg_zero;
02137 return;
02138 }
02139 }
02140
02141
02142
02143 alg_in = (struct algorithm *)alloca (sizeof (struct algorithm));
02144 best_alg = (struct algorithm *)alloca (sizeof (struct algorithm));
02145
02146
02147
02148
02149 if ((t & 1) == 0)
02150 {
02151 m = floor_log2 (t & -t);
02152 if (m < BITS_PER_WORD)
02153 {
02154 q = t >> m;
02155 cost = shift_cost[m];
02156 synth_mult (alg_in, q, cost_limit - cost);
02157
02158 cost += alg_in->cost;
02159 if (cost < cost_limit)
02160 {
02161 struct algorithm *x;
02162 x = alg_in, alg_in = best_alg, best_alg = x;
02163 best_alg->log[best_alg->ops] = m;
02164 best_alg->op[best_alg->ops] = alg_shift;
02165 cost_limit = cost;
02166 }
02167 }
02168 }
02169
02170
02171 if ((t & 1) != 0)
02172 {
02173 unsigned HOST_WIDE_INT w;
02174
02175 for (w = 1; (w & t) != 0; w <<= 1)
02176 ;
02177
02178
02179
02180
02181
02182 if (w == 0
02183 || (w > 2
02184
02185
02186 && t != 3))
02187 {
02188
02189
02190 cost = add_cost;
02191 synth_mult (alg_in, t + 1, cost_limit - cost);
02192
02193 cost += alg_in->cost;
02194 if (cost < cost_limit)
02195 {
02196 struct algorithm *x;
02197 x = alg_in, alg_in = best_alg, best_alg = x;
02198 best_alg->log[best_alg->ops] = 0;
02199 best_alg->op[best_alg->ops] = alg_sub_t_m2;
02200 cost_limit = cost;
02201 }
02202 }
02203 else
02204 {
02205
02206
02207 cost = add_cost;
02208 synth_mult (alg_in, t - 1, cost_limit - cost);
02209
02210 cost += alg_in->cost;
02211 if (cost < cost_limit)
02212 {
02213 struct algorithm *x;
02214 x = alg_in, alg_in = best_alg, best_alg = x;
02215 best_alg->log[best_alg->ops] = 0;
02216 best_alg->op[best_alg->ops] = alg_add_t_m2;
02217 cost_limit = cost;
02218 }
02219 }
02220 }
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232 for (m = floor_log2 (t - 1); m >= 2; m--)
02233 {
02234 unsigned HOST_WIDE_INT d;
02235
02236 d = ((unsigned HOST_WIDE_INT) 1 << m) + 1;
02237 if (t % d == 0 && t > d && m < BITS_PER_WORD)
02238 {
02239 cost = MIN (shiftadd_cost[m], add_cost + shift_cost[m]);
02240 synth_mult (alg_in, t / d, cost_limit - cost);
02241
02242 cost += alg_in->cost;
02243 if (cost < cost_limit)
02244 {
02245 struct algorithm *x;
02246 x = alg_in, alg_in = best_alg, best_alg = x;
02247 best_alg->log[best_alg->ops] = m;
02248 best_alg->op[best_alg->ops] = alg_add_factor;
02249 cost_limit = cost;
02250 }
02251
02252 break;
02253 }
02254
02255 d = ((unsigned HOST_WIDE_INT) 1 << m) - 1;
02256 if (t % d == 0 && t > d && m < BITS_PER_WORD)
02257 {
02258 cost = MIN (shiftsub_cost[m], add_cost + shift_cost[m]);
02259 synth_mult (alg_in, t / d, cost_limit - cost);
02260
02261 cost += alg_in->cost;
02262 if (cost < cost_limit)
02263 {
02264 struct algorithm *x;
02265 x = alg_in, alg_in = best_alg, best_alg = x;
02266 best_alg->log[best_alg->ops] = m;
02267 best_alg->op[best_alg->ops] = alg_sub_factor;
02268 cost_limit = cost;
02269 }
02270 break;
02271 }
02272 }
02273
02274
02275
02276 if ((t & 1) != 0)
02277 {
02278 q = t - 1;
02279 q = q & -q;
02280 m = exact_log2 (q);
02281 if (m >= 0 && m < BITS_PER_WORD)
02282 {
02283 cost = shiftadd_cost[m];
02284 synth_mult (alg_in, (t - 1) >> m, cost_limit - cost);
02285
02286 cost += alg_in->cost;
02287 if (cost < cost_limit)
02288 {
02289 struct algorithm *x;
02290 x = alg_in, alg_in = best_alg, best_alg = x;
02291 best_alg->log[best_alg->ops] = m;
02292 best_alg->op[best_alg->ops] = alg_add_t2_m;
02293 cost_limit = cost;
02294 }
02295 }
02296
02297 q = t + 1;
02298 q = q & -q;
02299 m = exact_log2 (q);
02300 if (m >= 0 && m < BITS_PER_WORD)
02301 {
02302 cost = shiftsub_cost[m];
02303 synth_mult (alg_in, (t + 1) >> m, cost_limit - cost);
02304
02305 cost += alg_in->cost;
02306 if (cost < cost_limit)
02307 {
02308 struct algorithm *x;
02309 x = alg_in, alg_in = best_alg, best_alg = x;
02310 best_alg->log[best_alg->ops] = m;
02311 best_alg->op[best_alg->ops] = alg_sub_t2_m;
02312 cost_limit = cost;
02313 }
02314 }
02315 }
02316
02317
02318
02319 if (cost_limit == alg_out->cost)
02320 return;
02321
02322
02323
02324 if (best_alg->ops == MAX_BITS_PER_WORD)
02325 return;
02326
02327
02328
02329
02330 alg_out->ops = best_alg->ops + 1;
02331 alg_out->cost = cost_limit;
02332 memcpy (alg_out->op, best_alg->op,
02333 alg_out->ops * sizeof *alg_out->op);
02334 memcpy (alg_out->log, best_alg->log,
02335 alg_out->ops * sizeof *alg_out->log);
02336 }
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346 rtx
02347 expand_mult (mode, op0, op1, target, unsignedp)
02348 enum machine_mode mode;
02349 rtx op0, op1, target;
02350 int unsignedp;
02351 {
02352 rtx const_op1 = op1;
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363 if (GET_CODE (op1) == CONST_DOUBLE
02364 && GET_MODE_CLASS (GET_MODE (op1)) == MODE_INT
02365 && HOST_BITS_PER_INT >= BITS_PER_WORD
02366 && CONST_DOUBLE_HIGH (op1) == 0)
02367 const_op1 = GEN_INT (CONST_DOUBLE_LOW (op1));
02368 else if (HOST_BITS_PER_INT < GET_MODE_BITSIZE (mode)
02369 && GET_CODE (op1) == CONST_INT
02370 && INTVAL (op1) < 0)
02371 const_op1 = 0;
02372
02373
02374
02375
02376
02377
02378 if (const_op1 && GET_CODE (const_op1) == CONST_INT
02379 && (unsignedp || ! flag_trapv))
02380 {
02381 struct algorithm alg;
02382 struct algorithm alg2;
02383 HOST_WIDE_INT val = INTVAL (op1);
02384 HOST_WIDE_INT val_so_far;
02385 rtx insn;
02386 int mult_cost;
02387 enum {basic_variant, negate_variant, add_variant} variant = basic_variant;
02388
02389
02390
02391 op0 = force_reg (mode, op0);
02392
02393
02394
02395
02396
02397 mult_cost = rtx_cost (gen_rtx_MULT (mode, op0, op1), SET);
02398 mult_cost = MIN (12 * add_cost, mult_cost);
02399
02400 synth_mult (&alg, val, mult_cost);
02401
02402
02403
02404 if (HOST_BITS_PER_INT >= GET_MODE_BITSIZE (mode))
02405 {
02406 synth_mult (&alg2, - val,
02407 (alg.cost < mult_cost ? alg.cost : mult_cost) - negate_cost);
02408 if (alg2.cost + negate_cost < alg.cost)
02409 alg = alg2, variant = negate_variant;
02410 }
02411
02412
02413 synth_mult (&alg2, val - 1,
02414 (alg.cost < mult_cost ? alg.cost : mult_cost) - add_cost);
02415 if (alg2.cost + add_cost < alg.cost)
02416 alg = alg2, variant = add_variant;
02417
02418 if (alg.cost < mult_cost)
02419 {
02420
02421 int opno;
02422 rtx accum, tem;
02423 enum machine_mode nmode;
02424
02425 op0 = protect_from_queue (op0, 0);
02426
02427
02428
02429 if (GET_CODE (op0) == MEM)
02430 op0 = force_reg (mode, op0);
02431
02432
02433
02434
02435 if (alg.op[0] == alg_zero)
02436 {
02437 accum = copy_to_mode_reg (mode, const0_rtx);
02438 val_so_far = 0;
02439 }
02440 else if (alg.op[0] == alg_m)
02441 {
02442 accum = copy_to_mode_reg (mode, op0);
02443 val_so_far = 1;
02444 }
02445 else
02446 abort ();
02447
02448 for (opno = 1; opno < alg.ops; opno++)
02449 {
02450 int log = alg.log[opno];
02451 int preserve = preserve_subexpressions_p ();
02452 rtx shift_subtarget = preserve ? 0 : accum;
02453 rtx add_target
02454 = (opno == alg.ops - 1 && target != 0 && variant != add_variant
02455 && ! preserve)
02456 ? target : 0;
02457 rtx accum_target = preserve ? 0 : accum;
02458
02459 switch (alg.op[opno])
02460 {
02461 case alg_shift:
02462 accum = expand_shift (LSHIFT_EXPR, mode, accum,
02463 build_int_2 (log, 0), NULL_RTX, 0);
02464 val_so_far <<= log;
02465 break;
02466
02467 case alg_add_t_m2:
02468 tem = expand_shift (LSHIFT_EXPR, mode, op0,
02469 build_int_2 (log, 0), NULL_RTX, 0);
02470 accum = force_operand (gen_rtx_PLUS (mode, accum, tem),
02471 add_target
02472 ? add_target : accum_target);
02473 val_so_far += (HOST_WIDE_INT) 1 << log;
02474 break;
02475
02476 case alg_sub_t_m2:
02477 tem = expand_shift (LSHIFT_EXPR, mode, op0,
02478 build_int_2 (log, 0), NULL_RTX, 0);
02479 accum = force_operand (gen_rtx_MINUS (mode, accum, tem),
02480 add_target
02481 ? add_target : accum_target);
02482 val_so_far -= (HOST_WIDE_INT) 1 << log;
02483 break;
02484
02485 case alg_add_t2_m:
02486 accum = expand_shift (LSHIFT_EXPR, mode, accum,
02487 build_int_2 (log, 0), shift_subtarget,
02488 0);
02489 accum = force_operand (gen_rtx_PLUS (mode, accum, op0),
02490 add_target
02491 ? add_target : accum_target);
02492 val_so_far = (val_so_far << log) + 1;
02493 break;
02494
02495 case alg_sub_t2_m:
02496 accum = expand_shift (LSHIFT_EXPR, mode, accum,
02497 build_int_2 (log, 0), shift_subtarget,
02498 0);
02499 accum = force_operand (gen_rtx_MINUS (mode, accum, op0),
02500 add_target
02501 ? add_target : accum_target);
02502 val_so_far = (val_so_far << log) - 1;
02503 break;
02504
02505 case alg_add_factor:
02506 tem = expand_shift (LSHIFT_EXPR, mode, accum,
02507 build_int_2 (log, 0), NULL_RTX, 0);
02508 accum = force_operand (gen_rtx_PLUS (mode, accum, tem),
02509 add_target
02510 ? add_target : accum_target);
02511 val_so_far += val_so_far << log;
02512 break;
02513
02514 case alg_sub_factor:
02515 tem = expand_shift (LSHIFT_EXPR, mode, accum,
02516 build_int_2 (log, 0), NULL_RTX, 0);
02517 accum = force_operand (gen_rtx_MINUS (mode, tem, accum),
02518 (add_target ? add_target
02519 : preserve ? 0 : tem));
02520 val_so_far = (val_so_far << log) - val_so_far;
02521 break;
02522
02523 default:
02524 abort ();
02525 }
02526
02527
02528
02529
02530
02531
02532 tem = op0, nmode = mode;
02533 if (GET_CODE (accum) == SUBREG)
02534 {
02535 nmode = GET_MODE (SUBREG_REG (accum));
02536 tem = gen_lowpart (nmode, op0);
02537 }
02538
02539 insn = get_last_insn ();
02540 set_unique_reg_note (insn,
02541 REG_EQUAL,
02542 gen_rtx_MULT (nmode, tem,
02543 GEN_INT (val_so_far)));
02544 }
02545
02546 if (variant == negate_variant)
02547 {
02548 val_so_far = - val_so_far;
02549 accum = expand_unop (mode, neg_optab, accum, target, 0);
02550 }
02551 else if (variant == add_variant)
02552 {
02553 val_so_far = val_so_far + 1;
02554 accum = force_operand (gen_rtx_PLUS (mode, accum, op0), target);
02555 }
02556
02557 if (val != val_so_far)
02558 abort ();
02559
02560 return accum;
02561 }
02562 }
02563
02564
02565
02566 op0 = expand_binop (mode,
02567 ! unsignedp
02568 && flag_trapv && (GET_MODE_CLASS(mode) == MODE_INT)
02569 ? smulv_optab : smul_optab,
02570 op0, op1, target, unsignedp, OPTAB_LIB_WIDEN);
02571 if (op0 == 0)
02572 abort ();
02573 return op0;
02574 }
02575
02576
02577
02578 int
02579 ceil_log2 (x)
02580 unsigned HOST_WIDE_INT x;
02581 {
02582 return floor_log2 (x - 1) + 1;
02583 }
02584
02585
02586
02587
02588
02589
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601 static
02602 unsigned HOST_WIDE_INT
02603 choose_multiplier (d, n, precision, multiplier_ptr, post_shift_ptr, lgup_ptr)
02604 unsigned HOST_WIDE_INT d;
02605 int n;
02606 int precision;
02607 unsigned HOST_WIDE_INT *multiplier_ptr;
02608 int *post_shift_ptr;
02609 int *lgup_ptr;
02610 {
02611 HOST_WIDE_INT mhigh_hi, mlow_hi;
02612 unsigned HOST_WIDE_INT mhigh_lo, mlow_lo;
02613 int lgup, post_shift;
02614 int pow, pow2;
02615 unsigned HOST_WIDE_INT nl, dummy1;
02616 HOST_WIDE_INT nh, dummy2;
02617
02618
02619 lgup = ceil_log2 (d);
02620
02621 if (lgup > n)
02622 abort ();
02623
02624 pow = n + lgup;
02625 pow2 = n + lgup - precision;
02626
02627 if (pow == 2 * HOST_BITS_PER_WIDE_INT)
02628 {
02629
02630
02631 abort ();
02632 }
02633
02634
02635 if (pow >= HOST_BITS_PER_WIDE_INT)
02636 {
02637 nh = (HOST_WIDE_INT) 1 << (pow - HOST_BITS_PER_WIDE_INT);
02638 nl = 0;
02639 }
02640 else
02641 {
02642 nh = 0;
02643 nl = (unsigned HOST_WIDE_INT) 1 << pow;
02644 }
02645 div_and_round_double (TRUNC_DIV_EXPR, 1, nl, nh, d, (HOST_WIDE_INT) 0,
02646 &mlow_lo, &mlow_hi, &dummy1, &dummy2);
02647
02648
02649 if (pow2 >= HOST_BITS_PER_WIDE_INT)
02650 nh |= (HOST_WIDE_INT) 1 << (pow2 - HOST_BITS_PER_WIDE_INT);
02651 else
02652 nl |= (unsigned HOST_WIDE_INT) 1 << pow2;
02653 div_and_round_double (TRUNC_DIV_EXPR, 1, nl, nh, d, (HOST_WIDE_INT) 0,
02654 &mhigh_lo, &mhigh_hi, &dummy1, &dummy2);
02655
02656 if (mhigh_hi && nh - d >= d)
02657 abort ();
02658 if (mhigh_hi > 1 || mlow_hi > 1)
02659 abort ();
02660
02661 if (! (mlow_hi < mhigh_hi || (mlow_hi == mhigh_hi && mlow_lo < mhigh_lo)))
02662 abort ();
02663
02664
02665
02666
02667
02668 for (post_shift = lgup; post_shift > 0; post_shift--)
02669 {
02670 unsigned HOST_WIDE_INT ml_lo = (mlow_hi << (HOST_BITS_PER_WIDE_INT - 1)) | (mlow_lo >> 1);
02671 unsigned HOST_WIDE_INT mh_lo = (mhigh_hi << (HOST_BITS_PER_WIDE_INT - 1)) | (mhigh_lo >> 1);
02672 if (ml_lo >= mh_lo)
02673 break;
02674
02675 mlow_hi = 0;
02676 mlow_lo = ml_lo;
02677 mhigh_hi = 0;
02678 mhigh_lo = mh_lo;
02679 }
02680
02681 *post_shift_ptr = post_shift;
02682 *lgup_ptr = lgup;
02683 if (n < HOST_BITS_PER_WIDE_INT)
02684 {
02685 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT) 1 << n) - 1;
02686 *multiplier_ptr = mhigh_lo & mask;
02687 return mhigh_lo >= mask;
02688 }
02689 else
02690 {
02691 *multiplier_ptr = mhigh_lo;
02692 return mhigh_hi;
02693 }
02694 }
02695
02696
02697
02698
02699 static unsigned HOST_WIDE_INT
02700 invert_mod2n (x, n)
02701 unsigned HOST_WIDE_INT x;
02702 int n;
02703 {
02704
02705
02706
02707
02708
02709
02710 unsigned HOST_WIDE_INT mask;
02711 unsigned HOST_WIDE_INT y = x;
02712 int nbit = 3;
02713
02714 mask = (n == HOST_BITS_PER_WIDE_INT
02715 ? ~(unsigned HOST_WIDE_INT) 0
02716 : ((unsigned HOST_WIDE_INT) 1 << n) - 1);
02717
02718 while (nbit < n)
02719 {
02720 y = y * (2 - x*y) & mask;
02721 nbit *= 2;
02722 }
02723 return y;
02724 }
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736 rtx
02737 expand_mult_highpart_adjust (mode, adj_operand, op0, op1, target, unsignedp)
02738 enum machine_mode mode;
02739 rtx adj_operand, op0, op1, target;
02740 int unsignedp;
02741 {
02742 rtx tem;
02743 enum rtx_code adj_code = unsignedp ? PLUS : MINUS;
02744
02745 tem = expand_shift (RSHIFT_EXPR, mode, op0,
02746 build_int_2 (GET_MODE_BITSIZE (mode) - 1, 0),
02747 NULL_RTX, 0);
02748 tem = expand_and (mode, tem, op1, NULL_RTX);
02749 adj_operand
02750 = force_operand (gen_rtx_fmt_ee (adj_code, mode, adj_operand, tem),
02751 adj_operand);
02752
02753 tem = expand_shift (RSHIFT_EXPR, mode, op1,
02754 build_int_2 (GET_MODE_BITSIZE (mode) - 1, 0),
02755 NULL_RTX, 0);
02756 tem = expand_and (mode, tem, op0, NULL_RTX);
02757 target = force_operand (gen_rtx_fmt_ee (adj_code, mode, adj_operand, tem),
02758 target);
02759
02760 return target;
02761 }
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772
02773 rtx
02774 expand_mult_highpart (mode, op0, cnst1, target, unsignedp, max_cost)
02775 enum machine_mode mode;
02776 rtx op0, target;
02777 unsigned HOST_WIDE_INT cnst1;
02778 int unsignedp;
02779 int max_cost;
02780 {
02781 enum machine_mode wider_mode = GET_MODE_WIDER_MODE (mode);
02782 optab mul_highpart_optab;
02783 optab moptab;
02784 rtx tem;
02785 int size = GET_MODE_BITSIZE (mode);
02786 rtx op1, wide_op1;
02787
02788
02789 if (size > HOST_BITS_PER_WIDE_INT)
02790 abort ();
02791
02792 op1 = gen_int_mode (cnst1, mode);
02793
02794 wide_op1
02795 = immed_double_const (cnst1,
02796 (unsignedp
02797 ? (HOST_WIDE_INT) 0
02798 : -(cnst1 >> (HOST_BITS_PER_WIDE_INT - 1))),
02799 wider_mode);
02800
02801
02802
02803 if (size < BITS_PER_WORD
02804 && mul_cost[(int) wider_mode] + shift_cost[size-1] < max_cost)
02805 {
02806
02807
02808 op0 = convert_to_mode (wider_mode, op0, unsignedp);
02809
02810
02811
02812 tem = expand_mult (wider_mode, op0, wide_op1, NULL_RTX, 0);
02813 tem = expand_shift (RSHIFT_EXPR, wider_mode, tem,
02814 build_int_2 (size, 0), NULL_RTX, 1);
02815 return convert_modes (mode, wider_mode, tem, unsignedp);
02816 }
02817
02818 if (target == 0)
02819 target = gen_reg_rtx (mode);
02820
02821
02822
02823 if (mul_highpart_cost[(int) mode] < max_cost)
02824 {
02825 mul_highpart_optab = unsignedp ? umul_highpart_optab : smul_highpart_optab;
02826 target = expand_binop (mode, mul_highpart_optab,
02827 op0, op1, target, unsignedp, OPTAB_DIRECT);
02828 if (target)
02829 return target;
02830 }
02831
02832
02833
02834 if (size - 1 < BITS_PER_WORD
02835 && (mul_highpart_cost[(int) mode] + 2 * shift_cost[size-1] + 4 * add_cost
02836 < max_cost))
02837 {
02838 mul_highpart_optab = unsignedp ? smul_highpart_optab : umul_highpart_optab;
02839 target = expand_binop (mode, mul_highpart_optab,
02840 op0, op1, target, unsignedp, OPTAB_DIRECT);
02841 if (target)
02842
02843 return expand_mult_highpart_adjust (mode, target, op0,
02844 op1, target, unsignedp);
02845 }
02846
02847
02848 moptab = unsignedp ? umul_widen_optab : smul_widen_optab;
02849 if (moptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
02850 && mul_widen_cost[(int) wider_mode] < max_cost)
02851 {
02852 op1 = force_reg (mode, op1);
02853 goto try;
02854 }
02855
02856
02857 moptab = smul_optab;
02858 if (smul_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
02859 && size - 1 < BITS_PER_WORD
02860 && mul_cost[(int) wider_mode] + shift_cost[size-1] < max_cost)
02861 {
02862 op1 = wide_op1;
02863 goto try;
02864 }
02865
02866
02867 moptab = unsignedp ? smul_widen_optab : umul_widen_optab;
02868 if (moptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
02869 && size - 1 < BITS_PER_WORD
02870 && (mul_widen_cost[(int) wider_mode]
02871 + 2 * shift_cost[size-1] + 4 * add_cost < max_cost))
02872 {
02873 rtx regop1 = force_reg (mode, op1);
02874 tem = expand_binop (wider_mode, moptab, op0, regop1,
02875 NULL_RTX, ! unsignedp, OPTAB_WIDEN);
02876 if (tem != 0)
02877 {
02878
02879 tem = expand_shift (RSHIFT_EXPR, wider_mode, tem,
02880 build_int_2 (size, 0), NULL_RTX, 1);
02881 tem = convert_modes (mode, wider_mode, tem, unsignedp);
02882
02883 return expand_mult_highpart_adjust (mode, tem, op0, op1,
02884 target, unsignedp);
02885 }
02886 }
02887
02888 return 0;
02889
02890 try:
02891
02892 tem = expand_binop (wider_mode, moptab, op0, op1,
02893 NULL_RTX, unsignedp, OPTAB_WIDEN);
02894 if (tem == 0)
02895 return 0;
02896
02897
02898 if (mode == word_mode)
02899 {
02900 return gen_highpart (mode, tem);
02901 }
02902 else
02903 {
02904 tem = expand_shift (RSHIFT_EXPR, wider_mode, tem,
02905 build_int_2 (size, 0), NULL_RTX, 1);
02906 return convert_modes (mode, wider_mode, tem, unsignedp);
02907 }
02908 }
02909
02910
02911
02912
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948 #define EXACT_POWER_OF_2_OR_ZERO_P(x) (((x) & ((x) - 1)) == 0)
02949
02950 rtx
02951 expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
02952 int rem_flag;
02953 enum tree_code code;
02954 enum machine_mode mode;
02955 rtx op0, op1, target;
02956 int unsignedp;
02957 {
02958 enum machine_mode compute_mode;
02959 rtx tquotient;
02960 rtx quotient = 0, remainder = 0;
02961 rtx last;
02962 int size;
02963 rtx insn, set;
02964 optab optab1, optab2;
02965 int op1_is_constant, op1_is_pow2;
02966 int max_cost, extra_cost;
02967 static HOST_WIDE_INT last_div_const = 0;
02968
02969 op1_is_constant = GET_CODE (op1) == CONST_INT;
02970 op1_is_pow2 = (op1_is_constant
02971 && ((EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))
02972 || (! unsignedp && EXACT_POWER_OF_2_OR_ZERO_P (-INTVAL (op1))))));
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006 if (op1 == const1_rtx)
03007 return rem_flag ? const0_rtx : op0;
03008
03009
03010
03011 if (! unsignedp && op1 == constm1_rtx)
03012 {
03013 if (rem_flag)
03014 return const0_rtx;
03015 return expand_unop (mode, flag_trapv && GET_MODE_CLASS(mode) == MODE_INT
03016 ? negv_optab : neg_optab, op0, target, 0);
03017 }
03018
03019 if (target
03020
03021
03022
03023 && ((REG_P (target) && REG_FUNCTION_VALUE_P (target))
03024
03025 || ((rem_flag || op1_is_constant)
03026 && (reg_mentioned_p (target, op0)
03027 || (GET_CODE (op0) == MEM && GET_CODE (target) == MEM)))
03028 || reg_mentioned_p (target, op1)
03029 || (GET_CODE (op1) == MEM && GET_CODE (target) == MEM)))
03030 target = 0;
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052 optab1 = ((op1_is_pow2 && op1 != const0_rtx)
03053 ? (unsignedp ? lshr_optab : ashr_optab)
03054 : (unsignedp ? udiv_optab : sdiv_optab));
03055 optab2 = ((op1_is_pow2 && op1 != const0_rtx)
03056 ? optab1
03057 : (unsignedp ? udivmod_optab : sdivmod_optab));
03058
03059 for (compute_mode = mode; compute_mode != VOIDmode;
03060 compute_mode = GET_MODE_WIDER_MODE (compute_mode))
03061 if (optab1->handlers[(int) compute_mode].insn_code != CODE_FOR_nothing
03062 || optab2->handlers[(int) compute_mode].insn_code != CODE_FOR_nothing)
03063 break;
03064
03065 if (compute_mode == VOIDmode)
03066 for (compute_mode = mode; compute_mode != VOIDmode;
03067 compute_mode = GET_MODE_WIDER_MODE (compute_mode))
03068 if (optab1->handlers[(int) compute_mode].libfunc
03069 || optab2->handlers[(int) compute_mode].libfunc)
03070 break;
03071
03072
03073
03074 if (compute_mode == VOIDmode)
03075 compute_mode = mode;
03076
03077 if (target && GET_MODE (target) == compute_mode)
03078 tquotient = target;
03079 else
03080 tquotient = gen_reg_rtx (compute_mode);
03081
03082 size = GET_MODE_BITSIZE (compute_mode);
03083 #if 0
03084
03085
03086
03087 size = GET_MODE_BITSIZE (mode);
03088 #endif
03089
03090
03091
03092
03093 max_cost = div_cost[(int) compute_mode]
03094 - (rem_flag && ! (last_div_const != 0 && op1_is_constant
03095 && INTVAL (op1) == last_div_const)
03096 ? mul_cost[(int) compute_mode] + add_cost : 0);
03097
03098 last_div_const = ! rem_flag && op1_is_constant ? INTVAL (op1) : 0;
03099
03100
03101 if (compute_mode != mode)
03102 {
03103 op0 = convert_modes (compute_mode, mode, op0, unsignedp);
03104 op1 = convert_modes (compute_mode, mode, op1, unsignedp);
03105
03106
03107
03108 op1_is_constant = GET_CODE (op1) == CONST_INT;
03109 op1_is_pow2 = (op1_is_constant
03110 && ((EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))
03111 || (! unsignedp
03112 && EXACT_POWER_OF_2_OR_ZERO_P (-INTVAL (op1)))))) ;
03113 }
03114
03115
03116
03117 if (GET_CODE (op0) == MEM && MEM_VOLATILE_P (op0))
03118 op0 = force_reg (compute_mode, op0);
03119 if (GET_CODE (op1) == MEM && MEM_VOLATILE_P (op1))
03120 op1 = force_reg (compute_mode, op1);
03121
03122
03123
03124 if (rem_flag || op1_is_constant)
03125 op0 = force_reg (compute_mode, op0);
03126
03127 last = get_last_insn ();
03128
03129
03130 if (unsignedp)
03131 {
03132 if (code == FLOOR_DIV_EXPR)
03133 code = TRUNC_DIV_EXPR;
03134 if (code == FLOOR_MOD_EXPR)
03135 code = TRUNC_MOD_EXPR;
03136 if (code == EXACT_DIV_EXPR && op1_is_pow2)
03137 code = TRUNC_DIV_EXPR;
03138 }
03139
03140 if (op1 != const0_rtx)
03141 switch (code)
03142 {
03143 case TRUNC_MOD_EXPR:
03144 case TRUNC_DIV_EXPR:
03145 if (op1_is_constant)
03146 {
03147 if (unsignedp)
03148 {
03149 unsigned HOST_WIDE_INT mh, ml;
03150 int pre_shift, post_shift;
03151 int dummy;
03152 unsigned HOST_WIDE_INT d = INTVAL (op1);
03153
03154 if (EXACT_POWER_OF_2_OR_ZERO_P (d))
03155 {
03156 pre_shift = floor_log2 (d);
03157 if (rem_flag)
03158 {
03159 remainder
03160 = expand_binop (compute_mode, and_optab, op0,
03161 GEN_INT (((HOST_WIDE_INT) 1 << pre_shift) - 1),
03162 remainder, 1,
03163 OPTAB_LIB_WIDEN);
03164 if (remainder)
03165 return gen_lowpart (mode, remainder);
03166 }
03167 quotient = expand_shift (RSHIFT_EXPR, compute_mode, op0,
03168 build_int_2 (pre_shift, 0),
03169 tquotient, 1);
03170 }
03171 else if (size <= HOST_BITS_PER_WIDE_INT)
03172 {
03173 if (d >= ((unsigned HOST_WIDE_INT) 1 << (size - 1)))
03174 {
03175
03176
03177 quotient = emit_store_flag (tquotient, GEU, op0, op1,
03178 compute_mode, 1, 1);
03179 if (quotient == 0)
03180 goto fail1;
03181 }
03182 else
03183 {
03184
03185
03186
03187 mh = choose_multiplier (d, size, size,
03188 &ml, &post_shift, &dummy);
03189
03190
03191
03192
03193 if (mh != 0 && (d & 1) == 0)
03194 {
03195 pre_shift = floor_log2 (d & -d);
03196 mh = choose_multiplier (d >> pre_shift, size,
03197 size - pre_shift,
03198 &ml, &post_shift, &dummy);
03199 if (mh)
03200 abort ();
03201 }
03202 else
03203 pre_shift = 0;
03204
03205 if (mh != 0)
03206 {
03207 rtx t1, t2, t3, t4;
03208
03209 if (post_shift - 1 >= BITS_PER_WORD)
03210 goto fail1;
03211
03212 extra_cost = (shift_cost[post_shift - 1]
03213 + shift_cost[1] + 2 * add_cost);
03214 t1 = expand_mult_highpart (compute_mode, op0, ml,
03215 NULL_RTX, 1,
03216 max_cost - extra_cost);
03217 if (t1 == 0)
03218 goto fail1;
03219 t2 = force_operand (gen_rtx_MINUS (compute_mode,
03220 op0, t1),
03221 NULL_RTX);
03222 t3 = expand_shift (RSHIFT_EXPR, compute_mode, t2,
03223 build_int_2 (1, 0), NULL_RTX,1);
03224 t4 = force_operand (gen_rtx_PLUS (compute_mode,
03225 t1, t3),
03226 NULL_RTX);
03227 quotient
03228 = expand_shift (RSHIFT_EXPR, compute_mode, t4,
03229 build_int_2 (post_shift - 1, 0),
03230 tquotient, 1);
03231 }
03232 else
03233 {
03234 rtx t1, t2;
03235
03236 if (pre_shift >= BITS_PER_WORD
03237 || post_shift >= BITS_PER_WORD)
03238 goto fail1;
03239
03240 t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
03241 build_int_2 (pre_shift, 0),
03242 NULL_RTX, 1);
03243 extra_cost = (shift_cost[pre_shift]
03244 + shift_cost[post_shift]);
03245 t2 = expand_mult_highpart (compute_mode, t1, ml,
03246 NULL_RTX, 1,
03247 max_cost - extra_cost);
03248 if (t2 == 0)
03249 goto fail1;
03250 quotient
03251 = expand_shift (RSHIFT_EXPR, compute_mode, t2,
03252 build_int_2 (post_shift, 0),
03253 tquotient, 1);
03254 }
03255 }
03256 }
03257 else
03258 break;
03259
03260 insn = get_last_insn ();
03261 if (insn != last
03262 && (set = single_set (insn)) != 0
03263 && SET_DEST (set) == quotient)
03264 set_unique_reg_note (insn,
03265 REG_EQUAL,
03266 gen_rtx_UDIV (compute_mode, op0, op1));
03267 }
03268 else
03269 {
03270 unsigned HOST_WIDE_INT ml;
03271 int lgup, post_shift;
03272 HOST_WIDE_INT d = INTVAL (op1);
03273 unsigned HOST_WIDE_INT abs_d = d >= 0 ? d : -d;
03274
03275
03276 if (rem_flag && d < 0)
03277 {
03278 d = abs_d;
03279 op1 = gen_int_mode (abs_d, compute_mode);
03280 }
03281
03282 if (d == 1)
03283 quotient = op0;
03284 else if (d == -1)
03285 quotient = expand_unop (compute_mode, neg_optab, op0,
03286 tquotient, 0);
03287 else if (abs_d == (unsigned HOST_WIDE_INT) 1 << (size - 1))
03288 {
03289
03290 quotient = emit_store_flag (tquotient, EQ, op0, op1,
03291 compute_mode, 1, 1);
03292 if (quotient == 0)
03293 goto fail1;
03294 }
03295 else if (EXACT_POWER_OF_2_OR_ZERO_P (d)
03296 && (rem_flag ? smod_pow2_cheap : sdiv_pow2_cheap)
03297
03298
03299
03300
03301 && (((rem_flag ? smod_optab : sdiv_optab)
03302 ->handlers[(int) compute_mode].insn_code
03303 != CODE_FOR_nothing)
03304 || (sdivmod_optab->handlers[(int) compute_mode]
03305 .insn_code != CODE_FOR_nothing)))
03306 ;
03307 else if (EXACT_POWER_OF_2_OR_ZERO_P (abs_d))
03308 {
03309 lgup = floor_log2 (abs_d);
03310 if (BRANCH_COST < 1 || (abs_d != 2 && BRANCH_COST < 3))
03311 {
03312 rtx label = gen_label_rtx ();
03313 rtx t1;
03314
03315 t1 = copy_to_mode_reg (compute_mode, op0);
03316 do_cmp_and_jump (t1, const0_rtx, GE,
03317 compute_mode, label);
03318 expand_inc (t1, gen_int_mode (abs_d - 1,
03319 compute_mode));
03320 emit_label (label);
03321 quotient = expand_shift (RSHIFT_EXPR, compute_mode, t1,
03322 build_int_2 (lgup, 0),
03323 tquotient, 0);
03324 }
03325 else
03326 {
03327 rtx t1, t2, t3;
03328 t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
03329 build_int_2 (size - 1, 0),
03330 NULL_RTX, 0);
03331 t2 = expand_shift (RSHIFT_EXPR, compute_mode, t1,
03332 build_int_2 (size - lgup, 0),
03333 NULL_RTX, 1);
03334 t3 = force_operand (gen_rtx_PLUS (compute_mode,
03335 op0, t2),
03336 NULL_RTX);
03337 quotient = expand_shift (RSHIFT_EXPR, compute_mode, t3,
03338 build_int_2 (lgup, 0),
03339 tquotient, 0);
03340 }
03341
03342
03343
03344 if (d < 0)
03345 {
03346 insn = get_last_insn ();
03347 if (insn != last
03348 && (set = single_set (insn)) != 0
03349 && SET_DEST (set) == quotient
03350 && abs_d < ((unsigned HOST_WIDE_INT) 1
03351 << (HOST_BITS_PER_WIDE_INT - 1)))
03352 set_unique_reg_note (insn,
03353 REG_EQUAL,
03354 gen_rtx_DIV (compute_mode,
03355 op0,
03356 GEN_INT
03357 (trunc_int_for_mode
03358 (abs_d,
03359 compute_mode))));
03360
03361 quotient = expand_unop (compute_mode, neg_optab,
03362 quotient, quotient, 0);
03363 }
03364 }
03365 else if (size <= HOST_BITS_PER_WIDE_INT)
03366 {
03367 choose_multiplier (abs_d, size, size - 1,
03368 &ml, &post_shift, &lgup);
03369 if (ml < (unsigned HOST_WIDE_INT) 1 << (size - 1))
03370 {
03371 rtx t1, t2, t3;
03372
03373 if (post_shift >= BITS_PER_WORD
03374 || size - 1 >= BITS_PER_WORD)
03375 goto fail1;
03376
03377 extra_cost = (shift_cost[post_shift]
03378 + shift_cost[size - 1] + add_cost);
03379 t1 = expand_mult_highpart (compute_mode, op0, ml,
03380 NULL_RTX, 0,
03381 max_cost - extra_cost);
03382 if (t1 == 0)
03383 goto fail1;
03384 t2 = expand_shift (RSHIFT_EXPR, compute_mode, t1,
03385 build_int_2 (post_shift, 0), NULL_RTX, 0);
03386 t3 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
03387 build_int_2 (size - 1, 0), NULL_RTX, 0);
03388 if (d < 0)
03389 quotient
03390 = force_operand (gen_rtx_MINUS (compute_mode,
03391 t3, t2),
03392 tquotient);
03393 else
03394 quotient
03395 = force_operand (gen_rtx_MINUS (compute_mode,
03396 t2, t3),
03397 tquotient);
03398 }
03399 else
03400 {
03401 rtx t1, t2, t3, t4;
03402
03403 if (post_shift >= BITS_PER_WORD
03404 || size - 1 >= BITS_PER_WORD)
03405 goto fail1;
03406
03407 ml |= (~(unsigned HOST_WIDE_INT) 0) << (size - 1);
03408 extra_cost = (shift_cost[post_shift]
03409 + shift_cost[size - 1] + 2 * add_cost);
03410 t1 = expand_mult_highpart (compute_mode, op0, ml,
03411 NULL_RTX, 0,
03412 max_cost - extra_cost);
03413 if (t1 == 0)
03414 goto fail1;
03415 t2 = force_operand (gen_rtx_PLUS (compute_mode,
03416 t1, op0),
03417 NULL_RTX);
03418 t3 = expand_shift (RSHIFT_EXPR, compute_mode, t2,
03419 build_int_2 (post_shift, 0),
03420 NULL_RTX, 0);
03421 t4 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
03422 build_int_2 (size - 1, 0),
03423 NULL_RTX, 0);
03424 if (d < 0)
03425 quotient
03426 = force_operand (gen_rtx_MINUS (compute_mode,
03427 t4, t3),
03428 tquotient);
03429 else
03430 quotient
03431 = force_operand (gen_rtx_MINUS (compute_mode,
03432 t3, t4),
03433 tquotient);
03434 }
03435 }
03436 else
03437 break;
03438
03439 insn = get_last_insn ();
03440 if (insn != last
03441 && (set = single_set (insn)) != 0
03442 && SET_DEST (set) == quotient)
03443 set_unique_reg_note (insn,
03444 REG_EQUAL,
03445 gen_rtx_DIV (compute_mode, op0, op1));
03446 }
03447 break;
03448 }
03449 fail1:
03450 delete_insns_since (last);
03451 break;
03452
03453 case FLOOR_DIV_EXPR:
03454 case FLOOR_MOD_EXPR:
03455
03456 if (op1_is_constant && HOST_BITS_PER_WIDE_INT >= size)
03457 {
03458 unsigned HOST_WIDE_INT mh, ml;
03459 int pre_shift, lgup, post_shift;
03460 HOST_WIDE_INT d = INTVAL (op1);
03461
03462 if (d > 0)
03463 {
03464
03465
03466 if (EXACT_POWER_OF_2_OR_ZERO_P (d))
03467 {
03468 pre_shift = floor_log2 (d);
03469 if (rem_flag)
03470 {
03471 remainder = expand_binop (compute_mode, and_optab, op0,
03472 GEN_INT (((HOST_WIDE_INT) 1 << pre_shift) - 1),
03473 remainder, 0, OPTAB_LIB_WIDEN);
03474 if (remainder)
03475 return gen_lowpart (mode, remainder);
03476 }
03477 quotient = expand_shift (RSHIFT_EXPR, compute_mode, op0,
03478 build_int_2 (pre_shift, 0),
03479 tquotient, 0);
03480 }
03481 else
03482 {
03483 rtx t1, t2, t3, t4;
03484
03485 mh = choose_multiplier (d, size, size - 1,
03486 &ml, &post_shift, &lgup);
03487 if (mh)
03488 abort ();
03489
03490 if (post_shift < BITS_PER_WORD
03491 && size - 1 < BITS_PER_WORD)
03492 {
03493 t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
03494 build_int_2 (size - 1, 0),
03495 NULL_RTX, 0);
03496 t2 = expand_binop (compute_mode, xor_optab, op0, t1,
03497 NULL_RTX, 0, OPTAB_WIDEN);
03498 extra_cost = (shift_cost[post_shift]
03499 + shift_cost[size - 1] + 2 * add_cost);
03500 t3 = expand_mult_highpart (compute_mode, t2, ml,
03501 NULL_RTX, 1,
03502 max_cost - extra_cost);
03503 if (t3 != 0)
03504 {
03505 t4 = expand_shift (RSHIFT_EXPR, compute_mode, t3,
03506 build_int_2 (post_shift, 0),
03507 NULL_RTX, 1);
03508 quotient = expand_binop (compute_mode, xor_optab,
03509 t4, t1, tquotient, 0,
03510 OPTAB_WIDEN);
03511 }
03512 }
03513 }
03514 }
03515 else
03516 {
03517 rtx nsign, t1, t2, t3, t4;
03518 t1 = force_operand (gen_rtx_PLUS (compute_mode,
03519 op0, constm1_rtx), NULL_RTX);
03520 t2 = expand_binop (compute_mode, ior_optab, op0, t1, NULL_RTX,
03521 0, OPTAB_WIDEN);
03522 nsign = expand_shift (RSHIFT_EXPR, compute_mode, t2,
03523 build_int_2 (size - 1, 0), NULL_RTX, 0);
03524 t3 = force_operand (gen_rtx_MINUS (compute_mode, t1, nsign),
03525 NULL_RTX);
03526 t4 = expand_divmod (0, TRUNC_DIV_EXPR, compute_mode, t3, op1,
03527 NULL_RTX, 0);
03528 if (t4)
03529 {
03530 rtx t5;
03531 t5 = expand_unop (compute_mode, one_cmpl_optab, nsign,
03532 NULL_RTX, 0);
03533 quotient = force_operand (gen_rtx_PLUS (compute_mode,
03534 t4, t5),
03535 tquotient);
03536 }
03537 }
03538 }
03539
03540 if (quotient != 0)
03541 break;
03542 delete_insns_since (last);
03543
03544
03545
03546
03547
03548
03549 if (target == 0 || GET_MODE (target) != compute_mode)
03550 target = gen_reg_rtx (compute_mode);
03551
03552 if (rem_flag)
03553 {
03554 remainder
03555 = GET_CODE (target) == REG ? target : gen_reg_rtx (compute_mode);
03556 quotient = gen_reg_rtx (compute_mode);
03557 }
03558 else
03559 {
03560 quotient
03561 = GET_CODE (target) == REG ? target : gen_reg_rtx (compute_mode);
03562 remainder = gen_reg_rtx (compute_mode);
03563 }
03564
03565 if (expand_twoval_binop (sdivmod_optab, op0, op1,
03566 quotient, remainder, 0))
03567 {
03568
03569
03570 rtx tem;
03571 rtx label = gen_label_rtx ();
03572 do_cmp_and_jump (remainder, const0_rtx, EQ, compute_mode, label);
03573 tem = expand_binop (compute_mode, xor_optab, op0, op1,
03574 NULL_RTX, 0, OPTAB_WIDEN);
03575 do_cmp_and_jump (tem, const0_rtx, GE, compute_mode, label);
03576 expand_dec (quotient, const1_rtx);
03577 expand_inc (remainder, op1);
03578 emit_label (label);
03579 return gen_lowpart (mode, rem_flag ? remainder : quotient);
03580 }
03581
03582
03583
03584 {
03585 rtx label1, label2, label3, label4, label5;
03586 rtx adjusted_op0;
03587 rtx tem;
03588
03589 quotient = gen_reg_rtx (compute_mode);
03590 adjusted_op0 = copy_to_mode_reg (compute_mode, op0);
03591 label1 = gen_label_rtx ();
03592 label2 = gen_label_rtx ();
03593 label3 = gen_label_rtx ();
03594 label4 = gen_label_rtx ();
03595 label5 = gen_label_rtx ();
03596 do_cmp_and_jump (op1, const0_rtx, LT, compute_mode, label2);
03597 do_cmp_and_jump (adjusted_op0, const0_rtx, LT, compute_mode, label1);
03598 tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
03599 quotient, 0, OPTAB_LIB_WIDEN);
03600 if (tem != quotient)
03601 emit_move_insn (quotient, tem);
03602 emit_jump_insn (gen_jump (label5));
03603 emit_barrier ();
03604 emit_label (label1);
03605 expand_inc (adjusted_op0, const1_rtx);
03606 emit_jump_insn (gen_jump (label4));
03607 emit_barrier ();
03608 emit_label (label2);
03609 do_cmp_and_jump (adjusted_op0, const0_rtx, GT, compute_mode, label3);
03610 tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
03611 quotient, 0, OPTAB_LIB_WIDEN);
03612 if (tem != quotient)
03613 emit_move_insn (quotient, tem);
03614 emit_jump_insn (gen_jump (label5));
03615 emit_barrier ();
03616 emit_label (label3);
03617 expand_dec (adjusted_op0, const1_rtx);
03618 emit_label (label4);
03619 tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
03620 quotient, 0, OPTAB_LIB_WIDEN);
03621 if (tem != quotient)
03622 emit_move_insn (quotient, tem);
03623 expand_dec (quotient, const1_rtx);
03624 emit_label (label5);
03625 }
03626 break;
03627
03628 case CEIL_DIV_EXPR:
03629 case CEIL_MOD_EXPR:
03630 if (unsignedp)
03631 {
03632 if (op1_is_constant && EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1)))
03633 {
03634 rtx t1, t2, t3;
03635 unsigned HOST_WIDE_INT d = INTVAL (op1);
03636 t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
03637 build_int_2 (floor_log2 (d), 0),
03638 tquotient, 1);
03639 t2 = expand_binop (compute_mode, and_optab, op0,
03640 GEN_INT (d - 1),
03641 NULL_RTX, 1, OPTAB_LIB_WIDEN);
03642 t3 = gen_reg_rtx (compute_mode);
03643 t3 = emit_store_flag (t3, NE, t2, const0_rtx,
03644 compute_mode, 1, 1);
03645 if (t3 == 0)
03646 {
03647 rtx lab;
03648 lab = gen_label_rtx ();
03649 do_cmp_and_jump (t2, const0_rtx, EQ, compute_mode, lab);
03650 expand_inc (t1, const1_rtx);
03651 emit_label (lab);
03652 quotient = t1;
03653 }
03654 else
03655 quotient = force_operand (gen_rtx_PLUS (compute_mode,
03656 t1, t3),
03657 tquotient);
03658 break;
03659 }
03660
03661
03662
03663
03664
03665
03666 if (target == 0 || GET_MODE (target) != compute_mode)
03667 target = gen_reg_rtx (compute_mode);
03668
03669 if (rem_flag)
03670 {
03671 remainder = (GET_CODE (target) == REG
03672 ? target : gen_reg_rtx (compute_mode));
03673 quotient = gen_reg_rtx (compute_mode);
03674 }
03675 else
03676 {
03677 quotient = (GET_CODE (target) == REG
03678 ? target : gen_reg_rtx (compute_mode));
03679 remainder = gen_reg_rtx (compute_mode);
03680 }
03681
03682 if (expand_twoval_binop (udivmod_optab, op0, op1, quotient,
03683 remainder, 1))
03684 {
03685
03686
03687 rtx label = gen_label_rtx ();
03688 do_cmp_and_jump (remainder, const0_rtx, EQ,
03689 compute_mode, label);
03690 expand_inc (quotient, const1_rtx);
03691 expand_dec (remainder, op1);
03692 emit_label (label);
03693 return gen_lowpart (mode, rem_flag ? remainder : quotient);
03694 }
03695
03696
03697
03698 {
03699 rtx label1, label2;
03700 rtx adjusted_op0, tem;
03701
03702 quotient = gen_reg_rtx (compute_mode);
03703 adjusted_op0 = copy_to_mode_reg (compute_mode, op0);
03704 label1 = gen_label_rtx ();
03705 label2 = gen_label_rtx ();
03706 do_cmp_and_jump (adjusted_op0, const0_rtx, NE,
03707 compute_mode, label1);
03708 emit_move_insn (quotient, const0_rtx);
03709 emit_jump_insn (gen_jump (label2));
03710 emit_barrier ();
03711 emit_label (label1);
03712 expand_dec (adjusted_op0, const1_rtx);
03713 tem = expand_binop (compute_mode, udiv_optab, adjusted_op0, op1,
03714 quotient, 1, OPTAB_LIB_WIDEN);
03715 if (tem != quotient)
03716 emit_move_insn (quotient, tem);
03717 expand_inc (quotient, const1_rtx);
03718 emit_label (label2);
03719 }
03720 }
03721 else
03722 {
03723 if (op1_is_constant && EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))
03724 && INTVAL (op1) >= 0)
03725 {
03726
03727
03728
03729
03730
03731
03732 rtx t1, t2, t3;
03733 unsigned HOST_WIDE_INT d = INTVAL (op1);
03734 t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
03735 build_int_2 (floor_log2 (d), 0),
03736 tquotient, 0);
03737 t2 = expand_binop (compute_mode, and_optab, op0,
03738 GEN_INT (d - 1),
03739 NULL_RTX, 1, OPTAB_LIB_WIDEN);
03740 t3 = gen_reg_rtx (compute_mode);
03741 t3 = emit_store_flag (t3, NE, t2, const0_rtx,
03742 compute_mode, 1, 1);
03743 if (t3 == 0)
03744 {
03745 rtx lab;
03746 lab = gen_label_rtx ();
03747 do_cmp_and_jump (t2, const0_rtx, EQ, compute_mode, lab);
03748 expand_inc (t1, const1_rtx);
03749 emit_label (lab);
03750 quotient = t1;
03751 }
03752 else
03753 quotient = force_operand (gen_rtx_PLUS (compute_mode,
03754 t1, t3),
03755 tquotient);
03756 break;
03757 }
03758
03759
03760
03761
03762
03763
03764 if (target == 0 || GET_MODE (target) != compute_mode)
03765 target = gen_reg_rtx (compute_mode);
03766 if (rem_flag)
03767 {
03768 remainder= (GET_CODE (target) == REG
03769 ? target : gen_reg_rtx (compute_mode));
03770 quotient = gen_reg_rtx (compute_mode);
03771 }
03772 else
03773 {
03774 quotient = (GET_CODE (target) == REG
03775 ? target : gen_reg_rtx (compute_mode));
03776 remainder = gen_reg_rtx (compute_mode);
03777 }
03778
03779 if (expand_twoval_binop (sdivmod_optab, op0, op1, quotient,
03780 remainder, 0))
03781 {
03782
03783
03784 rtx tem;
03785 rtx label = gen_label_rtx ();
03786 do_cmp_and_jump (remainder, const0_rtx, EQ,
03787 compute_mode, label);
03788 tem = expand_binop (compute_mode, xor_optab, op0, op1,
03789 NULL_RTX, 0, OPTAB_WIDEN);
03790 do_cmp_and_jump (tem, const0_rtx, LT, compute_mode, label);
03791 expand_inc (quotient, const1_rtx);
03792 expand_dec (remainder, op1);
03793 emit_label (label);
03794 return gen_lowpart (mode, rem_flag ? remainder : quotient);
03795 }
03796
03797
03798
03799 {
03800 rtx label1, label2, label3, label4, label5;
03801 rtx adjusted_op0;
03802 rtx tem;
03803
03804 quotient = gen_reg_rtx (compute_mode);
03805 adjusted_op0 = copy_to_mode_reg (compute_mode, op0);
03806 label1 = gen_label_rtx ();
03807 label2 = gen_label_rtx ();
03808 label3 = gen_label_rtx ();
03809 label4 = gen_label_rtx ();
03810 label5 = gen_label_rtx ();
03811 do_cmp_and_jump (op1, const0_rtx, LT, compute_mode, label2);
03812 do_cmp_and_jump (adjusted_op0, const0_rtx, GT,
03813 compute_mode, label1);
03814 tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
03815 quotient, 0, OPTAB_LIB_WIDEN);
03816 if (tem != quotient)
03817 emit_move_insn (quotient, tem);
03818 emit_jump_insn (gen_jump (label5));
03819 emit_barrier ();
03820 emit_label (label1);
03821 expand_dec (adjusted_op0, const1_rtx);
03822 emit_jump_insn (gen_jump (label4));
03823 emit_barrier ();
03824 emit_label (label2);
03825 do_cmp_and_jump (adjusted_op0, const0_rtx, LT,
03826 compute_mode, label3);
03827 tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
03828 quotient, 0, OPTAB_LIB_WIDEN);
03829 if (tem != quotient)
03830 emit_move_insn (quotient, tem);
03831 emit_jump_insn (gen_jump (label5));
03832 emit_barrier ();
03833 emit_label (label3);
03834 expand_inc (adjusted_op0, const1_rtx);
03835 emit_label (label4);
03836 tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
03837 quotient, 0, OPTAB_LIB_WIDEN);
03838 if (tem != quotient)
03839 emit_move_insn (quotient, tem);
03840 expand_inc (quotient, const1_rtx);
03841 emit_label (label5);
03842 }
03843 }
03844 break;
03845
03846 case EXACT_DIV_EXPR:
03847 if (op1_is_constant && HOST_BITS_PER_WIDE_INT >= size)
03848 {
03849 HOST_WIDE_INT d = INTVAL (op1);
03850 unsigned HOST_WIDE_INT ml;
03851 int pre_shift;
03852 rtx t1;
03853
03854 pre_shift = floor_log2 (d & -d);
03855 ml = invert_mod2n (d >> pre_shift, size);
03856 t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
03857 build_int_2 (pre_shift, 0), NULL_RTX, unsignedp);
03858 quotient = expand_mult (compute_mode, t1,
03859 gen_int_mode (ml, compute_mode),
03860 NULL_RTX, 0);
03861
03862 insn = get_last_insn ();
03863 set_unique_reg_note (insn,
03864 REG_EQUAL,
03865 gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
03866 compute_mode,
03867 op0, op1));
03868 }
03869 break;
03870
03871 case ROUND_DIV_EXPR:
03872 case ROUND_MOD_EXPR:
03873 if (unsignedp)
03874 {
03875 rtx tem;
03876 rtx label;
03877 label = gen_label_rtx ();
03878 quotient = gen_reg_rtx (compute_mode);
03879 remainder = gen_reg_rtx (compute_mode);
03880 if (expand_twoval_binop (udivmod_optab, op0, op1, quotient, remainder, 1) == 0)
03881 {
03882 rtx tem;
03883 quotient = expand_binop (compute_mode, udiv_optab, op0, op1,
03884 quotient, 1, OPTAB_LIB_WIDEN);
03885 tem = expand_mult (compute_mode, quotient, op1, NULL_RTX, 1);
03886 remainder = expand_binop (compute_mode, sub_optab, op0, tem,
03887 remainder, 1, OPTAB_LIB_WIDEN);
03888 }
03889 tem = plus_constant (op1, -1);
03890 tem = expand_shift (RSHIFT_EXPR, compute_mode, tem,
03891 build_int_2 (1, 0), NULL_RTX, 1);
03892 do_cmp_and_jump (remainder, tem, LEU, compute_mode, label);
03893 expand_inc (quotient, const1_rtx);
03894 expand_dec (remainder, op1);
03895 emit_label (label);
03896 }
03897 else
03898 {
03899 rtx abs_rem, abs_op1, tem, mask;
03900 rtx label;
03901 label = gen_label_rtx ();
03902 quotient = gen_reg_rtx (compute_mode);
03903 remainder = gen_reg_rtx (compute_mode);
03904 if (expand_twoval_binop (sdivmod_optab, op0, op1, quotient, remainder, 0) == 0)
03905 {
03906 rtx tem;
03907 quotient = expand_binop (compute_mode, sdiv_optab, op0, op1,
03908 quotient, 0, OPTAB_LIB_WIDEN);
03909 tem = expand_mult (compute_mode, quotient, op1, NULL_RTX, 0);
03910 remainder = expand_binop (compute_mode, sub_optab, op0, tem,
03911 remainder, 0, OPTAB_LIB_WIDEN);
03912 }
03913 abs_rem = expand_abs (compute_mode, remainder, NULL_RTX, 1, 0);
03914 abs_op1 = expand_abs (compute_mode, op1, NULL_RTX, 1, 0);
03915 tem = expand_shift (LSHIFT_EXPR, compute_mode, abs_rem,
03916 build_int_2 (1, 0), NULL_RTX, 1);
03917 do_cmp_and_jump (tem, abs_op1, LTU, compute_mode, label);
03918 tem = expand_binop (compute_mode, xor_optab, op0, op1,
03919 NULL_RTX, 0, OPTAB_WIDEN);
03920 mask = expand_shift (RSHIFT_EXPR, compute_mode, tem,
03921 build_int_2 (size - 1, 0), NULL_RTX, 0);
03922 tem = expand_binop (compute_mode, xor_optab, mask, const1_rtx,
03923 NULL_RTX, 0, OPTAB_WIDEN);
03924 tem = expand_binop (compute_mode, sub_optab, tem, mask,
03925 NULL_RTX, 0, OPTAB_WIDEN);
03926 expand_inc (quotient, tem);
03927 tem = expand_binop (compute_mode, xor_optab, mask, op1,
03928 NULL_RTX, 0, OPTAB_WIDEN);
03929 tem = expand_binop (compute_mode, sub_optab, tem, mask,
03930 NULL_RTX, 0, OPTAB_WIDEN);
03931 expand_dec (remainder, tem);
03932 emit_label (label);
03933 }
03934 return gen_lowpart (mode, rem_flag ? remainder : quotient);
03935
03936 default:
03937 abort ();
03938 }
03939
03940 if (quotient == 0)
03941 {
03942 if (target && GET_MODE (target) != compute_mode)
03943 target = 0;
03944
03945 if (rem_flag)
03946 {
03947
03948
03949
03950
03951
03952
03953
03954
03955
03956 remainder
03957 = sign_expand_binop (compute_mode, umod_optab, smod_optab,
03958 op0, op1, target,
03959 unsignedp,
03960 ((optab2->handlers[(int) compute_mode].insn_code
03961 != CODE_FOR_nothing)
03962 ? OPTAB_DIRECT : OPTAB_WIDEN));
03963 if (remainder == 0)
03964 {
03965
03966
03967 remainder = gen_reg_rtx (compute_mode);
03968 if (! expand_twoval_binop ((unsignedp
03969 ? udivmod_optab
03970 : sdivmod_optab),
03971 op0, op1,
03972 NULL_RTX, remainder, unsignedp))
03973 remainder = 0;
03974 }
03975
03976 if (remainder)
03977 return gen_lowpart (mode, remainder);
03978 }
03979
03980
03981
03982
03983
03984 quotient
03985 = sign_expand_binop (compute_mode, udiv_optab, sdiv_optab,
03986 op0, op1, rem_flag ? NULL_RTX : target,
03987 unsignedp,
03988 ((optab2->handlers[(int) compute_mode].insn_code
03989 != CODE_FOR_nothing)
03990 ? OPTAB_DIRECT : OPTAB_WIDEN));
03991
03992 if (quotient == 0)
03993 {
03994
03995
03996 quotient = gen_reg_rtx (compute_mode);
03997 if (! expand_twoval_binop (unsignedp ? udivmod_optab : sdivmod_optab,
03998 op0, op1,
03999 quotient, NULL_RTX, unsignedp))
04000 {
04001 quotient = 0;
04002 if (! rem_flag)
04003
04004
04005 quotient = sign_expand_binop (compute_mode,
04006 udiv_optab, sdiv_optab,
04007 op0, op1, target,
04008 unsignedp, OPTAB_LIB_WIDEN);
04009 }
04010 }
04011 }
04012
04013 if (rem_flag)
04014 {
04015 if (target && GET_MODE (target) != compute_mode)
04016 target = 0;
04017
04018 if (quotient == 0)
04019
04020 remainder = sign_expand_binop (compute_mode, umod_optab, smod_optab,
04021 op0, op1, target,
04022 unsignedp, OPTAB_LIB_WIDEN);
04023 else
04024 {
04025
04026 remainder = expand_mult (compute_mode, quotient, op1,
04027 NULL_RTX, unsignedp);
04028 remainder = expand_binop (compute_mode, sub_optab, op0,
04029 remainder, target, unsignedp,
04030 OPTAB_LIB_WIDEN);
04031 }
04032 }
04033
04034 return gen_lowpart (mode, rem_flag ? remainder : quotient);
04035 }
04036
04037
04038
04039
04040
04041
04042 tree
04043 make_tree (type, x)
04044 tree type;
04045 rtx x;
04046 {
04047 tree t;
04048
04049 switch (GET_CODE (x))
04050 {
04051 case CONST_INT:
04052 t = build_int_2 (INTVAL (x),
04053 (TREE_UNSIGNED (type)
04054 && (GET_MODE_BITSIZE (TYPE_MODE (type)) < HOST_BITS_PER_WIDE_INT))
04055 || INTVAL (x) >= 0 ? 0 : -1);
04056 TREE_TYPE (t) = type;
04057 return t;
04058
04059 case CONST_DOUBLE:
04060 if (GET_MODE (x) == VOIDmode)
04061 {
04062 t = build_int_2 (CONST_DOUBLE_LOW (x), CONST_DOUBLE_HIGH (x));
04063 TREE_TYPE (t) = type;
04064 }
04065 else
04066 {
04067 REAL_VALUE_TYPE d;
04068
04069 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
04070 t = build_real (type, d);
04071 }
04072
04073 return t;
04074
04075 case CONST_VECTOR:
04076 {
04077 int i, units;
04078 rtx elt;
04079 tree t = NULL_TREE;
04080
04081 units = CONST_VECTOR_NUNITS (x);
04082
04083
04084 for (i = units - 1; i >= 0; --i)
04085 {
04086 elt = CONST_VECTOR_ELT (x, i);
04087 t = tree_cons (NULL_TREE, make_tree (type, elt), t);
04088 }
04089
04090 return build_vector (type, t);
04091 }
04092
04093 case PLUS:
04094 return fold (build (PLUS_EXPR, type, make_tree (type, XEXP (x, 0)),
04095 make_tree (type, XEXP (x, 1))));
04096
04097 case MINUS:
04098 return fold (build (MINUS_EXPR, type, make_tree (type, XEXP (x, 0)),
04099 make_tree (type, XEXP (x, 1))));
04100
04101 case NEG:
04102 return fold (build1 (NEGATE_EXPR, type, make_tree (type, XEXP (x, 0))));
04103
04104 case MULT:
04105 return fold (build (MULT_EXPR, type, make_tree (type, XEXP (x, 0)),
04106 make_tree (type, XEXP (x, 1))));
04107
04108 case ASHIFT:
04109 return fold (build (LSHIFT_EXPR, type, make_tree (type, XEXP (x, 0)),
04110 make_tree (type, XEXP (x, 1))));
04111
04112 case LSHIFTRT:
04113 t = (*lang_hooks.types.unsigned_type) (type);
04114 return fold (convert (type,
04115 build (RSHIFT_EXPR, t,
04116 make_tree (t, XEXP (x, 0)),
04117 make_tree (type, XEXP (x, 1)))));
04118
04119 case ASHIFTRT:
04120 t = (*lang_hooks.types.signed_type) (type);
04121 return fold (convert (type,
04122 build (RSHIFT_EXPR, t,
04123 make_tree (t, XEXP (x, 0)),
04124 make_tree (type, XEXP (x, 1)))));
04125
04126 case DIV:
04127 if (TREE_CODE (type) != REAL_TYPE)
04128 t = (*lang_hooks.types.signed_type) (type);
04129 else
04130 t = type;
04131
04132 return fold (convert (type,
04133 build (TRUNC_DIV_EXPR, t,
04134 make_tree (t, XEXP (x, 0)),
04135 make_tree (t, XEXP (x, 1)))));
04136 case UDIV:
04137 t = (*lang_hooks.types.unsigned_type) (type);
04138 return fold (convert (type,
04139 build (TRUNC_DIV_EXPR, t,
04140 make_tree (t, XEXP (x, 0)),
04141 make_tree (t, XEXP (x, 1)))));
04142
04143 case SIGN_EXTEND:
04144 case ZERO_EXTEND:
04145 t = (*lang_hooks.types.type_for_mode) (GET_MODE (XEXP (x, 0)),
04146 GET_CODE (x) == ZERO_EXTEND);
04147 return fold (convert (type, make_tree (t, XEXP (x, 0))));
04148
04149 default:
04150 t = make_node (RTL_EXPR);
04151 TREE_TYPE (t) = type;
04152
04153 #ifdef POINTERS_EXTEND_UNSIGNED
04154
04155
04156 if (POINTER_TYPE_P (type) && GET_MODE (x) != TYPE_MODE (type))
04157 x = convert_memory_address (TYPE_MODE (type), x);
04158 #endif
04159
04160 RTL_EXPR_RTL (t) = x;
04161
04162
04163 RTL_EXPR_SEQUENCE (t) = 0;
04164 return t;
04165 }
04166 }
04167
04168
04169
04170
04171
04172
04173
04174
04175 bool
04176 const_mult_add_overflow_p (x, mult, add, mode, unsignedp)
04177 rtx x, mult, add;
04178 enum machine_mode mode;
04179 int unsignedp;
04180 {
04181 tree type, mult_type, add_type, result;
04182
04183 type = (*lang_hooks.types.type_for_mode) (mode, unsignedp);
04184
04185
04186
04187 mult_type = type;
04188 if (unsignedp)
04189 {
04190 mult_type = copy_node (type);
04191 TYPE_IS_SIZETYPE (mult_type) = 1;
04192 }
04193
04194 add_type = (GET_MODE (add) == VOIDmode ? mult_type
04195 : (*lang_hooks.types.type_for_mode) (GET_MODE (add), unsignedp));
04196
04197 result = fold (build (PLUS_EXPR, mult_type,
04198 fold (build (MULT_EXPR, mult_type,
04199 make_tree (mult_type, x),
04200 make_tree (mult_type, mult))),
04201 make_tree (add_type, add)));
04202
04203 return TREE_CONSTANT_OVERFLOW (result);
04204 }
04205
04206
04207
04208
04209
04210
04211
04212
04213
04214 rtx
04215 expand_mult_add (x, target, mult, add, mode, unsignedp)
04216 rtx x, target, mult, add;
04217 enum machine_mode mode;
04218 int unsignedp;
04219 {
04220 tree type = (*lang_hooks.types.type_for_mode) (mode, unsignedp);
04221 tree add_type = (GET_MODE (add) == VOIDmode
04222 ? type: (*lang_hooks.types.type_for_mode) (GET_MODE (add),
04223 unsignedp));
04224 tree result = fold (build (PLUS_EXPR, type,
04225 fold (build (MULT_EXPR, type,
04226 make_tree (type, x),
04227 make_tree (type, mult))),
04228 make_tree (add_type, add)));
04229
04230 return expand_expr (result, target, VOIDmode, 0);
04231 }
04232
04233
04234
04235
04236
04237
04238 rtx
04239 expand_and (mode, op0, op1, target)
04240 enum machine_mode mode;
04241 rtx op0, op1, target;
04242 {
04243 rtx tem = 0;
04244
04245 if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode)
04246 tem = simplify_binary_operation (AND, mode, op0, op1);
04247 if (tem == 0)
04248 tem = expand_binop (mode, and_optab, op0, op1, target, 0, OPTAB_LIB_WIDEN);
04249
04250 if (target == 0)
04251 target = tem;
04252 else if (tem != target)
04253 emit_move_insn (target, tem);
04254 return target;
04255 }
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271
04272 rtx
04273 emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
04274 rtx target;
04275 enum rtx_code code;
04276 rtx op0, op1;
04277 enum machine_mode mode;
04278 int unsignedp;
04279 int normalizep;
04280 {
04281 rtx subtarget;
04282 enum insn_code icode;
04283 enum machine_mode compare_mode;
04284 enum machine_mode target_mode = GET_MODE (target);
04285 rtx tem;
04286 rtx last = get_last_insn ();
04287 rtx pattern, comparison;
04288
04289
04290 op0 = protect_from_queue (op0, 0);
04291 op1 = protect_from_queue (op1, 0);
04292
04293 if (unsignedp)
04294 code = unsigned_condition (code);
04295
04296
04297
04298
04299 if (swap_commutative_operands_p (op0, op1))
04300 {
04301 tem = op0;
04302 op0 = op1;
04303 op1 = tem;
04304 code = swap_condition (code);
04305 }
04306
04307 if (mode == VOIDmode)
04308 mode = GET_MODE (op0);
04309
04310
04311
04312
04313
04314 switch (code)
04315 {
04316 case LT:
04317 if (op1 == const1_rtx)
04318 op1 = const0_rtx, code = LE;
04319 break;
04320 case LE:
04321 if (op1 == constm1_rtx)
04322 op1 = const0_rtx, code = LT;
04323 break;
04324 case GE:
04325 if (op1 == const1_rtx)
04326 op1 = const0_rtx, code = GT;
04327 break;
04328 case GT:
04329 if (op1 == constm1_rtx)
04330 op1 = const0_rtx, code = GE;
04331 break;
04332 case GEU:
04333 if (op1 == const1_rtx)
04334 op1 = const0_rtx, code = NE;
04335 break;
04336 case LTU:
04337 if (op1 == const1_rtx)
04338 op1 = const0_rtx, code = EQ;
04339 break;
04340 default:
04341 break;
04342 }
04343
04344
04345
04346 if (GET_MODE_BITSIZE (mode) == BITS_PER_WORD * 2
04347 && GET_MODE_CLASS (mode) == MODE_INT
04348 && op1 == const0_rtx
04349 && (GET_CODE (op0) != MEM || ! MEM_VOLATILE_P (op0)))
04350 {
04351 if (code == EQ || code == NE)
04352 {
04353 rtx op00, op01, op0both;
04354
04355
04356 op00 = simplify_gen_subreg (word_mode, op0, mode, 0);
04357 op01 = simplify_gen_subreg (word_mode, op0, mode, UNITS_PER_WORD);
04358 op0both = expand_binop (word_mode, ior_optab, op00, op01,
04359 NULL_RTX, unsignedp, OPTAB_DIRECT);
04360 if (op0both != 0)
04361 return emit_store_flag (target, code, op0both, op1, word_mode,
04362 unsignedp, normalizep);
04363 }
04364 else if (code == LT || code == GE)
04365 {
04366 rtx op0h;
04367
04368
04369 op0h = simplify_gen_subreg (word_mode, op0, mode,
04370 subreg_highpart_offset (word_mode, mode));
04371 return emit_store_flag (target, code, op0h, op1, word_mode,
04372 unsignedp, normalizep);
04373 }
04374 }
04375
04376
04377 icode = setcc_gen_code[(int) code];
04378
04379
04380
04381 if (op1 == const0_rtx && (code == LT || code == GE)
04382 && GET_MODE_CLASS (mode) == MODE_INT
04383 && (normalizep || STORE_FLAG_VALUE == 1
04384 || (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
04385 && ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
04386 == (HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)))))
04387 {
04388 subtarget = target;
04389
04390
04391
04392
04393 if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (mode))
04394 {
04395 op0 = protect_from_queue (op0, 0);
04396 op0 = convert_modes (target_mode, mode, op0, 0);
04397 mode = target_mode;
04398 }
04399
04400 if (target_mode != mode)
04401 subtarget = 0;
04402
04403 if (code == GE)
04404 op0 = expand_unop (mode, one_cmpl_optab, op0,
04405 ((STORE_FLAG_VALUE == 1 || normalizep)
04406 ? 0 : subtarget), 0);
04407
04408 if (STORE_FLAG_VALUE == 1 || normalizep)
04409
04410
04411
04412 op0 = expand_shift (RSHIFT_EXPR, mode, op0,
04413 size_int (GET_MODE_BITSIZE (mode) - 1),
04414 subtarget, normalizep != -1);
04415
04416 if (mode != target_mode)
04417 op0 = convert_modes (target_mode, mode, op0, 0);
04418
04419 return op0;
04420 }
04421
04422 if (icode != CODE_FOR_nothing)
04423 {
04424 insn_operand_predicate_fn pred;
04425
04426
04427
04428
04429
04430
04431
04432
04433 emit_queue ();
04434 do_pending_stack_adjust ();
04435 last = get_last_insn ();
04436
04437 comparison
04438 = compare_from_rtx (op0, op1, code, unsignedp, mode, NULL_RTX);
04439 if (GET_CODE (comparison) == CONST_INT)
04440 return (comparison == const0_rtx ? const0_rtx
04441 : normalizep == 1 ? const1_rtx
04442 : normalizep == -1 ? constm1_rtx
04443 : const_true_rtx);
04444
04445
04446
04447
04448
04449
04450
04451 code = GET_CODE (comparison);
04452
04453
04454 compare_mode = insn_data[(int) icode].operand[0].mode;
04455 subtarget = target;
04456 pred = insn_data[(int) icode].operand[0].predicate;
04457 if (preserve_subexpressions_p ()
04458 || ! (*pred) (subtarget, compare_mode))
04459 subtarget = gen_reg_rtx (compare_mode);
04460
04461 pattern = GEN_FCN (icode) (subtarget);
04462 if (pattern)
04463 {
04464 emit_insn (pattern);
04465
04466
04467
04468
04469
04470
04471
04472
04473
04474 if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (compare_mode))
04475 {
04476 convert_move (target, subtarget,
04477 (GET_MODE_BITSIZE (compare_mode)
04478 <= HOST_BITS_PER_WIDE_INT)
04479 && 0 == (STORE_FLAG_VALUE
04480 & ((HOST_WIDE_INT) 1
04481 << (GET_MODE_BITSIZE (compare_mode) -1))));
04482 op0 = target;
04483 compare_mode = target_mode;
04484 }
04485 else
04486 op0 = subtarget;
04487
04488
04489
04490
04491 if (preserve_subexpressions_p ())
04492 subtarget = 0;
04493
04494
04495
04496 if (normalizep == 0 || normalizep == STORE_FLAG_VALUE)
04497 ;
04498
04499
04500 else if (- normalizep == STORE_FLAG_VALUE)
04501 op0 = expand_unop (compare_mode, neg_optab, op0, subtarget, 0);
04502
04503
04504
04505
04506 else if (GET_MODE_BITSIZE (compare_mode) <= HOST_BITS_PER_WIDE_INT
04507 && (STORE_FLAG_VALUE
04508 & ((HOST_WIDE_INT) 1
04509 << (GET_MODE_BITSIZE (compare_mode) - 1))))
04510 op0 = expand_shift (RSHIFT_EXPR, compare_mode, op0,
04511 size_int (GET_MODE_BITSIZE (compare_mode) - 1),
04512 subtarget, normalizep == 1);
04513 else if (STORE_FLAG_VALUE & 1)
04514 {
04515 op0 = expand_and (compare_mode, op0, const1_rtx, subtarget);
04516 if (normalizep == -1)
04517 op0 = expand_unop (compare_mode, neg_optab, op0, op0, 0);
04518 }
04519 else
04520 abort ();
04521
04522
04523
04524 if (target_mode != compare_mode)
04525 {
04526 convert_move (target, op0, 0);
04527 return target;
04528 }
04529 else
04530 return op0;
04531 }
04532 }
04533
04534 delete_insns_since (last);
04535
04536
04537
04538
04539 subtarget = (!flag_expensive_optimizations
04540 && (target_mode == mode)) ? target : NULL_RTX;
04541
04542
04543
04544
04545
04546
04547
04548
04549 if (BRANCH_COST > 0
04550 && GET_MODE_CLASS (mode) == MODE_INT && (code == EQ || code == NE)
04551 && op1 != const0_rtx)
04552 {
04553 tem = expand_binop (mode, xor_optab, op0, op1, subtarget, 1,
04554 OPTAB_WIDEN);
04555
04556 if (tem == 0)
04557 tem = expand_binop (mode, sub_optab, op0, op1, subtarget, 1,
04558 OPTAB_WIDEN);
04559 if (tem != 0)
04560 tem = emit_store_flag (target, code, tem, const0_rtx,
04561 mode, unsignedp, normalizep);
04562 if (tem == 0)
04563 delete_insns_since (last);
04564 return tem;
04565 }
04566
04567
04568
04569
04570
04571
04572 if (BRANCH_COST == 0
04573 || GET_MODE_CLASS (mode) != MODE_INT || op1 != const0_rtx
04574 || (code != EQ && code != NE
04575 && (BRANCH_COST <= 1 || (code != LE && code != GT))))
04576 return 0;
04577
04578
04579
04580
04581 if (normalizep == 0)
04582 {
04583 if (STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
04584 normalizep = STORE_FLAG_VALUE;
04585
04586 else if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
04587 && ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
04588 == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)))
04589 ;
04590 else
04591 return 0;
04592 }
04593
04594
04595
04596
04597 tem = 0;
04598
04599
04600
04601
04602 if (code == LE)
04603 {
04604
04605 if (rtx_equal_p (subtarget, op0))
04606 subtarget = 0;
04607
04608 tem = expand_binop (mode, sub_optab, op0, const1_rtx, subtarget, 0,
04609 OPTAB_WIDEN);
04610 if (tem)
04611 tem = expand_binop (mode, ior_optab, op0, tem, subtarget, 0,
04612 OPTAB_WIDEN);
04613 }
04614
04615
04616
04617
04618 if (code == GT)
04619 {
04620 if (rtx_equal_p (subtarget, op0))
04621 subtarget = 0;
04622
04623 tem = expand_shift (RSHIFT_EXPR, mode, op0,
04624 size_int (GET_MODE_BITSIZE (mode) - 1),
04625 subtarget, 0);
04626 tem = expand_binop (mode, sub_optab, tem, op0, subtarget, 0,
04627 OPTAB_WIDEN);
04628 }
04629
04630 if (code == EQ || code == NE)
04631 {
04632
04633
04634
04635
04636
04637
04638
04639
04640
04641
04642
04643
04644
04645
04646
04647 if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
04648 tem = expand_unop (mode, abs_optab, op0, subtarget, 1);
04649 else if (ffs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
04650 tem = expand_unop (mode, ffs_optab, op0, subtarget, 1);
04651 else if (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
04652 {
04653 op0 = protect_from_queue (op0, 0);
04654 tem = convert_modes (word_mode, mode, op0, 1);
04655 mode = word_mode;
04656 }
04657
04658 if (tem != 0)
04659 {
04660 if (code == EQ)
04661 tem = expand_binop (mode, sub_optab, tem, const1_rtx, subtarget,
04662 0, OPTAB_WIDEN);
04663 else
04664 tem = expand_unop (mode, neg_optab, tem, subtarget, 0);
04665 }
04666
04667
04668
04669
04670
04671
04672 if (tem == 0 && (code == NE || BRANCH_COST > 1))
04673 {
04674 if (rtx_equal_p (subtarget, op0))
04675 subtarget = 0;
04676
04677 tem = expand_unop (mode, neg_optab, op0, subtarget, 0);
04678 tem = expand_binop (mode, ior_optab, tem, op0, subtarget, 0,
04679 OPTAB_WIDEN);
04680
04681 if (tem && code == EQ)
04682 tem = expand_unop (mode, one_cmpl_optab, tem, subtarget, 0);
04683 }
04684 }
04685
04686 if (tem && normalizep)
04687 tem = expand_shift (RSHIFT_EXPR, mode, tem,
04688 size_int (GET_MODE_BITSIZE (mode) - 1),
04689 subtarget, normalizep == 1);
04690
04691 if (tem)
04692 {
04693 if (GET_MODE (tem) != target_mode)
04694 {
04695 convert_move (target, tem, 0);
04696 tem = target;
04697 }
04698 else if (!subtarget)
04699 {
04700 emit_move_insn (target, tem);
04701 tem = target;
04702 }
04703 }
04704 else
04705 delete_insns_since (last);
04706
04707 return tem;
04708 }
04709
04710
04711
04712 rtx
04713 emit_store_flag_force (target, code, op0, op1, mode, unsignedp, normalizep)
04714 rtx target;
04715 enum rtx_code code;
04716 rtx op0, op1;
04717 enum machine_mode mode;
04718 int unsignedp;
04719 int normalizep;
04720 {
04721 rtx tem, label;
04722
04723
04724 tem = emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep);
04725 if (tem != 0)
04726 return tem;
04727
04728 if (normalizep == 0)
04729 normalizep = 1;
04730
04731
04732
04733 if (GET_CODE (target) != REG
04734 || reg_mentioned_p (target, op0) || reg_mentioned_p (target, op1))
04735 target = gen_reg_rtx (GET_MODE (target));
04736
04737 emit_move_insn (target, const1_rtx);
04738 label = gen_label_rtx ();
04739 do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, NULL_RTX,
04740 NULL_RTX, label);
04741
04742 emit_move_insn (target, const0_rtx);
04743 emit_label (label);
04744
04745 return target;
04746 }
04747
04748
04749
04750
04751
04752
04753
04754
04755
04756
04757 static void
04758 do_cmp_and_jump (arg1, arg2, op, mode, label)
04759 rtx arg1, arg2, label;
04760 enum rtx_code op;
04761 enum machine_mode mode;
04762 {
04763
04764
04765
04766 if (GET_MODE_CLASS (mode) == MODE_INT
04767 && ! can_compare_p (op, mode, ccp_jump))
04768 {
04769 rtx label2 = gen_label_rtx ();
04770
04771 switch (op)
04772 {
04773 case LTU:
04774 do_jump_by_parts_greater_rtx (mode, 1, arg2, arg1, label2, label);
04775 break;
04776
04777 case LEU:
04778 do_jump_by_parts_greater_rtx (mode, 1, arg1, arg2, label, label2);
04779 break;
04780
04781 case LT:
04782 do_jump_by_parts_greater_rtx (mode, 0, arg2, arg1, label2, label);
04783 break;
04784
04785 case GT:
04786 do_jump_by_parts_greater_rtx (mode, 0, arg1, arg2, label2, label);
04787 break;
04788
04789 case GE:
04790 do_jump_by_parts_greater_rtx (mode, 0, arg2, arg1, label, label2);
04791 break;
04792
04793
04794
04795 case EQ:
04796 if (arg2 != const0_rtx || mode != GET_MODE(arg1))
04797 abort ();
04798 do_jump_by_parts_equality_rtx (arg1, label2, label);
04799 break;
04800
04801 case NE:
04802 if (arg2 != const0_rtx || mode != GET_MODE(arg1))
04803 abort ();
04804 do_jump_by_parts_equality_rtx (arg1, label, label2);
04805 break;
04806
04807 default:
04808 abort ();
04809 }
04810
04811 emit_label (label2);
04812 }
04813 else
04814 emit_cmp_and_jump_insns (arg1, arg2, op, NULL_RTX, mode, 0, label);
04815 }