; Listing generated by Microsoft (R) Optimizing Compiler Version 14.00.50727.42 

	TITLE	c:\Documents and Settings\Tobi\My Documents\Visual Studio 2005\Projects\Scimark2-AMD\source\FFT.c
	.686P
	.XMM
	include listing.inc
	.model	flat

INCLUDELIB OLDNAMES

EXTRN	_printf:PROC
EXTRN	_exit:PROC
$SG-13	DB	'FFT: Data length is not a power of 2!: %d ', 00H
PUBLIC	_FFT_bitreverse
; Function compile flags: /Ogtpy
; File c:\documents and settings\tobi\my documents\visual studio 2005\projects\scimark2-amd\source\fft.c
_TEXT	SEGMENT
tv165 = -8						; size = 4
_nm1$ = -4						; size = 4
_FFT_bitreverse PROC
; _N$ = eax
; _data$ = edi

; 105  : void FFT_bitreverse(int N, double *data) {

	sub	esp, 8

; 106  :     /* This is the Goldrader bit-reversal algorithm */
; 107  :     int n=N/2;

	cdq
	push	ebx
	sub	eax, edx
	sar	eax, 1
	push	ebp

; 108  :     int nm1 = n-1;

	lea	ebp, DWORD PTR [eax-1]

; 109  :     int i=0; 

	xor	ebx, ebx

; 110  :     int j=0;

	xor	ecx, ecx

; 111  :     for (; i < nm1; i++) {

	test	ebp, ebp
	push	esi
	mov	DWORD PTR _nm1$[esp+20], ebp
	jle	SHORT $LN4@FFT_bitrev
	sar	eax, 1
	mov	DWORD PTR tv165[esp+20], eax
	jmp	SHORT $LN6@FFT_bitrev
$LL13@FFT_bitrev:

; 108  :     int nm1 = n-1;

	mov	eax, DWORD PTR tv165[esp+20]
$LN6@FFT_bitrev:

; 112  : 
; 113  :       /*int ii = 2*i; */
; 114  :       int ii = i << 1;
; 115  : 
; 116  :       /*int jj = 2*j; */
; 117  :       int jj = j << 1;
; 118  : 
; 119  :       /* int k = n / 2 ; */
; 120  :       int k = n >> 1;
; 121  : 
; 122  :       if (i < j) {

	cmp	ebx, ecx
	lea	edx, DWORD PTR [ebx+ebx]
	lea	esi, DWORD PTR [ecx+ecx]
	jge	SHORT $LN10@FFT_bitrev

; 123  :         double tmp_real    = data[ii];

	movsd	xmm0, QWORD PTR [edi+edx*8]

; 124  :         double tmp_imag    = data[ii+1];
; 125  :         data[ii]   = data[jj];

	fld	QWORD PTR [edi+esi*8]
	movsd	xmm1, QWORD PTR [edi+edx*8+8]
	fstp	QWORD PTR [edi+edx*8]

; 126  :         data[ii+1] = data[jj+1];

	fld	QWORD PTR [edi+esi*8+8]
	lea	ebp, DWORD PTR [edi+edx*8+8]
	lea	edx, DWORD PTR [edi+esi*8+8]
	fstp	QWORD PTR [ebp]

; 127  :         data[jj]   = tmp_real;
; 128  :         data[jj+1] = tmp_imag; }

	mov	ebp, DWORD PTR _nm1$[esp+20]
	movsd	QWORD PTR [edi+esi*8], xmm0
	movsd	QWORD PTR [edx], xmm1
$LN10@FFT_bitrev:

; 129  : 
; 130  :       while (k <= j) 

	cmp	eax, ecx
	jg	SHORT $LN1@FFT_bitrev
$LL2@FFT_bitrev:

; 131  :       {
; 132  :         /*j = j - k ; */
; 133  :         j -= k;

	sub	ecx, eax

; 134  : 
; 135  :         /*k = k / 2 ;  */
; 136  :         k >>= 1 ; 

	sar	eax, 1
	cmp	eax, ecx
	jle	SHORT $LL2@FFT_bitrev
$LN1@FFT_bitrev:

; 111  :     for (; i < nm1; i++) {

	add	ebx, 1

; 137  :       }
; 138  :       j += k ;

	add	ecx, eax
	cmp	ebx, ebp
	jl	SHORT $LL13@FFT_bitrev
$LN4@FFT_bitrev:

; 139  :     }
; 140  :   }

	pop	esi
	pop	ebp
	pop	ebx
	add	esp, 8
	ret	0
_FFT_bitreverse ENDP
; Function compile flags: /Ogtpy
_int_log2 PROC
; _n$ = esi

; 24   :     int k = 1;

	mov	edx, 1

; 25   :     int log = 0;

	xor	eax, eax

; 26   :     for(/*k=1*/; k < n; k *= 2, log++);

	cmp	esi, edx
	jle	SHORT $LN2@int_log2
	npad	5
$LL4@int_log2:
	add	edx, edx
	add	eax, 1
	cmp	edx, esi
	jl	SHORT $LL4@int_log2
$LN2@int_log2:

; 27   :     if (n != (1 << log))

	mov	edx, 1
	mov	ecx, eax
	shl	edx, cl
	cmp	esi, edx
	je	SHORT $LN5@int_log2

; 28   :     {
; 29   :       printf("FFT: Data length is not a power of 2!: %d ",n);

	push	esi
	push	OFFSET $SG-13
	call	_printf
	add	esp, 8

; 30   :       exit(1);

	push	1
	call	_exit
$LN5@int_log2:

; 31   :     }
; 32   :     return log; 
; 33   : }

	ret	0
