diff --git a/asm/opcodes.go b/asm/opcodes.go index 4a31c0c..bee6ce7 100644 --- a/asm/opcodes.go +++ b/asm/opcodes.go @@ -5,8 +5,6 @@ import "github.com/firestuff/subcoding/vm" var opCodeByName = map[string]vm.OpCodeType{ "noop": vm.OpNoOp, "nop": vm.OpNop, - "call": vm.OpCall, - "cal": vm.OpCal, "return": vm.OpReturn, "ret": vm.OpRet, @@ -48,6 +46,13 @@ var opCodeByName = map[string]vm.OpCodeType{ "jmpt": vm.OpJmpT, "jumpiffalse": vm.OpJumpIfFalse, "jmpf": vm.OpJmpF, + + "call": vm.OpCall, + "cal": vm.OpCal, + "calliftrue": vm.OpCallIfTrue, + "calt": vm.OpCalT, + "calliffalse": vm.OpCallIfFalse, + "calf": vm.OpCalF, } type operandType int @@ -61,7 +66,6 @@ const ( var operandsByOpCode = map[vm.OpCodeType][]operandType{ vm.OpNop: []operandType{}, - vm.OpCal: []operandType{s}, vm.OpRet: []operandType{}, vm.OpMov: []operandType{r, us}, @@ -84,4 +88,8 @@ var operandsByOpCode = map[vm.OpCodeType][]operandType{ vm.OpJmp: []operandType{s}, vm.OpJmpT: []operandType{s}, vm.OpJmpF: []operandType{s}, + + vm.OpCal: []operandType{s}, + vm.OpCalT: []operandType{s}, + vm.OpCalF: []operandType{s}, } diff --git a/test/opcode_test.go b/test/opcode_test.go index a4aaa74..8423770 100644 --- a/test/opcode_test.go +++ b/test/opcode_test.go @@ -11,20 +11,6 @@ functions: expectGlobalMemory(t, state, 0, 0) } -func TestCal(t *testing.T) { - state := assembleAndExecute(t, ` -functions: -- - [cal, +1] - - [add, g0, 1] - - [cal, +2] # Function doesn't exist, immediate implicit return - - [add, g0, 2] - -- - [mov, g0, 5] -`) - - expectGlobalMemory(t, state, 0, 8) -} - func TestRet(t *testing.T) { state := assembleAndExecute(t, ` functions: @@ -324,3 +310,53 @@ functions: expectGlobalMemory(t, state, 0, 5) } + +func TestCal(t *testing.T) { + state := assembleAndExecute(t, ` +functions: +- - [cal, +1] + - [add, g0, 1] + - [cal, +2] # Function doesn't exist, immediate implicit return + - [add, g0, 2] + +- - [mov, g0, 5] +`) + + expectGlobalMemory(t, state, 0, 8) +} + +func TestCalT(t *testing.T) { + state := assembleAndExecute(t, ` +functions: +- - [eq, 0, 0] + - [calt, +1] + - [add, g0, 1] + - [eq, 0, 1] + - [calt, +2] + - [add, g0, 2] + +- - [add, g0, 5] + +- - [add, g0, 13] +`) + + expectGlobalMemory(t, state, 0, 8) +} + +func TestCalF(t *testing.T) { + state := assembleAndExecute(t, ` +functions: +- - [eq, 0, 0] + - [calf, +1] + - [add, g0, 1] + - [eq, 0, 1] + - [calf, +2] + - [add, g0, 2] + +- - [add, g0, 5] + +- - [add, g0, 13] +`) + + expectGlobalMemory(t, state, 0, 16) +} diff --git a/vm/opcode.go b/vm/opcode.go index 20c583b..4056df0 100644 --- a/vm/opcode.go +++ b/vm/opcode.go @@ -5,8 +5,6 @@ type OpCodeType uint32 const ( OpNoOp OpCodeType = 0x00000000 OpNop = OpNoOp - OpCall = 0x00000001 - OpCal = OpCall OpReturn = 0x00000002 OpRet = OpReturn @@ -48,4 +46,11 @@ const ( OpJmpT = OpJumpIfTrue OpJumpIfFalse = 0x00000402 OpJmpF = OpJumpIfFalse + + OpCall = 0x00000500 + OpCal = OpCall + OpCallIfTrue = 0x00000501 + OpCalT = OpCallIfTrue + OpCallIfFalse = 0x00000502 + OpCalF = OpCallIfFalse ) diff --git a/vm/ophandler.go b/vm/ophandler.go index 5188539..9f7a426 100644 --- a/vm/ophandler.go +++ b/vm/ophandler.go @@ -4,7 +4,6 @@ type opHandler func(*State, *Instruction) var opHandlers = map[OpCodeType]opHandler{ OpNoOp: (*State).handleNoOp, - OpCall: (*State).handleCall, OpReturn: (*State).handleReturn, OpMove: (*State).handleMove, @@ -28,16 +27,15 @@ var opHandlers = map[OpCodeType]opHandler{ OpJump: (*State).handleJump, OpJumpIfTrue: (*State).handleJumpIfTrue, OpJumpIfFalse: (*State).handleJumpIfFalse, + + OpCall: (*State).handleCall, + OpCallIfTrue: (*State).handleCallIfTrue, + OpCallIfFalse: (*State).handleCallIfFalse, } func (state *State) handleNoOp(instr *Instruction) { } -func (state *State) handleCall(instr *Instruction) { - in := state.readSigned(&instr.Operand1) - state.call(in) -} - func (state *State) handleReturn(instr *Instruction) { state.ret() } @@ -147,3 +145,20 @@ func (state *State) handleJumpIfFalse(instr *Instruction) { state.handleJump(instr) } } + +func (state *State) handleCall(instr *Instruction) { + in := state.readSigned(&instr.Operand1) + state.call(in) +} + +func (state *State) handleCallIfTrue(instr *Instruction) { + if state.comparisonResult == true { + state.handleCall(instr) + } +} + +func (state *State) handleCallIfFalse(instr *Instruction) { + if state.comparisonResult == false { + state.handleCall(instr) + } +}