golang.org/x/arch@v0.17.0/s390x/s390xutil/util.go (about)

     1  // Copyright 2024 The Go Authors.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build ignore
     6  
     7  // Generate interesting test cases from s390x objdump via
     8  // go run util.go
     9  //
    10  // This requires "/usr/bin/gcc" and "objdump" be in the PATH this command is run.
    11  //
    12  // These tools can be acquired from the IBM advance toolchain for amd64 hosts too.
    13  
    14  package main
    15  
    16  import (
    17  	"bufio"
    18  	"fmt"
    19  	"io"
    20  	"os"
    21  	"os/exec"
    22  	"regexp"
    23  	"strconv"
    24  	"strings"
    25  )
    26  
    27  // Emit a test file using the generator called name.txt.  This requires
    28  // a GCC toolchain which supports -march=z16.
    29  func genOutput(name, tcPfx string, generator func(io.Writer)) {
    30  	// Generate object code from gcc
    31  	cmd := exec.Command(tcPfx+"gcc", "-c", "-march=z16", "-x", "assembler-with-cpp", "-o", name+".o", "-")
    32  	input, _ := cmd.StdinPipe()
    33  	cmd.Stderr = os.Stderr
    34  	go func() {
    35  		defer input.Close()
    36  		generator(input.(io.Writer))
    37  	}()
    38  	if cmd.Run() != nil {
    39  		fmt.Printf("Failed running gcc for: %s\n", name)
    40  		return
    41  	}
    42  	defer os.Remove(name + ".o")
    43  	cmd = exec.Command(tcPfx+"objdump", "-d", name+".o")
    44  
    45  	// Run objdump and parse output into test format
    46  	output, _ := cmd.StdoutPipe()
    47  	defer output.Close()
    48  	scanner := bufio.NewScanner(output)
    49  	spacere := regexp.MustCompile("[[:space:]]+")
    50  	outf, _ := os.Create(name + ".txt")
    51  	defer outf.Close()
    52  	if cmd.Start() != nil {
    53  		fmt.Printf("Failed running objdump for: %s\n", name)
    54  		return
    55  	}
    56  
    57  	for scanner.Scan() {
    58  		ln := spacere.Split(scanner.Text(), -1)
    59  		var cnt int16
    60  		if len(ln) >= 5 {
    61  			v, _ := strconv.ParseInt(ln[2], 16, 16)
    62  			if (v >> 6 & 0x3) == 0 {
    63  				cnt = 2
    64  			} else if v>>6&0x3 == 1 || v>>6&0x3 == 2 {
    65  				cnt = 4
    66  			} else {
    67  				cnt = 6
    68  			}
    69  			opc := strings.Join(ln[2:cnt+2], "")
    70  			dec := strings.Join(ln[cnt+2:], " ")
    71  			fmt.Fprintf(outf, "%12s|\tgnu\t%-18s\n", opc, dec)
    72  		}
    73  	}
    74  	cmd.Wait()
    75  }
    76  
    77  // Generate representative instructions for all[1] instructions in s390x.csv.
    78  //
    79  // [1] See hack.h for a few minor, exceptional workarounds.
    80  func emitGenerated(out io.Writer) {
    81  	cmd := exec.Command("go", "run", "../s390xmap/map.go", "-fmt=asm", "../s390x.csv")
    82  	cmdout, _ := cmd.Output()
    83  	out.Write(cmdout)
    84  }
    85  
    86  // Produce generated test outputs.  This should be run every so often with
    87  // new versions of objdump to ensure we stay up to date.
    88  func main() {
    89  	genOutput("decode_generated", "/usr/bin/", emitGenerated)
    90  }