gen_const_ppc64le.mx raw

   1  // Copyright 2017 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 the constant table associated with the poly used by the
   8  // vpmsumd crc32 algorithm.
   9  //
  10  // go run gen_const_ppc64le.go
  11  //
  12  // generates crc32_table_ppc64le.s
  13  
  14  // The following is derived from code written by Anton Blanchard
  15  // <anton@au.ibm.com> found at https://github.com/antonblanchard/crc32-vpmsum.
  16  // The original is dual licensed under GPL and Apache 2.  As the copyright holder
  17  // for the work, IBM has contributed this new work under the golang license.
  18  
  19  // This code was written in Go based on the original C implementation.
  20  
  21  // This is a tool needed to generate the appropriate constants needed for
  22  // the vpmsum algorithm.  It is included to generate new constant tables if
  23  // new polynomial values are included in the future.
  24  
  25  package main
  26  
  27  import (
  28  	"bytes"
  29  	"fmt"
  30  	"os"
  31  )
  32  
  33  var blocking = 32 * 1024
  34  
  35  func reflect_bits(b uint64, nr uint) uint64 {
  36  	var ref uint64
  37  
  38  	for bit := uint64(0); bit < uint64(nr); bit++ {
  39  		if (b & uint64(1)) == 1 {
  40  			ref |= (1 << (uint64(nr-1) - bit))
  41  		}
  42  		b = (b >> 1)
  43  	}
  44  	return ref
  45  }
  46  
  47  func get_remainder(poly uint64, deg uint, n uint) uint64 {
  48  
  49  	rem, _ := xnmodp(n, poly, deg)
  50  	return rem
  51  }
  52  
  53  func get_quotient(poly uint64, bits, n uint) uint64 {
  54  
  55  	_, div := xnmodp(n, poly, bits)
  56  	return div
  57  }
  58  
  59  // xnmodp returns two values, p and div:
  60  // p is the representation of the binary polynomial x**n mod (x ** deg + "poly")
  61  // That is p is the binary representation of the modulus polynomial except for its highest-order term.
  62  // div is the binary representation of the polynomial x**n / (x ** deg + "poly")
  63  func xnmodp(n uint, poly uint64, deg uint) (uint64, uint64) {
  64  
  65  	var mod, mask, high, div uint64
  66  
  67  	if n < deg {
  68  		div = 0
  69  		return poly, div
  70  	}
  71  	mask = 1<<deg - 1
  72  	poly &= mask
  73  	mod = poly
  74  	div = 1
  75  	deg--
  76  	n--
  77  	for n > deg {
  78  		high = (mod >> deg) & 1
  79  		div = (div << 1) | high
  80  		mod <<= 1
  81  		if high != 0 {
  82  			mod ^= poly
  83  		}
  84  		n--
  85  	}
  86  	return mod & mask, div
  87  }
  88  
  89  func main() {
  90  	w := &bytes.Buffer{}
  91  
  92  	// Standard: https://go.dev/s/generatedcode
  93  	fmt.Fprintln(w, `// Code generated by "go run gen_const_ppc64le.go"; DO NOT EDIT.`)
  94  	fmt.Fprintln(w)
  95  	fmt.Fprintln(w, `#include "textflag.h"`)
  96  
  97  	// These are the polynomials supported in vector now.
  98  	// If adding others, include the polynomial and a name
  99  	// to identify it.
 100  
 101  	genCrc32ConstTable(w, 0xedb88320, "IEEE")
 102  	genCrc32ConstTable(w, 0x82f63b78, "Cast")
 103  	genCrc32ConstTable(w, 0xeb31d82e, "Koop")
 104  	b := w.Bytes()
 105  
 106  	err := os.WriteFile("crc32_table_ppc64le.s", b, 0666)
 107  	if err != nil {
 108  		fmt.Fprintf(os.Stderr, "can't write output: %s\n", err)
 109  	}
 110  }
 111  
 112  func genCrc32ConstTable(w *bytes.Buffer, poly uint32, polyid []byte) {
 113  
 114  	ref_poly := reflect_bits(uint64(poly), 32)
 115  	fmt.Fprintf(w, "\n\t/* Reduce %d kbits to 1024 bits */\n", blocking*8)
 116  	j := 0
 117  	for i := (blocking * 8) - 1024; i > 0; i -= 1024 {
 118  		a := reflect_bits(get_remainder(ref_poly, 32, uint(i)), 32) << 1
 119  		b := reflect_bits(get_remainder(ref_poly, 32, uint(i+64)), 32) << 1
 120  
 121  		fmt.Fprintf(w, "\t/* x^%d mod p(x)%s, x^%d mod p(x)%s */\n", uint(i+64), "", uint(i), "")
 122  		fmt.Fprintf(w, "DATA ·%sConst+%d(SB)/8,$0x%016x\n", polyid, j*8, b)
 123  		fmt.Fprintf(w, "DATA ·%sConst+%d(SB)/8,$0x%016x\n", polyid, (j+1)*8, a)
 124  
 125  		j += 2
 126  		fmt.Fprintf(w, "\n")
 127  	}
 128  
 129  	for i := (1024 * 2) - 128; i >= 0; i -= 128 {
 130  		a := reflect_bits(get_remainder(ref_poly, 32, uint(i+32)), 32)
 131  		b := reflect_bits(get_remainder(ref_poly, 32, uint(i+64)), 32)
 132  		c := reflect_bits(get_remainder(ref_poly, 32, uint(i+96)), 32)
 133  		d := reflect_bits(get_remainder(ref_poly, 32, uint(i+128)), 32)
 134  
 135  		fmt.Fprintf(w, "\t/* x^%d mod p(x)%s, x^%d mod p(x)%s, x^%d mod p(x)%s, x^%d mod p(x)%s */\n", i+128, "", i+96, "", i+64, "", i+32, "")
 136  		fmt.Fprintf(w, "DATA ·%sConst+%d(SB)/8,$0x%08x%08x\n", polyid, j*8, c, d)
 137  		fmt.Fprintf(w, "DATA ·%sConst+%d(SB)/8,$0x%08x%08x\n", polyid, (j+1)*8, a, b)
 138  
 139  		j += 2
 140  		fmt.Fprintf(w, "\n")
 141  	}
 142  
 143  	fmt.Fprintf(w, "GLOBL ·%sConst(SB),RODATA,$4336\n", polyid)
 144  	fmt.Fprintf(w, "\n\t/* Barrett constant m - (4^32)/n */\n")
 145  	fmt.Fprintf(w, "DATA ·%sBarConst(SB)/8,$0x%016x\n", polyid, reflect_bits(get_quotient(ref_poly, 32, 64), 33))
 146  	fmt.Fprintf(w, "DATA ·%sBarConst+8(SB)/8,$0x0000000000000000\n", polyid)
 147  	fmt.Fprintf(w, "DATA ·%sBarConst+16(SB)/8,$0x%016x\n", polyid, reflect_bits((uint64(1)<<32)|ref_poly, 33)) // reflected?
 148  	fmt.Fprintf(w, "DATA ·%sBarConst+24(SB)/8,$0x0000000000000000\n", polyid)
 149  	fmt.Fprintf(w, "GLOBL ·%sBarConst(SB),RODATA,$32\n", polyid)
 150  }
 151