swamp_vm/
grid.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use 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}