Files
subcoding/vm/ophandler.go

243 lines
7.1 KiB
Go
Raw Normal View History

2021-11-15 20:44:26 -10:00
package vm
import "fmt"
2021-11-21 17:04:58 -08:00
import "math"
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-19 16:30:11 -10:00
OpNoOp: (*State).handleNoOp,
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-19 16:43:59 -10:00
OpNot: (*State).handleNot,
OpAnd: (*State).handleAnd,
OpOr: (*State).handleOr,
OpXor: (*State).handleXor,
2021-11-19 17:04:11 -10:00
OpShiftRight: (*State).handleShiftRight,
OpShiftLeft: (*State).handleShiftLeft,
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:30:11 -10:00
OpReturn: (*State).handleReturn,
OpReturnIfTrue: (*State).handleReturnIfTrue,
OpReturnIfFalse: (*State).handleReturnIfFalse,
2021-11-21 17:04:58 -08:00
OpSqrt: (*State).handleSqrt,
2021-11-15 20:44:26 -10:00
}
2021-11-19 16:30:11 -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) handleMove(instr *Instruction) {
2021-11-20 09:46:51 -10:00
in := state.readUnsigned(instr.Operands[1])
state.writeUnsigned(instr.Operands[0], 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-20 09:46:51 -10:00
in1 := state.readUnsigned(instr.Operands[0])
in2 := state.readUnsigned(instr.Operands[1])
state.writeUnsigned(instr.Operands[0], 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-20 09:46:51 -10:00
in1 := state.readUnsigned(instr.Operands[0])
in2 := state.readUnsigned(instr.Operands[1])
state.writeUnsigned(instr.Operands[0], 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-20 09:46:51 -10:00
in1 := state.readUnsigned(instr.Operands[0])
in2 := state.readUnsigned(instr.Operands[1])
state.writeUnsigned(instr.Operands[0], 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-20 09:46:51 -10:00
in1 := state.readUnsigned(instr.Operands[0])
in2 := state.readUnsigned(instr.Operands[1])
if in2 == 0 {
state.setError(fmt.Errorf("Divide by zero"))
} else {
state.writeUnsigned(instr.Operands[0], 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-20 09:46:51 -10:00
in1 := state.readSigned(instr.Operands[0])
in2 := state.readSigned(instr.Operands[1])
if in2 == 0 {
state.setError(fmt.Errorf("Divide by zero"))
} else {
state.writeSigned(instr.Operands[0], in1/in2)
}
2021-11-15 20:44:26 -10:00
}
2021-11-19 16:43:59 -10:00
func (state *State) handleNot(instr *Instruction) {
2021-11-20 09:46:51 -10:00
in := state.readUnsigned(instr.Operands[0])
state.writeUnsigned(instr.Operands[0], ^in)
2021-11-19 16:43:59 -10:00
}
func (state *State) handleAnd(instr *Instruction) {
2021-11-20 09:46:51 -10:00
in1 := state.readUnsigned(instr.Operands[0])
in2 := state.readUnsigned(instr.Operands[1])
state.writeUnsigned(instr.Operands[0], in1&in2)
2021-11-19 16:43:59 -10:00
}
func (state *State) handleOr(instr *Instruction) {
2021-11-20 09:46:51 -10:00
in1 := state.readUnsigned(instr.Operands[0])
in2 := state.readUnsigned(instr.Operands[1])
state.writeUnsigned(instr.Operands[0], in1|in2)
2021-11-19 16:43:59 -10:00
}
func (state *State) handleXor(instr *Instruction) {
2021-11-20 09:46:51 -10:00
in1 := state.readUnsigned(instr.Operands[0])
in2 := state.readUnsigned(instr.Operands[1])
state.writeUnsigned(instr.Operands[0], in1^in2)
2021-11-19 16:43:59 -10:00
}
2021-11-19 17:04:11 -10:00
func (state *State) handleShiftRight(instr *Instruction) {
2021-11-20 09:46:51 -10:00
in1 := state.readUnsigned(instr.Operands[0])
in2 := state.readUnsigned(instr.Operands[1])
state.writeUnsigned(instr.Operands[0], in1>>in2)
2021-11-19 17:04:11 -10:00
}
func (state *State) handleShiftLeft(instr *Instruction) {
2021-11-20 09:46:51 -10:00
in1 := state.readUnsigned(instr.Operands[0])
in2 := state.readUnsigned(instr.Operands[1])
state.writeUnsigned(instr.Operands[0], in1<<in2)
2021-11-19 17:04:11 -10:00
}
2021-11-16 15:33:03 -10:00
func (state *State) handleIsEqual(instr *Instruction) {
2021-11-20 09:46:51 -10:00
in1 := state.readUnsigned(instr.Operands[0])
in2 := state.readUnsigned(instr.Operands[1])
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-20 09:46:51 -10:00
in1 := state.readUnsigned(instr.Operands[0])
in2 := state.readUnsigned(instr.Operands[1])
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-20 09:46:51 -10:00
in1 := state.readSigned(instr.Operands[0])
in2 := state.readSigned(instr.Operands[1])
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-20 09:46:51 -10:00
in1 := state.readUnsigned(instr.Operands[0])
in2 := state.readUnsigned(instr.Operands[1])
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-20 09:46:51 -10:00
in1 := state.readSigned(instr.Operands[0])
in2 := state.readSigned(instr.Operands[1])
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-20 09:46:51 -10:00
in1 := state.readUnsigned(instr.Operands[0])
in2 := state.readUnsigned(instr.Operands[1])
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-20 09:46:51 -10:00
in1 := state.readSigned(instr.Operands[0])
in2 := state.readSigned(instr.Operands[1])
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-20 09:46:51 -10:00
in1 := state.readUnsigned(instr.Operands[0])
in2 := state.readUnsigned(instr.Operands[1])
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-20 09:46:51 -10:00
in1 := state.readSigned(instr.Operands[0])
in2 := state.readSigned(instr.Operands[1])
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-20 09:46:51 -10:00
in := state.readSigned(instr.Operands[0])
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) {
2021-11-20 09:46:51 -10:00
in := state.readSigned(instr.Operands[0])
2021-11-19 16:24:04 -10:00
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)
}
}
2021-11-19 16:30:11 -10:00
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)
}
}
2021-11-21 17:04:58 -08:00
func (state *State) handleSqrt(instr *Instruction) {
in := state.readUnsigned(instr.Operands[0])
state.writeUnsigned(instr.Operands[0], uint64(math.Round(math.Sqrt(float64(in)))))
}