1
2
3
4
5
6
7 package main
8
9 import (
10 "encoding/json"
11 "fmt"
12 "io/ioutil"
13 "log"
14 "os"
15 "regexp"
16 "strconv"
17 "strings"
18 )
19
20 var _ = os.Stdout
21 var _ = fmt.Sprintf
22
23 type Inst struct {
24 Name string
25 ID string
26 Bits string
27 Arch string
28 Syntax []string
29 Code string
30 Base uint32
31 Mask uint32
32 Prog []*Stmt
33 }
34
35 func main() {
36 data, err := ioutil.ReadFile("spec.json")
37 if err != nil {
38 log.Fatal(err)
39 }
40 var insts []Inst
41 if err := json.Unmarshal(data, &insts); err != nil {
42 log.Fatal(err)
43 }
44
45 var out []Inst
46 for _, inst := range insts {
47 inst.Prog = parse(inst.Name+" "+inst.ID, inst.Code)
48 if inst.ID[0] == 'A' && !strings.HasPrefix(inst.Syntax[0], "MSR<c>") && !strings.Contains(inst.Syntax[0], "<coproc>") && !strings.Contains(inst.Syntax[0], "VLDM") && !strings.Contains(inst.Syntax[0], "VSTM") {
49 out = append(out, inst)
50 }
51 }
52 insts = out
53
54 for i := range insts {
55 dosize(&insts[i])
56 }
57
58 var cond, special []Inst
59 for _, inst := range insts {
60 if inst.Base>>28 == 0xF {
61 special = append(special, inst)
62 } else {
63 cond = append(cond, inst)
64 }
65 }
66
67 fmt.Printf("special:\n")
68 split(special, 0xF0000000, 1)
69 fmt.Printf("cond:\n")
70 split(cond, 0xF0000000, 1)
71 }
72
73 func dosize(inst *Inst) {
74 var base, mask uint32
75 off := 0
76 for _, f := range strings.Split(inst.Bits, "|") {
77 if i := strings.Index(f, ":"); i >= 0 {
78 n, _ := strconv.Atoi(f[i+1:])
79 off += n
80 continue
81 }
82 for _, bit := range strings.Fields(f) {
83 switch bit {
84 case "0", "(0)":
85 mask |= 1 << uint(31-off)
86 case "1", "(1)":
87 base |= 1 << uint(31-off)
88 }
89 off++
90 }
91 }
92 if off != 16 && off != 32 {
93 log.Printf("incorrect bit count for %s %s: have %d", inst.Name, inst.Bits, off)
94 }
95 if off == 16 {
96 mask >>= 16
97 base >>= 16
98 }
99 mask |= base
100 inst.Mask = mask
101 inst.Base = base
102 }
103
104 func split(insts []Inst, used uint32, depth int) {
105 Again:
106 if len(insts) <= 1 {
107 for _, inst := range insts {
108 fmt.Printf("%*s%#08x %#08x %s %s %v\n", depth*2+2, "", inst.Mask, inst.Base, inst.Syntax[0], inst.Bits, seeRE.FindAllString(inst.Code, -1))
109 }
110 return
111 }
112
113 m := ^used
114 for _, inst := range insts {
115 m &= inst.Mask
116 }
117 if m == 0 {
118 fmt.Printf("«%*s%#08x masked out (%d)\n", depth*2, "", used, len(insts))
119 for _, inst := range insts {
120 fmt.Printf("%*s%#08x %#08x %s %s %v\n", depth*2+2, "", inst.Mask, inst.Base, inst.Syntax[0], inst.Bits, seeRE.FindAllString(inst.Code, -1))
121 }
122 updated := false
123 for i := range insts {
124 if updateMask(&insts[i]) {
125 updated = true
126 }
127 }
128 fmt.Printf("»\n")
129 if updated {
130 goto Again
131 }
132 fmt.Printf("%*s%#08x masked out (%d)\n", depth*2, "", used, len(insts))
133 for _, inst := range insts {
134 fmt.Printf("%*s%#08x %#08x %s %s %v\n", depth*2+2, "", inst.Mask, inst.Base, inst.Syntax[0], inst.Bits, seeRE.FindAllString(inst.Code, -1))
135 }
136
137 return
138 }
139 for i := 31; i >= 0; i-- {
140 if m&(1<<uint(i)) != 0 {
141 m = 1 << uint(i)
142 break
143 }
144 }
145 var bit [2][]Inst
146 for _, inst := range insts {
147 b := (inst.Base / m) & 1
148 bit[b] = append(bit[b], inst)
149 }
150
151 for b, list := range bit {
152 if len(list) > 0 {
153 suffix := ""
154 if len(bit[1-b]) == 0 {
155 suffix = " (only)"
156 }
157 fmt.Printf("%*sbit %#08x = %d%s\n", depth*2, "", m, b, suffix)
158 split(list, used|m, depth+1)
159 }
160 }
161 }
162
163 var seeRE = regexp.MustCompile(`SEE ([^;\n]+)`)
164
165 func updateMask(inst *Inst) bool {
166 defer func() {
167 if err := recover(); err != nil {
168 fmt.Println("PANIC:", err)
169 return
170 }
171 }()
172
173 print(".")
174 println(inst.Name, inst.ID, inst.Bits)
175 println(inst.Code)
176 wiggle := ^inst.Mask &^ 0xF0000000
177 n := countbits(wiggle)
178 m1 := ^uint32(0)
179 m2 := ^uint32(0)
180 for i := uint32(0); i < 1<<uint(n); i++ {
181 w := inst.Base | expand(i, wiggle)
182 if !isValid(inst, w) {
183 continue
184 }
185 m1 &= w
186 m2 &= ^w
187 }
188 m := m1 | m2
189 m &^= 0xF0000000
190 m |= 0xF0000000 & inst.Mask
191 if m&^inst.Mask != 0 {
192 fmt.Printf("%s %s: mask=%#x but decided %#x\n", inst.Name, inst.ID, inst.Mask, m)
193 inst.Mask = m
194 inst.Base = m1
195 return true
196 }
197 if inst.Mask&^m != 0 {
198 fmt.Printf("%s %s: mask=%#x but got %#x\n", inst.Name, inst.ID, inst.Mask, m)
199 panic("bad updateMask")
200 }
201 return false
202 }
203
204 func countbits(x uint32) int {
205 n := 0
206 for ; x != 0; x >>= 1 {
207 n += int(x & 1)
208 }
209 return n
210 }
211
212 func expand(x, m uint32) uint32 {
213 var out uint32
214 for i := uint(0); i < 32; i++ {
215 out >>= 1
216 if m&1 != 0 {
217 out |= (x & 1) << 31
218 x >>= 1
219 }
220 m >>= 1
221 }
222 return out
223 }
224
View as plain text