Commit 507563e85db880ff875f0a9498a1cf58a50cfad3

Authored by aurel32
1 parent 49bcf33c

target-mips: optimize gen_arith()/gen_arith_imm()

Optimize code generation in gen_arith()/gen_arith_imm():
- Don't do sign extension when the value is already guaranteed to be
  sign extended (otherwise, results are marked as UNPREDICTABLE).
- When the value is sign extended, compare the value to 0 instead of
  testing bit 31/63.
- Temp variables are valid up to and *including* the brcond instruction.
  Use them instead of temp local variables.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5680 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 32 additions and 46 deletions
target-mips/translate.c
... ... @@ -1333,7 +1333,7 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1333 1333 switch (opc) {
1334 1334 case OPC_ADDI:
1335 1335 {
1336   - TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
  1336 + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1337 1337 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1338 1338 int l1 = gen_new_label();
1339 1339  
... ... @@ -1341,24 +1341,21 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1341 1341 tcg_gen_ext32s_tl(r_tmp1, t0);
1342 1342 tcg_gen_addi_tl(t0, r_tmp1, uimm);
1343 1343  
1344   - tcg_gen_xori_tl(r_tmp1, r_tmp1, uimm);
1345   - tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
  1344 + tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
1346 1345 tcg_gen_xori_tl(r_tmp2, t0, uimm);
1347 1346 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1348 1347 tcg_temp_free(r_tmp2);
1349   - tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
1350   - tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1351   - tcg_temp_free(r_tmp1);
  1348 + tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1352 1349 /* operands of same sign, result different sign */
1353 1350 generate_exception(ctx, EXCP_OVERFLOW);
1354 1351 gen_set_label(l1);
  1352 + tcg_temp_free(r_tmp1);
1355 1353  
1356 1354 tcg_gen_ext32s_tl(t0, t0);
1357 1355 }
1358 1356 opn = "addi";
1359 1357 break;
1360 1358 case OPC_ADDIU:
1361   - tcg_gen_ext32s_tl(t0, t0);
1362 1359 tcg_gen_addi_tl(t0, t0, uimm);
1363 1360 tcg_gen_ext32s_tl(t0, t0);
1364 1361 opn = "addiu";
... ... @@ -1366,7 +1363,7 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1366 1363 #if defined(TARGET_MIPS64)
1367 1364 case OPC_DADDI:
1368 1365 {
1369   - TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
  1366 + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1370 1367 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1371 1368 int l1 = gen_new_label();
1372 1369  
... ... @@ -1374,17 +1371,15 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1374 1371 tcg_gen_mov_tl(r_tmp1, t0);
1375 1372 tcg_gen_addi_tl(t0, t0, uimm);
1376 1373  
1377   - tcg_gen_xori_tl(r_tmp1, r_tmp1, uimm);
1378   - tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
  1374 + tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
1379 1375 tcg_gen_xori_tl(r_tmp2, t0, uimm);
1380 1376 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1381 1377 tcg_temp_free(r_tmp2);
1382   - tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
1383   - tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1384   - tcg_temp_free(r_tmp1);
  1378 + tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1385 1379 /* operands of same sign, result different sign */
1386 1380 generate_exception(ctx, EXCP_OVERFLOW);
1387 1381 gen_set_label(l1);
  1382 + tcg_temp_free(r_tmp1);
1388 1383 }
1389 1384 opn = "daddi";
1390 1385 break;
... ... @@ -1417,7 +1412,6 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1417 1412 opn = "lui";
1418 1413 break;
1419 1414 case OPC_SLL:
1420   - tcg_gen_ext32u_tl(t0, t0);
1421 1415 tcg_gen_shli_tl(t0, t0, uimm);
1422 1416 tcg_gen_ext32s_tl(t0, t0);
1423 1417 opn = "sll";
... ... @@ -1425,15 +1419,17 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1425 1419 case OPC_SRA:
1426 1420 tcg_gen_ext32s_tl(t0, t0);
1427 1421 tcg_gen_sari_tl(t0, t0, uimm);
1428   - tcg_gen_ext32s_tl(t0, t0);
1429 1422 opn = "sra";
1430 1423 break;
1431 1424 case OPC_SRL:
1432 1425 switch ((ctx->opcode >> 21) & 0x1f) {
1433 1426 case 0:
1434   - tcg_gen_ext32u_tl(t0, t0);
1435   - tcg_gen_shri_tl(t0, t0, uimm);
1436   - tcg_gen_ext32s_tl(t0, t0);
  1427 + if (uimm != 0) {
  1428 + tcg_gen_ext32u_tl(t0, t0);
  1429 + tcg_gen_shri_tl(t0, t0, uimm);
  1430 + } else {
  1431 + tcg_gen_ext32s_tl(t0, t0);
  1432 + }
1437 1433 opn = "srl";
1438 1434 break;
1439 1435 case 1:
... ... @@ -1449,9 +1445,12 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1449 1445 }
1450 1446 opn = "rotr";
1451 1447 } else {
1452   - tcg_gen_ext32u_tl(t0, t0);
1453   - tcg_gen_shri_tl(t0, t0, uimm);
1454   - tcg_gen_ext32s_tl(t0, t0);
  1448 + if (uimm != 0) {
  1449 + tcg_gen_ext32u_tl(t0, t0);
  1450 + tcg_gen_shri_tl(t0, t0, uimm);
  1451 + } else {
  1452 + tcg_gen_ext32s_tl(t0, t0);
  1453 + }
1455 1454 opn = "srl";
1456 1455 }
1457 1456 break;
... ... @@ -1562,7 +1561,7 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1562 1561 switch (opc) {
1563 1562 case OPC_ADD:
1564 1563 {
1565   - TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
  1564 + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1566 1565 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1567 1566 int l1 = gen_new_label();
1568 1567  
... ... @@ -1576,27 +1575,24 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1576 1575 tcg_gen_xor_tl(r_tmp2, t0, t1);
1577 1576 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1578 1577 tcg_temp_free(r_tmp2);
1579   - tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
1580   - tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1581   - tcg_temp_free(r_tmp1);
  1578 + tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1582 1579 /* operands of same sign, result different sign */
1583 1580 generate_exception(ctx, EXCP_OVERFLOW);
1584 1581 gen_set_label(l1);
  1582 + tcg_temp_free(r_tmp1);
1585 1583  
1586 1584 tcg_gen_ext32s_tl(t0, t0);
1587 1585 }
1588 1586 opn = "add";
1589 1587 break;
1590 1588 case OPC_ADDU:
1591   - tcg_gen_ext32s_tl(t0, t0);
1592   - tcg_gen_ext32s_tl(t1, t1);
1593 1589 tcg_gen_add_tl(t0, t0, t1);
1594 1590 tcg_gen_ext32s_tl(t0, t0);
1595 1591 opn = "addu";
1596 1592 break;
1597 1593 case OPC_SUB:
1598 1594 {
1599   - TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
  1595 + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1600 1596 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1601 1597 int l1 = gen_new_label();
1602 1598  
... ... @@ -1609,20 +1605,17 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1609 1605 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1610 1606 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1611 1607 tcg_temp_free(r_tmp2);
1612   - tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
1613   - tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1614   - tcg_temp_free(r_tmp1);
  1608 + tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1615 1609 /* operands of different sign, first operand and result different sign */
1616 1610 generate_exception(ctx, EXCP_OVERFLOW);
1617 1611 gen_set_label(l1);
  1612 + tcg_temp_free(r_tmp1);
1618 1613  
1619 1614 tcg_gen_ext32s_tl(t0, t0);
1620 1615 }
1621 1616 opn = "sub";
1622 1617 break;
1623 1618 case OPC_SUBU:
1624   - tcg_gen_ext32s_tl(t0, t0);
1625   - tcg_gen_ext32s_tl(t1, t1);
1626 1619 tcg_gen_sub_tl(t0, t0, t1);
1627 1620 tcg_gen_ext32s_tl(t0, t0);
1628 1621 opn = "subu";
... ... @@ -1630,7 +1623,7 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1630 1623 #if defined(TARGET_MIPS64)
1631 1624 case OPC_DADD:
1632 1625 {
1633   - TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
  1626 + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1634 1627 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1635 1628 int l1 = gen_new_label();
1636 1629  
... ... @@ -1643,12 +1636,11 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1643 1636 tcg_gen_xor_tl(r_tmp2, t0, t1);
1644 1637 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1645 1638 tcg_temp_free(r_tmp2);
1646   - tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
1647   - tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1648   - tcg_temp_free(r_tmp1);
  1639 + tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1649 1640 /* operands of same sign, result different sign */
1650 1641 generate_exception(ctx, EXCP_OVERFLOW);
1651 1642 gen_set_label(l1);
  1643 + tcg_temp_free(r_tmp1);
1652 1644 }
1653 1645 opn = "dadd";
1654 1646 break;
... ... @@ -1658,7 +1650,7 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1658 1650 break;
1659 1651 case OPC_DSUB:
1660 1652 {
1661   - TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
  1653 + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1662 1654 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1663 1655 int l1 = gen_new_label();
1664 1656  
... ... @@ -1670,12 +1662,11 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1670 1662 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1671 1663 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1672 1664 tcg_temp_free(r_tmp2);
1673   - tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
1674   - tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1675   - tcg_temp_free(r_tmp1);
  1665 + tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1676 1666 /* operands of different sign, first operand and result different sign */
1677 1667 generate_exception(ctx, EXCP_OVERFLOW);
1678 1668 gen_set_label(l1);
  1669 + tcg_temp_free(r_tmp1);
1679 1670 }
1680 1671 opn = "dsub";
1681 1672 break;
... ... @@ -1710,8 +1701,6 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1710 1701 opn = "xor";
1711 1702 break;
1712 1703 case OPC_MUL:
1713   - tcg_gen_ext32s_tl(t0, t0);
1714   - tcg_gen_ext32s_tl(t1, t1);
1715 1704 tcg_gen_mul_tl(t0, t0, t1);
1716 1705 tcg_gen_ext32s_tl(t0, t0);
1717 1706 opn = "mul";
... ... @@ -1737,8 +1726,6 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1737 1726 opn = "movz";
1738 1727 goto print;
1739 1728 case OPC_SLLV:
1740   - tcg_gen_ext32u_tl(t0, t0);
1741   - tcg_gen_ext32u_tl(t1, t1);
1742 1729 tcg_gen_andi_tl(t0, t0, 0x1f);
1743 1730 tcg_gen_shl_tl(t0, t1, t0);
1744 1731 tcg_gen_ext32s_tl(t0, t0);
... ... @@ -1748,7 +1735,6 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1748 1735 tcg_gen_ext32s_tl(t1, t1);
1749 1736 tcg_gen_andi_tl(t0, t0, 0x1f);
1750 1737 tcg_gen_sar_tl(t0, t1, t0);
1751   - tcg_gen_ext32s_tl(t0, t0);
1752 1738 opn = "srav";
1753 1739 break;
1754 1740 case OPC_SRLV:
... ...