riscv64: add tests for riscv64asm
Add validation tests for riscv64asm GNU/Plan9 decoder, including
objdump test and external test.
Change-Id: Id7442704ea7e10c22ca4a799cdfc9f7d043f85c3
Reviewed-on: https://go-review.googlesource.com/c/arch/+/602916
Reviewed-by: Meng Zhuo <mengzhuo1203@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Mark Ryan <markdryan@rivosinc.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
diff --git a/riscv64/riscv64asm/decode_test.go b/riscv64/riscv64asm/decode_test.go
new file mode 100644
index 0000000..1590aaa
--- /dev/null
+++ b/riscv64/riscv64asm/decode_test.go
@@ -0,0 +1,80 @@
+// Copyright 2024 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.
+
+package riscv64asm
+
+import (
+ "bufio"
+ "encoding/hex"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+)
+
+func testDecode(t *testing.T, syntax string) {
+ input := filepath.Join("testdata", syntax+"cases.txt")
+ f, err := os.Open(input)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+ scanner := bufio.NewScanner(f)
+ for scanner.Scan() {
+ line := strings.TrimSpace(scanner.Text())
+ if line == "" || strings.HasPrefix(line, "#") {
+ continue
+ }
+ f := strings.SplitN(line, "\t", 2)
+ i := strings.Index(f[0], "|")
+
+ if i < 0 {
+ t.Errorf("parsing %q: missing | separator", f[0])
+ continue
+ }
+ if i%2 != 0 {
+ t.Errorf("parsing %q: misaligned | separator", f[0])
+ }
+ code, err := hex.DecodeString(f[0][:i] + f[0][i+1:])
+ if err != nil {
+ t.Errorf("parsing %q: %v", f[0], err)
+ continue
+ }
+ asm0 := strings.Replace(f[1], " ", " ", -1)
+ asm := strings.TrimSpace(asm0)
+ inst, decodeErr := Decode(code)
+ if decodeErr != nil && decodeErr != errUnknown {
+ if asm == "illegalins" && decodeErr == errShort {
+ continue
+ }
+ // Some rarely used system instructions are not supported
+ // Following logicals will filter such unknown instructions
+ t.Errorf("parsing %x: %s", code, decodeErr)
+ continue
+ }
+
+ var out string
+ switch syntax {
+ case "gnu":
+ out = GNUSyntax(inst)
+ case "plan9":
+ out = GoSyntax(inst, 0, nil, nil)
+ default:
+ t.Errorf("unknown syntax %q", syntax)
+ continue
+ }
+
+ if asm != out {
+ t.Errorf("Decode(%s) [%s] = %s want %s", f[0], syntax, out, asm)
+ }
+ }
+}
+
+func TestDecodeGNUSyntax(t *testing.T) {
+ testDecode(t, "gnu")
+}
+
+func TestDecodeGoSyntax(t *testing.T) {
+ testDecode(t, "plan9")
+}
diff --git a/riscv64/riscv64asm/ext_test.go b/riscv64/riscv64asm/ext_test.go
new file mode 100644
index 0000000..fa6961f
--- /dev/null
+++ b/riscv64/riscv64asm/ext_test.go
@@ -0,0 +1,330 @@
+// Copyright 2024 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.
+
+// Support for testing against external disassembler program.
+
+package riscv64asm
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/hex"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "math/rand"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "testing"
+ "time"
+)
+
+var (
+ dumpTest = flag.Bool("dump", false, "dump all encodings")
+ mismatch = flag.Bool("mismatch", false, "log allowed mismatches")
+ keep = flag.Bool("keep", false, "keep object files around")
+ debug = false
+)
+
+// An ExtInst represents a single decoded instruction parsed
+// from an external disassembler's output.
+type ExtInst struct {
+ addr uint64
+ enc [4]byte
+ nenc int
+ text string
+}
+
+func (r ExtInst) String() string {
+ return fmt.Sprintf("%#x: % x: %s", r.addr, r.enc, r.text)
+}
+
+// An ExtDis is a connection between an external disassembler and a test.
+type ExtDis struct {
+ Dec chan ExtInst
+ File *os.File
+ Size int
+ Cmd *exec.Cmd
+}
+
+// Run runs the given command - the external disassembler - and returns
+// a buffered reader of its standard output.
+func (ext *ExtDis) Run(cmd ...string) (*bufio.Reader, error) {
+ if *keep {
+ log.Printf("%s\n", strings.Join(cmd, " "))
+ }
+ ext.Cmd = exec.Command(cmd[0], cmd[1:]...)
+ out, err := ext.Cmd.StdoutPipe()
+ if err != nil {
+ return nil, fmt.Errorf("stdoutpipe: %v", err)
+ }
+ if err := ext.Cmd.Start(); err != nil {
+ return nil, fmt.Errorf("exec: %v", err)
+ }
+
+ b := bufio.NewReaderSize(out, 1<<20)
+ return b, nil
+}
+
+// Wait waits for the command started with Run to exit.
+func (ext *ExtDis) Wait() error {
+ return ext.Cmd.Wait()
+}
+
+// testExtDis tests a set of byte sequences against an external disassembler.
+// The disassembler is expected to produce the given syntax and run
+// in the given architecture mode (16, 32, or 64-bit).
+// The extdis function must start the external disassembler
+// and then parse its output, sending the parsed instructions on ext.Dec.
+// The generate function calls its argument f once for each byte sequence
+// to be tested. The generate function itself will be called twice, and it must
+// make the same sequence of calls to f each time.
+// When a disassembly does not match the internal decoding,
+// allowedMismatch determines whether this mismatch should be
+// allowed, or else considered an error.
+func testExtDis(
+ t *testing.T,
+ syntax string,
+ extdis func(ext *ExtDis) error,
+ generate func(f func([]byte)),
+ allowedMismatch func(text string, inst *Inst, dec ExtInst) bool,
+) {
+ start := time.Now()
+ ext := &ExtDis{
+ Dec: make(chan ExtInst),
+ }
+ errc := make(chan error)
+
+ // First pass: write instructions to input file for external disassembler.
+ file, f, size, err := writeInst(generate)
+ if err != nil {
+ t.Fatal(err)
+ }
+ ext.Size = size
+ ext.File = f
+ defer func() {
+ f.Close()
+ if !*keep {
+ os.Remove(file)
+ }
+ }()
+
+ // Second pass: compare disassembly against our decodings.
+ var (
+ totalTests = 0
+ totalSkips = 0
+ totalErrors = 0
+
+ errors = make([]string, 0, 100) // Sampled errors, at most cap
+ )
+ go func() {
+ errc <- extdis(ext)
+ }()
+
+ generate(func(enc []byte) {
+ dec, ok := <-ext.Dec
+ if !ok {
+ t.Errorf("decoding stream ended early")
+ return
+ }
+ inst, text := disasm(syntax, pad(enc))
+
+ totalTests++
+ if *dumpTest {
+ fmt.Printf("%x -> %s [%d]\n", enc, dec.text, dec.nenc)
+ }
+
+ if text != dec.text && !strings.Contains(dec.text, "unknown") && syntax == "gnu" {
+ suffix := ""
+ if allowedMismatch(text, &inst, dec) {
+ totalSkips++
+ if !*mismatch {
+ return
+ }
+ suffix += " (allowed mismatch)"
+ }
+ totalErrors++
+ cmp := fmt.Sprintf("decode(%x) = %q, %d, want %q, %d%s\n", enc, text, len(enc), dec.text, dec.nenc, suffix)
+
+ if len(errors) >= cap(errors) {
+ j := rand.Intn(totalErrors)
+ if j >= cap(errors) {
+ return
+ }
+ errors = append(errors[:j], errors[j+1:]...)
+ }
+ errors = append(errors, cmp)
+ }
+ })
+
+ if *mismatch {
+ totalErrors -= totalSkips
+ }
+
+ fmt.Printf("totalTest: %d total skip: %d total error: %d\n", totalTests, totalSkips, totalErrors)
+ // Here are some errors about mismatches(44)
+ for _, b := range errors {
+ t.Log(b)
+ }
+
+ if totalErrors > 0 {
+ t.Fail()
+ }
+ t.Logf("%d test cases, %d expected mismatches, %d failures; %.0f cases/second", totalTests, totalSkips, totalErrors, float64(totalTests)/time.Since(start).Seconds())
+ t.Logf("decoder coverage: %.1f%%;\n", decodeCoverage())
+}
+
+// Start address of text.
+const start = 0x8000
+
+// writeInst writes the generated byte sequences to a new file
+// starting at offset start. That file is intended to be the input to
+// the external disassembler.
+func writeInst(generate func(func([]byte))) (file string, f *os.File, size int, err error) {
+ f, err = ioutil.TempFile("", "riscv64asm")
+ if err != nil {
+ return
+ }
+
+ file = f.Name()
+
+ f.Seek(start, io.SeekStart)
+ w := bufio.NewWriter(f)
+ defer w.Flush()
+ size = 0
+ generate(func(x []byte) {
+ if debug {
+ fmt.Printf("%#x: %x%x\n", start+size, x, zeros[len(x):])
+ }
+ w.Write(x)
+ w.Write(zeros[len(x):])
+ size += len(zeros)
+ })
+ return file, f, size, nil
+}
+
+var zeros = []byte{0, 0, 0, 0}
+
+// pad pads the code sequence with pops.
+func pad(enc []byte) []byte {
+ if len(enc) < 4 {
+ enc = append(enc[:len(enc):len(enc)], zeros[:4-len(enc)]...)
+ }
+ return enc
+}
+
+// disasm returns the decoded instruction and text
+// for the given source bytes, using the given syntax and mode.
+func disasm(syntax string, src []byte) (inst Inst, text string) {
+ var err error
+ inst, err = Decode(src)
+ if err != nil {
+ text = "error: " + err.Error()
+ return
+ }
+ text = inst.String()
+ switch syntax {
+ case "gnu":
+ text = GNUSyntax(inst)
+ case "plan9": // [sic]
+ text = GoSyntax(inst, 0, nil, nil)
+ default:
+ text = "error: unknown syntax " + syntax
+ }
+ return
+}
+
+// decodecoverage returns a floating point number denoting the
+// decoder coverage.
+func decodeCoverage() float64 {
+ n := 0
+ for _, t := range decoderCover {
+ if t {
+ n++
+ }
+ }
+ return 100 * float64(1+n) / float64(1+len(decoderCover))
+}
+
+// Helpers for writing disassembler output parsers.
+
+// isHex reports whether b is a hexadecimal character (0-9a-fA-F).
+func isHex(b byte) bool {
+ return ('0' <= b && b <= '9') || ('a' <= b && b <= 'f') || ('A' <= b && b <= 'F')
+}
+
+// parseHex parses the hexadecimal byte dump in src,
+// appending the parsed bytes to raw and returning the updated slice.
+// The returned bool reports whether any invalid hex was found.
+// Spaces and tabs between bytes are okay but any other non-hex is not.
+func parseHex(src []byte, raw []byte) ([]byte, bool) {
+ src = bytes.TrimSpace(src)
+ raw, err := hex.AppendDecode(raw, src)
+ if err != nil {
+ return nil, false
+ }
+ return raw, true
+}
+
+// Generators.
+//
+// The test cases are described as functions that invoke a callback repeatedly,
+// with a new input sequence each time. These helpers make writing those
+// a little easier.
+
+// hexCases generates the cases written in hexadecimal in the encoded string.
+// Spaces in 'encoded' separate entire test cases, not individual bytes.
+func hexCases(t *testing.T, encoded string) func(func([]byte)) {
+ return func(try func([]byte)) {
+ for _, x := range strings.Fields(encoded) {
+ src, err := hex.DecodeString(x)
+ if err != nil {
+ t.Errorf("parsing %q: %v", x, err)
+ }
+ try(src)
+ }
+ }
+}
+
+// testdataCases generates the test cases recorded in testdata/cases.txt.
+// It only uses the inputs; it ignores the answers recorded in that file.
+func testdataCases(t *testing.T, syntax string) func(func([]byte)) {
+ var codes [][]byte
+ input := filepath.Join("testdata", syntax+"cases.txt")
+ data, err := ioutil.ReadFile(input)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, line := range strings.Split(string(data), "\n") {
+ line = strings.TrimSpace(line)
+ if line == "" || strings.HasPrefix(line, "#") {
+ continue
+ }
+ f := strings.Fields(line)[0]
+ i := strings.Index(f, "|")
+ if i < 0 {
+ t.Errorf("parsing %q: missing | separator", f)
+ continue
+ }
+ if i%2 != 0 {
+ t.Errorf("parsing %q: misaligned | separator", f)
+ }
+ code, err := hex.DecodeString(f[:i] + f[i+1:])
+ if err != nil {
+ t.Errorf("parsing %q: %v", f, err)
+ continue
+ }
+ codes = append(codes, code)
+ }
+
+ return func(try func([]byte)) {
+ for _, code := range codes {
+ try(code)
+ }
+ }
+}
diff --git a/riscv64/riscv64asm/objdump_test.go b/riscv64/riscv64asm/objdump_test.go
new file mode 100644
index 0000000..479301b
--- /dev/null
+++ b/riscv64/riscv64asm/objdump_test.go
@@ -0,0 +1,86 @@
+// Copyright 2024 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.
+
+package riscv64asm
+
+import (
+ "strings"
+ "testing"
+)
+
+func TestObjdumpRISCV64TestDecodeGNUSyntaxdata(t *testing.T) {
+ testObjdumpRISCV64(t, testdataCases(t, "gnu"))
+}
+func TestObjdumpRISCV64TestDecodeGoSyntaxdata(t *testing.T) {
+ testObjdumpRISCV64(t, testdataCases(t, "plan9"))
+}
+
+func TestObjdumpRISCV64Manual(t *testing.T) {
+ testObjdumpRISCV64(t, hexCases(t, objdumpManualTests))
+}
+
+// objdumpManualTests holds test cases that will be run by TestObjdumpRISCV64Manual.
+// If you are debugging a few cases that turned up in a longer run, it can be useful
+// to list them here and then use -run=Manual, particularly with tracing enabled.
+// Note that these are byte sequences, so they must be reversed from the usual
+// word presentation.
+var objdumpManualTests = `
+93020300
+13000000
+9b020300
+afb5b50e
+73b012c0
+73f01fc0
+73a012c0
+73e01fc0
+f3223000
+f3221000
+f3222000
+f3123300
+f3121300
+f3122300
+739012c0
+73d01fc0
+53a01022
+53a01020
+53801022
+53801020
+53901022
+53901020
+67800000
+67800200
+b3026040
+bb026040
+9342f3ff
+f32200c0
+f32200c8
+f32220c0
+f32220c8
+f32210c0
+f32210c8
+`
+
+// allowedMismatchObjdump reports whether the mismatch between text and dec
+// should be allowed by the test.
+func allowedMismatchObjdump(text string, inst *Inst, dec ExtInst) bool {
+ // Allow the mismatch of Branch/Jump instruction's offset.
+ decsp := strings.Split(dec.text, ",")
+
+ switch inst.Op {
+ case BEQ, BGE, BGEU, BLT, BLTU, BNE:
+ if inst.Args[2].(Simm).String() != decsp[len(decsp)-1] {
+ return true
+ }
+ case JAL:
+ if inst.Args[1].(Simm).String() != decsp[len(decsp)-1] {
+ return true
+ }
+ case JALR:
+ if inst.Args[1].(RegOffset).Ofs.String() != decsp[len(decsp)-1] {
+ return true
+ }
+ }
+
+ return false
+}
diff --git a/riscv64/riscv64asm/objdumpext_test.go b/riscv64/riscv64asm/objdumpext_test.go
new file mode 100644
index 0000000..4f1f21a
--- /dev/null
+++ b/riscv64/riscv64asm/objdumpext_test.go
@@ -0,0 +1,299 @@
+// Copyright 2024 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.
+
+package riscv64asm
+
+import (
+ "bytes"
+ "debug/elf"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "os/exec"
+ "strconv"
+ "strings"
+ "testing"
+)
+
+var objdumpPath = "riscv64-linux-gnu-objdump"
+
+func testObjdumpRISCV64(t *testing.T, generate func(func([]byte))) {
+ testObjdumpArch(t, generate)
+}
+
+func testObjdumpArch(t *testing.T, generate func(func([]byte))) {
+ checkObjdumpRISCV64(t)
+ testExtDis(t, "gnu", objdump, generate, allowedMismatchObjdump)
+ testExtDis(t, "plan9", objdump, generate, allowedMismatchObjdump)
+}
+
+func checkObjdumpRISCV64(t *testing.T) {
+ objdumpPath, err := exec.LookPath(objdumpPath)
+ if err != nil {
+ objdumpPath = "objdump"
+ }
+ out, err := exec.Command(objdumpPath, "-i").Output()
+ if err != nil {
+ t.Skipf("cannot run objdump: %v\n%s", err, out)
+ }
+ if !strings.Contains(string(out), "riscv") {
+ t.Skip("objdump does not have RISC-V support")
+ }
+}
+
+func objdump(ext *ExtDis) error {
+ // File already written with instructions; add ELF header.
+ if err := writeELF64(ext.File, ext.Size); err != nil {
+ return err
+ }
+
+ b, err := ext.Run(objdumpPath, "-M numeric", "-d", "-z", ext.File.Name())
+ if err != nil {
+ return err
+ }
+
+ var (
+ nmatch int
+ reading bool
+ next uint64 = start
+ addr uint64
+ encbuf [4]byte
+ enc []byte
+ text string
+ )
+ flush := func() {
+ if addr == next {
+ // PC-relative addresses are translated to absolute addresses based on PC by GNU objdump
+ // Following logical rewrites the absolute addresses back to PC-relative ones for comparing
+ // with our disassembler output which are PC-relative
+ if text == "undefined" && len(enc) == 4 {
+ text = "error: unknown instruction"
+ enc = nil
+ }
+ if len(enc) == 4 {
+ // prints as word but we want to record bytes
+ enc[0], enc[3] = enc[3], enc[0]
+ enc[1], enc[2] = enc[2], enc[1]
+ }
+ ext.Dec <- ExtInst{addr, encbuf, len(enc), text}
+ encbuf = [4]byte{}
+ enc = nil
+ next += 4
+ }
+ }
+ var textangle = []byte("<.text>:")
+ for {
+ line, err := b.ReadSlice('\n')
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ return fmt.Errorf("reading objdump output: %v", err)
+ }
+ if bytes.Contains(line, textangle) {
+ reading = true
+ continue
+ }
+ if !reading {
+ continue
+ }
+ if debug {
+ os.Stdout.Write(line)
+ }
+ if enc1 := parseContinuation(line, encbuf[:len(enc)]); enc1 != nil {
+ enc = enc1
+ continue
+ }
+ flush()
+ nmatch++
+ addr, enc, text = parseLine(line, encbuf[:0])
+ if addr > next {
+ return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line)
+ }
+ }
+ flush()
+ if next != start+uint64(ext.Size) {
+ return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size)
+ }
+ if err := ext.Wait(); err != nil {
+ return fmt.Errorf("exec: %v", err)
+ }
+
+ return nil
+}
+
+var (
+ undefined = []byte("undefined")
+ unpredictable = []byte("unpredictable")
+ slashslash = []byte("//")
+)
+
+func parseLine(line []byte, encstart []byte) (addr uint64, enc []byte, text string) {
+ ok := false
+ oline := line
+ i := bytes.Index(line, []byte(":\t"))
+ if i < 0 {
+ log.Fatalf("cannot parse disassembly: %q", oline)
+ }
+ x, err := strconv.ParseUint(string(bytes.TrimSpace(line[:i])), 16, 32)
+ if err != nil {
+ log.Fatalf("cannot parse disassembly: %q", oline)
+ }
+ addr = uint64(x)
+ line = line[i+2:]
+ i = bytes.IndexByte(line, '\t')
+ if i < 0 {
+ log.Fatalf("cannot parse disassembly: %q", oline)
+ }
+ enc, ok = parseHex(line[:i], encstart)
+ if !ok {
+ log.Fatalf("cannot parse disassembly: %q", oline)
+ }
+ line = bytes.TrimSpace(line[i:])
+ if bytes.Contains(line, undefined) {
+ text = "undefined"
+ return
+ }
+ if false && bytes.Contains(line, unpredictable) {
+ text = "unpredictable"
+ return
+ }
+ // Strip trailing comment starting with '#'
+ if i := bytes.IndexByte(line, '#'); i >= 0 {
+ line = bytes.TrimSpace(line[:i])
+ }
+ // Strip trailing comment starting with "//"
+ if i := bytes.Index(line, slashslash); i >= 0 {
+ line = bytes.TrimSpace(line[:i])
+ }
+ text = string(fixSpace(line))
+ return
+}
+
+// fixSpace rewrites runs of spaces, tabs, and newline characters into single spaces in s.
+// If s must be rewritten, it is rewritten in place.
+func fixSpace(s []byte) []byte {
+ s = bytes.TrimSpace(s)
+ for i := 0; i < len(s); i++ {
+ if s[i] == '\t' || s[i] == '\n' || i > 0 && s[i] == ' ' && s[i-1] == ' ' {
+ goto Fix
+ }
+ }
+ return s
+
+Fix:
+ b := s
+ w := 0
+ for i := 0; i < len(s); i++ {
+ c := s[i]
+ if c == '\t' || c == '\n' {
+ c = ' '
+ }
+ if c == ' ' && w > 0 && b[w-1] == ' ' {
+ continue
+ }
+ b[w] = c
+ w++
+ }
+ if w > 0 && b[w-1] == ' ' {
+ w--
+ }
+ return b[:w]
+}
+
+func parseContinuation(line []byte, enc []byte) []byte {
+ i := bytes.Index(line, []byte(":\t"))
+ if i < 0 {
+ return nil
+ }
+ line = line[i+1:]
+ enc, _ = parseHex(line, enc)
+ return enc
+}
+
+// writeELF64 writes an ELF64 header to the file, describing a text
+// segment that starts at start (0x8000) and extends for size bytes.
+func writeELF64(f *os.File, size int) error {
+ f.Seek(0, io.SeekStart)
+ var hdr elf.Header64
+ var prog elf.Prog64
+ var sect elf.Section64
+ var buf bytes.Buffer
+ binary.Write(&buf, binary.LittleEndian, &hdr)
+ off1 := buf.Len()
+ binary.Write(&buf, binary.LittleEndian, &prog)
+ off2 := buf.Len()
+ binary.Write(&buf, binary.LittleEndian, §)
+ off3 := buf.Len()
+ buf.Reset()
+ data := byte(elf.ELFDATA2LSB)
+ hdr = elf.Header64{
+ Ident: [16]byte{0x7F, 'E', 'L', 'F', 2, data, 1},
+ Type: 2,
+ Machine: uint16(elf.EM_RISCV),
+ Version: 1,
+ Entry: start,
+ Phoff: uint64(off1),
+ Shoff: uint64(off2),
+ Flags: 0x5,
+ Ehsize: uint16(off1),
+ Phentsize: uint16(off2 - off1),
+ Phnum: 1,
+ Shentsize: uint16(off3 - off2),
+ Shnum: 4,
+ Shstrndx: 3,
+ }
+ binary.Write(&buf, binary.LittleEndian, &hdr)
+ prog = elf.Prog64{
+ Type: 1,
+ Off: start,
+ Vaddr: start,
+ Paddr: start,
+ Filesz: uint64(size),
+ Memsz: uint64(size),
+ Flags: 5,
+ Align: start,
+ }
+ binary.Write(&buf, binary.LittleEndian, &prog)
+ binary.Write(&buf, binary.LittleEndian, §) // NULL section
+ sect = elf.Section64{
+ Name: 1,
+ Type: uint32(elf.SHT_PROGBITS),
+ Addr: start,
+ Off: start,
+ Size: uint64(size),
+ Flags: uint64(elf.SHF_ALLOC | elf.SHF_EXECINSTR),
+ Addralign: 4,
+ }
+ binary.Write(&buf, binary.LittleEndian, §) // .text
+ strtabsize := len("\x00.text\x00.riscv.attributes\x00.shstrtab\x00")
+ // RISC-V objdump needs the .riscv.attributes section to identify
+ // the RV64G (not include compressed) extensions.
+ sect = elf.Section64{
+ Name: uint32(len("\x00.text\x00")),
+ Type: uint32(0x70000003), // SHT_RISCV_ATTRIBUTES
+ Addr: 0,
+ Off: uint64(off2 + (off3-off2)*4 + strtabsize),
+ Size: 102,
+ Addralign: 1,
+ }
+ binary.Write(&buf, binary.LittleEndian, §)
+ sect = elf.Section64{
+ Name: uint32(len("\x00.text\x00.riscv.attributes\x00")),
+ Type: uint32(elf.SHT_STRTAB),
+ Addr: 0,
+ Off: uint64(off2 + (off3-off2)*4),
+ Size: uint64(strtabsize),
+ Addralign: 1,
+ }
+ binary.Write(&buf, binary.LittleEndian, §)
+ buf.WriteString("\x00.text\x00.riscv.attributes\x00.shstrtab\x00")
+ // Contents of .riscv.attributes section
+ // which specify the extension and priv spec version. (1.11)
+ buf.WriteString("Ae\x00\x00\x00riscv\x00\x01[\x00\x00\x00\x05rv64i2p1_m2pp_a2p1_f2p2_d2p2_q2p2_zibsr2p0_zifencei2p0_zmmul1p0_zfh1p0_zfhmin1p0\x00\x08\x01\x0a\x0b")
+ f.Write(buf.Bytes())
+ return nil
+}
diff --git a/riscv64/riscv64asm/testdata/Makefile b/riscv64/riscv64asm/testdata/Makefile
new file mode 100644
index 0000000..8ac7835
--- /dev/null
+++ b/riscv64/riscv64asm/testdata/Makefile
@@ -0,0 +1,9 @@
+go test command:
+ cd ..; go generate
+ cd ..; go test -run 'ObjdumpRISCV64TestGUNSyntaxdata' -v -timeout 10h 2>&1 | tee -a log
+ cd ..; go test -run 'ObjdumpRISCV64TestGoSyntaxdata' -v -timeout 10h 2>&1 | tee -a log
+ cd ..; go test -run 'ObjdumpRISCV64' -v -timeout 10h 2>&1 | tee -a log
+ cd ..; go test -run 'ObjdumpRISCV64Manual' -v -timeout 10h 2>&1 | tee -a log
+ cd ..; go test -run 'TestDecodeGNUSyntax'
+ cd ..; go test -run 'TestDecodeGoSyntax'
+ cd ..; go test -run '.*'
diff --git a/riscv64/riscv64asm/testdata/gnucases.txt b/riscv64/riscv64asm/testdata/gnucases.txt
new file mode 100644
index 0000000..dad05a7
--- /dev/null
+++ b/riscv64/riscv64asm/testdata/gnucases.txt
@@ -0,0 +1,390 @@
+b3027300| add x5,x6,x7
+9302f3ff| addi x5,x6,-1
+9302f37f| addi x5,x6,2047
+1305a000| li x10,10
+13000000| nop
+93870900| mv x15,x19
+9b02f37f| addiw x5,x6,2047
+1b830a00| sext.w x6,x21
+bb027300| addw x5,x6,x7
+afb26300| amoadd.d x5,x6,(x7)
+afb26304| amoadd.d.aq x5,x6,(x7)
+afb26302| amoadd.d.rl x5,x6,(x7)
+afa26300| amoadd.w x5,x6,(x7)
+afa26304| amoadd.w.aq x5,x6,(x7)
+afa26302| amoadd.w.rl x5,x6,(x7)
+afb26360| amoand.d x5,x6,(x7)
+afb26364| amoand.d.aq x5,x6,(x7)
+afb26362| amoand.d.rl x5,x6,(x7)
+afa26360| amoand.w x5,x6,(x7)
+afa26364| amoand.w.aq x5,x6,(x7)
+afa26362| amoand.w.rl x5,x6,(x7)
+afb263e0| amomaxu.d x5,x6,(x7)
+afb263e4| amomaxu.d.aq x5,x6,(x7)
+afb263e2| amomaxu.d.rl x5,x6,(x7)
+afa263e0| amomaxu.w x5,x6,(x7)
+afa263e4| amomaxu.w.aq x5,x6,(x7)
+afa263e2| amomaxu.w.rl x5,x6,(x7)
+afb263a0| amomax.d x5,x6,(x7)
+afb263a4| amomax.d.aq x5,x6,(x7)
+afb263a2| amomax.d.rl x5,x6,(x7)
+afa263a0| amomax.w x5,x6,(x7)
+afa263a4| amomax.w.aq x5,x6,(x7)
+afa263a2| amomax.w.rl x5,x6,(x7)
+afb263c0| amominu.d x5,x6,(x7)
+afb263c4| amominu.d.aq x5,x6,(x7)
+afb263c2| amominu.d.rl x5,x6,(x7)
+afa263c0| amominu.w x5,x6,(x7)
+afa263c4| amominu.w.aq x5,x6,(x7)
+afa263c2| amominu.w.rl x5,x6,(x7)
+afb26380| amomin.d x5,x6,(x7)
+afb26384| amomin.d.aq x5,x6,(x7)
+afb26382| amomin.d.rl x5,x6,(x7)
+afa26380| amomin.w x5,x6,(x7)
+afa26384| amomin.w.aq x5,x6,(x7)
+afa26382| amomin.w.rl x5,x6,(x7)
+afb26340| amoor.d x5,x6,(x7)
+afb26344| amoor.d.aq x5,x6,(x7)
+afb26342| amoor.d.rl x5,x6,(x7)
+afa26340| amoor.w x5,x6,(x7)
+afa26344| amoor.w.aq x5,x6,(x7)
+afa26342| amoor.w.rl x5,x6,(x7)
+afb26308| amoswap.d x5,x6,(x7)
+afb2630c| amoswap.d.aq x5,x6,(x7)
+afb2630a| amoswap.d.rl x5,x6,(x7)
+afa26308| amoswap.w x5,x6,(x7)
+afa2630c| amoswap.w.aq x5,x6,(x7)
+afa2630a| amoswap.w.rl x5,x6,(x7)
+afb26320| amoxor.d x5,x6,(x7)
+afb26324| amoxor.d.aq x5,x6,(x7)
+afb26322| amoxor.d.rl x5,x6,(x7)
+afa26320| amoxor.w x5,x6,(x7)
+afa26324| amoxor.w.aq x5,x6,(x7)
+afa26322| amoxor.w.rl x5,x6,(x7)
+b3727300| and x5,x6,x7
+9372f3ff| andi x5,x6,-1
+9372f37f| andi x5,x6,2047
+97020000| auipc x5,0x0
+97028000| auipc x5,0x800
+e38062f0| beq x5,x6,-256
+e3de62ee| bge x5,x6,-260
+e3fc62ee| bgeu x5,x6,-264
+e3ca62ee| blt x5,x6,-268
+e3e862ee| bltu x5,x6,-272
+e39662ee| bne x5,x6,-276
+63940200| bnez x5,8
+63c40400| bltz x9,8
+63447000| bgtz x7,8
+63d40900| bgez x19,8
+6354d001| blez x29,8
+63040800| beqz x16,8
+f33213c0| csrrc x5,time,x6
+f3f21fc0| csrrci x5,time,31
+f32213c0| csrrs x5,time,x6
+f3e21fc0| csrrsi x5,time,31
+f31213c0| csrrw x5,time,x6
+f3d21fc0| csrrwi x5,time,31
+733015c0| csrc time,x10
+73f010c0| csrci time,1
+73253000| frcsr x10
+f3251000| frflags x11
+73262000| frrm x12
+f32400c0| rdcycle x9
+732920c0| rdinstret x18
+f32910c0| rdtime x19
+f3224014| csrr x5,sip
+73201bc0| csrs time,x22
+736014c8| csrsi timeh,8
+73903700| fscsr x15
+73101800| fsflags x16
+73902800| fsrm x17
+731014c0| csrw time,x8
+735016c8| csrwi timeh,12
+b3427302| div x5,x6,x7
+b3527302| divu x5,x6,x7
+bb527302| divuw x5,x6,x7
+bb427302| divw x5,x6,x7
+73001000| ebreak
+73000000| ecall
+0f00f00f| fence
+53f02002| fadd.d f0,f1,f2
+53f02004| fadd.h f0,f1,f2
+53f02006| fadd.q f0,f1,f2
+53f02000| fadd.s f0,f1,f2
+d31200e2| fclass.d x5,f0
+d31200e4| fclass.h x5,f0
+d31200e6| fclass.q x5,f0
+d31200e0| fclass.s x5,f0
+53f022d2| fcvt.d.l f0,x5
+53f032d2| fcvt.d.lu f0,x5
+53f03042| fcvt.d.q f0,f1
+53800042| fcvt.d.s f0,f1
+538002d2| fcvt.d.w f0,x5
+538012d2| fcvt.d.wu f0,x5
+53f022d4| fcvt.h.l f0,x5
+53f032d4| fcvt.h.lu f0,x5
+53f00044| fcvt.h.s f0,f1
+53f002d4| fcvt.h.w f0,x5
+53f012d4| fcvt.h.wu f0,x5
+d37230c2| fcvt.lu.d x5,f0
+d37230c4| fcvt.lu.h x5,f0
+d37230c6| fcvt.lu.q x5,f0
+d37230c0| fcvt.lu.s x5,f0
+d37220c2| fcvt.l.d x5,f0
+d37220c4| fcvt.l.h x5,f0
+d37220c6| fcvt.l.q x5,f0
+d37220c0| fcvt.l.s x5,f0
+53801046| fcvt.q.d f0,f1
+538022d6| fcvt.q.l f0,x5
+538032d6| fcvt.q.lu f0,x5
+53800046| fcvt.q.s f0,f1
+538002d6| fcvt.q.w f0,x5
+538012d6| fcvt.q.wu f0,x5
+53f01040| fcvt.s.d f0,f1
+53802040| fcvt.s.h f0,f1
+53f022d0| fcvt.s.l f0,x5
+53f032d0| fcvt.s.lu f0,x5
+53f03040| fcvt.s.q f0,f1
+53f002d0| fcvt.s.w f0,x5
+53f012d0| fcvt.s.wu f0,x5
+d37210c2| fcvt.wu.d x5,f0
+d37210c4| fcvt.wu.h x5,f0
+d37210c6| fcvt.wu.q x5,f0
+d37210c0| fcvt.wu.s x5,f0
+d37200c2| fcvt.w.d x5,f0
+d37200c4| fcvt.w.h x5,f0
+d37200c6| fcvt.w.q x5,f0
+d37200c0| fcvt.w.s x5,f0
+53f0201a| fdiv.d f0,f1,f2
+53f0201c| fdiv.h f0,f1,f2
+53f0201e| fdiv.q f0,f1,f2
+53f02018| fdiv.s f0,f1,f2
+0f00f00f| fence
+0f100000| fence.i
+d32210a2| feq.d x5,f0,f1
+d32210a4| feq.h x5,f0,f1
+d32210a6| feq.q x5,f0,f1
+d32210a0| feq.s x5,f0,f1
+07b0f27f| fld f0,2047(x5)
+d30210a2| fle.d x5,f0,f1
+d30210a4| fle.h x5,f0,f1
+d30210a6| fle.q x5,f0,f1
+d30210a0| fle.s x5,f0,f1
+0790f27f| flh f0,2047(x5)
+07c0f27f| flq f0,2047(x5)
+d31210a2| flt.d x5,f0,f1
+d31210a4| flt.h x5,f0,f1
+d31210a6| flt.q x5,f0,f1
+d31210a0| flt.s x5,f0,f1
+07a0f27f| flw f0,2047(x5)
+43f0201a| fmadd.d f0,f1,f2,f3
+43f0201c| fmadd.h f0,f1,f2,f3
+43f0201e| fmadd.q f0,f1,f2,f3
+43f02018| fmadd.s f0,f1,f2,f3
+5390202a| fmax.d f0,f1,f2
+5390202c| fmax.h f0,f1,f2
+5390202e| fmax.q f0,f1,f2
+53902028| fmax.s f0,f1,f2
+5380202a| fmin.d f0,f1,f2
+5380202c| fmin.h f0,f1,f2
+5380202e| fmin.q f0,f1,f2
+53802028| fmin.s f0,f1,f2
+47f0201a| fmsub.d f0,f1,f2,f3
+47f0201c| fmsub.h f0,f1,f2,f3
+47f0201e| fmsub.q f0,f1,f2,f3
+47f02018| fmsub.s f0,f1,f2,f3
+53f02012| fmul.d f0,f1,f2
+53f02014| fmul.h f0,f1,f2
+53f02016| fmul.q f0,f1,f2
+53f02010| fmul.s f0,f1,f2
+538002f2| fmv.d.x f0,x5
+538002f4| fmv.h.x f0,x5
+d30200e2| fmv.x.d x5,f0
+d30200e4| fmv.x.h x5,f0
+d30200e0| fmv.x.w x5,f0
+4ff0201a| fnmadd.d f0,f1,f2,f3
+4ff0201c| fnmadd.h f0,f1,f2,f3
+4ff0201e| fnmadd.q f0,f1,f2,f3
+4ff02018| fnmadd.s f0,f1,f2,f3
+4bf0201a| fnmsub.d f0,f1,f2,f3
+4bf0201c| fnmsub.h f0,f1,f2,f3
+4bf0201e| fnmsub.q f0,f1,f2,f3
+4bf02018| fnmsub.s f0,f1,f2,f3
+a7bf027e| fsd f0,2047(x5)
+53902022| fsgnjn.d f0,f1,f2
+53902024| fsgnjn.h f0,f1,f2
+53902026| fsgnjn.q f0,f1,f2
+53902020| fsgnjn.s f0,f1,f2
+53a02022| fsgnjx.d f0,f1,f2
+53a02024| fsgnjx.h f0,f1,f2
+53a02026| fsgnjx.q f0,f1,f2
+53a02020| fsgnjx.s f0,f1,f2
+53802022| fsgnj.d f0,f1,f2
+53802024| fsgnj.h f0,f1,f2
+53802026| fsgnj.q f0,f1,f2
+53802020| fsgnj.s f0,f1,f2
+53a01022| fabs.d f0,f1
+53a49420| fabs.s f8,f9
+d305c622| fmv.d f11,f12
+d306e720| fmv.s f13,f14
+d3170823| fneg.d f15,f16
+d398f720| fneg.s f17,f15
+a79f027e| fsh f0,2047(x5)
+a7cf027e| fsq f0,2047(x5)
+53f0005a| fsqrt.d f0,f1
+53f0005c| fsqrt.h f0,f1
+53f0005e| fsqrt.q f0,f1
+53f00058| fsqrt.s f0,f1
+53f0200a| fsub.d f0,f1,f2
+53f0200c| fsub.h f0,f1,f2
+53f0200e| fsub.q f0,f1,f2
+53f02008| fsub.s f0,f1,f2
+a7af027e| fsw f0,2047(x5)
+6ff0dfcb| j -836
+eff09fcb| jal -840
+eff25fcb| jal x5,-844
+67800200| jr x5
+e7800202| jalr x1,32(x5)
+67800000| ret
+6700a500| jr 10(x10)
+8302f37f| lb x5,2047(x6)
+8342f37f| lbu x5,2047(x6)
+af320310| lr.d x5,(x6)
+af320314| lr.d.aq x5,(x6)
+af320312| lr.d.rl x5,(x6)
+af220310| lr.w x5,(x6)
+af220314| lr.w.aq x5,(x6)
+af220312| lr.w.rl x5,(x6)
+b7829102| lui x5,0x2918
+8322f37f| lw x5,2047(x6)
+8362f37f| lwu x5,2047(x6)
+b3027302| mul x5,x6,x7
+b3127302| mulh x5,x6,x7
+b3227302| mulhsu x5,x6,x7
+b3327302| mulhu x5,x6,x7
+bb027302| mulw x5,x6,x7
+b3627300| or x5,x6,x7
+93620380| ori x5,x6,-2048
+b3627302| rem x5,x6,x7
+b3727302| remu x5,x6,x7
+bb627302| remw x5,x6,x7
+a30f537e| sb x5,2047(x6)
+afb26318| sc.d x5,x6,(x7)
+afb2631c| sc.d.aq x5,x6,(x7)
+afb2631a| sc.d.rl x5,x6,(x7)
+afa26318| sc.w x5,x6,(x7)
+afa2631c| sc.w.aq x5,x6,(x7)
+afa2631a| sc.w.rl x5,x6,(x7)
+a33f537e| sd x5,2047(x6)
+23105380| sh x5,-2048(x6)
+b3127300| sll x5,x6,x7
+93124303| slli x5,x6,0x34
+9b127301| slliw x5,x6,0x17
+b3227300| slt x5,x6,x7
+b3226000| sgtz x5,x6
+b32e0f00| sltz x29,x30
+9322f37f| slti x5,x6,2047
+93320380| sltiu x5,x6,-2048
+93321300| seqz x5,x6
+b3327300| sltu x5,x6,x7
+33394001| snez x18,x20
+b3527340| sra x5,x6,x7
+93524343| srai x5,x6,0x34
+9b526341| sraiw x5,x6,0x16
+bb527340| sraw x5,x6,x7
+b3527300| srl x5,x6,x7
+93524303| srli x5,x6,0x34
+9b526301| srliw x5,x6,0x16
+bb527300| srlw x5,x6,x7
+b3027340| sub x5,x6,x7
+b3026040| neg x5,x6
+bb027340| subw x5,x6,x7
+3b0ff041| negw x30,x31
+a32f537e| sw x5,2047(x6)
+b3427300| xor x5,x6,x7
+9342f37f| xori x5,x6,2047
+93c2ffff| not x5,x31
+bb003108| add.uw x1,x2,x3
+33a26220| sh1add x4,x5,x6
+bb239420| sh1add.uw x7,x8,x9
+33c5c520| sh2add x10,x11,x12
+bb46f720| sh2add.uw x13,x14,x15
+33e82821| sh3add x16,x17,x18
+bb695a21| sh3add.uw x19,x20,x21
+1b9b7b09| slli.uw x22,x23,0x17
+33fcac41| andn x24,x25,x26
+b36dde41| orn x27,x28,x29
+33cf1f40| xnor x30,x31,x1
+13910160| clz x2,x3
+1b920260| clzw x4,x5
+13931360| ctz x6,x7
+1b941460| ctzw x8,x9
+13952560| cpop x10,x11
+1b962660| cpopw x12,x13
+33e7070b| max x14,x15,x16
+b378390b| maxu x17,x18,x19
+33ca6a0b| min x20,x21,x22
+b35b9c0b| minu x23,x24,x25
+139d4d60| sext.b x26,x27
+139e5e60| sext.h x28,x29
+3bcf0f08| zext.h x30,x31
+b3102060| rol x1,x0,x2
+bb115260| rolw x3,x4,x5
+33d38360| ror x6,x7,x8
+9354a560| rori x9,x10,0xa
+9b55e660| roriw x11,x12,0xe
+bb56f760| rorw x13,x14,x15
+13d87828| orc.b x16,x17
+13d9896b| rev8 x18,x19
+339a6a49| bclr x20,x21,x22
+931bfc48| bclri x23,x24,0xf
+b35cbd49| bext x25,x26,x27
+13de8e48| bexti x28,x29,0x8
+339f0f68| binv x30,x31,x0
+9310016a| binvi x1,x2,0x20
+b3115228| bset x3,x4,x5
+1393f32b| bseti x6,x7,0x3f
+4000| addi x8,x2,4
+2041| lw x8,64(x10)
+94d0| sw x13,32(x9)
+0100| nop
+811f| addi x31,x31,-32
+4111| addi x2,x2,-16
+8158| li x17,-32
+4161| addi x2,x2,16
+4163| lui x6,0x10
+819b| andi x15,x15,-32
+0d8c| sub x8,x8,x11
+b18c| xor x9,x9,x12
+558c| or x8,x8,x13
+f98c| and x9,x9,x14
+01a8| j 16
+99c5| beqz x11,14
+85e3| bnez x15,32
+c248| lw x17,16(x2)
+8283| jr x7
+fa88| mv x17,x30
+0290| ebreak
+0295| jalr x10
+c297| add x15,x15,x16
+76c4| sw x29,8(x2)
+8873| ld x10,32(x15)
+00ea| sd x8,16(x12)
+3d31| addiw x2,x2,-17
+2180| srli x8,x8,0x8
+c184| srai x9,x9,0x10
+919d| subw x11,x11,x12
+b99e| addw x13,x13,x14
+4a01| slli x2,x2,0x12
+027d| ld x26,32(x2)
+a260| ld x1,8(x2)
+864d| lw x27,64(x2)
+2021| fld f8,64(x10)
+8cb0| fsd f11,32(x9)
+8624| fld f9,64(x2)
+3eb0| fsd f15,32(x2)
+0000| unimp
+ab| illegalins
+f3| illegalins
+abc3| illegalins
+abcde3| illegalins
diff --git a/riscv64/riscv64asm/testdata/plan9cases.txt b/riscv64/riscv64asm/testdata/plan9cases.txt
new file mode 100644
index 0000000..d38c5eb
--- /dev/null
+++ b/riscv64/riscv64asm/testdata/plan9cases.txt
@@ -0,0 +1,336 @@
+b3027300| ADD X7, X6, X5
+9302f3ff| ADDI $-1, X6, X5
+9302f37f| ADDI $2047, X6, X5
+93870900| MOV X19, X15
+93070100| MOV X2, X15
+9b02f37f| ADDIW $2047, X6, X5
+1b830a00| MOVW X21, X6
+1b810a00| MOVW X21, X2
+bb027300| ADDW X7, X6, X5
+afb26300| AMOADDD X6, (X7), X5
+afb26304| AMOADDD X6, (X7), X5
+afb26302| AMOADDD X6, (X7), X5
+afa26300| AMOADDW X6, (X7), X5
+afa26304| AMOADDW X6, (X7), X5
+afa26302| AMOADDW X6, (X7), X5
+afb26360| AMOANDD X6, (X7), X5
+afb26364| AMOANDD X6, (X7), X5
+afb26362| AMOANDD X6, (X7), X5
+afa26360| AMOANDW X6, (X7), X5
+afa26364| AMOANDW X6, (X7), X5
+afa26362| AMOANDW X6, (X7), X5
+afb263e0| AMOMAXUD X6, (X7), X5
+afb263e4| AMOMAXUD X6, (X7), X5
+afb263e2| AMOMAXUD X6, (X7), X5
+afa263e0| AMOMAXUW X6, (X7), X5
+afa263e4| AMOMAXUW X6, (X7), X5
+afa263e2| AMOMAXUW X6, (X7), X5
+afb263a0| AMOMAXD X6, (X7), X5
+afb263a4| AMOMAXD X6, (X7), X5
+afb263a2| AMOMAXD X6, (X7), X5
+afa263a0| AMOMAXW X6, (X7), X5
+afa263a4| AMOMAXW X6, (X7), X5
+afa263a2| AMOMAXW X6, (X7), X5
+afb263c0| AMOMINUD X6, (X7), X5
+afb263c4| AMOMINUD X6, (X7), X5
+afb263c2| AMOMINUD X6, (X7), X5
+afa263c0| AMOMINUW X6, (X7), X5
+afa263c4| AMOMINUW X6, (X7), X5
+afa263c2| AMOMINUW X6, (X7), X5
+afb26380| AMOMIND X6, (X7), X5
+afb26384| AMOMIND X6, (X7), X5
+afb26382| AMOMIND X6, (X7), X5
+afa26380| AMOMINW X6, (X7), X5
+afa26384| AMOMINW X6, (X7), X5
+afa26382| AMOMINW X6, (X7), X5
+afb26340| AMOORD X6, (X7), X5
+afb26344| AMOORD X6, (X7), X5
+afb26342| AMOORD X6, (X7), X5
+afa26340| AMOORW X6, (X7), X5
+afa26344| AMOORW X6, (X7), X5
+afa26342| AMOORW X6, (X7), X5
+afb26308| AMOSWAPD X6, (X7), X5
+afb2630c| AMOSWAPD X6, (X7), X5
+afb2630a| AMOSWAPD X6, (X7), X5
+afa26308| AMOSWAPW X6, (X7), X5
+afa2630c| AMOSWAPW X6, (X7), X5
+afa2630a| AMOSWAPW X6, (X7), X5
+afb26320| AMOXORD X6, (X7), X5
+afb26324| AMOXORD X6, (X7), X5
+afb26322| AMOXORD X6, (X7), X5
+afa26320| AMOXORW X6, (X7), X5
+afa26324| AMOXORW X6, (X7), X5
+afa26322| AMOXORW X6, (X7), X5
+b3727300| AND X7, X6, X5
+9372f3ff| ANDI $-1, X6, X5
+9372f37f| ANDI $2047, X6, X5
+9372f30f| MOVBU X6, X5
+97020000| AUIPC $0, X5
+97028000| AUIPC $2048, X5
+e38062f0| BEQ X5, X6, -64(PC)
+e3de62ee| BGE X5, X6, -65(PC)
+e3fc62ee| BGEU X5, X6, -66(PC)
+e3ca62ee| BLT X5, X6, -67(PC)
+e3e862ee| BLTU X5, X6, -68(PC)
+e39662ee| BNE X5, X6, -69(PC)
+e30403ee| BEQZ X6, -70(PC)
+e35203ee| BGEZ X6, -71(PC)
+e34003ee| BLTZ X6, -72(PC)
+e31e03ec| BNEZ X6, -73(PC)
+f33213c0| CSRRC X6, TIME, X5
+f3f21fc0| CSRRCI $31, TIME, X5
+f32213c0| CSRRS X6, TIME, X5
+f3e21fc0| CSRRSI $31, TIME, X5
+f31213c0| CSRRW X6, TIME, X5
+f3d21fc0| CSRRWI $31, TIME, X5
+733015c0| CSRRC X10, TIME, X0
+73f010c0| CSRRCI $1, TIME, X0
+73253000| FRCSR X10
+f3251000| FRFLAGS X11
+73262000| FRRM X12
+f32400c0| RDCYCLE X9
+732920c0| RDINSTRET X18
+f32910c0| RDTIME X19
+f3224014| CSRRS X0, SIP, X5
+73201bc0| CSRRS X22, TIME, X0
+736014c8| CSRRSI $8, TIMEH, X0
+73903700| FSCSR X15, X0
+73101800| FSFLAGS X16, X0
+73902800| FSRM X17, X0
+731014c0| CSRRW X8, TIME, X0
+735016c8| CSRRWI $12, TIMEH, X0
+b3427302| DIV X7, X6, X5
+b3527302| DIVU X7, X6, X5
+bb527302| DIVUW X7, X6, X5
+bb427302| DIVW X7, X6, X5
+73001000| EBREAK
+73000000| ECALL
+53f02002| FADDD F2, F1, F0
+53f02004| FADDH F2, F1, F0
+53f02006| FADDQ F2, F1, F0
+53f02000| FADDS F2, F1, F0
+d31200e2| FCLASSD F0, X5
+d31200e4| FCLASSH F0, X5
+d31200e6| FCLASSQ F0, X5
+d31200e0| FCLASSS F0, X5
+53f022d2| FCVTDL X5, F0
+53f032d2| FCVTDLU X5, F0
+53f03042| FCVTDQ F1, F0
+53800042| FCVTDS F1, F0
+538002d2| FCVTDW X5, F0
+538012d2| FCVTDWU X5, F0
+53f022d4| FCVTHL X5, F0
+53f032d4| FCVTHLU X5, F0
+53f00044| FCVTHS F1, F0
+53f002d4| FCVTHW X5, F0
+53f012d4| FCVTHWU X5, F0
+d37230c2| FCVTLUD F0, X5
+d37230c4| FCVTLUH F0, X5
+d37230c6| FCVTLUQ F0, X5
+d37230c0| FCVTLUS F0, X5
+d37220c2| FCVTLD F0, X5
+d37220c4| FCVTLH F0, X5
+d37220c6| FCVTLQ F0, X5
+d37220c0| FCVTLS F0, X5
+53801046| FCVTQD F1, F0
+538022d6| FCVTQL X5, F0
+538032d6| FCVTQLU X5, F0
+53800046| FCVTQS F1, F0
+538002d6| FCVTQW X5, F0
+538012d6| FCVTQWU X5, F0
+53f01040| FCVTSD F1, F0
+53802040| FCVTSH F1, F0
+53f022d0| FCVTSL X5, F0
+53f032d0| FCVTSLU X5, F0
+53f03040| FCVTSQ F1, F0
+53f002d0| FCVTSW X5, F0
+53f012d0| FCVTSWU X5, F0
+d37210c2| FCVTWUD F0, X5
+d37210c4| FCVTWUH F0, X5
+d37210c6| FCVTWUQ F0, X5
+d37210c0| FCVTWUS F0, X5
+d37200c2| FCVTWD F0, X5
+d37200c4| FCVTWH F0, X5
+d37200c6| FCVTWQ F0, X5
+d37200c0| FCVTWS F0, X5
+53f0201a| FDIVD F2, F1, F0
+53f0201c| FDIVH F2, F1, F0
+53f0201e| FDIVQ F2, F1, F0
+53f02018| FDIVS F2, F1, F0
+0f00f00f| FENCE
+0f100000| FENCEI
+d32210a2| FEQD F1, F0, X5
+d32210a4| FEQH F1, F0, X5
+d32210a6| FEQQ F1, F0, X5
+d32210a0| FEQS F1, F0, X5
+07b0f27f| MOVD F0, 2047(X5)
+d30210a2| FLED F1, F0, X5
+d30210a4| FLEH F1, F0, X5
+d30210a6| FLEQ F1, F0, X5
+d30210a0| FLES F1, F0, X5
+0790f27f| FLH 2047(X5), F0
+07c0f27f| FLQ 2047(X5), F0
+d31210a2| FLTD F1, F0, X5
+d31210a4| FLTH F1, F0, X5
+d31210a6| FLTQ F1, F0, X5
+d31210a0| FLTS F1, F0, X5
+07a0f27f| MOVF F0, 2047(X5)
+43f0201a| FMADDD F1, F2, F3, F0
+43f0201c| FMADDH F1, F2, F3, F0
+43f0201e| FMADDQ F1, F2, F3, F0
+43f02018| FMADDS F1, F2, F3, F0
+5390202a| FMAXD F2, F1, F0
+5390202c| FMAXH F2, F1, F0
+5390202e| FMAXQ F2, F1, F0
+53902028| FMAXS F2, F1, F0
+5380202a| FMIND F2, F1, F0
+5380202c| FMINH F2, F1, F0
+5380202e| FMINQ F2, F1, F0
+53802028| FMINS F2, F1, F0
+47f0201a| FMSUBD F1, F2, F3, F0
+47f0201c| FMSUBH F1, F2, F3, F0
+47f0201e| FMSUBQ F1, F2, F3, F0
+47f02018| FMSUBS F1, F2, F3, F0
+53f02012| FMULD F2, F1, F0
+53f02014| FMULH F2, F1, F0
+53f02016| FMULQ F2, F1, F0
+53f02010| FMULS F2, F1, F0
+538002f2| FMVDX X5, F0
+538002f4| FMVHX X5, F0
+d30200e2| FMVXD F0, X5
+d30200e4| FMVXH F0, X5
+d30200e0| FMVXW F0, X5
+4ff0201a| FNMADDD F1, F2, F3, F0
+4ff0201c| FNMADDH F1, F2, F3, F0
+4ff0201e| FNMADDQ F1, F2, F3, F0
+4ff02018| FNMADDS F1, F2, F3, F0
+4bf0201a| FNMSUBD F1, F2, F3, F0
+4bf0201c| FNMSUBH F1, F2, F3, F0
+4bf0201e| FNMSUBQ F1, F2, F3, F0
+4bf02018| FNMSUBS F1, F2, F3, F0
+a7bf027e| MOVD 2047(X5), F0
+53902022| FSGNJND F2, F1, F0
+53902024| FSGNJNH F2, F1, F0
+53902026| FSGNJNQ F2, F1, F0
+53902020| FSGNJNS F2, F1, F0
+53a02022| FSGNJXD F2, F1, F0
+53a02024| FSGNJXH F2, F1, F0
+53a02026| FSGNJXQ F2, F1, F0
+53a02020| FSGNJXS F2, F1, F0
+53802022| FSGNJD F2, F1, F0
+53802024| FSGNJH F2, F1, F0
+53802026| FSGNJQ F2, F1, F0
+53802020| FSGNJS F2, F1, F0
+a79f027e| FSH 2047(X5), F0
+a7cf027e| FSQ 2047(X5), F0
+53f0005a| FSQRTD F1, F0
+53f0005c| FSQRTH F1, F0
+53f0005e| FSQRTQ F1, F0
+53f00058| FSQRTS F1, F0
+53f0200a| FSUBD F2, F1, F0
+53f0200c| FSUBH F2, F1, F0
+53f0200e| FSUBQ F2, F1, F0
+53f02008| FSUBS F2, F1, F0
+a7af027e| MOVF 2047(X5), F0
+6ff0dfcb| JMP -209(PC)
+eff09fcb| CALL -210(PC)
+eff25fcb| JAL X5, -211(PC)
+67800202| JMP 32(X5)
+e7800202| CALL 32(X5)
+e7820202| JALR X5, 32(X5)
+67800000| RET
+8302f37f| MOVB 2047(X6), X5
+8342f37f| MOVBU 2047(X6), X5
+af320310| LRD (X6), X5
+af320314| LRD (X6), X5
+af320312| LRD (X6), X5
+af220310| LRW (X6), X5
+af220314| LRW (X6), X5
+af220312| LRW (X6), X5
+b7829102| LUI $10520, X5
+8322f37f| MOVW 2047(X6), X5
+8362f37f| MOVWU 2047(X6), X5
+b3027302| MUL X7, X6, X5
+b3127302| MULH X7, X6, X5
+b3227302| MULHSU X7, X6, X5
+b3327302| MULHU X7, X6, X5
+bb027302| MULW X7, X6, X5
+b3627300| OR X7, X6, X5
+93620380| ORI $-2048, X6, X5
+b3627302| REM X7, X6, X5
+b3727302| REMU X7, X6, X5
+bb627302| REMW X7, X6, X5
+a30f537e| MOVB X5, 2047(X6)
+afb26318| SCD X6, (X7), X5
+afb2631c| SCD X6, (X7), X5
+afb2631a| SCD X6, (X7), X5
+afa26318| SCW X6, (X7), X5
+afa2631c| SCW X6, (X7), X5
+afa2631a| SCW X6, (X7), X5
+a33f537e| MOV X5, 2047(X6)
+23105380| MOVH X5, -2048(X6)
+b3127300| SLL X7, X6, X5
+93124303| SLLI $52, X6, X5
+9b127301| SLLIW $23, X6, X5
+b3227300| SLT X7, X6, X5
+9322f37f| SLTI $2047, X6, X5
+93320380| SLTIU $-2048, X6, X5
+93321300| SEQZ X6, X5
+b3327300| SLTU X7, X6, X5
+33394001| SNEZ X20, X18
+b3527340| SRA X7, X6, X5
+93524343| SRAI $52, X6, X5
+9b526341| SRAIW $22, X6, X5
+bb527340| SRAW X7, X6, X5
+b3527300| SRL X7, X6, X5
+93524303| SRLI $52, X6, X5
+9b526301| SRLIW $22, X6, X5
+bb527300| SRLW X7, X6, X5
+b3027340| SUB X7, X6, X5
+b3026040| NEG X6, X5
+bb027340| SUBW X7, X6, X5
+a32f537e| MOVW X5, 2047(X6)
+b3427300| XOR X7, X6, X5
+9342f37f| XORI $2047, X6, X5
+93c2ffff| NOT X31, X5
+bb003108| ADDUW X3, X2, X1
+33a26220| SH1ADD X6, X5, X4
+bb239420| SH1ADDUW X9, X8, X7
+33c5c520| SH2ADD X12, X11, X10
+bb46f720| SH2ADDUW X15, X14, X13
+33e82821| SH3ADD X18, X17, X16
+bb695a21| SH3ADDUW X21, X20, X19
+1b9b7b09| SLLIUW $23, X23, X22
+33fcac41| ANDN X26, X25, X24
+b36dde41| ORN X29, X28, X27
+33cf1f40| XNOR X1, X31, X30
+13910160| CLZ X3, X2
+1b920260| CLZW X5, X4
+13931360| CTZ X7, X6
+1b941460| CTZW X9, X8
+13952560| CPOP X11, X10
+1b962660| CPOPW X13, X12
+33e7070b| MAX X16, X15, X14
+b378390b| MAXU X19, X18, X17
+33ca6a0b| MIN X22, X21, X20
+b35b9c0b| MINU X25, X24, X23
+139d4d60| SEXTB X27, X26
+139e5e60| SEXTH X29, X28
+3bcf0f08| ZEXTH X31, X30
+b3102060| ROL X2, X0, X1
+bb115260| ROLW X5, X4, X3
+33d38360| ROR X8, X7, X6
+9354a560| RORI $10, X10, X9
+9b55e660| RORIW $14, X12, X11
+bb56f760| RORW X15, X14, X13
+13d87828| ORCB X17, X16
+13d9896b| REV8 X19, X18
+339a6a49| BCLR X22, X21, X20
+931bfc48| BCLRI $15, X24, X23
+b35cbd49| BEXT X27, X26, X25
+13de8e48| BEXTI $8, X29, X28
+339f0f68| BINV X0, X31, X30
+9310016a| BINVI $32, X2, X1
+b3115228| BSET X5, X4, X3
+1393f32b| BSETI $63, X7, X6
+0000| UNIMP