1
0

checksum_arm64.s 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #include "textflag.h"
  2. // func checksumNEON(buf []byte, initial uint16) uint16
  3. //
  4. // Mirrors the algorithm in checksum_amd64.s: sum the buffer treating it as
  5. // a stream of uint32s in machine (little-endian) byte order, accumulating
  6. // into 64-bit lanes that have ample carry headroom; fold and byte-swap once
  7. // at the very end to recover the on-wire (big-endian) result.
  8. //
  9. // Each loop iteration loads 64 bytes via VLD1.P into V0..V3 (4 Q regs).
  10. // VUADDW takes the low two uint32 lanes of a Q reg, zero-extends them to
  11. // uint64, and adds them into a 2×uint64 accumulator; VUADDW2 does the same
  12. // for the high two lanes. Four ymm-equivalent accumulators (V8..V11) get
  13. // updated twice per iter to break the dep chain. Tail bytes go through a
  14. // scalar ADCS chain seeded with the byte-swapped initial.
  15. TEXT ·checksumNEON(SB), NOSPLIT, $0-34
  16. MOVD buf_base+0(FP), R0
  17. MOVD buf_len+8(FP), R1
  18. MOVHU initial+24(FP), R2
  19. // Pre-byteswap initial into the LE-summing space so it merges directly
  20. // with the rest of the accumulator.
  21. REV16W R2, R2
  22. MOVD ZR, R3 // scalar accumulator
  23. CMP $32, R1
  24. BLT scalar_tail
  25. VEOR V8.B16, V8.B16, V8.B16
  26. VEOR V9.B16, V9.B16, V9.B16
  27. VEOR V10.B16, V10.B16, V10.B16
  28. VEOR V11.B16, V11.B16, V11.B16
  29. CMP $64, R1
  30. BLT loop16_init
  31. loop64:
  32. VLD1.P 64(R0), [V0.B16, V1.B16, V2.B16, V3.B16]
  33. VUADDW V0.S2, V8.D2, V8.D2
  34. VUADDW2 V0.S4, V9.D2, V9.D2
  35. VUADDW V1.S2, V10.D2, V10.D2
  36. VUADDW2 V1.S4, V11.D2, V11.D2
  37. VUADDW V2.S2, V8.D2, V8.D2
  38. VUADDW2 V2.S4, V9.D2, V9.D2
  39. VUADDW V3.S2, V10.D2, V10.D2
  40. VUADDW2 V3.S4, V11.D2, V11.D2
  41. SUB $64, R1, R1
  42. CMP $64, R1
  43. BGE loop64
  44. loop16_init:
  45. CMP $16, R1
  46. BLT reduce_vec
  47. loop16:
  48. VLD1.P 16(R0), [V0.B16]
  49. VUADDW V0.S2, V8.D2, V8.D2
  50. VUADDW2 V0.S4, V9.D2, V9.D2
  51. SUB $16, R1, R1
  52. CMP $16, R1
  53. BGE loop16
  54. reduce_vec:
  55. // Combine the four accumulators into V8.
  56. VADD V9.D2, V8.D2, V8.D2
  57. VADD V11.D2, V10.D2, V10.D2
  58. VADD V10.D2, V8.D2, V8.D2
  59. // Horizontal-add the two lanes of V8.D2 into a single uint64.
  60. VADDP V8.D2, V8.D2, V8.D2
  61. VMOV V8.D[0], R8
  62. ADDS R8, R3, R3
  63. ADC ZR, R3, R3
  64. scalar_tail:
  65. CMP $8, R1
  66. BLT tail4
  67. loop8:
  68. MOVD.P 8(R0), R8
  69. ADDS R8, R3, R3
  70. ADC ZR, R3, R3
  71. SUB $8, R1, R1
  72. CMP $8, R1
  73. BGE loop8
  74. tail4:
  75. CMP $4, R1
  76. BLT tail2
  77. MOVWU.P 4(R0), R8
  78. ADDS R8, R3, R3
  79. ADC ZR, R3, R3
  80. SUB $4, R1, R1
  81. tail2:
  82. CMP $2, R1
  83. BLT tail1
  84. MOVHU.P 2(R0), R8
  85. ADDS R8, R3, R3
  86. ADC ZR, R3, R3
  87. SUB $2, R1, R1
  88. tail1:
  89. CBZ R1, fold
  90. MOVBU (R0), R8
  91. ADDS R8, R3, R3
  92. ADC ZR, R3, R3
  93. fold:
  94. // Merge the byte-swapped initial into our LE-form accumulator.
  95. ADDS R2, R3, R3
  96. ADC ZR, R3, R3
  97. // 64 → 33 bits.
  98. LSR $32, R3, R8
  99. AND $0xffffffff, R3, R3
  100. ADD R8, R3, R3
  101. // 33 → 32 (truncate after adding bit 32 back).
  102. LSR $32, R3, R8
  103. ADD R8, R3, R3
  104. AND $0xffffffff, R3, R3
  105. // 32 → 17.
  106. LSR $16, R3, R8
  107. AND $0xffff, R3, R3
  108. ADD R8, R3, R3
  109. // 17 → 16 (truncation absorbs bit 16 below).
  110. LSR $16, R3, R8
  111. ADD R8, R3, R3
  112. // AX low 16 bits hold the 16-bit sum in machine (LE) byte order; flip
  113. // to big-endian to match the gvisor API contract. REV16W swaps bytes
  114. // within each 16-bit halfword of the low 32 bits, so it acts as a
  115. // 16-bit byte-swap on the live low 16.
  116. REV16W R3, R3
  117. AND $0xffff, R3, R3
  118. MOVH R3, ret+32(FP)
  119. RET