@ lookup3.s by Simon Stapleton, 2010, Public Domain @ Thumb-2 implementation of 'hashlittle2' by Bob Jenkins. .syntax unified .align 2 .thumb .global hash .type hash, %function @ Hash Function @ In : R0 -> pointer to string @ R1 -> length of string @ R2 -> Initial value for 'hash c' @ R3 -> Initial value for 'hash b' @ Out : R0 -> 'hash c', the main hash value @ R1 -> 'hash b', the secondary hash value @ Clobbers R2, R3, flags hash: push {r4-r7,lr} @ Within the function, we use registers as follows: @ r1 : length @ r2-r4 : temporary for character loading @ r5-r7 : a, b, c @ initial setup adr r7, hash_constant @ a = b = c = 0xdeadbeef + length + hash c ldr r7, [r7] adds r7, r1 adds r7, r2 mov r5, r7 mov r6, r7 adds r7, r3 @ c += hash b hash_loop: cmp r1, #0x0c @ Is r4 <= 12? it le ble hash_tail @ If so, go do the tail part ldmia r0!, {r2, r3, r4} @ Load values adds r5, r2 adds r6, r3 adds r7, r4 subs r1, #0x0c @ Subtract 12 from length @ Mix subs r5, r7 @ a -= c eor.W r5, r5, r7, ror #28 @ a ^= rot(c,4) adds r7, r6 @ c += b subs r6, r5 @ b -= a eor.W r6, r6, r5, ror #26 @ b ^= rot(a,6) adds r5, r7 @ a += c ; subs r7, r6 @ c -= b ; eor.W r7, r7, r6, ror #24 @ c ^= rot(b, 8) ; adds r6, r5 @ b += a ; subs r5, r7 @ a -= c eor.W r5, r5, r7, ror #16 @ a ^= rot(c,16) adds r7, r6 @ c += b subs r6, r5 @ b -= a eor.W r6, r6, r5, ror #13 @ b ^= rot(a,19) adds r5, r7 @ a += c ; subs r7, r6 @ c -= b ; eor.W r7, r7, r6, ror #28 @ c ^= rot(b, 4) ; adds r6, r5 @ b += a ; b hash_loop hash_tail: cmp r1, #0x00 @ length 0 requires no extra work it eq beq hash_done ldmia r0!, {r2, r3, r4} @ Load values adr r0, do_hash_mask add r0, r0, r1, lsl #2 do_hash_mask: mov.W pc, r0 @ doubles for count 0 entry in masking table, *must* be 4 bytes hence .W @ Here we mask off the bits we don't want according to @ what data we have bic r2, #0x0000ff00 @ count is 1, mask off all but least significant byte bic r2, #0x00ff0000 @ etc etc bic r2, #0xff000000 bic r3, #0x000000ff bic r3, #0x0000ff00 bic r3, #0x00ff0000 bic r3, #0xff000000 bic r4, #0x000000ff bic r4, #0x0000ff00 bic r4, #0x00ff0000 bic r4, #0xff000000 bic r4, #0x00000000 adds r5, r2 @ Add masked vales before final mix adds r6, r3 adds r7, r4 @ Final mix eors r7, r6 @ c ^= b sub r7, r7, r6, ror #18 @ c -= rot(b,14) eors r5, r7 @ a ^= c sub r5, r5, r7, ror #21 @ c -= rot(c,11) eors r6, r5 @ b ^= a sub r6, r6, r5, ror #7 @ b -= rot(a,25) eors r7, r6 @ c ^= b sub r7, r7, r6, ror #16 @ c -= rot(b,16) eors r5, r7 @ a ^= c sub r5, r5, r7, ror #28 @ c -= rot(c,4) eors r6, r5 @ b ^= a sub r6, r6, r5, ror #18 @ b -= rot(a,14) eors r7, r6 @ c ^= b sub r7, r7, r6, ror #8 @ c -= rot(b,24) hash_done: mov r0, r7 mov r1, r6 pop {r4-r7, pc} hash_constant: .word 0xdeadbeef .ltorg @ Uncomment to build hash testing function HASH_TEST = 1 .ifdef HASH_TEST .align 2 .global hash_test .type hash_test, %function hash_test: push {r4-r10, lr} adr r0, hash_test_string mov r1, #0 mov r2, #0 mov r3, #0 bl hash @ r0 = 0xdeadbeef, r1 = 0xdeadbeef adr r0, hash_test_string mov r1, #0 mov r2, #0 adr r3, hash_constant ldr r3, [r3] bl hash @ r0 = 0xbd5b7dde, r1 = 0xdeadbeef adr r0, hash_test_string mov r1, #0 adr r3, hash_constant ldr r2, [r3] ldr r3, [r3] bl hash @ r0 = 0x9c093ccd, r1 = 0xbd5b7dde adr r0, hash_test_string mov r1, #30 mov r2, #0 mov r3, #0 bl hash @ r0 = 0x17770551, r1 = 0xce7226e6 adr r0, hash_test_string mov r1, #30 mov r2, #0 mov r3, #1 bl hash @ r0 = 0xe3607cae, r1 = 0xbd371de4 adr r0, hash_test_string mov r1, #30 mov r2, #1 mov r3, #0 bl hash @ r0 = 0xcd628161, r1 = 0x6cbea4b3 pop {r4-r10, pc} hash_test_string: .string "Four score and seven years ago" .align 2 .ltorg .endif