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
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include <stdint.h>
00047 #include <signal.h>
00048 #include "defs.h"
00049 #include "errors.h"
00050 #include "erglob.h"
00051 #include "ercg.h"
00052 #include "tracing.h"
00053 #include "config.h"
00054 #include "config_targ_opt.h"
00055 #include "config_debug.h"
00056 #include "mtypes.h"
00057 #include "tn.h"
00058 #include "cg_flags.h"
00059 #include "op.h"
00060 #include "cgexp.h"
00061 #include "cgexp_internals.h"
00062 #include "whirl2ops.h"
00063
00064 #define RESET_COND_DEF_LAST(ops) Set_OP_cond_def_kind(OPS_last(ops),OP_ALWAYS_UNC_DEF)
00065
00066
00067
00068
00069
00070
00071
00072 void
00073 Expand_Float_Divide(TN *result, TN *src1, TN *src2, TYPE_ID mtype, OPS *ops)
00074 {
00075 FmtAssert(FALSE, ("Not Yet Implemented"));
00076 }
00077
00078 void
00079 Expand_Float_Recip(TN *result, TN *src, TYPE_ID mtype, OPS *ops)
00080 {
00081 FmtAssert(FALSE, ("Not Yet Implemented"));
00082 }
00083
00084
00085
00086
00087
00088
00089
00090
00091 #define IS_POWER_OF_2(val) ((val != 0) && ((val & (val-1)) == 0))
00092
00093 static BOOL Is_Power_Of_2(INT64 val, TYPE_ID mtype)
00094 {
00095 if (MTYPE_is_signed(mtype) && val < 0) val = -val;
00096
00097 if (mtype == MTYPE_U4) val &= 0xffffffffull;
00098
00099 return IS_POWER_OF_2(val);
00100 }
00101
00102
00103 static INT
00104 Get_Power_Of_2 (INT64 val, TYPE_ID mtype)
00105 {
00106 INT i;
00107 INT64 pow2mask;
00108
00109 if (MTYPE_is_signed(mtype) && val < 0) val = -val;
00110
00111 if (mtype == MTYPE_U4) val &= 0xffffffffull;
00112
00113 pow2mask = 1;
00114 for ( i = 0; i < MTYPE_size_reg(mtype); ++i ) {
00115 if (val == pow2mask) return i;
00116 pow2mask <<= 1;
00117 }
00118
00119 FmtAssert(FALSE, ("Get_Power_Of_2 unexpected value"));
00120
00121 }
00122
00123
00124
00125
00126
00127 static void
00128 Expand_Power_Of_2_Divide (TN *result, TN *numer, INT64 dvsr,
00129 TYPE_ID mtype, OPS *ops)
00130 {
00131 INT n = Get_Power_Of_2(dvsr, mtype);
00132
00133 if (MTYPE_is_unsigned(mtype)) {
00134 Expand_Shift(result, numer, Gen_Literal_TN(n, 4), mtype,
00135 shift_lright, ops);
00136 } else {
00137 TN *t1 = Build_TN_Of_Mtype(mtype);
00138 INT64 absdvsr = dvsr < 0 ? -dvsr : dvsr;
00139 BOOL is_double = MTYPE_is_size_double(mtype);
00140 TN *t2 = Build_TN_Of_Mtype(mtype);
00141 TN *t3 = Build_TN_Of_Mtype(mtype);
00142 TN *t4 = Build_TN_Of_Mtype(mtype);
00143 TN *t5 = (dvsr < 0) ? Build_TN_Of_Mtype(mtype) : result;
00144 Expand_Shift(t1, numer, Gen_Literal_TN(is_double?63:31, 4), mtype,
00145 shift_aright, ops);
00146 Expand_Immediate (t2, Gen_Literal_TN (absdvsr - 1, is_double?8:4),
00147 FALSE, ops);
00148 Expand_Binary_And( t3, t1, t2, mtype, ops );
00149 Expand_Add( t4, t3, numer, mtype, ops );
00150 Expand_Shift(t5, t4, Gen_Literal_TN(n, 4), mtype,
00151 shift_aright, ops);
00152 if (dvsr < 0) Expand_Neg(result, t5, mtype, ops);
00153 }
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 static UINT64 determine_pseudo_inverse (
00206 UINT64 b,
00207 INT64 maxbits_a,
00208 INT64 *pn)
00209 {
00210 INT64 i, n;
00211 UINT64 m, q, b1;
00212
00213
00214
00215
00216
00217 b1 = b - 1;
00218 n = 1;
00219 m = 1;
00220 while(m < b1) {
00221 n++;
00222 m = (m<<1) | 1;
00223 }
00224 *pn = n;
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 for(q=i=0; i<=maxbits_a; i++) {
00238 q <<= 1;
00239 if(m >= b) {
00240 m -= b;
00241 q |= 1;
00242 }
00243 m = (m<<1) | 1;
00244 }
00245 return 1+q;
00246 }
00247
00248
00249 static UINT log2 (UINT i)
00250 {
00251 UINT t = 0;
00252 i = i >> 1;
00253 while(i) {
00254 i = i >> 1;
00255 t ++;
00256 }
00257 return t;
00258 }
00259
00260
00261
00262
00263 static BOOL
00264 Expand_Integer_Divide_By_Constant(TN *result, TN *numer_tn, INT64 denom_val,
00265 TYPE_ID mtype, OPS *ops)
00266 {
00267 UINT64 b;
00268 UINT64 d;
00269 INT64 precision_required;
00270 INT64 n;
00271 BOOL is_odd;
00272 TN *d_tn;
00273 TN *mult_tn;
00274 TN *shift_tn;
00275 TOP opc;
00276 TN *p1;
00277 BOOL is_double = MTYPE_is_size_double(mtype);
00278 BOOL is_signed = MTYPE_is_signed(mtype);
00279
00280
00281
00282 if (denom_val == 1) {
00283 Exp_COPY(result, numer_tn, ops);
00284 return TRUE;
00285 } else if (is_signed && denom_val == -1) {
00286 Expand_Neg(result, numer_tn, mtype, ops);
00287 return TRUE;
00288 }
00289
00290
00291
00292 if (Is_Power_Of_2( denom_val, mtype)) {
00293 Expand_Power_Of_2_Divide(result, numer_tn, denom_val, mtype, ops);
00294 return TRUE;
00295 }
00296
00297 if (!CGEXP_cvrt_int_div_to_mult) return FALSE;
00298
00299 if (!is_double && CG_idivbyconst_opt) {
00300 if (is_signed) {
00301 UINT64 d = labs((UINT64)denom_val);
00302 UINT l = log2((UINT)d);
00303 INT64 e = denom_val;
00304 UINT s, a;
00305 UINT64 m;
00306 UINT64 m_low, m_high, j, k;
00307 UINT shift_amt = 31;
00308
00309 j = (((UINT64)(0x80000000)) % ((UINT64)(d)));
00310 k = (((UINT64)(1)) << (32 + l)) / ((UINT64)(0X80000000 - j));
00311 m_low = (((UINT64)(1)) << (32 + l)) / d;
00312 m_high = ((((UINT64)(1)) << (32 + l)) + k) / d;
00313
00314 while (((m_low >> 1) < (m_high >> 1)) && (l > 0)) {
00315 m_low = m_low >> 1;
00316 m_high = m_high >> 1;
00317 l = l - 1;
00318 }
00319 m = ((UINT)(m_high));
00320 s = l;
00321 a = (m_high >> 31) ? 1: 0;
00322
00323 if (is_double) {
00324 m |= (m -1)<<32;
00325 shift_amt = 63;
00326 }
00327
00328 if (a) {
00329 TN* tmp1_tn = Build_TN_Of_Mtype(MTYPE_I8);
00330 if (!is_double)
00331 Expand_Convert_Length(tmp1_tn, numer_tn, Gen_Literal_TN(32, 4),
00332 MTYPE_I8, TRUE, ops);
00333 else
00334 Expand_Copy( tmp1_tn, numer_tn, mtype, ops);
00335 mult_tn = Build_TN_Of_Mtype(MTYPE_I8);
00336 d_tn = Build_TN_Of_Mtype(MTYPE_I8);
00337 Expand_Immediate (d_tn,
00338 Gen_Literal_TN (!is_double ? (INT)m : m, 8),
00339 is_signed, ops);
00340 if (!is_double) {
00341 Expand_Multiply(mult_tn, tmp1_tn, d_tn, MTYPE_I8, ops);
00342 shift_tn = Build_TN_Of_Mtype(MTYPE_I8);
00343 Expand_Shift(shift_tn, mult_tn, Gen_Literal_TN(32, 4),
00344 MTYPE_I8, shift_lright, ops);
00345 } else {
00346 Expand_High_Multiply(mult_tn, tmp1_tn, d_tn, MTYPE_I8, ops);
00347 shift_tn = mult_tn;
00348 }
00349 TN* tmp2_tn = Build_TN_Of_Mtype(mtype);
00350 Expand_Add(tmp2_tn, shift_tn, numer_tn, mtype, ops);
00351 TN* tmp3_tn = Build_TN_Of_Mtype(mtype);
00352 Expand_Shift(tmp3_tn, numer_tn, Gen_Literal_TN(shift_amt, 4),
00353 mtype, shift_aright, ops);
00354 TN* tmp4_tn = Build_TN_Like(result);
00355 Expand_Shift(tmp4_tn, tmp2_tn, Gen_Literal_TN(s, 4),
00356 mtype, shift_aright, ops);
00357 Expand_Sub(result, tmp4_tn, tmp3_tn, mtype, ops);
00358
00359 if (e > 0)
00360 Expand_Sub(result, tmp4_tn, tmp3_tn, mtype, ops);
00361 else
00362 Expand_Sub(result, tmp3_tn, tmp4_tn, mtype, ops);
00363
00364 } else if( Is_Target_32bit() ){
00365 TN* eax_tn = Build_TN_Of_Mtype(mtype);
00366 Expand_Immediate( eax_tn, Gen_Literal_TN(m,4), is_signed, ops );
00367
00368 TN* edx_tn = Build_TN_Like( result );
00369 Build_OP( TOP_imulx32, eax_tn, edx_tn, eax_tn, numer_tn, ops );
00370
00371 Expand_Copy( eax_tn, numer_tn, mtype, ops );
00372
00373 if( s ){
00374 Expand_Shift( edx_tn, edx_tn, Gen_Literal_TN(s, 4),
00375 mtype, shift_aright, ops);
00376 }
00377
00378 Expand_Shift( eax_tn, eax_tn, Gen_Literal_TN(shift_amt, 4),
00379 mtype, shift_lright, ops);
00380
00381 Expand_Add( edx_tn, edx_tn, eax_tn, mtype, ops );
00382
00383 if( e < 0 ){
00384 Expand_Neg( edx_tn, edx_tn, mtype, ops );
00385 }
00386
00387 Expand_Copy( result, edx_tn, mtype, ops );
00388
00389 } else {
00390 TN* tmp1_tn = Build_TN_Of_Mtype(MTYPE_I8);
00391 if (!is_double)
00392 Expand_Convert_Length(tmp1_tn, numer_tn, Gen_Literal_TN(32, 4),
00393 MTYPE_I8, TRUE, ops);
00394 else
00395 Expand_Copy( tmp1_tn, numer_tn, mtype, ops);
00396 TN* tmp2_tn = Build_TN_Of_Mtype(mtype);
00397 Expand_Shift(tmp2_tn, numer_tn, Gen_Literal_TN(shift_amt, 4),
00398 mtype, shift_aright, ops);
00399 mult_tn = Build_TN_Of_Mtype(MTYPE_I8);
00400 d_tn = Build_TN_Of_Mtype(MTYPE_I8);
00401 Expand_Immediate (d_tn, Gen_Literal_TN (m, 8), is_signed, ops);
00402 if (!is_double) {
00403 Expand_Multiply(mult_tn, tmp1_tn, d_tn, MTYPE_I8, ops);
00404 shift_tn = Build_TN_Of_Mtype(MTYPE_I8);
00405 Expand_Shift(shift_tn, mult_tn, Gen_Literal_TN(32, 4),
00406 MTYPE_I8, shift_lright, ops);
00407 } else {
00408 Expand_High_Multiply(mult_tn, tmp1_tn, d_tn, MTYPE_I8, ops);
00409 shift_tn = mult_tn;
00410 }
00411 TN* tmp3_tn = Build_TN_Like(result);
00412 if (s)
00413 Expand_Shift(tmp3_tn, shift_tn, Gen_Literal_TN(s, 4),
00414 mtype, shift_aright, ops);
00415 else
00416 Expand_Copy(tmp3_tn, shift_tn, mtype, ops);
00417
00418 if( e < 0 )
00419
00420 Expand_Sub(result, tmp2_tn, tmp3_tn, mtype, ops);
00421 else
00422 Expand_Sub(result, tmp3_tn, tmp2_tn, mtype, ops);
00423 }
00424 return TRUE;
00425 } else if ((UINT)denom_val < 0x80000000UL) {
00426 UINT l, n, t, d, m, s, a, r;
00427 UINT64 m_low, m_high, j, k;
00428
00429 n = 0;
00430 t = d = (UINT)denom_val;
00431
00432 while (!(t & 1)) {
00433 t >>= 1;
00434 n++;
00435 }
00436
00437 l = log2(t) + 1;
00438 j = (((UINT64)(0xffffffff)) % ((UINT64)(t)));
00439 k = (((UINT64)(1)) << (32 + l)) / ((UINT64)(0xffffffff - j));
00440 m_low = (((UINT64)(1)) << (32 + l)) / t;
00441 m_high = ((((UINT64)(1)) << (32 + l)) + k) / t;
00442 while (((m_low >> 1) < (m_high >> 1)) && (l > 0)) {
00443 m_low = m_low >> 1;
00444 m_high = m_high >> 1;
00445 l = l - 1;
00446 }
00447 if ((m_high >> 32) == 0) {
00448 m = ((UINT)(m_high));
00449 s = l;
00450 a = 0;
00451 }
00452 else {
00453 s = log2(t);
00454 m_low = (((UINT64)(1)) << (32 + s)) / ((UINT64)(t));
00455 r = ((UINT)((((UINT64)(1)) << (32 + s)) % ((UINT64)(t))));
00456 m = (r < ((t >> 1) + 1)) ? ((UINT)(m_low)) : ((UINT)(m_low)) + 1;
00457 a = 1;
00458 }
00459
00460 s += n;
00461
00462 if (a) {
00463 TN* tmp1_tn = Build_TN_Of_Mtype(MTYPE_I8);
00464 TN* tmp2_tn = Build_TN_Like(result);
00465 TN* tmp3_tn = Build_TN_Like(result);
00466 TN* tmp4_tn = Build_TN_Like(result);
00467 m <<= 1;
00468 m ++;
00469 d_tn = Build_TN_Of_Mtype(MTYPE_I8);
00470 Expand_Immediate(d_tn, Gen_Literal_TN (m, 8), is_signed, ops);
00471 mult_tn = Build_TN_Of_Mtype(MTYPE_I8);
00472 Expand_Multiply(mult_tn, numer_tn, d_tn, MTYPE_I8, ops);
00473 Expand_Shift(tmp1_tn, mult_tn, Gen_Literal_TN(32, 4),
00474 MTYPE_I8, shift_lright, ops);
00475 Expand_Sub(tmp2_tn, numer_tn, tmp1_tn, mtype, ops);
00476 Expand_Shift(tmp3_tn, tmp2_tn, Gen_Literal_TN(1, 4),
00477 mtype, shift_lright, ops);
00478 Expand_Add(tmp4_tn, tmp3_tn, tmp1_tn, mtype, ops);
00479 Expand_Shift(result, tmp4_tn, Gen_Literal_TN(s, 4),
00480 mtype, shift_lright, ops);
00481 } else {
00482 TN* tmp1_tn = Build_TN_Of_Mtype(MTYPE_I8);
00483 d_tn = Build_TN_Of_Mtype(MTYPE_I8);
00484 Expand_Immediate (d_tn, Gen_Literal_TN (m, 8), is_signed, ops);
00485 mult_tn = Build_TN_Of_Mtype(MTYPE_I8);
00486 Expand_Multiply(mult_tn, numer_tn, d_tn, MTYPE_I8, ops);
00487 Expand_Shift(tmp1_tn, mult_tn, Gen_Literal_TN(32, 4),
00488 MTYPE_I8, shift_lright, ops);
00489 Expand_Shift(result, tmp1_tn, Gen_Literal_TN(s, 4),
00490 mtype, shift_lright, ops);
00491 }
00492 return TRUE;
00493 } else {
00494
00495 TN* tmp1_tn = Build_TN_Of_Mtype(MTYPE_I4);
00496 TN* tmp2_tn = Build_TN_Of_Mtype(MTYPE_I4);
00497 TN* tmp3_tn = Build_TN_Of_Mtype(MTYPE_I4);
00498 TN* rflags = Rflags_TN();
00499 Expand_Immediate (tmp1_tn, Gen_Literal_TN ((INT)denom_val, 4),
00500 is_signed, ops);
00501 Build_OP(TOP_cmp32, rflags, numer_tn, tmp1_tn, ops);
00502 Expand_Immediate(tmp2_tn, Gen_Literal_TN (0, 4), is_signed, ops);
00503 Expand_Immediate(tmp3_tn, Gen_Literal_TN(-1, 4), is_signed, ops);
00504 Build_OP(TOP_sbb32, result, tmp2_tn, tmp3_tn, ops);
00505 return TRUE;
00506 }
00507 }
00508
00509 if (is_signed) {
00510
00511 b = denom_val<0 ? -denom_val : denom_val;
00512 is_odd = (b&1);
00513
00514 d = determine_pseudo_inverse (b, is_double?63:31, &n);
00515
00516 if (n > (is_double ? 63 : 31)) {
00517
00518 return FALSE;
00519 }
00520
00521 d_tn = Build_TN_Like (result);
00522 Expand_Immediate (d_tn, Gen_Literal_TN (d, 8), is_signed, ops);
00523
00524
00525
00526 TN *neg_tn = Build_TN_Of_Mtype (mtype);
00527 p1 = Rflags_TN();
00528 Expand_Neg (neg_tn, numer_tn, mtype, ops);
00529 Expand_Cmov (TOP_cmovs, neg_tn, numer_tn, p1, ops);
00530
00531
00532
00533 mult_tn = Build_TN_Of_Mtype (mtype);
00534 Expand_High_Multiply (mult_tn, neg_tn, d_tn,
00535 is_double?MTYPE_U8:MTYPE_U4, ops);
00536
00537
00538
00539 if (n > 0) {
00540 shift_tn = Build_TN_Of_Mtype (mtype);
00541 Expand_Shift(shift_tn, mult_tn, Gen_Literal_TN (n-1, 4),
00542 mtype, shift_aright, ops);
00543 } else {
00544 shift_tn = mult_tn;
00545 }
00546
00547
00548
00549 if (shift_tn == result) {
00550 TN *tmp_result = Build_TN_Like(shift_tn);
00551 Expand_Copy( tmp_result, shift_tn, mtype, ops);
00552 shift_tn = tmp_result;
00553 } else if (result == numer_tn) {
00554 TN *tmp_numer = Build_TN_Like(numer_tn);
00555 Expand_Copy( tmp_numer, numer_tn, mtype, ops);
00556 numer_tn = tmp_numer;
00557 }
00558 Expand_Neg(result, shift_tn, mtype, ops);
00559 Build_OP(is_double?TOP_test64:TOP_test32, p1,
00560 numer_tn, numer_tn, ops);
00561 if (denom_val > 0)
00562 Expand_Cmov (TOP_cmovge, result, shift_tn, p1, ops);
00563 else
00564 Expand_Cmov (TOP_cmovl, result, shift_tn, p1, ops);
00565 }
00566
00567 else {
00568
00569 b = denom_val;
00570 is_odd = (b&1);
00571
00572
00573
00574 if (is_odd) {
00575 precision_required = is_double?64:32;
00576 } else {
00577
00578
00579
00580
00581
00582 b >>= 1;
00583 precision_required = is_double?63:31;
00584
00585
00586
00587 TN *tmp1_tn = Build_TN_Of_Mtype (mtype);
00588 Expand_Shift(tmp1_tn, numer_tn, Gen_Literal_TN (1, 4),
00589 mtype, shift_lright, ops);
00590 numer_tn = tmp1_tn;
00591 }
00592
00593 d = determine_pseudo_inverse (b, precision_required, &n);
00594
00595 if (n > precision_required) {
00596
00597 return FALSE;
00598 }
00599
00600 d_tn = Build_TN_Like (result);
00601
00602 Expand_Immediate (d_tn, Gen_Literal_TN (d, 8), is_signed, ops);
00603
00604
00605
00606 mult_tn = Build_TN_Of_Mtype (mtype);
00607
00608 Expand_High_Multiply (mult_tn, numer_tn, d_tn,
00609 is_double?MTYPE_U8:MTYPE_U4, ops);
00610
00611 if (precision_required == 64 || precision_required == 32) {
00612
00613
00614
00615 TN *tmp1_tn = Build_TN_Of_Mtype (mtype);
00616 TN *tmp2_tn = Build_TN_Of_Mtype (mtype);
00617 TN *tmp3_tn = Build_TN_Of_Mtype (mtype);
00618 Expand_Sub (tmp1_tn, numer_tn, mult_tn, mtype, ops);
00619 Expand_Shift (tmp2_tn, tmp1_tn, Gen_Literal_TN (1, 4),
00620 mtype, shift_lright, ops);
00621 Expand_Add (tmp3_tn, mult_tn, tmp2_tn, mtype, ops);
00622 mult_tn = tmp3_tn;
00623 }
00624
00625
00626
00627 Expand_Shift (result, mult_tn, Gen_Literal_TN (n-1, 4),
00628 mtype, shift_lright, ops);
00629 }
00630
00631 return TRUE;
00632 }
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 static void Expand_Fast_Power_Of_2_Rem( TN* result, TN* src1, INT64 src2_val,
00653 TYPE_ID mtype, OPS* ops )
00654 {
00655 FmtAssert( !TN_is_dedicated(result), ("NYI") );
00656
00657 const BOOL is_64bit = MTYPE_is_size_double(mtype);
00658 BB* bb_entry = Cur_BB;
00659 BB* bb_then = Gen_And_Append_BB( bb_entry );
00660 BB* bb_else = Gen_And_Append_BB( bb_then );
00661 const LABEL_IDX bb_else_label = Gen_Label_For_BB( bb_else );
00662
00663 BB* bb_exit = Gen_And_Append_BB( bb_else );
00664 const LABEL_IDX bb_exit_label = Gen_Label_For_BB( bb_exit );
00665
00666 BB_branch_wn(bb_then) = WN_Create(OPC_GOTO,0);
00667 WN_label_number(BB_branch_wn(bb_then)) = bb_exit_label;
00668
00669 BB_branch_wn(bb_entry) = WN_Create(OPC_TRUEBR,1);
00670 WN_kid0(BB_branch_wn(bb_entry)) = NULL;
00671 WN_label_number(BB_branch_wn(bb_entry)) = bb_else_label;
00672
00673
00674 {
00675 Exp_OP3v( OPC_TRUEBR,
00676 NULL,
00677 Gen_Label_TN( bb_else_label, 0 ),
00678 src1,
00679 Gen_Literal_TN(0,4),
00680 V_BR_I4GE,
00681 ops );
00682
00683 if( &New_OPs != ops )
00684 OPS_Append_Ops( &New_OPs, ops );
00685 Process_New_OPs();
00686 BB_Append_Ops( bb_entry, &New_OPs );
00687 OPS_Init( &New_OPs );
00688 OPS_Init( ops );
00689 }
00690
00691
00692 {
00693 OPS* bb_then_ops = &New_OPs;
00694
00695 TN *t1 = Build_TN_Of_Mtype(mtype);
00696 INT64 absdvsr = src2_val < 0 ? -src2_val : src2_val;
00697 BOOL is_double = MTYPE_is_size_double(mtype);
00698 TN *t2 = Build_TN_Of_Mtype(mtype);
00699 TN *t3 = Build_TN_Of_Mtype(mtype);
00700 TN *t4 = Build_TN_Of_Mtype(mtype);
00701 TN *t5 = Build_TN_Of_Mtype(mtype);
00702 Expand_Shift(t1, src1, Gen_Literal_TN(is_double?63:31, 4), mtype,
00703 shift_aright, bb_then_ops);
00704 Expand_Immediate (t2, Gen_Literal_TN (absdvsr - 1, is_double?8:4),
00705 FALSE, bb_then_ops);
00706 Expand_Binary_And( t3, t1, t2, mtype, bb_then_ops );
00707 Expand_Add( t4, t3, src1, mtype, bb_then_ops );
00708 Expand_Binary_And( t5, t4, t2, mtype, bb_then_ops );
00709 Expand_Sub( result, t5, t3, mtype, bb_then_ops );
00710
00711 Build_OP( TOP_jmp, Gen_Label_TN( bb_exit_label, 0 ), bb_then_ops );
00712
00713 total_bb_insts = 0;
00714 Last_Processed_OP = NULL;
00715 Process_New_OPs();
00716 BB_Append_Ops( bb_then, bb_then_ops );
00717 OPS_Init( bb_then_ops );
00718 }
00719
00720
00721 {
00722 OPS* bb_else_ops = &New_OPs;
00723
00724 FmtAssert( ISA_LC_Value_In_Class( src2_val, LC_simm32 ), ("NYI") );
00725 Expand_Binary_And( result, src1, Gen_Literal_TN(src2_val-1,4),
00726 mtype, bb_else_ops );
00727
00728 total_bb_insts = 0;
00729 Last_Processed_OP = NULL;
00730 Process_New_OPs();
00731 BB_Append_Ops( bb_else, bb_else_ops );
00732 OPS_Init( bb_else_ops );
00733 }
00734
00735 Cur_BB = bb_exit;
00736 }
00737
00738
00739 static void
00740 Expand_Power_Of_2_Rem (TN *result, TN *src1, INT64 src2_val, TYPE_ID mtype, OPS *ops)
00741 {
00742 BOOL is_double = MTYPE_is_size_double(mtype);
00743 INT n = Get_Power_Of_2(src2_val, mtype);
00744 INT64 nMask = (1LL << n) - 1;
00745 TN *con = Gen_Literal_TN(nMask, is_double ? 8 : 4);
00746
00747 if (MTYPE_is_signed(mtype)) {
00748
00749
00750
00751 if( CG_use_setcc || Is_Target_32bit() || src2_val < 0 ){
00752 TN *t1 = Build_TN_Of_Mtype(mtype);
00753 INT64 absdvsr = src2_val < 0 ? -src2_val : src2_val;
00754 BOOL is_double = MTYPE_is_size_double(mtype);
00755 TN *t2 = Build_TN_Of_Mtype(mtype);
00756 TN *t3 = Build_TN_Of_Mtype(mtype);
00757 TN *t4 = Build_TN_Of_Mtype(mtype);
00758 TN *t5 = Build_TN_Of_Mtype(mtype);
00759 Expand_Shift(t1, src1, Gen_Literal_TN(is_double?63:31, 4), mtype,
00760 shift_aright, ops);
00761 Expand_Immediate (t2, Gen_Literal_TN (absdvsr - 1, is_double?8:4),
00762 FALSE, ops);
00763 Expand_Binary_And( t3, t1, t2, mtype, ops );
00764 Expand_Add( t4, t3, src1, mtype, ops );
00765 Expand_Binary_And( t5, t4, t2, mtype, ops );
00766 Expand_Sub( result, t5, t3, mtype, ops );
00767
00768 } else {
00769 Expand_Fast_Power_Of_2_Rem( result, src1, src2_val, mtype, ops );
00770 }
00771 } else {
00772 Expand_Binary_And(result, src1, con, mtype, ops);
00773 }
00774 }
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791 static void
00792 Expand_Power_Of_2_Mod (TN *result, TN *src1, INT64 src2_val, TYPE_ID mtype, OPS *ops)
00793 {
00794 BOOL is_double = MTYPE_is_size_double(mtype);
00795 INT64 absval = src2_val < 0 ? -src2_val : src2_val;
00796 INT n = Get_Power_Of_2(absval, mtype);
00797 INT64 nMask = (1LL << n) - 1;
00798 TN *con = Gen_Literal_TN(nMask, is_double ? 8 : 4);
00799
00800 if (MTYPE_is_signed(mtype) && src2_val < 0) {
00801 TN *tmp1, *tmp2;
00802
00803 tmp1 = Build_TN_Of_Mtype(mtype);
00804 Expand_Neg(tmp1, src1, mtype, ops);
00805
00806 tmp2 = Build_TN_Of_Mtype(mtype);
00807 Expand_Binary_And(tmp2, tmp1, con, mtype, ops);
00808
00809 Expand_Neg(result, tmp2, mtype, ops);
00810 } else {
00811 Expand_Binary_And(result, src1, con, mtype, ops);
00812 }
00813 }
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823 static void
00824 Extend_Dividend (TN **dividend_lo, TN **dividend_hi, TYPE_ID mtype,
00825 BOOL is_double, OPS *ops)
00826 {
00827 *dividend_hi = Build_TN_Like(*dividend_lo);
00828 if (MTYPE_is_signed(mtype)){
00829
00830
00831
00832
00833
00834
00835
00836 TN *new_dividend_lo = Build_TN_Like(*dividend_lo);
00837 Build_OP(is_double ? TOP_cqto : TOP_cltd, new_dividend_lo, *dividend_hi,
00838 *dividend_lo, ops);
00839 *dividend_lo = new_dividend_lo;
00840 } else {
00841 Build_OP(TOP_ldc32, *dividend_hi, Gen_Literal_TN(0, 4), ops);
00842 }
00843 }
00844
00845 TN *
00846 Expand_Divide (TN *result, TN *src1, TN *src2, TYPE_ID mtype, OPS *ops)
00847 {
00848
00849
00850 INT64 src2_val;
00851 BOOL const_src2 = TN_Value_At_Op (src2, NULL, &src2_val);
00852 BOOL is_double = MTYPE_is_size_double(mtype);
00853 if (const_src2) {
00854 if (src2_val == 0){
00855
00856
00857
00858
00859
00860 DevWarn("Division by zero detected.\n");
00861
00862 } else if (Expand_Integer_Divide_By_Constant(result, src1, src2_val, mtype, ops)){
00863 return NULL;
00864 }
00865 }
00866
00867 TOP top;
00868 FmtAssert(!TN_is_constant(src1),
00869 ("Expand_Divide: unexpected constant operand"));
00870 if (TN_is_constant(src2))
00871 src2 = Expand_Immediate_Into_Register(src2, is_double, ops);
00872
00873
00874 switch (mtype) {
00875 case MTYPE_I4: top = TOP_idiv32; break;
00876 case MTYPE_I8: top = TOP_idiv64; break;
00877 case MTYPE_U4: top = TOP_div32; break;
00878 case MTYPE_U8: top = TOP_div64; break;
00879 default: FmtAssert (FALSE, ("Handle this")); break;
00880 }
00881 TN *result1 = Build_TN_Like(result);
00882 TN *src3;
00883 Extend_Dividend(&src1, &src3, mtype, is_double, ops);
00884 FmtAssert( !OP_NEED_PAIR(mtype), ("NYI") );
00885 Build_OP(top, result, result1, src1, src3, src2, ops);
00886 }
00887
00888
00889 void
00890 Expand_Rem (TN *result, TN *src1, TN *src2, TYPE_ID mtype, OPS *ops)
00891 {
00892 TOP top;
00893 BOOL is_double = MTYPE_is_size_double(mtype);
00894
00895 if( src1 == src2 ){
00896 Build_OP( is_double ? TOP_ldc64 : TOP_ldc32,
00897 result, Gen_Literal_TN(0, 4), ops );
00898 return;
00899 }
00900
00901
00902
00903 INT64 src2_val;
00904 BOOL const_src2 = TN_Value_At_Op (src2, NULL, &src2_val);
00905 if (const_src2) {
00906 if (src2_val == 0)
00907 DevWarn("Division by zero detected.\n");
00908
00909
00910
00911 if (Is_Power_Of_2(src2_val, mtype)) {
00912 Expand_Power_Of_2_Rem(result, src1, src2_val, mtype, ops);
00913 return;
00914 }
00915
00916
00917
00918
00919
00920 if (CGEXP_cvrt_int_div_to_mult && (src2_val != 0)) {
00921
00922 TN *div_tn = Build_TN_Like (result);
00923
00924 if (Expand_Integer_Divide_By_Constant(div_tn, src1, src2_val,
00925 mtype, ops)) {
00926 TN *mult_tn;
00927
00928
00929
00930 mult_tn = Build_TN_Like (result);
00931 Expand_Multiply(mult_tn, div_tn, src2, mtype, ops);
00932
00933
00934
00935 Build_OP(is_double?TOP_sub64:TOP_sub32, result, src1, mult_tn, ops);
00936 return;
00937 }
00938 }
00939 }
00940
00941 FmtAssert(!TN_is_constant(src1),
00942 ("Expand_Divide: unexpected constant operand"));
00943 if (TN_is_constant(src2))
00944 src2 = Expand_Immediate_Into_Register(src2, is_double, ops);
00945 switch (mtype) {
00946 case MTYPE_I4: top = TOP_idiv32; break;
00947 case MTYPE_I8: top = TOP_idiv64; break;
00948 case MTYPE_U4: top = TOP_div32; break;
00949 case MTYPE_U8: top = TOP_div64; break;
00950 default: FmtAssert (FALSE, ("Handle this")); break;
00951 }
00952 TN *result1 = Build_TN_Like(result);
00953 TN *src3;
00954 Extend_Dividend(&src1, &src3, mtype, is_double, ops);
00955 Build_OP(top, result1, result, src1, src3, src2, ops);
00956 }
00957
00958
00959
00960 void
00961 Expand_Mod (TN *result, TN *src1, TN *src2, TYPE_ID mtype, OPS *ops)
00962 {
00963 TOP opc;
00964 BOOL is_double = MTYPE_is_size_double(mtype);
00965
00966
00967
00968 INT64 src2_val;
00969 BOOL const_src2 = TN_Value_At_Op (src2, NULL, &src2_val);
00970 if (const_src2 && Is_Power_Of_2(src2_val, mtype)) {
00971 Expand_Power_Of_2_Mod (result, src1, src2_val, mtype, ops);
00972 return;
00973 }
00974
00975 if (const_src2)
00976 if (src2_val == 0)
00977 FmtAssert (FALSE, ("Division by zero detected.\n"));
00978
00979
00980 TN *remainder = result;
00981 Expand_Rem(remainder, src1, src2, mtype, ops);
00982
00983
00984
00985
00986
00987
00988
00989 TN *p1 = Rflags_TN();
00990 TN *src1_xor_src2 = Build_TN_Like(result);
00991 Build_OP(is_double ? TOP_xor64 : TOP_xor32, src1_xor_src2, src1, src2, ops);
00992 Build_OP(is_double ? TOP_test64 : TOP_test32, p1,
00993 src1_xor_src2, src1_xor_src2, ops);
00994
00995
00996 TN *divisor_or_zero = Build_TN_Like(result);
00997 Build_OP(is_double ? TOP_ldc64 : TOP_ldc32,
00998 divisor_or_zero, Gen_Literal_TN(0, is_double ? 8 : 4), ops);
00999 Expand_Cmov(TOP_cmovl, divisor_or_zero, src2, p1, ops);
01000
01001
01002 TN *remainder_plus_divisor = Build_TN_Like(result);
01003 Build_OP(is_double ? TOP_add64 : TOP_add32,
01004 remainder_plus_divisor, remainder, divisor_or_zero, ops);
01005
01006
01007 TN *p2 = Rflags_TN();
01008 Build_OP(TOP_test32, p2, remainder, remainder, ops);
01009 Expand_Cmov(TOP_cmovne, remainder, remainder_plus_divisor, p2, ops);
01010
01011
01012
01013 }
01014
01015
01016 void
01017 Expand_DivRem(TN *result, TN *result2, TN *src1, TN *src2, TYPE_ID mtype, OPS *ops)
01018 {
01019 BOOL is_double = MTYPE_is_size_double(mtype);
01020
01021
01022
01023
01024
01025
01026
01027 INT64 src1_val;
01028 BOOL const_src1 = TN_Value_At_Op (src1, NULL, &src1_val);
01029 INT64 src2_val;
01030 BOOL const_src2 = TN_Value_At_Op (src2, NULL, &src2_val);
01031
01032 if (const_src2){
01033 if (src2_val == 0){
01034 DevWarn( "Division by zero detected at compile time.\n" );
01035 const_src2 = FALSE;
01036 }
01037 }
01038
01039 if (const_src1 && const_src2) {
01040 if (MTYPE_is_signed(mtype)) {
01041 const INT64 minintval = is_double ? INT64_MIN : INT32_MIN;
01042 if (src1_val == minintval && src2_val == -1) {
01043
01044
01045 printf("pathcc - division overflow detected\n");
01046 INT tn_size = MTYPE_is_size_double(mtype) ? 8 : 4;
01047 src2 = Expand_Immediate_Into_Register(Gen_Literal_TN(src2_val, tn_size),
01048 is_double, ops);
01049 src1 = Expand_Immediate_Into_Register(Gen_Literal_TN(src1_val, tn_size),
01050 is_double, ops);
01051 TN *src3;
01052 Extend_Dividend(&src1, &src3, mtype, is_double, ops);
01053 Build_OP(is_double ? TOP_idiv64 : TOP_idiv32,
01054 result, result2, src1, src3, src2, ops);
01055 return;
01056 }
01057 }
01058 INT64 quot_val, rem_val;
01059 switch (mtype) {
01060 case MTYPE_I8:
01061 quot_val = (INT64)src1_val / (INT64)src2_val;
01062 rem_val = (INT64)src1_val % (INT64)src2_val;
01063 break;
01064 case MTYPE_U8:
01065 quot_val = (UINT64)src1_val / (UINT64)src2_val;
01066 rem_val = (UINT64)src1_val % (UINT64)src2_val;
01067 break;
01068 case MTYPE_U4:
01069 quot_val = (UINT32)src1_val / (UINT32)src2_val;
01070 rem_val = (UINT32)src1_val % (UINT32)src2_val;
01071 break;
01072 case MTYPE_I4:
01073 quot_val = (INT32)src1_val / (INT32)src2_val;
01074 rem_val = (INT32)src1_val % (INT32)src2_val;
01075 break;
01076 }
01077 BOOL is_signed = MTYPE_is_signed(mtype);
01078 INT tn_size = MTYPE_is_size_double(mtype) ? 8 : 4;
01079 Exp_Immediate(result, Gen_Literal_TN(quot_val, tn_size), is_signed, ops);
01080 Exp_Immediate(result2, Gen_Literal_TN(rem_val, tn_size), is_signed, ops);
01081 return;
01082 }
01083
01084
01085
01086 if (const_src2) {
01087 if (Expand_Integer_Divide_By_Constant(result, src1, src2_val, mtype, ops)) {
01088
01089
01090
01091
01092
01093 if (!MTYPE_is_signed(mtype) && Is_Power_Of_2(src2_val, mtype)) {
01094 Expand_Power_Of_2_Rem(result2, src1, src2_val, mtype, ops);
01095 } else {
01096 TN *t1 = Build_TN_Like(result);
01097 Expand_Multiply(t1, result, src2, mtype, ops);
01098 Expand_Sub( result2, src1, t1, mtype, ops );
01099 }
01100 return;
01101 }
01102 }
01103
01104 FmtAssert( !OP_NEED_PAIR(mtype), ("Expand_DivRem: DIVREM should not be 64-bit") );
01105
01106 TOP top;
01107 FmtAssert(!TN_is_constant(src1),
01108 ("Expand_Divide: unexpected constant operand"));
01109 if (TN_is_constant(src2))
01110 src2 = Expand_Immediate_Into_Register(src2, is_double, ops);
01111
01112
01113 switch (mtype) {
01114 case MTYPE_I4: top = TOP_idiv32; break;
01115 case MTYPE_I8: top = TOP_idiv64; break;
01116 case MTYPE_U4: top = TOP_div32; break;
01117 case MTYPE_U8: top = TOP_div64; break;
01118 default: FmtAssert (FALSE, ("Handle this")); break;
01119 }
01120 TN *src3;
01121 Extend_Dividend(&src1, &src3, mtype, is_double, ops);
01122 Build_OP(top, result, result2, src1, src3, src2, ops);
01123 }