From 50f986fb136a9562c99f68a9855fb6d26d735861 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Fri, 19 Nov 2021 16:30:11 -1000 Subject: [PATCH] Conditional return instructions --- asm/opcodes.go | 18 +++++++++---- test/opcode_test.go | 66 ++++++++++++++++++++++++++++++++++----------- vm/opcode.go | 13 ++++++--- vm/ophandler.go | 27 ++++++++++++++----- 4 files changed, 94 insertions(+), 30 deletions(-) diff --git a/asm/opcodes.go b/asm/opcodes.go index bee6ce7..d0384e4 100644 --- a/asm/opcodes.go +++ b/asm/opcodes.go @@ -3,10 +3,8 @@ package asm import "github.com/firestuff/subcoding/vm" var opCodeByName = map[string]vm.OpCodeType{ - "noop": vm.OpNoOp, - "nop": vm.OpNop, - "return": vm.OpReturn, - "ret": vm.OpRet, + "noop": vm.OpNoOp, + "nop": vm.OpNop, "move": vm.OpMove, "mov": vm.OpMov, @@ -53,6 +51,13 @@ var opCodeByName = map[string]vm.OpCodeType{ "calt": vm.OpCalT, "calliffalse": vm.OpCallIfFalse, "calf": vm.OpCalF, + + "return": vm.OpReturn, + "ret": vm.OpRet, + "returniftrue": vm.OpReturnIfTrue, + "rett": vm.OpRetT, + "returniffalse": vm.OpReturnIfFalse, + "retf": vm.OpRetF, } type operandType int @@ -66,7 +71,6 @@ const ( var operandsByOpCode = map[vm.OpCodeType][]operandType{ vm.OpNop: []operandType{}, - vm.OpRet: []operandType{}, vm.OpMov: []operandType{r, us}, vm.OpAdd: []operandType{r, us}, @@ -92,4 +96,8 @@ var operandsByOpCode = map[vm.OpCodeType][]operandType{ vm.OpCal: []operandType{s}, vm.OpCalT: []operandType{s}, vm.OpCalF: []operandType{s}, + + vm.OpRet: []operandType{}, + vm.OpRetT: []operandType{}, + vm.OpRetF: []operandType{}, } diff --git a/test/opcode_test.go b/test/opcode_test.go index 8423770..8359890 100644 --- a/test/opcode_test.go +++ b/test/opcode_test.go @@ -11,21 +11,6 @@ functions: expectGlobalMemory(t, state, 0, 0) } -func TestRet(t *testing.T) { - state := assembleAndExecute(t, ` -functions: -- - [cal, +1] - - [add, g0, 1] - - [ret] - -- - [mov, g0, 5] - - [ret] - - [add, g0, 2] -`) - - expectGlobalMemory(t, state, 0, 6) -} - func TestMov(t *testing.T) { state := assembleAndExecute(t, ` functions: @@ -360,3 +345,54 @@ functions: expectGlobalMemory(t, state, 0, 16) } + +func TestRet(t *testing.T) { + state := assembleAndExecute(t, ` +functions: +- - [cal, +1] + - [add, g0, 1] + - [ret] + +- - [mov, g0, 5] + - [ret] + - [add, g0, 2] +`) + + expectGlobalMemory(t, state, 0, 6) +} + +func TestRetT(t *testing.T) { + state := assembleAndExecute(t, ` +functions: +- - [cal, +1] + - [add, g0, 1] + +- - [add, g0, 2] + - [eq, 0, 0] + - [rett] + - [add, g0, 4] + - [eq, 0, 1] + - [rett] + - [add, g0, 8] +`) + + expectGlobalMemory(t, state, 0, 3) +} + +func TestRetF(t *testing.T) { + state := assembleAndExecute(t, ` +functions: +- - [cal, +1] + - [add, g0, 1] + +- - [add, g0, 2] + - [eq, 0, 0] + - [retf] + - [add, g0, 4] + - [eq, 0, 1] + - [retf] + - [add, g0, 8] +`) + + expectGlobalMemory(t, state, 0, 7) +} diff --git a/vm/opcode.go b/vm/opcode.go index 4056df0..956ba33 100644 --- a/vm/opcode.go +++ b/vm/opcode.go @@ -3,10 +3,8 @@ package vm type OpCodeType uint32 const ( - OpNoOp OpCodeType = 0x00000000 - OpNop = OpNoOp - OpReturn = 0x00000002 - OpRet = OpReturn + OpNoOp OpCodeType = 0x00000000 + OpNop = OpNoOp OpMove = 0x00000100 OpMov = OpMove @@ -53,4 +51,11 @@ const ( OpCalT = OpCallIfTrue OpCallIfFalse = 0x00000502 OpCalF = OpCallIfFalse + + OpReturn = 0x00000600 + OpRet = OpReturn + OpReturnIfTrue = 0x00000601 + OpRetT = OpReturnIfTrue + OpReturnIfFalse = 0x00000602 + OpRetF = OpReturnIfFalse ) diff --git a/vm/ophandler.go b/vm/ophandler.go index 9f7a426..330ab93 100644 --- a/vm/ophandler.go +++ b/vm/ophandler.go @@ -3,8 +3,7 @@ package vm type opHandler func(*State, *Instruction) var opHandlers = map[OpCodeType]opHandler{ - OpNoOp: (*State).handleNoOp, - OpReturn: (*State).handleReturn, + OpNoOp: (*State).handleNoOp, OpMove: (*State).handleMove, @@ -31,15 +30,15 @@ var opHandlers = map[OpCodeType]opHandler{ OpCall: (*State).handleCall, OpCallIfTrue: (*State).handleCallIfTrue, OpCallIfFalse: (*State).handleCallIfFalse, + + OpReturn: (*State).handleReturn, + OpReturnIfTrue: (*State).handleReturnIfTrue, + OpReturnIfFalse: (*State).handleReturnIfFalse, } func (state *State) handleNoOp(instr *Instruction) { } -func (state *State) handleReturn(instr *Instruction) { - state.ret() -} - func (state *State) handleMove(instr *Instruction) { in := state.readUnsigned(&instr.Operand2) state.writeUnsigned(&instr.Operand1, in) @@ -162,3 +161,19 @@ func (state *State) handleCallIfFalse(instr *Instruction) { state.handleCall(instr) } } + +func (state *State) handleReturn(instr *Instruction) { + state.ret() +} + +func (state *State) handleReturnIfTrue(instr *Instruction) { + if state.comparisonResult == true { + state.handleReturn(instr) + } +} + +func (state *State) handleReturnIfFalse(instr *Instruction) { + if state.comparisonResult == false { + state.handleReturn(instr) + } +}