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,200 +1452,338 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1452 int rd, int rs, int rt) 1452 int rd, int rs, int rt)
1453 { 1453 {
1454 const char *opn = "arith"; 1454 const char *opn = "arith";
1455 - TCGv t0 = tcg_temp_local_new();  
1456 - TCGv t1 = tcg_temp_local_new();  
1457 1455
1458 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB 1456 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1459 && opc != OPC_DADD && opc != OPC_DSUB) { 1457 && opc != OPC_DADD && opc != OPC_DSUB) {
1460 /* If no destination, treat it as a NOP. 1458 /* If no destination, treat it as a NOP.
1461 For add & sub, we must generate the overflow exception when needed. */ 1459 For add & sub, we must generate the overflow exception when needed. */
1462 MIPS_DEBUG("NOP"); 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 switch (opc) { 1464 switch (opc) {
1474 case OPC_ADD: 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 int l1 = gen_new_label(); 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 /* operands of same sign, result different sign */ 1483 /* operands of same sign, result different sign */
1492 generate_exception(ctx, EXCP_OVERFLOW); 1484 generate_exception(ctx, EXCP_OVERFLOW);
1493 gen_set_label(l1); 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 opn = "add"; 1489 opn = "add";
1499 break; 1490 break;
1500 case OPC_ADDU: 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 opn = "addu"; 1502 opn = "addu";
1504 break; 1503 break;
1505 case OPC_SUB: 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 int l1 = gen_new_label(); 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 generate_exception(ctx, EXCP_OVERFLOW); 1522 generate_exception(ctx, EXCP_OVERFLOW);
1523 gen_set_label(l1); 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 opn = "sub"; 1527 opn = "sub";
1529 break; 1528 break;
1530 case OPC_SUBU: 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 opn = "subu"; 1540 opn = "subu";
1534 break; 1541 break;
1535 #if defined(TARGET_MIPS64) 1542 #if defined(TARGET_MIPS64)
1536 case OPC_DADD: 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 int l1 = gen_new_label(); 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 /* operands of same sign, result different sign */ 1560 /* operands of same sign, result different sign */
1553 generate_exception(ctx, EXCP_OVERFLOW); 1561 generate_exception(ctx, EXCP_OVERFLOW);
1554 gen_set_label(l1); 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 opn = "dadd"; 1566 opn = "dadd";
1558 break; 1567 break;
1559 case OPC_DADDU: 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 opn = "daddu"; 1578 opn = "daddu";
1562 break; 1579 break;
1563 case OPC_DSUB: 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 int l1 = gen_new_label(); 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 generate_exception(ctx, EXCP_OVERFLOW); 1597 generate_exception(ctx, EXCP_OVERFLOW);
1580 gen_set_label(l1); 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 opn = "dsub"; 1602 opn = "dsub";
1584 break; 1603 break;
1585 case OPC_DSUBU: 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 opn = "dsubu"; 1614 opn = "dsubu";
1588 break; 1615 break;
1589 #endif 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 break; 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 break; 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 case OPC_AND: 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 opn = "and"; 1685 opn = "and";
1601 break; 1686 break;
1602 case OPC_NOR: 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 opn = "nor"; 1697 opn = "nor";
1605 break; 1698 break;
1606 case OPC_OR: 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 opn = "or"; 1709 opn = "or";
1609 break; 1710 break;
1610 case OPC_XOR: 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 opn = "xor"; 1721 opn = "xor";
1613 break; 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 break; 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 case OPC_SLLV: 1777 case OPC_SLLV:
1640 tcg_gen_andi_tl(t0, t0, 0x1f); 1778 tcg_gen_andi_tl(t0, t0, 0x1f);
1641 tcg_gen_shl_tl(t0, t1, t0); 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 opn = "sllv"; 1781 opn = "sllv";
1644 break; 1782 break;
1645 case OPC_SRAV: 1783 case OPC_SRAV:
1646 tcg_gen_ext32s_tl(t1, t1); 1784 tcg_gen_ext32s_tl(t1, t1);
1647 tcg_gen_andi_tl(t0, t0, 0x1f); 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 opn = "srav"; 1787 opn = "srav";
1650 break; 1788 break;
1651 case OPC_SRLV: 1789 case OPC_SRLV:
@@ -1654,37 +1792,28 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, @@ -1654,37 +1792,28 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1654 tcg_gen_ext32u_tl(t1, t1); 1792 tcg_gen_ext32u_tl(t1, t1);
1655 tcg_gen_andi_tl(t0, t0, 0x1f); 1793 tcg_gen_andi_tl(t0, t0, 0x1f);
1656 tcg_gen_shr_tl(t0, t1, t0); 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 opn = "srlv"; 1796 opn = "srlv";
1659 break; 1797 break;
1660 case 1: 1798 case 1:
1661 /* rotrv is decoded as srlv on non-R2 CPUs */ 1799 /* rotrv is decoded as srlv on non-R2 CPUs */
1662 if (env->insn_flags & ISA_MIPS32R2) { 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 opn = "rotrv"; 1811 opn = "rotrv";
1683 } else { 1812 } else {
1684 tcg_gen_ext32u_tl(t1, t1); 1813 tcg_gen_ext32u_tl(t1, t1);
1685 tcg_gen_andi_tl(t0, t0, 0x1f); 1814 tcg_gen_andi_tl(t0, t0, 0x1f);
1686 tcg_gen_shr_tl(t0, t1, t0); 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 opn = "srlv"; 1817 opn = "srlv";
1689 } 1818 }
1690 break; 1819 break;
@@ -1697,36 +1826,26 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, @@ -1697,36 +1826,26 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1697 #if defined(TARGET_MIPS64) 1826 #if defined(TARGET_MIPS64)
1698 case OPC_DSLLV: 1827 case OPC_DSLLV:
1699 tcg_gen_andi_tl(t0, t0, 0x3f); 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 opn = "dsllv"; 1830 opn = "dsllv";
1702 break; 1831 break;
1703 case OPC_DSRAV: 1832 case OPC_DSRAV:
1704 tcg_gen_andi_tl(t0, t0, 0x3f); 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 opn = "dsrav"; 1835 opn = "dsrav";
1707 break; 1836 break;
1708 case OPC_DSRLV: 1837 case OPC_DSRLV:
1709 switch ((ctx->opcode >> 6) & 0x1f) { 1838 switch ((ctx->opcode >> 6) & 0x1f) {
1710 case 0: 1839 case 0:
1711 tcg_gen_andi_tl(t0, t0, 0x3f); 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 opn = "dsrlv"; 1842 opn = "dsrlv";
1714 break; 1843 break;
1715 case 1: 1844 case 1:
1716 /* drotrv is decoded as dsrlv on non-R2 CPUs */ 1845 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1717 if (env->insn_flags & ISA_MIPS32R2) { 1846 if (env->insn_flags & ISA_MIPS32R2) {
1718 - int l1 = gen_new_label();  
1719 - int l2 = gen_new_label();  
1720 -  
1721 tcg_gen_andi_tl(t0, t0, 0x3f); 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 opn = "drotrv"; 1849 opn = "drotrv";
1731 } else { 1850 } else {
1732 tcg_gen_andi_tl(t0, t0, 0x3f); 1851 tcg_gen_andi_tl(t0, t0, 0x3f);
@@ -1741,15 +1860,8 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, @@ -1741,15 +1860,8 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1741 } 1860 }
1742 break; 1861 break;
1743 #endif 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 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); 1864 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1752 - out:  
1753 tcg_temp_free(t0); 1865 tcg_temp_free(t0);
1754 tcg_temp_free(t1); 1866 tcg_temp_free(t1);
1755 } 1867 }
@@ -7465,14 +7577,29 @@ static void decode_opc (CPUState *env, DisasContext *ctx) @@ -7465,14 +7577,29 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
7465 case OPC_SRL ... OPC_SRA: 7577 case OPC_SRL ... OPC_SRA:
7466 gen_arith_imm(env, ctx, op1, rd, rt, sa); 7578 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7467 break; 7579 break;
7468 - case OPC_MOVZ ... OPC_MOVN: 7580 + case OPC_MOVN: /* Conditional move */
  7581 + case OPC_MOVZ:
7469 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32); 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 gen_arith(env, ctx, op1, rd, rs, rt); 7586 gen_arith(env, ctx, op1, rd, rs, rt);
7475 break; 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 case OPC_MULT ... OPC_DIVU: 7603 case OPC_MULT ... OPC_DIVU:
7477 if (sa) { 7604 if (sa) {
7478 check_insn(env, ctx, INSN_VR54XX); 7605 check_insn(env, ctx, INSN_VR54XX);
@@ -7545,13 +7672,18 @@ static void decode_opc (CPUState *env, DisasContext *ctx) @@ -7545,13 +7672,18 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
7545 check_mips_64(ctx); 7672 check_mips_64(ctx);
7546 gen_arith_imm(env, ctx, op1, rd, rt, sa); 7673 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7547 break; 7674 break;
7548 - case OPC_DSLLV:  
7549 - case OPC_DSRLV ... OPC_DSRAV:  
7550 case OPC_DADD ... OPC_DSUBU: 7675 case OPC_DADD ... OPC_DSUBU:
7551 check_insn(env, ctx, ISA_MIPS3); 7676 check_insn(env, ctx, ISA_MIPS3);
7552 check_mips_64(ctx); 7677 check_mips_64(ctx);
7553 gen_arith(env, ctx, op1, rd, rs, rt); 7678 gen_arith(env, ctx, op1, rd, rs, rt);
7554 break; 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 case OPC_DMULT ... OPC_DDIVU: 7687 case OPC_DMULT ... OPC_DDIVU:
7556 check_insn(env, ctx, ISA_MIPS3); 7688 check_insn(env, ctx, ISA_MIPS3);
7557 check_mips_64(ctx); 7689 check_mips_64(ctx);