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.
7 // Generate the constant table associated with the poly used by the
8 // vpmsumd crc32 algorithm.
10 // go run gen_const_ppc64le.go
12 // generates crc32_table_ppc64le.s
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.
19 // This code was written in Go based on the original C implementation.
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.
33 var blocking
= 32 * 1024
35 func reflect_bits(b
uint64, nr
uint) uint64 {
38 for bit
:= uint64(0); bit
< uint64(nr
); bit
++ {
39 if (b
& uint64(1)) == 1 {
40 ref |
= (1 << (uint64(nr
-1) - bit
))
47 func get_remainder(poly
uint64, deg
uint, n
uint) uint64 {
49 rem
, _
:= xnmodp(n
, poly
, deg
)
53 func get_quotient(poly
uint64, bits
, n
uint) uint64 {
55 _
, div
:= xnmodp(n
, poly
, bits
)
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) {
65 var mod
, mask
, high
, div
uint64
78 high
= (mod
>> deg
) & 1
79 div
= (div
<< 1) | high
86 return mod
& mask
, div
90 w
:= new(bytes
.Buffer
)
92 fmt
.Fprintf(w
, "// autogenerated: do not edit!\n")
93 fmt
.Fprintf(w
, "// generated from crc32/gen_const_ppc64le.go\n")
95 fmt
.Fprintf(w
, "#include \"textflag.h\"\n")
97 // These are the polynomials supported in vector now.
98 // If adding others, include the polynomial and a name
101 genCrc32ConstTable(w
, 0xedb88320, "IEEE")
102 genCrc32ConstTable(w
, 0x82f63b78, "Cast")
103 genCrc32ConstTable(w
, 0xeb31d82e, "Koop")
106 err
:= ioutil
.WriteFile("crc32_table_ppc64le.s", b
, 0666)
108 fmt
.Printf("can't write output: %s\n", err
)
112 func genCrc32ConstTable(w
*bytes
.Buffer
, poly
uint32, polyid
string) {
114 ref_poly
:= reflect_bits(uint64(poly
), 32)
115 fmt
.Fprintf(w
, "\n\t/* Reduce %d kbits to 1024 bits */\n", blocking
*8)
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
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
)
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)
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
)
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
)