2021-11-15 20:44:26 -10:00
|
|
|
package vm
|
|
|
|
|
|
2021-11-16 15:27:30 -10:00
|
|
|
type opHandler func(*State, *Instruction)
|
2021-11-15 20:44:26 -10:00
|
|
|
|
2021-11-16 15:27:30 -10:00
|
|
|
var opHandlers = map[OpCodeType]opHandler{
|
2021-11-16 15:33:03 -10:00
|
|
|
OpNoOp: (*State).handleNoOp,
|
|
|
|
|
OpReturn: (*State).handleReturn,
|
2021-11-15 20:44:26 -10:00
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
OpMove: (*State).handleMove,
|
2021-11-15 20:44:26 -10:00
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
OpAdd: (*State).handleAdd,
|
|
|
|
|
OpSubtract: (*State).handleSubtract,
|
|
|
|
|
OpMultiply: (*State).handleMultiply,
|
|
|
|
|
OpDivideUnsigned: (*State).handleDivideUnsigned,
|
|
|
|
|
OpDivideSigned: (*State).handleDivideSigned,
|
2021-11-15 20:44:26 -10:00
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
OpIsEqual: (*State).handleIsEqual,
|
|
|
|
|
OpIsLessThanUnsigned: (*State).handleIsLessThanUnsigned,
|
|
|
|
|
OpIsLessThanSigned: (*State).handleIsLessThanSigned,
|
|
|
|
|
OpIsGreaterThanUnsigned: (*State).handleIsGreaterThanUnsigned,
|
|
|
|
|
OpIsGreaterThanSigned: (*State).handleIsGreaterThanSigned,
|
|
|
|
|
OpIsLessThanOrEqualUnsigned: (*State).handleIsLessThanOrEqualUnsigned,
|
|
|
|
|
OpIsLessThanOrEqualSigned: (*State).handleIsLessThanOrEqualSigned,
|
|
|
|
|
OpIsGreaterThanOrEqualUnsigned: (*State).handleIsGreaterThanOrEqualUnsigned,
|
|
|
|
|
OpIsGreaterThanOrEqualSigned: (*State).handleIsGreaterThanOrEqualSigned,
|
2021-11-15 20:44:26 -10:00
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
OpJump: (*State).handleJump,
|
|
|
|
|
OpJumpIfTrue: (*State).handleJumpIfTrue,
|
|
|
|
|
OpJumpIfFalse: (*State).handleJumpIfFalse,
|
2021-11-15 20:44:26 -10:00
|
|
|
|
2021-11-19 16:24:04 -10:00
|
|
|
OpCall: (*State).handleCall,
|
|
|
|
|
OpCallIfTrue: (*State).handleCallIfTrue,
|
|
|
|
|
OpCallIfFalse: (*State).handleCallIfFalse,
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-19 16:24:04 -10:00
|
|
|
func (state *State) handleNoOp(instr *Instruction) {
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleReturn(instr *Instruction) {
|
2021-11-15 20:44:26 -10:00
|
|
|
state.ret()
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleMove(instr *Instruction) {
|
2021-11-16 15:13:30 -10:00
|
|
|
in := state.readUnsigned(&instr.Operand2)
|
|
|
|
|
state.writeUnsigned(&instr.Operand1, in)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleAdd(instr *Instruction) {
|
2021-11-16 15:13:30 -10:00
|
|
|
in1 := state.readUnsigned(&instr.Operand1)
|
|
|
|
|
in2 := state.readUnsigned(&instr.Operand2)
|
|
|
|
|
state.writeUnsigned(&instr.Operand1, in1+in2)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleSubtract(instr *Instruction) {
|
2021-11-16 15:13:30 -10:00
|
|
|
in1 := state.readUnsigned(&instr.Operand1)
|
|
|
|
|
in2 := state.readUnsigned(&instr.Operand2)
|
|
|
|
|
state.writeUnsigned(&instr.Operand1, in1-in2)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleMultiply(instr *Instruction) {
|
2021-11-16 15:13:30 -10:00
|
|
|
in1 := state.readUnsigned(&instr.Operand1)
|
|
|
|
|
in2 := state.readUnsigned(&instr.Operand2)
|
|
|
|
|
state.writeUnsigned(&instr.Operand1, in1*in2)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleDivideUnsigned(instr *Instruction) {
|
2021-11-16 15:13:30 -10:00
|
|
|
in1 := state.readUnsigned(&instr.Operand1)
|
|
|
|
|
in2 := state.readUnsigned(&instr.Operand2)
|
|
|
|
|
state.writeUnsigned(&instr.Operand1, in1/in2)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleDivideSigned(instr *Instruction) {
|
2021-11-16 15:13:30 -10:00
|
|
|
in1 := state.readSigned(&instr.Operand1)
|
|
|
|
|
in2 := state.readSigned(&instr.Operand2)
|
|
|
|
|
state.writeSigned(&instr.Operand1, in1/in2)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleIsEqual(instr *Instruction) {
|
2021-11-16 15:13:30 -10:00
|
|
|
in1 := state.readUnsigned(&instr.Operand1)
|
|
|
|
|
in2 := state.readUnsigned(&instr.Operand2)
|
2021-11-15 20:49:54 -10:00
|
|
|
state.comparisonResult = (in1 == in2)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleIsLessThanUnsigned(instr *Instruction) {
|
2021-11-16 15:13:30 -10:00
|
|
|
in1 := state.readUnsigned(&instr.Operand1)
|
|
|
|
|
in2 := state.readUnsigned(&instr.Operand2)
|
2021-11-15 20:49:54 -10:00
|
|
|
state.comparisonResult = (in1 < in2)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleIsLessThanSigned(instr *Instruction) {
|
2021-11-16 15:13:30 -10:00
|
|
|
in1 := state.readSigned(&instr.Operand1)
|
|
|
|
|
in2 := state.readSigned(&instr.Operand2)
|
2021-11-15 20:49:54 -10:00
|
|
|
state.comparisonResult = (in1 < in2)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleIsGreaterThanUnsigned(instr *Instruction) {
|
2021-11-16 15:13:30 -10:00
|
|
|
in1 := state.readUnsigned(&instr.Operand1)
|
|
|
|
|
in2 := state.readUnsigned(&instr.Operand2)
|
2021-11-15 20:49:54 -10:00
|
|
|
state.comparisonResult = (in1 > in2)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleIsGreaterThanSigned(instr *Instruction) {
|
2021-11-16 15:13:30 -10:00
|
|
|
in1 := state.readSigned(&instr.Operand1)
|
|
|
|
|
in2 := state.readSigned(&instr.Operand2)
|
2021-11-15 20:49:54 -10:00
|
|
|
state.comparisonResult = (in1 > in2)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleIsLessThanOrEqualUnsigned(instr *Instruction) {
|
2021-11-16 15:13:30 -10:00
|
|
|
in1 := state.readUnsigned(&instr.Operand1)
|
|
|
|
|
in2 := state.readUnsigned(&instr.Operand2)
|
2021-11-15 20:49:54 -10:00
|
|
|
state.comparisonResult = (in1 <= in2)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleIsLessThanOrEqualSigned(instr *Instruction) {
|
2021-11-16 15:13:30 -10:00
|
|
|
in1 := state.readSigned(&instr.Operand1)
|
|
|
|
|
in2 := state.readSigned(&instr.Operand2)
|
2021-11-15 20:49:54 -10:00
|
|
|
state.comparisonResult = (in1 <= in2)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleIsGreaterThanOrEqualUnsigned(instr *Instruction) {
|
2021-11-16 15:13:30 -10:00
|
|
|
in1 := state.readUnsigned(&instr.Operand1)
|
|
|
|
|
in2 := state.readUnsigned(&instr.Operand2)
|
2021-11-15 20:49:54 -10:00
|
|
|
state.comparisonResult = (in1 >= in2)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleIsGreaterThanOrEqualSigned(instr *Instruction) {
|
2021-11-16 15:13:30 -10:00
|
|
|
in1 := state.readSigned(&instr.Operand1)
|
|
|
|
|
in2 := state.readSigned(&instr.Operand2)
|
2021-11-15 20:49:54 -10:00
|
|
|
state.comparisonResult = (in1 >= in2)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleJump(instr *Instruction) {
|
2021-11-16 15:13:30 -10:00
|
|
|
in := state.readSigned(&instr.Operand1)
|
2021-11-16 15:33:03 -10:00
|
|
|
state.jump(in)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleJumpIfTrue(instr *Instruction) {
|
2021-11-15 20:49:54 -10:00
|
|
|
if state.comparisonResult == true {
|
2021-11-16 15:33:03 -10:00
|
|
|
state.handleJump(instr)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-16 15:33:03 -10:00
|
|
|
func (state *State) handleJumpIfFalse(instr *Instruction) {
|
2021-11-15 20:49:54 -10:00
|
|
|
if state.comparisonResult == false {
|
2021-11-16 15:33:03 -10:00
|
|
|
state.handleJump(instr)
|
2021-11-15 20:44:26 -10:00
|
|
|
}
|
|
|
|
|
}
|
2021-11-19 16:24:04 -10:00
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
}
|