/****************************************************************************/
/*	Copyright (c) 2009, Bendor Research Pty. Ltd. All rights reserved.		*/
/*	This software is released under the GNU General Public License, version	*/
/*	3, with the exemptions that 1) the header files installed by this 	 	*/
/*	package can be included in closed-source code and 2) the libraries		*/
/*	built by this package can be statically linked into a closed-source 	*/
/*	binary. See the file LICENSE for the details.							*/
/*	This software is provided "AS IS", without any warranty or guarantee.	*/
/*	By using this software you acknowledge that neither Bendor Research nor	*/
/*	any of its personnel or affiliates can be held liable for any damages,	*/
/*	including, but not limited to, loss of business, loss of money, loss of */
/*	life, loss of reputation, arising out of this software being faulty or	*/
/*	not performing as advertised, even if Bendor Research was aware of such	*/
/*	faults in the software. You use this software at your own risk, any and */
/*	all liabilities that arise out of your using this software are strictly	*/
/*	yours.																	*/
/****************************************************************************/

/*
*	This file contains a wrapper that turns the N-point 16-bit complex
*	FFT into a 2N point real-valued FFT. The complex FFT works with
*	N points in both the time and the frequency domains, this function
*	works with 2N real valued points in the time domain and N complex
*	valued points in the frequency domain.
*
*	Apart from accessing the memory in 16-bit fashion, this code is exactly
*	the same as the fft32r.S file, you can find all the comments and
*	everything there. No comments here, though.
*/

#include <chips/ARM/func.h>

/*
*	Register definitions Do *not* change them!
*/

#define	R1		r0
#define	I1		r1
#define	R2		r2
#define	I2		r3
#define	RC		r4
#define	IC		r5
#define	ML		r6
#define	MH		r7
#define	LC		r8
#define	DP		r9
#define	CP		r10
#define	N2		r11
#define	TP		r12

/*
*	Real-valued FFT, using the complex FFT as its core
*/

	afunc	fft16r
	sub		r2,r2,#1
	tst		r3,r3
	bne		1f
	stmdb	sp!,{DP-N2,lr}
	mov		DP,r0
	mov		CP,r1
	mov		N2,r2
	bl		_blm_fft16c
	stmdb	sp!,{RC-LC}
	mov		LC,#1
	mov		N2,LC,lsl N2
0:
	add		TP,DP,LC,lsl #2
	ldrsh	R1,[TP,#0]
	ldrsh	I1,[TP,#2]
	sub		TP,N2,LC
	add		TP,DP,TP,lsl #2
	ldrsh	R2,[TP,#0]
	ldrsh	I2,[TP,#2]
	sub		TP,R2,R1
	add		R1,R2,R1
	add		R2,I1,I2
	sub		I1,I1,I2
	movs	R1,R1,asr #1
	adcpl	R1,R1,#0
	movs	R2,R2,asr #1
	adcpl	R2,R2,#0
	movs	I1,I1,asr #1
	adcpl	I1,I1,#0
	movs	I2,TP,asr #1
	adcpl	I2,I2,#0
	movs	ML,LC,lsr #1
	rsb		MH,ML,N2,lsr #2
	adccs	ML,ML,N2,lsr #2
	addcs	MH,MH,N2,lsr #2
	mov		ML,ML,lsl #1
	mov		MH,MH,lsl #1
	ldrh	IC,[CP,ML]
	ldrh	RC,[CP,MH]
	mul		ML,RC,I2
	mla		ML,IC,R2,ML
	rsb		I2,I2,#0
	mul		MH,RC,R2
	mla		MH,IC,I2,MH
	movs	IC,ML,asr #15
	adcpl	IC,IC,#0
	movs	RC,MH,asr #15
	adcpl	RC,RC,#0
	sub		R2,R1,RC
	add		R1,R1,RC
	sub		I2,IC,I1
	add		I1,IC,I1
	add		TP,DP,LC,lsl #2
	strh	R1,[TP,#0]
	strh	I1,[TP,#2]
	sub		TP,N2,LC
	add		TP,DP,TP,lsl #2
	strh	R2,[TP,#0]
	strh	I2,[TP,#2]
	add		LC,LC,#1
	cmp		LC,N2,lsr #1
	blt		0b
	ldrsh	R1,[DP,#0]
	ldrsh	R2,[DP,#2]
	sub		I1,R1,R2
	add		R1,R1,R2
	movs	I1,I1,asr #1
	adcpl	I1,I1,#0
	movs	R1,R1,asr #1
	adcpl	R1,R1,#0
	strh	R1,[DP,#0]
	strh	I1,[DP,#2]
	ldmia	sp!,{RC-N2,lr}
	bx		lr
1:
	stmdb	sp!,{RC-N2,lr}
	mov		DP,r0
	mov		CP,r1
	mov		lr,r2
	mov		LC,#1
	mov		N2,LC,lsl lr
0:
	add		TP,DP,LC,lsl #2
	ldrsh	R1,[TP,#0]
	ldrsh	I1,[TP,#2]
	sub		TP,N2,LC
	add		TP,DP,TP,lsl #2
	ldrsh	R2,[TP,#0]
	ldrsh	I2,[TP,#2]
	add		TP,I1,I2
	sub		I1,I1,I2
	sub		I2,R1,R2
	add		R1,R1,R2
	rsb		R2,TP,#0
	movs	ML,LC,lsr #1
	rsb		MH,ML,N2,lsr #2
	adccs	ML,ML,N2,lsr #2
	addcs	MH,MH,N2,lsr #2
	mov		ML,ML,lsl #1
	mov		MH,MH,lsl #1
	ldrh	IC,[CP,ML]
	ldrh	RC,[CP,MH]
	mul		ML,RC,R2
	mla		ML,IC,I2,ML
	rsb		IC,IC,#0
	mul		MH,RC,I2
	mla		MH,IC,R2,MH
	movs	RC,ML,asr #15
	adcpl	RC,RC,#0
	movs	IC,MH,asr #15
	adcpl	IC,IC,#0
	sub		I2,IC,I1
	sub		R2,R1,RC
	add		R1,R1,RC
	add		I1,IC,I1
	movs	R1,R1,asr #1
	adcpl	R1,R1,#0
	movs	R2,R2,asr #1
	adcpl	R2,R2,#0
	movs	I1,I1,asr #1
	adcpl	I1,I1,#0
	movs	I2,I2,asr #1
	adcpl	I2,I2,#0
	add		TP,DP,LC,lsl #2
	strh	R1,[TP,#0]
	strh	I1,[TP,#2]
	sub		TP,N2,LC
	add		TP,DP,TP,lsl #2
	strh	R2,[TP,#0]
	strh	I2,[TP,#2]
	add		LC,LC,#1
	cmp		LC,N2,lsr #1
	blt		0b
	ldrsh	R1,[DP,#0]
	ldrsh	I1,[DP,#2]
	add		TP,R1,I1
	sub		I1,R1,I1
	strh	TP,[DP,#0]
	strh	I1,[DP,#2]
	ldmia	sp!,{RC-LC}
	mov		r0,DP
	mov		r1,CP
	mov		r2,lr
	mov		r3,#-1
	bl		_blm_fft16c
	ldmia	sp!,{DP-N2,lr}
	bx		lr
	.endfunc

