local ops = {} local constants = require("constants") local intutil = require("intutil") function ops.select(a, b, c) return (c ~= 0) and a or b end --[[ i64 ]] function ops.i64_eqz(a) return (a == 0) and 1 or 0 end function ops.i64_eq(a, b) return (a == b) and 1 or 0 end function ops.i64_ne(a, b) return (a ~= b) and 1 or 0 end function ops.i64_lt_s(a, b) return (a < b) and 1 or 0 end function ops.i64_gt_s(a, b) return (a > b) and 1 or 0 end function ops.i64_le_s(a, b) return (a <= b) and 1 or 0 end function ops.i64_ge_s(a, b) return (a >= b) and 1 or 0 end function ops.i64_clz(a) if a == 0 then return 64 end local n = 0 if (a & 0xFFFFFFFF00000000) == 0 then n = n + 32 a = a << 32 end if (a & 0xFFFF000000000000) == 0 then n = n + 16 a = a << 16 end if (a & 0xFF00000000000000) == 0 then n = n + 8 a = a << 8 end if (a & 0xF000000000000000) == 0 then n = n + 4 a = a << 4 end if (a & 0xC000000000000000) == 0 then n = n + 2 a = a << 2 end if (a & 0x8000000000000000) == 0 then n = n + 1 end return n end function ops.i64_ctz(a) if a == 0 then return 64 end local n = 0 if (a & 0x00000000FFFFFFFF) == 0 then n = n + 32 a = a >> 32 end if (a & 0x000000000000FFFF) == 0 then n = n + 16 a = a >> 16 end if (a & 0x00000000000000FF) == 0 then n = n + 8 a = a >> 8 end if (a & 0x000000000000000F) == 0 then n = n + 4 a = a >> 4 end if (a & 0x0000000000000003) == 0 then n = n + 2 a = a >> 2 end if (a & 0x0000000000000001) == 0 then n = n + 1 end return n end function ops.i64_popcnt(a) local n = 0 for _ = 1, 64 do if (a & 1) == 1 then n = n + 1 end a = a >> 1 end return n end function ops.i64_add(a, b) return a + b end function ops.i64_sub(a, b) return a - b end function ops.i64_mul(a, b) return a * b end function ops.i64_div_s(a, b) return a // b end function ops.i64_rem_s(a, b) return a % b end function ops.i64_and(a, b) return a & b end function ops.i64_or(a, b) return a | b end function ops.i64_xor(a, b) return a ~ b end function ops.i64_shl(a, b) return a << b end function ops.i64_shr_u(a, b) return a >> b end function ops.i64_rotl(a, b) local c = b % 64 return (a << c) | (a >> (64 - c)) end function ops.i64_rotr(a, b) local c = b % 64 return (a >> c) | (a << (64 - c)) end --[[ i32 ]] function ops.i32_eqz(a) return (a == 0) and 1 or 0 end function ops.i32_eq(a, b) return (a == b) and 1 or 0 end function ops.i32_ne(a, b) return (a ~= b) and 1 or 0 end function ops.i32_lt_s(a, b) a = intutil.signexti32(a) b = intutil.signexti32(b) return (a < b) and 1 or 0 end function ops.i32_lt_s(a, b) a = intutil.signexti32(a) b = intutil.signexti32(b) return (a < b) and 1 or 0 end function ops.i32_lt_u(a, b) return (a < b) and 1 or 0 end function ops.i32_gt_s(a, b) a = intutil.signexti32(a) b = intutil.signexti32(b) return (a > b) and 1 or 0 end function ops.i32_gt_u(a, b) return (a > b) and 1 or 0 end function ops.i32_le_s(a, b) a = intutil.signexti32(a) b = intutil.signexti32(b) return (a <= b) and 1 or 0 end function ops.i32_le_u(a, b) return (a <= b) and 1 or 0 end function ops.i32_ge_s(a, b) a = intutil.signexti32(a) b = intutil.signexti32(b) return (a >= b) and 1 or 0 end function ops.i32_ge_u(a, b) return (a >= b) and 1 or 0 end function ops.i32_clz(a) if a == 0 then return 32 end local n = 0 if (a & 0xFFFF0000) == 0 then n = n + 16 a = a << 16 end if (a & 0xFF000000) == 0 then n = n + 8 a = a << 8 end if (a & 0xF0000000) == 0 then n = n + 4 a = a << 4 end if (a & 0xC0000000) == 0 then n = n + 2 a = a << 2 end if (a & 0x80000000) == 0 then n = n + 1 end return n end function ops.i32_ctz(a) if a == 0 then return 64 end local n = 0 if (a & 0x0000FFFF) == 0 then n = n + 16 a = a >> 16 end if (a & 0x000000FF) == 0 then n = n + 8 a = a >> 8 end if (a & 0x0000000F) == 0 then n = n + 4 a = a >> 4 end if (a & 0x00000003) == 0 then n = n + 2 a = a >> 2 end if (a & 0x00000001) == 0 then n = n + 1 end return n end function ops.i32_popcnt(a) local n = 0 for _ = 1, 32 do if (a & 1) == 1 then n = n + 1 end a = a >> 1 end return n end function ops.i32_add(a, b) return (a + b) & constants.I32_MAX end function ops.i32_sub(a, b) return (a - b) & constants.I32_MAX end function ops.i32_mul(a, b) return (a * b) & constants.I32_MAX end function ops.i32_div_s(a, b) a = intutil.signexti32(a) b = intutil.signexti32(b) return (a // b) & constants.I32_MAX end function ops.i32_div_u(a, b) return (a // b) & constants.I32_MAX end function ops.i32_rem_s(a, b) a = intutil.signexti32(a) b = intutil.signexti32(b) return (a % b) & constants.I32_MAX end function ops.i32_rem_u(a, b) return (a % b) & constants.I32_MAX end function ops.i32_and(a, b) return a & b end function ops.i32_or(a, b) return a | b end function ops.i32_xor(a, b) return a ~ b end function ops.i32_shl(a, b) return (a << b) & constants.I32_MAX end function ops.i32_shr_u(a, b) return (a >> b) & constants.I32_MAX end function ops.i32_shr_s(a, b) if b >= 32 then if (a & 0x80000000) == 0 then return 0 else return constants.I32_MAX end end local result = a >> b if (a & 0x80000000) ~= 0 then result = result | (((1 << b) - 1) << (32 - b)) end return result end function ops.i32_rotl(a, b) local c = b % 32 return ((a << c) | (a >> (32 - c))) & constants.I32_MAX end function ops.i32_rotr(a, b) local c = b % 32 return ((a >> c) | (a << (32 - c))) & constants.I32_MAX end --[[ int conversions ]] function ops.i32_wrap_i64(a) return a & constants.I32_MAX end function ops.i64_extend_i32_s(a) return intutil.signexti32(a) end function ops.i64_extend_i32_u(a) return a end function ops.i32_extend8_s(a) return intutil.signexti8(a) & constants.I32_MAX end function ops.i32_extend16_s(a) return intutil.signexti16(a) & constants.I32_MAX end function ops.i64_extend8_s(a) return intutil.signexti8(a) end function ops.i64_extend16_s(a) return intutil.signexti16(a) end function ops.i64_extend32_s(a) return intutil.signexti32(a) end return ops