Split files

This commit is contained in:
Ian Gulliver
2021-11-15 20:44:26 -10:00
parent be6b726851
commit 6b1da92a3a
6 changed files with 254 additions and 291 deletions

30
instruction.go Normal file
View File

@@ -0,0 +1,30 @@
package vm
import "bytes"
import "github.com/lunixbochs/struc"
import "github.com/pkg/errors"
const InstructionBytes = 32
type Instruction struct {
OpCode OpCodeType
Reserved [4]byte
Operand1 Operand
Operand2 Operand
opHandler OpHandler `struc:"skip"`
}
func NewInstruction(byteCode []byte) (*Instruction, error) {
instr := &Instruction{}
reader := bytes.NewReader(byteCode)
err := struc.Unpack(reader, instr)
if err != nil {
return nil, errors.Wrap(err, "Error decoding instruction")
}
return instr, nil
}

51
opcode.go Normal file
View File

@@ -0,0 +1,51 @@
package vm
type OpCodeType uint32
const (
OpNoOp OpCodeType = 0x00000000
OpNop = OpNoOp
OpCall = 0x00000001
OpCal = OpCall
OpReturn = 0x00000002
OpRet = OpReturn
OpMove = 0x00000100
OpMov = OpMove
OpAdd = 0x00000200
OpSubtract = 0x00000201
OpSub = OpSubtract
OpMultiply = 0x00000202
OpMul = OpMultiply
OpDivideUnsigned = 0x00000203
OpDivU = OpDivideUnsigned
OpDivideSigned = 0x00000204
OpDivS = OpDivideSigned
OpIsEqual = 0x00000300
OpEq = OpIsEqual
OpIsLessThanUnsigned = 0x00000301
OpLTU = OpIsLessThanUnsigned
OpIsLessThanSigned = 0x00000302
OpLTS = OpIsLessThanSigned
OpIsGreaterThanUnsigned = 0x00000303
OpGTU = OpIsGreaterThanUnsigned
OpIsGreaterThanSigned = 0x00000304
OpGTS = OpIsGreaterThanSigned
OpIsLessThanOrEqualUnsigned = 0x00000305
OpLTEU = OpIsLessThanOrEqualUnsigned
OpIsLessThanOrEqualSigned = 0x00000306
OpLTES = OpIsLessThanOrEqualSigned
OpIsGreaterThanOrEqualUnsigned = 0x00000307
OpGTEU = OpIsGreaterThanOrEqualUnsigned
OpIsGreaterThanOrEqualSigned = 0x00000308
OpGTES = OpIsGreaterThanOrEqualSigned
OpJump = 0x00000400
OpJmp = OpJump
OpJumpIfTrue = 0x00000401
OpJmpT = OpJumpIfTrue
OpJumpIfFalse = 0x00000402
OpJmpF = OpJumpIfFalse
)

15
operand.go Normal file
View File

@@ -0,0 +1,15 @@
package vm
type OperandType uint8
const (
Literal OperandType = 0
FunctionMemoryIndex = 1
GlobalMemoryIndex = 2
)
type Operand struct {
Type OperandType
Reserved [3]byte
Value uint64
}

149
ophandler.go Normal file
View File

