golang.org/x/arch@v0.17.0/arm/armspec/specmap.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build ignore 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 //checkOverlap(used, insts) 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 }