Home | History | Annotate | Download | only in 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 // +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 (a] 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 	"io/ioutil"
     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 := new(bytes.Buffer)
     91 
     92 	fmt.Fprintf(w, "// autogenerated: do not edit!\n")
     93 	fmt.Fprintf(w, "// generated from crc32/gen_const_ppc64le.go\n")
     94 	fmt.Fprintln(w)
     95 	fmt.Fprintf(w, "#include \"textflag.h\"\n")
     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 := ioutil.WriteFile("crc32_table_ppc64le.s", b, 0666)
    107 	if err != nil {
    108 		fmt.Printf("can't write output: %s\n", err)
    109 	}
    110 }
    111 
    112 func genCrc32ConstTable(w *bytes.Buffer, poly uint32, polyid string) {
    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 /* 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