Black Lives Matter. Support the Equal Justice Initiative.

Source file src/hash/crc32/gen_const_ppc64le.go

Documentation: hash/crc32

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

View as plain text