Commit 507563e85db880ff875f0a9498a1cf58a50cfad3
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: | ... | ... |