$LN9@int_log2:
_int_log2 ENDP
_TEXT	ENDS
PUBLIC	__real@4014000000000000
PUBLIC	_FFT_num_flops
;	COMDAT __real@4014000000000000
CONST	SEGMENT
__real@4014000000000000 DQ 04014000000000000r	; 5
; Function compile flags: /Ogtpy
CONST	ENDS
_TEXT	SEGMENT
_FFT_num_flops PROC
; _N$ = edx

; 15   : 
; 16   :      double Nd = (double) N;
; 17   :      double logN = (double) int_log2(N);

	mov	eax, 1
	xor	ecx, ecx
	cmp	edx, eax
	cvtsi2sd xmm1, edx
	jle	SHORT $LN4@FFT_num_fl
	npad	1
$LL6@FFT_num_fl:
	add	eax, eax
	add	ecx, 1
	cmp	eax, edx
	jl	SHORT $LL6@FFT_num_fl
$LN4@FFT_num_fl:
	mov	eax, 1
	shl	eax, cl
	cmp	edx, eax
	je	SHORT $LN3@FFT_num_fl
	push	edx
	push	OFFSET $SG-13
	call	_printf
	add	esp, 8
	push	1
	call	_exit
$LN3@FFT_num_fl:

; 18   : 
; 19   :      return (5.0*Nd-2)*logN + 2*(Nd+1);

	movsd	xmm2, QWORD PTR _RESOLUTION_DEFAULT
	movapd	xmm0, xmm1
	mulsd	xmm0, QWORD PTR __real@4014000000000000
	addsd	xmm1, QWORD PTR __real@3ff0000000000000
	subsd	xmm0, xmm2
	cvtsi2sd xmm3, ecx
	mulsd	xmm0, xmm3
	mulsd	xmm1, xmm2
	addsd	xmm0, xmm1

; 20   : }

	ret	0
$LN12@FFT_num_fl:
_FFT_num_flops ENDP
PUBLIC	__real@3fe0000000000000
PUBLIC	__real@401921fb54442d18
EXTRN	___libm_sse2_sin:PROC
;	COMDAT __real@3fe0000000000000
CONST	SEGMENT
__real@3fe0000000000000 DQ 03fe0000000000000r	; 0.5
CONST	ENDS
;	COMDAT __real@401921fb54442d18
CONST	SEGMENT
__real@401921fb54442d18 DQ 0401921fb54442d18r	; 6.28319
; Function compile flags: /Ogtpy
CONST	ENDS
_TEXT	SEGMENT
_dual$ = -52						; size = 4
tv1058 = -48						; size = 4
tv1081 = -44						; size = 4
_s$3750 = -40						; size = 8
tv267 = -32						; size = 8
_theta$3748 = -24					; size = 8
_w_imag$3745 = -16					; size = 8
_w_real$3744 = -8					; size = 8
tv1027 = 8						; size = 4
_N$ = 8							; size = 4
_data$ = 12						; size = 4
_direction$ = 16					; size = 4
_FFT_transform_internal PROC

