1// Auto-generated file. Do not edit! 2// Template: src/f32-igemm/4x8-minmax-aarch32-neon-cortex-a7.S.in 3// Generator: tools/xngen 4// 5// Copyright 2019 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#include <xnnpack/assembly.h> 11 12.syntax unified 13 14// void xnn_f32_igemm_minmax_ukernel_4x8__aarch32_neon_cortex_a7( 15// size_t mr, r0 16// size_t nc, r1 17// size_t kc, r2 -> r5 -> sp + 68 18// size_t ks, r3 -> sp + 72 -> r14 19// const float**restrict a, sp + 112 -> r2 20// const void*restrict w, sp + 116 -> r9 21// uint8_t*restrict c, sp + 120 -> r11 22// size_t cm_stride, sp + 124 -> (r6) 23// size_t cn_stride, sp + 128 -> (r7) 24// size_t a_offset, sp + 132 -> (r5) 25// const float* zero, sp + 136 -> (r7) 26// minmax_params*params, sp + 140 -> (r5) 27 28// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved. 29 30// Register usage 31// A0 r3 d0 32// A1 r12 d1 33// A2 r10 d2 34// A3 r0 d3 35 36// B r9 d8, d9, d10, d11 37// B d12, d13, d14, d15 38 39// C0 r11 d16-d17 q8 d18-d19 q9 40// C1 r4 d20-d21 q10 d22-d23 q11 41// C2 r8 d24-d25 q12 d26-d27 q13 42// C3 r6 d28-d29 q14 d30-d31 q15 43 44// Clamp (r5) d4 d5 d6 d7 45 46BEGIN_FUNCTION xnn_f32_igemm_minmax_ukernel_4x8__aarch32_neon_cortex_a7 47 .arm 48#ifndef __APPLE__ 49 .arch armv7-a 50 .fpu neon 51#endif 52 # Push 112 bytes 53 # r2 will be reloaded in outer loop. r3 is ks 54 PUSH {r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, lr} // +44 55 SUB sp, sp, 4 // 4 56 VPUSH {d8-d15} // +64 = 112 57 58 LDR r11, [sp, 120] // c 59 LDR r6, [sp, 124] // cm_stride 60 LDR r2, [sp, 112] // a 61 LDR r9, [sp, 116] // w 62 LDR r5, [sp, 140] // params 63 MOV r14, r3 // p = ks 64 65 # Clamp C pointers 66 CMP r0, 2 // if mr >= 2 67 ADD r4, r11, r6 // c1 = c0 + cm_stride 68 MOVLO r4, r11 // c1 69 // if mr > 2 70 ADD r8, r4, r6 // c2 = c1 + cm_stride 71 MOVLS r8, r4 // c2 72 CMP r0, 4 // if mr >=4 73 ADD r6, r8, r6 // c3 = c2 + cm_stride 74 MOVLO r6, r8 // c3 75 76 # Load min/max values 77 VLD1.32 {d4[], d5[]}, [r5]! 78 VLD1.32 {d6[], d7[]}, [r5] 79 800: 81 # Load initial bias from w into accumulators 82 VLDM r9!, {d16-d19} // Bias 83 VMOV q10, q8 84 VMOV q11, q9 85 VMOV q12, q8 86 VMOV q13, q9 87 VMOV q14, q8 88 VMOV q15, q9 89 90 PLD [r9, 0] // Prefetch B 91 PLD [r9, 64] 92 PLD [r9, 128] 93 PLD [r9, 192] 94 PLD [r9, 256] 95 PLD [r9, 320] 96 PLD [r9, 384] 97 PLD [r9, 448] 981: 99 # Load next 4 A pointers 100 LDR r3, [r2, 0] 101 LDR r12, [r2, 4] 102 LDR r10, [r2, 8] 103 LDR r0, [r2, 12] 104 ADD r2, r2, 16 105 106 # Add a_offset 107 LDR r5, [sp, 132] // a_offset 108 LDR r7, [sp, 136] // zero 109 CMP r3, r7 // if a0 == zero 110 ADD r3, r3, r5 // a0 += a_offset 111 MOVEQ r3, r7 // a0 = zero, else += a0 + a_offset 112 CMP r12, r7 // if a1 == zero 113 ADD r12, r12, r5 // a1 += a_offset 114 MOVEQ r12, r7 // a1 = zero, else += a1 + a_offset 115 CMP r10, r7 // if a2 == zero 116 ADD r10, r10, r5 // a2 += a_offset 117 MOVEQ r10, r7 // a2 = zero, else += a2 + a_offset 118 CMP r0, r7 // if a3 == zero 119 ADD r0, r0, r5 // a3 += a_offset 120 LDR r5, [sp, 68] // kc 121 MOVEQ r0, r7 // a3 = zero, else += a3 + a_offset 122 123 PLD [r3, 0] // Prefetch A 124 PLD [r3, 64] 125 PLD [r12, 0] 126 PLD [r12, 64] 127 PLD [r10, 0] 128 PLD [r10, 64] 129 PLD [r0, 0] 130 PLD [r0, 64] 131 132 SUBS r5, r5, 8 // kc - 8 133 BLO 4f // less than 2 channels? 134 135 # Main loop - 2 floats of A (8 bytes) 1362: 137 VLD1.32 {d0}, [r3]! // A0 138 VLDM r9!, {d8-d11} // B0 139 VLD1.32 {d1}, [r12]! // A1 140 VLD1.32 {d2}, [r10]! // A2 141 VLD1.32 {d3}, [ r0]! // A3 142 VLDM r9!, {d12-d15} // B1 143 144 VMLA.F32 q8, q4, d0[0] 145 VMLA.F32 q9, q5, d0[0] 146 VMLA.F32 q10, q4, d1[0] 147 VMLA.F32 q11, q5, d1[0] 148 VMLA.F32 q12, q4, d2[0] 149 VMLA.F32 q13, q5, d2[0] 150 VMLA.F32 q14, q4, d3[0] 151 VMLA.F32 q15, q5, d3[0] 152 VMLA.F32 q8, q6, d0[1] 153 VMLA.F32 q9, q7, d0[1] 154 VMLA.F32 q10, q6, d1[1] 155 VMLA.F32 q11, q7, d1[1] 156 SUBS r5, r5, 8 157 VMLA.F32 q12, q6, d2[1] 158 VMLA.F32 q13, q7, d2[1] 159 VMLA.F32 q14, q6, d3[1] 160 VMLA.F32 q15, q7, d3[1] 161 PLD [r9, 448] // Prefetch B 162 PLD [r3, 128] // Prefetch A0 163 PLD [r12, 128] // Prefetch A1 164 PLD [r10, 128] // Prefetch A2 165 PLD [r0, 128] // Prefetch A3 166 BHS 2b 167 168 # Is there a remainder?- 1 float of A (4 bytes) 169 TST r5, 4 170 BNE 4f 171 1723: 173 # ks loop 174 SUBS r14, r14, 16 // ks -= MR * sizeof(void*) 175 BHI 1b 176 177 LDR r7, [sp, 128] // cn_stride 178 LDR r14, [sp, 72] // p = ks 179 180 # Clamp 181 VMAX.F32 q8, q8, q2 182 SUBS r1, r1, 8 183 VMAX.F32 q9, q9, q2 184 VMAX.F32 q10, q10, q2 185 VMAX.F32 q11, q11, q2 186 VMAX.F32 q12, q12, q2 187 VMAX.F32 q13, q13, q2 188 VMAX.F32 q14, q14, q2 189 VMAX.F32 q15, q15, q2 190 VMIN.F32 q8, q8, q3 191 VMIN.F32 q9, q9, q3 192 VMIN.F32 q10, q10, q3 193 VMIN.F32 q11, q11, q3 194 VMIN.F32 q12, q12, q3 195 VMIN.F32 q13, q13, q3 196 VMIN.F32 q14, q14, q3 197 VMIN.F32 q15, q15, q3 198 199 # Store full 4 x 8 200 BLO 5f 201 VST1.32 {d28-d31}, [r6], r7 202 VST1.32 {d24-d27}, [r8], r7 203 VST1.32 {d20-d23}, [r4], r7 204 VST1.32 {d16-d19}, [r11], r7 205 SUB r2, r2, r14 // a -= ks 206 BHI 0b 207 208 VPOP {d8-d15} 209 ADD sp, sp, 12 // skip pad, r2, r3 210 POP {r4, r5, r6, r7, r8, r9, r10, r11, pc} 211 2124: 213 # Remainder- 1 float of A (4 bytes) 214 VLDM r3!, {s0} // A0 215 VLDM r9!, {d8-d11} // B0 216 VLDM r12!, {s2} // A1 217 VLDM r10!, {s4} // A2 218 VLDM r0!, {s6} // A3 219 VMLA.F32 q8, q4, d0[0] 220 VMLA.F32 q9, q5, d0[0] 221 VMLA.F32 q10, q4, d1[0] 222 VMLA.F32 q11, q5, d1[0] 223 VMLA.F32 q12, q4, d2[0] 224 VMLA.F32 q13, q5, d2[0] 225 VMLA.F32 q14, q4, d3[0] 226 VMLA.F32 q15, q5, d3[0] 227 B 3b 228 229 # Store odd width 2305: 231 TST r1, 4 232 BEQ 6f 233 VST1.32 {d28-d29}, [r6]! 234 VST1.32 {d24-d25}, [r8]! 235 VMOV q14, q15 236 VMOV q12, q13 237 VST1.32 {d20-d21}, [r4]! 238 VST1.32 {d16-d17}, [r11]! 239 VMOV q10, q11 240 VMOV q8, q9 241 2426: 243 TST r1, 2 244 BEQ 7f 245 VST1.32 {d28}, [r6]! 246 VST1.32 {d24}, [r8]! 247 VMOV d28, d29 248 VMOV d24, d25 249 VST1.32 {d20}, [r4]! 250 VST1.32 {d16}, [r11]! 251 VMOV d20, d21 252 VMOV d16, d17 253 2547: 255 TST r1, 1 256 BEQ 8f 257 VST1.32 {d28[0]}, [r6]! 258 VST1.32 {d24[0]}, [r8]! 259 VST1.32 {d20[0]}, [r4]! 260 VST1.32 {d16[0]}, [r11]! 261 2628: 263 VPOP {d8-d15} 264 ADD sp, sp, 12 // skip pad, r2, r3 265 POP {r4, r5, r6, r7, r8, r9, r10, r11, pc} 266 267END_FUNCTION xnn_f32_igemm_minmax_ukernel_4x8__aarch32_neon_cortex_a7 268 269#ifdef __ELF__ 270.section ".note.GNU-stack","",%progbits 271#endif 272