@@ -0,0 +1,149 @@
package vm
type OpHandler func(*State, *Instruction)
var OpHandlers = map[OpCodeType]OpHandler{
OpNoOp: (*State).NoOp,
OpCall: (*State).Call,
OpReturn: (*State).Return,
OpMove: (*State).Move,
OpAdd: (*State).Add,
OpSubtract: (*State).Subtract,
OpMultiply: (*State).Multiply,
OpDivideUnsigned: (*State).DivideUnsigned,
OpDivideSigned: (*State).DivideSigned,
OpIsEqual: (*State).IsEqual,
OpIsLessThanUnsigned: (*State).IsLessThanUnsigned,
OpIsLessThanSigned: (*State).IsLessThanSigned,
OpIsGreaterThanUnsigned: (*State).IsGreaterThanUnsigned,
OpIsGreaterThanSigned: (*State).IsGreaterThanSigned,
OpIsLessThanOrEqualUnsigned: (*State).IsLessThanOrEqualUnsigned,
OpIsLessThanOrEqualSigned: (*State).IsLessThanOrEqualSigned,
OpIsGreaterThanOrEqualUnsigned: (*State).IsGreaterThanOrEqualUnsigned,
OpIsGreaterThanOrEqualSigned: (*State).IsGreaterThanOrEqualSigned,
OpJump: (*State).Jump,
OpJumpIfTrue: (*State).JumpIfTrue,
OpJumpIfFalse: (*State).JumpIfFalse,
}
func (state *State) NoOp(instr *Instruction) {
}
func (state *State) Call(instr *Instruction) {
in := state.ReadSigned(&instr.Operand1)
state.call(in)
}
func (state *State) Return(instr *Instruction) {
state.ret()
}
func (state *State) Move(instr *Instruction) {
in := state.ReadUnsigned(&instr.Operand2)
state.WriteUnsigned(&instr.Operand1, in)
}
func (state *State) Add(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.WriteUnsigned(&instr.Operand1, in1+in2)
}
func (state *State) Subtract(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.WriteUnsigned(&instr.Operand1, in1-in2)
}
func (state *State) Multiply(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.WriteUnsigned(&instr.Operand1, in1*in2)
}
func (state *State) DivideUnsigned(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.WriteUnsigned(&instr.Operand1, in1/in2)
}
func (state *State) DivideSigned(instr *Instruction) {
in1 := state.ReadSigned(&instr.Operand1)
in2 := state.ReadSigned(&instr.Operand2)
state.WriteSigned(&instr.Operand1, in1/in2)
}
func (state *State) IsEqual(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.ComparisonResult = (in1 == in2)
}
func (state *State) IsLessThanUnsigned(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.ComparisonResult = (in1 < in2)
}
func (state *State) IsLessThanSigned(instr *Instruction) {
in1 := state.ReadSigned(&instr.Operand1)
in2 := state.ReadSigned(&instr.Operand2)
state.ComparisonResult = (in1 < in2)
}
func (state *State) IsGreaterThanUnsigned(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.ComparisonResult = (in1 > in2)
}
func (state *State) IsGreaterThanSigned(instr *Instruction) {
in1 := state.ReadSigned(&instr.Operand1)
in2 := state.ReadSigned(&instr.Operand2)
state.ComparisonResult = (in1 > in2)
}
func (state *State) IsLessThanOrEqualUnsigned(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.ComparisonResult = (in1 <= in2)
}
func (state *State) IsLessThanOrEqualSigned(instr *Instruction) {
in1 := state.ReadSigned(&instr.Operand1)
in2 := state.ReadSigned(&instr.Operand2)
state.ComparisonResult = (in1 <= in2)
}
func (state *State) IsGreaterThanOrEqualUnsigned(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.ComparisonResult = (in1 >= in2)
}
func (state *State) IsGreaterThanOrEqualSigned(instr *Instruction) {
in1 := state.ReadSigned(&instr.Operand1)
in2 := state.ReadSigned(&instr.Operand2)
state.ComparisonResult = (in1 >= in2)
}
func (state *State) Jump(instr *Instruction) {
in := state.ReadSigned(&instr.Operand1)
state.InstructionIndex += in - 1
}
func (state *State) JumpIfTrue(instr *Instruction) {
if state.ComparisonResult == true {
state.Jump(instr)
}
}
func (state *State) JumpIfFalse(instr *Instruction) {
if state.ComparisonResult == false {
state.Jump(instr)
}
}

9
stackframe.go Normal file
View File

@@ -0,0 +1,9 @@
package vm
const FunctionMemoryEntries = 16
type StackFrame struct {
PreviousFunctionIndex int64
PreviousInstructionIndex int64
FunctionMemory [FunctionMemoryEntries]uint64
}

291
state.go
View File

