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 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 "os"
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 := &bytes.Buffer{}
91 92 // Standard: https://go.dev/s/generatedcode
93 fmt.Fprintln(w, `// Code generated by "go run gen_const_ppc64le.go"; DO NOT EDIT.`)
94 fmt.Fprintln(w)
95 fmt.Fprintln(w, `#include "textflag.h"`)
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 := os.WriteFile("crc32_table_ppc64le.s", b, 0666)
107 if err != nil {
108 fmt.Fprintf(os.Stderr, "can't write output: %s\n", err)
109 }
110 }
111 112 func genCrc32ConstTable(w *bytes.Buffer, poly uint32, polyid []byte) {
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\t/* 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