whatcanGOwrong

This commit is contained in:
2024-09-19 21:38:24 -04:00
commit d0ae4d841d
17908 changed files with 4096831 additions and 0 deletions
@@ -0,0 +1,163 @@
// Copyright 2021 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.
//
// This file requires gcc and binutils with -mcpu=power10 support.
// ppc64util runs a series of commands like:
// go run map.go -fmt=asm ../pp64.csv > asm.S
// powerpc64le-linux-gnu-gcc -c asm.S -mcpu=power10 -mbig
// powerpc64le-linux-gnu-objdump -d asm.o
// to create the file decode_generated.txt used to verify the disassembler.
//
// Note, the golang disassembler is not expected to support every extended
// mnemonic, but it should support those which frequently show up in object
// files compiled by the golang toolchain.
#define RA 1
#define RB 2
#define RS 3
#define RT 4
#define RC 5
#define RSp 6
#define RTp 8
#define MB 1
#define ME 7
#define NB 2
#define CY 1
#define LEV 1
#define FRBp 2
#define FRAp 4
#define FRTp 6
#define FRSp 8
#define FRT 3
#define FRA 5
#define FRB 7
#define FRC 9
#define FRS 11
#define FLM 8
#define U 3
#define W 0
#define TE 15
#define SP 1
#define S 1
#define DRM 0x7
#define RM 0x3
#define BF 3
#define SH 7
#define XT 33
#define XA 35
#define XB 37
#define XS 39
#define XC 41
#define XAp 36
#define XTp 38
#define XSp 40
#define DM 1
#define SHW 2
#define VRA 1
#define VRB 2
#define VRC 3
#define VRT 4
#define VRS 5
#define SHB 3
#define SIX 1
#define ST 1
#define PS 0
#define MP 1
#define bm 0x45FF
#define N 3
#define AT 7
#define AS 6
#define RMC 3
#define UIM 1
#define DCMX 0x23
#define DCM 0x11
#define DGM 0x11
#define R 1
#define BA 1
#define BB 2
#define BT 3
#define BO 4
#define BI 6
#define BH 0
#define BFA 7
#define FXM 8
#define BC 11
#define L 1
#define EH 1
#define SPR 69
#define BHRBE 69
#define TO 0x11
#define TBR 268
#define CT 2
#define FC 2
#define TH 3
#define WC 1
#define PL 0
#define IH 4
#define RIC 1
#define PRS 1
#define SIM 6
#define IMM 13
#define IMM8 14
#define D 0x80
#define SC 1
#define target_addr 0x690
#define XMSK 0x9
#define YMSK 0x3
#define PMSK 0x2
#define IX 1
#define IMM32 0x1234567
#define Dpfx 0x160032
#define RApfx 0x0
#define Rpfx 1
#define SIpfx 0xFFFFFFFE00010007
// A valid displacement value for the hash check and hash store instructions.
#define offset -128
// These decode as m.fpr* or m.vr*. This is a matter of preference. We
// don't support these mnemonics, and I don't think they improve reading
// disassembled code in most cases. so ignore.
//
// Likewise, if you add to this list, add tests to decode.txt to ensure we
// still test these, while ignoring the extended mnemonics which get
// generated.
#define mfvsrd xsrsp
#define mfvsrwz xsrsp
#define mtvsrd xsrsp
#define mtvsrwz xsrsp
#define mtvsrwa xsrsp
// isel BC bit is not decoded like other BC fields.
// A special test case is added to decode.txt to verify this.
// We decode it like other BC fields.
#define isel rldicl
// Likewise, these are obscure book ii instructions with extended mnemonics
// which are almost guaranteed never to show up in go code
#define dcbf add
#define sync xsrsp
#define wait xsrsp
#define rfebb sc
// sync 1,1 is the stncisync extended mnemonic. Similar to the above, but
// the lwsync/hwsync extended mnemonics are tested in decode.txt
#define sync xsrsp
@@ -0,0 +1,149 @@
// Copyright 2021 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
// Generate interesting test cases from ppc64 objdump via
// go run util.go
//
// This requires powerpc64le-linux-gnu-gcc and powerpc64le-linux-gnu-objdump be in
// the PATH this command is run.
//
// These tools can be acquired from the IBM advance toolchain for amd64 hosts too.
package main
import (
"bufio"
"fmt"
"io"
"os"
"os/exec"
"regexp"
"strconv"
"strings"
)
// Generator for branch on spr (bclr, bctar, bcctr)
func emitBSpr(bo, bi, l uint32, out io.Writer) {
var insn [3]uint32 = [3]uint32{19<<26 | 16<<1, 19<<26 | 528<<1, 19<<26 | 560<<1}
for bh := uint32(0); bh < 3; bh++ {
for _, m := range insn {
m |= bo << 21
m |= bi << 16
m |= bh << 11
m |= l << 0
fmt.Fprintf(out, "\t.long 0x%08x\n", m)
}
}
}
// Generator for bc
func emitBc(bo, bi, l uint32, out io.Writer) {
for aa := uint32(0); aa < 2; aa++ {
m := uint32(16 << 26)
m |= bo << 21
m |= bi << 16
m |= l << 0
m |= aa << 1
m |= 128
fmt.Fprintf(out, "\t.long 0x%08x\n", m)
}
}
// Generator all interesting conditional branch type instructions
func emitBranches(out io.Writer) {
fmt.Fprintf(out, ".text\n")
for bo := 0; bo < 0x20; bo++ {
// objdump behaves strangely on some cases when a z bit is set.
// Ignore these, they should never show up in correct code.
if bo&0x15 == 0x1 {
// skip 0b0.0.z cases where z != 0
continue
}
if bo&0x14 == 0x14 && bo != 14 {
// skip 0b1z1zz cases where z != 0
continue
}
// skip at == 1 cases. objdump doesn't handle these well either.
reserved_at := map[int]bool{5: true, 13: true, 17: true, 19: true}
if reserved_at[bo] {
continue
}
// only test cr0/cr1 bits. cr2-cr7 cases are basically identical to cr1.
for bi := 0; bi < 0x8; bi++ {
for l := 0; l < 2; l++ {
emitBSpr(uint32(bo), uint32(bi), uint32(l), out)
emitBc(uint32(bo), uint32(bi), uint32(l), out)
}
}
}
}
// Emit a test file using the generator called name.txt. This requires
// a GCC toolchain which supports -mcpu=power10.
func genOutput(name, tcPfx string, generator func(io.Writer)) {
// Generate object code from gcc
cmd := exec.Command(tcPfx+"gcc", "-c", "-mbig", "-mcpu=power10", "-x", "assembler-with-cpp", "-o", name+".o", "-")
input, _ := cmd.StdinPipe()
cmd.Stderr = os.Stderr
go func() {
defer input.Close()
generator(input.(io.Writer))
}()
if cmd.Run() != nil {
fmt.Printf("Failed running gcc for: %s\n", name)
return
}
defer os.Remove(name + ".o")
cmd = exec.Command(tcPfx+"objdump", "-d", name+".o")
// Run objdump and parse output into test format
output, _ := cmd.StdoutPipe()
defer output.Close()
scanner := bufio.NewScanner(output)
spacere := regexp.MustCompile("[[:space:]]+")
outf, _ := os.Create(name + ".txt")
defer outf.Close()
if cmd.Start() != nil {
fmt.Printf("Failed running objdump for: %s\n", name)
return
}
pfx := ""
dec := ""
for scanner.Scan() {
ln := spacere.Split(scanner.Text(), -1)
if len(ln) >= 7 {
opc := strings.Join(ln[2:6], "")
if len(pfx) == 0 {
dec = strings.Join(ln[6:], " ")
}
if v, _ := strconv.ParseInt(ln[2], 16, 16); v&0xFC == 0x04 {
pfx = opc
continue
}
fmt.Fprintf(outf, "%s%s|\tgnu\t%s\n", pfx, opc, dec)
pfx = ""
}
}
cmd.Wait()
}
// Generate representative instructions for all[1] instructions in pp64.csv.
//
// [1] See hack.h for a few minor, exceptional workarounds.
func emitGenerated(out io.Writer) {
cmd := exec.Command("go", "run", "../ppc64map/map.go", "-fmt=asm", "../pp64.csv")
cmdout, _ := cmd.Output()
out.Write(cmdout)
}
// Produce generated test outputs. This should be run every so often with
// new versions of objdump to ensure we stay up to date.
func main() {
genOutput("decode_branch", "powerpc64le-linux-gnu-", emitBranches)
genOutput("decode_generated", "powerpc64le-linux-gnu-", emitGenerated)
}