; 35   : static void FFT_transform_internal (int N, double *data, int direction) {

	sub	esp, 56					; 00000038H
	push	ebx
	push	ebp
	push	esi
	push	edi

; 36   :     int n = N/2;

	mov	edi, DWORD PTR _N$[esp+68]
	mov	eax, edi
	cdq
	sub	eax, edx
	mov	ebp, eax

; 37   :     int bit = 0;
; 38   :     int logn;
; 39   :     int dual = 1;

	mov	esi, 1
	sar	ebp, 1

; 40   : 
; 41   :     if (n == 1) return;         /* Identity operation! */

	cmp	ebp, esi
	mov	DWORD PTR _dual$[esp+72], esi
	je	$LN10@FFT_transf

; 42   :     logn = int_log2(n);

	xor	ebx, ebx
	cmp	ebp, esi
	mov	eax, esi
	jle	SHORT $LN18@FFT_transf
	npad	3
$LL20@FFT_transf:
	add	eax, eax
	add	ebx, esi
	cmp	eax, ebp
	jl	SHORT $LL20@FFT_transf
$LN18@FFT_transf:
	mov	eax, esi
	mov	ecx, ebx
	shl	eax, cl
	cmp	ebp, eax
	je	SHORT $LN17@FFT_transf
	push	ebp
	push	OFFSET $SG-13
	call	_printf
	add	esp, 8
	push	1
	call	_exit
$LN17@FFT_transf:

; 43   : 
; 44   : 
; 45   :     if (N == 0) return;    

	test	edi, edi
	je	$LN10@FFT_transf

; 46   : 
; 47   :     /* bit reverse the input data for decimation in time algorithm */
; 48   :     FFT_bitreverse(N, data) ;

	mov	edi, DWORD PTR _data$[esp+68]
	mov	eax, DWORD PTR _N$[esp+68]
	call	_FFT_bitreverse

; 49   : 
; 50   :     /* apply fft recursion */
; 51   :     /* this loop executed int_log2(N) times */
; 52   :     for (bit = 0; bit < logn; bit++, dual *= 2) {

	test	ebx, ebx
	jle	$LN10@FFT_transf
	cvtsi2sd xmm0, DWORD PTR _direction$[esp+68]
	mulsd	xmm0, QWORD PTR __real@401921fb54442d18
	movsd	QWORD PTR tv267[esp+72], xmm0
	mov	DWORD PTR tv1081[esp+72], ebx
	jmp	SHORT $LN12@FFT_transf
	npad	2
$LL34@FFT_transf:

; 46   : 
; 47   :     /* bit reverse the input data for decimation in time algorithm */
; 48   :     FFT_bitreverse(N, data) ;

	movsd	xmm0, QWORD PTR tv267[esp+72]
	mov	esi, DWORD PTR _dual$[esp+72]
$LN12@FFT_transf:

; 53   :       double w_real = 1.0;

	movsd	xmm1, QWORD PTR __real@3ff0000000000000
	movsd	QWORD PTR _w_real$3744[esp+72], xmm1

; 54   :       double w_imag = 0.0;

	xorps	xmm1, xmm1
	movsd	QWORD PTR _w_imag$3745[esp+72], xmm1

; 55   :       int a;
; 56   :       int b;
; 57   : 
; 58   :       double theta = 2.0 * direction * PI / (2.0 * (double) dual);

	cvtsi2sd xmm1, esi
	mulsd	xmm1, QWORD PTR _RESOLUTION_DEFAULT
	divsd	xmm0, xmm1
	movsd	QWORD PTR _theta$3748[esp+72], xmm0

; 59   :       double s = sin(theta);

	call	___libm_sse2_sin
	movsd	QWORD PTR _s$3750[esp+72], xmm0

; 60   :       double t = sin(theta / 2.0);

	movsd	xmm0, QWORD PTR _theta$3748[esp+72]
	mulsd	xmm0, QWORD PTR __real@3fe0000000000000
	call	___libm_sse2_sin

; 61   :       double s2 = 2.0 * t * t;

	movapd	xmm5, xmm0

; 62   : 
; 63   :       for (a=0, b = 0; b < n; b += 2 * dual) {

	xor	edi, edi
	test	ebp, ebp
	mulsd	xmm5, xmm0
	mulsd	xmm5, QWORD PTR _RESOLUTION_DEFAULT
	jle	SHORT $LN7@FFT_transf
	mov	eax, DWORD PTR _data$[esp+68]
	lea	ebx, DWORD PTR [esi+esi]
	mov	ecx, esi
	mov	edx, ebx
	shl	ecx, 4
	shl	edx, 4
	add	ecx, eax
	npad	2
$LL9@FFT_transf:

; 64   :         int i = 2*b ;
; 65   :         int j = 2*(b + dual);
; 66   : 
; 67   :         double wd_real = data[j] ;

	movsd	xmm0, QWORD PTR [ecx]

; 68   :         double wd_imag = data[j+1] ;
; 69   :           
; 70   :         data[j]   = data[i]   - wd_real;

	movsd	xmm2, QWORD PTR [eax]
	movsd	xmm1, QWORD PTR [ecx+8]
	subsd	xmm2, xmm0
	movsd	QWORD PTR [ecx], xmm2

; 71   :         data[j+1] = data[i+1] - wd_imag;

	movsd	xmm2, QWORD PTR [eax+8]
	subsd	xmm2, xmm1
	movsd	QWORD PTR [ecx+8], xmm2

; 72   :         data[i]  += wd_real;

	addsd	xmm0, QWORD PTR [eax]
	movsd	QWORD PTR [eax], xmm0

; 73   :         data[i+1]+= wd_imag;

	movsd	xmm0, QWORD PTR [eax+8]
	addsd	xmm0, xmm1
	movsd	QWORD PTR [eax+8], xmm0
	add	edi, ebx
	add	ecx, edx
	add	eax, edx
	cmp	edi, ebp
	jl	SHORT $LL9@FFT_transf
$LN7@FFT_transf:

; 74   :       }
; 75   :       
; 76   :       /* a = 1 .. (dual-1) */
; 77   :       for (a = 1; a < dual; a++) {

	cmp	esi, 1
	jle	$LN11@FFT_transf
	mov	eax, DWORD PTR _data$[esp+68]
	movsd	xmm6, QWORD PTR _w_imag$3745[esp+72]
	movsd	xmm4, QWORD PTR _w_real$3744[esp+72]
	movsd	xmm0, QWORD PTR _s$3750[esp+72]
	lea	edi, DWORD PTR [esi+1]
	lea	ecx, DWORD PTR [eax+16]
	shl	edi, 4
	lea	edx, DWORD PTR [esi-1]
	mov	DWORD PTR tv1027[esp+68], ecx
	add	edi, eax
	mov	DWORD PTR tv1058[esp+72], edx
	npad	8
$LL6@FFT_transf:

; 78   :         /* trignometric recurrence for w-> exp(i theta) w */
; 79   :         {
; 80   :           double tmp_real = w_real - s * w_imag - s2 * w_real;
; 81   :           double tmp_imag = w_imag + s * w_real - s2 * w_imag;

	movapd	xmm3, xmm0
	mulsd	xmm3, xmm4
	addsd	xmm3, xmm6
	movapd	xmm1, xmm5
	mulsd	xmm1, xmm6
	subsd	xmm3, xmm1
	movapd	xmm1, xmm0
	mulsd	xmm1, xmm6
	movapd	xmm2, xmm4
	subsd	xmm2, xmm1
	movapd	xmm1, xmm5
	mulsd	xmm1, xmm4

; 82   :           w_real = tmp_real;
; 83   :           w_imag = tmp_imag;
; 84   :         }
; 85   :         for (b = 0; b < n; b += 2 * dual) {

	xor	ebx, ebx
	test	ebp, ebp
	subsd	xmm2, xmm1
	movapd	xmm4, xmm2
	movapd	xmm6, xmm3
	jle	$LN5@FFT_transf
	mov	eax, DWORD PTR tv1027[esp+68]
	add	esi, esi
	mov	edx, esi
	shl	edx, 4
	mov	ecx, edi
$LL3@FFT_transf:

; 86   :           int i = 2*(b + a);
; 87   :           int j = 2*(b + a + dual);
; 88   : 
; 89   :           double z1_real = data[j];

	movsd	xmm0, QWORD PTR [ecx]

; 90   :           double z1_imag = data[j+1];

	movsd	xmm2, QWORD PTR [ecx+8]

; 91   :               
; 92   :           double wd_real = w_real * z1_real - w_imag * z1_imag;

	movapd	xmm7, xmm2

; 93   :           double wd_imag = w_real * z1_imag + w_imag * z1_real;

	mulsd	xmm2, xmm4
	movapd	xmm1, xmm0
	mulsd	xmm1, xmm4
	mulsd	xmm0, xmm3
	addsd	xmm0, xmm2

; 94   : 
; 95   :           data[j]   = data[i]   - wd_real;

	movsd	xmm2, QWORD PTR [eax]
	mulsd	xmm7, xmm3
	subsd	xmm1, xmm7
	subsd	xmm2, xmm1
	movsd	QWORD PTR [ecx], xmm2

; 96   :           data[j+1] = data[i+1] - wd_imag;

	movsd	xmm2, QWORD PTR [eax+8]
	subsd	xmm2, xmm0
	movsd	QWORD PTR [ecx+8], xmm2

; 97   :           data[i]  += wd_real;

	movsd	xmm2, QWORD PTR [eax]
	addsd	xmm2, xmm1

; 98   :           data[i+1]+= wd_imag;

	movsd	xmm1, QWORD PTR [eax+8]
	addsd	xmm1, xmm0
	movsd	QWORD PTR [eax], xmm2
	movsd	QWORD PTR [eax+8], xmm1
	add	ebx, esi
	add	eax, edx
	add	ecx, edx
	cmp	ebx, ebp
	jl	SHORT $LL3@FFT_transf
	movsd	xmm0, QWORD PTR _s$3750[esp+72]
	mov	esi, DWORD PTR _dual$[esp+72]
$LN5@FFT_transf:
	add	DWORD PTR tv1027[esp+68], 16		; 00000010H
	add	edi, 16					; 00000010H
	sub	DWORD PTR tv1058[esp+72], 1
	jne	$LL6@FFT_transf
$LN11@FFT_transf:

; 49   : 
; 50   :     /* apply fft recursion */
; 51   :     /* this loop executed int_log2(N) times */
; 52   :     for (bit = 0; bit < logn; bit++, dual *= 2) {

	sub	DWORD PTR tv1081[esp+72], 1
	lea	eax, DWORD PTR [esi+esi]
	mov	DWORD PTR _dual$[esp+72], eax
	jne	$LL34@FFT_transf
$LN10@FFT_transf:

; 99   :         }
; 100  :       }
; 101  :     }
; 102  :   }

	pop	edi
	pop	esi
	pop	ebp
	pop	ebx
	add	esp, 56					; 00000038H
	ret	0
$LN35@FFT_transf:
_FFT_transform_internal ENDP
_TEXT	ENDS
PUBLIC	_FFT_inverse
; Function compile flags: /Ogtpy
_TEXT	SEGMENT
_FFT_inverse PROC
; _N$ = esi
; _data$ = edi

; 150  : {

	push	ecx

; 151  :     int n = N/2;
; 152  :     double norm = 0.0;
; 153  :     int i=0;
; 154  :     FFT_transform_internal(N, data, +1);

	push	1
	push	edi
	push	esi
	call	_FFT_transform_internal

; 155  : 
; 156  :     /* Normalize */
; 157  : 
; 158  : 
; 159  :     norm=1/((double) n);

	movsd	xmm0, QWORD PTR __real@3ff0000000000000
	mov	eax, esi
	cdq
	sub	eax, edx
	sar	eax, 1
	add	esp, 12					; 0000000cH

; 160  :     for(i=0; i<N; i++)

	xor	ecx, ecx
	cmp	esi, 4
	cvtsi2sd xmm1, eax
	divsd	xmm0, xmm1
	jl	SHORT $LC9@FFT_invers
	lea	edx, DWORD PTR [esi-4]
	shr	edx, 2
	add	edx, 1
	lea	eax, DWORD PTR [edi+16]
	lea	ecx, DWORD PTR [edx*4]
	npad	2
$LL10@FFT_invers:

; 161  :       data[i] *= norm;

	movsd	xmm1, QWORD PTR [eax-16]
	mulsd	xmm1, xmm0
	movsd	QWORD PTR [eax-16], xmm1
	movsd	xmm1, QWORD PTR [eax-8]
	mulsd	xmm1, xmm0
	movsd	QWORD PTR [eax-8], xmm1
	movsd	xmm1, QWORD PTR [eax]
	mulsd	xmm1, xmm0
	movsd	QWORD PTR [eax], xmm1
	movapd	xmm1, xmm0
	mulsd	xmm1, QWORD PTR [eax+8]
	movsd	QWORD PTR [eax+8], xmm1
	add	eax, 32					; 00000020H
	sub	edx, 1
	jne	SHORT $LL10@FFT_invers
$LC9@FFT_invers:

; 160  :     for(i=0; i<N; i++)

	cmp	ecx, esi
	jge	SHORT $LN8@FFT_invers
$LC3@FFT_invers:

; 161  :       data[i] *= norm;

	movsd	xmm1, QWORD PTR [edi+ecx*8]
	mulsd	xmm1, xmm0
	movsd	QWORD PTR [edi+ecx*8], xmm1
	add	ecx, 1
	cmp	ecx, esi
	jl	SHORT $LC3@FFT_invers
$LN8@FFT_invers:
	pop	ecx

; 162  :   
; 163  : }

	ret	0
_FFT_inverse ENDP
_TEXT	ENDS
PUBLIC	_FFT_transform
; Function compile flags: /Ogtpy
_TEXT	SEGMENT
_FFT_transform PROC
; _N$ = ecx
; _data$ = eax

; 144  : {

	push	ecx

; 145  :     FFT_transform_internal(N, data, -1);

	push	-1
	push	eax
	push	ecx
	call	_FFT_transform_internal
	add	esp, 12					; 0000000cH
	pop	ecx

; 146  : }

	ret	0
_FFT_transform ENDP
END
