Last active
January 10, 2020 03:24
-
-
Save ryancdotorg/52e9c5d0301a409da868ac9b40aa3157 to your computer and use it in GitHub Desktop.
SipHash-2-4 in x86_64 assembly, hand optimized for size
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SipHash-2-4 in x86_64 assembly, hand optimized for size (183 bytes) | |
// Written by Ryan Castellucci | |
// Disclaimer: Don't use this. | |
.global siphash | |
.global end_siphash | |
.text | |
// uint64_t siphash(const void *src, uint32_t src_sz, const uint8_t key[16]) | |
// %rdi = src, %rsi = src_sz, %rdx = key | |
siphash: | |
// initialize the internal state | |
movabs $0x736f6d6570736575,%r8 | |
movabs $0x646f72616e646f6d,%r9 | |
movabs $0x6c7967656e657261,%rcx | |
movabs $0x7465646279746573,%rax | |
// v0 ^= k0; v2 ^= k2 | |
xor (%rdx), %r8 | |
xor (%rdx), %rcx | |
// v1 ^= k1; v3 ^= k1 | |
xor 8(%rdx), %r9 | |
xor 8(%rdx), %rax | |
// we no longer need the key address | |
// push b (sz << 56) on the stack for later | |
mov %esi, %edx | |
shl $56, %rdx | |
push %rdx | |
siphash_blocks: | |
// set count for siphash_rounds (we will be back here before loop exit) | |
mov $2, %dl | |
// exit loop once sz < 8 | |
cmp $7, %esi | |
jbe siphash_bytes_entry | |
// v3 ^= *in | |
xor (%rdi), %rax | |
// siphash_rounds(2), dl set above | |
callq siphash_rounds | |
// v0 ^= *in | |
xor (%rdi), %r8 | |
// sz -= 8; *in +=8 | |
sub $8, %esi | |
add $8, %rdi | |
jmp siphash_blocks | |
siphash_bytes: | |
// copy a byte of message data to the stack | |
mov (%rdi,%rsi,1),%dh | |
mov %dh,(%rsp,%rsi,1) | |
siphash_bytes_entry: | |
// t is (%rsp) | |
dec %esi | |
// sign bit will be set when we underflow | |
jns siphash_bytes | |
// we no longer need rdi or rsi | |
siphash_finalize: | |
// pop b off the stack | |
pop %rdi | |
// v3 ^= b | |
xor %rdi, %rax | |
// siphash_rounds(2) dl set at top of siphash_blocks | |
callq siphash_rounds | |
// safe to use rdx again | |
// v0 ^= b | |
xor %rdi, %r8 | |
// v2 ^= 0xff | |
xor $0xff, %cl | |
// siphash_rounds(4) | |
mov $4, %dl | |
callq siphash_rounds | |
// produce output | |
xor %r8, %rax | |
xor %r9, %rax | |
xor %rcx, %rax | |
// return | |
retq | |
// do %dl full rounds of siphash | |
siphash_rounds: | |
// half round, a=r8, b=r9, c=rcx, d=rax, s=13, t=16 | |
add %r9, %r8 | |
add %rax, %rcx | |
rol $13, %r9 | |
xor %r8, %r9 | |
rol $16, %rax | |
xor %rcx, %rax | |
rol $32, %r8 | |
// half round a=rcx, b=r9, c=r8, d=rax, s=17, t=21 | |
add %r9, %rcx | |
add %rax, %r8 | |
rol $17, %r9 | |
xor %rcx, %r9 | |
rol $21, %rax | |
xor %r8, %rax | |
rol $32, %rcx | |
dec %dl | |
jnz siphash_rounds | |
retq |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment