Simplify main loop conditional
This commit is contained in:
139
main.go
139
main.go
@@ -9,6 +9,7 @@ import "github.com/lunixbochs/struc"
|
|||||||
import "github.com/pkg/errors"
|
import "github.com/pkg/errors"
|
||||||
|
|
||||||
type OperandType uint8
|
type OperandType uint8
|
||||||
|
type OpCodeType uint32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Literal OperandType = 0
|
Literal OperandType = 0
|
||||||
@@ -16,6 +17,54 @@ const (
|
|||||||
GlobalMemoryIndex = 2
|
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 InstructionBytes = 32
|
||||||
const GlobalMemoryEntries = 16
|
const GlobalMemoryEntries = 16
|
||||||
const FunctionMemoryEntries = 16
|
const FunctionMemoryEntries = 16
|
||||||
@@ -29,7 +78,7 @@ type Operand struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Instruction struct {
|
type Instruction struct {
|
||||||
OpCode uint32
|
OpCode OpCodeType
|
||||||
Reserved [4]byte
|
Reserved [4]byte
|
||||||
Operand1 Operand
|
Operand1 Operand
|
||||||
Operand2 Operand
|
Operand2 Operand
|
||||||
@@ -38,6 +87,7 @@ type Instruction struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type State struct {
|
type State struct {
|
||||||
|
Running bool
|
||||||
Error error
|
Error error
|
||||||
|
|
||||||
Functions [][]*Instruction
|
Functions [][]*Instruction
|
||||||
@@ -55,32 +105,32 @@ type StackFrame struct {
|
|||||||
FunctionMemory [FunctionMemoryEntries]uint64
|
FunctionMemory [FunctionMemoryEntries]uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
var OpHandlers = map[uint32]OpHandler{
|
var OpHandlers = map[OpCodeType]OpHandler{
|
||||||
0x00000000: (*State).NoOp,
|
OpNoOp: (*State).NoOp,
|
||||||
0x00000001: (*State).Call,
|
OpCall: (*State).Call,
|
||||||
0x00000002: (*State).Return,
|
OpReturn: (*State).Return,
|
||||||
|
|
||||||
0x00000100: (*State).Move,
|
OpMove: (*State).Move,
|
||||||
|
|
||||||
0x00000200: (*State).Add,
|
OpAdd: (*State).Add,
|
||||||
0x00000201: (*State).Subtract,
|
OpSubtract: (*State).Subtract,
|
||||||
0x00000202: (*State).Multiply,
|
OpMultiply: (*State).Multiply,
|
||||||
0x00000203: (*State).DivideUnsigned,
|
OpDivideUnsigned: (*State).DivideUnsigned,
|
||||||
0x00000204: (*State).DivideSigned,
|
OpDivideSigned: (*State).DivideSigned,
|
||||||
|
|
||||||
0x00000300: (*State).IsEqual,
|
OpIsEqual: (*State).IsEqual,
|
||||||
0x00000301: (*State).IsLessThanUnsigned,
|
OpIsLessThanUnsigned: (*State).IsLessThanUnsigned,
|
||||||
0x00000302: (*State).IsLessThanSigned,
|
OpIsLessThanSigned: (*State).IsLessThanSigned,
|
||||||
0x00000303: (*State).IsGreaterThanUnsigned,
|
OpIsGreaterThanUnsigned: (*State).IsGreaterThanUnsigned,
|
||||||
0x00000304: (*State).IsGreaterThanSigned,
|
OpIsGreaterThanSigned: (*State).IsGreaterThanSigned,
|
||||||
0x00000305: (*State).IsLessThanOrEqualUnsigned,
|
OpIsLessThanOrEqualUnsigned: (*State).IsLessThanOrEqualUnsigned,
|
||||||
0x00000306: (*State).IsLessThanOrEqualSigned,
|
OpIsLessThanOrEqualSigned: (*State).IsLessThanOrEqualSigned,
|
||||||
0x00000307: (*State).IsGreaterThanOrEqualUnsigned,
|
OpIsGreaterThanOrEqualUnsigned: (*State).IsGreaterThanOrEqualUnsigned,
|
||||||
0x00000308: (*State).IsGreaterThanOrEqualSigned,
|
OpIsGreaterThanOrEqualSigned: (*State).IsGreaterThanOrEqualSigned,
|
||||||
|
|
||||||
0x00000400: (*State).Jump,
|
OpJump: (*State).Jump,
|
||||||
0x00000401: (*State).JumpIfTrue,
|
OpJumpIfTrue: (*State).JumpIfTrue,
|
||||||
0x00000402: (*State).JumpIfFalse,
|
OpJumpIfFalse: (*State).JumpIfFalse,
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewInstruction(byteCode []byte) (*Instruction, error) {
|
func NewInstruction(byteCode []byte) (*Instruction, error) {
|
||||||
@@ -111,6 +161,10 @@ func NewState(byteCodes [][]byte) (*State, error) {
|
|||||||
instrs = append(instrs, instr)
|
instrs = append(instrs, instr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instrs = append(instrs, &Instruction{
|
||||||
|
OpCode: OpReturn,
|
||||||
|
})
|
||||||
|
|
||||||
state.Functions = append(state.Functions, instrs)
|
state.Functions = append(state.Functions, instrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,20 +180,26 @@ func (state *State) Function() []*Instruction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (state *State) Execute() {
|
func (state *State) Execute() {
|
||||||
state.prepare()
|
state.setHandlers()
|
||||||
state.call(0)
|
state.call(0)
|
||||||
|
state.Running = true
|
||||||
|
|
||||||
for len(state.Stack) > 0 && state.Error == nil{
|
for state.Running {
|
||||||
state.ProcessInstruction()
|
state.ProcessInstruction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (state *State) prepare() {
|
func (state *State) setError(err error) {
|
||||||
|
state.Error = err
|
||||||
|
state.Running = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *State) setHandlers() {
|
||||||
for _, fnc := range state.Functions {
|
for _, fnc := range state.Functions {
|
||||||
for _, instr := range fnc {
|
for _, instr := range fnc {
|
||||||
handler, found := OpHandlers[instr.OpCode]
|
handler, found := OpHandlers[instr.OpCode]
|
||||||
if !found {
|
if !found {
|
||||||
state.Error = fmt.Errorf("Invalid OpCode: 0x%08x", instr.OpCode)
|
state.setError(fmt.Errorf("Invalid OpCode: 0x%08x", instr.OpCode))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,12 +210,6 @@ func (state *State) prepare() {
|
|||||||
|
|
||||||
func (state *State) ProcessInstruction() {
|
func (state *State) ProcessInstruction() {
|
||||||
fnc := state.Function()
|
fnc := state.Function()
|
||||||
|
|
||||||
if state.InstructionIndex >= int64(len(fnc)) {
|
|
||||||
state.ret()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
instr := fnc[state.InstructionIndex]
|
instr := fnc[state.InstructionIndex]
|
||||||
state.InstructionIndex += 1
|
state.InstructionIndex += 1
|
||||||
instr.opHandler(state, instr)
|
instr.opHandler(state, instr)
|
||||||
@@ -168,20 +222,20 @@ func (state *State) ReadUnsigned(op *Operand) uint64 {
|
|||||||
|
|
||||||
case FunctionMemoryIndex:
|
case FunctionMemoryIndex:
|
||||||
if op.Value >= FunctionMemoryEntries {
|
if op.Value >= FunctionMemoryEntries {
|
||||||
state.Error = fmt.Errorf("Invalid function memory index: %016x", op.Value)
|
state.setError(fmt.Errorf("Invalid function memory index: %016x", op.Value))
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return state.StackFrame().FunctionMemory[op.Value]
|
return state.StackFrame().FunctionMemory[op.Value]
|
||||||
|
|
||||||
case GlobalMemoryIndex:
|
case GlobalMemoryIndex:
|
||||||
if op.Value >= GlobalMemoryEntries {
|
if op.Value >= GlobalMemoryEntries {
|
||||||
state.Error = fmt.Errorf("Invalid global memory index: %016x", op.Value)
|
state.setError(fmt.Errorf("Invalid global memory index: %016x", op.Value))
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return state.GlobalMemory[op.Value]
|
return state.GlobalMemory[op.Value]
|
||||||
|
|
||||||
default:
|
default:
|
||||||
state.Error = fmt.Errorf("Unknown operand type: 0x%02x", op.Type)
|
state.setError(fmt.Errorf("Unknown operand type: 0x%02x", op.Type))
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,24 +247,24 @@ func (state *State) ReadSigned(op *Operand) int64 {
|
|||||||
func (state *State) WriteUnsigned(op *Operand, value uint64) {
|
func (state *State) WriteUnsigned(op *Operand, value uint64) {
|
||||||
switch op.Type {
|
switch op.Type {
|
||||||
case Literal:
|
case Literal:
|
||||||
state.Error = fmt.Errorf("Write to literal operand")
|
state.setError(fmt.Errorf("Write to literal operand"))
|
||||||
|
|
||||||
case FunctionMemoryIndex:
|
case FunctionMemoryIndex:
|
||||||
if op.Value >= FunctionMemoryEntries {
|
if op.Value >= FunctionMemoryEntries {
|
||||||
state.Error = fmt.Errorf("Invalid function memory index: %016x", op.Value)
|
state.setError(fmt.Errorf("Invalid function memory index: %016x", op.Value))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
state.StackFrame().FunctionMemory[op.Value] = value
|
state.StackFrame().FunctionMemory[op.Value] = value
|
||||||
|
|
||||||
case GlobalMemoryIndex:
|
case GlobalMemoryIndex:
|
||||||
if op.Value >= GlobalMemoryEntries {
|
if op.Value >= GlobalMemoryEntries {
|
||||||
state.Error = fmt.Errorf("Invalid global memory index: %016x", op.Value)
|
state.setError(fmt.Errorf("Invalid global memory index: %016x", op.Value))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
state.GlobalMemory[op.Value] = value
|
state.GlobalMemory[op.Value] = value
|
||||||
|
|
||||||
default:
|
default:
|
||||||
state.Error = fmt.Errorf("Unknown operand type: 0x%02x", op.Type)
|
state.setError(fmt.Errorf("Unknown operand type: 0x%02x", op.Type))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +282,7 @@ func (state *State) Call(instr *Instruction) {
|
|||||||
|
|
||||||
func (state *State) call(functionOffset int64) {
|
func (state *State) call(functionOffset int64) {
|
||||||
if state.FunctionIndex+functionOffset >= int64(len(state.Functions)) {
|
if state.FunctionIndex+functionOffset >= int64(len(state.Functions)) {
|
||||||
state.Error = fmt.Errorf("Invalid function call index: %d + %d = %d", state.FunctionIndex, functionOffset, state.FunctionIndex+functionOffset)
|
state.setError(fmt.Errorf("Invalid function call index: %d + %d = %d", state.FunctionIndex, functionOffset, state.FunctionIndex+functionOffset))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,6 +303,9 @@ func (state *State) ret() {
|
|||||||
state.FunctionIndex = state.StackFrame().PreviousFunctionIndex
|
state.FunctionIndex = state.StackFrame().PreviousFunctionIndex
|
||||||
state.InstructionIndex = state.StackFrame().PreviousInstructionIndex
|
state.InstructionIndex = state.StackFrame().PreviousInstructionIndex
|
||||||
state.Stack = state.Stack[:len(state.Stack)-1]
|
state.Stack = state.Stack[:len(state.Stack)-1]
|
||||||
|
if len(state.Stack) == 0 {
|
||||||
|
state.Running = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (state *State) Move(instr *Instruction) {
|
func (state *State) Move(instr *Instruction) {
|
||||||
|
|||||||
Reference in New Issue
Block a user