rwasm 0.4.3

ZK-friendly WebAssembly runtime optimized for blockchain and zero-knowledge applications
Documentation
use crate::{InstructionSet, TrapCode};

impl InstructionSet {
    pub const MSH_I64_REM_U: u32 = 20;

    /// Computes the unsigned 64-bit integer remainder (modulus) using only 32-bit arithmetic,
    /// returning the 64-bit remainder as two `u32` limbs (low, high).
    ///
    /// Emulates full unsigned 64-bit remainder operation for platforms or VMs lacking native
    /// 64-bit division/modulo, such as WASM VMs with 32-bit stack elements.
    ///
    /// # Arguments
    /// - `n_lo`, `n_hi`: Low and high 32 bits of the dividend (`n = (n_hi << 32) | n_lo`,
    ///   interpreted as u64)
    /// - `d_lo`, `d_hi`: Low and high 32 bits of the divisor (`d = (d_hi << 32) | d_lo`,
    ///   interpreted as u64)
    ///
    /// # Returns
    /// - `(rem_lo, rem_hi)`: Low and high 32 bits of the unsigned remainder
    ///
    /// # Algorithm
    /// - Traps on division by zero, matching WASM and Rust semantics.
    /// - Fast path: When divisor fits in 32 bits, uses a custom 64-by-32 remainder loop.
    /// - General path: For arbitrary 64-bit divisors, performs classic binary long division over 64
    ///   iterations, building up quotient and remainder bitwise using only 32-bit arithmetic.
    /// - Returns the unsigned remainder as two 32-bit limbs.
    ///
    /// # Panics / Traps
    /// - Division by zero triggers a trap (`core::intrinsics::abort()`).
    ///
    /// # Note
    /// Input and output values are two-limb representations of unsigned 64-bit integers.
    ///
    /// Max stack height: 14
    pub fn op_i64_rem_u(&mut self) {
        self.op_i32_const(0);
        self.op_i32_const(0);
        self.op_i32_const(0);
        self.op_i32_const(0);
        self.op_i32_const(0);
        self.op_i32_const(0);
        self.op_local_get(7);
        self.op_br_if_nez(144);
        self.op_local_get(8);
        self.op_br_if_nez(2);
        self.op_trap(TrapCode::IntegerDivisionByZero);
        self.op_local_get(8);
        self.op_i32_const(0);
        self.op_i32_lt_s();
        self.op_br_if_nez(137);
        self.op_i32_const(64);
        self.op_local_set(6);
        self.op_i32_const(0);
        self.op_local_set(5);
        self.op_local_get(6);
        self.op_i32_const(32);
        self.op_i32_gt_u();
        self.op_local_set(7);
        self.op_local_get(6);
        self.op_i32_const(4294967295u32 as i32);
        self.op_i32_add();
        self.op_local_set(4);
        self.op_i32_const(0);
        self.op_local_get(10);
        self.op_local_get(8);
        self.op_i32_const(4294967294u32 as i32);
        self.op_i32_add();
        self.op_local_tee(9);
        self.op_i32_shr_u();
        self.op_i32_const(1);
        self.op_i32_and();
        self.op_local_get(6);
        self.op_i32_const(32);
        self.op_i32_gt_u();
        self.op_select();
        self.op_i32_const(0);
        self.op_local_get(11);
        self.op_local_get(7);
        self.op_i32_shr_u();
        self.op_i32_const(1);
        self.op_i32_and();
        self.op_local_get(10);
        self.op_select();
        self.op_local_get(7);
        self.op_i32_const(1);
        self.op_i32_shl();
        self.op_i32_or();
        self.op_local_tee(7);
        self.op_i32_const(0);
        self.op_local_get(11);
        self.op_local_get(9);
        self.op_local_get(13);
        self.op_i32_lt_u();
        self.op_select();
        self.op_i32_sub();
        self.op_i32_const(1);
        self.op_i32_shl();
        self.op_i32_or();
        self.op_local_tee(6);
        self.op_i32_const(0);
        self.op_local_get(10);
        self.op_local_get(8);
        self.op_local_get(12);
        self.op_i32_lt_u();
        self.op_select();
        self.op_i32_sub();
        self.op_local_set(5);
        self.op_local_get(4);
        self.op_i32_const(1);
        self.op_i32_ne();
        self.op_br_if_nez(-56);
        self.op_i32_const(95);
        self.op_local_set(6);
        self.op_i32_const(0);
        self.op_local_set(4);
        self.op_local_get(5);
        self.op_local_get(7);
        self.op_i32_const(4294967295u32 as i32);
        self.op_i32_add();
        self.op_i32_const(30);
        self.op_i32_and();
        self.op_i32_shr_u();
        self.op_local_get(11);
        self.op_local_get(8);
        self.op_i32_const(4294967263u32 as i32);
        self.op_i32_add();
        self.op_local_tee(12);
        self.op_i32_shr_u();
        self.op_local_get(8);
        self.op_i32_const(4294967264u32 as i32);
        self.op_i32_add();
        self.op_local_tee(10);
        self.op_i32_const(32);
        self.op_i32_gt_u();
        self.op_select();
        self.op_i32_const(1);
        self.op_i32_and();
        self.op_local_get(6);
        self.op_local_get(8);
        self.op_i32_shr_u();
        self.op_local_get(12);
        self.op_local_get(10);
        self.op_i32_shr_u();
        self.op_local_get(9);
        self.op_i32_const(4294967265u32 as i32);
        self.op_i32_add();
        self.op_i32_const(32);
        self.op_i32_gt_u();
        self.op_select();
        self.op_i32_const(1);
        self.op_i32_and();
        self.op_local_get(6);
        self.op_i32_const(1);
        self.op_i32_shl();
        self.op_i32_or();
        self.op_local_tee(6);
        self.op_i32_const(0);
        self.op_local_get(11);
        self.op_local_get(8);
        self.op_local_get(13);
        self.op_i32_lt_u();
        self.op_select();
        self.op_i32_sub();
        self.op_i32_const(1);
        self.op_i32_shl();
        self.op_i32_or();
        self.op_local_tee(5);
        self.op_i32_const(0);
        self.op_local_get(10);
        self.op_local_get(7);
        self.op_local_get(12);
        self.op_i32_lt_u();
        self.op_select();
        self.op_i32_sub();
        self.op_local_set(4);
        self.op_local_get(6);
        self.op_i32_const(4294967294u32 as i32);
        self.op_i32_add();
        self.op_local_set(6);
        self.op_local_get(9);
        self.op_br_if_nez(-65);
        self.op_i32_const(0);
        self.op_i32_const(0);
        self.op_local_set(3);
        self.op_local_set(3);
        self.op_br(182);
        self.op_i32_const(0);
        self.op_local_set(6);
        self.op_i32_const(64);
        self.op_local_set(1);
        self.op_i32_const(0);
        self.op_local_set(4);
        self.op_local_get(4);
        self.op_i32_const(1);
        self.op_i32_shl();
        self.op_local_get(10);
        self.op_i32_const(31);
        self.op_i32_shr_u();
        self.op_i32_or();
        self.op_local_set(5);
        self.op_local_get(6);
        self.op_i32_const(1);
        self.op_i32_shl();
        self.op_local_get(5);
        self.op_i32_const(31);
        self.op_i32_shr_u();
        self.op_i32_or();
        self.op_local_tee(7);
        self.op_local_get(8);
        self.op_i32_gt_u();
        self.op_br_if_nez(12);
        self.op_local_get(6);
        self.op_local_get(8);
        self.op_i32_ne();
        self.op_br_if_nez(5);
        self.op_local_get(5);
        self.op_local_get(9);
        self.op_i32_ge_u();
        self.op_br_if_nez(4);
        self.op_local_get(5);
        self.op_local_set(4);
        self.op_br(13);
        self.op_local_get(6);
        self.op_local_get(8);
        self.op_i32_sub();
        self.op_local_get(6);
        self.op_local_get(10);
        self.op_i32_lt_u();
        self.op_i32_sub();
        self.op_local_set(6);
        self.op_local_get(5);
        self.op_local_get(9);
        self.op_i32_sub();
        self.op_local_set(4);
        self.op_local_get(9);
        self.op_i32_const(1);
        self.op_i32_shl();
        self.op_local_get(11);
        self.op_i32_const(31);
        self.op_i32_shr_u();
        self.op_i32_or();
        self.op_local_set(9);
        self.op_local_get(10);
        self.op_i32_const(1);
        self.op_i32_shl();
        self.op_local_set(10);
        self.op_local_get(1);
        self.op_i32_const(4294967295u32 as i32);
        self.op_i32_add();
        self.op_local_tee(2);
        self.op_br_if_nez(-58);
        self.op_local_get(6);
        self.op_i32_const(0);
        self.op_i32_const(32);
        self.op_i32_const(0);
        self.op_i32_const(0);
        self.op_i32_const(0);
        self.op_local_get(4);
        self.op_i32_const(63);
        self.op_i32_and();
        self.op_local_tee(3);
        self.op_br_if_nez(4);
        self.op_local_get(6);
        self.op_local_set(1);
        self.op_br(44);
        self.op_local_get(2);
        self.op_i32_const(32);
        self.op_i32_eq();
        self.op_br_if_nez(36);
        self.op_local_get(2);
        self.op_i32_const(4294967295u32 as i32);
        self.op_i32_add();
        self.op_i32_const(31);
        self.op_i32_lt_u();
        self.op_br_if_nez(10);
        self.op_i32_const(0);
        self.op_local_set(1);
        self.op_local_get(2);
        self.op_i32_const(32);
        self.op_i32_gt_u();
        self.op_br_if_nez(19);
        self.op_i32_const(0);
        self.op_local_set(5);
        self.op_br(25);
        self.op_local_get(5);
        self.op_local_get(5);
        self.op_i32_shl();
        self.op_local_get(7);
        self.op_i32_const(0);
        self.op_local_get(7);
        self.op_i32_sub();
        self.op_i32_shr_u();
        self.op_i32_or();
        self.op_local_set(5);
        self.op_local_get(6);
        self.op_local_get(5);
        self.op_i32_shl();
        self.op_local_set(1);
        self.op_br(10);
        self.op_local_get(6);
        self.op_local_get(5);
        self.op_i32_shl();
        self.op_local_set(5);
        self.op_br(5);
        self.op_i32_const(0);
        self.op_local_set(1);
        self.op_local_get(6);
        self.op_local_set(5);
        self.op_local_get(5);
        self.op_i32_const(0);
        self.op_i32_const(32);
        self.op_i32_const(0);
        self.op_local_get(2);
        self.op_i32_const(63);
        self.op_i32_and();
        self.op_local_set(2);
        self.op_local_get(2);
        self.op_br_if_eqz(32);
        self.op_local_get(2);
        self.op_i32_const(31);
        self.op_i32_gt_u();
        self.op_br_if_eqz(10);
        self.op_local_get(4);
        self.op_local_get(3);
        self.op_i32_const(32);
        self.op_i32_sub();
        self.op_i32_shl();
        self.op_local_set(3);
        self.op_i32_const(0);
        self.op_local_set(4);
        self.op_br(19);
        self.op_local_get(4);
        self.op_local_get(3);
        self.op_i32_shl();
        self.op_local_set(4);
        self.op_local_get(3);
        self.op_local_get(3);
        self.op_i32_shl();
        self.op_local_set(3);
        self.op_local_get(4);
        self.op_i32_const(32);
        self.op_local_get(4);
        self.op_i32_const(31);
        self.op_i32_and();
        self.op_i32_sub();
        self.op_i32_shr_u();
        self.op_local_get(4);
        self.op_i32_or();
        self.op_local_set(3);
        self.op_drop();
        self.op_drop();
        self.op_local_get(3);
        self.op_i32_const(0);
        self.op_local_get(3);
        self.op_i32_or();
        self.op_local_set(2);
        self.op_local_get(3);
        self.op_i32_or();
        self.op_local_set(2);
        self.op_local_set(6);
        self.op_local_set(6);
        self.op_drop();
        self.op_drop();
        self.op_drop();
        self.op_drop();
        self.op_local_set(3);
        self.op_local_set(3);
        self.op_local_get(3);
        self.op_local_get(3);
        self.op_local_get(6);
        self.op_i32_const(0);
        self.op_local_get(3);
        self.op_i32_or();
        self.op_local_set(2);
        self.op_local_get(3);
        self.op_i32_or();
        self.op_local_set(2);
        self.op_local_set(10);
        self.op_local_set(10);
        self.op_drop();
        self.op_drop();
        self.op_drop();
        self.op_drop();
        self.op_drop();
        self.op_drop();
        self.op_drop();
        self.op_drop();
    }
}