| 1733 | } |
| 1734 | |
| 1735 | static void emit_shift_handler(X64Emitter& e, const VMConfig& vm, void (X64Emitter::*op_cl)(std::uint8_t, bool)) { |
| 1736 | const auto& r = vm.dispatcher_regs(); |
| 1737 | emit_fetch_byte_dec(e, vm, r.scratch_a); // dst slot |
| 1738 | emit_fetch_byte_dec(e, vm, r.scratch_b); // dst width |
| 1739 | e.push_reg(r.scratch_a); e.push_reg(r.scratch_b); |
| 1740 | e.mov_reg_mem_sib( |
| 1741 | rx::rax, |
| 1742 | r.state_ptr, |
| 1743 | r.scratch_a, |
| 1744 | 3, |
| 1745 | static_cast<std::int32_t>(vm.state_layout().regs_base), |
| 1746 | true |
| 1747 | ); |
| 1748 | emit_fetch_byte_dec(e, vm, r.scratch_a); |
| 1749 | auto lbl_reg = e.new_label(), lbl_done = e.new_label(); |
| 1750 | e.cmp_reg_imm32(r.scratch_a, 0); |
| 1751 | e.jcc_label(cc::z, lbl_reg); |
| 1752 | emit_fetch_byte_dec(e, vm, rx::rcx); |
| 1753 | e.jmp_label(lbl_done); |
| 1754 | e.bind(lbl_reg); |
| 1755 | emit_fetch_byte_dec(e, vm, r.scratch_b); |
| 1756 | emit_fetch_byte_dec(e, vm, r.scratch_a); |
| 1757 | e.mov_reg_mem_sib( |
| 1758 | rx::rcx, |
| 1759 | r.state_ptr, |
| 1760 | r.scratch_b, |
| 1761 | 3, |
| 1762 | static_cast<std::int32_t>(vm.state_layout().regs_base), |
| 1763 | true |
| 1764 | ); |
| 1765 | e.bind(lbl_done); |
| 1766 | e.and_reg_imm32(rx::rcx, 0x3F); |
| 1767 | |
| 1768 | // width-aware shift |
| 1769 | auto lbl_w8_shift = e.new_label(), lbl_shift_done = e.new_label(); |
| 1770 | e.mov_reg_mem( |
| 1771 | rx::rdx, |
| 1772 | rx::rsp, |
| 1773 | 0, |
| 1774 | true |
| 1775 | ); // rdx = saved width byte |
| 1776 | |
| 1777 | e.and_reg_imm32(rx::rdx, 0x7F); |
| 1778 | e.cmp_reg_imm32(rx::rdx, 8); |
| 1779 | e.jcc_label(cc::z, lbl_w8_shift); |
| 1780 | (e.*op_cl)(rx::rax, false); // 32-bit shift zero-extends |
| 1781 | e.jmp_label(lbl_shift_done); |
| 1782 | e.bind(lbl_w8_shift); |
| 1783 | (e.*op_cl)(rx::rax, true); // 64-bit shift |
| 1784 | e.bind(lbl_shift_done); |
| 1785 | e.pop_reg(r.scratch_b); |
| 1786 | e.pop_reg(r.scratch_a); |
| 1787 | emit_store_slot_value( |
| 1788 | e, |
| 1789 | vm, |
| 1790 | r.scratch_a, |
| 1791 | rx::rax, |
| 1792 | r.scratch_b |
no test coverage detected