📄 fft.asm
字号:
;Fuction: 实现dif基2的复数FFT运算
.mmregs
; .cpl_on
.include "Rx_twiddle.inc"
.bss temp_fft,2
; .ref _twiddle
;//-----------------------------------------------------------------------------
;// Program section
;//-----------------------------------------------------------------------------
.sect ".fftcode"
.global _cfft
; .text
_cfft:
;//-----------------------------------------------------------------------------
;// Context save / get arguments将子程序所用寄存器进行压站保护
;//-----------------------------------------------------------------------------
PSH mmap(ST1_55)
PSH mmap(ST2_55)
AADD #-17, SP ; create local frame
MOV XAR0, dbl(*SP(#0)) ; SP(#0) is xy
MOV pair(T0), dbl(*SP(#2)) ; SP(#2) is nx, SP(#3) is scale
MOV XAR5, dbl(*SP(#4)) ; save on entry
MOV XAR6, dbl(*SP(#6)) ; save on entry
MOV XAR7, dbl(*SP(#8)) ; save on entry
MOV pair(T2), dbl(*SP(#10)) ; save on entry
; SP(#12) is tempmem
; SP(#14) is tempmem1
;//-----------------------------------------------------------------------------
;// Initialization code
;//-----------------------------------------------------------------------------
Initialize:
OR #010FH,mmap(ST2_55) ;CDP,AR0,AR1,AR2,AR3设置为循环寻址
MOV XAR0,XAR1 ;向量FFT_VECTOR.
MOV XAR0,XAR2
MOV XAR0,XAR3
MOV mmap(AR2),BSA23 ;设置BSA23
MOV mmap(AR2),BSA01 ;设置BSA01
AMOV #ctwiddle,XCDP ;CDP指向旋转因子
MOV CDP,mmap(BSAC) ;设置BSAC。 (twiddle)
MOV #0,AR1 ;AR1的初始偏移为0
MOV #0,AR2 ;AR2的初始偏移为0
MOV #2,AR3 ;AR3的初始偏移为2
MOV #0,CDP ;CDP的初始偏移为0。
AMOV #temp_fft,XAR6 ;AR6指向一个分配的临时区
MOV XAR6,XAR7 ;AR7也指向一个分配的临时区
ADD #1,AR7 ;AR7指针加1
MOV #512,T0 ;FFT变换的长度为LENGTH
MOV mmap(T0),BKC ;系数存储器的长度为LENGTH
SUB #2,T0,T1
MOV T1,CSR ;CSR循环计数器为(LENGTH-2)
MOV T0,T3
SFTL T3,#-1 ;T3=(LENGTH/2)
SUB #2,T3,T1
MOV mmap(T1),BRC0 ;外循环计数器为(LENGTH/2-2)
SFTL T0,#1
MOV mmap(T0),BK03 ;输入数据存储器的长度为2*LENGTH
MOV #4,T1
;-------------------------------------------------------------------------------
;基2(DIF)-第一级变换
;-------------------------------------------------------------------------------
MOV #0,mmap(AR0)
;MOV #1, BRC0
;RPTBLOCAL first_stage
MOV dbl(*AR0+),AC0 ;为了防止溢出,变换数据除以2
RPT CSR
MOV AC0>>#1,dual(*AR1+)
||MOV dbl(*AR0+),AC0
MOV AC0>>#1,dual(*AR1+)
first_stage: ;第一级变换开始
MOV dbl(*AR3),AC0
SUB AC0,dual(*AR2),AC2
RPTBLOCAL fftloop1
ADD dual(*AR2),AC0,AC1 ;xi+1(k)=xi(k+1)+xi(k)
||MOV AC2,dbl(*AR6)
MPY *AR6,*CDP+,AC2 ;xi+1(k+1)=(xi(k)-xi+1(k))*WN
::MPY *AR7,*CDP+,AC3 ;xi(k)-xi(k+1)
MOV AC1,dbl(*(AR2+T1)) ;保存xi+1(k)到AR2所指的k位置
MOV dbl(*AR3(T1)),AC0
MASR *AR6,*CDP+,AC3
::MACR *AR7,*CDP+,AC2
MOV pair(HI(AC2)),dbl(*(AR3+T1)) ;保存xi+1(k+1)到AR3所指的k+1位置
||SUB AC0,dual(*AR2),AC2
fftloop1:
ADD dual(*AR2), AC0, AC1
||MOV AC2, dbl(*AR6) ; store tr, ti
MPY *AR6, *CDP+, AC2 ; c*tr
::MPY *AR7, *CDP+, AC3 ; c*ti
MOV AC1, dbl(*(AR2+T1)) ; store ar, ai
MASR *AR6, *CDP+, AC3 ; bi' = c*ti - s*tr
::MACR *AR7, *CDP+, AC2 ; br' = c*tr + s*ti
MOV pair(HI(AC2)), dbl(*(AR3+T1)) ; store br', bi'
;-----------------------------------------------------------------
;基2(DIF)-除去第一级后的所有其他级变换
;-----------------------------------------------------------------
radix_2_stages:
MOV *SP(#2), AC0
||SFTS T3, #-1 ;T3=(LENGTH/4)
SFTS AC0, #-4 ; last two stage shift right by 4
||SFTS AR3, #1 ; pointer to AR3
MOV AC0, AR4
||MOV #2, T0
MOV #2, T2
outer_loop:
SUB #1,T3,T1
MOV T1, BRC0
SUB #2, T2, T1
MOV T1, BRC1
SFTS T2, #1
ADD #2, T2, T1
SFTS AR4, #-1
;------------------------------------------------------------------------------------
MOV dbl(*AR0+), AC0 ; 为了防止溢出,在每一级均需除以2
RPT CSR
MOV AC0 >> #1, dual(*AR1+)
||MOV dbl(*AR0+), AC0
MOV AC0 >> #1, dual(*AR1+)
;--------------------------------------------------------------------------------------
RPTBLOCAL fftloop2
MOV dbl(*AR3), AC0 ; load ar,ai
SUB AC0, dual(*AR2), AC2
RPTBLOCAL fftloop3
ADD dual(*AR2), AC0, AC1
||MOV AC2, dbl(*AR6)
MOV AC1, dbl(*AR2+)
||MOV dbl(*AR3(T0)), AC0 ; store tr, ti
MPY *AR6, *CDP+, AC2
::MPY *AR7, *CDP+, AC3
MASR *AR6, *CDP-, AC3 ; bi' = c*ti - s*tr
::MACR *AR7, *CDP-, AC2 ; br' = c*tr + s*ti
MOV pair(HI(AC2)), dbl(*AR3+) ; store br', bi'
||SUB AC0, dual(*AR2), AC2
fftloop3:
ADD dual(*AR2), AC0, AC1
||MOV AC2, dbl(*AR6)
MOV AC1, dbl(*(AR2+T1))
; store ar, ai ; store tr, ti
MPY *AR6, *CDP+, AC2 ; c*tr
::MPY *AR7, *CDP+, AC3 ; c*ti
MASR *AR6, *CDP+, AC3 ; bi' = c*ti - s*tr
::MACR *AR7, *CDP+, AC2 ; br' = c*tr + s*ti
MOV pair(HI(AC2)), dbl(*(AR3+T1)) ; 修改AR3的指针
fftloop2:
SFTS AR3, #1
||MOV #0, CDP ; rewind coefficient pointer
SFTS T3, #-1
||BCC outer_loop, AR4 != #0
;//-----------------------------------------------------------------------------
;// Radix-4 stage
;//-----------------------------------------------------------------------------
radix_4_stage:
BCC no_scale_4, AR5 == #0
||MOV #1, BRC0 ; 2 x scale by 2 is faster
; MOV #0,AR0 ;更新AR0的值以便进行移位运算
; RPTBLOCAL loop4-1
MOV dbl(*AR0+), AC0 ; scale by 2 - prime the pipe
RPT CSR
MOV AC0 >> #1, dual(*AR1+)
||MOV dbl(*AR0+), AC0
MOV AC0 >> #1, dual(*AR1+)
loop4:
no_scale_4:
AND #0FEF0h, mmap(ST2_55) ; linear addr for AR2, AR3, Ar1, AR0
MOV dbl(*SP(#0)), XAR0 ; point to data
MOV *SP(#2), T0
SFTS T0, #-1 ; DR0 = 2*nx/4
MOV T0, T1 ; DR1 = 2*nx/4
MOV XAR0, XAR1 ; AR1 = AR0
ADD T1, AR1 ; AR1 = AR0 + 1*2*nx/4
MOV XAR0, XAR2 ; AR2 = AR0
ADD T0, T1 ; DR1 = 2*(2*nx/4)
ADD T1, AR2 ; AR2 = AR0 + 2*2*nx/4
MOV XAR0, XAR3 ; AR3 = #fftdata
ADD T0, T1 ; DR1 = 3*(2*nx/4)
ADD T1, AR3 ; AR3 = AR0 + 3*2*nx/4
SFTL T0, #-1 ; nx/4
SUB #2, T0 ; nx/4 - 2
MOV XSP, XAR7
ADD #14, AR7 ; temp mem in local frame
; MOV mmap(T0), BRC0 ;外循环计数器没有用到
; MOV T0, AR4 ; patch because CCS1.00b does
; ADD #1, T0, AR4 ; not work with localrepeat{}
; .if $isdefed("SI_BUGS")
; MOV XAR1, XAR5
; MOV #1, T0
; .else
MOV XAR1, XAR5
MOV #1, T0
; .endif
MOV #2, T1 ;
||MOV dbl(*AR0), AC0 ; (0-in)
ADD dual(*AR1), AC0, AC2
MOV dbl(*AR2), AC1 ; (2-in)
||MOV AC2, dbl(*AR6)
SUB dual(*(AR1+T1)), AC0
; MOV #1,AR0 ;为了防止T0的错误
ADD dual(*AR3), AC1, AC3
||MOV AC0, dbl(*AR7(T0)) ; (r0-r1),(i0-i1) (unaligned)
SUB dual(*AR3), AC1
ADD dual(*AR6), AC3, AC2
||MOV AC1, T2 ; move (i2-i3)
SUB AC3, dual(*AR6), AC3
||MOV AC2, dbl(*(AR0+T1))
SUBADD T2, *AR7(T0), AC0
||MOV HI(AC1), T3 ; move (r2-r3)
ADDSUB T3, *AR7, AC1
loop_start: ; CCS1.02b - wrong result
RPTBLOCAL loop5
MOV AC3, dbl(*(AR2+T1)) ; * (2 - out)
||MOV dbl(*AR0), AC3 ; (0-in)
ADD dual(*AR1), AC3, AC2
||MOV pair(HI(AC0)), dbl(*(AR3+T1)) ; * store 3-re, 3 -im
MOV pair(LO(AC0)), dbl(*(AR5+T1)) ; * (1 - out)
||MOV dbl(*AR2), AC1 ; (2-in)
SUB dual(*(AR1+T1)), AC3
||MOV AC2, dbl(*AR6) ; store out (r0+r1),(i0+i1)
ADD dual(*AR3), AC1, AC3
||MOv AC3, dbl(*AR7(T0)) ; (r0-r1),(i0-i1) (unaligned)
SUB dual(*AR3), AC1
MOV AC1, T2 ; move (i2-i3)
||ADD dual(*AR6), AC3, AC2
SUB AC3, dual(*AR6), AC3
||MOV AC2, dbl(*(AR0+T1))
SUBADD T2, *AR7(T0), AC0
||MOV HI(AC1), T3 ; move (r2-r3)
ADDSUB T3, *AR7, AC1
loop5:
; SUB #1, AR4 ;
; BCC loop_start, AR4!=#0 ;
MOV AC3, dbl(*(AR2+T1))
MOV pair(LO(AC0)), dbl(*(AR5+T1)) ; store 1-re, 1 -im
MOV pair(HI(AC0)), dbl(*(AR3+T1)) ; store 3-re, 3 -im
;//-----------------------------------------------------------------------------
;// Context restore
;//-----------------------------------------------------------------------------
MOV dbl(*SP(#10)), pair(T2)
MOV dbl(*SP(#8)), XAR7
MOV dbl(*SP(#6)), XAR6
MOV dbl(*SP(#4)), XAR5
MOV dbl(*SP(#2)), pair(T0) ;
MOV dbl(*SP(#0)), XAR0 ;
AADD #17, SP ; destroy local frame
POP mmap(ST2_55)
POP mmap(ST1_55)
;//-----------------------------------------------------------------------------
;// Return
;//-----------------------------------------------------------------------------
RET
.end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -