MCPcopy Create free account
hub / github.com/N64Recomp/N64Recomp / emit_muldiv

Method emit_muldiv

LiveRecomp/live_generator.cpp:1751–1910  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1749}
1750
1751void 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

Callers

nothing calls this directly

Calls 1

get_gpr_valuesFunction · 0.85

Tested by

no test coverage detected