diff --git a/asm/assemble.go b/asm/assemble.go index 08abce4..081a7a8 100644 --- a/asm/assemble.go +++ b/asm/assemble.go @@ -21,7 +21,11 @@ func Assemble(src []byte) (*vm.Program, error) { return nil, errors.Wrapf(err, "At function index %d\n", f) } - ret.Functions = append(ret.Functions, instrs) + newFunc := &vm.Function{ + Instructions: instrs, + } + + ret.Functions = append(ret.Functions, newFunc) } return ret, nil diff --git a/asm/disassemble.go b/asm/disassemble.go new file mode 100644 index 0000000..1c30f61 --- /dev/null +++ b/asm/disassemble.go @@ -0,0 +1,34 @@ +package asm + +import "fmt" + +import "github.com/firestuff/subcoding/vm" +import "github.com/pkg/errors" + +func Disassemble(prog *vm.Program) ([]byte, error) { + for f, fnc := range prog.Functions { + _, err := disassembleFunction(fnc) + if err != nil { + return nil, errors.Wrapf(err, "At function index %d", f) + } + } + + return nil, nil +} + +func disassembleFunction(fnc *vm.Function) ([]byte, error) { + for i, instr := range fnc.Instructions { + _, err := disassembleInstruction(instr) + if err != nil { + return nil, errors.Wrapf(err, "At instruction index %d", i) + } + } + + return nil, nil +} + +func disassembleInstruction(in *vm.Instruction) ([]byte, error) { + fmt.Printf("%s\n", nameByOpCode[in.OpCode]) + + return nil, nil +} diff --git a/asm/opcodes.go b/asm/opcodes.go index 20e151b..e8282b6 100644 --- a/asm/opcodes.go +++ b/asm/opcodes.go @@ -70,6 +70,48 @@ var opCodeByName = map[string]vm.OpCodeType{ "retf": vm.OpRetF, } +var nameByOpCode = map[vm.OpCodeType]string{ + vm.OpNop: "nop", + + vm.OpMov: "mov", + + vm.OpAdd: "add", + vm.OpSub: "sub", + vm.OpMul: "mul", + vm.OpDivU: "divu", + vm.OpDivS: "divs", + + vm.OpNot: "not", + vm.OpAnd: "and", + vm.OpOr: "or", + vm.OpXor: "xor", + + vm.OpShR: "shr", + vm.OpShL: "shl", + + vm.OpEq: "eq", + vm.OpLTU: "ltu", + vm.OpLTS: "lts", + vm.OpGTU: "gtu", + vm.OpGTS: "gts", + vm.OpLTEU: "lteu", + vm.OpLTES: "ltes", + vm.OpGTEU: "gteu", + vm.OpGTES: "gtes", + + vm.OpJmp: "jmp", + vm.OpJmpT: "jmpt", + vm.OpJmpF: "jmpf", + + vm.OpCal: "cal", + vm.OpCalT: "calt", + vm.OpCalF: "calf", + + vm.OpRet: "ret", + vm.OpRetT: "rett", + vm.OpRetF: "retf", +} + type operandType int const ( diff --git a/test/disasm_test.go b/test/disasm_test.go new file mode 100644 index 0000000..c35d13d --- /dev/null +++ b/test/disasm_test.go @@ -0,0 +1,20 @@ +package test + +import "testing" + +import "github.com/firestuff/subcoding/asm" + +func TestRoundTrip(t *testing.T) { + prog, err := asm.AssembleString(` +functions: +- - [nop] +`) + if err != nil { + t.Fatal(err) + } + + _, err = asm.Disassemble(prog) + if err != nil { + t.Fatal(err) + } +} diff --git a/vm/function.go b/vm/function.go new file mode 100644 index 0000000..74b1dd2 --- /dev/null +++ b/vm/function.go @@ -0,0 +1,5 @@ +package vm + +type Function struct { + Instructions []*Instruction +} diff --git a/vm/program.go b/vm/program.go index c24fdd9..462e0b4 100644 --- a/vm/program.go +++ b/vm/program.go @@ -1,5 +1,5 @@ package vm type Program struct { - Functions [][]*Instruction + Functions []*Function } diff --git a/vm/state.go b/vm/state.go index a5b66f2..2728c5f 100644 --- a/vm/state.go +++ b/vm/state.go @@ -42,7 +42,7 @@ func (state *State) stackFrame() *stackFrame { return state.stack[len(state.stack)-1] } -func (state *State) function() []*Instruction { +func (state *State) function() *Function { return state.program.Functions[state.functionIndex] } @@ -53,7 +53,7 @@ func (state *State) setError(err error) { func (state *State) setHandlers() { for _, fnc := range state.program.Functions { - for _, instr := range fnc { + for _, instr := range fnc.Instructions { handler, found := opHandlers[instr.OpCode] if !found { state.setError(fmt.Errorf("Invalid OpCode: 0x%08x", instr.OpCode)) @@ -67,7 +67,7 @@ func (state *State) setHandlers() { func (state *State) processInstruction() { fnc := state.function() - instr := fnc[state.instructionIndex] + instr := fnc.Instructions[state.instructionIndex] state.instructionIndex += 1 instr.opHandler(state, instr) @@ -75,7 +75,7 @@ func (state *State) processInstruction() { state.ret() } - if state.instructionIndex >= int64(len(fnc)) { + if state.instructionIndex >= int64(len(fnc.Instructions)) { state.ret() } }