-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathmain.go
116 lines (99 loc) · 2.66 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright 2016 Jeffrey Wilcke
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package main
import (
"flag"
"fmt"
"os"
"github.com/obscuren/tinyvm/asm"
"github.com/obscuren/tinyvm/vm"
)
var (
versionFlag = flag.Bool("version", false, "outputs version string")
statFlag = flag.Bool("vmstats", false, "display virtual machine stats")
printCode = flag.Bool("printcode", false, "prints executing code in hex")
debug = flag.Bool("debug", false, "prints debug information during execution")
assemble = flag.Bool("assemble", false, "assembles the given .asm to an object file")
)
func main() {
flag.Parse()
if *versionFlag {
fmt.Println("TinyVM", vm.VersionString, "- (c) Jeffrey Wilcke")
os.Exit(0)
}
var (
code []byte
err error
)
if len(flag.Args()) > 0 {
var err error
code, err = os.ReadFile(flag.Args()[0])
if err != nil {
fmt.Println(err)
os.Exit(1)
}
code, err = asm.Assemble(string(code))
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if *assemble {
outPath := "out.obj"
if (len(flag.Args()) > 1) {
outPath = flag.Args()[1]
}
if err := os.WriteFile(outPath, code, 0o600); err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Printf("%s file successfully assembled: %s\n", flag.Args()[0], outPath)
os.Exit(0)
}
} else {
err = fmt.Errorf("usage: tinyvm <flags> filename")
}
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if *printCode {
fmt.Printf("(len=%d) %x\n", len(code), code)
for i := 0; i < len(code); i += 4 {
for _, b := range code[i : i+4] {
fmt.Printf("%08b", b)
}
fmt.Printf(" ")
}
fmt.Println()
}
v := vm.New(*debug)
for i, registerFlag := range registerFlags {
v.Set(asm.Reg, uint32(i), uint32(*registerFlag))
}
if err := v.Exec(code); err != nil {
fmt.Println("err", err)
os.Exit(1)
}
if *statFlag {
v.Stats()
}
fmt.Println(v.Get(asm.Reg, asm.R0))
}
var registerFlags [asm.MaxRegister]*int
func init() {
for i := 0; i < asm.MaxRegister; i++ {
registerFlags[i] = flag.Int(fmt.Sprintf("r%d", i), 0, fmt.Sprintf("sets the r%d register", i))
}
}