xxhash_amd64.s raw

   1  //go:build !appengine && gc && !purego
   2  // +build !appengine
   3  // +build gc
   4  // +build !purego
   5  
   6  #include "textflag.h"
   7  
   8  // Registers:
   9  #define h      AX
  10  #define d      AX
  11  #define p      SI // pointer to advance through b
  12  #define n      DX
  13  #define end    BX // loop end
  14  #define v1     R8
  15  #define v2     R9
  16  #define v3     R10
  17  #define v4     R11
  18  #define x      R12
  19  #define prime1 R13
  20  #define prime2 R14
  21  #define prime4 DI
  22  
  23  #define round(acc, x) \
  24  	IMULQ prime2, x   \
  25  	ADDQ  x, acc      \
  26  	ROLQ  $31, acc    \
  27  	IMULQ prime1, acc
  28  
  29  // round0 performs the operation x = round(0, x).
  30  #define round0(x) \
  31  	IMULQ prime2, x \
  32  	ROLQ  $31, x    \
  33  	IMULQ prime1, x
  34  
  35  // mergeRound applies a merge round on the two registers acc and x.
  36  // It assumes that prime1, prime2, and prime4 have been loaded.
  37  #define mergeRound(acc, x) \
  38  	round0(x)         \
  39  	XORQ  x, acc      \
  40  	IMULQ prime1, acc \
  41  	ADDQ  prime4, acc
  42  
  43  // blockLoop processes as many 32-byte blocks as possible,
  44  // updating v1, v2, v3, and v4. It assumes that there is at least one block
  45  // to process.
  46  #define blockLoop() \
  47  loop:  \
  48  	MOVQ +0(p), x  \
  49  	round(v1, x)   \
  50  	MOVQ +8(p), x  \
  51  	round(v2, x)   \
  52  	MOVQ +16(p), x \
  53  	round(v3, x)   \
  54  	MOVQ +24(p), x \
  55  	round(v4, x)   \
  56  	ADDQ $32, p    \
  57  	CMPQ p, end    \
  58  	JLE  loop
  59  
  60  // func Sum64(b []byte) uint64
  61  TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32
  62  	// Load fixed primes.
  63  	MOVQ ·primes+0(SB), prime1
  64  	MOVQ ·primes+8(SB), prime2
  65  	MOVQ ·primes+24(SB), prime4
  66  
  67  	// Load slice.
  68  	MOVQ b_base+0(FP), p
  69  	MOVQ b_len+8(FP), n
  70  	LEAQ (p)(n*1), end
  71  
  72  	// The first loop limit will be len(b)-32.
  73  	SUBQ $32, end
  74  
  75  	// Check whether we have at least one block.
  76  	CMPQ n, $32
  77  	JLT  noBlocks
  78  
  79  	// Set up initial state (v1, v2, v3, v4).
  80  	MOVQ prime1, v1
  81  	ADDQ prime2, v1
  82  	MOVQ prime2, v2
  83  	XORQ v3, v3
  84  	XORQ v4, v4
  85  	SUBQ prime1, v4
  86  
  87  	blockLoop()
  88  
  89  	MOVQ v1, h
  90  	ROLQ $1, h
  91  	MOVQ v2, x
  92  	ROLQ $7, x
  93  	ADDQ x, h
  94  	MOVQ v3, x
  95  	ROLQ $12, x
  96  	ADDQ x, h
  97  	MOVQ v4, x
  98  	ROLQ $18, x
  99  	ADDQ x, h
 100  
 101  	mergeRound(h, v1)
 102  	mergeRound(h, v2)
 103  	mergeRound(h, v3)
 104  	mergeRound(h, v4)
 105  
 106  	JMP afterBlocks
 107  
 108  noBlocks:
 109  	MOVQ ·primes+32(SB), h
 110  
 111  afterBlocks:
 112  	ADDQ n, h
 113  
 114  	ADDQ $24, end
 115  	CMPQ p, end
 116  	JG   try4
 117  
 118  loop8:
 119  	MOVQ  (p), x
 120  	ADDQ  $8, p
 121  	round0(x)
 122  	XORQ  x, h
 123  	ROLQ  $27, h
 124  	IMULQ prime1, h
 125  	ADDQ  prime4, h
 126  
 127  	CMPQ p, end
 128  	JLE  loop8
 129  
 130  try4:
 131  	ADDQ $4, end
 132  	CMPQ p, end
 133  	JG   try1
 134  
 135  	MOVL  (p), x
 136  	ADDQ  $4, p
 137  	IMULQ prime1, x
 138  	XORQ  x, h
 139  
 140  	ROLQ  $23, h
 141  	IMULQ prime2, h
 142  	ADDQ  ·primes+16(SB), h
 143  
 144  try1:
 145  	ADDQ $4, end
 146  	CMPQ p, end
 147  	JGE  finalize
 148  
 149  loop1:
 150  	MOVBQZX (p), x
 151  	ADDQ    $1, p
 152  	IMULQ   ·primes+32(SB), x
 153  	XORQ    x, h
 154  	ROLQ    $11, h
 155  	IMULQ   prime1, h
 156  
 157  	CMPQ p, end
 158  	JL   loop1
 159  
 160  finalize:
 161  	MOVQ  h, x
 162  	SHRQ  $33, x
 163  	XORQ  x, h
 164  	IMULQ prime2, h
 165  	MOVQ  h, x
 166  	SHRQ  $29, x
 167  	XORQ  x, h
 168  	IMULQ ·primes+16(SB), h
 169  	MOVQ  h, x
 170  	SHRQ  $32, x
 171  	XORQ  x, h
 172  
 173  	MOVQ h, ret+24(FP)
 174  	RET
 175  
 176  // func writeBlocks(d *Digest, b []byte) int
 177  TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40
 178  	// Load fixed primes needed for round.
 179  	MOVQ ·primes+0(SB), prime1
 180  	MOVQ ·primes+8(SB), prime2
 181  
 182  	// Load slice.
 183  	MOVQ b_base+8(FP), p
 184  	MOVQ b_len+16(FP), n
 185  	LEAQ (p)(n*1), end
 186  	SUBQ $32, end
 187  
 188  	// Load vN from d.
 189  	MOVQ s+0(FP), d
 190  	MOVQ 0(d), v1
 191  	MOVQ 8(d), v2
 192  	MOVQ 16(d), v3
 193  	MOVQ 24(d), v4
 194  
 195  	// We don't need to check the loop condition here; this function is
 196  	// always called with at least one block of data to process.
 197  	blockLoop()
 198  
 199  	// Copy vN back to d.
 200  	MOVQ v1, 0(d)
 201  	MOVQ v2, 8(d)
 202  	MOVQ v3, 16(d)
 203  	MOVQ v4, 24(d)
 204  
 205  	// The number of bytes written is p minus the old base pointer.
 206  	SUBQ b_base+8(FP), p
 207  	MOVQ p, ret+32(FP)
 208  
 209  	RET
 210