summaryrefslogtreecommitdiffstats
path: root/src/hash/crc32/gen_const_ppc64le.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/hash/crc32/gen_const_ppc64le.go')
-rw-r--r--src/hash/crc32/gen_const_ppc64le.go150
1 files changed, 150 insertions, 0 deletions
diff --git a/src/hash/crc32/gen_const_ppc64le.go b/src/hash/crc32/gen_const_ppc64le.go
new file mode 100644
index 0000000..2f15a60
--- /dev/null
+++ b/src/hash/crc32/gen_const_ppc64le.go
@@ -0,0 +1,150 @@
+// Copyright 2017 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 the constant table associated with the poly used by the
+// vpmsumd crc32 algorithm.
+//
+// go run gen_const_ppc64le.go
+//
+// generates crc32_table_ppc64le.s
+
+// The following is derived from code written by Anton Blanchard
+// <anton@au.ibm.com> found at https://github.com/antonblanchard/crc32-vpmsum.
+// The original is dual licensed under GPL and Apache 2. As the copyright holder
+// for the work, IBM has contributed this new work under the golang license.
+
+// This code was written in Go based on the original C implementation.
+
+// This is a tool needed to generate the appropriate constants needed for
+// the vpmsum algorithm. It is included to generate new constant tables if
+// new polynomial values are included in the future.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+)
+
+var blocking = 32 * 1024
+
+func reflect_bits(b uint64, nr uint) uint64 {
+ var ref uint64
+
+ for bit := uint64(0); bit < uint64(nr); bit++ {
+ if (b & uint64(1)) == 1 {
+ ref |= (1 << (uint64(nr-1) - bit))
+ }
+ b = (b >> 1)
+ }
+ return ref
+}
+
+func get_remainder(poly uint64, deg uint, n uint) uint64 {
+
+ rem, _ := xnmodp(n, poly, deg)
+ return rem
+}
+
+func get_quotient(poly uint64, bits, n uint) uint64 {
+
+ _, div := xnmodp(n, poly, bits)
+ return div
+}
+
+// xnmodp returns two values, p and div:
+// p is the representation of the binary polynomial x**n mod (x ** deg + "poly")
+// That is p is the binary representation of the modulus polynomial except for its highest-order term.
+// div is the binary representation of the polynomial x**n / (x ** deg + "poly")
+func xnmodp(n uint, poly uint64, deg uint) (uint64, uint64) {
+
+ var mod, mask, high, div uint64
+
+ if n < deg {
+ div = 0
+ return poly, div
+ }
+ mask = 1<<deg - 1
+ poly &= mask
+ mod = poly
+ div = 1
+ deg--
+ n--
+ for n > deg {
+ high = (mod >> deg) & 1
+ div = (div << 1) | high
+ mod <<= 1
+ if high != 0 {
+ mod ^= poly
+ }
+ n--
+ }
+ return mod & mask, div
+}
+
+func main() {
+ w := new(bytes.Buffer)
+
+ fmt.Fprintf(w, "// autogenerated: do not edit!\n")
+ fmt.Fprintf(w, "// generated from crc32/gen_const_ppc64le.go\n")
+ fmt.Fprintln(w)
+ fmt.Fprintf(w, "#include \"textflag.h\"\n")
+
+ // These are the polynomials supported in vector now.
+ // If adding others, include the polynomial and a name
+ // to identify it.
+
+ genCrc32ConstTable(w, 0xedb88320, "IEEE")
+ genCrc32ConstTable(w, 0x82f63b78, "Cast")
+ genCrc32ConstTable(w, 0xeb31d82e, "Koop")
+ b := w.Bytes()
+
+ err := os.WriteFile("crc32_table_ppc64le.s", b, 0666)
+ if err != nil {
+ fmt.Printf("can't write output: %s\n", err)
+ }
+}
+
+func genCrc32ConstTable(w *bytes.Buffer, poly uint32, polyid string) {
+
+ ref_poly := reflect_bits(uint64(poly), 32)
+ fmt.Fprintf(w, "\n\t/* Reduce %d kbits to 1024 bits */\n", blocking*8)
+ j := 0
+ for i := (blocking * 8) - 1024; i > 0; i -= 1024 {
+ a := reflect_bits(get_remainder(ref_poly, 32, uint(i)), 32) << 1
+ b := reflect_bits(get_remainder(ref_poly, 32, uint(i+64)), 32) << 1
+
+ fmt.Fprintf(w, "\t/* x^%d mod p(x)%s, x^%d mod p(x)%s */\n", uint(i+64), "", uint(i), "")
+ fmt.Fprintf(w, "DATA ·%sConst+%d(SB)/8,$0x%016x\n", polyid, j*8, b)
+ fmt.Fprintf(w, "DATA ·%sConst+%d(SB)/8,$0x%016x\n", polyid, (j+1)*8, a)
+
+ j += 2
+ fmt.Fprintf(w, "\n")
+ }
+
+ for i := (1024 * 2) - 128; i >= 0; i -= 128 {
+ a := reflect_bits(get_remainder(ref_poly, 32, uint(i+32)), 32)
+ b := reflect_bits(get_remainder(ref_poly, 32, uint(i+64)), 32)
+ c := reflect_bits(get_remainder(ref_poly, 32, uint(i+96)), 32)
+ d := reflect_bits(get_remainder(ref_poly, 32, uint(i+128)), 32)
+
+ 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, "")
+ fmt.Fprintf(w, "DATA ·%sConst+%d(SB)/8,$0x%08x%08x\n", polyid, j*8, c, d)
+ fmt.Fprintf(w, "DATA ·%sConst+%d(SB)/8,$0x%08x%08x\n", polyid, (j+1)*8, a, b)
+
+ j += 2
+ fmt.Fprintf(w, "\n")
+ }
+
+ fmt.Fprintf(w, "GLOBL ·%sConst(SB),RODATA,$4336\n", polyid)
+ fmt.Fprintf(w, "\n /* Barrett constant m - (4^32)/n */\n")
+ fmt.Fprintf(w, "DATA ·%sBarConst(SB)/8,$0x%016x\n", polyid, reflect_bits(get_quotient(ref_poly, 32, 64), 33))
+ fmt.Fprintf(w, "DATA ·%sBarConst+8(SB)/8,$0x0000000000000000\n", polyid)
+ fmt.Fprintf(w, "DATA ·%sBarConst+16(SB)/8,$0x%016x\n", polyid, reflect_bits((uint64(1)<<32)|ref_poly, 33)) // reflected?
+ fmt.Fprintf(w, "DATA ·%sBarConst+24(SB)/8,$0x0000000000000000\n", polyid)
+ fmt.Fprintf(w, "GLOBL ·%sBarConst(SB),RODATA,$32\n", polyid)
+}