@;
@; ARM code in-place dit fft subroutine.
@; 18/7/98
@;
@; Entry conditions,
@; r0 = &x      ,address of real followed by imaginary buffer
@; r1 = 0 for inverse fft
@;    = 1 (non zero) for forward fft
@;
@; stack usage,
@;  0 = &x
@;  4 = forward/inverse flag

.set npt,   1024  @; number of points
.set bits,  30    @; fractional bits in sin/cos tables
.set scale, 32-bits

    .text
    .align 2
    .global fft
fft:
@; store input parameters
    stmfd   sp!, {r4-r12,lr}      @;push return address
    sub     sp, sp, #8
    str     r0, [sp, #0]          @; [sp+0] = &xr
    add     r3, r0, #npt*4        @; &xi = &xr + npt
    str     r1, [sp, #4]          @; [sp+4] = forward/inverse flag

@; bit reverse input data

    mov     r4, #1                @;j = 1
    mov     r5, #1                @;i = 1
    sub     r0, r0, #4            @;xr index starts at 0
    sub     r3, r3, #4            @;and xi
fft_shuff1:                       @;for i=1 to npt-1
    cmp     r5, r4                @;  if (i<j)
    bge     fft_shuff2            @;
    ldr     r6, [r0, r5, lsl #2]  @;    swap
    ldr     r7, [r0, r4, lsl #2]  @;    xr(i)
    str     r6, [r0, r4, lsl #2]  @;    with
    str     r7, [r0, r5, lsl #2]  @;    xr(j)
    ldr     r6, [r3, r5, lsl #2]  @;    and
    ldr     r7, [r3, r4, lsl #2]  @;    xi(i)
    str     r6, [r3, r4, lsl #2]  @;    with
    str     r7, [r3, r5, lsl #2]  @;    xi(j)
fft_shuff2:
    mov     r6, #npt/2            @;  k=npt/2
fft_shuff3:
    cmp     r6, r4                @;  while (k<j)
    sublt   r4, r4, r6            @;    j-=k
    movlt   r6, r6, lsr #1        @;    k/=2
    blt     fft_shuff3            @;
    add     r4, r4, r6            @;  j+=k
    add     r5, r5, #1            @;next
    cmp     r5, #npt              @;
    bne     fft_shuff1            @;

@; perform fft for each stage

    mov     r11, #npt/2           @;b = n/2
    mov     r8, #1                @;g = 1
fft_loop1:                        @;do
    mov     r14, #0               @;  p = 0
    mov     r9, #1                @;  j = 1
fft_loop2:                        @;  do
    adr     r0, coeff             @;    load &cos
    add     r1, r0, #npt*2        @;    &sin = &cos + npt/2
    ldr     r0, [r0, r14, lsl #2] @;    load c=cos(p)
    ldr     r1, [r1, r14, lsl #2] @;    load s=sin(p)
    ldr     r2, [sp, #4]          @;    load forward / inverse flag
    movs    r2, r2                @;    zero set for inverse
    rsbne   r1, r1, #0            @;    s = -s (forward only)

    sub     r4, r9, #1            @;    i = j-1
    ldr     r3, [sp, #0]          @;    load &xr
    add     r2, r3, #npt*4        @;    &xi = &xr + npt
    add     r3, r3, r4, lsl #2    @;    &xr(i) = &xr+(i*4)
    add     r2, r2, r4, lsl #2    @;    &xi(i) = &xi+(i*4)
    mov     r10, r11              @;    a=b
fft_loop3:                        @;    do
    ldr     r5, [r2, r8, lsl #2]  @;      load xi(k)
    ldr     r4, [r3, r8, lsl #2]  @;      load xr(k)

    smull   r12, r7, r4, r0       @;      xr(k)*c
    smull   r12, r6, r5, r1       @;      xi(k)*s
    sub     r6, r7, r6            @;      tr=xr(k)*c-xi(k)*s
    smull   r12, r7, r4, r1       @;      xr(k)*s
    smlal   r12, r7, r5, r0       @;      ti=xi(k)*c+xr(k)*s

    ldr     r12, [sp, #4]         @;      load forward / inverse flag
    movs    r12, r12              @;      zero set for inverse

    ldr     r12, [r3]             @;      load xr(i)
    sub     r4, r12, r6, lsl #scale  @;   xr(k)=xr(i)-tr (and scale tr)
    movne   r4, r4, asr #1        @;      scale for bit growth (forward only)
    str     r4, [r3, r8, lsl #2]  @;      store xr(k)
    ldr     r4, [r2]              @;      load xi(i)
    sub     r5, r4, r7, lsl #scale   @;   xi(k)=xi(i)-ti (and scale ti)
    movne   r5, r5, asr #1        @;      scale for bit growth (forward only)
    str     r5, [r2, r8, lsl #2]  @;      store xi(k)
    add     r12, r12, r6, lsl #scale @;   xr(i)+=tr (and scale tr)
    movne   r12, r12, asr #1      @;      scale for bit growth (forward only)
    str     r12, [r3]             @;      store xr(i)
    add     r4, r4, r7, lsl #scale   @;   xi(i)+=ti (and scale ti)
    movne   r4, r4, asr #1        @;      scale for bit growth (forward only)
    str     r4, [r2]              @;      store xi(i)
    add     r3, r3, r8, lsl #3    @;      &xr(i)+=g*2
    add     r2, r2, r8, lsl #3    @;      &xi(i)+=g*2
    subs    r10, r10, #1          @;      a--
    bne     fft_loop3             @;    while (a!=0)

    add     r14, r14, r11         @;    p+=b
    add     r9, r9, #1            @;    j++
    cmp     r9, r8                @;
    ble     fft_loop2             @;  while (j<=g)

    mov     r8, r8, lsl #1        @;  g<<=1
    movs    r11, r11, lsr #1      @;  b>>=1
    bne     fft_loop1             @;while (b!=0)

    add     sp, sp, #8
    ldmfd   sp!, {r4-r12,pc}      @;return

coeff:
@; cosine table
.word 1073741823,1073721610,1073660972,1073559912,1073418432,1073236539,1073014239,1072751541,1072448454,1072104990
.word 1071721162,1071296984,1070832473,1070327645,1069782520,1069197119,1068571463,1067905575,1067199482,1066453209
.word 1065666785,1064840239,1063973602,1063066908,1062120189,1061133482,1060106825,1059040254,1057933812,1056787539
.word 1055601478,1054375675,1053110175,1051805026,1050460277,1049075979,1047652184,1046188945,1044686318,1043144359
.word 1041563126,1039942679,1038283079,1036584388,1034846670,1033069991,1031254417,1029400017,1027506861,1025575019
.word 1023604566,1021595574,1019548120,1017462280,1015338133,1013175760,1010975241,1008736659,1006460099,1004145647
.word 1001793389,999403414,996975812,994510674,992008093,989468165,986890983,984276645,981625250,978936897
.word 976211688,973449724,970651112,967815954,964944359,962036434,959092290,956112035,953095784,950043649
.word 946955746,943832190,940673100,937478594,934248792,930983816,927683790,924348836,920979081,917574652
.word 914135677,910662285,907154607,903612776,900036923,896427185,892783697,889106596,885396021,881652111
.word 877875008,874064853,870221790,866345963,862437519,858496605,854523369,850517960,846480530,842411231
.word 838310215,834177637,830013653,825818420,821592095,817334837,813046807,808728167,804379078,799999705
.word 795590212,791150766,786681533,782182683,777654383,773096805,768510121,763894503,759250124,754577160
.word 749875787,745146182,740388522,735602986,730789756,725949012,721080936,716185713,711263525,706314558
.word 701338999,696337035,691308855,686254647,681174601,676068910,670937766,665781361,660599890,655393547
.word 650162529,644907033,639627257,634323399,628995659,623644238,618269337,612871159,607449906,602005783
.word 596538995,591049747,585538247,580004702,574449320,568872310,563273882,557654248,552013618,546352205
.word 540670222,534967883,529245403,523502998,517740882,511959274,506158392,500338452,494499675,488642280
.word 482766489,476872521,470960600,465030947,459083785,453119340,447137835,441139495,435124547,429093217
.word 423045731,416982318,410903206,404808624,398698801,392573967,386434353,380280189,374111709,367929143
.word 361732725,355522688,349299266,343062693,336813204,330551034,324276419,317989595,311690799,305380267
.word 299058239,292724951,286380642,280025552,273659918,267283981,260897981,254502159,248096754,241682009
.word 235258165,228825463,222384147,215934457,209476638,203010932,196537583,190056834,183568930,177074115
.word 170572632,164064728,157550647,151030634,144504935,137973796,131437462,124896179,118350194,111799753
.word 105245103,98686490,92124163,85558366,78989349,72417357,65842639,59265442,52686014,46104602
.word 39521455,32936819,26350943,19764076,13176464,6588356,0,-6588356,-13176464,-19764076
.word -26350943,-32936819,-39521455,-46104602,-52686014,-59265442,-65842639,-72417357,-78989349,-85558366
.word -92124163,-98686490,-105245103,-111799753,-118350194,-124896179,-131437462,-137973796,-144504935,-151030634
.word -157550647,-164064728,-170572632,-177074115,-183568930,-190056834,-196537583,-203010932,-209476638,-215934457
.word -222384147,-228825463,-235258165,-241682009,-248096754,-254502159,-260897981,-267283981,-273659918,-280025552
.word -286380642,-292724951,-299058239,-305380267,-311690799,-317989595,-324276419,-330551034,-336813204,-343062693
.word -349299266,-355522688,-361732725,-367929143,-374111709,-380280189,-386434353,-392573967,-398698801,-404808624
.word -410903206,-416982318,-423045731,-429093217,-435124547,-441139495,-447137835,-453119340,-459083785,-465030947
.word -470960600,-476872521,-482766489,-488642280,-494499675,-500338452,-506158392,-511959274,-517740882,-523502998
.word -529245403,-534967883,-540670222,-546352205,-552013618,-557654248,-563273882,-568872310,-574449320,-580004702
.word -585538247,-591049747,-596538995,-602005783,-607449906,-612871159,-618269337,-623644238,-628995659,-634323399
.word -639627257,-644907033,-650162529,-655393547,-660599890,-665781361,-670937766,-676068910,-681174601,-686254647
.word -691308855,-696337035,-701338999,-706314558,-711263525,-716185713,-721080936,-725949012,-730789756,-735602986
.word -740388522,-745146182,-749875787,-754577160,-759250124,-763894503,-768510121,-773096805,-777654383,-782182683
.word -786681533,-791150766,-795590212,-799999705,-804379078,-808728167,-813046807,-817334837,-821592095,-825818420
.word -830013653,-834177637,-838310215,-842411231,-846480530,-850517960,-854523369,-858496605,-862437519,-866345963
.word -870221790,-874064853,-877875008,-881652111,-885396021,-889106596,-892783697,-896427185,-900036923,-903612776
.word -907154607,-910662285,-914135677,-917574652,-920979081,-924348836,-927683790,-930983816,-934248792,-937478594
.word -940673100,-943832190,-946955746,-950043649,-953095784,-956112035,-959092290,-962036434,-964944359,-967815954
.word -970651112,-973449724,-976211688,-978936897,-981625250,-984276645,-986890983,-989468165,-992008093,-994510674
.word -996975812,-999403414,-1001793389,-1004145647,-1006460099,-1008736659,-1010975241,-1013175760,-1015338133,-1017462280
.word -1019548120,-1021595574,-1023604566,-1025575019,-1027506861,-1029400017,-1031254417,-1033069991,-1034846670,-1036584388
.word -1038283079,-1039942679,-1041563126,-1043144359,-1044686318,-1046188945,-1047652184,-1049075979,-1050460277,-1051805026
.word -1053110175,-1054375675,-1055601478,-1056787539,-1057933812,-1059040254,-1060106825,-1061133482,-1062120189,-1063066908
.word -1063973602,-1064840239,-1065666785,-1066453209,-1067199482,-1067905575,-1068571463,-1069197119,-1069782520,-1070327645
.word -1070832473,-1071296984,-1071721162,-1072104990,-1072448454,-1072751541,-1073014239,-1073236539,-1073418432,-1073559912
.word -1073660972,-1073721610
@; sine table
.word 0,6588356,13176464,19764076,26350943,32936819,39521455,46104602,52686014,59265442
.word 65842639,72417357,78989349,85558366,92124163,98686490,105245103,111799753,118350194,124896179
.word 131437462,137973796,144504935,151030634,157550647,164064728,170572632,177074115,183568930,190056834
.word 196537583,203010932,209476638,215934457,222384147,228825463,235258165,241682009,248096754,254502159
.word 260897981,267283981,273659918,280025552,286380642,292724951,299058239,305380267,311690799,317989595
.word 324276419,330551034,336813204,343062693,349299266,355522688,361732725,367929143,374111709,380280189
.word 386434353,392573967,398698801,404808624,410903206,416982318,423045731,429093217,435124547,441139495
.word 447137835,453119340,459083785,465030947,470960600,476872521,482766489,488642280,494499675,500338452
.word 506158392,511959274,517740882,523502998,529245403,534967883,540670222,546352205,552013618,557654248
.word 563273882,568872310,574449320,580004702,585538247,591049747,596538995,602005783,607449906,612871159
.word 618269337,623644238,628995659,634323399,639627257,644907033,650162529,655393547,660599890,665781361
.word 670937766,676068910,681174601,686254647,691308855,696337035,701338999,706314558,711263525,716185713
.word 721080936,725949012,730789756,735602986,740388522,745146182,749875787,754577160,759250124,763894503
.word 768510121,773096805,777654383,782182683,786681533,791150766,795590212,799999705,804379078,808728167
.word 813046807,817334837,821592095,825818420,830013653,834177637,838310215,842411231,846480530,850517960
.word 854523369,858496605,862437519,866345963,870221790,874064853,877875008,881652111,885396021,889106596
.word 892783697,896427185,900036923,903612776,907154607,910662285,914135677,917574652,920979081,924348836
.word 927683790,930983816,934248792,937478594,940673100,943832190,946955746,950043649,953095784,956112035
.word 959092290,962036434,964944359,967815954,970651112,973449724,976211688,978936897,981625250,984276645
.word 986890983,989468165,992008093,994510674,996975812,999403414,1001793389,1004145647,1006460099,1008736659
.word 1010975241,1013175760,1015338133,1017462280,1019548120,1021595574,1023604566,1025575019,1027506861,1029400017
.word 1031254417,1033069991,1034846670,1036584388,1038283079,1039942679,1041563126,1043144359,1044686318,1046188945
.word 1047652184,1049075979,1050460277,1051805026,1053110175,1054375675,1055601478,1056787539,1057933812,1059040254
.word 1060106825,1061133482,1062120189,1063066908,1063973602,1064840239,1065666785,1066453209,1067199482,1067905575
.word 1068571463,1069197119,1069782520,1070327645,1070832473,1071296984,1071721162,1072104990,1072448454,1072751541
.word 1073014239,1073236539,1073418432,1073559912,1073660972,1073721610,1073741823,1073721610,1073660972,1073559912
.word 1073418432,1073236539,1073014239,1072751541,1072448454,1072104990,1071721162,1071296984,1070832473,1070327645
.word 1069782520,1069197119,1068571463,1067905575,1067199482,1066453209,1065666785,1064840239,1063973602,1063066908
.word 1062120189,1061133482,1060106825,1059040254,1057933812,1056787539,1055601478,1054375675,1053110175,1051805026
.word 1050460277,1049075979,1047652184,1046188945,1044686318,1043144359,1041563126,1039942679,1038283079,1036584388
.word 1034846670,1033069991,1031254417,1029400017,1027506861,1025575019,1023604566,1021595574,1019548120,1017462280
.word 1015338133,1013175760,1010975241,1008736659,1006460099,1004145647,1001793389,999403414,996975812,994510674
.word 992008093,989468165,986890983,984276645,981625250,978936897,976211688,973449724,970651112,967815954
.word 964944359,962036434,959092290,956112035,953095784,950043649,946955746,943832190,940673100,937478594
.word 934248792,930983816,927683790,924348836,920979081,917574652,914135677,910662285,907154607,903612776
.word 900036923,896427185,892783697,889106596,885396021,881652111,877875008,874064853,870221790,866345963
.word 862437519,858496605,854523369,850517960,846480530,842411231,838310215,834177637,830013653,825818420
.word 821592095,817334837,813046807,808728167,804379078,799999705,795590212,791150766,786681533,782182683
.word 777654383,773096805,768510121,763894503,759250124,754577160,749875787,745146182,740388522,735602986
.word 730789756,725949012,721080936,716185713,711263525,706314558,701338999,696337035,691308855,686254647
.word 681174601,676068910,670937766,665781361,660599890,655393547,650162529,644907033,639627257,634323399
.word 628995659,623644238,618269337,612871159,607449906,602005783,596538995,591049747,585538247,580004702
.word 574449320,568872310,563273882,557654248,552013618,546352205,540670222,534967883,529245403,523502998
.word 517740882,511959274,506158392,500338452,494499675,488642280,482766489,476872521,470960600,465030947
.word 459083785,453119340,447137835,441139495,435124547,429093217,423045731,416982318,410903206,404808624
.word 398698801,392573967,386434353,380280189,374111709,367929143,361732725,355522688,349299266,343062693
.word 336813204,330551034,324276419,317989595,311690799,305380267,299058239,292724951,286380642,280025552
.word 273659918,267283981,260897981,254502159,248096754,241682009,235258165,228825463,222384147,215934457
.word 209476638,203010932,196537583,190056834,183568930,177074115,170572632,164064728,157550647,151030634
.word 144504935,137973796,131437462,124896179,118350194,111799753,105245103,98686490,92124163,85558366
.word 78989349,72417357,65842639,59265442,52686014,46104602,39521455,32936819,26350943,19764076
.word 13176464,6588356
    .end
