Conditional return instructions

This commit is contained in:
Ian Gulliver
2021-11-19 16:30:11 -10:00
parent 7a24eee583
commit 50f986fb13
4 changed files with 94 additions and 30 deletions

View File

@@ -5,8 +5,6 @@ import "github.com/firestuff/subcoding/vm"
var opCodeByName = map[string]vm.OpCodeType{ var opCodeByName = map[string]vm.OpCodeType{
"noop": vm.OpNoOp, "noop": vm.OpNoOp,
"nop": vm.OpNop, "nop": vm.OpNop,
"return": vm.OpReturn,
"ret": vm.OpRet,
"move": vm.OpMove, "move": vm.OpMove,
"mov": vm.OpMov, "mov": vm.OpMov,
@@ -53,6 +51,13 @@ var opCodeByName = map[string]vm.OpCodeType{
"calt": vm.OpCalT, "calt": vm.OpCalT,
"calliffalse": vm.OpCallIfFalse, "calliffalse": vm.OpCallIfFalse,
"calf": vm.OpCalF, "calf": vm.OpCalF,
"return": vm.OpReturn,
"ret": vm.OpRet,
"returniftrue": vm.OpReturnIfTrue,
"rett": vm.OpRetT,
"returniffalse": vm.OpReturnIfFalse,
"retf": vm.OpRetF,
} }
type operandType int type operandType int
@@ -66,7 +71,6 @@ const (
var operandsByOpCode = map[vm.OpCodeType][]operandType{ var operandsByOpCode = map[vm.OpCodeType][]operandType{
vm.OpNop: []operandType{}, vm.OpNop: []operandType{},
vm.OpRet: []operandType{},
vm.OpMov: []operandType{r, us}, vm.OpMov: []operandType{r, us},
vm.OpAdd: []operandType{r, us}, vm.OpAdd: []operandType{r, us},
@@ -92,4 +96,8 @@ var operandsByOpCode = map[vm.OpCodeType][]operandType{
vm.OpCal: []operandType{s}, vm.OpCal: []operandType{s},
vm.OpCalT: []operandType{s}, vm.OpCalT: []operandType{s},
vm.OpCalF: []operandType{s}, vm.OpCalF: []operandType{s},
vm.OpRet: []operandType{},
vm.OpRetT: []operandType{},
vm.OpRetF: []operandType{},
} }

View File

@@ -11,21 +11,6 @@ functions:
expectGlobalMemory(t, state, 0, 0) 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) { func TestMov(t *testing.T) {
state := assembleAndExecute(t, ` state := assembleAndExecute(t, `
functions: functions:
@@ -360,3 +345,54 @@ functions:
expectGlobalMemory(t, state, 0, 16) 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)
}

View File

@@ -5,8 +5,6 @@ type OpCodeType uint32
const ( const (
OpNoOp OpCodeType = 0x00000000 OpNoOp OpCodeType = 0x00000000
OpNop = OpNoOp OpNop = OpNoOp
OpReturn = 0x00000002
OpRet = OpReturn
OpMove = 0x00000100 OpMove = 0x00000100
OpMov = OpMove OpMov = OpMove
@@ -53,4 +51,11 @@ const (
OpCalT = OpCallIfTrue OpCalT = OpCallIfTrue
OpCallIfFalse = 0x00000502 OpCallIfFalse = 0x00000502
OpCalF = OpCallIfFalse OpCalF = OpCallIfFalse
OpReturn = 0x00000600
OpRet = OpReturn
OpReturnIfTrue = 0x00000601
OpRetT = OpReturnIfTrue
OpReturnIfFalse = 0x00000602
OpRetF = OpReturnIfFalse
) )

View File

@@ -4,7 +4,6 @@ type opHandler func(*State, *Instruction)
var opHandlers = map[OpCodeType]opHandler{ var opHandlers = map[OpCodeType]opHandler{
OpNoOp: (*State).handleNoOp, OpNoOp: (*State).handleNoOp,
OpReturn: (*State).handleReturn,
OpMove: (*State).handleMove, OpMove: (*State).handleMove,
@@ -31,15 +30,15 @@ var opHandlers = map[OpCodeType]opHandler{
OpCall: (*State).handleCall, OpCall: (*State).handleCall,
OpCallIfTrue: (*State).handleCallIfTrue, OpCallIfTrue: (*State).handleCallIfTrue,
OpCallIfFalse: (*State).handleCallIfFalse, OpCallIfFalse: (*State).handleCallIfFalse,
OpReturn: (*State).handleReturn,
OpReturnIfTrue: (*State).handleReturnIfTrue,
OpReturnIfFalse: (*State).handleReturnIfFalse,
} }
func (state *State) handleNoOp(instr *Instruction) { func (state *State) handleNoOp(instr *Instruction) {
} }
func (state *State) handleReturn(instr *Instruction) {
state.ret()
}
func (state *State) handleMove(instr *Instruction) { func (state *State) handleMove(instr *Instruction) {
in := state.readUnsigned(&instr.Operand2) in := state.readUnsigned(&instr.Operand2)
state.writeUnsigned(&instr.Operand1, in) state.writeUnsigned(&instr.Operand1, in)
@@ -162,3 +161,19 @@ func (state *State) handleCallIfFalse(instr *Instruction) {
state.handleCall(instr) 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)
}
}