// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build ignore package main import ( "encoding/json" "fmt" "io/ioutil" "log" "os" "regexp" "strconv" "strings" ) var _ = os.Stdout var _ = fmt.Sprintf type Inst struct { Name string ID string Bits string Arch string Syntax []string Code string Base uint32 Mask uint32 Prog []*Stmt } func main() { data, err := ioutil.ReadFile("spec.json") if err != nil { log.Fatal(err) } var insts []Inst if err := json.Unmarshal(data, &insts); err != nil { log.Fatal(err) } var out []Inst for _, inst := range insts { inst.Prog = parse(inst.Name+" "+inst.ID, inst.Code) if inst.ID[0] == 'A' && !strings.HasPrefix(inst.Syntax[0], "MSR") && !strings.Contains(inst.Syntax[0], "") && !strings.Contains(inst.Syntax[0], "VLDM") && !strings.Contains(inst.Syntax[0], "VSTM") { out = append(out, inst) } } insts = out for i := range insts { dosize(&insts[i]) } var cond, special []Inst for _, inst := range insts { if inst.Base>>28 == 0xF { special = append(special, inst) } else { cond = append(cond, inst) } } fmt.Printf("special:\n") split(special, 0xF0000000, 1) fmt.Printf("cond:\n") split(cond, 0xF0000000, 1) } func dosize(inst *Inst) { var base, mask uint32 off := 0 for _, f := range strings.Split(inst.Bits, "|") { if i := strings.Index(f, ":"); i >= 0 { n, _ := strconv.Atoi(f[i+1:]) off += n continue } for _, bit := range strings.Fields(f) { switch bit { case "0", "(0)": mask |= 1 << uint(31-off) case "1", "(1)": base |= 1 << uint(31-off) } off++ } } if off != 16 && off != 32 { log.Printf("incorrect bit count for %s %s: have %d", inst.Name, inst.Bits, off) } if off == 16 { mask >>= 16 base >>= 16 } mask |= base inst.Mask = mask inst.Base = base } func split(insts []Inst, used uint32, depth int) { Again: if len(insts) <= 1 { for _, inst := range insts { 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)) } return } m := ^used for _, inst := range insts { m &= inst.Mask } if m == 0 { fmt.Printf("«%*s%#08x masked out (%d)\n", depth*2, "", used, len(insts)) for _, inst := range insts { 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)) } updated := false for i := range insts { if updateMask(&insts[i]) { updated = true } } fmt.Printf("»\n") if updated { goto Again } fmt.Printf("%*s%#08x masked out (%d)\n", depth*2, "", used, len(insts)) for _, inst := range insts { 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)) } //checkOverlap(used, insts) return } for i := 31; i >= 0; i-- { if m&(1< 0 { suffix := "" if len(bit[1-b]) == 0 { suffix = " (only)" } fmt.Printf("%*sbit %#08x = %d%s\n", depth*2, "", m, b, suffix) split(list, used|m, depth+1) } } } var seeRE = regexp.MustCompile(`SEE ([^;\n]+)`) func updateMask(inst *Inst) bool { defer func() { if err := recover(); err != nil { fmt.Println("PANIC:", err) return } }() print(".") println(inst.Name, inst.ID, inst.Bits) println(inst.Code) wiggle := ^inst.Mask &^ 0xF0000000 n := countbits(wiggle) m1 := ^uint32(0) m2 := ^uint32(0) for i := uint32(0); i < 1<>= 1 { n += int(x & 1) } return n } func expand(x, m uint32) uint32 { var out uint32 for i := uint(0); i < 32; i++ { out >>= 1 if m&1 != 0 { out |= (x & 1) << 31 x >>= 1 } m >>= 1 } return out }