QortalOS Brooklyn for Raspberry Pi 4
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

229 lines
6.7 KiB

/*
Copyright (c) 2013, Raspberry Pi Foundation
Copyright (c) 2013, RISC OS Open Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of the copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
/* Prevent the stack from becoming executable */
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif
.text
.arch armv6
.object_arch armv4
.arm
.altmacro
.p2align 2
.macro myfunc fname
.func fname
.global fname
/* For ELF format also set function visibility to hidden */
#ifdef __ELF__
.hidden fname
.type fname, %function
#endif
fname:
.endm
.macro hashmix A, B, C
sub A, A, C
eor A, A, C, ror #32-4
add C, C, B
sub B, B, A
eor B, B, A, ror #32-6
add A, A, C
sub C, C, B
eor C, C, B, ror #32-8
add B, B, A
sub A, A, C
eor A, A, C, ror #32-16
add C, C, B
sub B, B, A
eor B, B, A, ror #32-19
add A, A, C
sub C, C, B
eor C, C, B, ror #32-4
add B, B, A
.endm
.macro hashfinal A, B, C
eor C, C, B
sub C, C, B, ror #32-14
eor A, A, C
sub A, A, C, ror #32-11
eor B, B, A
sub B, B, A, ror #32-25
eor C, C, B
sub C, C, B, ror #32-16
eor A, A, C
sub A, A, C, ror #32-4
eor B, B, A
sub B, B, A, ror #32-14
eor C, C, B
sub C, C, B, ror #32-24
.endm
/*
* uint32_t khrn_hashword(const uint32_t *k, int length, uint32_t initval);
* On entry:
* a1 = pointer to buffer
* a2 = number of 32-bit words
* a3 = seed
* On exit:
* a1 = hash value
*/
.set prefetch_distance, 2
myfunc khrn_hashword
S .req a1
N .req a2
AA .req a3
BB .req a4
CC .req v1
DAT0 .req v2
DAT1 .req ip
DAT2 .req lr
ldr BB, =0xDEADBEEF
push {CC, DAT0, lr}
add AA, AA, N, lsl #2
add AA, AA, BB
mov BB, AA
mov CC, AA
/* To preload ahead as we go, we need at least (prefetch_distance+2) 32-byte blocks */
cmp N, #(prefetch_distance+2)*32/4
blo 170f
/* Long case */
/* Adjust N to simplify inner loop termination. We want it to
* stop when there are (prefetch_distance+1) complete cache
* lines to go. */
sub N, N, #(prefetch_distance+2)*32/4
bic DAT0, S, #31
.set OFFSET, 0
.rept prefetch_distance+1
pld [DAT0, #OFFSET]
.set OFFSET, OFFSET+32
.endr
and DAT1, S, #0x1C
cmp DAT1, #0x0C
bhs 156f
154: /* Now at first complete triple-word within cacheline, with at
* least one prefetch to go (but no prefetch required until we
* have processed at least 2 triple-words) */
ldmia S!, {DAT0, DAT1, DAT2}
sub N, N, #12/4
add AA, AA, DAT0
add BB, BB, DAT1
add CC, CC, DAT2
hashmix AA, BB, CC
156: ldmia S!, {DAT0, DAT1, DAT2}
sub N, N, #12/4
add AA, AA, DAT0
add BB, BB, DAT1
add CC, CC, DAT2
hashmix AA, BB, CC
tst S, #0x10
bne 156b
bic DAT0, S, #0x1F
and DAT1, S, #0x1F
pld [DAT0, #prefetch_distance*32]
adds DAT1, N, DAT1, lsr #2
bpl 154b
/* Just before the final (prefetch_distance+1) 32-byte blocks,
* deal with final preload */
cmp DAT1, #-32/4
beq 157f
pld [DAT0, #(prefetch_distance+1)*32]
157: add N, N, #(prefetch_distance+2)*32/4 - 1 - 3
158: ldmia S!, {DAT0, DAT1, DAT2}
add AA, AA, DAT0
add BB, BB, DAT1
add CC, CC, DAT2
hashmix AA, BB, CC
subs N, N, #3
bhs 158b
cmp N, #-2
ldr DAT0, [S], #4
ldrhs DAT1, [S], #4
ldrhi DAT2, [S], #4
add AA, AA, DAT0
addhs BB, BB, DAT1
addhi CC, CC, DAT2
hashfinal AA, BB, CC
mov a1, CC
pop {CC, DAT0, pc}
170: /* Short case */
cmp N, #1
blo 199f
bic DAT0, S, #31
pld [DAT0]
add DAT1, S, N, lsl #2
sub DAT1, DAT1, #1
bic DAT1, DAT1, #31
cmp DAT1, DAT0
beq 92f
91: add DAT0, DAT0, #32
cmp DAT0, DAT1
pld [DAT0]
bne 91b
92: sub N, N, #1
b 176f
175: ldmia S!, {DAT0, DAT1, DAT2}
add AA, AA, DAT0
add BB, BB, DAT1
add CC, CC, DAT2
hashmix AA, BB, CC
176: subs N, N, #3
bhs 175b
cmp N, #-2
ldr DAT0, [S], #4
ldrhs DAT1, [S], #4
ldrhi DAT2, [S], #4
add AA, AA, DAT0
addhs BB, BB, DAT1
addhi CC, CC, DAT2
hashfinal AA, BB, CC
199: mov a1, CC
pop {CC, DAT0, pc}
.unreq S
.unreq N
.unreq AA
.unreq BB
.unreq CC
.unreq DAT0
.unreq DAT1
.unreq DAT2
.endfunc
.ltorg