Commit 460f00c4e1f43cf610633e31ad4988c9ddcc415f

Authored by aurel32
1 parent 35fbce2c

target-mips: optimize gen_arith()

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

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7043 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 290 additions and 158 deletions
target-mips/translate.c
... ... @@ -1452,200 +1452,338 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1452 1452 int rd, int rs, int rt)
1453 1453 {
1454 1454 const char *opn = "arith";
1455   - TCGv t0 = tcg_temp_local_new();
1456   - TCGv t1 = tcg_temp_local_new();
1457 1455  
1458 1456 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1459 1457 && opc != OPC_DADD && opc != OPC_DSUB) {
1460 1458 /* If no destination, treat it as a NOP.
1461 1459 For add & sub, we must generate the overflow exception when needed. */
1462 1460 MIPS_DEBUG("NOP");
1463   - goto out;
1464   - }
1465   - gen_load_gpr(t0, rs);
1466   - /* Specialcase the conventional move operation. */
1467   - if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
1468   - || opc == OPC_SUBU || opc == OPC_DSUBU)) {
1469   - gen_store_gpr(t0, rd);
1470   - goto out;
  1461 + return;
1471 1462 }
1472   - gen_load_gpr(t1, rt);
  1463 +
1473 1464 switch (opc) {
1474 1465 case OPC_ADD:
1475 1466 {
1476   - TCGv r_tmp1 = tcg_temp_new();
1477   - TCGv r_tmp2 = tcg_temp_new();
  1467 + TCGv t0 = tcg_temp_local_new();
  1468 + TCGv t1 = tcg_temp_new();
  1469 + TCGv t2 = tcg_temp_new();
1478 1470 int l1 = gen_new_label();
1479 1471  
1480   - save_cpu_state(ctx, 1);
1481   - tcg_gen_ext32s_tl(r_tmp1, t0);
1482   - tcg_gen_ext32s_tl(r_tmp2, t1);
1483   - tcg_gen_add_tl(t0, r_tmp1, r_tmp2);
1484   -
1485   - tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
1486   - tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1487   - tcg_gen_xor_tl(r_tmp2, t0, t1);
1488   - tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1489   - tcg_temp_free(r_tmp2);
1490   - tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
  1472 + gen_load_gpr(t1, rs);
  1473 + gen_load_gpr(t2, rt);
  1474 + tcg_gen_add_tl(t0, t1, t2);
  1475 + tcg_gen_ext32s_tl(t0, t0);
  1476 + tcg_gen_xor_tl(t1, t1, t2);
  1477 + tcg_gen_not_tl(t1, t1);
  1478 + tcg_gen_xor_tl(t2, t0, t2);
  1479 + tcg_gen_and_tl(t1, t1, t2);
  1480 + tcg_temp_free(t2);
  1481 + tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
  1482 + tcg_temp_free(t1);
1491 1483 /* operands of same sign, result different sign */
1492 1484 generate_exception(ctx, EXCP_OVERFLOW);
1493 1485 gen_set_label(l1);
1494   - tcg_temp_free(r_tmp1);
1495   -
1496   - tcg_gen_ext32s_tl(t0, t0);
  1486 + gen_store_gpr(t0, rd);
  1487 + tcg_temp_free(t0);
1497 1488 }
1498 1489 opn = "add";
1499 1490 break;
1500 1491 case OPC_ADDU:
1501   - tcg_gen_add_tl(t0, t0, t1);
1502   - tcg_gen_ext32s_tl(t0, t0);
  1492 + if (rs != 0 && rt != 0) {
  1493 + tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
  1494 + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
  1495 + } else if (rs == 0 && rt != 0) {
  1496 + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
  1497 + } else if (rs != 0 && rt == 0) {
  1498 + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
  1499 + } else {
  1500 + tcg_gen_movi_tl(cpu_gpr[rd], 0);
  1501 + }
1503 1502 opn = "addu";
1504 1503 break;
1505 1504 case OPC_SUB:
1506 1505 {
1507   - TCGv r_tmp1 = tcg_temp_new();
1508   - TCGv r_tmp2 = tcg_temp_new();
  1506 + TCGv t0 = tcg_temp_local_new();
  1507 + TCGv t1 = tcg_temp_new();
  1508 + TCGv t2 = tcg_temp_new();
1509 1509 int l1 = gen_new_label();
1510 1510  
1511   - save_cpu_state(ctx, 1);
1512   - tcg_gen_ext32s_tl(r_tmp1, t0);
1513   - tcg_gen_ext32s_tl(r_tmp2, t1);
1514   - tcg_gen_sub_tl(t0, r_tmp1, r_tmp2);
1515   -
1516   - tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1517   - tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1518   - tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1519   - tcg_temp_free(r_tmp2);
1520   - tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1521   - /* operands of different sign, first operand and result different sign */
  1511 + gen_load_gpr(t1, rs);
  1512 + gen_load_gpr(t2, rt);
  1513 + tcg_gen_sub_tl(t0, t1, t2);
  1514 + tcg_gen_ext32s_tl(t0, t0);
  1515 + tcg_gen_xor_tl(t2, t1, t2);
  1516 + tcg_gen_xor_tl(t1, t0, t1);
  1517 + tcg_gen_and_tl(t1, t1, t2);
  1518 + tcg_temp_free(t2);
  1519 + tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
  1520 + tcg_temp_free(t1);
  1521 + /* operands of same sign, result different sign */
1522 1522 generate_exception(ctx, EXCP_OVERFLOW);
1523 1523 gen_set_label(l1);
1524   - tcg_temp_free(r_tmp1);
1525   -
1526   - tcg_gen_ext32s_tl(t0, t0);
  1524 + gen_store_gpr(t0, rd);
  1525 + tcg_temp_free(t0);
1527 1526 }
1528 1527 opn = "sub";
1529 1528 break;
1530 1529 case OPC_SUBU:
1531   - tcg_gen_sub_tl(t0, t0, t1);
1532   - tcg_gen_ext32s_tl(t0, t0);
  1530 + if (rs != 0 && rt != 0) {
  1531 + tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
  1532 + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
  1533 + } else if (rs == 0 && rt != 0) {
  1534 + tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
  1535 + } else if (rs != 0 && rt == 0) {
  1536 + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
  1537 + } else {
  1538 + tcg_gen_movi_tl(cpu_gpr[rd], 0);
  1539 + }
1533 1540 opn = "subu";
1534 1541 break;
1535 1542 #if defined(TARGET_MIPS64)
1536 1543 case OPC_DADD:
1537 1544 {
1538   - TCGv r_tmp1 = tcg_temp_new();
1539   - TCGv r_tmp2 = tcg_temp_new();
  1545 + TCGv t0 = tcg_temp_local_new();
  1546 + TCGv t1 = tcg_temp_new();
  1547 + TCGv t2 = tcg_temp_new();
1540 1548 int l1 = gen_new_label();
1541 1549  
1542   - save_cpu_state(ctx, 1);
1543   - tcg_gen_mov_tl(r_tmp1, t0);
1544   - tcg_gen_add_tl(t0, t0, t1);
1545   -
1546   - tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
1547   - tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1548   - tcg_gen_xor_tl(r_tmp2, t0, t1);
1549   - tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1550   - tcg_temp_free(r_tmp2);
1551   - tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
  1550 + gen_load_gpr(t1, rs);
  1551 + gen_load_gpr(t2, rt);
  1552 + tcg_gen_add_tl(t0, t1, t2);
  1553 + tcg_gen_xor_tl(t1, t1, t2);
  1554 + tcg_gen_not_tl(t1, t1);
  1555 + tcg_gen_xor_tl(t2, t0, t2);
  1556 + tcg_gen_and_tl(t1, t1, t2);
  1557 + tcg_temp_free(t2);
  1558 + tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
  1559 + tcg_temp_free(t1);
1552 1560 /* operands of same sign, result different sign */
1553 1561 generate_exception(ctx, EXCP_OVERFLOW);
1554 1562 gen_set_label(l1);
1555   - tcg_temp_free(r_tmp1);
  1563 + gen_store_gpr(t0, rd);
  1564 + tcg_temp_free(t0);
1556 1565 }
1557 1566 opn = "dadd";
1558 1567 break;
1559 1568 case OPC_DADDU:
1560   - tcg_gen_add_tl(t0, t0, t1);
  1569 + if (rs != 0 && rt != 0) {
  1570 + tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
  1571 + } else if (rs == 0 && rt != 0) {
  1572 + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
  1573 + } else if (rs != 0 && rt == 0) {
  1574 + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
  1575 + } else {
  1576 + tcg_gen_movi_tl(cpu_gpr[rd], 0);
  1577 + }
1561 1578 opn = "daddu";
1562 1579 break;
1563 1580 case OPC_DSUB:
1564 1581 {
1565   - TCGv r_tmp1 = tcg_temp_new();
1566   - TCGv r_tmp2 = tcg_temp_new();
  1582 + TCGv t0 = tcg_temp_local_new();
  1583 + TCGv t1 = tcg_temp_new();
  1584 + TCGv t2 = tcg_temp_new();
1567 1585 int l1 = gen_new_label();
1568 1586  
1569   - save_cpu_state(ctx, 1);
1570   - tcg_gen_mov_tl(r_tmp1, t0);
1571   - tcg_gen_sub_tl(t0, t0, t1);
1572   -
1573   - tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1574   - tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1575   - tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1576   - tcg_temp_free(r_tmp2);
1577   - tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1578   - /* operands of different sign, first operand and result different sign */
  1587 + gen_load_gpr(t1, rs);
  1588 + gen_load_gpr(t2, rt);
  1589 + tcg_gen_sub_tl(t0, t1, t2);
  1590 + tcg_gen_xor_tl(t2, t1, t2);
  1591 + tcg_gen_xor_tl(t1, t0, t1);
  1592 + tcg_gen_and_tl(t1, t1, t2);
  1593 + tcg_temp_free(t2);
  1594 + tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
  1595 + tcg_temp_free(t1);
  1596 + /* operands of same sign, result different sign */
1579 1597 generate_exception(ctx, EXCP_OVERFLOW);
1580 1598 gen_set_label(l1);
1581   - tcg_temp_free(r_tmp1);
  1599 + gen_store_gpr(t0, rd);
  1600 + tcg_temp_free(t0);
1582 1601 }
1583 1602 opn = "dsub";
1584 1603 break;
1585 1604 case OPC_DSUBU:
1586   - tcg_gen_sub_tl(t0, t0, t1);
  1605 + if (rs != 0 && rt != 0) {
  1606 + tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
  1607 + } else if (rs == 0 && rt != 0) {
  1608 + tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
  1609 + } else if (rs != 0 && rt == 0) {
  1610 + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
  1611 + } else {
  1612 + tcg_gen_movi_tl(cpu_gpr[rd], 0);
  1613 + }
1587 1614 opn = "dsubu";
1588 1615 break;
1589 1616 #endif
1590   - case OPC_SLT:
1591   - gen_op_lt(t0, t0, t1);
1592   - opn = "slt";
  1617 + case OPC_MUL:
  1618 + if (likely(rs != 0 && rt != 0)) {
  1619 + tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
  1620 + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
  1621 + } else {
  1622 + tcg_gen_movi_tl(cpu_gpr[rd], 0);
  1623 + }
  1624 + opn = "mul";
1593 1625 break;
1594   - case OPC_SLTU:
1595   - gen_op_ltu(t0, t0, t1);
1596   - opn = "sltu";
  1626 + }
  1627 + MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
  1628 +}
  1629 +
  1630 +/* Conditional move */
  1631 +static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
  1632 +{
  1633 + const char *opn = "cond move";
  1634 + int l1;
  1635 +
  1636 + if (rd == 0) {
  1637 + /* If no destination, treat it as a NOP.
  1638 + For add & sub, we must generate the overflow exception when needed. */
  1639 + MIPS_DEBUG("NOP");
  1640 + return;
  1641 + }
  1642 +
  1643 + l1 = gen_new_label();
  1644 + switch (opc) {
  1645 + case OPC_MOVN:
  1646 + if (likely(rt != 0))
  1647 + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
  1648 + else
  1649 + tcg_gen_br(l1);
  1650 + opn = "movn";
  1651 + break;
  1652 + case OPC_MOVZ:
  1653 + if (likely(rt != 0))
  1654 + tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
  1655 + opn = "movz";
1597 1656 break;
  1657 + }
  1658 + if (rs != 0)
  1659 + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
  1660 + else
  1661 + tcg_gen_movi_tl(cpu_gpr[rd], 0);
  1662 + gen_set_label(l1);
  1663 +
  1664 + MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
  1665 +}
  1666 +
  1667 +/* Logic */
  1668 +static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
  1669 +{
  1670 + const char *opn = "logic";
  1671 +
  1672 + if (rd == 0) {
  1673 + /* If no destination, treat it as a NOP. */
  1674 + MIPS_DEBUG("NOP");
  1675 + return;
  1676 + }
  1677 +
  1678 + switch (opc) {
1598 1679 case OPC_AND:
1599   - tcg_gen_and_tl(t0, t0, t1);
  1680 + if (likely(rs != 0 && rt != 0)) {
  1681 + tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
  1682 + } else {
  1683 + tcg_gen_movi_tl(cpu_gpr[rd], 0);
  1684 + }
1600 1685 opn = "and";
1601 1686 break;
1602 1687 case OPC_NOR:
1603   - tcg_gen_nor_tl(t0, t0, t1);
  1688 + if (rs != 0 && rt != 0) {
  1689 + tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
  1690 + } else if (rs == 0 && rt != 0) {
  1691 + tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
  1692 + } else if (rs != 0 && rt == 0) {
  1693 + tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
  1694 + } else {
  1695 + tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
  1696 + }
1604 1697 opn = "nor";
1605 1698 break;
1606 1699 case OPC_OR:
1607   - tcg_gen_or_tl(t0, t0, t1);
  1700 + if (likely(rs != 0 && rt != 0)) {
  1701 + tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
  1702 + } else if (rs == 0 && rt != 0) {
  1703 + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
  1704 + } else if (rs != 0 && rt == 0) {
  1705 + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
  1706 + } else {
  1707 + tcg_gen_movi_tl(cpu_gpr[rd], 0);
  1708 + }
1608 1709 opn = "or";
1609 1710 break;
1610 1711 case OPC_XOR:
1611   - tcg_gen_xor_tl(t0, t0, t1);
  1712 + if (likely(rs != 0 && rt != 0)) {
  1713 + tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
  1714 + } else if (rs == 0 && rt != 0) {
  1715 + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
  1716 + } else if (rs != 0 && rt == 0) {
  1717 + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
  1718 + } else {
  1719 + tcg_gen_movi_tl(cpu_gpr[rd], 0);
  1720 + }
1612 1721 opn = "xor";
1613 1722 break;
1614   - case OPC_MUL:
1615   - tcg_gen_mul_tl(t0, t0, t1);
1616   - tcg_gen_ext32s_tl(t0, t0);
1617   - opn = "mul";
  1723 + }
  1724 + MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
  1725 +}
  1726 +
  1727 +/* Set on lower than */
  1728 +static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
  1729 +{
  1730 + const char *opn = "slt";
  1731 + TCGv t0, t1;
  1732 +
  1733 + if (rd == 0) {
  1734 + /* If no destination, treat it as a NOP. */
  1735 + MIPS_DEBUG("NOP");
  1736 + return;
  1737 + }
  1738 +
  1739 + t0 = tcg_temp_new();
  1740 + t1 = tcg_temp_new();
  1741 + gen_load_gpr(t0, rs);
  1742 + gen_load_gpr(t1, rt);
  1743 + switch (opc) {
  1744 + case OPC_SLT:
  1745 + gen_op_lt(cpu_gpr[rd], t0, t1);
  1746 + opn = "slt";
1618 1747 break;
1619   - case OPC_MOVN:
1620   - {
1621   - int l1 = gen_new_label();
  1748 + case OPC_SLTU:
  1749 + gen_op_ltu(cpu_gpr[rd], t0, t1);
  1750 + opn = "sltu";
  1751 + break;
  1752 + }
  1753 + MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
  1754 + tcg_temp_free(t0);
  1755 + tcg_temp_free(t1);
  1756 +}
1622 1757  
1623   - tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1624   - gen_store_gpr(t0, rd);
1625   - gen_set_label(l1);
1626   - }
1627   - opn = "movn";
1628   - goto print;
1629   - case OPC_MOVZ:
1630   - {
1631   - int l1 = gen_new_label();
  1758 +/* Shifts */
  1759 +static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
  1760 + int rd, int rs, int rt)
  1761 +{
  1762 + const char *opn = "shifts";
  1763 + TCGv t0, t1;
1632 1764  
1633   - tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
1634   - gen_store_gpr(t0, rd);
1635   - gen_set_label(l1);
1636   - }
1637   - opn = "movz";
1638   - goto print;
  1765 + if (rd == 0) {
  1766 + /* If no destination, treat it as a NOP.
  1767 + For add & sub, we must generate the overflow exception when needed. */
  1768 + MIPS_DEBUG("NOP");
  1769 + return;
  1770 + }
  1771 +
  1772 + t0 = tcg_temp_new();
  1773 + t1 = tcg_temp_new();
  1774 + gen_load_gpr(t0, rs);
  1775 + gen_load_gpr(t1, rt);
  1776 + switch (opc) {
1639 1777 case OPC_SLLV:
1640 1778 tcg_gen_andi_tl(t0, t0, 0x1f);
1641 1779 tcg_gen_shl_tl(t0, t1, t0);
1642   - tcg_gen_ext32s_tl(t0, t0);
  1780 + tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1643 1781 opn = "sllv";
1644 1782 break;
1645 1783 case OPC_SRAV:
1646 1784 tcg_gen_ext32s_tl(t1, t1);
1647 1785 tcg_gen_andi_tl(t0, t0, 0x1f);
1648   - tcg_gen_sar_tl(t0, t1, t0);
  1786 + tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1649 1787 opn = "srav";
1650 1788 break;
1651 1789 case OPC_SRLV:
... ... @@ -1654,37 +1792,28 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1654 1792 tcg_gen_ext32u_tl(t1, t1);
1655 1793 tcg_gen_andi_tl(t0, t0, 0x1f);
1656 1794 tcg_gen_shr_tl(t0, t1, t0);
1657   - tcg_gen_ext32s_tl(t0, t0);
  1795 + tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1658 1796 opn = "srlv";
1659 1797 break;
1660 1798 case 1:
1661 1799 /* rotrv is decoded as srlv on non-R2 CPUs */
1662 1800 if (env->insn_flags & ISA_MIPS32R2) {
1663   - int l1 = gen_new_label();
1664   - int l2 = gen_new_label();
1665   -
1666   - tcg_gen_andi_tl(t0, t0, 0x1f);
1667   - tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1668   - {
1669   - TCGv_i32 r_tmp1 = tcg_temp_new_i32();
1670   - TCGv_i32 r_tmp2 = tcg_temp_new_i32();
1671   -
1672   - tcg_gen_trunc_tl_i32(r_tmp1, t0);
1673   - tcg_gen_trunc_tl_i32(r_tmp2, t1);
1674   - tcg_gen_rotr_i32(r_tmp1, r_tmp1, r_tmp2);
1675   - tcg_temp_free_i32(r_tmp1);
1676   - tcg_temp_free_i32(r_tmp2);
1677   - tcg_gen_br(l2);
1678   - }
1679   - gen_set_label(l1);
1680   - tcg_gen_mov_tl(t0, t1);
1681   - gen_set_label(l2);
  1801 + TCGv_i32 t2 = tcg_temp_new_i32();
  1802 + TCGv_i32 t3 = tcg_temp_new_i32();
  1803 +
  1804 + tcg_gen_trunc_tl_i32(t2, t0);
  1805 + tcg_gen_trunc_tl_i32(t3, t1);
  1806 + tcg_gen_andi_i32(t2, t2, 0x1f);
  1807 + tcg_gen_rotr_i32(t2, t3, t2);
  1808 + tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
  1809 + tcg_temp_free_i32(t2);
  1810 + tcg_temp_free_i32(t3);
1682 1811 opn = "rotrv";
1683 1812 } else {
1684 1813 tcg_gen_ext32u_tl(t1, t1);
1685 1814 tcg_gen_andi_tl(t0, t0, 0x1f);
1686 1815 tcg_gen_shr_tl(t0, t1, t0);
1687   - tcg_gen_ext32s_tl(t0, t0);
  1816 + tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1688 1817 opn = "srlv";
1689 1818 }
1690 1819 break;
... ... @@ -1697,36 +1826,26 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1697 1826 #if defined(TARGET_MIPS64)
1698 1827 case OPC_DSLLV:
1699 1828 tcg_gen_andi_tl(t0, t0, 0x3f);
1700   - tcg_gen_shl_tl(t0, t1, t0);
  1829 + tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1701 1830 opn = "dsllv";
1702 1831 break;
1703 1832 case OPC_DSRAV:
1704 1833 tcg_gen_andi_tl(t0, t0, 0x3f);
1705   - tcg_gen_sar_tl(t0, t1, t0);
  1834 + tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1706 1835 opn = "dsrav";
1707 1836 break;
1708 1837 case OPC_DSRLV:
1709 1838 switch ((ctx->opcode >> 6) & 0x1f) {
1710 1839 case 0:
1711 1840 tcg_gen_andi_tl(t0, t0, 0x3f);
1712   - tcg_gen_shr_tl(t0, t1, t0);
  1841 + tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1713 1842 opn = "dsrlv";
1714 1843 break;
1715 1844 case 1:
1716 1845 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1717 1846 if (env->insn_flags & ISA_MIPS32R2) {
1718   - int l1 = gen_new_label();
1719   - int l2 = gen_new_label();
1720   -
1721 1847 tcg_gen_andi_tl(t0, t0, 0x3f);
1722   - tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1723   - {
1724   - tcg_gen_rotr_tl(t0, t1, t0);
1725   - tcg_gen_br(l2);
1726   - }
1727   - gen_set_label(l1);
1728   - tcg_gen_mov_tl(t0, t1);
1729   - gen_set_label(l2);
  1848 + tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1730 1849 opn = "drotrv";
1731 1850 } else {
1732 1851 tcg_gen_andi_tl(t0, t0, 0x3f);
... ... @@ -1741,15 +1860,8 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1741 1860 }
1742 1861 break;
1743 1862 #endif
1744   - default:
1745   - MIPS_INVAL(opn);
1746   - generate_exception(ctx, EXCP_RI);
1747   - goto out;
1748 1863 }
1749   - gen_store_gpr(t0, rd);
1750   - print:
1751 1864 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1752   - out:
1753 1865 tcg_temp_free(t0);
1754 1866 tcg_temp_free(t1);
1755 1867 }
... ... @@ -7465,14 +7577,29 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
7465 7577 case OPC_SRL ... OPC_SRA:
7466 7578 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7467 7579 break;
7468   - case OPC_MOVZ ... OPC_MOVN:
  7580 + case OPC_MOVN: /* Conditional move */
  7581 + case OPC_MOVZ:
