github.com/m10x/go/src@v0.0.0-20220112094212-ba61592315da/internal/bytealg/equal_arm64.s (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include "go_asm.h" 6 #include "textflag.h" 7 8 // memequal(a, b unsafe.Pointer, size uintptr) bool 9 TEXT runtime·memequal<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-25 10 #ifndef GOEXPERIMENT_regabiargs 11 MOVD size+16(FP), R2 12 #endif 13 // short path to handle 0-byte case 14 CBZ R2, equal 15 #ifndef GOEXPERIMENT_regabiargs 16 MOVD a+0(FP), R0 17 MOVD b+8(FP), R1 18 MOVD $ret+24(FP), R8 19 #endif 20 B memeqbody<>(SB) 21 equal: 22 MOVD $1, R0 23 #ifndef GOEXPERIMENT_regabiargs 24 MOVB R0, ret+24(FP) 25 #endif 26 RET 27 28 // memequal_varlen(a, b unsafe.Pointer) bool 29 TEXT runtime·memequal_varlen<ABIInternal>(SB),NOSPLIT,$0-17 30 #ifndef GOEXPERIMENT_regabiargs 31 MOVD a+0(FP), R0 32 MOVD b+8(FP), R1 33 #endif 34 CMP R0, R1 35 BEQ eq 36 MOVD 8(R26), R2 // compiler stores size at offset 8 in the closure 37 CBZ R2, eq 38 #ifndef GOEXPERIMENT_regabiargs 39 MOVD $ret+16(FP), R8 40 #endif 41 B memeqbody<>(SB) 42 eq: 43 MOVD $1, R0 44 #ifndef GOEXPERIMENT_regabiargs 45 MOVB R0, ret+16(FP) 46 #endif 47 RET 48 49 // input: 50 // R0: pointer a 51 // R1: pointer b 52 // R2: data len 53 #ifdef GOEXPERIMENT_regabiargs 54 // at return: result in R0 55 #else 56 // R8: address to put result 57 #endif 58 59 TEXT memeqbody<>(SB),NOSPLIT,$0 60 CMP $1, R2 61 // handle 1-byte special case for better performance 62 BEQ one 63 CMP $16, R2 64 // handle specially if length < 16 65 BLO tail 66 BIC $0x3f, R2, R3 67 CBZ R3, chunk16 68 // work with 64-byte chunks 69 ADD R3, R0, R6 // end of chunks 70 chunk64_loop: 71 VLD1.P (R0), [V0.D2, V1.D2, V2.D2, V3.D2] 72 VLD1.P (R1), [V4.D2, V5.D2, V6.D2, V7.D2] 73 VCMEQ V0.D2, V4.D2, V8.D2 74 VCMEQ V1.D2, V5.D2, V9.D2 75 VCMEQ V2.D2, V6.D2, V10.D2 76 VCMEQ V3.D2, V7.D2, V11.D2 77 VAND V8.B16, V9.B16, V8.B16 78 VAND V8.B16, V10.B16, V8.B16 79 VAND V8.B16, V11.B16, V8.B16 80 CMP R0, R6 81 VMOV V8.D[0], R4 82 VMOV V8.D[1], R5 83 CBZ R4, not_equal 84 CBZ R5, not_equal 85 BNE chunk64_loop 86 AND $0x3f, R2, R2 87 CBZ R2, equal 88 chunk16: 89 // work with 16-byte chunks 90 BIC $0xf, R2, R3 91 CBZ R3, tail 92 ADD R3, R0, R6 // end of chunks 93 chunk16_loop: 94 LDP.P 16(R0), (R4, R5) 95 LDP.P 16(R1), (R7, R9) 96 EOR R4, R7 97 CBNZ R7, not_equal 98 EOR R5, R9 99 CBNZ R9, not_equal 100 CMP R0, R6 101 BNE chunk16_loop 102 AND $0xf, R2, R2 103 CBZ R2, equal 104 tail: 105 // special compare of tail with length < 16 106 TBZ $3, R2, lt_8 107 MOVD (R0), R4 108 MOVD (R1), R5 109 EOR R4, R5 110 CBNZ R5, not_equal 111 SUB $8, R2, R6 // offset of the last 8 bytes 112 MOVD (R0)(R6), R4 113 MOVD (R1)(R6), R5 114 EOR R4, R5 115 CBNZ R5, not_equal 116 B equal 117 lt_8: 118 TBZ $2, R2, lt_4 119 MOVWU (R0), R4 120 MOVWU (R1), R5 121 EOR R4, R5 122 CBNZ R5, not_equal 123 SUB $4, R2, R6 // offset of the last 4 bytes 124 MOVWU (R0)(R6), R4 125 MOVWU (R1)(R6), R5 126 EOR R4, R5 127 CBNZ R5, not_equal 128 B equal 129 lt_4: 130 TBZ $1, R2, lt_2 131 MOVHU.P 2(R0), R4 132 MOVHU.P 2(R1), R5 133 CMP R4, R5 134 BNE not_equal 135 lt_2: 136 TBZ $0, R2, equal 137 one: 138 MOVBU (R0), R4 139 MOVBU (R1), R5 140 CMP R4, R5 141 BNE not_equal 142 equal: 143 MOVD $1, R0 144 #ifndef GOEXPERIMENT_regabiargs 145 MOVB R0, (R8) 146 #endif 147 RET 148 not_equal: 149 #ifdef GOEXPERIMENT_regabiargs 150 MOVB ZR, R0 151 #else 152 MOVB ZR, (R8) 153 #endif 154 RET