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 #define __STDC_LIMIT_MACROS
00043 #include <stdint.h>
00044 #include <signal.h>
00045 #include "defs.h"
00046 #include "errors.h"
00047 #include "erglob.h"
00048 #include "ercg.h"
00049 #include "tracing.h"
00050 #include "config.h"
00051 #include "config_targ_opt.h"
00052 #include "config_debug.h"
00053 #include "mtypes.h"
00054 #include "tn.h"
00055 #include "cg_flags.h"
00056 #include "op.h"
00057 #include "cgexp.h"
00058 #include "cgexp_internals.h"
00059
00060 #define RESET_COND_DEF_LAST(ops) Set_OP_cond_def_kind(OPS_last(ops),OP_ALWAYS_UNC_DEF)
00061
00062
00063
00064
00065
00066
00067
00068 void
00069 Expand_Float_Divide(TN *result, TN *src1, TN *src2, TYPE_ID mtype, OPS *ops)
00070 {
00071 FmtAssert(FALSE, ("Not Yet Implemented"));
00072 }
00073
00074 void
00075 Expand_Float_Recip(TN *result, TN *src, TYPE_ID mtype, OPS *ops)
00076 {
00077 FmtAssert(FALSE, ("Not Yet Implemented"));
00078 }
00079
00080
00081
00082
00083
00084
00085
00086
00087 #define IS_POWER_OF_2(val) ((val != 0) && ((val & (val-1)) == 0))
00088
00089 BOOL Is_Power_Of_2(INT64 val, TYPE_ID mtype)
00090 {
00091 if (MTYPE_is_signed(mtype) && val < 0) val = -val;
00092
00093 if (mtype == MTYPE_U4) val &= 0xffffffffull;
00094
00095 return IS_POWER_OF_2(val);
00096 }
00097
00098
00099 static INT
00100 Get_Power_Of_2 (INT64 val, TYPE_ID mtype)
00101 {
00102 INT i;
00103 INT64 pow2mask;
00104
00105 if (MTYPE_is_signed(mtype) && val < 0) val = -val;
00106
00107 if (mtype == MTYPE_U4) val &= 0xffffffffull;
00108
00109 pow2mask = 1;
00110 for ( i = 0; i < MTYPE_size_reg(mtype); ++i ) {
00111 if (val == pow2mask) return i;
00112 pow2mask <<= 1;
00113 }
00114
00115 FmtAssert(FALSE, ("Get_Power_Of_2 unexpected value"));
00116
00117 }
00118
00119
00120
00121
00122
00123 static void
00124 Expand_Power_Of_2_Divide (TN *result, TN *numer, INT64 dvsr, TYPE_ID mtype, OPS *ops)
00125 {
00126 INT n = Get_Power_Of_2(dvsr, mtype);
00127 TN *tmp_result;
00128
00129 if (MTYPE_is_unsigned(mtype)) {
00130 Expand_Shift(result, numer, Gen_Literal_TN(n, 4), mtype, shift_lright, ops);
00131 }
00132 else {
00133 #if 0
00134 if (TN_is_dedicated(result)) {
00135 tmp_result = Build_TN_Of_Mtype(mtype);
00136 }
00137 else
00138 tmp_result = result;
00139 #endif
00140
00141
00142 TN *t1 = Build_TN_Of_Mtype(mtype);
00143 TN *t2 = dvsr < 0 ? Build_TN_Of_Mtype(mtype) : result;
00144 INT64 absdvsr = dvsr < 0 ? -dvsr : dvsr;
00145 BOOL is_double = MTYPE_is_size_double(mtype);
00146
00147 TN* mask_tn = Build_TN_Of_Mtype (mtype);
00148 Expand_Shift(mask_tn, numer, Gen_Literal_TN(MTYPE_size_reg(mtype)-1, 4), mtype, shift_aright, ops);
00149
00150 TN* addend = Build_TN_Of_Mtype (mtype);
00151 TN* absdvsr_tn = Build_TN_Of_Mtype (mtype);
00152 Expand_Immediate(absdvsr_tn, Gen_Literal_TN(absdvsr-1, 8), TRUE, ops);
00153 Build_OP (TOP_and, addend, mask_tn, absdvsr_tn, ops);
00154 TN* temp = Build_TN_Like(result);
00155 Expand_Add (temp, numer, addend, mtype, ops);
00156
00157 Expand_Shift(t2, temp, Gen_Literal_TN(n, 4), mtype, shift_aright, ops);
00158
00159
00160 if (dvsr < 0) Expand_Neg(result, t2, mtype, ops);
00161
00162
00163 #if 0
00164 #if defined(TARG_SL)
00165
00166 Expand_Add (t1, Gen_Literal_TN(absdvsr-1, is_double ? 8 : 4),
00167 numer, mtype, ops);
00168 int unsignedflag = (mtype == MTYPE_U4) ? 1 : 0;
00169 Is_True((mtype == MTYPE_U4 || mtype==MTYPE_I4) ,
00170 (" Expand_Power_Of_2_Divide:: mtype must be MTYPE_I4 or MTYPE_U4" ));
00171 Exp_2inst_MC_Zero(TOP_mc_z_lt, tmp_result, t1, numer, numer, unsignedflag, ops);
00172 #else
00173 TN *p1 = Build_TN_Of_Mtype(MTYPE_I4);
00174 Build_OP(TOP_slt, p1, numer, Zero_TN, ops);
00175 Expand_Add (t1, Gen_Literal_TN(absdvsr-1, is_double ? 8 : 4),
00176 numer, mtype, ops);
00177 Build_OP(TOP_movz, t1, numer, p1, ops);
00178 Set_OP_cond_def_kind(OPS_last(ops), OP_ALWAYS_COND_DEF);
00179 #endif
00180 if (n > 31 && is_double)
00181 #ifdef TARG_SL
00182 Build_OP(TOP_dsra32, t2, tmp_result, Gen_Literal_TN(n-32, 4), ops);
00183 #else
00184 Build_OP(TOP_dsra32, t2, t1, Gen_Literal_TN(n-32, 4), ops);
00185 #endif
00186 else
00187 #ifdef TARG_SL
00188 Build_OP(is_double ? TOP_dsra : TOP_sra, t2, tmp_result, Gen_Literal_TN(n, 4), ops);
00189 if (dvsr < 0) Expand_Neg(tmp_result, t2, mtype, ops);
00190 if (tmp_result != result) {
00191 Expand_Copy(result, tmp_result, mtype, ops);
00192 }
00193 #else
00194 Build_OP(is_double ? TOP_dsra : TOP_sra, t2, t1, Gen_Literal_TN(n, 4), ops);
00195 if (dvsr < 0) Expand_Neg(result, t2, mtype, ops);
00196 #endif
00197 #endif
00198 }
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 static UINT64 determine_pseudo_inverse (
00251 UINT64 b,
00252 INT64 maxbits_a,
00253 INT64 *pn)
00254 {
00255 INT64 i, n;
00256 UINT64 m, q, b1;
00257
00258
00259
00260
00261
00262 b1 = b - 1;
00263 n = 1;
00264 m = 1;
00265 while(m < b1) {
00266 n++;
00267 m = (m<<1) | 1;
00268 }
00269 *pn = n;
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 for(q=i=0; i<=maxbits_a; i++) {
00283 q <<= 1;
00284 if(m >= b) {
00285 m -= b;
00286 q |= 1;
00287 }
00288 m = (m<<1) | 1;
00289 }
00290 return 1+q;
00291 }
00292
00293
00294
00295
00296
00297 static BOOL
00298 Expand_Integer_Divide_By_Constant(TN *result, TN *numer_tn, INT64 denom_val,
00299 TYPE_ID mtype, OPS *ops)
00300 {
00301 UINT64 b;
00302 UINT64 d;
00303 INT64 precision_required;
00304 INT64 n;
00305 BOOL is_odd;
00306 TN *d_tn;
00307 TN *mult_tn;
00308 TN *shift_tn;
00309 TOP opc;
00310 TN *p1;
00311 BOOL is_double = MTYPE_is_size_double(mtype);
00312 BOOL is_signed = MTYPE_is_signed(mtype);
00313
00314
00315
00316 if (denom_val == 1) {
00317 Exp_COPY(result, numer_tn, ops);
00318 return TRUE;
00319 } else if (is_signed && denom_val == -1) {
00320 Expand_Neg(result, numer_tn, mtype, ops);
00321 return TRUE;
00322 }
00323
00324
00325
00326 if (Is_Power_Of_2( denom_val, mtype)) {
00327 Expand_Power_Of_2_Divide(result, numer_tn, denom_val, mtype, ops);
00328 return TRUE;
00329 }
00330
00331 if (!CGEXP_cvrt_int_div_to_mult) return FALSE;
00332
00333 if (is_signed) {
00334
00335 b = denom_val<0 ? -denom_val : denom_val;
00336 is_odd = (b&1);
00337
00338 d = determine_pseudo_inverse (b, is_double ? 63 : 31, &n);
00339
00340 if (n > (is_double ? 63 : 31)) {
00341
00342 return FALSE;
00343 }
00344
00345 d_tn = Build_TN_Like (result);
00346 Expand_Immediate (d_tn, Gen_Literal_TN (d, 8), is_signed, ops);
00347
00348
00349
00350 TN *neg_tn = Build_TN_Of_Mtype (mtype);
00351 p1 = Build_TN_Like (result);
00352 if (is_double)
00353 Build_OP (TOP_dsubu, neg_tn, Zero_TN, numer_tn, ops);
00354 else
00355 Build_OP (TOP_subu, neg_tn, Zero_TN, numer_tn, ops);
00356 if (is_double)
00357 Build_OP (TOP_dsrl32, p1, numer_tn, Gen_Literal_TN(31, 4), ops);
00358 else
00359 Build_OP (TOP_srl, p1, numer_tn, Gen_Literal_TN(31, 4), ops);
00360 Build_OP (TOP_movz, neg_tn, numer_tn, p1, ops);
00361 Set_OP_cond_def_kind(OPS_last(ops), OP_ALWAYS_COND_DEF);
00362
00363
00364
00365 mult_tn = Build_TN_Of_Mtype (mtype);
00366 if (denom_val > 0) {
00367 Expand_High_Multiply (mult_tn, neg_tn, d_tn,
00368 is_double?MTYPE_U8:MTYPE_U4, ops);
00369
00370
00371
00372 if (n > 0) {
00373 shift_tn = Build_TN_Of_Mtype (mtype);
00374 if (is_double)
00375 Build_OP (((n - 1)>31)?TOP_dsra32:TOP_dsra,
00376 shift_tn, mult_tn, Gen_Literal_TN ((n-1)%32, 4), ops);
00377 else
00378 Build_OP (TOP_sra,
00379 shift_tn, mult_tn, Gen_Literal_TN ((n-1)%32, 4), ops);
00380 } else {
00381 shift_tn = mult_tn;
00382 }
00383
00384
00385
00386 if (is_double)
00387 Build_OP (TOP_dsubu, result, Zero_TN, shift_tn, ops);
00388 else
00389 Build_OP (TOP_subu, result, Zero_TN, shift_tn, ops);
00390 Build_OP (TOP_movz, result, shift_tn, p1, ops);
00391 Set_OP_cond_def_kind(OPS_last(ops), OP_ALWAYS_COND_DEF);
00392 } else {
00393 Expand_High_Multiply (result, neg_tn, d_tn,
00394 is_double?MTYPE_U8:MTYPE_U4, ops);
00395
00396
00397
00398 if (n > 0) {
00399 shift_tn = Build_TN_Of_Mtype (mtype);
00400 if (is_double)
00401 Build_OP (((n - 1)>31)?TOP_dsra32:TOP_dsra,
00402 result, result, Gen_Literal_TN ((n-1)%32, 4), ops);
00403 else
00404 Build_OP (TOP_sra,
00405 result, result, Gen_Literal_TN ((n-1)%32, 4), ops);
00406 }
00407
00408
00409
00410 if (is_double)
00411 Build_OP (TOP_dsubu, mult_tn, Zero_TN, result, ops);
00412 else
00413 Build_OP (TOP_subu, mult_tn, Zero_TN, result, ops);
00414 Build_OP (TOP_movz, result, mult_tn, p1, ops);
00415 Set_OP_cond_def_kind(OPS_last(ops), OP_ALWAYS_COND_DEF);
00416 }
00417 }
00418
00419 else {
00420
00421 b = denom_val;
00422 is_odd = (b&1);
00423
00424
00425
00426 if (is_odd) {
00427 precision_required = is_double?64:32;
00428 } else {
00429
00430
00431
00432
00433
00434 b >>= 1;
00435 precision_required = is_double?63:31;
00436
00437
00438
00439 TN *tmp1_tn = Build_TN_Of_Mtype (mtype);
00440 Build_OP (is_double?TOP_dsrl:TOP_srl, tmp1_tn, numer_tn, Gen_Literal_TN (1, 4), ops);
00441 numer_tn = tmp1_tn;
00442 }
00443
00444 d = determine_pseudo_inverse (b, precision_required, &n);
00445
00446 if (n > precision_required) {
00447
00448 return FALSE;
00449 }
00450
00451 d_tn = Build_TN_Like (result);
00452
00453 Expand_Immediate (d_tn, Gen_Literal_TN (d, 8), is_signed, ops);
00454
00455
00456
00457 mult_tn = Build_TN_Of_Mtype (mtype);
00458
00459 Expand_High_Multiply (mult_tn, numer_tn, d_tn,
00460 is_double?MTYPE_U8:MTYPE_U4, ops);
00461
00462 if (precision_required == 64 || precision_required == 32) {
00463
00464
00465
00466 TN *tmp1_tn = Build_TN_Of_Mtype (mtype);
00467 TN *tmp2_tn = Build_TN_Of_Mtype (mtype);
00468 TN *tmp3_tn = Build_TN_Of_Mtype (mtype);
00469 if (is_double) {
00470 Build_OP (TOP_dsubu, tmp1_tn, numer_tn, mult_tn, ops);
00471 Build_OP (TOP_dsrl, tmp2_tn, tmp1_tn, Gen_Literal_TN (1, 4), ops);
00472 Build_OP (TOP_daddu, tmp3_tn, mult_tn, tmp2_tn, ops);
00473 }
00474 else {
00475 Build_OP (TOP_subu, tmp1_tn, numer_tn, mult_tn, ops);
00476 Build_OP (TOP_srl, tmp2_tn, tmp1_tn, Gen_Literal_TN (1, 4), ops);
00477 Build_OP (TOP_addu, tmp3_tn, mult_tn, tmp2_tn, ops);
00478 }
00479 mult_tn = tmp3_tn;
00480 }
00481
00482
00483
00484 if (is_double)
00485 Build_OP (((n-1)>31)?TOP_dsrl32:TOP_dsrl,
00486 result, mult_tn, Gen_Literal_TN ((n-1)%32, 4), ops);
00487 else
00488 Build_OP (TOP_srl, result, mult_tn, Gen_Literal_TN ((n-1)%32, 4), ops);
00489 }
00490
00491 return TRUE;
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 static void
00512 Expand_Power_Of_2_Rem (TN *result, TN *src1, INT64 src2_val, TYPE_ID mtype, OPS *ops)
00513 {
00514 BOOL is_double = MTYPE_is_size_double(mtype);
00515 INT n = Get_Power_Of_2(src2_val, mtype);
00516 INT64 nMask = (1LL << n) - 1;
00517 TN *con = Gen_Literal_TN(nMask, is_double ? 8 : 4);
00518
00519 if (MTYPE_is_signed(mtype)) {
00520 TN *tmp1, *tmp2;
00521 TN *p1;
00522 TOP opc;
00523
00524 #if defined(TARG_SL)
00525
00526 tmp1 = Build_TN_Of_Mtype(mtype);
00527 Build_OP(TOP_mc_abs, tmp1, src1, ops);
00528 Set_OP_cond_def_kind(OPS_last(ops), OP_ALWAYS_UNC_DEF);
00529 #else
00530
00531
00532 p1 = Build_TN_Of_Mtype(MTYPE_I4);
00533 Build_OP(TOP_slt, p1, src1, Zero_TN, ops);
00534
00535
00536
00537 tmp1 = Build_TN_Of_Mtype(mtype);
00538 if (is_double)
00539 Build_OP(TOP_dsubu, tmp1, Zero_TN, src1, ops);
00540 else
00541 Build_OP(TOP_subu, tmp1, Zero_TN, src1, ops);
00542 Build_OP(TOP_movz, tmp1, src1, p1, ops);
00543 Set_OP_cond_def_kind(OPS_last(ops), OP_ALWAYS_COND_DEF);
00544 #endif
00545
00546
00547
00548 tmp2 = Build_TN_Of_Mtype(mtype);
00549 Expand_Binary_And(tmp2, tmp1, con, mtype, ops);
00550
00551
00552
00553 #if defined(TARG_SL)
00554
00555 int unsignedflag = (mtype == MTYPE_U4) ? 1 : 0;
00556 Is_True((mtype == MTYPE_U4 || mtype==MTYPE_I4) ,
00557 (" Expand_Power_Of_2_Rem:: mtype must be MTYPE_I4 or MTYPE_U4" ));
00558 Build_MC_OP(TOP_mc_zn_ge, result, src1, tmp2, unsignedflag, ops, OP_ALWAYS_UNC_DEF);
00559 #else
00560 if (is_double)
00561 Build_OP(TOP_dsubu, result, Zero_TN, tmp2, ops);
00562 else
00563 Build_OP(TOP_subu, result, Zero_TN, tmp2, ops);
00564 Build_OP(TOP_movz, result, tmp2, p1, ops);
00565 Set_OP_cond_def_kind(OPS_last(ops), OP_ALWAYS_COND_DEF);
00566 #endif
00567 } else {
00568 Expand_Binary_And(result, src1, con, mtype, ops);
00569 }
00570 }
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 static void
00588 Expand_Power_Of_2_Mod (TN *result, TN *src1, INT64 src2_val, TYPE_ID mtype, OPS *ops)
00589 {
00590 BOOL is_double = MTYPE_is_size_double(mtype);
00591 INT64 absval = src2_val < 0 ? -src2_val : src2_val;
00592 INT n = Get_Power_Of_2(absval, mtype);
00593 INT64 nMask = (1LL << n) - 1;
00594 TN *con = Gen_Literal_TN(nMask, is_double ? 8 : 4);
00595
00596 if (MTYPE_is_signed(mtype) && src2_val < 0) {
00597 TN *tmp1, *tmp2;
00598
00599 tmp1 = Build_TN_Of_Mtype(mtype);
00600 Expand_Neg(tmp1, src1, mtype, ops);
00601
00602 tmp2 = Build_TN_Of_Mtype(mtype);
00603 Expand_Binary_And(tmp2, tmp1, con, mtype, ops);
00604
00605 Expand_Neg(result, tmp2, mtype, ops);
00606 } else {
00607 Expand_Binary_And(result, src1, con, mtype, ops);
00608 }
00609 }
00610
00611
00612
00613
00614
00615
00616
00617 TN *
00618 Expand_Divide (TN *result, TN *src1, TN *src2, TYPE_ID mtype, OPS *ops)
00619 {
00620
00621
00622 INT64 src2_val;
00623 BOOL const_src2 = TN_Value_At_Op (src2, NULL, &src2_val);
00624 if (const_src2) {
00625 if (src2_val == 0)
00626 FmtAssert (FALSE, ("Division by zero detected.\n"));
00627 if (Expand_Integer_Divide_By_Constant(result, src1, src2_val, mtype, ops)) {
00628 return NULL;
00629 }
00630 }
00631
00632 if (MTYPE_signed(mtype) && !MTYPE_is_size_double(mtype)) {
00633
00634
00635
00636 TN *tmp = Build_TN_Of_Mtype (mtype);
00637 UINT success = 1;
00638 if (!CGEXP_cvrt_int_div_to_mult && const_src2 && TN_is_constant(src2)) {
00639 success = 0;
00640 tmp = Expand_Immediate_Into_Register (src2, mtype, ops);
00641 }
00642
00643 TN *t1 = Build_TN_Of_Mtype(MTYPE_F8);
00644 TN *t2 = Build_TN_Of_Mtype(MTYPE_F8);
00645 TN *t3 = Build_TN_Of_Mtype(MTYPE_F8);
00646 TN *t4 = Build_TN_Of_Mtype(MTYPE_F8);
00647 TN *t5 = Build_TN_Of_Mtype(MTYPE_F8);
00648 TN *t6 = Build_TN_Of_Mtype(MTYPE_F8);
00649 Build_OP(TOP_mtc1, t1, src1, ops);
00650 Build_OP(TOP_mtc1, t2, (success == 1)? src2: tmp, ops);
00651 Build_OP(TOP_cvt_d_w, t3, t1, ops);
00652 Build_OP(TOP_cvt_d_w, t4, t2, ops);
00653 Build_OP(TOP_div_d, t5, t3, t4, ops);
00654 Build_OP(TOP_trunc_w_d, t6, t5, ops);
00655 Build_OP(TOP_mfc1, result, t6, ops);
00656 Build_OP(TOP_teq, (success == 1)? src2: tmp,
00657 Zero_TN, Gen_Literal_TN(7, 4), ops);
00658 return NULL;
00659 }
00660
00661 TOP top;
00662 FmtAssert(!TN_is_constant(src1),("Expand_Divide: unexpected constant operand"));
00663 if (! MTYPE_is_size_double(mtype))
00664 top = MTYPE_signed(mtype) ? TOP_div : TOP_divu;
00665 else top = MTYPE_signed(mtype) ? TOP_ddiv : TOP_ddivu;
00666 if (TN_is_constant(src2))
00667 src2 = Expand_Immediate_Into_Register(src2, MTYPE_is_size_double(mtype), ops);
00668 Build_OP(top, Hilo_TN(), src1, src2, ops);
00669 #if !defined(TARG_SL)
00670 Build_OP(TOP_teq, src2, Zero_TN, Gen_Literal_TN(7, 4), ops);
00671 #else
00672 DevWarn("Handle Division by zero");
00673 #endif
00674 Build_OP(TOP_mflo, result, Hilo_TN(), ops);
00675 }
00676
00677
00678 void
00679 Expand_Rem (TN *result, TN *src1, TN *src2, TYPE_ID mtype, OPS *ops)
00680 {
00681 TOP top;
00682 BOOL is_double = MTYPE_is_size_double(mtype);
00683
00684
00685
00686 INT64 src2_val;
00687 BOOL const_src2 = TN_Value_At_Op (src2, NULL, &src2_val);
00688 if (const_src2) {
00689 #if 0
00690 if (src2_val == 0)
00691 FmtAssert (FALSE, ("Division by zero detected.\n"));
00692 #endif
00693
00694
00695
00696 if (Is_Power_Of_2(src2_val, mtype)) {
00697 Expand_Power_Of_2_Rem(result, src1, src2_val, mtype, ops);
00698 return;
00699 }
00700
00701 if (CGEXP_cvrt_int_div_to_mult) {
00702 TN *div_tn = Build_TN_Like (result);
00703
00704 if (Expand_Integer_Divide_By_Constant(div_tn, src1, src2_val, mtype, ops)) {
00705 TN *mult_tn;
00706
00707
00708
00709 mult_tn = Build_TN_Like (result);
00710 Expand_Multiply(mult_tn, div_tn, src2, mtype, ops);
00711
00712
00713
00714 if (is_double)
00715 Build_OP(TOP_dsubu, result, src1, mult_tn, ops);
00716 else
00717 Build_OP(TOP_subu, result, src1, mult_tn, ops);
00718 return;
00719 }
00720 }
00721 }
00722
00723 FmtAssert(!TN_is_constant(src1),("Expand_Rem: unexpected constant operand"));
00724 if (! MTYPE_is_size_double(mtype))
00725 top = MTYPE_signed(mtype) ? TOP_div : TOP_divu;
00726 else top = MTYPE_signed(mtype) ? TOP_ddiv : TOP_ddivu;
00727 if (TN_is_constant(src2))
00728 src2 = Expand_Immediate_Into_Register(src2, MTYPE_is_size_double(mtype), ops);
00729 Build_OP(top, Hilo_TN(), src1, src2, ops);
00730 #if !defined(TARG_SL)
00731 Build_OP(TOP_teq, src2, Zero_TN, Gen_Literal_TN(7, 4), ops);
00732 #else
00733 DevWarn("Handle Division by zero");
00734 #endif
00735 Build_OP(TOP_mfhi, result, Hilo_TN(), ops);
00736 }
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 void
00747 Expand_Mod (TN *result, TN *src1, TN *src2, TYPE_ID mtype, OPS *ops)
00748 {
00749 TN *tmp1;
00750 TN *tmp2;
00751 TN *tmp3;
00752 TN *p1;
00753 TOP opc;
00754 BOOL is_double = MTYPE_is_size_double(mtype);
00755
00756
00757
00758 INT64 src2_val;
00759 BOOL const_src2 = TN_Value_At_Op (src2, NULL, &src2_val);
00760 if (const_src2 && Is_Power_Of_2(src2_val, mtype)) {
00761 Expand_Power_Of_2_Mod (result, src1, src2_val, mtype, ops);
00762 return;
00763 }
00764
00765 if (const_src2)
00766 if (src2_val == 0)
00767 FmtAssert (FALSE, ("Division by zero detected.\n"));
00768
00769
00770
00771 tmp1 = Build_TN_Like(result);
00772 Expand_Rem(tmp1, src1, src2, mtype, ops);
00773
00774
00775
00776 tmp2 = Build_TN_Like(result);
00777 Build_OP(TOP_xor, tmp2, tmp1, src2, ops);
00778
00779 p1 = Gen_Typed_Register_TN(MTYPE_I4, 4);
00780 Build_OP(TOP_slt, p1, tmp2, Zero_TN, ops);
00781
00782
00783
00784
00785 tmp3 = Build_TN_Like(result);
00786 Build_OP(TOP_movn, tmp3, src2, p1, ops);
00787 Set_OP_cond_def_kind(OPS_last(ops), OP_ALWAYS_COND_DEF);
00788 Build_OP(TOP_movz, tmp3, Zero_TN, p1, ops);
00789 Set_OP_cond_def_kind(OPS_last(ops), OP_ALWAYS_COND_DEF);
00790 if (is_double)
00791 Build_OP(TOP_daddu, result, tmp1, tmp3, ops);
00792 else
00793 Build_OP(TOP_addu, result, tmp1, tmp3, ops);
00794 }
00795
00796
00797 void
00798 Expand_DivRem(TN *result, TN *result2, TN *src1, TN *src2, TYPE_ID mtype, OPS *ops)
00799 {
00800 BOOL is_double = MTYPE_is_size_double(mtype);
00801
00802
00803
00804
00805
00806
00807
00808 INT64 src1_val;
00809 BOOL const_src1 = TN_Value_At_Op (src1, NULL, &src1_val);
00810 INT64 src2_val;
00811 BOOL const_src2 = TN_Value_At_Op (src2, NULL, &src2_val);
00812
00813 if (const_src2)
00814 if (src2_val == 0)
00815 FmtAssert (FALSE, ("Division by zero detected.\n"));
00816 if (const_src1 && const_src2) {
00817 if (MTYPE_is_signed(mtype)) {
00818 const INT64 minintval = is_double ? INT64_MIN : INT32_MIN;
00819 if (src1_val == minintval && src2_val == -1)
00820 FmtAssert (FALSE, ("Division overflow detected.\n"));
00821 }
00822 INT64 quot_val, rem_val;
00823 switch (mtype) {
00824 case MTYPE_I8:
00825 quot_val = (INT64)src1_val / (INT64)src2_val;
00826 rem_val = (INT64)src1_val % (INT64)src2_val;
00827 break;
00828 case MTYPE_U8:
00829 quot_val = (UINT64)src1_val / (UINT64)src2_val;
00830 rem_val = (UINT64)src1_val % (UINT64)src2_val;
00831 break;
00832 case MTYPE_U4:
00833 quot_val = (UINT32)src1_val / (UINT32)src2_val;
00834 rem_val = (UINT32)src1_val % (UINT32)src2_val;
00835 break;
00836 case MTYPE_I4:
00837 quot_val = (INT32)src1_val / (INT32)src2_val;
00838 rem_val = (INT32)src1_val % (INT32)src2_val;
00839 break;
00840 }
00841 BOOL is_signed = MTYPE_is_signed(mtype);
00842 INT tn_size = MTYPE_is_size_double(mtype) ? 8 : 4;
00843 Exp_Immediate(result, Gen_Literal_TN(quot_val, tn_size), is_signed, ops);
00844 Exp_Immediate(result2, Gen_Literal_TN(rem_val, tn_size), is_signed, ops);
00845 return;
00846 }
00847
00848
00849
00850 if (const_src2) {
00851 if (Expand_Integer_Divide_By_Constant(result, src1, src2_val, mtype, ops)) {
00852
00853
00854
00855
00856
00857 if (!MTYPE_is_signed(mtype) && Is_Power_Of_2(src2_val, mtype)) {
00858 Expand_Power_Of_2_Rem(result2, src1, src2_val, mtype, ops);
00859 } else {
00860 TN *t1 = Build_TN_Like(result);
00861 Expand_Multiply(t1, result, src2, mtype, ops);
00862 if (is_double)
00863 Build_OP(TOP_dsubu, result2, src1, t1, ops);
00864 else
00865 Build_OP(TOP_subu, result2, src1, t1, ops);
00866 }
00867 return;
00868 }
00869 }
00870
00871 TOP top;
00872 if (! MTYPE_is_size_double(mtype))
00873 top = MTYPE_signed(mtype) ? TOP_div : TOP_divu;
00874 else top = MTYPE_signed(mtype) ? TOP_ddiv : TOP_ddivu;
00875 if (TN_is_constant(src2))
00876 src2 = Expand_Immediate_Into_Register(src2, MTYPE_is_size_double(mtype), ops);
00877 Build_OP(top, Hilo_TN(), src1, src2, ops);
00878 #if !defined(TARG_SL)
00879 Build_OP(TOP_teq, src2, Zero_TN, Gen_Literal_TN(7, 4), ops);
00880 #else
00881 DevWarn("Handle Division by zero");
00882 #endif
00883 Build_OP(TOP_mflo, result, Hilo_TN(), ops);
00884 Build_OP(TOP_mfhi, result2, Hilo_TN(), ops);
00885 }