1use crate::{TrapCode, Vm, get_reg, set_reg, u16_from_u8s};
6use swamp_vm_isa::{GRID_HEADER_PAYLOAD_OFFSET, GRID_SECRET_CODE, GridHeader};
7
8impl Vm {
9 pub fn execute_grid_init(
10 &mut self,
11 dest_reg: u8,
12 element_size_reg: u8,
13 width_lower: u8,
14 width_upper: u8,
15 height_lower: u8,
16 height_upper: u8,
17 ) {
18 let element_size = get_reg!(self, element_size_reg);
19 let width = u16_from_u8s!(width_lower, width_upper);
20 debug_assert!(width < 1024);
21 let height = u16_from_u8s!(height_lower, height_upper);
22 debug_assert!(height < 1024);
23
24 unsafe {
25 let dest_addr = get_reg!(self, dest_reg);
26 let grid_header = self.memory.get_heap_ptr(dest_addr as usize) as *mut GridHeader;
27 (*grid_header).width = width;
28 (*grid_header).height = height;
29 (*grid_header).element_size = element_size;
30 (*grid_header).capacity = width * height;
31 (*grid_header).element_count = width * height;
32 (*grid_header).padding = GRID_SECRET_CODE;
33 }
34 }
35
36 pub fn execute_grid_get_entry_addr(
37 &mut self,
38 dest_reg: u8,
39 self_addr_reg: u8,
40 x_reg: u8,
41 y_reg: u8,
42 element_lower: u8,
43 element_upper: u8,
44 ) {
45 unsafe {
46 let grid_header_addr = get_reg!(self, self_addr_reg);
47 let grid_header =
48 self.memory.get_heap_const_ptr(grid_header_addr as usize) as *mut GridHeader;
49
50 if (*grid_header).padding != GRID_SECRET_CODE {
51 return self.internal_trap(TrapCode::MemoryCorruption);
52 }
53
54 let x_value = get_reg!(self, x_reg);
55 if x_value >= (*grid_header).width as u32 {
56 return self.internal_trap(TrapCode::GridBoundsXFail {
57 x: x_value,
58 width: (*grid_header).width,
59 });
60 }
61
62 let y_value = get_reg!(self, y_reg);
63 if y_value >= (*grid_header).height as u32 {
64 return self.internal_trap(TrapCode::GridBoundsYFail {
65 y: y_value,
66 height: (*grid_header).height,
67 });
68 }
69
70 let index = y_value * (*grid_header).width as u32 + x_value;
71
72 if index > ((*grid_header).height * (*grid_header).width) as u32 {
73 return self.internal_trap(TrapCode::GridBoundsFail);
74 }
75
76 let element_size = u16_from_u8s!(element_lower, element_upper) as u32;
77 debug_assert!(element_size < 1024);
78
79 let element_offset = index * element_size;
80 let entry_addr = grid_header_addr + GRID_HEADER_PAYLOAD_OFFSET.0 + element_offset;
81 set_reg!(self, dest_reg, entry_addr);
82 }
83 }
84}