use crate::{
AddressOffset, DataSegmentIdx, I64ValueSplit, InstructionSet, TrapCode, N_BYTES_PER_MEMORY_PAGE,
};
use rwasm_fuel_policy::{MEMORY_BYTES_PER_FUEL, MEMORY_BYTES_PER_FUEL_LOG2};
impl InstructionSet {
pub const MSH_I64_LOAD: u32 = 2;
pub const MSH_I64_LOAD8_S: u32 = 1;
pub const MSH_I64_LOAD8_U: u32 = 1;
pub const MSH_I64_LOAD16_S: u32 = 1;
pub const MSH_I64_LOAD16_U: u32 = 1;
pub const MSH_I64_LOAD32_S: u32 = 1;
pub const MSH_I64_LOAD32_U: u32 = 1;
pub const MSH_I64_STORE: u32 = 2;
pub const MSH_I64_STORE8: u32 = 0;
pub const MSH_I64_STORE16: u32 = 0;
pub const MSH_I64_STORE32: u32 = 0;
pub const MSH_I64_CONST: u32 = 2;
pub const MSH_MEMORY_GROW_CHECKED: u32 = 2;
pub const MSH_MEMORY_FILL_CHECKED: u32 = 2;
pub const MSH_MEMORY_COPY_CHECKED: u32 = 2;
pub const MSH_MEMORY_INIT_CHECKED: u32 = 2;
pub fn op_i64_load(&mut self, offset: AddressOffset) {
self.op_local_get(1);
self.op_i32_load(offset.saturating_add(4));
self.op_local_get(2);
self.op_i32_load(offset);
self.op_local_set(2);
}
pub fn op_i64_load8_s(&mut self, offset: AddressOffset) {
self.op_i32_load8_s(offset);
self.op_dup();
self.op_i32_const(31);
self.op_i32_shr_s();
}
pub fn op_i64_load8_u(&mut self, offset: AddressOffset) {
self.op_i32_load8_u(offset);
self.op_i32_const(0);
}
pub fn op_i64_load16_s(&mut self, offset: AddressOffset) {
self.op_i32_load16_s(offset);
self.op_dup();
self.op_i32_const(31);
self.op_i32_shr_s();
}
pub fn op_i64_load16_u(&mut self, offset: AddressOffset) {
self.op_i32_load16_u(offset);
self.op_i32_const(0);
}
pub fn op_i64_load32_s(&mut self, offset: AddressOffset) {
self.op_i32_load(offset);
self.op_dup();
self.op_i32_const(31);
self.op_i32_shr_s();
}
pub fn op_i64_load32_u(&mut self, offset: AddressOffset) {
self.op_i32_load(offset);
self.op_i32_const(0);
}
pub fn op_i64_store(&mut self, offset: AddressOffset) {
self.op_local_get(3);
self.op_local_get(2);
self.op_i32_store(offset.saturating_add(4));
self.op_drop();
self.op_i32_store(offset);
}
pub fn op_i64_store8(&mut self, offset: AddressOffset) {
self.op_drop();
self.op_i32_store8(offset);
}
pub fn op_i64_store16(&mut self, offset: AddressOffset) {
self.op_drop();
self.op_i32_store16(offset);
}
pub fn op_i64_store32(&mut self, offset: AddressOffset) {
self.op_drop();
self.op_i32_store(offset);
}
pub fn op_i64_const(&mut self, value: i64) {
let (lo, hi) = value.split_into_i32_tuple();
self.op_i32_const(lo); self.op_i32_const(hi); }
pub fn op_memory_grow_checked(&mut self, max_pages: Option<u32>, inject_fuel_check: bool) {
if let Some(max_pages) = max_pages {
self.op_local_get(1); self.op_memory_size(); self.op_i32_add(); self.op_i32_const(max_pages); self.op_i32_gt_s(); self.op_br_if_eqz(4);
self.op_drop();
self.op_i32_const(u32::MAX);
self.op_br(if inject_fuel_check { 8 } else { 2 });
}
if inject_fuel_check {
self.op_local_get(1); self.op_i32_const(N_BYTES_PER_MEMORY_PAGE); self.op_i32_mul(); self.op_i32_const(MEMORY_BYTES_PER_FUEL_LOG2); self.op_i32_shr_u(); self.op_consume_fuel_stack();
}
self.op_memory_grow();
}
pub fn op_memory_fill_checked(&mut self, inject_fuel_check: bool) {
if inject_fuel_check {
self.op_local_get(1); self.op_i32_const(MEMORY_BYTES_PER_FUEL - 1); self.op_i32_add(); self.op_i32_const(MEMORY_BYTES_PER_FUEL_LOG2); self.op_i32_shr_u(); self.op_consume_fuel_stack();
}
self.op_memory_fill();
}
pub fn op_memory_copy_checked(&mut self, inject_fuel_check: bool) {
if inject_fuel_check {
self.op_local_get(1); self.op_i32_const(MEMORY_BYTES_PER_FUEL - 1); self.op_i32_add(); self.op_i32_const(MEMORY_BYTES_PER_FUEL_LOG2); self.op_i32_shr_u(); self.op_consume_fuel_stack();
}
self.op_memory_copy();
}
pub fn op_memory_init_checked(
&mut self,
rewrite_offset: Option<u32>,
rewrite_length: Option<u32>,
data_segment_index: DataSegmentIdx,
inject_fuel_check: bool,
) {
if let Some(length) = rewrite_length.filter(|v| *v > 0) {
self.op_local_get(1); self.op_local_get(3); self.op_i32_add(); self.op_i32_const(length);
self.op_i32_gt_s(); self.op_br_if_eqz(2);
self.op_trap(TrapCode::MemoryOutOfBounds);
}
if let Some(offset) = rewrite_offset.filter(|v| *v > 0) {
self.op_i32_const(offset);
self.op_local_get(3);
self.op_i32_add();
self.op_local_set(2);
}
if inject_fuel_check {
self.op_local_get(1); self.op_i32_const(MEMORY_BYTES_PER_FUEL - 1); self.op_i32_add(); self.op_i32_const(MEMORY_BYTES_PER_FUEL_LOG2); self.op_i32_shr_u(); self.op_consume_fuel_stack();
}
self.op_memory_init(data_segment_index);
}
}