...

Source file src/hash/crc32/gen_const_ppc64le.go

     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@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	

View as plain text