blob: 2db2126fc3edaf21e2737bb03a7662ccbc1fde38 [file]
// Copyright 2026 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.
// instgen is used to generate the ARM64 instruction table for encoding and decoding.
// Usage:
//
// instgen [-i=inputDir] [-o=outputDir] [-url=url] [-version=version]
//
// Users can download the ARM64 XML instruction manual from
// https://developer.arm.com/downloads/-/exploration-tools,
// decompress it, and pass the directory containing the latest XML
// instruction files by "-i" to instgen. Example:
//
// curl -o foo.gz https://developer.arm.com/-/cdn-downloads/permalink/Exploration-Tools-A64-ISA/ISA_A64/ISA_A64_xml_A_profile-2025-12.tar.gz
// mkdir foo
// (cd foo; tar xfz ../foo.gz)
// ./instgen -i foo/ISA_A64_xml_A_profile-2025-12
//
// If the user does not provide "-i" option, the program will try to do the above
// automatically, the temporary directory will be cleaned up after the program exits.
//
// The program parses and processes all the XML files, and generates four .go files:
// inst_gen.go, elem_gen.go, goops_gen.go and arm64ops_gen.go to the output directory.
// The output directory is assumed to be GOROOT, these four files will be generated to
// <outputDir>/src/cmd/internal/obj/arm64/.
//
// If -o option is not specified, no output files will be generated.
//
// Since the format of the ARM64 instruction specification document may update,
// this parser may not work for some versions of the XML document.
// Due to differences in documents between different versions, the generated instruction
// table may also be inconsistent, mainly elements. These differences need to be fixed
// when applying the output to the assembler and disassembler.
//
// The current implementation is based on version:
// https://developer.arm.com/-/cdn-downloads/permalink/Exploration-Tools-A64-ISA/ISA_A64/ISA_A64_xml_A_profile-2025-12.tar.gz
// And after decompressing the tarball, the latest version will be used, i.e. "ISA_A64_xml_A_profile-2025-12".
// Users can provide the url and version of the xml files by "-url" and "-version" options.
// But there is no guarantee that the logic of instgen will work for other versions.
package main
import (
"flag"
"log"
"os"
"golang.org/x/arch/arm64/instgen/xmlspec"
)
var input = flag.String("i", "", "the input directory of the xml files, this is an optional argument")
var output = flag.String("o", "", "the output directory of the generated files, this is an optional argument")
var genE2E = flag.Bool("e2e", false, "generate end-to-end test data")
var url = flag.String("url", xmlspec.ExpectedURL, "the url of the xml files")
var version = flag.String("version", xmlspec.ExpectedVersion, "the version of the xml files")
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
flag.Parse()
xmlDir := *input
if *input == "" {
tmpDir, err := os.MkdirTemp("", "instgen_xml_spec")
if err != nil {
// Failed to create a temporary directory, ask the user to provide the data then.
flag.Usage()
os.Exit(1)
}
defer os.RemoveAll(tmpDir)
xmlDir, err = xmlspec.GetArm64XMLSpec(tmpDir, *url, *version)
if err != nil {
// Get XML data from remote failed, ask the user to provide the data.
flag.Usage()
return
}
}
// Parse each xml file to insts.
insts := xmlspec.ParseXMLFiles(xmlDir)
xmlspec.ProcessXMLFiles(insts)
if *output != "" {
Generate(insts, *output, *genE2E)
}
errCnt := 0
for _, inst := range insts {
if inst == nil {
continue
}
if inst.ParseError != "" {
errCnt++
log.Printf("error: %s", inst.ParseError)
}
}
log.Printf("len(insts) = %v, error count = %v\n", len(insts), errCnt)
}