diff options
Diffstat (limited to 'vm')
-rw-r--r-- | vm/instruction.go | 147 | ||||
-rw-r--r-- | vm/instructions.go | 162 | ||||
-rw-r--r-- | vm/main.go | 8 | ||||
-rw-r--r-- | vm/memory.go | 14 | ||||
-rw-r--r-- | vm/opcodes.go | 9 | ||||
-rw-r--r-- | vm/rom.go | 9 | ||||
-rw-r--r-- | vm/stack.go | 5 | ||||
-rw-r--r-- | vm/vm.go | 28 |
8 files changed, 213 insertions, 169 deletions
diff --git a/vm/instruction.go b/vm/instruction.go deleted file mode 100644 index 5cd56e6..0000000 --- a/vm/instruction.go +++ /dev/null @@ -1,147 +0,0 @@ -package main - -import ( - "github.com/holiman/uint256" -) - -type Handler func(vm *Evm) - -type Instruction struct { - name string - n int // number of params - handler Handler -} - -type Inst Instruction // shorthand - -// i miss c macros :( -var Instructions = [256]Instruction{ - STOP: { - name: "STOP", - n: 0, - handler: func(vm *Evm) { vm.stopped = true }, - } , - ADD: { - name: "ADD", - n: 2, - handler: func(vm *Evm) { - o := uint256.NewInt(0) - vm.stack.Push(o.Add(vm.stack.Pop(), vm.stack.Pop())) - }, - }, - MUL: { - n: 2, - name: "MUL", - handler: func(vm *Evm) { - o := uint256.NewInt(0) - vm.stack.Push(o.Mul(vm.stack.Pop(), vm.stack.Pop())) - }, - }, - SUB: { - n: 2, - name: "SUB", - handler: func(vm *Evm) { - o := uint256.NewInt(0) - vm.stack.Push(o.Sub(vm.stack.Pop(), vm.stack.Pop())) - }, - }, - DIV: { - n: 2, - name: "DIV", - handler: func(vm *Evm) { - o := uint256.NewInt(0) - vm.stack.Push(o.Div(vm.stack.Pop(), vm.stack.Pop())) - }, - }, - SDIV: { - n: 2, - name: "SDIV", - handler: func(vm *Evm) { - o := uint256.NewInt(0) - vm.stack.Push(o.SDiv(vm.stack.Pop(), vm.stack.Pop())) - }, - }, - MOD: { - n: 2, - name: "MOD", - handler: func(vm *Evm) { - o := uint256.NewInt(0) - vm.stack.Push(o.Mod(vm.stack.Pop(), vm.stack.Pop())) - }, - }, - SMOD: { - n: 2, - name: "SMOD", - handler: func(vm *Evm) { - o := uint256.NewInt(0) - vm.stack.Push(o.SMod(vm.stack.Pop(), vm.stack.Pop())) - }, - }, - ADDMOD: { - n: 3, - name: "ADDMOD", - handler: func(vm *Evm) { - o := uint256.NewInt(0) - vm.stack.Push(o.AddMod(vm.stack.Pop(), vm.stack.Pop(), vm.stack.Pop())) - }, - }, - MULMOD: { - n: 3, - name: "MULMOD", - handler: func(vm *Evm) { - o := uint256.NewInt(0) - vm.stack.Push(o.MulMod(vm.stack.Pop(), vm.stack.Pop(), vm.stack.Pop())) - }, - }, - POP: { - n: 1, - name: "POP", - handler: func(vm *Evm) { - vm.stack.Pop() - }, - }, - MLOAD: { - n: 1, - name: "MLOAD", - }, - MSTORE: { - n: 2, - name: "MSTORE", - }, - MSTORE8: { - n: 2, - name: "MSTORE8", - }, - PUSH1: { name: "PUSH1" }, - PUSH2: { name: "PUSH2" }, - PUSH3: { name: "PUSH3" }, - PUSH4: { name: "PUSH4" }, - PUSH5: { name: "PUSH5" }, - PUSH6: { name: "PUSH6" }, - PUSH7: { name: "PUSH7" }, - PUSH8: { name: "PUSH8" }, - PUSH9: { name: "PUSH9" }, - PUSH10: { name: "PUSH0" }, - PUSH11: { name: "PUSH11" }, - PUSH12: { name: "PUSH12" }, - PUSH13: { name: "PUSH13" }, - PUSH14: { name: "PUSH14" }, - PUSH15: { name: "PUSH15" }, - PUSH16: { name: "PUSH16" }, - PUSH17: { name: "PUSH17" }, - PUSH18: { name: "PUSH18" }, - PUSH19: { name: "PUSH19" }, - PUSH20: { name: "PUSH20" }, - PUSH21: { name: "PUSH21" }, - PUSH22: { name: "PUSH22" }, - PUSH23: { name: "PUSH23" }, - PUSH24: { name: "PUSH24" }, - PUSH25: { name: "PUSH25" }, - PUSH26: { name: "PUSH26" }, - PUSH27: { name: "PUSH27" }, - PUSH28: { name: "PUSH28" }, - PUSH29: { name: "PUSH29" }, - PUSH30: { name: "PUSH30" }, - PUSH31: { name: "PUSH31" }, - PUSH32: { name: "PUSH32" }, -} diff --git a/vm/instructions.go b/vm/instructions.go index 5a1220b..8b8b2e2 100644 --- a/vm/instructions.go +++ b/vm/instructions.go @@ -1,3 +1,163 @@ package main -type InstructionHandler func (vm *Evm) +import ( + "github.com/holiman/uint256" +) + +type Handler func(vm *Evm) + +type Instruction struct { + name string + n int // number of params + handler Handler +} + +type Inst Instruction // shorthand + +// i miss c macros :( +var Instructions = [256]Instruction{ + STOP: { + name: "STOP", + n: 0, + handler: func(vm *Evm) { vm.stopped = true }, + } , + ADD: { + name: "ADD", + n: 2, + handler: func(vm *Evm) { + o := uint256.NewInt(0) + vm.stack.Push(o.Add(vm.stack.Pop(), vm.stack.Pop())) + }, + }, + MUL: { + n: 2, + name: "MUL", + handler: func(vm *Evm) { + o := uint256.NewInt(0) + vm.stack.Push(o.Mul(vm.stack.Pop(), vm.stack.Pop())) + }, + }, + SUB: { + n: 2, + name: "SUB", + handler: func(vm *Evm) { + o := uint256.NewInt(0) + vm.stack.Push(o.Sub(vm.stack.Pop(), vm.stack.Pop())) + }, + }, + DIV: { + n: 2, + name: "DIV", + handler: func(vm *Evm) { + o := uint256.NewInt(0) + vm.stack.Push(o.Div(vm.stack.Pop(), vm.stack.Pop())) + }, + }, + SDIV: { + n: 2, + name: "SDIV", + handler: func(vm *Evm) { + o := uint256.NewInt(0) + vm.stack.Push(o.SDiv(vm.stack.Pop(), vm.stack.Pop())) + }, + }, + MOD: { + n: 2, + name: "MOD", + handler: func(vm *Evm) { + o := uint256.NewInt(0) + vm.stack.Push(o.Mod(vm.stack.Pop(), vm.stack.Pop())) + }, + }, + SMOD: { + n: 2, + name: "SMOD", + handler: func(vm *Evm) { + o := uint256.NewInt(0) + vm.stack.Push(o.SMod(vm.stack.Pop(), vm.stack.Pop())) + }, + }, + ADDMOD: { + n: 3, + name: "ADDMOD", + handler: func(vm *Evm) { + o := uint256.NewInt(0) + vm.stack.Push(o.AddMod(vm.stack.Pop(), vm.stack.Pop(), vm.stack.Pop())) + }, + }, + MULMOD: { + n: 3, + name: "MULMOD", + handler: func(vm *Evm) { + o := uint256.NewInt(0) + vm.stack.Push(o.MulMod(vm.stack.Pop(), vm.stack.Pop(), vm.stack.Pop())) + }, + }, + POP: { + n: 1, + name: "POP", + handler: func(vm *Evm) { + vm.stack.Pop() + }, + }, + MLOAD: { + n: 1, + name: "MLOAD", + }, + MSTORE: { + n: 2, + name: "MSTORE", + handler: func(vm *Evm) { + vm.memory.sw(vm.stack.Pop().Uint64(), vm.stack.Pop()) + }, + }, + MSTORE8: { + n: 2, + name: "MSTORE8", + handler: func(vm *Evm) { + ost := vm.stack.Pop().Uint64() + x := vm.stack.Pop().Bytes() + n := x[len(x)-1] + vm.memory.sb(ost, n) + }, + }, + PUSH1: { name: "PUSH1" }, + PUSH2: { name: "PUSH2" }, + PUSH3: { name: "PUSH3" }, + PUSH4: { name: "PUSH4" }, + PUSH5: { name: "PUSH5" }, + PUSH6: { name: "PUSH6" }, + PUSH7: { name: "PUSH7" }, + PUSH8: { name: "PUSH8" }, + PUSH9: { name: "PUSH9" }, + PUSH10: { name: "PUSH0" }, + PUSH11: { name: "PUSH11" }, + PUSH12: { name: "PUSH12" }, + PUSH13: { name: "PUSH13" }, + PUSH14: { name: "PUSH14" }, + PUSH15: { name: "PUSH15" }, + PUSH16: { name: "PUSH16" }, + PUSH17: { name: "PUSH17" }, + PUSH18: { name: "PUSH18" }, + PUSH19: { name: "PUSH19" }, + PUSH20: { name: "PUSH20" }, + PUSH21: { name: "PUSH21" }, + PUSH22: { name: "PUSH22" }, + PUSH23: { name: "PUSH23" }, + PUSH24: { name: "PUSH24" }, + PUSH25: { name: "PUSH25" }, + PUSH26: { name: "PUSH26" }, + PUSH27: { name: "PUSH27" }, + PUSH28: { name: "PUSH28" }, + PUSH29: { name: "PUSH29" }, + PUSH30: { name: "PUSH30" }, + PUSH31: { name: "PUSH31" }, + PUSH32: { name: "PUSH32" }, + RETURN: { + n: 2, + name: "RETURN", + handler: func(vm *Evm) { + vm.returndata = vm.memory.ld(vm.stack.Pop().Uint64(), vm.stack.Pop().Uint64()) + }, + }, +} @@ -21,6 +21,12 @@ func main() { vm := NewEvm(b) - vm.Start() + returndata := vm.Run() + + fmt.Printf("finished execution.\n") + + if (returndata != nil) { + fmt.Printf("callee returned: %v\n", returndata) + } } diff --git a/vm/memory.go b/vm/memory.go index 0a9dd2c..a0c610a 100644 --- a/vm/memory.go +++ b/vm/memory.go @@ -26,14 +26,18 @@ func (m *Memory) sb(ost uint64, val byte) { (*m)[ost] = val } -// loads 256b word fron offset in memory -func (m *Memory) ld(ost uint64) []byte { - if ost + 32 > uint64(len(*m)) { +func (m *Memory) ld(ost uint64, n uint64) []byte { + if ost + n > uint64(len(*m)) { log.Fatal("trying to load out of memory") } - r := make([]byte, 32) - copy(r, (*m)[ost:ost+32]) + r := make([]byte, n) + copy(r, (*m)[ost:ost+n]) + return r +} + +func (m *Memory) lw(ost uint64) []byte { + r := m.ld(ost, 32) return r } diff --git a/vm/opcodes.go b/vm/opcodes.go index b3d4229..d1f6905 100644 --- a/vm/opcodes.go +++ b/vm/opcodes.go @@ -49,9 +49,18 @@ const ( PUSH30 = 0x7d PUSH31 = 0x7e PUSH32 = 0x7f + RETURN = 0xF3 //... ) func (op *Opcode) String() string { return Instructions[*op].name } + +func (o *Opcode) IsPush() byte { + d := *o - PUSH1 + if d >= 0 && d < 31 { + return byte(d) + 1 + } + return 0 +} @@ -1,16 +1,15 @@ package main import ( - "os" - "fmt" +// "os" +// "fmt" ) type Rom []byte func (r *Rom) Fetch(pc *uint64, n uint64) []byte { - if (*pc + n > uint64(len(*r)) - 1) { - fmt.Fprintf(os.Stderr, "error: trying to read outside of rom\n") - os.Exit(1) + if (*pc + n > uint64(len(*r))) { + return nil } x := make([]byte, n) copy(x, (*r)[*pc:*pc + n]) diff --git a/vm/stack.go b/vm/stack.go index fc1cbd4..ec2a738 100644 --- a/vm/stack.go +++ b/vm/stack.go @@ -2,8 +2,8 @@ package main import ( "log" - - "github.com/holiman/uint256" + "fmt" + "github.com/holiman/uint256" ) const STACK_CAP = (1 << 10) @@ -11,6 +11,7 @@ const STACK_CAP = (1 << 10) type Stack []uint256.Int func (s *Stack) Push(x *uint256.Int) { + fmt.Printf("pushing %s to stack\n", x.String()) *s = append(*s, *x) if len(*s) + 1 > STACK_CAP { log.Fatal("stack overflow") @@ -11,6 +11,7 @@ type Evm struct { memory Memory pc uint64 stopped bool + returndata []byte } func NewEvm(_code []byte) *Evm { @@ -19,25 +20,36 @@ func NewEvm(_code []byte) *Evm { stopped: true, stack : Stack{}, code: _code, + returndata: nil, } } -func (vm *Evm) Start() { +func (vm *Evm) Run() []byte { vm.stopped = false + fmt.Printf("code: ", vm.code) for !(vm.stopped) { - op := vm.code.Fetch(&(vm.pc), 1)[0] - fmt.Printf("pc: %d | opcode: %x -> string: %s\n", vm.pc, op, Instructions[op].name) - if op >= PUSH1 && op <= PUSH32 { - nb := op - PUSH1 + 1 - fmt.Printf("pushing %d byte value to the stack!\n", vm.pc, nb) - b := vm.code.Fetch(&(vm.pc), uint64(nb)) + s := vm.code.Fetch(&(vm.pc), 1) + op := Opcode(STOP) + if (s != nil) { + op = Opcode(s[0]) + } + + fmt.Printf("pc: %d | opcode: 0x%x -> string: %s\n", vm.pc, op, Instructions[op].name) + push := (&op).IsPush() + if (push != 0) { + b := vm.code.Fetch(&(vm.pc), uint64(push)) x := uint256.NewInt(0) x = x.SetBytes(b) vm.stack.Push(x) } else { - vm.Execute(op) + vm.Execute(byte(op)) } + + if (op == RETURN) { + return vm.returndata + } } + return nil } func (vm *Evm) Execute(op byte) { |