/*
	synth_neon_float: ARM NEON optimized synth (float output version)

	copyright 1995-2010 by the mpg123 project - free software under the terms of the LGPL 2.1
	see COPYING and AUTHORS files in distribution or http://mpg123.org
	initially written by Taihei Monma
*/

#include "mangle.h"

#define WINDOW r0
#define B0 r1
#define SAMPLES r2

/*
	int synth_1to1_real_neon_asm(real *window, real *b0, real *samples, int bo1);
	return value: number of clipped samples (0)
*/

#ifndef _M_ARM
	.code 32
#endif
#ifndef __APPLE__
	.fpu neon
#endif

	.text
	GLOBAL_SYMBOL ASM_NAME(INT123_synth_1to1_real_neon_asm)
#ifdef __ELF__
	.type ASM_NAME(INT123_synth_1to1_real_neon_asm), %function
#endif
	ALIGN4
ASM_NAME(INT123_synth_1to1_real_neon_asm):
	push		{r4-r5, lr}
	vpush		{q4-q7}

	add			WINDOW, WINDOW, #64
	sub			WINDOW, WINDOW, r3, lsl #2

	mov			r3, #4
	mov			r4, #128
	mov			r5, #64
1:
	vld1.32		{q0,q1}, [WINDOW], r4
	vld1.32		{q2,q3}, [WINDOW], r4
	vld1.32		{q4,q5}, [WINDOW], r4
	vld1.32		{q6,q7}, [WINDOW]
	sub			WINDOW, WINDOW, #352
	vld1.32		{q8,q9}, [B0, :128], r5
	vld1.32		{q10,q11}, [B0, :128], r5
	vld1.32		{q12,q13}, [B0, :128], r5
	vld1.32		{q14,q15}, [B0, :128]
	vswp		q1, q4
	vswp		q3, q6
	sub			B0, B0, #160
	vmul.f32	q0, q0, q8
	vmul.f32	q2, q2, q10
	vmul.f32	q1, q1, q12
	vmul.f32	q3, q3, q14
	vmla.f32	q0, q4, q9
	vmla.f32	q2, q6, q11
	vmla.f32	q1, q5, q13
	vmla.f32	q3, q7, q15
	vld1.32		{q4,q5}, [WINDOW], r4
	vld1.32		{q6,q7}, [WINDOW], r4
	vld1.32		{q8,q9}, [WINDOW], r4
	vld1.32		{q10,q11}, [B0, :128], r5
	vld1.32		{q12,q13}, [B0, :128], r5
	vld1.32		{q14,q15}, [B0, :128], r5
	vswp		q5, q6
	vswp		q11, q12
	vmla.f32	q0, q4, q10
	vmla.f32	q2, q5, q11
	vmla.f32	q1, q8, q14
	vld1.32		{q4,q5}, [WINDOW]
	vld1.32		{q10,q11}, [B0, :128]!
	add			WINDOW, WINDOW, #96
	vmla.f32	q3, q4, q10
	vmla.f32	q0, q6, q12
	vmla.f32	q2, q7, q13
	vmla.f32	q1, q9, q15
	vmla.f32	q3, q5, q11
	vld2.32		{q4,q5}, [SAMPLES]
	vpadd.f32	d0, d0, d1
	vpadd.f32	d4, d4, d5
	vpadd.f32	d2, d2, d3
	vpadd.f32	d6, d6, d7
	vpadd.f32	d0, d0, d4
	vpadd.f32	d1, d2, d6

	vmov.i32	q1, #0x38000000
	vmul.f32	q4, q0, q1
	vst2.32		{q4,q5}, [SAMPLES]!

	subs		r3, r3, #1
	bne			1b

	mov			r3, #4
	mov			r5, #-64
1:
	vld1.32		{q0,q1}, [WINDOW], r4
	vld1.32		{q2,q3}, [WINDOW], r4
	vld1.32		{q4,q5}, [WINDOW], r4
	vld1.32		{q6,q7}, [WINDOW]
	sub			WINDOW, WINDOW, #352
	vld1.32		{q8,q9}, [B0, :128], r5
	vld1.32		{q10,q11}, [B0, :128], r5
	vld1.32		{q12,q13}, [B0, :128], r5
	vld1.32		{q14,q15}, [B0, :128]
	vswp		q1, q4
	vswp		q3, q6
	add			B0, B0, #224
	vmul.f32	q0, q0, q8
	vmul.f32	q2, q2, q10
	vmul.f32	q1, q1, q12
	vmul.f32	q3, q3, q14
	vmla.f32	q0, q4, q9
	vmla.f32	q2, q6, q11
	vmla.f32	q1, q5, q13
	vmla.f32	q3, q7, q15
	vld1.32		{q4,q5}, [WINDOW], r4
	vld1.32		{q6,q7}, [WINDOW], r4
	vld1.32		{q8,q9}, [WINDOW], r4
	vld1.32		{q10,q11}, [B0, :128], r5
	vld1.32		{q12,q13}, [B0, :128], r5
	vld1.32		{q14,q15}, [B0, :128], r5
	vswp		q5, q6
	vswp		q11, q12
	vmla.f32	q0, q4, q10
	vmla.f32	q2, q5, q11
	vmla.f32	q1, q8, q14
	vld1.32		{q4,q5}, [WINDOW]
	vld1.32		{q10,q11}, [B0, :128]
	add			WINDOW, WINDOW, #96
	sub			B0, B0, #96
	vmla.f32	q3, q4, q10
	vmla.f32	q0, q6, q12
	vmla.f32	q2, q7, q13
	vmla.f32	q1, q9, q15
	vmla.f32	q3, q5, q11
	vld2.32		{q4,q5}, [SAMPLES]
	vpadd.f32	d0, d0, d1
	vpadd.f32	d4, d4, d5
	vpadd.f32	d2, d2, d3
	vpadd.f32	d6, d6, d7
	vpadd.f32	d0, d0, d4
	vpadd.f32	d1, d2, d6

	vmov.i32	q1, #0x38000000
	vmul.f32	q4, q0, q1
	vst2.32		{q4,q5}, [SAMPLES]!

	subs		r3, r3, #1
	bne			1b

	mov			r0, #0

	vpop		{q4-q7}
	pop			{r4-r5, pc}

NONEXEC_STACK
