| 1749 | } |
| 1750 | |
| 1751 | void N64Recomp::LiveGenerator::emit_muldiv(InstrId instr_id, int reg1, int reg2) const { |
| 1752 | sljit_sw src1; |
| 1753 | sljit_sw src1w; |
| 1754 | sljit_sw src2; |
| 1755 | sljit_sw src2w; |
| 1756 | get_gpr_values(reg1, src1, src1w); |
| 1757 | get_gpr_values(reg2, src2, src2w); |
| 1758 | |
| 1759 | auto do_mul32_op = [src1, src1w, src2, src2w, this](bool is_signed) { |
| 1760 | // Load the two inputs into the multiplication input registers (R0/R1). |
| 1761 | if (is_signed) { |
| 1762 | // 32-bit signed multiplication is really 64 bits * 35 bits, so load accordingly. |
| 1763 | sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, src1, src1w); |
| 1764 | |
| 1765 | // Sign extend to 35 bits by shifting left by 64 - 35 and then shifting right by the same amount. |
| 1766 | sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R1, 0, src2, src2w, SLJIT_IMM, 64 - 35); |
| 1767 | sljit_emit_op2(compiler, SLJIT_ASHR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 64 - 35); |
| 1768 | } |
| 1769 | else { |
| 1770 | sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, src1, src1w); |
| 1771 | sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R1, 0, src2, src2w); |
| 1772 | } |
| 1773 | |
| 1774 | // Perform the multiplication. |
| 1775 | sljit_emit_op0(compiler, is_signed ? SLJIT_LMUL_SW : SLJIT_LMUL_UW); |
| 1776 | |
| 1777 | // Move the results into hi and lo with sign extension. |
| 1778 | sljit_emit_op2(compiler, SLJIT_ASHR, Registers::hi, 0, SLJIT_R0, 0, SLJIT_IMM, 32); |
| 1779 | sljit_emit_op1(compiler, SLJIT_MOV_S32, Registers::lo, 0, SLJIT_R0, 0); |
| 1780 | }; |
| 1781 | |
| 1782 | auto do_mul64_op = [src1, src1w, src2, src2w, this](bool is_signed) { |
| 1783 | // Load the two inputs into the multiplication input registers (R0/R1). |
| 1784 | sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, src1, src1w); |
| 1785 | sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, src2, src2w); |
| 1786 | |
| 1787 | // Perform the multiplication. |
| 1788 | sljit_emit_op0(compiler, is_signed ? SLJIT_LMUL_SW : SLJIT_LMUL_UW); |
| 1789 | |
| 1790 | // Move the results into hi and lo. |
| 1791 | sljit_emit_op1(compiler, SLJIT_MOV, Registers::hi, 0, SLJIT_R1, 0); |
| 1792 | sljit_emit_op1(compiler, SLJIT_MOV, Registers::lo, 0, SLJIT_R0, 0); |
| 1793 | }; |
| 1794 | |
| 1795 | auto do_div_op = [src1, src1w, src2, src2w, this](bool doubleword, bool is_signed) { |
| 1796 | // Pick the division opcode based on the bit width and signedness. |
| 1797 | // Note that the 64-bit division opcode is used for 32-bit signed division to match hardware behavior and prevent overflow. |
| 1798 | sljit_sw div_opcode = doubleword ? |
| 1799 | (is_signed ? SLJIT_DIVMOD_SW : SLJIT_DIVMOD_UW) : |
| 1800 | (is_signed ? SLJIT_DIVMOD_SW : SLJIT_DIVMOD_U32); |
| 1801 | |
| 1802 | // Pick the move opcode to use for loading the operands. |
| 1803 | sljit_sw load_opcode = doubleword ? SLJIT_MOV : |
| 1804 | (is_signed ? SLJIT_MOV_S32 : SLJIT_MOV_U32); |
| 1805 | |
| 1806 | // Pick the move opcode to use for saving the results. |
| 1807 | sljit_sw save_opcode = doubleword ? SLJIT_MOV : SLJIT_MOV_S32; |
| 1808 |
nothing calls this directly
no test coverage detected