|
| 1 | +// Adler-32 ProcessBlocks AArch64 NEON implementation (32-byte blocks). |
| 2 | +// Expects AAPCS64: x0 = AData, w1 = ANumBlocks, x2 = ASums, x3 = AConstants. |
| 3 | +// ASums layout: [SumA: UInt32, SumB: UInt32]. Does NOT apply mod 65521. |
| 4 | +// Constants layout matches Adler32Constants: bytes [32..1] at offset 0..31 |
| 5 | +// (two 16-byte halves; only the weight bytes are read here). |
| 6 | +// Reference (golden): HashLib Adler32BlocksSsse3_x86_64.inc; |
| 7 | +// Chromium zlib adler32_simd.c ADLER32_SIMD_NEON column-sum + vmlal path. |
| 8 | +// |
| 9 | +// Instruction encodings (for assembler compatibility): |
| 10 | +// FPC 3.2.2's inline assembler cannot encode AArch64 vector mnemonics |
| 11 | +// (subscripted vector regs require FPC 3.3+, and ldr/str/ldp with qN crash the |
| 12 | +// 3.2.2 assembler). Each such instruction is therefore emitted as its raw 32-bit |
| 13 | +// '.long' opcode, with the equivalent mnemonic in the trailing comment; only |
| 14 | +// neg/ret stay as text. |
| 15 | +// |
| 16 | +// Register map: |
| 17 | +// w9 = block counter (from w1) |
| 18 | +// w10 = SumA in / SumA out |
| 19 | +// w11 = SumB in / SumB out |
| 20 | +// w12 = SumA * num_blocks (v_ps lane 0 seed) |
| 21 | +// w13 = horizontal-reduce scratch |
| 22 | +// v0 = v_s1 (uint32x4 byte-sum accumulators) |
| 23 | +// v1 = v_s2 (uint32x4 s2 partial, SumB seeded in lane 0) |
| 24 | +// v4-v5 = 32 input bytes per block |
| 25 | +// v6-v8 = uaddlp / horizontal-reduce temps |
| 26 | +// v16-v19 = column sums (uint16x8) |
| 27 | +// v20 = v_ps (SumA*blocks + per-block v_s1), lane 0 used before <<5 add |
| 28 | +// v24-v27 = widened weight vectors for vmlal |
| 29 | +// v28-v29 = weight byte loads from AConstants |
| 30 | +// v30 = ext scratch for weight / reduce halves |
| 31 | + .long 0xb940004a // ldr w10, [x2] |
| 32 | + .long 0xb940044b // ldr w11, [x2, #4] |
| 33 | + .long 0x1b017d4c // mul w12, w10, w1 |
| 34 | + .long 0x2a0103e9 // mov w9, w1 |
| 35 | + .long 0x6e341e94 // eor v20.16b, v20.16b, v20.16b |
| 36 | + .long 0x4e041d94 // ins v20.s[0], w12 |
| 37 | + .long 0x6e211c21 // eor v1.16b, v1.16b, v1.16b |
| 38 | + .long 0x4e041d61 // ins v1.s[0], w11 |
| 39 | + .long 0x6e201c00 // eor v0.16b, v0.16b, v0.16b |
| 40 | + .long 0x6e301e10 // eor v16.16b, v16.16b, v16.16b |
| 41 | + .long 0x6e311e31 // eor v17.16b, v17.16b, v17.16b |
| 42 | + .long 0x6e321e52 // eor v18.16b, v18.16b, v18.16b |
| 43 | + .long 0x6e331e73 // eor v19.16b, v19.16b, v19.16b |
| 44 | + .long 0x3dc0007c // ldr q28, [x3, #0x0] |
| 45 | + .long 0x3dc0047d // ldr q29, [x3, #0x10] |
| 46 | +.Ladler_blocks_loop: |
| 47 | + .long 0x4ea08694 // add v20.4s, v20.4s, v0.4s |
| 48 | + .long 0x3dc00004 // ldr q4, [x0, #0x0] |
| 49 | + .long 0x3dc00405 // ldr q5, [x0, #0x10] |
| 50 | + .long 0x6e202886 // uaddlp v6.8h, v4.16b |
| 51 | + .long 0x6e6068c0 // uadalp v0.4s, v6.8h |
| 52 | + .long 0x6e2028a7 // uaddlp v7.8h, v5.16b |
| 53 | + .long 0x6e6068e0 // uadalp v0.4s, v7.8h |
| 54 | + .long 0x2e241210 // uaddw v16.8h, v16.8h, v4.8b |
| 55 | + .long 0x6e241231 // uaddw2 v17.8h, v17.8h, v4.16b |
| 56 | + .long 0x2e251252 // uaddw v18.8h, v18.8h, v5.8b |
| 57 | + .long 0x6e251273 // uaddw2 v19.8h, v19.8h, v5.16b |
| 58 | + .long 0x91008000 // add x0, x0, #32 |
| 59 | + .long 0x71000529 // subs w9, w9, #1 |
| 60 | + b.ne .Ladler_blocks_loop |
| 61 | + .long 0x4f255694 // shl v20.4s, v20.4s, #5 |
| 62 | + .long 0x4eb48421 // add v1.4s, v1.4s, v20.4s |
| 63 | + .long 0x2f08a798 // ushll v24.8h, v28.8b, #0 |
| 64 | + .long 0x6e1c439e // ext v30.16b, v28.16b, v28.16b, #8 |
| 65 | + .long 0x2f08a7d9 // ushll v25.8h, v30.8b, #0 |
| 66 | + .long 0x2f08a7ba // ushll v26.8h, v29.8b, #0 |
| 67 | + .long 0x6e1d43be // ext v30.16b, v29.16b, v29.16b, #8 |
| 68 | + .long 0x2f08a7db // ushll v27.8h, v30.8b, #0 |
| 69 | + .long 0x2e788201 // umlal v1.4s, v16.4h, v24.4h |
| 70 | + .long 0x6e788201 // umlal2 v1.4s, v16.8h, v24.8h |
| 71 | + .long 0x2e798221 // umlal v1.4s, v17.4h, v25.4h |
| 72 | + .long 0x6e798221 // umlal2 v1.4s, v17.8h, v25.8h |
| 73 | + .long 0x2e7a8241 // umlal v1.4s, v18.4h, v26.4h |
| 74 | + .long 0x6e7a8241 // umlal2 v1.4s, v18.8h, v26.8h |
| 75 | + .long 0x2e7b8261 // umlal v1.4s, v19.4h, v27.4h |
| 76 | + .long 0x6e7b8261 // umlal2 v1.4s, v19.8h, v27.8h |
| 77 | + .long 0x4ea0bc06 // addp v6.4s, v0.4s, v0.4s |
| 78 | + .long 0x0ea6bcc6 // addp v6.2s, v6.2s, v6.2s |
| 79 | + .long 0x0e043ccd // umov w13, v6.s[0] |
| 80 | + .long 0x0b0d014a // add w10, w10, w13 |
| 81 | + .long 0x4ea1bc26 // addp v6.4s, v1.4s, v1.4s |
| 82 | + .long 0x0ea6bcc6 // addp v6.2s, v6.2s, v6.2s |
| 83 | + .long 0x0e043ccb // umov w11, v6.s[0] |
| 84 | + .long 0xb900004a // str w10, [x2] |
| 85 | + .long 0xb900044b // str w11, [x2, #4] |
| 86 | + ret |
0 commit comments