test / src /cs16-fftr /cs16-fftr-asm-aarch32-neon-x4.S
Androidonnxfork's picture
Upload folder using huggingface_hub
8b7c501
raw
history blame
3.63 kB
// Copyright 2022 Google LLC
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree.
#include <xnnpack/assembly.h>
.syntax unified
// void xnn_cs16_fftr_ukernel__asm_aarch32_neon_x4(
// size_t samples, r0 (256)
// int16_t* data, r1
// const int16_t* twiddle) r2
// d8-d15, r12-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved.
// Register usage
// vilr r1 d0
// vili d1
// virr r3 d2
// viri d3
// vdiv2 d4
// vtwr r2 d6
// vtwi d7
// vacc1r q8 = vilr + virr;
// vacc1i q9 = vili + viri;
// vacc2r d0 = vilr - virr;
// vacc2i d1 = vili - viri;
// vaccr q10 (d20/d21)
// vacci q11 (d22/d23)
// voutlr q12 (vaccr + vacc1r) / 2
// voutli q13 (vacci + vacc1i) / 2
// voutrr q14 (vacc1r - vaccr) / 2
// voutri q15 (vacci - vacc1i) / 2
// unused d5, d8-d15
BEGIN_FUNCTION xnn_cs16_fftr_ukernel__asm_aarch32_neon_x4
.arm
#ifndef __APPLE__
.arch armv7-a
.fpu neon
#endif
ADD r3, r1, r0, lsl #2 // dr = data + samples * 4
VMOV.U16 q0, 0
VMVN.U16 d4, 49152 // 16383
VLD2.16 {d0[0],d1[0]}, [r1] // first value
VQRDMULH.S16 q0, q0, d4[0] // vilr /= 2
VADD.I16 d16, d0, d1 // dl[0] = vicr + vici;
VSUB.I16 d18, d0, d1 // dr[0] = vicr - vici;
VST1.32 {d16[0]}, [r1]!
VST1.32 {d18[0]}, [r3]
// Main loop of 4 cs16 value at a time
0:
SUB r3, r3, 16 // dr -= 16
VLD2.16 {d0,d1}, [r1] // load left r and i
VLD2.16 {d2,d3}, [r3] // load right r and i
VLD2.16 {d6,d7}, [r2]! // load twiddle values vtwr, vtwi
VREV64.16 q1, q1 // reverse right side
VQRDMULH.S16 q0, q0, d4[0] // vilr /= 2
VQRDMULH.S16 q1, q1, d4[0] // virr /= 2
VADDL.S16 q8, d0, d2 // vacc1r = vilr + virr;
VSUBL.S16 q9, d1, d3 // vacc1i = vili - viri;
VSUB.I16 d0, d0, d2 // vacc2r = vilr - virr;
VADD.I16 d1, d1, d3 // vacc2i = vili + viri;
VMULL.S16 q10, d0, d6 // vaccr = vacc2r * vtwr
VMULL.S16 q11, d0, d7 // vacci = vacc2r * vtwi
VMLSL.S16 q10, d1, d7 // vaccr -= vacc2i * vtwi
VMLAL.S16 q11, d1, d6 // vacci += vacc2i * vtwr
VRSHR.S32 q10, q10, 15 // (vaccr + 16384) >> 15
VRSHR.S32 q11, q11, 15 // (vacci + 16384) >> 15
VHADD.S32 q12, q10, q8 // (vaccr + vacc1r) / 2
VHADD.S32 q13, q11, q9 // (vacci + vacc1i) / 2
VHSUB.S32 q14, q8, q10 // (vacc1r - vaccr) / 2
VHSUB.S32 q15, q11, q9 // (vacci - vacc1i) / 2
VMOVN.S32 d0, q12
VMOVN.S32 d1, q13
VMOVN.S32 d2, q14
VMOVN.S32 d3, q15
SUBS r0, r0, 8 // 8 samples (left and right) per loop
VREV64.16 q1, q1 // reverse right side
VST2.16 {d0,d1}, [r1]! // store left r and i
VST2.16 {d2,d3}, [r3] // store right r and i
BHI 0b
BX lr
END_FUNCTION xnn_cs16_fftr_ukernel__asm_aarch32_neon_x4
#ifdef __ELF__
.section ".note.GNU-stack","",%progbits
#endif