@@ -1,90 +1,10 @@
package vm
import "bytes"
import "encoding/hex"
import "fmt"
import "strings"
import "github.com/lunixbochs/struc"
import "github.com/pkg/errors"
type OperandType uint8
type OpCodeType uint32
const (
Literal OperandType = 0
FunctionMemoryIndex = 1
GlobalMemoryIndex = 2
)
const (
OpNoOp OpCodeType = 0x00000000
OpNop = OpNoOp
OpCall = 0x00000001
OpCal = OpCall
OpReturn = 0x00000002
OpRet = OpReturn
OpMove = 0x00000100
OpMov = OpMove
OpAdd = 0x00000200
OpSubtract = 0x00000201
OpSub = OpSubtract
OpMultiply = 0x00000202
OpMul = OpMultiply
OpDivideUnsigned = 0x00000203
OpDivU = OpDivideUnsigned
OpDivideSigned = 0x00000204
OpDivS = OpDivideSigned
OpIsEqual = 0x00000300
OpEq = OpIsEqual
OpIsLessThanUnsigned = 0x00000301
OpLTU = OpIsLessThanUnsigned
OpIsLessThanSigned = 0x00000302
OpLTS = OpIsLessThanSigned
OpIsGreaterThanUnsigned = 0x00000303
OpGTU = OpIsGreaterThanUnsigned
OpIsGreaterThanSigned = 0x00000304
OpGTS = OpIsGreaterThanSigned
OpIsLessThanOrEqualUnsigned = 0x00000305
OpLTEU = OpIsLessThanOrEqualUnsigned
OpIsLessThanOrEqualSigned = 0x00000306
OpLTES = OpIsLessThanOrEqualSigned
OpIsGreaterThanOrEqualUnsigned = 0x00000307
OpGTEU = OpIsGreaterThanOrEqualUnsigned
OpIsGreaterThanOrEqualSigned = 0x00000308
OpGTES = OpIsGreaterThanOrEqualSigned
OpJump = 0x00000400
OpJmp = OpJump
OpJumpIfTrue = 0x00000401
OpJmpT = OpJumpIfTrue
OpJumpIfFalse = 0x00000402
OpJmpF = OpJumpIfFalse
)
const InstructionBytes = 32
const GlobalMemoryEntries = 16
const FunctionMemoryEntries = 16
type OpHandler func(*State, *Instruction)
type Operand struct {
Type OperandType
Reserved [3]byte
Value uint64
}
type Instruction struct {
OpCode OpCodeType
Reserved [4]byte
Operand1 Operand
Operand2 Operand
opHandler OpHandler `struc:"skip"`
}
type State struct {
Running bool
@@ -99,53 +19,6 @@ type State struct {
Stack []*StackFrame
}
type StackFrame struct {
PreviousFunctionIndex int64
PreviousInstructionIndex int64
FunctionMemory [FunctionMemoryEntries]uint64
}
var OpHandlers = map[OpCodeType]OpHandler{
OpNoOp: (*State).NoOp,
OpCall: (*State).Call,
OpReturn: (*State).Return,
OpMove: (*State).Move,
OpAdd: (*State).Add,
OpSubtract: (*State).Subtract,
OpMultiply: (*State).Multiply,
OpDivideUnsigned: (*State).DivideUnsigned,
OpDivideSigned: (*State).DivideSigned,
OpIsEqual: (*State).IsEqual,
OpIsLessThanUnsigned: (*State).IsLessThanUnsigned,
OpIsLessThanSigned: (*State).IsLessThanSigned,
OpIsGreaterThanUnsigned: (*State).IsGreaterThanUnsigned,
OpIsGreaterThanSigned: (*State).IsGreaterThanSigned,
OpIsLessThanOrEqualUnsigned: (*State).IsLessThanOrEqualUnsigned,
OpIsLessThanOrEqualSigned: (*State).IsLessThanOrEqualSigned,
OpIsGreaterThanOrEqualUnsigned: (*State).IsGreaterThanOrEqualUnsigned,
OpIsGreaterThanOrEqualSigned: (*State).IsGreaterThanOrEqualSigned,
OpJump: (*State).Jump,
OpJumpIfTrue: (*State).JumpIfTrue,
OpJumpIfFalse: (*State).JumpIfFalse,
}
func NewInstruction(byteCode []byte) (*Instruction, error) {
instr := &Instruction{}
reader := bytes.NewReader(byteCode)
err := struc.Unpack(reader, instr)
if err != nil {
return nil, errors.Wrap(err, "Error decoding instruction")
}
return instr, nil
}
func NewState(byteCodes [][]byte) (*State, error) {
state := &State{}
@@ -272,14 +145,6 @@ func (state *State) WriteSigned(op *Operand, value int64) {
state.WriteUnsigned(op, uint64(value))
}
func (state *State) NoOp(instr *Instruction) {
}
func (state *State) Call(instr *Instruction) {
in := state.ReadSigned(&instr.Operand1)
state.call(in)
}
func (state *State) call(functionOffset int64) {
if state.FunctionIndex+functionOffset >= int64(len(state.Functions)) {
state.setError(fmt.Errorf("Invalid function call index: %d + %d = %d", state.FunctionIndex, functionOffset, state.FunctionIndex+functionOffset))
@@ -295,10 +160,6 @@ func (state *State) call(functionOffset int64) {
state.InstructionIndex = 0
}
func (state *State) Return(instr *Instruction) {
state.ret()
}
func (state *State) ret() {
state.FunctionIndex = state.StackFrame().PreviousFunctionIndex
state.InstructionIndex = state.StackFrame().PreviousInstructionIndex
@@ -307,155 +168,3 @@ func (state *State) ret() {
state.Running = false
}
}
func (state *State) Move(instr *Instruction) {
in := state.ReadUnsigned(&instr.Operand2)
state.WriteUnsigned(&instr.Operand1, in)
}
func (state *State) Add(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.WriteUnsigned(&instr.Operand1, in1+in2)
}
func (state *State) Subtract(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.WriteUnsigned(&instr.Operand1, in1-in2)
}
func (state *State) Multiply(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.WriteUnsigned(&instr.Operand1, in1*in2)
}
func (state *State) DivideUnsigned(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.WriteUnsigned(&instr.Operand1, in1/in2)
}
func (state *State) DivideSigned(instr *Instruction) {
in1 := state.ReadSigned(&instr.Operand1)
in2 := state.ReadSigned(&instr.Operand2)
state.WriteSigned(&instr.Operand1, in1/in2)
}
func (state *State) IsEqual(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.ComparisonResult = (in1 == in2)
}
func (state *State) IsLessThanUnsigned(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.ComparisonResult = (in1 < in2)
}
func (state *State) IsLessThanSigned(instr *Instruction) {
in1 := state.ReadSigned(&instr.Operand1)
in2 := state.ReadSigned(&instr.Operand2)
state.ComparisonResult = (in1 < in2)
}
func (state *State) IsGreaterThanUnsigned(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.ComparisonResult = (in1 > in2)
}
func (state *State) IsGreaterThanSigned(instr *Instruction) {
in1 := state.ReadSigned(&instr.Operand1)
in2 := state.ReadSigned(&instr.Operand2)
state.ComparisonResult = (in1 > in2)
}
func (state *State) IsLessThanOrEqualUnsigned(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.ComparisonResult = (in1 <= in2)
}
func (state *State) IsLessThanOrEqualSigned(instr *Instruction) {
in1 := state.ReadSigned(&instr.Operand1)
in2 := state.ReadSigned(&instr.Operand2)
state.ComparisonResult = (in1 <= in2)
}
func (state *State) IsGreaterThanOrEqualUnsigned(instr *Instruction) {
in1 := state.ReadUnsigned(&instr.Operand1)
in2 := state.ReadUnsigned(&instr.Operand2)
state.ComparisonResult = (in1 >= in2)
}
func (state *State) IsGreaterThanOrEqualSigned(instr *Instruction) {
in1 := state.ReadSigned(&instr.Operand1)
in2 := state.ReadSigned(&instr.Operand2)
state.ComparisonResult = (in1 >= in2)
}
func (state *State) Jump(instr *Instruction) {
in := state.ReadSigned(&instr.Operand1)
state.InstructionIndex += in - 1
}
func (state *State) JumpIfTrue(instr *Instruction) {
if state.ComparisonResult == true {
state.Jump(instr)
}
}
func (state *State) JumpIfFalse(instr *Instruction) {
if state.ComparisonResult == false {
state.Jump(instr)
}
}
func main() {
asm := [][]string{
[]string{
"0000020000000000010000000000000000000000000000000000000000000001",
"0000000100000000000000000000000000000001000000000000000000000000",
"0000030100000000010000000000000000000000000000000000000000000003",
"000004010000000000000000fffffffffffffffd000000000000000000000000",
},
[]string{
"0000020000000000020000000000000000000000000000000000000000000001",
},
}
functionByteCode := [][]byte{}
for _, fnc := range asm {
fncString := strings.Join(fnc, "")
byteCode, err := hex.DecodeString(fncString)
if err != nil {
panic(err)
}
functionByteCode = append(functionByteCode, byteCode)
}
state, err := NewState(functionByteCode)
if err != nil {
panic(err)
}
state.Execute()
if state.Error != nil {
fmt.Printf("ERROR: %s\n", state.Error)
fmt.Printf("\tNext function index: 0x%016x\n", state.FunctionIndex)
fmt.Printf("\tNext instruction index: 0x%016x\n", state.InstructionIndex)
fmt.Printf("\n")
}
fmt.Printf("Global memory:\n")
for i, v := range state.GlobalMemory {
fmt.Printf("\t0x%08x: 0x%016x %d %d\n", i, v, v, int64(v))
}
}