1// Auto-generated file. Do not edit!
2//   Template: src/qs8-gemm/4x8-aarch32-neon-mlal-lane-cortex-a7.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_qc8_gemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_prfm_cortex_a7(
16//     size_t mr,                            r0
17//     size_t nc,                            r1
18//     size_t kc,                            (r2) -> r5
19//     const int8_t*restrict a,              r3
20//     size_t a_stride,           sp + 88 -> (r7)
21//     const void*restrict w,     sp + 92 -> r9
22//     int8_t*restrict c,         sp + 96 -> r11
23//     size_t cm_stride,          sp + 100 -> (r6)
24//     size_t cn_stride,          sp + 104 -> r7
25//     xnn_qs8_minmax_params params)  sp + 108 -> (r5)
26
27// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved.
28
29// Based on cortex_a53 microkernel but with Neon loads
30
31// Register usage
32// A0   r3  d0-d1 q0
33// A1  r12  d2-d3 q1
34// A2  r10  d4-d5 q2
35// A3   r0  d6-d7 q3
36
37// B    r9  d8-d9 q4 q5
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// Unused d15
45
46// params structure is 10 bytes
47// struct {
48//   float magic_bias;                           d12[0]
49//   int32_t magic_bias_less_output_zero_point;  d12[1]
50//   int8_t output_min;                          d13[6]
51//   int8_t output_max;                          d13[7]
52// } xnn_qs8_minmax_params.neon;
53
54BEGIN_FUNCTION xnn_qc8_gemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_prfm_cortex_a7
55        # Push 88 bytes
56        PUSH    {r4, r5, r6, r7, r8, r9, r10, r11}  // 32
57        SUB     sp, sp, 8                           // +8
58        VPUSH   {d8-d13}                            // +48 = 88
59
60        LDR     r7, [sp, 88]            // a_stride
61        LDR     r11, [sp, 96]           // c
62        LDR     r6, [sp, 100]           // cm_stride
63        LDR     r9, [sp, 92]            // w
64        LDR     r5, [sp, 108]           // params
65
66        # Clamp A and C pointers
67        CMP     r0, 2                   // if mr >= 2
68        ADD     r12, r3, r7             //   a1 = a0 + a_stride
69        ADD     r4, r11, r6             //   c1 = c0 + cm_stride
70        MOVLO   r12, r3                 // a1
71        MOVLO   r4, r11                 // c1
72                                        // if mr > 2
73        ADD     r10, r12, r7            //   a2 = a1 + a_stride
74        ADD     r8, r4, r6              //   c2 = c1 + cm_stride
75        MOVLS   r10, r12                // a2
76        MOVLS   r8, r4                  // c2
77
78        CMP     r0, 4                   // if mr >=4
79        ADD     r0, r10, r7             //   a3 = a2 + a_stride
80        ADD     r6, r8, r6              //   c3 = c2 + cm_stride
81        MOVLO   r0, r10                 // a3
82        MOVLO   r6, r8                  // c3
83
84        # Load params values
85        VLDM    r5!, {d12}              // QC8 neon params
86        VLD1.16 {d13[]}, [r5]           // output_min/max
87        LDR     r7, [sp, 104]            // cn_stride
88
89        PLD     [r9,  64]               // Prefetch B
90        PLD     [r9, 128]
91        PLD     [r9, 192]
92        PLD     [r9, 256]
93        PLD     [r9, 320]
94        PLD     [r9, 384]
95
96        .p2align 3
970:
98        # Load initial bias from w into accumulators
99        VLDM    r9!, {d16-d19}          // Bias
100        SUBS    r5, r2, 8               // k = kc - 8
101
102        VMOV    q10, q8
103        PLD     [r3,  64]               // Prefetch A
104        VMOV    q11, q9
105        PLD     [r12, 64]
106        VMOV    q12, q8
107        PLD     [r10, 64]
108        VMOV    q13, q9
109        PLD     [r0,  64]
110        VMOV    q14, q8
111        VMOV    q15, q9
112        BLO     4f                      // less than 8 channels?
113
114        // Prologue - load 4A's and B0
115        VLD1.8  {d0},  [r3]!            // A0
116        VLD1.8  {d2}, [r12]!            // A1
117        VLD1.8  {d4}, [r10]!            // A2
118        VLD1.8  {d6},  [r0]!            // A3
119        VLD1.8  {d8},  [r9]!            // B0
120
121        SUBS    r5, r5, 8               // k = k - 8
122        BLO     2f                      // less than 8 channels?
123
124        // Main loop - 8 bytes
125        // 64 bytes for weights.
126        // 5 VMOVL = 4 A and 1 B = 5 cycles
127        // 7 blocks with VLD B, VMOVL, 8 VMLA = 10 cycles
128        // 1 blocks with VLD B, VMLA = 9 cycles
129        // total = 84 cycles
130        .p2align 3
1311:
132        // Extend - 5 cycles
133        VMOVL.S8 q0, d0
134        VMOVL.S8 q4, d8
135        PLD     [r9, 448]
136        VMOVL.S8 q1, d2
137        VMOVL.S8 q2, d4
138        VMOVL.S8 q3, d6
139
140        // BLOCK 0 - 10 cycles
141        VLD1.8  {d10},  [r9]!           // B1
142        VMLAL.S16 q8, d8, d0[0]
143        VMLAL.S16 q9, d9, d0[0]
144        VMLAL.S16 q10, d8, d2[0]
145        VMLAL.S16 q11, d9, d2[0]
146        VMOVL.S8 q5, d10
147        VMLAL.S16 q12, d8, d4[0]
148        VMLAL.S16 q13, d9, d4[0]
149        VMLAL.S16 q14, d8, d6[0]
150        VMLAL.S16 q15, d9, d6[0]
151
152        // BLOCK 1 - 10 cycles
153        VLD1.8  {d8},  [r9]!            // B2
154        VMLAL.S16 q8, d10, d0[1]
155        VMLAL.S16 q9, d11, d0[1]
156        VMLAL.S16 q10, d10, d2[1]
157        VMLAL.S16 q11, d11, d2[1]
158        VMOVL.S8 q4, d8
159        VMLAL.S16 q12, d10, d4[1]
160        VMLAL.S16 q13, d11, d4[1]
161        VMLAL.S16 q14, d10, d6[1]
162        VMLAL.S16 q15, d11, d6[1]
163
164        // BLOCK 2 - 10 cycles
165        VLD1.8  {d10},  [r9]!           // B3
166        VMLAL.S16 q8, d8, d0[2]
167        VMLAL.S16 q9, d9, d0[2]
168        VMLAL.S16 q10, d8, d2[2]
169        VMLAL.S16 q11, d9, d2[2]
170        VMOVL.S8 q5, d10
171        VMLAL.S16 q12, d8, d4[2]
172        VMLAL.S16 q13, d9, d4[2]
173        VMLAL.S16 q14, d8, d6[2]
174        VMLAL.S16 q15, d9, d6[2]
175
176        // BLOCK 3 - 10 cycles
177        VLD1.8  {d8},  [r9]!            // B4
178        VMLAL.S16 q8, d10, d0[3]
179        VMLAL.S16 q9, d11, d0[3]
180        VMLAL.S16 q10, d10, d2[3]
181        VMLAL.S16 q11, d11, d2[3]
182        VLD1.8  {d0},  [r3]!            // A0
183        VMOVL.S8 q4, d8
184        VMLAL.S16 q12, d10, d4[3]
185        VMLAL.S16 q13, d11, d4[3]
186        VMLAL.S16 q14, d10, d6[3]
187        VMLAL.S16 q15, d11, d6[3]
188
189        // BLOCK 4 - 10 cycles
190        VLD1.8  {d10},  [r9]!           // B5
191        VMLAL.S16 q8, d8, d1[0]
192        VMLAL.S16 q9, d9, d1[0]
193        VMLAL.S16 q10, d8, d3[0]
194        VMLAL.S16 q11, d9, d3[0]
195        VLD1.8  {d2}, [r12]!            // A1
196        VMOVL.S8 q5, d10
197        VMLAL.S16 q12, d8, d5[0]
198        VMLAL.S16 q13, d9, d5[0]
199        VMLAL.S16 q14, d8, d7[0]
200        VMLAL.S16 q15, d9, d7[0]
201
202        // BLOCK 5 - 10 cycles
203        VLD1.8  {d8},  [r9]!            // B6
204        VMLAL.S16 q8, d10, d1[1]
205        VMLAL.S16 q9, d11, d1[1]
206        VMLAL.S16 q10, d10, d3[1]
207        VMLAL.S16 q11, d11, d3[1]
208        VLD1.8  {d4}, [r10]!            // A2
209        VMOVL.S8 q4, d8
210        VMLAL.S16 q12, d10, d5[1]
211        VMLAL.S16 q13, d11, d5[1]
212        VMLAL.S16 q14, d10, d7[1]
213        VMLAL.S16 q15, d11, d7[1]
214
215        // BLOCK 6 - 10 cycles
216        VLD1.8  {d10},  [r9]!           // B7
217        VMLAL.S16 q8, d8, d1[2]
218        VMLAL.S16 q9, d9, d1[2]
219        VMLAL.S16 q10, d8, d3[2]
220        VMLAL.S16 q11, d9, d3[2]
221        VLD1.8  {d6},  [r0]!            // A3
222        VMOVL.S8 q5, d10
223        VMLAL.S16 q12, d8, d5[2]
224        VMLAL.S16 q13, d9, d5[2]
225        VMLAL.S16 q14, d8, d7[2]
226        VMLAL.S16 q15, d9, d7[2]
227
228        // BLOCK 7 - 9 cycles
229        VLD1.8  {d8},  [r9]!            // B0
230        VMLAL.S16 q8, d10, d1[3]
231        VMLAL.S16 q9, d11, d1[3]
232        VMLAL.S16 q10, d10, d3[3]
233        VMLAL.S16 q11, d11, d3[3]
234        VMLAL.S16 q12, d10, d5[3]
235        VMLAL.S16 q13, d11, d5[3]
236        SUBS    r5, r5, 8
237        VMLAL.S16 q14, d10, d7[3]
238        VMLAL.S16 q15, d11, d7[3]
239        BHS     1b
240
241        // Epilogue
242
243        .p2align 3
2442:
245        VMOVL.S8 q0, d0
246        VMOVL.S8 q4, d8
247        VMOVL.S8 q1, d2
248        VMOVL.S8 q2, d4
249        VMOVL.S8 q3, d6
250
251        VLD1.8  {d10},  [r9]!           // B1
252        VMLAL.S16 q8, d8, d0[0]
253        VMLAL.S16 q9, d9, d0[0]
254        VMLAL.S16 q10, d8, d2[0]
255        VMLAL.S16 q11, d9, d2[0]
256        VMOVL.S8 q5, d10
257        VMLAL.S16 q12, d8, d4[0]
258        VMLAL.S16 q13, d9, d4[0]
259        VMLAL.S16 q14, d8, d6[0]
260        VMLAL.S16 q15, d9, d6[0]
261
262        VLD1.8  {d8},  [r9]!            // B2
263        VMLAL.S16 q8, d10, d0[1]
264        VMLAL.S16 q9, d11, d0[1]
265        VMLAL.S16 q10, d10, d2[1]
266        VMLAL.S16 q11, d11, d2[1]
267        VMOVL.S8 q4, d8
268        VMLAL.S16 q12, d10, d4[1]
269        VMLAL.S16 q13, d11, d4[1]
270        VMLAL.S16 q14, d10, d6[1]
271        VMLAL.S16 q15, d11, d6[1]
272
273        VLD1.8  {d10},  [r9]!           // B3
274        VMLAL.S16 q8, d8, d0[2]
275        VMLAL.S16 q9, d9, d0[2]
276        VMLAL.S16 q10, d8, d2[2]
277        VMLAL.S16 q11, d9, d2[2]
278        VMOVL.S8 q5, d10
279        VMLAL.S16 q12, d8, d4[2]
280        VMLAL.S16 q13, d9, d4[2]
281        VMLAL.S16 q14, d8, d6[2]
282        VMLAL.S16 q15, d9, d6[2]
283
284        VLD1.8  {d8},  [r9]!            // B4
285        VMLAL.S16 q8, d10, d0[3]
286        VMLAL.S16 q9, d11, d0[3]
287        VMLAL.S16 q10, d10, d2[3]
288        VMLAL.S16 q11, d11, d2[3]
289        VMOVL.S8 q4, d8
290        VMLAL.S16 q12, d10, d4[3]
291        VMLAL.S16 q13, d11, d4[3]
292        VMLAL.S16 q14, d10, d6[3]
293        VMLAL.S16 q15, d11, d6[3]
294
295        VLD1.8  {d10},  [r9]!           // B5
296        VMLAL.S16 q8, d8, d1[0]
297        VMLAL.S16 q9, d9, d1[0]
298        VMLAL.S16 q10, d8, d3[0]
299        VMLAL.S16 q11, d9, d3[0]
300        VMOVL.S8 q5, d10
301        VMLAL.S16 q12, d8, d5[0]
302        VMLAL.S16 q13, d9, d5[0]
303        VMLAL.S16 q14, d8, d7[0]
304        VMLAL.S16 q15, d9, d7[0]
305
306        VLD1.8  {d8},  [r9]!            // B6
307        VMLAL.S16 q8, d10, d1[1]
308        VMLAL.S16 q9, d11, d1[1]
309        VMLAL.S16 q10, d10, d3[1]
310        VMLAL.S16 q11, d11, d3[1]
311        VMOVL.S8 q4, d8
312        VMLAL.S16 q12, d10, d5[1]
313        VMLAL.S16 q13, d11, d5[1]
314        VMLAL.S16 q14, d10, d7[1]
315        VMLAL.S16 q15, d11, d7[1]
316
317        VLD1.8  {d10},  [r9]!           // B7
318        VMLAL.S16 q8, d8, d1[2]
319        VMLAL.S16 q9, d9, d1[2]
320        VMLAL.S16 q10, d8, d3[2]
321        VMLAL.S16 q11, d9, d3[2]
322        VMOVL.S8 q5, d10
323        VMLAL.S16 q12, d8, d5[2]
324        VMLAL.S16 q13, d9, d5[2]
325        VMLAL.S16 q14, d8, d7[2]
326        VMLAL.S16 q15, d9, d7[2]
327
328        VMLAL.S16 q8, d10, d1[3]
329        VMLAL.S16 q9, d11, d1[3]
330        VMLAL.S16 q10, d10, d3[3]
331        VMLAL.S16 q11, d11, d3[3]
332        VMLAL.S16 q12, d10, d5[3]
333        VMLAL.S16 q13, d11, d5[3]
334        ADDS    r5, r5, 8
335        VMLAL.S16 q14, d10, d7[3]
336        VMLAL.S16 q15, d11, d7[3]
337
338        # Is there a remainder?- 1-7 bytes of A
339        BNE     4f
340
3413:
342        # QC8 FP32 quantization
343        VLD1.8  {q0-q1},  [r9]!
344
345        VDUP.32 q2, d12[0]              // magic_bias
346        VDUP.32 q3, d12[1]              // magic_bias_less_output_zero_point
347
348        VCVT.F32.S32 q8,  q8
349        VCVT.F32.S32 q9,  q9
350        VCVT.F32.S32 q10, q10
351        VCVT.F32.S32 q11, q11
352        VCVT.F32.S32 q12, q12
353        VCVT.F32.S32 q13, q13
354        VCVT.F32.S32 q14, q14
355        VCVT.F32.S32 q15, q15
356
357        VMUL.F32 q8,  q8, q0            // multiplier
358        VMUL.F32 q9,  q9, q1
359        VMUL.F32 q10, q10, q0
360        VMUL.F32 q11, q11, q1
361        VMUL.F32 q12, q12, q0
362        VMUL.F32 q13, q13, q1
363        VMUL.F32 q14, q14, q0
364        VMUL.F32 q15, q15, q1
365
366        VADD.F32 q8,  q8, q2            // magic_bias
367        VADD.F32 q9,  q9, q2
368        VADD.F32 q10, q10, q2
369        VADD.F32 q11, q11, q2
370        VADD.F32 q12, q12, q2
371        VADD.F32 q13, q13, q2
372        VADD.F32 q14, q14, q2
373        VADD.F32 q15, q15, q2
374
375        VQSUB.S32 q8,  q8, q3           // magic_bias_less_output_zero_point
376        VQSUB.S32 q9,  q9, q3
377        VQSUB.S32 q10, q10, q3
378        VQSUB.S32 q11, q11, q3
379        VQSUB.S32 q12, q12, q3
380        VQSUB.S32 q13, q13, q3
381        VQSUB.S32 q14, q14, q3
382        VQSUB.S32 q15, q15, q3
383
384
385        VQMOVN.S32 d16, q8
386        VQMOVN.S32 d17, q9
387        VQMOVN.S32 d18, q10
388        VQMOVN.S32 d19, q11
389        VQMOVN.S32 d20, q12
390        VQMOVN.S32 d21, q13
391        VQMOVN.S32 d22, q14
392        VQMOVN.S32 d23, q15
393
394
395        VDUP.8  q12, d13[6]             // output_min
396
397        VQMOVN.S16 d0,  q8
398        VQMOVN.S16 d1,  q9
399        VQMOVN.S16 d2, q10
400        VQMOVN.S16 d3, q11
401
402        VDUP.8  q13, d13[7]             // output_max
403
404        VMAX.S8 q0, q0, q12
405        VMAX.S8 q1, q1, q12
406
407        SUBS    r1, r1, 8
408
409        VMIN.S8 q0, q0, q13
410        VMIN.S8 q1, q1, q13
411
412        # Store full 4 x 8
413        BLO     5f
414        VST1.8  {d0}, [r11], r7
415        SUB     r3, r3, r2
416        VST1.8  {d1}, [r4], r7
417        SUB     r12, r12, r2
418        VST1.8  {d2}, [r8], r7
419        SUB     r10, r10, r2
420        VST1.8  {d3}, [r6], r7
421        SUB     r0, r0, r2
422        BHI     0b
423
424        VPOP    {d8-d13}
425        ADD     sp, sp, 8               // skip d14
426        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
427        BX      lr
428
429        # Remainder- 1 to 7 bytes of A
430        .p2align 3
4314:
432        AND     r5, r5, 7               // kc remainder 1 to 7
433
434        VLD1.8  {d0},  [r3], r5
435        VLD1.8  {d8},  [r9]!
436        VLD1.8  {d2}, [r12], r5
437        VLD1.8  {d4}, [r10], r5
438        VLD1.8  {d6},  [r0], r5
439
440        VMOVL.S8 q0, d0
441        VMOVL.S8 q4, d8
442        VMOVL.S8 q1, d2
443        VMOVL.S8 q2, d4
444        VMOVL.S8 q3, d6
445        VMLAL.S16 q8, d8, d0[0]
446        VMLAL.S16 q9, d9, d0[0]
447        VMLAL.S16 q10, d8, d2[0]
448        VMLAL.S16 q11, d9, d2[0]
449        VMLAL.S16 q12, d8, d4[0]
450        VMLAL.S16 q13, d9, d4[0]
451        VMLAL.S16 q14, d8, d6[0]
452        VMLAL.S16 q15, d9, d6[0]
453        CMP     r5, 2
454        BLO     3b
455
456        VLD1.8  {d8},  [r9]!
457        VMOVL.S8 q4, d8
458        VMLAL.S16 q8, d8, d0[1]
459        VMLAL.S16 q9, d9, d0[1]
460        VMLAL.S16 q10, d8, d2[1]
461        VMLAL.S16 q11, d9, d2[1]
462        VMLAL.S16 q12, d8, d4[1]
463        VMLAL.S16 q13, d9, d4[1]
464        VMLAL.S16 q14, d8, d6[1]
465        VMLAL.S16 q15, d9, d6[1]
466        BEQ     3b
467
468        VLD1.8  {d8},  [r9]!
469        VMOVL.S8 q4, d8
470        VMLAL.S16 q8, d8, d0[2]
471        VMLAL.S16 q9, d9, d0[2]
472        VMLAL.S16 q10, d8, d2[2]
473        VMLAL.S16 q11, d9, d2[2]
474        VMLAL.S16 q12, d8, d4[2]
475        VMLAL.S16 q13, d9, d4[2]
476        VMLAL.S16 q14, d8, d6[2]
477        VMLAL.S16 q15, d9, d6[2]
478        CMP     r5, 4
479        BLO     3b
480
481        VLD1.8  {d8},  [r9]!
482        VMOVL.S8 q4, d8
483        VMLAL.S16 q8, d8, d0[3]
484        VMLAL.S16 q9, d9, d0[3]
485        VMLAL.S16 q10, d8, d2[3]
486        VMLAL.S16 q11, d9, d2[3]
487        VMLAL.S16 q12, d8, d4[3]
488        VMLAL.S16 q13, d9, d4[3]
489        VMLAL.S16 q14, d8, d6[3]
490        VMLAL.S16 q15, d9, d6[3]
491        BEQ     3b
492
493        VLD1.8  {d8},  [r9]!
494        VMOVL.S8 q4, d8
495        VMLAL.S16 q8, d8, d1[0]
496        VMLAL.S16 q9, d9, d1[0]
497        VMLAL.S16 q10, d8, d3[0]
498        VMLAL.S16 q11, d9, d3[0]
499        VMLAL.S16 q12, d8, d5[0]
500        VMLAL.S16 q13, d9, d5[0]
501        VMLAL.S16 q14, d8, d7[0]
502        VMLAL.S16 q15, d9, d7[0]
503        CMP     r5, 6
504        BLO     3b
505
506        VLD1.8  {d8},  [r9]!
507        VMOVL.S8 q4, d8
508        VMLAL.S16 q8, d8, d1[1]
509        VMLAL.S16 q9, d9, d1[1]
510        VMLAL.S16 q10, d8, d3[1]
511        VMLAL.S16 q11, d9, d3[1]
512        VMLAL.S16 q12, d8, d5[1]
513        VMLAL.S16 q13, d9, d5[1]
514        VMLAL.S16 q14, d8, d7[1]
515        VMLAL.S16 q15, d9, d7[1]
516        BEQ     3b
517
518        VLD1.8  {d8},  [r9]!
519        VMOVL.S8 q4, d8
520        VMLAL.S16 q8, d8, d1[2]
521        VMLAL.S16 q9, d9, d1[2]
522        VMLAL.S16 q10, d8, d3[2]
523        VMLAL.S16 q11, d9, d3[2]
524        VMLAL.S16 q12, d8, d5[2]
525        VMLAL.S16 q13, d9, d5[2]
526        VMLAL.S16 q14, d8, d7[2]
527        VMLAL.S16 q15, d9, d7[2]
528        B       3b
529
530        # Store odd width
531        .p2align 3
5325:
533        TST     r1, 4
534        BEQ     6f
535        VST1.32 {d0[0]}, [r11]!
536        VST1.32 {d1[0]}, [r4]!
537        VST1.32 {d2[0]}, [r8]!
538        VST1.32 {d3[0]}, [r6]!
539        VEXT.8  q0, q0, q0, 4
540        VEXT.8  q1, q1, q1, 4
5416:
542        TST     r1, 2
543        BEQ     7f
544        VST1.16 {d0[0]}, [r11]!
545        VST1.16 {d1[0]}, [r4]!
546        VST1.16 {d2[0]}, [r8]!
547        VST1.16 {d3[0]}, [r6]!
548        VEXT.8  q0, q0, q0, 2
549        VEXT.8  q1, q1, q1, 2
550
5517:
552        TST     r1, 1
553        BEQ     8f
554        VST1.8  {d0[0]}, [r11]
555        VST1.8  {d1[0]}, [r4]
556        VST1.8  {d2[0]}, [r8]
557        VST1.8  {d3[0]}, [r6]
558
5598:
560        VPOP    {d8-d13}
561        ADD     sp, sp, 8               // skip d14
562        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
563        BX      lr
564
565END_FUNCTION xnn_qc8_gemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_prfm_cortex_a7
566
567#ifdef __ELF__
568.section ".note.GNU-stack","",%progbits
569#endif
570
571