7469 7582 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7470   - case OPC_SLLV: /* Arithmetic */
7471   - case OPC_SRLV ... OPC_SRAV:
7472   - case OPC_ADD ... OPC_NOR:
7473   - case OPC_SLT ... OPC_SLTU:
  7583 + gen_cond_move(env, op1, rd, rs, rt);
  7584 + break;
  7585 + case OPC_ADD ... OPC_SUBU:
7474 7586 gen_arith(env, ctx, op1, rd, rs, rt);
7475 7587 break;
  7588 + case OPC_SLLV: /* Shifts */
  7589 + case OPC_SRLV:
  7590 + case OPC_SRAV:
  7591 + gen_shift(env, ctx, op1, rd, rs, rt);
  7592 + break;
  7593 + case OPC_SLT: /* Set on less than */
  7594 + case OPC_SLTU:
  7595 + gen_slt(env, op1, rd, rs, rt);
  7596 + break;
  7597 + case OPC_AND: /* Logic*/
  7598 + case OPC_OR:
  7599 + case OPC_NOR:
  7600 + case OPC_XOR:
  7601 + gen_logic(env, op1, rd, rs, rt);
  7602 + break;
7476 7603 case OPC_MULT ... OPC_DIVU:
7477 7604 if (sa) {
7478 7605 check_insn(env, ctx, INSN_VR54XX);
... ... @@ -7545,13 +7672,18 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
7545 7672 check_mips_64(ctx);
7546 7673 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7547 7674 break;
7548   - case OPC_DSLLV:
7549   - case OPC_DSRLV ... OPC_DSRAV:
7550 7675 case OPC_DADD ... OPC_DSUBU:
7551 7676 check_insn(env, ctx, ISA_MIPS3);
7552 7677 check_mips_64(ctx);
7553 7678 gen_arith(env, ctx, op1, rd, rs, rt);
7554 7679 break;
  7680 + case OPC_DSLLV:
  7681 + case OPC_DSRAV:
  7682 + case OPC_DSRLV:
  7683 + check_insn(env, ctx, ISA_MIPS3);
  7684 + check_mips_64(ctx);
  7685 + gen_shift(env, ctx, op1, rd, rs, rt);
  7686 + break;
7555 7687 case OPC_DMULT ... OPC_DDIVU:
7556 7688 check_insn(env, ctx, ISA_MIPS3);
7557 7689 check_mips_64(ctx);
... ...