Add conditional call instructions

This commit is contained in:
Ian Gulliver
2021-11-19 16:24:04 -10:00
parent 6e36152b6a
commit 7a24eee583
4 changed files with 89 additions and 25 deletions

View File

@@ -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},
}

View File

@@ -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)
}

View File

@@ -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
)

View File

@@ -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)
}
}