first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
* Copyright (C) 2007-2012 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Computer, Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
#include <sys.h>
|
||||
#include <arch.h>
|
||||
#include <sys/types.h>
|
||||
#include <lib/cksum.h>
|
||||
|
||||
#if (ARCH_ARMv7 && WITH_VFP) || defined(__arm64__)
|
||||
extern uint32_t adler32_vec(uint32_t, uint32_t, const uint8_t *, long);
|
||||
#endif
|
||||
|
||||
|
||||
#define BASE 65521L /* largest prime smaller than 65536 */
|
||||
#define NMAX 5000
|
||||
// NMAX (was 5521) the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
|
||||
|
||||
#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
|
||||
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
|
||||
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
|
||||
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
|
||||
#define DO16(buf) DO8(buf,0); DO8(buf,8);
|
||||
|
||||
uint32_t adler32(const uint8_t *buf, long len)
|
||||
{
|
||||
uint32_t s1 = 1; // adler & 0xffff;
|
||||
uint32_t s2 = 0; // (adler >> 16) & 0xffff;
|
||||
int k;
|
||||
|
||||
#if (ARCH_ARMv7 && WITH_VFP) || defined(__arm64__)
|
||||
|
||||
/* align buf to 16-byte boundary */
|
||||
while ((int)buf & 15) { /* not on a 16-byte boundary */
|
||||
len--;
|
||||
s1 += *buf++;
|
||||
s2 += s1;
|
||||
s1 %= BASE;
|
||||
s2 %= BASE;
|
||||
}
|
||||
if (len > 16) {
|
||||
#if WITH_VFP_ALWAYS_ON
|
||||
return adler32_vec(s1, s2, buf, len);
|
||||
#else
|
||||
bool fp_enabled;
|
||||
uint32_t result;
|
||||
|
||||
fp_enabled = arch_task_fp_enable(true);
|
||||
result = adler32_vec(s1, s2, buf, len);
|
||||
arch_task_fp_enable(fp_enabled);
|
||||
|
||||
return result;
|
||||
#endif // WITH_VFP_ALWAYS_ON
|
||||
}
|
||||
#endif
|
||||
|
||||
while (len > 0) {
|
||||
k = len < NMAX ? len : NMAX;
|
||||
len -= k;
|
||||
while (k >= 16) {
|
||||
DO16(buf);
|
||||
buf += 16;
|
||||
k -= 16;
|
||||
}
|
||||
if (k != 0) do {
|
||||
s1 += *buf++;
|
||||
s2 += s1;
|
||||
} while (--k);
|
||||
s1 %= BASE;
|
||||
s2 %= BASE;
|
||||
}
|
||||
return (s2 << 16) | s1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Computer, Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#if defined(__arm__)
|
||||
|
||||
#define BASE 65521 /* largest prime smaller than 65536 */
|
||||
#define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||
|
||||
// Note: buf should have been 16-byte aligned in the caller function,
|
||||
|
||||
// uLong adler32_vec(unsigned int adler, unsigned int sum2, const Bytef* buf, int len) {
|
||||
// unsigned n;
|
||||
// while (len >= NMAX) {
|
||||
// len -= NMAX;
|
||||
// n = NMAX / 16; /* NMAX is divisible by 16 */
|
||||
// do {
|
||||
// DO16(buf); /* 16 sums unrolled */
|
||||
// buf += 16;
|
||||
// } while (--n);
|
||||
// MOD(adler);
|
||||
// MOD(sum2);
|
||||
// }
|
||||
// if (len) { /* avoid modulos if none remaining */
|
||||
// while (len >= 16) {
|
||||
// len -= 16;
|
||||
// DO16(buf);
|
||||
// buf += 16;
|
||||
// }
|
||||
// while (len--) {
|
||||
// adler += *buf++;
|
||||
// sum2 += adler;
|
||||
// }
|
||||
// MOD(adler);
|
||||
// MOD(sum2);
|
||||
// }
|
||||
// return adler | (sum2 << 16); /* return recombined sums */
|
||||
// }
|
||||
|
||||
|
||||
/*
|
||||
DO16 vectorization:
|
||||
given initial unsigned int sum2 and adler, and a new set of 16 input bytes (x[0:15]), it can be shown that
|
||||
sum2 += (16*adler + 16*x[0] + 15*x[1] + ... + 1*x[15]);
|
||||
adler += (x[0] + x[1] + ... + x[15]);
|
||||
|
||||
therefore, this is what can be done to vectorize the above computation
|
||||
1. 16-byte aligned vector load into q2 (x[0:x15])
|
||||
2. sum2 += (adler<<4);
|
||||
3. vmull.u8 (q9,q8),q2,d2 where d2 = (1,1,1,1...,1), (q9,q8) + 16 16-bit elements x[0:15]
|
||||
4. vmull.u8 (q11,q10),q2,q0 where q0 = (1,2,3,4...,16), (q11,q10) + 16 16-bit elements (16:1)*x[0:15]
|
||||
5. parallel add (with once expansion to 32-bit) (q9,q8) and (q11,q10) all the way to accumulate to adler and sum2
|
||||
|
||||
In this revision, whenever possible, 2 DO16 loops are combined into a DO32 loop.
|
||||
1. 32-byte aligned vector load into q2,q14 (x[0:x31])
|
||||
2. sum2 += (adler<<5);
|
||||
3. vmull.u8 (4 q registers),(q2,q14),d2 where d2 = (1,1,1,1...,1), (4 q registers) : 32 16-bit elements x[0:31]
|
||||
4. vmull.u8 (4 q registers),(q2,q14),(q0,q15) where q0 = (1,...,32), (4 q regs) : 32 16-bit elements (32:1)*x[0:31]
|
||||
5. parallel add (with once expansion to 32-bit) the pair of (4 q regs) all the way to accumulate to adler and sum2
|
||||
|
||||
This change improves the performance by ~ 0.55 cycle/uncompress byte on ARM Cortex-A8.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
MOD implementation:
|
||||
adler%BASE = adler - floor(adler*(1/BASE))*BASE; where (1/BASE) = 0x80078071 in Q47
|
||||
1. vmull.u32 q2,(adler,sum2),(1/BASE) // *(1/BASE) in Q47
|
||||
2. vshr.u64 q2,q2,#47 // floor function
|
||||
3. vpadd.u32 d4,d4,d5 // merge into a double word in d4
|
||||
4. vmls.u32 (adler,sum2),d4,d3[0] // (adler,sum2) -= floor[(adler,sum2)/BASE]*BASE
|
||||
|
||||
*/
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.globl _adler32_vec
|
||||
_adler32_vec:
|
||||
|
||||
#define adler r0
|
||||
#define sum2 r1
|
||||
#define buf r2
|
||||
#define len r3
|
||||
#define nmax r4
|
||||
#define vecs lr // vecs = NMAX/16
|
||||
#define n r5
|
||||
|
||||
#define t r12
|
||||
|
||||
#define sum2_coeff q0
|
||||
#define sum2_coeff0 d0
|
||||
#define sum2_coeff1 d1
|
||||
#define alder_coeff q1
|
||||
#define ones d2
|
||||
#define x0_x15 q2
|
||||
#define x0_x7 d4
|
||||
#define x8_x15 d5
|
||||
#define adlersum2 d6
|
||||
#define adler16 d25
|
||||
|
||||
adr t, vec_table // address to vec_table[]
|
||||
stmfd sp!, {r4, r5, lr}
|
||||
|
||||
vld1.32 {q0-q1},[t,:128]! // loading up coefficients for adler/sum2 computation
|
||||
vld1.32 {q15},[t,:128]! // for sum2 computation
|
||||
ldr nmax, [t] // NMAX
|
||||
|
||||
vmov adlersum2, sum2, adler // pack up adler/sum2 into a double register
|
||||
|
||||
cmp len, nmax // len vs NMAX
|
||||
lsr vecs, nmax, #4 // vecs = NMAX/16;
|
||||
blt L_len_lessthan_NMAX // if (len < NMAX) skip the while loop
|
||||
|
||||
sub len, nmax // pre-decrement len by NMAX
|
||||
|
||||
L_while_len_ge_NMAX_loop: // while (len>=NMAX) {
|
||||
|
||||
mov n, vecs, lsr #1 // n = NMAX/16;
|
||||
|
||||
L_do_loop: // do {
|
||||
|
||||
vshll.u32 q12, adlersum2, #5 // d25 = (0,32*adler) to be added into (adler,sum2)
|
||||
vld1.32 {x0_x15},[buf,:128]! // 16-byte input x0:x15
|
||||
vmull.u8 q8, x0_x7, ones // 16-bit x0-x7
|
||||
vld1.32 {q14}, [buf,:128]! // x16:x31
|
||||
vmull.u8 q9, x8_x15, ones // 16-bit x8-x15
|
||||
vadd.u32 adlersum2,adler16 // sum2 += old adler*32;
|
||||
vmull.u8 q12, d28, ones // 16-bit x16-x23
|
||||
vmull.u8 q13, d29, ones // 16-bit x24-x31
|
||||
vmull.u8 q10, d28, sum2_coeff0 // 16-bit x16*16, x17*15, ..., x23*9
|
||||
vmull.u8 q11, d29, sum2_coeff1 // 16-bit x24*8, x25*7, ..., x31*1
|
||||
vadd.u16 q8, q8, q9 // q8 = (x0+x8):(x7+x15) 8 16-bit elements for adler
|
||||
vmull.u8 q9, x0_x7, d30 // 16-bit x0*32,...,x7*25
|
||||
vmull.u8 q14, x8_x15, d31 // 16-bit x8*24,...,x15*17
|
||||
vadd.u16 q12, q12, q13 // q12 = (x16+x24):(x23+x31) 8 16-bit elements for adler
|
||||
vadd.u16 q10, q11 // 8 16-bit elements for sum2
|
||||
vadd.u16 q8, q12 // 8 16-bit elements for adler
|
||||
vadd.u16 q9, q14 // 8 16-bit elements for sum2
|
||||
vadd.u16 q10, q9 // 8 16-bit elements for sum2
|
||||
#if 0
|
||||
vpaddl.u16 q8, q8 // 4 32-bit elements for adler
|
||||
vpaddl.u16 q10, q10 // 4 32-bit elements for sum2
|
||||
vpadd.u32 d16,d16,d17 // 2 32-bit elements for adler
|
||||
vpadd.u32 d17,d20,d21 // 2 32-bit elements for sum2
|
||||
#else
|
||||
vadd.u16 d16, d17
|
||||
vadd.u16 d20, d21
|
||||
vpaddl.u16 d16, d16
|
||||
vpaddl.u16 d17, d20
|
||||
#endif
|
||||
vpadd.u32 d4,d17,d16 // s8 : 32-bit elements for sum2, s9 : 32-bit element for adler
|
||||
vadd.u32 adlersum2,d4 // update adler/sum2 with the new 16 bytes input
|
||||
|
||||
subs n, #1 // --n
|
||||
bgt L_do_loop // } while (--n);
|
||||
|
||||
vshll.u32 q12, adlersum2, #4 // d25 = (0,16*adler) to be added into (adler,sum2)
|
||||
|
||||
vld1.32 {x0_x15},[buf,:128]! // 16-byte input
|
||||
|
||||
vmull.u8 q8, x0_x7, ones // 16-bit x0-x7
|
||||
vmull.u8 q9, x8_x15, ones // 16-bit x8-x15
|
||||
vmull.u8 q10, x0_x7, sum2_coeff0 // 16-bit x0*16, x1*15, ..., x7*9
|
||||
vmull.u8 q11, x8_x15, sum2_coeff1 // 16-bit x8*8, x9*7, ..., x15*1
|
||||
|
||||
vadd.u16 q8, q8, q9 // 8 16-bit elements for adler
|
||||
vadd.u16 q10, q10, q11 // 8 16-bit elements for sum2
|
||||
#if 0
|
||||
vpaddl.u16 q8, q8 // 4 32-bit elements for adler
|
||||
vpaddl.u16 q10, q10 // 4 32-bit elements for sum2
|
||||
vpadd.u32 d16,d16,d17 // 2 32-bit elements for adler
|
||||
vpadd.u32 d17,d20,d21 // 2 32-bit elements for sum2
|
||||
#else
|
||||
vadd.u16 d16, d17
|
||||
vadd.u16 d20, d21
|
||||
vpaddl.u16 d16, d16
|
||||
vpaddl.u16 d17, d20
|
||||
|
||||
#endif
|
||||
vadd.u32 adlersum2,adler16 // sum2 += old adler;
|
||||
vpadd.u32 d4,d17,d16 // s8 : 32-bit elements for sum2, s9 : 32-bit element for adler
|
||||
vadd.u32 adlersum2,d4 // update adler/sum2 with the new 16 bytes input
|
||||
|
||||
// mod(alder,BASE); mod(sum2,BASE);
|
||||
vmull.u32 q2,adlersum2,d3[1] // alder/BASE, sum2/BASE in Q47
|
||||
vshr.u64 q2,q2,#47 // take the integer part
|
||||
vpadd.u32 d4,d4,d5 // merge into a double word in d4
|
||||
vmls.u32 adlersum2,d4,d3[0] // (adler,sum2) -= floor[(adler,sum2)/BASE]*BASE
|
||||
|
||||
subs len, nmax // len -= NMAX;
|
||||
bge L_while_len_ge_NMAX_loop // repeat while len >= NMAX
|
||||
|
||||
add len, nmax // post-increment len by NMAX
|
||||
|
||||
L_len_lessthan_NMAX:
|
||||
|
||||
cmp len, #0
|
||||
beq L_len_is_zero // if len==0, branch to skip the following
|
||||
|
||||
|
||||
subs len, #32 // pre-decrement len by 32
|
||||
blt L_len_lessthan_32 // if len < 32, branch to L_len16_loop
|
||||
|
||||
L_len32_loop:
|
||||
|
||||
vshll.u32 q12, adlersum2, #5 // d25 = (0,32*adler) to be added into (adler,sum2)
|
||||
vld1.32 {x0_x15},[buf,:128]! // 16-byte input x0:x15
|
||||
vmull.u8 q8, x0_x7, ones // 16-bit x0-x7
|
||||
vld1.32 {q14}, [buf,:128]! // x16:x31
|
||||
vmull.u8 q9, x8_x15, ones // 16-bit x8-x15
|
||||
vadd.u32 adlersum2,adler16 // sum2 += old adler*32;
|
||||
vmull.u8 q12, d28, ones // 16-bit x16-x23
|
||||
vmull.u8 q13, d29, ones // 16-bit x24-x31
|
||||
vmull.u8 q10, d28, sum2_coeff0 // 16-bit x16*16, x17*15, ..., x23*9
|
||||
vmull.u8 q11, d29, sum2_coeff1 // 16-bit x24*8, x25*7, ..., x31*1
|
||||
vadd.u16 q8, q8, q9 // q8 = (x0+x8):(x7+x15) 8 16-bit elements for adler
|
||||
vmull.u8 q9, x0_x7, d30 // 16-bit x0*32,...,x7*25
|
||||
vmull.u8 q14, x8_x15, d31 // 16-bit x8*24,...,x15*17
|
||||
vadd.u16 q12, q12, q13 // q12 = (x16+x24):(x23+x31) 8 16-bit elements for adler
|
||||
vadd.u16 q10, q11 // 8 16-bit elements for sum2
|
||||
vadd.u16 q8, q12 // 8 16-bit elements for adler
|
||||
vadd.u16 q9, q14 // 8 16-bit elements for sum2
|
||||
vadd.u16 q10, q9 // 8 16-bit elements for sum2
|
||||
#if 0
|
||||
vpaddl.u16 q8, q8 // 4 32-bit elements for adler
|
||||
vpaddl.u16 q10, q10 // 4 32-bit elements for sum2
|
||||
vpadd.u32 d16,d16,d17 // 2 32-bit elements for adler
|
||||
vpadd.u32 d17,d20,d21 // 2 32-bit elements for sum2
|
||||
#else
|
||||
vadd.u16 d16, d17
|
||||
vadd.u16 d20, d21
|
||||
vpaddl.u16 d16, d16
|
||||
vpaddl.u16 d17, d20
|
||||
#endif
|
||||
vpadd.u32 d4,d17,d16 // s8 : 32-bit elements for sum2, s9 : 32-bit element for adler
|
||||
vadd.u32 adlersum2,d4 // update adler/sum2 with the new 16 bytes input
|
||||
|
||||
subs len, #32 // len -= 32;
|
||||
bge L_len32_loop
|
||||
|
||||
L_len_lessthan_32:
|
||||
|
||||
adds len, #(32-16) // post-increment len by 32, then pre-decrement by 16
|
||||
blt L_len_lessthan_16 // if len < 16, branch to L_len_lessthan_16
|
||||
|
||||
vshll.u32 q12, adlersum2, #4 // d25 = (0,16*adler) to be added into (adler,sum2)
|
||||
|
||||
vld1.32 {x0_x15},[buf,:128]! // 16-byte input
|
||||
|
||||
|
||||
vmull.u8 q8, x0_x7, ones // 16-bit x0-x7
|
||||
vmull.u8 q9, x8_x15, ones // 16-bit x8-x15
|
||||
vmull.u8 q10, x0_x7, sum2_coeff0 // 16-bit x0*16, x1*15, ..., x7*9
|
||||
vmull.u8 q11, x8_x15, sum2_coeff1 // 16-bit x8*8, x9*7, ..., x15*1
|
||||
|
||||
vadd.u16 q8, q8, q9 // 8 16-bit elements for adler
|
||||
vadd.u16 q10, q10, q11 // 8 16-bit elements for sum2
|
||||
#if 0
|
||||
vpaddl.u16 q8, q8 // 4 32-bit elements for adler
|
||||
vpaddl.u16 q10, q10 // 4 32-bit elements for sum2
|
||||
vpadd.u32 d16,d16,d17 // 2 32-bit elements for adler
|
||||
vpadd.u32 d17,d20,d21 // 2 32-bit elements for sum2
|
||||
#else
|
||||
vadd.u16 d16, d17
|
||||
vadd.u16 d20, d21
|
||||
vpaddl.u16 d16, d16
|
||||
vpaddl.u16 d17, d20
|
||||
#endif
|
||||
subs len, #16 // decrement len by 16
|
||||
vadd.u32 adlersum2,adler16 // sum2 += old adler;
|
||||
vpadd.u32 d4,d17,d16 // s8 : 32-bit elements for sum2, s9 : 32-bit element for adler
|
||||
vadd.u32 adlersum2,d4 // update adler/sum2 with the new 16 bytes input
|
||||
|
||||
L_len_lessthan_16:
|
||||
adds len, #16 // post-increment len by 16
|
||||
beq L_len_is_zero_internal // if len==0, branch to len_is_zero_internal
|
||||
|
||||
// restore adler/sum2 into general registers for remaining (<16) bytes
|
||||
|
||||
vmov sum2, adler, adlersum2
|
||||
L_remaining_len_loop:
|
||||
ldrb t, [buf], #1 // *buf++;
|
||||
subs len, #1 // len--;
|
||||
add adler,t // adler += *buf
|
||||
add sum2,adler // sum2 += adler
|
||||
bgt L_remaining_len_loop // break if len<=0
|
||||
|
||||
vmov adlersum2, sum2, adler // move to double register for modulo operation
|
||||
|
||||
L_len_is_zero_internal:
|
||||
|
||||
// mod(alder,BASE); mod(sum2,BASE);
|
||||
|
||||
vmull.u32 q2,adlersum2,d3[1] // alder/BASE, sum2/BASE in Q47
|
||||
vshr.u64 q2,q2,#47 // take the integer part
|
||||
vpadd.u32 d4,d4,d5 // merge into a double word in d4
|
||||
vmls.u32 adlersum2,d4,d3[0] // (adler,sum2) -= floor[(adler,sum2)/BASE]*BASE
|
||||
|
||||
L_len_is_zero:
|
||||
|
||||
vmov sum2, adler, adlersum2 // restore adler/sum2 from (s12=sum2, s13=adler)
|
||||
add r0, adler, sum2, lsl #16 // to return adler | (sum2 << 16);
|
||||
ldmfd sp!, {r4, r5, pc} // restore registers and return
|
||||
|
||||
|
||||
// constants to be loaded into q registers
|
||||
.align 4 // 16 byte aligned
|
||||
|
||||
vec_table:
|
||||
|
||||
// coefficients for computing sum2
|
||||
.long 0x0d0e0f10 // s0
|
||||
.long 0x090a0b0c // s1
|
||||
.long 0x05060708 // s2
|
||||
.long 0x01020304 // s3
|
||||
|
||||
// coefficients for computing adler
|
||||
.long 0x01010101 // s4/d2
|
||||
.long 0x01010101 // s5
|
||||
|
||||
.long BASE // s6 : BASE
|
||||
.long 0x80078071 // s7 : 1/BASE in Q47
|
||||
|
||||
// q15 : d30.d31
|
||||
.long 0x1d1e1f20 // s0
|
||||
.long 0x191a1b1c // s1
|
||||
.long 0x15161718 // s2
|
||||
.long 0x11121314 // s3
|
||||
|
||||
NMAX_loc:
|
||||
.long NMAX // NMAX
|
||||
|
||||
#endif // defined(__arm__)
|
||||
|
||||
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Computer, Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#if defined(__arm64__)
|
||||
|
||||
#define BASE 65521 /* largest prime smaller than 65536 */
|
||||
#define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||
|
||||
// Note: buf should have been 16-byte aligned in the caller function,
|
||||
|
||||
// uLong adler32_vec(unsigned int adler, unsigned int sum2, const Bytef* buf, int len) {
|
||||
// unsigned n;
|
||||
// while (len >= NMAX) {
|
||||
// len -= NMAX;
|
||||
// n = NMAX / 16; /* NMAX is divisible by 16 */
|
||||
// do {
|
||||
// DO16(buf); /* 16 sums unrolled */
|
||||
// buf += 16;
|
||||
// } while (--n);
|
||||
// MOD(adler);
|
||||
// MOD(sum2);
|
||||
// }
|
||||
// if (len) { /* avoid modulos if none remaining */
|
||||
// while (len >= 16) {
|
||||
// len -= 16;
|
||||
// DO16(buf);
|
||||
// buf += 16;
|
||||
// }
|
||||
// while (len--) {
|
||||
// adler += *buf++;
|
||||
// sum2 += adler;
|
||||
// }
|
||||
// MOD(adler);
|
||||
// MOD(sum2);
|
||||
// }
|
||||
// return adler | (sum2 << 16); /* return recombined sums */
|
||||
// }
|
||||
|
||||
|
||||
/*
|
||||
DO16 vectorization:
|
||||
given initial unsigned int sum2 and adler, and a new set of 16 input bytes (x[0:15]), it can be shown that
|
||||
sum2 += (16*adler + 16*x[0] + 15*x[1] + ... + 1*x[15]);
|
||||
adler += (x[0] + x[1] + ... + x[15]);
|
||||
|
||||
similarly, 2 DO16 = DO32 vectorization:
|
||||
given initial unsigned int sum2 and adler, and a new set of 32 input bytes (x[0:31]), it can be shown that
|
||||
sum2 += (32*adler + 32*x[0] + 31*x[1] + ... + 1*x[31]);
|
||||
adler += (x[0] + x[1] + ... + x[31]);
|
||||
|
||||
NMAX = 5552
|
||||
NMAX/16 = 347 = 173*2 + 1
|
||||
|
||||
therefore, for a block of 5552 bytes
|
||||
|
||||
n = 173;
|
||||
do {
|
||||
DO32(buf); buf+=32;
|
||||
} while (n--);
|
||||
|
||||
DO16(buf); buf+=16;
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
|
||||
for a residual remaining len bytes,
|
||||
while (len >= 32) {
|
||||
DO32(buf); buf += 32; len -= 32;
|
||||
}
|
||||
if (len>=16) {
|
||||
DO16(buf); buf += 16; len -= 16;
|
||||
}
|
||||
while (len--) {
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
|
||||
|
||||
|
||||
|
||||
DO32:
|
||||
pack sum2:adler in a 64-bit register
|
||||
|
||||
0. sum2 += adler*32;
|
||||
|
||||
sum2:adler += (sum2:adler) << (32+5);
|
||||
|
||||
1. (32, 31, ..., 1) * ( x0, x1, ..., x31) (v2, v3) * (v0, v1)
|
||||
umull.8h v4, v2, v0
|
||||
umull2.8h v5, v2, v0
|
||||
umull.8h v6, v3, v1
|
||||
umull2.8h v7, v3, v1
|
||||
add.8h v4, v4, v5
|
||||
add.8h v6, v6, v7
|
||||
add.8h v4, v4, v6
|
||||
uaddlv s4, v4.8h
|
||||
|
||||
add sum2, sum2, s4
|
||||
|
||||
2. adler += (x0 + x1 + x2 + ... + x31)
|
||||
|
||||
uaddlp v0.8h, v0.16b
|
||||
uaddlp v1.8h, v1.16b
|
||||
uaddlv s0, v0.8h
|
||||
uaddlv s1, v1.8h
|
||||
add s0, s0, s1
|
||||
|
||||
add adler, adler, s0
|
||||
|
||||
|
||||
therefore, this is what can be done to vectorize the above computation
|
||||
1. 16-byte aligned vector load into q2 (x[0:x15])
|
||||
2. sum2 += (adler<<32); // pack adler/sum2 into a 64-bit word
|
||||
3. vmull.u8 (q9,q8),q2,d2 where d2 = (1,1,1,1...,1), (q9,q8) + 16 16-bit elements x[0:15]
|
||||
4. vmull.u8 (q11,q10),q2,q0 where q0 = (1,2,3,4...,16), (q11,q10) + 16 16-bit elements (16:1)*x[0:15]
|
||||
5. parallel add (with once expansion to 32-bit) (q9,q8) and (q11,q10) all the way to accumulate to adler and sum2
|
||||
|
||||
In this revision, whenever possible, 2 DO16 loops are combined into a DO32 loop.
|
||||
1. 32-byte aligned vector load into q2,q14 (x[0:x31])
|
||||
2. sum2 += (adler<<32);
|
||||
3. vmull.u8 (4 q registers),(q2,q14),d2 where d2 = (1,1,1,1...,1), (4 q registers) : 32 16-bit elements x[0:31]
|
||||
4. vmull.u8 (4 q registers),(q2,q14),(q0,q15) where q0 = (1,...,32), (4 q regs) : 32 16-bit elements (32:1)*x[0:31]
|
||||
5. parallel add (with once expansion to 32-bit) the pair of (4 q regs) all the way to accumulate to adler and sum2
|
||||
|
||||
This change improves the performance by ~ 0.55 cycle/uncompress byte on ARM Cortex-A8.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
MOD implementation:
|
||||
adler%BASE = adler - floor(adler*(1/BASE))*BASE; where (1/BASE) = 0x80078071 in Q47
|
||||
1. vmull.u32 q2,(adler,sum2),(1/BASE) // *(1/BASE) in Q47
|
||||
2. vshr.u64 q2,q2,#47 // floor function
|
||||
3. vpadd.u32 d4,d4,d5 // merge into a double word in d4
|
||||
4. vmls.u32 (adler,sum2),d4,d3[0] // (adler,sum2) -= floor[(adler,sum2)/BASE]*BASE
|
||||
|
||||
*/
|
||||
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.globl _adler32_vec
|
||||
_adler32_vec:
|
||||
|
||||
|
||||
|
||||
#define adler w0
|
||||
#define sum2 w1
|
||||
#define buf x2
|
||||
#define len w3
|
||||
#define nmax w4
|
||||
#define nvec w6 // vecs = NMAX/16
|
||||
|
||||
#define t x7
|
||||
|
||||
#define vadlersum2 v5 // only lower part
|
||||
#define adlersum2 d5 // only lower part
|
||||
|
||||
add x0, x0, x1, lsl #32
|
||||
adrp t, vec_table@PAGE
|
||||
mov nmax, #NMAX // NMAX
|
||||
add t, t, vec_table@PAGEOFF
|
||||
ins vadlersum2.d[0], x0
|
||||
|
||||
|
||||
#if KERNEL
|
||||
sub x6, sp, #8*16
|
||||
sub sp, sp, #8*16
|
||||
st1.4s {v0,v1,v2,v3},[x6],#4*16
|
||||
st1.4s {v4,v5,v6,v7},[x6],#4*16
|
||||
#endif
|
||||
|
||||
cmp len, nmax // len vs NMAX
|
||||
ld1.4s {v0, v1}, [t], #2*16 // loading up coefficients for adler/sum2 computation
|
||||
ldr d7, [t] // for MOD operation
|
||||
b.lt L_len_lessthan_NMAX // if (len < NMAX) skip the while loop
|
||||
|
||||
sub len, len, nmax // pre-decrement len by NMAX
|
||||
|
||||
L_while_len_ge_NMAX_loop: // while (len>=NMAX) {
|
||||
|
||||
|
||||
// 5552/16 = 173*2 + 1, need 1 DO16 + 173 DO32
|
||||
|
||||
.macro DO16
|
||||
ld1.4s {v2},[buf] // 16 bytes input
|
||||
shl d6, adlersum2, #(4+32) // adler * 16
|
||||
umull.8h v4, v2, v1 // 16*x0, 15*x1, ..., 9*x7
|
||||
add adlersum2, adlersum2, d6 // sum2 += adler * 16
|
||||
umlal2.8h v4, v2, v1 // 8*x8, 7*x9, ..., 1*x15
|
||||
uaddlv h2, v2.16b // x0+x1+x2+...+x15
|
||||
uaddlv s4, v4.8h // 16*x0 + 15*x1 + ... + 1*x15
|
||||
zip1.2s v4, v2, v4
|
||||
add buf, buf, #16
|
||||
add.2s vadlersum2, vadlersum2, v4
|
||||
.endm
|
||||
|
||||
.macro DO32
|
||||
ld1.4s {v2,v3},[buf] // 32 bytes input
|
||||
shl d6, adlersum2, #(5+32) // adler * 32
|
||||
umull.8h v4, v2, v0 // 32*x0, 31*x1, ..., 25*x7
|
||||
add adlersum2, adlersum2, d6 // sum2 += adler * 32
|
||||
umlal2.8h v4, v2, v0 // accumulate 24*x8, 23*x9, ..., 17*x15
|
||||
uaddlv h2, v2.16b // x0+x1+x2+...+x15 and extend from byte to short
|
||||
umlal.8h v4, v3, v1 // accumulate 16*x16, 15*x17, ..., 9*x23
|
||||
uaddlv h6, v3.16b // x16+x17+x18+...+x31 and extend from byte to short
|
||||
umlal2.8h v4, v3, v1 // accumulate 8*x24, 7*x25, ..., 1*x31
|
||||
uaddl.4s v2, v2, v6 // x0+x1+...+x31 and extend from short to int
|
||||
uaddlv s4, v4.8h // 32*x0 + 31*x1 + ... + 1*x31
|
||||
zip1.2s v4, v2, v4
|
||||
add buf, buf, #32
|
||||
add.2s vadlersum2, vadlersum2, v4
|
||||
.endm
|
||||
|
||||
.macro MOD_BASE
|
||||
umull.2d v2,vadlersum2,v7[1]
|
||||
ushr.2d v2, v2, #47
|
||||
ins v2.s[1], v2.s[2]
|
||||
mls.2s vadlersum2,v2,v7[0]
|
||||
.endm
|
||||
|
||||
DO16
|
||||
mov nvec, #173 // number of DO32 loops
|
||||
|
||||
0:
|
||||
DO32
|
||||
|
||||
subs nvec, nvec, #1
|
||||
b.gt 0b
|
||||
|
||||
MOD_BASE // MOD(adler,sum2);
|
||||
|
||||
subs len, len, nmax // pre-decrement len by NMAX
|
||||
b.ge L_while_len_ge_NMAX_loop // repeat while len >= NMAX
|
||||
|
||||
adds len, len, nmax // post-increment len by NMAX
|
||||
|
||||
L_len_lessthan_NMAX:
|
||||
|
||||
subs len, len, #32 // pre-decrement len by 32
|
||||
b.lt L_len_lessthan_32 // if len < 32, branch to len16_loop
|
||||
|
||||
L_len32_loop:
|
||||
|
||||
DO32
|
||||
|
||||
subs len, len, #32 // len -= 32;
|
||||
b.ge L_len32_loop
|
||||
|
||||
L_len_lessthan_32:
|
||||
|
||||
tst len, #16
|
||||
b.eq 1f
|
||||
|
||||
DO16
|
||||
|
||||
1:
|
||||
ands len, len, #15
|
||||
b.eq L_len_is_zero
|
||||
|
||||
|
||||
L_remaining_len_loop:
|
||||
ldrb w0, [buf], #1 // *buf++;
|
||||
sub len, len, #1
|
||||
ins v2.d[0], x0
|
||||
|
||||
add adlersum2, adlersum2, d2 // adler += *buf
|
||||
shl d6, adlersum2, #32 // shift adler up to sum2 position
|
||||
add adlersum2, adlersum2, d6 // sum2 += adler
|
||||
cbnz len, L_remaining_len_loop // break if len<=0
|
||||
|
||||
|
||||
L_len_is_zero:
|
||||
|
||||
|
||||
MOD_BASE // mod(alder,BASE); mod(sum2,BASE);
|
||||
|
||||
umov w0, vadlersum2.s[0] // adler
|
||||
umov w1, vadlersum2.s[1] // sum2
|
||||
add w0, w0, w1, lsl #16 // to return adler | (sum2 << 16);
|
||||
|
||||
#if KERNEL
|
||||
ld1.4s {v0,v1,v2,v3},[sp],#4*16
|
||||
ld1.4s {v4,v5,v6,v7},[sp],#4*16
|
||||
#endif
|
||||
|
||||
ret lr
|
||||
|
||||
// constants to be loaded into q registers
|
||||
.align 4 // 16 byte aligned
|
||||
|
||||
vec_table:
|
||||
|
||||
// coefficients for computing sum2
|
||||
.long 0x1d1e1f20 // s0
|
||||
.long 0x191a1b1c // s1
|
||||
.long 0x15161718 // s2
|
||||
.long 0x11121314 // s3
|
||||
.long 0x0d0e0f10 // s0
|
||||
.long 0x090a0b0c // s1
|
||||
.long 0x05060708 // s2
|
||||
.long 0x01020304 // s3
|
||||
|
||||
.long BASE // s6 : BASE
|
||||
.long 0x80078071 // s7 : 1/BASE in Q47
|
||||
|
||||
|
||||
|
||||
#endif // __arm64__
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
/* $NetBSD: crc.c,v 1.18 2006/09/04 20:01:10 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* James W. Williams of NASA Goddard Space Flight Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <lib/cksum.h>
|
||||
|
||||
static const uint32_t crctab[] = {
|
||||
0x0,
|
||||
0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
|
||||
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
|
||||
0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
|
||||
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
|
||||
0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
|
||||
0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
|
||||
0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
|
||||
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
|
||||
0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
|
||||
0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
|
||||
0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
|
||||
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
|
||||
0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
|
||||
0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
|
||||
0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
|
||||
0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
|
||||
0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
|
||||
0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
|
||||
0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
|
||||
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
|
||||
0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
|
||||
0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
|
||||
0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
|
||||
0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
|
||||
0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
|
||||
0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
|
||||
0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
|
||||
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
|
||||
0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
|
||||
0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
|
||||
0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
|
||||
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
|
||||
0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
|
||||
0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
|
||||
0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
|
||||
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
|
||||
0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
|
||||
0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
|
||||
0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
|
||||
0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
|
||||
0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
|
||||
0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
|
||||
0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
|
||||
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
|
||||
0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
|
||||
0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
|
||||
0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
|
||||
0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
|
||||
0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
|
||||
0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
|
||||
0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
|
||||
};
|
||||
|
||||
#define COMPUTE(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
|
||||
|
||||
/*
|
||||
* Compute a POSIX 1003.2 checksum. Length is included in the checksum.
|
||||
*/
|
||||
uint32_t
|
||||
crc(const void *buf, size_t len)
|
||||
{
|
||||
const uint8_t *p = buf;
|
||||
size_t nr = len;
|
||||
uint32_t thecrc = INITIAL_CRC;
|
||||
|
||||
for (p = buf; nr; p++, nr--)
|
||||
COMPUTE(thecrc, *p);
|
||||
|
||||
/* Include the length of the buffer. */
|
||||
for (; len != 0; len >>= 8) {
|
||||
COMPUTE(thecrc, len & 0xff);
|
||||
}
|
||||
return ~thecrc;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
crc_byte(uint32_t thecrc, unsigned int byte_val)
|
||||
{
|
||||
COMPUTE(thecrc, byte_val & 0xff);
|
||||
return thecrc;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#include <lib/cksum.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Table of CRCs of all 8-bit messages. */
|
||||
static uint32_t crc32_table[256];
|
||||
|
||||
/* Flag: has the table been computed? Initially false. */
|
||||
static int crc32_table_computed = 0;
|
||||
|
||||
/* Make the table for a fast CRC. */
|
||||
static void make_crc32_table(void)
|
||||
{
|
||||
uint32_t c;
|
||||
int n, k;
|
||||
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = (uint32_t) n;
|
||||
for (k = 0; k < 8; k++) {
|
||||
if (c & 1)
|
||||
c = 0xedb88320L ^ (c >> 1);
|
||||
else
|
||||
c = c >> 1;
|
||||
}
|
||||
crc32_table[n] = c;
|
||||
}
|
||||
crc32_table_computed = 1;
|
||||
}
|
||||
|
||||
/* Update a running CRC with the bytes buf[0..len-1]--the CRC
|
||||
should be initialized to all 1's, and the transmitted value
|
||||
is the 1's complement of the final running CRC (see the
|
||||
crc32() routine below). */
|
||||
|
||||
uint32_t update_crc32(uint32_t crc, const uint8_t *buf,
|
||||
int len)
|
||||
{
|
||||
uint32_t c = crc;
|
||||
int n;
|
||||
|
||||
if (!crc32_table_computed)
|
||||
make_crc32_table();
|
||||
for (n = 0; n < len; n++) {
|
||||
c = crc32_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Return the CRC of the bytes buf[0..len-1]. */
|
||||
uint32_t crc32(const uint8_t *buf, int len)
|
||||
{
|
||||
return update_crc32(0xffffffffL, buf, len) ^ 0xffffffffL;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2009, 2013-2014 Apple Inc. All rights reserved.
|
||||
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <lib/cksum.h>
|
||||
#include <sys/menu.h>
|
||||
#include <drivers/sha1.h>
|
||||
|
||||
int do_crc(int argc, struct cmd_arg *args)
|
||||
{
|
||||
if (argc < 3) {
|
||||
printf("not enough arguments.\n");
|
||||
printf("%s <address> <len>\n", args[0].str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!security_allow_memory((void *)args[1].u, args[2].u)) {
|
||||
printf("Permission Denied\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t crc32 = crc((void *)args[1].u, args[2].u);
|
||||
printf("crc %u (length %zu)\n", crc32, args[2].u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple Inc.
|
||||
# It is considered confidential and proprietary.
|
||||
#
|
||||
# This document may not be reproduced or transmitted in any form,
|
||||
# in whole or in part, without the express written permission of
|
||||
# Apple Inc.
|
||||
#
|
||||
|
||||
LIBCKSUM_DIR := $(GET_LOCAL_DIR)
|
||||
LIBCKSUM_BUILD := $(call TOLIBDIR,$(LIBCKSUM_DIR)/LIBCKSUM.a)
|
||||
COMMONLIBS += LIBCKSUM
|
||||
|
||||
# Only process the remainder of the makefile if we are building libraries
|
||||
#
|
||||
ifeq ($(MAKEPHASE),libraries)
|
||||
|
||||
LIBCKSUM_OBJS := \
|
||||
$(LIBCKSUM_DIR)/adler32.o \
|
||||
$(LIBCKSUM_DIR)/$(ARCH)/adler32vec.o \
|
||||
$(LIBCKSUM_DIR)/crc.o \
|
||||
$(LIBCKSUM_DIR)/crc32.o \
|
||||
$(LIBCKSUM_DIR)/debug.o \
|
||||
$(LIBCKSUM_DIR)/siphash.o
|
||||
|
||||
LIBCKSUM_OBJS := $(call TOLIBOBJDIR,$(LIBCKSUM_OBJS))
|
||||
|
||||
ALL_DEPS += $(LIBCKSUM_OBJS:%o=%d)
|
||||
|
||||
$(LIBCKSUM_BUILD): $(LIBCKSUM_OBJS)
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright (C) 2007-2014 Apple Inc. All rights reserved.
|
||||
# Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple Computer, Inc.
|
||||
# It is considered confidential and proprietary.
|
||||
#
|
||||
# This document may not be reproduced or transmitted in any form,
|
||||
# in whole or in part, without the express written permission of
|
||||
# Apple Inc.
|
||||
#
|
||||
|
||||
OPTIONS += WITH_CKSUM=1
|
||||
LIBRARY_MODULES += lib/cksum
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
SipHash reference C implementation
|
||||
|
||||
Copyright (c) 2012 Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com>
|
||||
Copyright (c) 2012 Daniel J. Bernstein <djb@cr.yp.to>
|
||||
|
||||
To the extent possible under law, the author(s) have dedicated all copyright
|
||||
and related and neighboring rights to this software to the public domain
|
||||
worldwide. This software is distributed without any warranty.
|
||||
|
||||
You should have received a copy of the CC0 Public Domain Dedication along with
|
||||
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
typedef uint64_t u64;
|
||||
typedef uint32_t u32;
|
||||
typedef uint8_t u8;
|
||||
|
||||
#define cROUNDS 2
|
||||
#define dROUNDS 4
|
||||
|
||||
#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
|
||||
|
||||
#define U32TO8_LE(p, v) \
|
||||
(p)[0] = (u8)((v) ); (p)[1] = (u8)((v) >> 8); \
|
||||
(p)[2] = (u8)((v) >> 16); (p)[3] = (u8)((v) >> 24);
|
||||
|
||||
#define U64TO8_LE(p, v) \
|
||||
U32TO8_LE((p), (u32)((v) )); \
|
||||
U32TO8_LE((p) + 4, (u32)((v) >> 32));
|
||||
|
||||
#define U8TO64_LE(p) \
|
||||
(((u64)((p)[0]) ) | \
|
||||
((u64)((p)[1]) << 8) | \
|
||||
((u64)((p)[2]) << 16) | \
|
||||
((u64)((p)[3]) << 24) | \
|
||||
((u64)((p)[4]) << 32) | \
|
||||
((u64)((p)[5]) << 40) | \
|
||||
((u64)((p)[6]) << 48) | \
|
||||
((u64)((p)[7]) << 56))
|
||||
|
||||
#define SIPROUND \
|
||||
do { \
|
||||
v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
|
||||
v2 += v3; v3=ROTL(v3,16); v3 ^= v2; \
|
||||
v0 += v3; v3=ROTL(v3,21); v3 ^= v0; \
|
||||
v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
|
||||
} while(0)
|
||||
|
||||
/* SipHash-2-4 */
|
||||
void siphash( uint8_t *out, const uint8_t *in, size_t inlen, const uint8_t *k )
|
||||
{
|
||||
/* "somepseudorandomlygeneratedbytes" */
|
||||
u64 v0 = 0x736f6d6570736575ULL;
|
||||
u64 v1 = 0x646f72616e646f6dULL;
|
||||
u64 v2 = 0x6c7967656e657261ULL;
|
||||
u64 v3 = 0x7465646279746573ULL;
|
||||
u64 b;
|
||||
u64 k0 = U8TO64_LE( k );
|
||||
u64 k1 = U8TO64_LE( k + 8 );
|
||||
u64 m;
|
||||
int i;
|
||||
const u8 *end = in + inlen - ( inlen % sizeof( u64 ) );
|
||||
const int left = inlen & 7;
|
||||
b = ( ( u64 )inlen ) << 56;
|
||||
v3 ^= k1;
|
||||
v2 ^= k0;
|
||||
v1 ^= k1;
|
||||
v0 ^= k0;
|
||||
|
||||
for ( ; in != end; in += 8 )
|
||||
{
|
||||
m = U8TO64_LE( in );
|
||||
#ifdef SIPHASH_DEBUG
|
||||
printf( "(%3d) v0 %08x %08x\n", ( int )inlen, ( u32 )( v0 >> 32 ), ( u32 )v0 );
|
||||
printf( "(%3d) v1 %08x %08x\n", ( int )inlen, ( u32 )( v1 >> 32 ), ( u32 )v1 );
|
||||
printf( "(%3d) v2 %08x %08x\n", ( int )inlen, ( u32 )( v2 >> 32 ), ( u32 )v2 );
|
||||
printf( "(%3d) v3 %08x %08x\n", ( int )inlen, ( u32 )( v3 >> 32 ), ( u32 )v3 );
|
||||
printf( "(%3d) compress %08x %08x\n", ( int )inlen, ( u32 )( m >> 32 ), ( u32 )m );
|
||||
#endif
|
||||
v3 ^= m;
|
||||
|
||||
for( i=0; i<cROUNDS; ++i ) SIPROUND;
|
||||
|
||||
v0 ^= m;
|
||||
}
|
||||
|
||||
switch( left )
|
||||
{
|
||||
case 7: b |= ( ( u64 )in[ 6] ) << 48;
|
||||
|
||||
case 6: b |= ( ( u64 )in[ 5] ) << 40;
|
||||
|
||||
case 5: b |= ( ( u64 )in[ 4] ) << 32;
|
||||
|
||||
case 4: b |= ( ( u64 )in[ 3] ) << 24;
|
||||
|
||||
case 3: b |= ( ( u64 )in[ 2] ) << 16;
|
||||
|
||||
case 2: b |= ( ( u64 )in[ 1] ) << 8;
|
||||
|
||||
case 1: b |= ( ( u64 )in[ 0] ); break;
|
||||
|
||||
case 0: break;
|
||||
}
|
||||
|
||||
#ifdef SIPHASH_DEBUG
|
||||
printf( "(%3d) v0 %08x %08x\n", ( int )inlen, ( u32 )( v0 >> 32 ), ( u32 )v0 );
|
||||
printf( "(%3d) v1 %08x %08x\n", ( int )inlen, ( u32 )( v1 >> 32 ), ( u32 )v1 );
|
||||
printf( "(%3d) v2 %08x %08x\n", ( int )inlen, ( u32 )( v2 >> 32 ), ( u32 )v2 );
|
||||
printf( "(%3d) v3 %08x %08x\n", ( int )inlen, ( u32 )( v3 >> 32 ), ( u32 )v3 );
|
||||
printf( "(%3d) padding %08x %08x\n", ( int )inlen, ( u32 )( b >> 32 ), ( u32 )b );
|
||||
#endif
|
||||
v3 ^= b;
|
||||
|
||||
for( i=0; i<cROUNDS; ++i ) SIPROUND;
|
||||
|
||||
v0 ^= b;
|
||||
#ifdef SIPHASH_DEBUG
|
||||
printf( "(%3d) v0 %08x %08x\n", ( int )inlen, ( u32 )( v0 >> 32 ), ( u32 )v0 );
|
||||
printf( "(%3d) v1 %08x %08x\n", ( int )inlen, ( u32 )( v1 >> 32 ), ( u32 )v1 );
|
||||
printf( "(%3d) v2 %08x %08x\n", ( int )inlen, ( u32 )( v2 >> 32 ), ( u32 )v2 );
|
||||
printf( "(%3d) v3 %08x %08x\n", ( int )inlen, ( u32 )( v3 >> 32 ), ( u32 )v3 );
|
||||
#endif
|
||||
v2 ^= 0xff;
|
||||
|
||||
for( i=0; i<dROUNDS; ++i ) SIPROUND;
|
||||
|
||||
b = v0 ^ v1 ^ v2 ^ v3;
|
||||
U64TO8_LE( out, b );
|
||||
}
|
||||
|
||||
|
||||
void siphash_aligned(uint64_t *out, const uint64_t *in_aligned, size_t inlen, const uint64_t *k)
|
||||
{
|
||||
/* "somepseudorandomlygeneratedbytes" */
|
||||
u64 v0 = 0x736f6d6570736575ULL;
|
||||
u64 v1 = 0x646f72616e646f6dULL;
|
||||
u64 v2 = 0x6c7967656e657261ULL;
|
||||
u64 v3 = 0x7465646279746573ULL;
|
||||
u64 b;
|
||||
u64 k0 = k[0];
|
||||
u64 k1 = k[1];
|
||||
u64 m;
|
||||
int i;
|
||||
const u8 *in = (const u8 *)in_aligned;
|
||||
const u8 *end = in + inlen - ( inlen % sizeof( u64 ) );
|
||||
const int left = inlen & 7;
|
||||
b = ( ( u64 )inlen ) << 56;
|
||||
v3 ^= k1;
|
||||
v2 ^= k0;
|
||||
v1 ^= k1;
|
||||
v0 ^= k0;
|
||||
|
||||
ASSERT(((uintptr_t)in_aligned & (sizeof(u64) - 1)) == 0);
|
||||
|
||||
for ( ; in != end; in += 8 )
|
||||
{
|
||||
m = *(u64 *)in;
|
||||
#ifdef SIPHASH_DEBUG
|
||||
printf( "(%3d) v0 %08x %08x\n", ( int )inlen, ( u32 )( v0 >> 32 ), ( u32 )v0 );
|
||||
printf( "(%3d) v1 %08x %08x\n", ( int )inlen, ( u32 )( v1 >> 32 ), ( u32 )v1 );
|
||||
printf( "(%3d) v2 %08x %08x\n", ( int )inlen, ( u32 )( v2 >> 32 ), ( u32 )v2 );
|
||||
printf( "(%3d) v3 %08x %08x\n", ( int )inlen, ( u32 )( v3 >> 32 ), ( u32 )v3 );
|
||||
printf( "(%3d) compress %08x %08x\n", ( int )inlen, ( u32 )( m >> 32 ), ( u32 )m );
|
||||
#endif
|
||||
v3 ^= m;
|
||||
|
||||
for( i=0; i<cROUNDS; ++i ) SIPROUND;
|
||||
|
||||
v0 ^= m;
|
||||
}
|
||||
|
||||
switch( left )
|
||||
{
|
||||
case 7: b |= ( ( u64 )in[ 6] ) << 48;
|
||||
|
||||
case 6: b |= ( ( u64 )in[ 5] ) << 40;
|
||||
|
||||
case 5: b |= ( ( u64 )in[ 4] ) << 32;
|
||||
|
||||
case 4: b |= ( ( u64 )in[ 3] ) << 24;
|
||||
|
||||
case 3: b |= ( ( u64 )in[ 2] ) << 16;
|
||||
|
||||
case 2: b |= ( ( u64 )in[ 1] ) << 8;
|
||||
|
||||
case 1: b |= ( ( u64 )in[ 0] ); break;
|
||||
|
||||
case 0: break;
|
||||
}
|
||||
|
||||
#ifdef SIPHASH_DEBUG
|
||||
printf( "(%3d) v0 %08x %08x\n", ( int )inlen, ( u32 )( v0 >> 32 ), ( u32 )v0 );
|
||||
printf( "(%3d) v1 %08x %08x\n", ( int )inlen, ( u32 )( v1 >> 32 ), ( u32 )v1 );
|
||||
printf( "(%3d) v2 %08x %08x\n", ( int )inlen, ( u32 )( v2 >> 32 ), ( u32 )v2 );
|
||||
printf( "(%3d) v3 %08x %08x\n", ( int )inlen, ( u32 )( v3 >> 32 ), ( u32 )v3 );
|
||||
printf( "(%3d) padding %08x %08x\n", ( int )inlen, ( u32 )( b >> 32 ), ( u32 )b );
|
||||
#endif
|
||||
v3 ^= b;
|
||||
|
||||
for( i=0; i<cROUNDS; ++i ) SIPROUND;
|
||||
|
||||
v0 ^= b;
|
||||
#ifdef SIPHASH_DEBUG
|
||||
printf( "(%3d) v0 %08x %08x\n", ( int )inlen, ( u32 )( v0 >> 32 ), ( u32 )v0 );
|
||||
printf( "(%3d) v1 %08x %08x\n", ( int )inlen, ( u32 )( v1 >> 32 ), ( u32 )v1 );
|
||||
printf( "(%3d) v2 %08x %08x\n", ( int )inlen, ( u32 )( v2 >> 32 ), ( u32 )v2 );
|
||||
printf( "(%3d) v3 %08x %08x\n", ( int )inlen, ( u32 )( v3 >> 32 ), ( u32 )v3 );
|
||||
#endif
|
||||
v2 ^= 0xff;
|
||||
|
||||
for( i=0; i<dROUNDS; ++i ) SIPROUND;
|
||||
|
||||
b = v0 ^ v1 ^ v2 ^ v3;
|
||||
*out = b;
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
#include <unittest.h>
|
||||
#include <lib/cksum.h>
|
||||
|
||||
struct crc_test {
|
||||
const char *data;
|
||||
uint32_t len;
|
||||
uint32_t expected;
|
||||
};
|
||||
|
||||
static struct crc_test crc32_tests[] = {
|
||||
{ "", 0, 0x00000000 },
|
||||
{ "a", 1, 0xe8b7be43 },
|
||||
{ "abc", 3, 0x352441c2 },
|
||||
{ "aaaa", 4, 0xad98e545 },
|
||||
{ "abcdefghijklmnopqrstuvwxyz", 26, 0x4c2750bd }
|
||||
};
|
||||
|
||||
void test_crc32(uintptr_t param)
|
||||
{
|
||||
for (unsigned i = 0; i < sizeof crc32_tests / sizeof(crc32_tests[0]); i++) {
|
||||
struct crc_test *test = &crc32_tests[i];
|
||||
uint32_t calculated = crc32((const uint8_t *)test->data, test->len);
|
||||
|
||||
TEST_ASSERT_EQ(calculated, test->expected);
|
||||
}
|
||||
}
|
||||
|
||||
void test_update_crc32(uintptr_t param)
|
||||
{
|
||||
for (unsigned i = 0; i < sizeof crc32_tests / sizeof(crc32_tests[0]); i++) {
|
||||
struct crc_test *test = &crc32_tests[i];
|
||||
|
||||
uint32_t calculated = 0xffffffff;
|
||||
const uint8_t *data = (const uint8_t *)test->data;
|
||||
|
||||
if (test->len != 0) {
|
||||
calculated = update_crc32(calculated, data, 1);
|
||||
calculated = update_crc32(calculated, data + 1, test->len - 1);
|
||||
} else {
|
||||
calculated = update_crc32(calculated, data, test->len);
|
||||
}
|
||||
|
||||
calculated ^= 0xffffffff;
|
||||
|
||||
TEST_ASSERT_EQ(calculated, test->expected);
|
||||
|
||||
// updating with data of length 0 shouldn't have an effect
|
||||
calculated = update_crc32(calculated, (const uint8_t *)"a", 0);
|
||||
|
||||
TEST_ASSERT_EQ(calculated, test->expected);
|
||||
}
|
||||
}
|
||||
|
||||
// generated with the "cksum" commandline tool
|
||||
static struct crc_test crc_tests[] = {
|
||||
{ "", 0, 4294967295 },
|
||||
{ "a", 1, 1220704766 },
|
||||
{ "abc", 3, 1219131554 },
|
||||
{ "aaaa", 4, 3100911197 },
|
||||
{ "abcdefghijklmnopqrstuvwxyz", 26, 2713270184 },
|
||||
{ "\0\0\0\0", 4, 3975907619 },
|
||||
};
|
||||
|
||||
void test_crc(uintptr_t data)
|
||||
{
|
||||
for (unsigned i = 0; i < sizeof crc_tests / sizeof(crc_tests[0]); i++) {
|
||||
struct crc_test *test = &crc_tests[i];
|
||||
uint32_t calculated = crc((const uint8_t *)test->data, test->len);
|
||||
|
||||
TEST_ASSERT_EQ(calculated, test->expected);
|
||||
}
|
||||
}
|
||||
|
||||
void test_crc_byte(uintptr_t data)
|
||||
{
|
||||
for (unsigned i = 0; i < sizeof crc_tests / sizeof(crc_tests[0]); i++) {
|
||||
struct crc_test *test = &crc_tests[i];
|
||||
uint32_t calculated = INITIAL_CRC;
|
||||
|
||||
for (uint32_t j = 0; j < test->len; j++)
|
||||
calculated = crc_byte(calculated, ((const uint8_t *)test->data)[j]);
|
||||
|
||||
for (uint32_t n = test->len; n != 0; n >>= 8)
|
||||
calculated = crc_byte(calculated, n & 0xff);
|
||||
|
||||
calculated = ~calculated;
|
||||
|
||||
TEST_ASSERT_EQ(calculated, test->expected);
|
||||
}
|
||||
}
|
||||
|
||||
static struct crc_test adler32_tests[] = {
|
||||
{ "", 0, 0x00000001 },
|
||||
{ "a", 1, 0x00620062 },
|
||||
{ "abc", 3, 0x024d0127 },
|
||||
{ "message digest", 14, 0x29750586 },
|
||||
{ "abcdefghijklmnopqrstuvwxyz", 26, 0x90860b20 },
|
||||
};
|
||||
|
||||
void test_adler32(uintptr_t data)
|
||||
{
|
||||
for (unsigned i = 0; i < sizeof adler32_tests / sizeof(adler32_tests[0]); i++) {
|
||||
struct crc_test *test = &adler32_tests[i];
|
||||
uint32_t calculated = adler32((const uint8_t *)test->data, test->len);
|
||||
|
||||
TEST_ASSERT_EQ(calculated, test->expected);
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t siphash_vectors[64][SIPHASH_HASH_SIZE] =
|
||||
{
|
||||
{ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, },
|
||||
{ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, },
|
||||
{ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, },
|
||||
{ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, },
|
||||
{ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, },
|
||||
{ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, },
|
||||
{ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, },
|
||||
{ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, },
|
||||
{ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, },
|
||||
{ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, },
|
||||
{ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, },
|
||||
{ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, },
|
||||
{ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, },
|
||||
{ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, },
|
||||
{ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, },
|
||||
{ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, },
|
||||
{ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, },
|
||||
{ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, },
|
||||
{ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, },
|
||||
{ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, },
|
||||
{ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, },
|
||||
{ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, },
|
||||
{ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, },
|
||||
{ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, },
|
||||
{ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, },
|
||||
{ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, },
|
||||
{ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, },
|
||||
{ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, },
|
||||
{ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, },
|
||||
{ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, },
|
||||
{ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, },
|
||||
{ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, },
|
||||
{ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, },
|
||||
{ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, },
|
||||
{ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, },
|
||||
{ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, },
|
||||
{ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, },
|
||||
{ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, },
|
||||
{ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, },
|
||||
{ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, },
|
||||
{ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, },
|
||||
{ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, },
|
||||
{ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, },
|
||||
{ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, },
|
||||
{ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, },
|
||||
{ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, },
|
||||
{ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, },
|
||||
{ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, },
|
||||
{ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, },
|
||||
{ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, },
|
||||
{ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, },
|
||||
{ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, },
|
||||
{ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, },
|
||||
{ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, },
|
||||
{ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, },
|
||||
{ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, },
|
||||
{ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, },
|
||||
{ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, },
|
||||
{ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, },
|
||||
{ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, },
|
||||
{ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, },
|
||||
{ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, },
|
||||
{ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, },
|
||||
{ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, }
|
||||
};
|
||||
|
||||
void test_siphash(uintptr_t context)
|
||||
{
|
||||
uint8_t in[64], out[SIPHASH_HASH_SIZE], k[SIPHASH_KEY_SIZE];
|
||||
unsigned i;
|
||||
|
||||
for(i = 0; i < 16; ++i)
|
||||
k[i] = i;
|
||||
|
||||
for(i = 0; i < sizeof(in); ++i)
|
||||
{
|
||||
in[i] = i;
|
||||
siphash(out, in, i, k);
|
||||
|
||||
TEST_ASSERT_MEM_EQ(out, siphash_vectors[i], sizeof(out));
|
||||
}
|
||||
}
|
||||
|
||||
void test_siphash_aligned(uintptr_t context)
|
||||
{
|
||||
uint64_t in_aligned[64 / 8];
|
||||
uint64_t out[SIPHASH_HASH_SIZE / 8];
|
||||
uint64_t key_aligned[SIPHASH_KEY_SIZE / 8];
|
||||
uint8_t *in = (uint8_t *)&in_aligned[0];
|
||||
uint8_t *key = (uint8_t *)&key_aligned[0];
|
||||
unsigned i;
|
||||
|
||||
for(i = 0; i < 16; ++i)
|
||||
key[i] = i;
|
||||
|
||||
for(i = 0; i < sizeof(in); ++i)
|
||||
{
|
||||
in[i] = i;
|
||||
siphash_aligned(out, in_aligned, i, key_aligned);
|
||||
|
||||
TEST_ASSERT_MEM_EQ(out, siphash_vectors[i], sizeof(out));
|
||||
}
|
||||
}
|
||||
|
||||
struct test_suite cksum_suite = {
|
||||
.name = "cksum",
|
||||
.test_cases = {
|
||||
{ "crc32", test_crc32, 0, "Tests the crc32 checksum function" },
|
||||
{ "update_crc32", test_update_crc32, 0, "Tests the update_crc32 checksum function" },
|
||||
{ "crc", test_crc, 0, "Tests the crc POSIX 1003.2 checksum function" },
|
||||
{ "crc_byte", test_crc_byte, 0, "Tests the crc_byte bytewise POSIX 1003.2 checksum function" },
|
||||
{ "adler32", test_adler32, 0, "Tests the adler32 checksum function" },
|
||||
{ "siphash", test_siphash, 0, "Tests the siphash checksum function" },
|
||||
{ "siphash_aligned", test_siphash_aligned, 0, "Tests the siphash_aligned checksum function" },
|
||||
TEST_CASE_LAST
|
||||
}
|
||||
};
|
||||
|
||||
TEST_SUITE(cksum_suite);
|
||||
@@ -0,0 +1,39 @@
|
||||
# Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple Inc.
|
||||
# It is considered confidential and proprietary.
|
||||
#
|
||||
# This document may not be reproduced or transmitted in any form,
|
||||
# in whole or in part, without the express written permission of
|
||||
# Apple Inc.
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
TEST_NAME := cksum
|
||||
|
||||
TEST_OBJS := \
|
||||
$(LOCAL_DIR)/adler32.o \
|
||||
$(LOCAL_DIR)/crc.o \
|
||||
$(LOCAL_DIR)/crc32.o \
|
||||
$(LOCAL_DIR)/siphash.o
|
||||
|
||||
TEST_SUPPORT_OBJS := \
|
||||
tests/unittest-main.o \
|
||||
$(LOCAL_DIR)/tests.o
|
||||
|
||||
ifeq ($(ARM_ARCH),armv7)
|
||||
TEST_OBJS += \
|
||||
$(LOCAL_DIR)/arm/adler32vec.o
|
||||
endif
|
||||
|
||||
ifeq ($(ARM_ARCH),armv7k)
|
||||
TEST_OBJS += \
|
||||
$(LOCAL_DIR)/arm/adler32vec.o
|
||||
endif
|
||||
|
||||
ifeq ($(ARM_ARCH),arm64)
|
||||
TEST_OBJS += \
|
||||
$(LOCAL_DIR)/arm64/adler32vec.o
|
||||
endif
|
||||
|
||||
Reference in new issue
Block a user