1// Auto-generated file. Do not edit! 2// Template: src/qs8-gemm/4x8c4-aarch32-neondot-ld64.S.in 3// Generator: tools/xngen 4// 5// Copyright 2021 Google LLC 6// 7// This source code is licensed under the BSD-style license found in the 8// LICENSE file in the root directory of this source tree. 9 10 11#include <xnnpack/assembly.h> 12 13.syntax unified 14 15// void xnn_qs8_gemm_minmax_rndnu_ukernel_4x8c4__aarch32_neondot_ld64( 16// size_t mr, r0 17// size_t nc, r1 18// size_t kc, r2 -> r5 19// const uint8_t*restrict a, r3 20// size_t a_stride, sp + 80 -> (r7) 21// const void*restrict w, sp + 84 -> r9 22// uint8_t*restrict c, sp + 88 -> r11 23// size_t cm_stride, sp + 92 -> (r6) 24// size_t cn_stride, sp + 96 -> r7 25// xnn_qs8_conv_minmax_params params) sp + 100 -> (r5) 26 27// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved. 28 29// Register usage 30// A0 r3 d0 31// A1 r12 d1 32// A2 r10 d2 33// A3 r0 d3 34 35// B r9 q2 q3 q4 q5 36 37// C0 r11 d16-d17 q8 d18-d19 q9 38// C1 r4 d20-d21 q10 d22-d23 q11 39// C2 r8 d24-d25 q12 d26-d27 q13 40// C3 r6 d28-d29 q14 d30-d31 q15 41 42// unused q7 43 44// params structure is 16 bytes 45// struct { 46// int32_t right_pre_shift; d12[0] 47// int32_t multiplier; d12[1] 48// int32_t right_post_shift; d13[0] 49// int16_t output_zero_point; d13[2] 50// int8_t output_min; d13[6] 51// int8_t output_max; d13[7] 52// } rndnu_neon; 53 54// iOS does not support 32 bit ARM with Neon DotProduct. 55#ifndef __APPLE__ 56BEGIN_FUNCTION xnn_qs8_gemm_minmax_rndnu_ukernel_4x8c4__aarch32_neondot_ld64 57 # Push 80 bytes 58 PUSH {r4, r5, r6, r7, r8, r9, r10, r11} // 32 59 VPUSH {d8-d13} // +48 = 80 60 61 LDR r7, [sp, 80] // a_stride 62 ADD r2, r2, 3 // kc = (kc + 3) & ~3 63 LDR r11, [sp, 88] // c 64 LDR r6, [sp, 92] // cm_stride 65 LDR r9, [sp, 84] // w 66 BIC r2, r2, 3 67 LDR r5, [sp, 100] // params 68 69 # Clamp A and C pointers 70 CMP r0, 2 // if mr >= 2 71 ADD r12, r3, r7 // a1 = a0 + a_stride 72 ADD r4, r11, r6 // c1 = c0 + cm_stride 73 MOVLO r12, r3 // a1 74 MOVLO r4, r11 // c1 75 // if mr > 2 76 ADD r10, r12, r7 // a2 = a1 + a_stride 77 ADD r8, r4, r6 // c2 = c1 + cm_stride 78 MOVLS r10, r12 // a2 79 MOVLS r8, r4 // c2 80 81 CMP r0, 4 // if mr >=4 82 ADD r0, r10, r7 // a3 = a2 + a_stride 83 ADD r6, r8, r6 // c3 = c2 + cm_stride 84 MOVLO r0, r10 // a3 85 MOVLO r6, r8 // c3 86 87 # Load params values 88 VLDM r5, {d12-d13} // RNDNU params 89 LDR r7, [sp, 96] // cn_stride 90 91 .p2align 3 920: 93 # Load initial bias from w into accumulators 94 VLDM r9!, {d16-d19} // Bias 95 SUBS r5, r2, 8 // k = kc - 8 96 VMOV q10, q8 97 VMOV q11, q9 98 VMOV q12, q8 99 VMOV q13, q9 100 VMOV q14, q8 101 VMOV q15, q9 102 BLO 3f // less than 8 channels? 103 104 # Main loop - 8 bytes of A. 105 # 16 SDOT, 4 LD64 A, 4 LD128 B 106 .p2align 3 1071: 108 VLD1.8 {d0}, [r3]! // A0 109 VLD1.8 {q2}, [r9]! // B0 110 VLD1.8 {d1}, [r12]! // A1 111 VLD1.8 {q3}, [r9]! // B1 112 VLD1.8 {d2}, [r10]! // A2 113 VLD1.8 {q4}, [r9]! // B2 114 VLD1.8 {d3}, [r0]! // A3 115 VLD1.8 {q5}, [r9]! // B3 116 SUBS r5, r5, 8 117 118 VSDOT.S8 q8, q2, d0[0] 119 VSDOT.S8 q9, q3, d0[0] 120 VSDOT.S8 q10, q2, d1[0] 121 VSDOT.S8 q11, q3, d1[0] 122 VSDOT.S8 q12, q2, d2[0] 123 VSDOT.S8 q13, q3, d2[0] 124 VSDOT.S8 q14, q2, d3[0] 125 VSDOT.S8 q15, q3, d3[0] 126 127 VSDOT.S8 q8, q4, d0[1] 128 VSDOT.S8 q9, q5, d0[1] 129 VSDOT.S8 q10, q4, d1[1] 130 VSDOT.S8 q11, q5, d1[1] 131 VSDOT.S8 q12, q4, d2[1] 132 VSDOT.S8 q13, q5, d2[1] 133 VSDOT.S8 q14, q4, d3[1] 134 VSDOT.S8 q15, q5, d3[1] 135 BHS 1b 136 137 # Is there a remainder?- 4 bytes of A 138 ADDS r5, r5, 8 139 BNE 3f 140 1412: 142 # RNDNU quantization 143 VDUP.32 q0, d12[0] // right_pre_shift 144 145 VQSHL.S32 q8, q8, q0 146 VQSHL.S32 q9, q9, q0 147 VQSHL.S32 q10, q10, q0 148 VQSHL.S32 q11, q11, q0 149 VQSHL.S32 q12, q12, q0 150 VQSHL.S32 q13, q13, q0 151 VQSHL.S32 q14, q14, q0 152 VQSHL.S32 q15, q15, q0 153 154 VDUP.32 q2, d13[0] // right_post_shift 155 156 VQDMULH.S32 q8, q8, d12[1] // multiplier 157 VQDMULH.S32 q9, q9, d12[1] 158 VQDMULH.S32 q10, q10, d12[1] 159 VQDMULH.S32 q11, q11, d12[1] 160 VQDMULH.S32 q12, q12, d12[1] 161 VQDMULH.S32 q13, q13, d12[1] 162 VQDMULH.S32 q14, q14, d12[1] 163 VQDMULH.S32 q15, q15, d12[1] 164 165 VRSHL.S32 q8, q8, q2 166 VRSHL.S32 q9, q9, q2 167 VRSHL.S32 q10, q10, q2 168 VRSHL.S32 q11, q11, q2 169 VRSHL.S32 q12, q12, q2 170 VRSHL.S32 q13, q13, q2 171 VRSHL.S32 q14, q14, q2 172 VRSHL.S32 q15, q15, q2 173 174 VDUP.16 q0, d13[2] // output_zero_point 175 176 VQMOVN.S32 d16, q8 177 VQMOVN.S32 d17, q9 178 VQMOVN.S32 d18, q10 179 VQMOVN.S32 d19, q11 180 VQMOVN.S32 d20, q12 181 VQMOVN.S32 d21, q13 182 VQMOVN.S32 d22, q14 183 VQMOVN.S32 d23, q15 184 185 VQADD.S16 q8, q8, q0 186 VQADD.S16 q9, q9, q0 187 VQADD.S16 q10, q10, q0 188 VQADD.S16 q11, q11, q0 189 190 VDUP.8 q12, d13[6] // output_min 191 192 VQMOVN.S16 d0, q8 193 VQMOVN.S16 d1, q9 194 VQMOVN.S16 d2, q10 195 VQMOVN.S16 d3, q11 196 197 VDUP.8 q13, d13[7] // output_max 198 199 VMAX.S8 q0, q0, q12 200 VMAX.S8 q1, q1, q12 201 202 SUBS r1, r1, 8 203 204 VMIN.S8 q0, q0, q13 205 VMIN.S8 q1, q1, q13 206 207 # Store full 4 x 8 208 BLO 4f 209 VST1.8 {d0}, [r11], r7 210 SUB r3, r3, r2 211 VST1.8 {d1}, [r4], r7 212 SUB r12, r12, r2 213 VST1.8 {d2}, [r8], r7 214 SUB r10, r10, r2 215 VST1.8 {d3}, [r6], r7 216 SUB r0, r0, r2 217 BHI 0b 218 219 VPOP {d8-d13} 220 POP {r4, r5, r6, r7, r8, r9, r10, r11} 221 BX lr 222 223 # Remainder- 4 bytes of A 224 .p2align 3 2253: 226 VLD1.32 {d0[0]}, [r3]! // A0 227 VLD1.32 {q2}, [r9]! // B0 228 VLD1.32 {d1[0]}, [r12]! // A1 229 VLD1.32 {q3}, [r9]! // B1 230 VLD1.32 {d2[0]}, [r10]! // A2 231 VLD1.32 {d3[0]}, [r0]! // A3 232 233 VSDOT.S8 q8, q2, d0[0] 234 VSDOT.S8 q9, q3, d0[0] 235 VSDOT.S8 q10, q2, d1[0] 236 VSDOT.S8 q11, q3, d1[0] 237 VSDOT.S8 q12, q2, d2[0] 238 VSDOT.S8 q13, q3, d2[0] 239 VSDOT.S8 q14, q2, d3[0] 240 VSDOT.S8 q15, q3, d3[0] 241 B 2b 242 243 # Store odd width 244 .p2align 3 2454: 246 TST r1, 4 247 BEQ 5f 248 VST1.32 {d0[0]}, [r11]! 249 VST1.32 {d1[0]}, [r4]! 250 VST1.32 {d2[0]}, [r8]! 251 VST1.32 {d3[0]}, [r6]! 252 VEXT.8 q0, q0, q0, 4 253 VEXT.8 q1, q1, q1, 4 2545: 255 TST r1, 2 256 BEQ 6f 257 VST1.16 {d0[0]}, [r11]! 258 VST1.16 {d1[0]}, [r4]! 259 VST1.16 {d2[0]}, [r8]! 260 VST1.16 {d3[0]}, [r6]! 261 VEXT.8 q0, q0, q0, 2 262 VEXT.8 q1, q1, q1, 2 263 2646: 265 TST r1, 1 266 BEQ 7f 267 VST1.8 {d0[0]}, [r11] 268 VST1.8 {d1[0]}, [r4] 269 VST1.8 {d2[0]}, [r8] 270 VST1.8 {d3[0]}, [r6] 271 2727: 273 VPOP {d8-d13} 274 POP {r4, r5, r6, r7, r8, r9, r10, r11} 275 BX lr 276 277END_FUNCTION xnn_qs8_gemm_minmax_rndnu_ukernel_4x8c4__aarch32_neondot_ld64 278#endif // __APPLE__ 279 280#ifdef __ELF__ 281.section ".note.GNU-stack","",%progbits 282#endif 283 284