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