github.com/comwrg/go/src@v0.0.0-20220319063731-c238d0440370/hash/crc32/gen_const_ppc64le.go (about) 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 // +build ignore 7 8 // Generate the constant table associated with the poly used by the 9 // vpmsumd crc32 algorithm. 10 // 11 // go run gen_const_ppc64le.go 12 // 13 // generates crc32_table_ppc64le.s 14 15 // The following is derived from code written by Anton Blanchard 16 // <anton@au.ibm.com> found at https://github.com/antonblanchard/crc32-vpmsum. 17 // The original is dual licensed under GPL and Apache 2. As the copyright holder 18 // for the work, IBM has contributed this new work under the golang license. 19 20 // This code was written in Go based on the original C implementation. 21 22 // This is a tool needed to generate the appropriate constants needed for 23 // the vpmsum algorithm. It is included to generate new constant tables if 24 // new polynomial values are included in the future. 25 26 package main 27 28 import ( 29 "bytes" 30 "fmt" 31 "os" 32 ) 33 34 var blocking = 32 * 1024 35 36 func reflect_bits(b uint64, nr uint) uint64 { 37 var ref uint64 38 39 for bit := uint64(0); bit < uint64(nr); bit++ { 40 if (b & uint64(1)) == 1 { 41 ref |= (1 << (uint64(nr-1) - bit)) 42 } 43 b = (b >> 1) 44 } 45 return ref 46 } 47 48 func get_remainder(poly uint64, deg uint, n uint) uint64 { 49 50 rem, _ := xnmodp(n, poly, deg) 51 return rem 52 } 53 54 func get_quotient(poly uint64, bits, n uint) uint64 { 55 56 _, div := xnmodp(n, poly, bits) 57 return div 58 } 59 60 // xnmodp returns two values, p and div: 61 // p is the representation of the binary polynomial x**n mod (x ** deg + "poly") 62 // That is p is the binary representation of the modulus polynomial except for its highest-order term. 63 // div is the binary representation of the polynomial x**n / (x ** deg + "poly") 64 func xnmodp(n uint, poly uint64, deg uint) (uint64, uint64) { 65 66 var mod, mask, high, div uint64 67 68 if n < deg { 69 div = 0 70 return poly, div 71 } 72 mask = 1<<deg - 1 73 poly &= mask 74 mod = poly 75 div = 1 76 deg-- 77 n-- 78 for n > deg { 79 high = (mod >> deg) & 1 80 div = (div << 1) | high 81 mod <<= 1 82 if high != 0 { 83 mod ^= poly 84 } 85 n-- 86 } 87 return mod & mask, div 88 } 89 90 func main() { 91 w := new(bytes.Buffer) 92 93 fmt.Fprintf(w, "// autogenerated: do not edit!\n") 94 fmt.Fprintf(w, "// generated from crc32/gen_const_ppc64le.go\n") 95 fmt.Fprintln(w) 96 fmt.Fprintf(w, "#include \"textflag.h\"\n") 97 98 // These are the polynomials supported in vector now. 99 // If adding others, include the polynomial and a name 100 // to identify it. 101 102 genCrc32ConstTable(w, 0xedb88320, "IEEE") 103 genCrc32ConstTable(w, 0x82f63b78, "Cast") 104 genCrc32ConstTable(w, 0xeb31d82e, "Koop") 105 b := w.Bytes() 106 107 err := os.WriteFile("crc32_table_ppc64le.s", b, 0666) 108 if err != nil { 109 fmt.Printf("can't write output: %s\n", err) 110 } 111 } 112 113 func genCrc32ConstTable(w *bytes.Buffer, poly uint32, polyid string) { 114 115 ref_poly := reflect_bits(uint64(poly), 32) 116 fmt.Fprintf(w, "\n\t/* Reduce %d kbits to 1024 bits */\n", blocking*8) 117 j := 0 118 for i := (blocking * 8) - 1024; i > 0; i -= 1024 { 119 a := reflect_bits(get_remainder(ref_poly, 32, uint(i)), 32) << 1 120 b := reflect_bits(get_remainder(ref_poly, 32, uint(i+64)), 32) << 1 121 122 fmt.Fprintf(w, "\t/* x^%d mod p(x)%s, x^%d mod p(x)%s */\n", uint(i+64), "", uint(i), "") 123 fmt.Fprintf(w, "DATA ·%sConst+%d(SB)/8,$0x%016x\n", polyid, j*8, b) 124 fmt.Fprintf(w, "DATA ·%sConst+%d(SB)/8,$0x%016x\n", polyid, (j+1)*8, a) 125 126 j += 2 127 fmt.Fprintf(w, "\n") 128 } 129 130 for i := (1024 * 2) - 128; i >= 0; i -= 128 { 131 a := reflect_bits(get_remainder(ref_poly, 32, uint(i+32)), 32) 132 b := reflect_bits(get_remainder(ref_poly, 32, uint(i+64)), 32) 133 c := reflect_bits(get_remainder(ref_poly, 32, uint(i+96)), 32) 134 d := reflect_bits(get_remainder(ref_poly, 32, uint(i+128)), 32) 135 136 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, "") 137 fmt.Fprintf(w, "DATA ·%sConst+%d(SB)/8,$0x%08x%08x\n", polyid, j*8, c, d) 138 fmt.Fprintf(w, "DATA ·%sConst+%d(SB)/8,$0x%08x%08x\n", polyid, (j+1)*8, a, b) 139 140 j += 2 141 fmt.Fprintf(w, "\n") 142 } 143 144 fmt.Fprintf(w, "GLOBL ·%sConst(SB),RODATA,$4336\n", polyid) 145 fmt.Fprintf(w, "\n /* Barrett constant m - (4^32)/n */\n") 146 fmt.Fprintf(w, "DATA ·%sBarConst(SB)/8,$0x%016x\n", polyid, reflect_bits(get_quotient(ref_poly, 32, 64), 33)) 147 fmt.Fprintf(w, "DATA ·%sBarConst+8(SB)/8,$0x0000000000000000\n", polyid) 148 fmt.Fprintf(w, "DATA ·%sBarConst+16(SB)/8,$0x%016x\n", polyid, reflect_bits((uint64(1)<<32)|ref_poly, 33)) // reflected? 149 fmt.Fprintf(w, "DATA ·%sBarConst+24(SB)/8,$0x0000000000000000\n", polyid) 150 fmt.Fprintf(w, "GLOBL ·%sBarConst(SB),RODATA,$32\n", polyid) 151 }