func main() { log.SetFlags(0) log.SetPrefix("armspec: ") if len(os.Args) != 2 { fmt.Fprintf(os.Stderr, "usage: armspec file.pdf\n") os.Exit(2) } f, err := pdf.Open(os.Args[1]) if err != nil { log.Fatal(err) } // Find instruction set reference in outline, to build instruction list. instList := instHeadings(f.Outline()) if len(instList) < 200 { log.Fatalf("only found %d instructions in table of contents", len(instList)) } stdout = bufio.NewWriter(os.Stdout) fmt.Fprintf(stdout, "[") numTable := 0 defer stdout.Flush() // Scan document looking for instructions. // Must find exactly the ones in the outline. n := f.NumPage() PageLoop: for pageNum := 1; pageNum <= n; pageNum++ { if debugPage > 0 && pageNum != debugPage { continue } if pageNum > 1127 { break } p := f.Page(pageNum) name, table := parsePage(pageNum, p) if name == "" { continue } if len(table) < 1 { if false { fmt.Fprintf(os.Stderr, "no encodings for instruction %q (page %d)\n", name, pageNum) } continue } for _, inst := range table { if numTable > 0 { fmt.Fprintf(stdout, ",") } numTable++ js, _ := json.Marshal(inst) fmt.Fprintf(stdout, "\n%s", jsFix.Replace(string(js))) } for j, headline := range instList { if name == headline { instList[j] = "" continue PageLoop } } fmt.Fprintf(os.Stderr, "unexpected instruction %q (page %d)\n", name, pageNum) } fmt.Fprintf(stdout, "\n]\n") stdout.Flush() if debugPage == 0 { for _, headline := range instList { if headline != "" { switch headline { default: fmt.Fprintf(os.Stderr, "missing instruction %q\n", headline) case "CHKA": // ThumbEE case "CPS": // system instruction case "CPY": // synonym for MOV case "ENTERX": // ThumbEE case "F* (former VFP instruction mnemonics)": // synonyms case "HB, HBL, HBLP, HBP": // ThumbEE case "LEAVEX": // ThumbEE case "MOV (shifted register)": // pseudo instruction for ASR, LSL, LSR, ROR, and RRX case "NEG": // synonym for RSB case "RFE": // system instruction case "SMC (previously SMI)": // system instruction case "SRS": // system instruction case "SUBS PC, LR and related instructions": // system instruction case "VAND (immediate)": // pseudo instruction case "VCLE (register)": // pseudo instruction case "VCLT (register)": // pseudo instruction case "VORN (immediate)": // pseudo instruction } } } } }
func main() { log.SetFlags(0) log.SetPrefix("armspec: ") if len(os.Args) != 2 { fmt.Fprintf(os.Stderr, "usage: armspec file.pdf\n") os.Exit(2) } f, err := pdf.Open(os.Args[1]) if err != nil { log.Fatal(err) } // Find instruction set reference in outline, to build instruction list. instList := instHeadings(f.Outline()) if len(instList) < 200 { log.Fatalf("only found %d instructions in table of contents", len(instList)) } var all = []Inst{ // Split across multiple columns and pages! {"Count Leading Zeros Word X-form", "cntlzw RA, RS (Rc=0)\ncntlzw. RA, RS (Rc=1)", "31@0|RS@6|RA@11|///@16|26@21|Rc@31|"}, } for j, headline := range instList { for _, inst := range all { if headline == inst.Name { instList[j] = "" break } } } // Scan document looking for instructions. // Must find exactly the ones in the outline. n := f.NumPage() for pageNum := 1; pageNum <= n; pageNum++ { if debugPage > 0 && pageNum != debugPage { continue } p := f.Page(pageNum) table := parsePage(pageNum, p) if len(table) == 0 { continue } InstLoop: for _, inst := range table { for j, headline := range instList { if inst.Name == headline { instList[j] = "" continue InstLoop } } fmt.Fprintf(os.Stderr, "page %d: unexpected instruction %q\n", pageNum, inst.Name) } all = append(all, table...) } if debugPage == 0 { for _, headline := range instList { if headline != "" { switch headline { default: fmt.Fprintf(os.Stderr, "missing instruction %q\n", headline) case "CHKA": // ThumbEE case "CPS": // system instruction case "CPY": // synonym for MOV case "ENTERX": // ThumbEE case "F* (former VFP instruction mnemonics)": // synonyms case "HB, HBL, HBLP, HBP": // ThumbEE case "LEAVEX": // ThumbEE case "MOV (shifted register)": // pseudo instruction for ASR, LSL, LSR, ROR, and RRX case "NEG": // synonym for RSB case "RFE": // system instruction case "SMC (previously SMI)": // system instruction case "SRS": // system instruction case "SUBS PC, LR and related instructions": // system instruction case "VAND (immediate)": // pseudo instruction case "VCLE (register)": // pseudo instruction case "VCLT (register)": // pseudo instruction case "VORN (immediate)": // pseudo instruction } } } } stdout = bufio.NewWriter(os.Stdout) for _, inst := range all { fmt.Fprintf(stdout, "%q,%q,%q,%q\n", inst.Name, strings.Replace(inst.Text, "\n", "|", -1), inst.Enc, "") } stdout.Flush() }