* Calculate * (x*2^4 + worda[3,0]*h^4+wordb[3,0]*h^3+...+wordd[3,0]*h) * * ... * 2^4 + worda[63,60]*h^4+ ... + wordd[63,60]*h * * Passing/returning struct is .5% faster than passing in via pointer on * amd64. */
| 172 | * amd64. |
| 173 | */ |
| 174 | static struct gf128 |
| 175 | gfmultword4(uint64_t worda, uint64_t wordb, uint64_t wordc, uint64_t wordd, |
| 176 | struct gf128 x, struct gf128table4 *tbl) |
| 177 | { |
| 178 | struct gf128 rowa, rowb, rowc, rowd; |
| 179 | unsigned bitsa, bitsb, bitsc, bitsd; |
| 180 | unsigned redbits; |
| 181 | int i; |
| 182 | |
| 183 | /* |
| 184 | * XXX - nibble reverse words to save a shift? probably not as |
| 185 | * nibble reverse would take 20 ops (5 * 4) verse 16 |
| 186 | */ |
| 187 | |
| 188 | for (i = 0; i < 64; i += 4) { |
| 189 | bitsa = worda % 16; |
| 190 | bitsb = wordb % 16; |
| 191 | bitsc = wordc % 16; |
| 192 | bitsd = wordd % 16; |
| 193 | |
| 194 | /* fetch row */ |
| 195 | rowa = readrow(&tbl->tbls[3], bitsa); |
| 196 | rowb = readrow(&tbl->tbls[2], bitsb); |
| 197 | rowc = readrow(&tbl->tbls[1], bitsc); |
| 198 | rowd = readrow(&tbl->tbls[0], bitsd); |
| 199 | |
| 200 | /* x * 2^4 */ |
| 201 | redbits = x.v[1] % 16; |
| 202 | x.v[1] = (x.v[1] >> 4) | (x.v[0] % 16) << 60; |
| 203 | x.v[0] >>= 4; |
| 204 | x.v[0] ^= (uint64_t)reduction[redbits] << (64 - 16); |
| 205 | |
| 206 | worda >>= 4; |
| 207 | wordb >>= 4; |
| 208 | wordc >>= 4; |
| 209 | wordd >>= 4; |
| 210 | |
| 211 | x = gf128_add(x, gf128_add(rowa, gf128_add(rowb, |
| 212 | gf128_add(rowc, rowd)))); |
| 213 | } |
| 214 | |
| 215 | return x; |
| 216 | } |
| 217 | |
| 218 | struct gf128 |
| 219 | gf128_mul(struct gf128 v, struct gf128table *tbl) |
no test coverage detected