Unified · Split
| @@ -1394,33 +1394,38 @@ static void gen_opl(int op) · 1393 unmodified lines | ||
| 1394 | 1394 | } |
| 1395 | 1395 | #endif |
| 1396 | 1396 | |
| 1397 | +static uint64_t gen_opic_sdiv(uint64_t a, uint64_t b) | |
| 1398 | +{ | |
| 1399 | + uint64_t x = (a >> 63 ? -a : a) / (b >> 63 ? -b : b); | |
| 1400 | + return (a ^ b) >> 63 ? -x : x; | |
| 1401 | +} | |
| 1402 | + | |
| 1403 | +static int gen_opic_lt(uint64_t a, uint64_t b) | |
| 1404 | +{ | |
| 1405 | + return (a ^ (uint64_t)1 << 63) < (b ^ (uint64_t)1 << 63); | |
| 1406 | +} | |
| 1407 | + | |
| 1397 | 1408 | /* handle integer constant optimizations and various machine |
| 1398 | 1409 | independent opt */ |
| 1399 | 1410 | static void gen_opic(int op) |
| 1400 | 1411 | { |
| 1401 | − int c1, c2, t1, t2, n; | |
| 1402 | − SValue *v1, *v2; | |
| 1403 | − long long l1, l2; | |
| 1404 | − typedef unsigned long long U; | |
| 1412 | + SValue *v1 = vtop - 1; | |
| 1413 | + SValue *v2 = vtop; | |
| 1414 | + int t1 = v1->type.t & VT_BTYPE; | |
| 1415 | + int t2 = v2->type.t & VT_BTYPE; | |
| 1416 | + int c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; | |
| 1417 | + int c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; | |
| 1418 | + uint64_t l1 = c1 ? v1->c.i : 0; | |
| 1419 | + uint64_t l2 = c2 ? v2->c.i : 0; | |
| 1420 | + int shm = (t1 == VT_LLONG) ? 63 : 31; | |
| 1405 | 1421 | |
| 1406 | − v1 = vtop - 1; | |
| 1407 | − v2 = vtop; | |
| 1408 | − t1 = v1->type.t & VT_BTYPE; | |
| 1409 | − t2 = v2->type.t & VT_BTYPE; | |
| 1410 | − | |
| 1411 | − l1 = v1->c.i; | |
| 1412 | 1422 | if (t1 != VT_LLONG) |
| 1413 | 1423 | l1 = ((uint32_t)l1 | |
| 1414 | 1424 | (v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000))); |
| 1415 | − | |
| 1416 | − l2 = v2->c.i; | |
| 1417 | 1425 | if (t2 != VT_LLONG) |
| 1418 | 1426 | l2 = ((uint32_t)l2 | |
| 1419 | 1427 | (v2->type.t & VT_UNSIGNED ? 0 : -(l2 & 0x80000000))); |
| 1420 | 1428 | |
| 1421 | − /* currently, we cannot do computations with forward symbols */ | |
| 1422 | − c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; | |
| 1423 | − c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; | |
| 1424 | 1429 | if (c1 && c2) { |
| 1425 | 1430 | switch(op) { |
| 1426 | 1431 | case '+': l1 += l2; break; |
| @@ -1442,26 +1447,28 @@ static void gen_opic(int op) · 15 unmodified lines | ||
| 1442 | 1447 | goto general_case; |
| 1443 | 1448 | } |
| 1444 | 1449 | switch(op) { |
| 1445 | − default: l1 /= l2; break; | |
| 1446 | − case '%': l1 %= l2; break; | |
| 1447 | − case TOK_UDIV: l1 = (U)l1 / l2; break; | |
| 1448 | − case TOK_UMOD: l1 = (U)l1 % l2; break; | |
| 1450 | + default: l1 = gen_opic_sdiv(l1, l2); break; | |
| 1451 | + case '%': l1 = l1 - l2 * gen_opic_sdiv(l1, l2); break; | |
| 1452 | + case TOK_UDIV: l1 = l1 / l2; break; | |
| 1453 | + case TOK_UMOD: l1 = l1 % l2; break; | |
| 1449 | 1454 | } |
| 1450 | 1455 | break; |
| 1451 | − case TOK_SHL: l1 <<= l2; break; | |
| 1452 | − case TOK_SHR: l1 = (U)l1 >> l2; break; | |
| 1453 | − case TOK_SAR: l1 >>= l2; break; | |
| 1456 | + case TOK_SHL: l1 <<= (l2 & shm); break; | |
| 1457 | + case TOK_SHR: l1 >>= (l2 & shm); break; | |
| 1458 | + case TOK_SAR: | |
| 1459 | + l1 = (l1 >> 63) ? ~(~l1 >> (l2 & shm)) : l1 >> (l2 & shm); | |
| 1460 | + break; | |
| 1454 | 1461 | /* tests */ |
| 1455 | − case TOK_ULT: l1 = (U)l1 < (U)l2; break; | |
| 1456 | − case TOK_UGE: l1 = (U)l1 >= (U)l2; break; | |
| 1462 | + case TOK_ULT: l1 = l1 < l2; break; | |
| 1463 | + case TOK_UGE: l1 = l1 >= l2; break; | |
| 1457 | 1464 | case TOK_EQ: l1 = l1 == l2; break; |
| 1458 | 1465 | case TOK_NE: l1 = l1 != l2; break; |
| 1459 | − case TOK_ULE: l1 = (U)l1 <= (U)l2; break; | |
| 1460 | − case TOK_UGT: l1 = (U)l1 > (U)l2; break; | |
| 1461 | − case TOK_LT: l1 = l1 < l2; break; | |
| 1462 | − case TOK_GE: l1 = l1 >= l2; break; | |
| 1463 | − case TOK_LE: l1 = l1 <= l2; break; | |
| 1464 | − case TOK_GT: l1 = l1 > l2; break; | |
| 1466 | + case TOK_ULE: l1 = l1 <= l2; break; | |
| 1467 | + case TOK_UGT: l1 = l1 > l2; break; | |
| 1468 | + case TOK_LT: l1 = gen_opic_lt(l1, l2); break; | |
| 1469 | + case TOK_GE: l1 = !gen_opic_lt(l1, l2); break; | |
| 1470 | + case TOK_LE: l1 = !gen_opic_lt(l2, l1); break; | |
| 1471 | + case TOK_GT: l1 = gen_opic_lt(l2, l1); break; | |
| 1465 | 1472 | /* logical */ |
| 1466 | 1473 | case TOK_LAND: l1 = l1 && l2; break; |
| 1467 | 1474 | case TOK_LOR: l1 = l1 || l2; break; |
| @@ -1507,7 +1514,7 @@ static void gen_opic(int op) · 39 unmodified lines | ||
| 1507 | 1514 | } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) { |
| 1508 | 1515 | /* try to use shifts instead of muls or divs */ |
| 1509 | 1516 | if (l2 > 0 && (l2 & (l2 - 1)) == 0) { |
| 1510 | − n = -1; | |
| 1517 | + int n = -1; | |
| 1511 | 1518 | while (l2) { |
| 1512 | 1519 | l2 >>= 1; |
| 1513 | 1520 | n++; |