^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2013 ARM Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2013 Linaro.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This code is based on glibc cortex strings work originally authored by Linaro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * be found @
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * http://bazaar.launchpad.net/~linaro-toolchain-dev/cortex-strings/trunk/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * files/head:/src/aarch64/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/linkage.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/assembler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * compare memory areas(when two memory areas' offset are different,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * alignment handled by the hardware)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Parameters:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * x0 - const memory area 1 pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * x1 - const memory area 2 pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * x2 - the maximal compare byte length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * x0 - a compare result, maybe less than, equal to, or greater than ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* Parameters and result. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) src1 .req x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) src2 .req x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) limit .req x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) result .req x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Internal variables. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) data1 .req x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) data1w .req w3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) data2 .req x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) data2w .req w4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) has_nul .req x5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) diff .req x6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) endloop .req x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) tmp1 .req x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) tmp2 .req x9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) tmp3 .req x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) pos .req x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) limit_wd .req x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) mask .req x13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) SYM_FUNC_START_WEAK_PI(memcmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) cbz limit, .Lret0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) eor tmp1, src1, src2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) tst tmp1, #7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) b.ne .Lmisaligned8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) ands tmp1, src1, #7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) b.ne .Lmutual_align
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) sub limit_wd, limit, #1 /* limit != 0, so no underflow. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) lsr limit_wd, limit_wd, #3 /* Convert to Dwords. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * The input source addresses are at alignment boundary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * Directly compare eight bytes each time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .Lloop_aligned:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ldr data1, [src1], #8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) ldr data2, [src2], #8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) .Lstart_realigned:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) subs limit_wd, limit_wd, #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) eor diff, data1, data2 /* Non-zero if differences found. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) csinv endloop, diff, xzr, cs /* Last Dword or differences. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) cbz endloop, .Lloop_aligned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* Not reached the limit, must have found a diff. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) tbz limit_wd, #63, .Lnot_limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* Limit % 8 == 0 => the diff is in the last 8 bytes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ands limit, limit, #7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) b.eq .Lnot_limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * The remained bytes less than 8. It is needed to extract valid data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * from last eight bytes of the intended memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) lsl limit, limit, #3 /* bytes-> bits. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) mov mask, #~0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) CPU_BE( lsr mask, mask, limit )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) CPU_LE( lsl mask, mask, limit )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) bic data1, data1, mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) bic data2, data2, mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) orr diff, diff, mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) b .Lnot_limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .Lmutual_align:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * Sources are mutually aligned, but are not currently at an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * alignment boundary. Round down the addresses and then mask off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * the bytes that precede the start point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) bic src1, src1, #7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) bic src2, src2, #7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) ldr data1, [src1], #8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) ldr data2, [src2], #8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * We can not add limit with alignment offset(tmp1) here. Since the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * addition probably make the limit overflown.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) sub limit_wd, limit, #1/*limit != 0, so no underflow.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) and tmp3, limit_wd, #7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) lsr limit_wd, limit_wd, #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) add tmp3, tmp3, tmp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) add limit_wd, limit_wd, tmp3, lsr #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) add limit, limit, tmp1/* Adjust the limit for the extra. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) lsl tmp1, tmp1, #3/* Bytes beyond alignment -> bits.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) neg tmp1, tmp1/* Bits to alignment -64. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) mov tmp2, #~0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /*mask off the non-intended bytes before the start address.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) CPU_BE( lsl tmp2, tmp2, tmp1 )/*Big-endian.Early bytes are at MSB*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* Little-endian. Early bytes are at LSB. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) CPU_LE( lsr tmp2, tmp2, tmp1 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) orr data1, data1, tmp2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) orr data2, data2, tmp2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) b .Lstart_realigned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /*src1 and src2 have different alignment offset.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .Lmisaligned8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) cmp limit, #8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) b.lo .Ltiny8proc /*limit < 8: compare byte by byte*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) and tmp1, src1, #7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) neg tmp1, tmp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) add tmp1, tmp1, #8/*valid length in the first 8 bytes of src1*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) and tmp2, src2, #7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) neg tmp2, tmp2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) add tmp2, tmp2, #8/*valid length in the first 8 bytes of src2*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) subs tmp3, tmp1, tmp2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) csel pos, tmp1, tmp2, hi /*Choose the maximum.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) sub limit, limit, pos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /*compare the proceeding bytes in the first 8 byte segment.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .Ltinycmp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) ldrb data1w, [src1], #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ldrb data2w, [src2], #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) subs pos, pos, #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) ccmp data1w, data2w, #0, ne /* NZCV = 0b0000. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) b.eq .Ltinycmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) cbnz pos, 1f /*diff occurred before the last byte.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) cmp data1w, data2w
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) b.eq .Lstart_align
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) sub result, data1, data2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) ret
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .Lstart_align:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) lsr limit_wd, limit, #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) cbz limit_wd, .Lremain8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) ands xzr, src1, #7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) b.eq .Lrecal_offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /*process more leading bytes to make src1 aligned...*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) add src1, src1, tmp3 /*backwards src1 to alignment boundary*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) add src2, src2, tmp3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) sub limit, limit, tmp3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) lsr limit_wd, limit, #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) cbz limit_wd, .Lremain8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /*load 8 bytes from aligned SRC1..*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ldr data1, [src1], #8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) ldr data2, [src2], #8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) subs limit_wd, limit_wd, #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) eor diff, data1, data2 /*Non-zero if differences found.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) csinv endloop, diff, xzr, ne
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) cbnz endloop, .Lunequal_proc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /*How far is the current SRC2 from the alignment boundary...*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) and tmp3, tmp3, #7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .Lrecal_offset:/*src1 is aligned now..*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) neg pos, tmp3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .Lloopcmp_proc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * Divide the eight bytes into two parts. First,backwards the src2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * to an alignment boundary,load eight bytes and compare from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * the SRC2 alignment boundary. If all 8 bytes are equal,then start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * the second part's comparison. Otherwise finish the comparison.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * This special handle can garantee all the accesses are in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * thread/task space in avoid to overrange access.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) ldr data1, [src1,pos]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) ldr data2, [src2,pos]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) eor diff, data1, data2 /* Non-zero if differences found. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) cbnz diff, .Lnot_limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /*The second part process*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) ldr data1, [src1], #8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) ldr data2, [src2], #8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) eor diff, data1, data2 /* Non-zero if differences found. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) subs limit_wd, limit_wd, #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) csinv endloop, diff, xzr, ne/*if limit_wd is 0,will finish the cmp*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) cbz endloop, .Lloopcmp_proc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .Lunequal_proc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) cbz diff, .Lremain8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* There is difference occurred in the latest comparison. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .Lnot_limit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * For little endian,reverse the low significant equal bits into MSB,then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * following CLZ can find how many equal bits exist.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) CPU_LE( rev diff, diff )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) CPU_LE( rev data1, data1 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) CPU_LE( rev data2, data2 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * The MS-non-zero bit of DIFF marks either the first bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * that is different, or the end of the significant data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * Shifting left now will bring the critical information into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * top bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) clz pos, diff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) lsl data1, data1, pos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) lsl data2, data2, pos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * We need to zero-extend (char is unsigned) the value and then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * perform a signed subtraction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) lsr data1, data1, #56
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) sub result, data1, data2, lsr #56
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) ret
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .Lremain8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) /* Limit % 8 == 0 =>. all data are equal.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) ands limit, limit, #7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) b.eq .Lret0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) .Ltiny8proc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ldrb data1w, [src1], #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ldrb data2w, [src2], #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) subs limit, limit, #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ccmp data1w, data2w, #0, ne /* NZCV = 0b0000. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) b.eq .Ltiny8proc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) sub result, data1, data2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) ret
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .Lret0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) mov result, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ret
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) SYM_FUNC_END_PI(memcmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) EXPORT_SYMBOL_NOKASAN(memcmp)