Commit 460f00c4e1f43cf610633e31ad4988c9ddcc415f
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); | ... | ... |