1// Auto-generated file. Do not edit! 2// Template: src/f32-gemm/4x8-minmax-aarch32-neon-ld64.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_gemm_minmax_ukernel_4x8__aarch32_neon_ld64( 15// size_t mr, r0 16// size_t nc, r1 17// size_t kc, r2 -> r5 18// const uint8_t*restrict a, r3 19// size_t a_stride, sp + 96 -> (r7) 20// const void*restrict w, sp + 100 -> r9 21// uint8_t*restrict c, sp + 104 -> r11 22// size_t cm_stride, sp + 108 -> (r6) 23// size_t cn_stride, sp + 112 -> r7 24// const union xnn_f32_minmax_params params[restrict XNN_MIN_ELEMENTS(1)]) sp + 116 -> (r7) 25 26 27// inner loop registers 28 29// A0 r3 d0 30// A1 r12 d1 31// A2 r10 d2 32// A3 r0 d3 33 34// B r9 d8, d9, d10, d11 35// B d12, d13, d14, d15 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// Clamp (r5) d4 d5 d6 d7 43 44BEGIN_FUNCTION xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_ld64 45 .arm 46#ifndef __APPLE__ 47 .arch armv7-a 48 .fpu neon 49#endif 50 // Push 96 bytes 51 PUSH {r4, r5, r6, r7, r8, r9, r10, r11} // 32 52 VPUSH {d8-d15} // +64 = 96 53 54 LDR r7, [sp, 96] // a_stride 55 LDR r11, [sp, 104] // c 56 LDR r6, [sp, 108] // cm_stride 57 LDR r9, [sp, 100] // w 58 LDR r5, [sp, 116] // params 59 60 // Clamp A and C pointers 61 CMP r0, 2 // if mr >= 2 62 ADD r12, r3, r7 // a1 = a0 + a_stride 63 ADD r4, r11, r6 // c1 = c0 + cm_stride 64 MOVLO r12, r3 // a1 65 MOVLO r4, r11 // c1 66 // if mr > 2 67 ADD r10, r12, r7 // a2 = a1 + a_stride 68 ADD r8, r4, r6 // c2 = c1 + cm_stride 69 MOVLS r10, r12 // a2 70 MOVLS r8, r4 // c2 71 72 CMP r0, 4 // if mr >=4 73 ADD r0, r10, r7 // a3 = a2 + a_stride 74 ADD r6, r8, r6 // c3 = c2 + cm_stride 75 MOVLO r0, r10 // a3 76 MOVLO r6, r8 // c3 77 78 // Load min/max values 79 VLD1.32 {d4[], d5[]}, [r5]! 80 LDR r7, [sp, 112] // cn_stride 81 VLD1.32 {d6[], d7[]}, [r5] 82 830: 84 # Load initial bias from w into accumulators 85 VLDM r9!, {d16-d19} // Bias 86 SUBS r5, r2, 8 87 VMOV q10, q8 88 VMOV q11, q9 89 VMOV q12, q8 90 VMOV q13, q9 91 VMOV q14, q8 92 VMOV q15, q9 93 94 BLO 3f // less than 2 channels? 95 96 // Main loop - 2 floats of A (8 bytes) 971: 98 VLD1.32 {d0}, [r3]! // A0 99 VLDM r9!, {d8-d11} // B0 100 VLD1.32 {d1}, [r12]! // A1 101 VLD1.32 {d2}, [r10]! // A2 102 VLD1.32 {d3}, [ r0]! // A3 103 VLDM r9!, {d12-d15} // B1 104 105 VMLA.F32 q8, q4, d0[0] 106 VMLA.F32 q9, q5, d0[0] 107 VMLA.F32 q10, q4, d1[0] 108 VMLA.F32 q13, q5, d2[0] 109 VMLA.F32 q11, q5, d1[0] 110 VMLA.F32 q12, q4, d2[0] 111 VMLA.F32 q14, q4, d3[0] 112 VMLA.F32 q15, q5, d3[0] 113 VMLA.F32 q8, q6, d0[1] 114 VMLA.F32 q9, q7, d0[1] 115 VMLA.F32 q10, q6, d1[1] 116 VMLA.F32 q11, q7, d1[1] 117 SUBS r5, r5, 8 118 VMLA.F32 q12, q6, d2[1] 119 VMLA.F32 q13, q7, d2[1] 120 VMLA.F32 q14, q6, d3[1] 121 VMLA.F32 q15, q7, d3[1] 122 BHS 1b 123 124 // Is there a remainder?- 1 floats of A (4 bytes) 125 TST r5, 4 126 BNE 3f 127 1282: 129 // Clamp 130 VMAX.F32 q8, q8, q2 131 SUBS r1, r1, 8 132 VMAX.F32 q9, q9, q2 133 VMAX.F32 q10, q10, q2 134 VMAX.F32 q11, q11, q2 135 VMAX.F32 q12, q12, q2 136 VMAX.F32 q13, q13, q2 137 VMAX.F32 q14, q14, q2 138 VMAX.F32 q15, q15, q2 139 VMIN.F32 q8, q8, q3 140 VMIN.F32 q9, q9, q3 141 VMIN.F32 q10, q10, q3 142 VMIN.F32 q11, q11, q3 143 VMIN.F32 q12, q12, q3 144 VMIN.F32 q13, q13, q3 145 VMIN.F32 q14, q14, q3 146 VMIN.F32 q15, q15, q3 147 148 // Store full 4 x 8 149 BLO 4f 150 VST1.32 {d16-d19}, [r11], r7 151 SUB r0, r0, r2 152 VST1.32 {d20-d23}, [r4], r7 153 SUB r10, r10, r2 154 VST1.32 {d24-d27}, [r8], r7 155 SUB r12, r12, r2 156 VST1.32 {d28-d31}, [r6], r7 157 SUB r3, r3, r2 158 BHI 0b 159 160 VPOP {d8-d15} 161 POP {r4, r5, r6, r7, r8, r9, r10, r11} 162 BX lr 163 1643: 165 // Remainder- 1 floats of A (4 bytes) 166 VLDM r3!, {s0} // A0 167 VLDM r9!, {d8-d11} // B0 168 VLDM r12!, {s2} // A1 169 VLDM r10!, {s4} // A2 170 VLDM r0!, {s6} // A3 171 VMLA.F32 q8, q4, d0[0] 172 VMLA.F32 q9, q5, d0[0] 173 VMLA.F32 q10, q4, d1[0] 174 VMLA.F32 q11, q5, d1[0] 175 VMLA.F32 q12, q4, d2[0] 176 VMLA.F32 q13, q5, d2[0] 177 VMLA.F32 q14, q4, d3[0] 178 VMLA.F32 q15, q5, d3[0] 179 B 2b 180 181 // Store odd width 1824: 183 TST r1, 4 184 BEQ 5f 185 VST1.32 {d16-d17}, [r11]! 186 VMOV q8, q9 187 VST1.32 {d20-d21}, [r4]! 188 VMOV q10, q11 189 VST1.32 {d24-d25}, [r8]! 190 VMOV q12, q13 191 VST1.32 {d28-d29}, [r6]! 192 VMOV q14, q15 193 1945: 195 TST r1, 2 196 BEQ 6f 197 VST1.32 {d16}, [r11]! 198 VMOV d16, d17 199 VST1.32 {d20}, [r4]! 200 VMOV d20, d21 201 VST1.32 {d24}, [r8]! 202 VMOV d24, d25 203 VST1.32 {d28}, [r6]! 204 VMOV d28, d29 205 2066: 207 TST r1, 1 208 BEQ 7f 209 VST1.32 {d16[0]}, [r11] 210 VST1.32 {d20[0]}, [r4] 211 VST1.32 {d24[0]}, [r8] 212 VST1.32 {d28[0]}, [r6] 213 2147: 215 VPOP {d8-d15} 216 POP {r4, r5, r6, r7, r8, r9, r10, r11} 217 BX lr 218 219END_FUNCTION xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_ld64 220 221#ifdef __ELF__ 222.section ".note.GNU-stack","",%progbits 223#endif 224 225