diff --git a/memory.go b/memory.go new file mode 100644 index 0000000..bd38168 --- /dev/null +++ b/memory.go @@ -0,0 +1,39 @@ +package vm + +import "fmt" + +type memory struct { + entries []uint64 +} + +func newMemory(size uint64) *memory { + return &memory{ + entries: make([]uint64, size), + } +} + +func (mem *memory) readUnsigned(index uint64) (uint64, error) { + if index >= uint64(len(mem.entries)) { + return 0, fmt.Errorf("Invalid memory index: %016x", index) + } + + return mem.entries[index], nil +} + +func (mem *memory) mustReadUnsigned(index uint64) uint64 { + value, err := mem.readUnsigned(index) + if err != nil { + panic(err) + } + return value +} + +func (mem *memory) writeUnsigned(index uint64, value uint64) error { + if index >= uint64(len(mem.entries)) { + return fmt.Errorf("Invalid memory index: %016x", index) + } + + mem.entries[index] = value + + return nil +} diff --git a/state.go b/state.go index 89c0ae3..944ab53 100644 --- a/state.go +++ b/state.go @@ -15,13 +15,14 @@ type State struct { instructionIndex int64 comparisonResult bool - globalMemory [globalMemoryEntries]uint64 + globalMemory *memory stack []*stackFrame } func NewState(functions [][]*Instruction) (*State, error) { return &State{ - functions: functions, + functions: functions, + globalMemory: newMemory(globalMemoryEntries), }, nil } @@ -97,11 +98,11 @@ func (state *State) readUnsigned(op *Operand) uint64 { return state.stackFrame().functionMemory[op.Value] case GlobalMemoryIndex: - if op.Value >= globalMemoryEntries { - state.setError(fmt.Errorf("Invalid global memory index: %016x", op.Value)) - return 0 + value, err := state.globalMemory.readUnsigned(op.Value) + if err != nil { + state.setError(err) } - return state.globalMemory[op.Value] + return value default: state.setError(fmt.Errorf("Unknown operand type: 0x%02x", op.Type)) @@ -126,11 +127,10 @@ func (state *State) writeUnsigned(op *Operand, value uint64) { state.stackFrame().functionMemory[op.Value] = value case GlobalMemoryIndex: - if op.Value >= globalMemoryEntries { - state.setError(fmt.Errorf("Invalid global memory index: %016x", op.Value)) - return + err := state.globalMemory.writeUnsigned(op.Value, value) + if err != nil { + state.setError(err) } - state.globalMemory[op.Value] = value default: state.setError(fmt.Errorf("Unknown operand type: 0x%02x", op.Type)) diff --git a/state_test.go b/state_test.go index 9ff064a..c23d147 100644 --- a/state_test.go +++ b/state_test.go @@ -41,7 +41,7 @@ func TestFirst(t *testing.T) { t.Fatal(state) } - if state.globalMemory[0] != 3 { - t.Fatal(state.globalMemory[0]) + if state.globalMemory.mustReadUnsigned(0) != 3 { + t.Fatal(state.globalMemory.mustReadUnsigned(0)) } }