-
Notifications
You must be signed in to change notification settings - Fork 2
/
ops.go
155 lines (134 loc) · 3.34 KB
/
ops.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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package stackvm
import "fmt"
type op func(*Mach) error
type opDecoder func(arg uint32, have bool) op
type opCode uint8
const opCodeWithImm = opCode(0x80)
func (c opCode) String() string {
od := ops[c.code()]
name := od.name
if name == "" {
name = fmt.Sprintf("UNDEFINED<%#02x>", c.code())
}
if c.hasImm() {
return fmt.Sprintf("%s-%s", od.imm.short(), name)
}
return name
}
func (c opCode) hasImm() bool { return (c & opCodeWithImm) != 0 }
func (c opCode) code() uint8 { return uint8(c & ^opCodeWithImm) }
type opImmKind int
const (
opImmNone = opImmKind(iota)
opImmVal
opImmAddr
opImmOffset
opImmType = 0x0f
opImmFlags = ^0x0f
opImmReq = 0x010
)
func (k opImmKind) kind() opImmKind { return k & opImmType }
func (k opImmKind) required() bool { return (k & opImmReq) != 0 }
func (k opImmKind) short() string {
switch k {
case opImmNone:
return ""
case opImmVal:
return "val"
case opImmAddr:
return "addr"
case opImmOffset:
return "offset"
}
return fmt.Sprintf("Invalid<%d>", k)
}
func (k opImmKind) String() string {
switch k {
case opImmNone:
return "NoImmediate"
case opImmVal:
return "ImmediateVal"
case opImmAddr:
return "ImmediateAddr"
case opImmOffset:
return "ImmediateOffset"
}
return fmt.Sprintf("InvalidImmediate<%d>", k)
}
type opDef struct {
name string
imm opImmKind
}
var noop = opDef{}
func valop(name string) opDef { return opDef{name, opImmVal} }
func addrop(name string) opDef { return opDef{name, opImmAddr} }
func offop(name string) opDef { return opDef{name, opImmOffset} }
func justop(name string) opDef { return opDef{name, opImmNone} }
// TODO: mark required ops
// case opCodePush:
// m.err = errImmReq
// case opCodeCpush:
// m.err = errImmReq
var ops = [128]opDef{
// 0x00
justop("crash"), justop("nop"),
valop("push"), valop("pop"),
valop("dup"), valop("swap"),
noop, noop,
// 0x08
addrop("fetch"), valop("store"), addrop("storeTo"),
noop, noop, noop, noop, noop,
// 0x10
valop("add"), valop("sub"),
valop("mul"), valop("div"),
valop("mod"), valop("divmod"),
justop("neg"), noop,
// 0x18
valop("lt"), valop("lte"), valop("gt"), valop("gte"),
valop("eq"), valop("neq"), noop, noop,
// 0x20
justop("not"), justop("and"), justop("or"),
noop, noop, noop, noop, noop,
// 0x28
valop("cpush"), valop("cpop"), valop("p2c"), valop("c2p"),
justop("mark"), noop, noop, noop,
// 0x30
offop("jump"), offop("jnz"), offop("jz"),
addrop("call"), justop("ret"),
noop, noop, noop,
// 0x38
noop, noop, noop, noop, noop, noop, noop, noop,
// 0x40
offop("fork"), offop("fnz"), offop("fz"),
noop, noop, noop, noop, noop,
// 0x48
noop, noop, noop, noop, noop, noop, noop, noop,
// 0x50
offop("branch"), offop("bnz"), offop("bz"),
noop, noop, noop, noop, noop,
// 0x58
justop("bitnot"), valop("bitand"), valop("bitor"), valop("bitxor"),
valop("shiftl"), valop("shiftr"),
noop, noop,
// 0x60
addrop("bitest"),
addrop("bitset"),
addrop("bitost"),
addrop("bitseta"),
addrop("bitosta"),
noop, noop, noop,
// 0x68
noop, noop, noop, noop, noop, noop, noop, noop,
// 0x70
noop, noop, noop, noop, noop, noop, noop, noop,
// 0x78
noop, noop, noop, noop, noop,
valop("hnz"), valop("hz"), valop("halt"),
}
//go:generate python gen_op_codes.py -i ops.go -o op_codes.go
var opName2Code = make(map[string]byte, 128)
func init() {
for i, def := range ops {
opName2Code[def.name] = byte(i)
}
}