diff --git a/main.go b/main.go index 54edfc7..25481dd 100644 --- a/main.go +++ b/main.go @@ -17,6 +17,8 @@ const ( ) const InstructionBytes = 32 +const GlobalMemoryEntries = 16 +const FunctionMemoryEntries = 16 type Operand struct { Type OperandType @@ -39,15 +41,14 @@ type State struct { InstructionIndex int64 ComparisonResult bool - GlobalMemory [16]uint64 + GlobalMemory [GlobalMemoryEntries]uint64 Stack []*StackFrame - StackFrame *StackFrame } type StackFrame struct { PreviousFunctionIndex int64 PreviousInstructionIndex int64 - FunctionMemory [16]uint64 + FunctionMemory [FunctionMemoryEntries]uint64 } type OpHandler func(*State, *Instruction) @@ -86,15 +87,26 @@ func NewState(functionByteCode [][]byte) *State { } } +func (state *State) StackFrame() *StackFrame { + return state.Stack[len(state.Stack) - 1] +} + +func (state *State) Function() []byte { + return state.FunctionByteCode[state.FunctionIndex] +} + func (state *State) Execute() { state.call(0) for len(state.Stack) > 0 && state.Error == nil { - fnc := state.FunctionByteCode[state.FunctionIndex] start := state.InstructionIndex * InstructionBytes - chunk := fnc[start : start+InstructionBytes] + chunk := state.Function()[start : start+InstructionBytes] state.InstructionIndex += 1 state.ProcessInstruction(chunk) + + if state.InstructionIndex >= int64(len(state.Function()) / InstructionBytes) { + state.ret() + } } if state.Error != nil { @@ -128,10 +140,21 @@ func (state *State) ReadUnsigned(op *Operand) uint64 { switch op.Type { case Literal: return op.Value + case FunctionMemoryIndex: - return state.StackFrame.FunctionMemory[op.Value] + if op.Value >= FunctionMemoryEntries { + state.Error = fmt.Errorf("Invalid function memory index: %016x", op.Value) + return 0 + } + return state.StackFrame().FunctionMemory[op.Value] + case GlobalMemoryIndex: + if op.Value >= GlobalMemoryEntries { + state.Error = fmt.Errorf("Invalid global memory index: %016x", op.Value) + return 0 + } return state.GlobalMemory[op.Value] + default: state.Error = fmt.Errorf("Unknown operand type: 0x%02x", op.Type) return 0 @@ -146,10 +169,21 @@ func (state *State) WriteUnsigned(op *Operand, value uint64) { switch op.Type { case Literal: state.Error = fmt.Errorf("Write to literal operand") + case FunctionMemoryIndex: - state.StackFrame.FunctionMemory[op.Value] = value + if op.Value >= FunctionMemoryEntries { + state.Error = fmt.Errorf("Invalid function memory index: %016x", op.Value) + return + } + state.StackFrame().FunctionMemory[op.Value] = value + case GlobalMemoryIndex: + if op.Value >= GlobalMemoryEntries { + state.Error = fmt.Errorf("Invalid global memory index: %016x", op.Value) + return + } state.GlobalMemory[op.Value] = value + default: state.Error = fmt.Errorf("Unknown operand type: 0x%02x", op.Type) } @@ -170,24 +204,29 @@ func (state *State) Call(instr *Instruction) { } func (state *State) call(functionOffset int64) { + if state.FunctionIndex + functionOffset >= int64(len(state.FunctionByteCode)) { + state.Error = fmt.Errorf("Invalid function call index: %d + %d = %d", state.FunctionIndex, functionOffset, state.FunctionIndex + functionOffset) + return + } + stackFrame := &StackFrame{ PreviousFunctionIndex: state.FunctionIndex, PreviousInstructionIndex: state.InstructionIndex, } state.Stack = append(state.Stack, stackFrame) - state.StackFrame = stackFrame state.FunctionIndex += functionOffset state.InstructionIndex = 0 } func (state *State) Return(instr *Instruction) { fmt.Printf("Return\n") - state.FunctionIndex = state.StackFrame.PreviousFunctionIndex - state.InstructionIndex = state.StackFrame.PreviousInstructionIndex + state.ret() +} + +func (state *State) ret() { + state.FunctionIndex = state.StackFrame().PreviousFunctionIndex + state.InstructionIndex = state.StackFrame().PreviousInstructionIndex state.Stack = state.Stack[:len(state.Stack)-1] - if len(state.Stack) > 0 { - state.StackFrame = state.Stack[len(state.Stack)-1] - } } func (state *State) Move(instr *Instruction) { @@ -321,11 +360,9 @@ func main() { "0000000100000000000000000000000000000001000000000000000000000000", "0000030100000000010000000000000000000000000000000000000000000003", "000004010000000000000000fffffffffffffffd000000000000000000000000", - "0000000200000000000000000000000000000000000000000000000000000000", }, []string{ "0000020000000000020000000000000000000000000000000000000000000001", - "0000000200000000000000000000000000000000000000000000000000000000", }, }