From 5af90aa6ff287ff84b5779dc8bb7c696251261dd Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Sat, 20 Nov 2021 18:27:06 -1000 Subject: [PATCH] Make memory sizes parameters --- asm/assemble.go | 5 +++- asm/disassemble.go | 9 ++++++- asm/parse.go | 14 +++++++++- gen/instruction.go | 4 +-- gen/operand.go | 6 ++--- gen/program.go | 21 ++++++++------- gen/rand.go | 4 +-- test/asm_test.go | 10 +++++++ test/complex_test.go | 2 ++ test/disasm_test.go | 4 ++- test/gen_test.go | 2 +- test/opcode_test.go | 62 ++++++++++++++++++++++++++++++++++++++++++++ vm/program.go | 4 ++- vm/stackframe.go | 4 +-- vm/state.go | 4 +-- 15 files changed, 127 insertions(+), 28 deletions(-) diff --git a/asm/assemble.go b/asm/assemble.go index 4fd6e3b..e405927 100644 --- a/asm/assemble.go +++ b/asm/assemble.go @@ -13,7 +13,10 @@ func Assemble(src []byte) (*vm.Program, error) { return nil, err } - ret := &vm.Program{} + ret := &vm.Program{ + GlobalMemorySize: parsed.GlobalMemorySize, + FunctionMemorySize: parsed.FunctionMemorySize, + } for f, fnc := range parsed.Functions { instrs, err := assembleFunction(fnc) diff --git a/asm/disassemble.go b/asm/disassemble.go index 7e37a47..525bc4c 100644 --- a/asm/disassemble.go +++ b/asm/disassemble.go @@ -21,7 +21,14 @@ func Disassemble(prog *vm.Program) (string, error) { fncs = append(fncs, dis) } - return fmt.Sprintf("functions:\n%s", strings.Join(fncs, "")), nil + return fmt.Sprintf(`global_memory_size: %d +function_memory_size: %d +functions: +%s`, + prog.GlobalMemorySize, + prog.FunctionMemorySize, + strings.Join(fncs, ""), + ), nil } func disassembleFunction(fnc *vm.Function) (string, error) { diff --git a/asm/parse.go b/asm/parse.go index 039829f..78d7586 100644 --- a/asm/parse.go +++ b/asm/parse.go @@ -1,9 +1,13 @@ package asm +import "fmt" + import "gopkg.in/yaml.v2" type program struct { - Functions []function `yaml:"functions"` + GlobalMemorySize uint64 `yaml:"global_memory_size"` + FunctionMemorySize uint64 `yaml:"function_memory_size"` + Functions []function `yaml:"functions"` } type function []instruction @@ -18,5 +22,13 @@ func parse(src []byte) (*program, error) { return nil, err } + if prog.GlobalMemorySize == 0 { + return nil, fmt.Errorf("global_memory_size must be set and non-zero") + } + + if prog.FunctionMemorySize == 0 { + return nil, fmt.Errorf("function_memory_size must be set and non-zero") + } + return prog, nil } diff --git a/gen/instruction.go b/gen/instruction.go index 24aecca..a98004d 100644 --- a/gen/instruction.go +++ b/gen/instruction.go @@ -2,13 +2,13 @@ package gen import "github.com/firestuff/subcoding/vm" -func randInstruction() *vm.Instruction { +func randInstruction(prog *vm.Program) *vm.Instruction { instr := &vm.Instruction{ OpCode: randOpCode(), } for i, t := range vm.OperandsByOpCode[instr.OpCode] { - instr.Operands[i] = randOperand(t) + instr.Operands[i] = randOperand(prog, t) } return instr diff --git a/gen/operand.go b/gen/operand.go index 8545414..0599242 100644 --- a/gen/operand.go +++ b/gen/operand.go @@ -4,7 +4,7 @@ import "math/rand" import "github.com/firestuff/subcoding/vm" -func randOperand(t vm.OperandNumericType) *vm.Operand { +func randOperand(prog *vm.Program, t vm.OperandNumericType) *vm.Operand { for { op := &vm.Operand{ Type: randOperandType(), @@ -12,10 +12,10 @@ func randOperand(t vm.OperandNumericType) *vm.Operand { switch op.Type { case vm.GlobalMemoryIndex: - op.Value = RandBiasedUint64n(vm.GlobalMemorySize) + op.Value = RandBiasedUint64n(prog.GlobalMemorySize) case vm.FunctionMemoryIndex: - op.Value = RandBiasedUint64n(vm.FunctionMemorySize) + op.Value = RandBiasedUint64n(prog.FunctionMemorySize) case vm.Literal: switch t { diff --git a/gen/program.go b/gen/program.go index 901c012..b793ad7 100644 --- a/gen/program.go +++ b/gen/program.go @@ -2,14 +2,17 @@ package gen import "github.com/firestuff/subcoding/vm" -func RandProgram() *vm.Program { - return &vm.Program{ - Functions: []*vm.Function{ - &vm.Function{ - Instructions: []*vm.Instruction{ - randInstruction(), - }, - }, - }, +func RandProgram(globalMemorySize, functionMemorySize uint64) *vm.Program { + prog := &vm.Program{ + GlobalMemorySize: globalMemorySize, + FunctionMemorySize: functionMemorySize, } + + prog.Functions = append(prog.Functions, &vm.Function{ + Instructions: []*vm.Instruction{ + randInstruction(prog), + }, + }) + + return prog } diff --git a/gen/rand.go b/gen/rand.go index fbf1012..81b8109 100644 --- a/gen/rand.go +++ b/gen/rand.go @@ -5,7 +5,7 @@ import "math/rand" // Generate a random uint64 with an even distribution of bits.Len64() func RandBiasedUint64() uint64 { // The shift-right by up to 64 (shifting it to 0) makes up for randomness - // lost by setting the high bit. + // lost by setting the high bit. return (rand.Uint64() | 0x8000000000000000) >> rand.Intn(65) } @@ -29,7 +29,7 @@ func RandBiasedInt64() uint64 { if shift < 64 { return uint64(int64((rand.Uint64() | 0x8000000000000000) >> (shift + 1))) } else { - return uint64(int64((rand.Uint64() | 0x8000000000000000) >> (shift - 63)) * -1) + return uint64(int64((rand.Uint64()|0x8000000000000000)>>(shift-63)) * -1) } } diff --git a/test/asm_test.go b/test/asm_test.go index 48ec345..f2b84f5 100644 --- a/test/asm_test.go +++ b/test/asm_test.go @@ -6,6 +6,8 @@ import "github.com/firestuff/subcoding/asm" func TestTooManyOperands(t *testing.T) { _, err := asm.AssembleString(` +global_memory_size: 4 +function_memory_size: 4 functions: - - [nop, 0] `) @@ -16,6 +18,8 @@ functions: func TestTooFewOperands(t *testing.T) { _, err := asm.AssembleString(` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0] `) @@ -26,6 +30,8 @@ functions: func TestIncorrectSigned(t *testing.T) { _, err := asm.AssembleString(` +global_memory_size: 4 +function_memory_size: 4 functions: - - [ltu, 0, -1] `) @@ -36,6 +42,8 @@ functions: func TestHex(t *testing.T) { prog, err := asm.AssembleString(` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 0xfeedc0de] `) @@ -51,6 +59,8 @@ functions: func TestBinary(t *testing.T) { prog, err := asm.AssembleString(` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 0b100101] `) diff --git a/test/complex_test.go b/test/complex_test.go index c4d68f8..d6b9988 100644 --- a/test/complex_test.go +++ b/test/complex_test.go @@ -4,6 +4,8 @@ import "testing" func TestLoop(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [add, f0, 1] - [call, +1] diff --git a/test/disasm_test.go b/test/disasm_test.go index 4ecca28..dce0fca 100644 --- a/test/disasm_test.go +++ b/test/disasm_test.go @@ -6,7 +6,9 @@ import "github.com/firestuff/subcoding/asm" import "github.com/firestuff/subcoding/vm" func TestRoundTrip(t *testing.T) { - src := `functions: + src := `global_memory_size: 4 +function_memory_size: 4 +functions: - - [nop] - [mov, g0, 1] - [add, f0, 5] diff --git a/test/gen_test.go b/test/gen_test.go index b8ae5ae..face1d0 100644 --- a/test/gen_test.go +++ b/test/gen_test.go @@ -7,7 +7,7 @@ import "github.com/firestuff/subcoding/asm" func TestRandProgram(t *testing.T) { for i := 0; i < 100; i++ { - prog := gen.RandProgram() + prog := gen.RandProgram(4, 4) src, err := asm.Disassemble(prog) if err != nil { diff --git a/test/opcode_test.go b/test/opcode_test.go index 02ddbac..ac5d430 100644 --- a/test/opcode_test.go +++ b/test/opcode_test.go @@ -4,6 +4,8 @@ import "testing" func TestNop(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [nop] `) @@ -13,6 +15,8 @@ functions: func TestMov(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 1] - [mov, g1, g0] @@ -27,6 +31,8 @@ functions: func TestAdd(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [add, g0, 5] - [add, g0, 2] @@ -41,6 +47,8 @@ functions: func TestSub(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [sub, g0, 2] - [sub, g0, -5] @@ -53,6 +61,8 @@ functions: func TestMul(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 5] - [mul, g0, 3] @@ -67,6 +77,8 @@ functions: func TestDivU(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 15] - [divu, g0, 3] @@ -80,6 +92,8 @@ functions: func TestDivS(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 15] - [divs, g0, -3] @@ -96,6 +110,8 @@ functions: func TestNot(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 8] - [not, g0] @@ -107,6 +123,8 @@ functions: func TestAnd(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 7] - [and, g0, 18] @@ -117,6 +135,8 @@ functions: func TestOr(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 7] - [or, g0, 18] @@ -127,6 +147,8 @@ functions: func TestXor(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 7] - [xor, g0, 18] @@ -137,6 +159,8 @@ functions: func TestShR(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 53] - [shr, g0, 2] @@ -147,6 +171,8 @@ functions: func TestShL(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 53] - [shl, g0, 2] @@ -157,6 +183,8 @@ functions: func TestEq(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 5] - [eq, g0, 5] @@ -172,6 +200,8 @@ functions: func TestLTU(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 5] - [ltu, g0, 4] @@ -190,6 +220,8 @@ functions: func TestLTS(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 0] - [lts, g0, -1] @@ -208,6 +240,8 @@ functions: func TestGTU(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 5] - [gtu, g0, 4] @@ -226,6 +260,8 @@ functions: func TestGTS(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 0] - [gts, g0, -1] @@ -244,6 +280,8 @@ functions: func TestLTEU(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 5] - [lteu, g0, 4] @@ -262,6 +300,8 @@ functions: func TestLTES(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 0] - [ltes, g0, -1] @@ -280,6 +320,8 @@ functions: func TestGTEU(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 5] - [gteu, g0, 4] @@ -298,6 +340,8 @@ functions: func TestGTES(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [mov, g0, 0] - [gtes, g0, -1] @@ -316,6 +360,8 @@ functions: func TestJmp(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [jmp, +2] - [add, g0, 1] @@ -329,6 +375,8 @@ functions: func TestJmpT(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [eq, 0, 0] - [jmpt, +2] @@ -344,6 +392,8 @@ functions: func TestJmpF(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [eq, 0, 0] - [jmpf, +2] @@ -359,6 +409,8 @@ functions: func TestCal(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [cal, +1] - [add, g0, 1] @@ -373,6 +425,8 @@ functions: func TestCalT(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [eq, 0, 0] - [calt, +1] @@ -391,6 +445,8 @@ functions: func TestCalF(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [eq, 0, 0] - [calf, +1] @@ -409,6 +465,8 @@ functions: func TestRet(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [cal, +1] - [add, g0, 1] @@ -424,6 +482,8 @@ functions: func TestRetT(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [cal, +1] - [add, g0, 1] @@ -442,6 +502,8 @@ functions: func TestRetF(t *testing.T) { state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 functions: - - [cal, +1] - [add, g0, 1] diff --git a/vm/program.go b/vm/program.go index 462e0b4..21145b6 100644 --- a/vm/program.go +++ b/vm/program.go @@ -1,5 +1,7 @@ package vm type Program struct { - Functions []*Function + GlobalMemorySize uint64 + FunctionMemorySize uint64 + Functions []*Function } diff --git a/vm/stackframe.go b/vm/stackframe.go index 2cdba2c..19a885f 100644 --- a/vm/stackframe.go +++ b/vm/stackframe.go @@ -1,7 +1,5 @@ package vm -const FunctionMemorySize = 16 - type stackFrame struct { previousFunctionIndex int64 previousInstructionIndex int64 @@ -12,6 +10,6 @@ func newStackFrame(state *State) *stackFrame { return &stackFrame{ previousFunctionIndex: state.functionIndex, previousInstructionIndex: state.instructionIndex, - functionMemory: NewMemory(FunctionMemorySize), + functionMemory: NewMemory(state.program.FunctionMemorySize), } } diff --git a/vm/state.go b/vm/state.go index dc734c5..b6772c6 100644 --- a/vm/state.go +++ b/vm/state.go @@ -2,8 +2,6 @@ package vm import "fmt" -const GlobalMemorySize = 16 - type State struct { running bool err error @@ -20,7 +18,7 @@ type State struct { func NewState(prog *Program) (*State, error) { return &State{ program: prog, - globalMemory: NewMemory(GlobalMemorySize), + globalMemory: NewMemory(prog.GlobalMemorySize), }, nil }