/* decode_i586_dither: asm synth with dither noise copyright ?-2007 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 Stefan Bieschewski as decode_i586.s without dither This version uses "circular" 64k dither noise. (Patch by Adrian ) Thomas learned something about assembler and the stack while making this one thread safe (removing static data). */ #include "mangle.h" .data #if !defined (__APPLE__) && !defined (__OS2__) .section .rodata #endif ALIGN8 .LC0: .long 0x0,0x40dfffc0 ALIGN8 .LC1: .long 0x0,0xc0e00000 ALIGN8 .text /* int synth_1to1_i586_asm_dither(real *bandPtr, int channel, unsigned char *out, unsigned char *buffs, int bo_and_ditherindex[2], real *decwin, real* dithernoise); */ .globl ASM_NAME(synth_1to1_i586_asm_dither) ASM_NAME(synth_1to1_i586_asm_dither): subl $16,%esp pushl %ebp pushl %edi pushl %esi pushl %ebx /* stack: 0(%esp)=%ebx 4=esi 8=edi 12=ebp 16,20,24,28=local 32=back 36=bandptr 40=channel 44=out 48=buffs 52=bo 56=decwin 60=dithernoise */ #define BANDPTR 36(%esp) #define CHANNEL 40(%esp) #define OUT 44(%esp) #define BUFFS 48(%esp) #define BO 52(%esp) #define DECWIN 56(%esp) #define DITHERNOISE 60(%esp) /*#define DITHERNOISE $(ASM_NAME(dithernoise))*/ #define LOC0 16(%esp) #define LOC1 20(%esp) #define LOC2 24(%esp) #define DITHERINDEX 28(%esp) /* During application of the dithering, we need the shifted locations because there's an additional value on the stack. */ #define DITHERNOISE2 64(%esp) #define DITHERINDEX2 32(%esp) movl BANDPTR,%eax movl OUT,%esi movl BO, %ebx movl (%ebx),%ebp /* get bo value */ movl 4(%ebx),%edi; /* get the ditherindex behind bo */ movl %edi,DITHERINDEX xorl %edi,%edi cmpl %edi,CHANNEL jne .L48 decl %ebp andl $15,%ebp movl %ebp,(%ebx) /* save bo back */ movl BUFFS,%ecx jmp .L49 .L48: /* In stereo mode , "rewind" dither pointer 32 samples , so 2nd channel */ /* has same dither values. Tested OK for mono and stereo MP2 and MP3 */ subl $128,DITHERINDEX /* better move to %edi for the two calculations? */ andl $0x0003fffc,DITHERINDEX addl $2,%esi movl BUFFS,%ecx addl $2176,%ecx .L49: /* now the call of dct64 is prepared, stuff pushed to the stack, but soon after it's removed again */ testl $1,%ebp je .L50 movl %ecx,%ebx movl %ebp,LOC0 pushl %eax movl LOC1,%edx leal (%ebx,%edx,4),%eax pushl %eax movl LOC2,%eax incl %eax andl $15,%eax leal 1088(,%eax,4),%eax addl %ebx,%eax jmp .L74 .L50: leal 1088(%ecx),%ebx leal 1(%ebp),%edx movl %edx,LOC0 pushl %eax leal 1092(%ecx,%ebp,4),%eax pushl %eax leal (%ecx,%ebp,4),%eax .L74: pushl %eax call FUNC(dct64_i386) addl $12,%esp /* Now removed the parameters. stack: 0(%esp)=%ebx 4=esi 8=edi 12=ebp 16,20,24,28=local 32=back 36=bandptr 40=channel 44=out 48=buffs 52=bo 56=decwin 60=dithernoise */ movl LOC0,%edx leal 0(,%edx,4),%edx /* movl ASM_VALUE(decwin)+64,%eax */ movl DECWIN,%eax addl $64,%eax movl %eax,%ecx subl %edx,%ecx movl $16,%ebp .L55: flds (%ecx) fmuls (%ebx) flds 4(%ecx) fmuls 4(%ebx) fxch %st(1) flds 8(%ecx) fmuls 8(%ebx) fxch %st(2) fsubrp %st,%st(1) flds 12(%ecx) fmuls 12(%ebx) fxch %st(2) faddp %st,%st(1) flds 16(%ecx) fmuls 16(%ebx) fxch %st(2) fsubrp %st,%st(1) flds 20(%ecx) fmuls 20(%ebx) fxch %st(2) faddp %st,%st(1) flds 24(%ecx) fmuls 24(%ebx) fxch %st(2) fsubrp %st,%st(1) flds 28(%ecx) fmuls 28(%ebx) fxch %st(2) faddp %st,%st(1) flds 32(%ecx) fmuls 32(%ebx) fxch %st(2) fsubrp %st,%st(1) flds 36(%ecx) fmuls 36(%ebx) fxch %st(2) faddp %st,%st(1) flds 40(%ecx) fmuls 40(%ebx) fxch %st(2) fsubrp %st,%st(1) flds 44(%ecx) fmuls 44(%ebx) fxch %st(2) faddp %st,%st(1) flds 48(%ecx) fmuls 48(%ebx) fxch %st(2) fsubrp %st,%st(1) flds 52(%ecx) fmuls 52(%ebx) fxch %st(2) faddp %st,%st(1) flds 56(%ecx) fmuls 56(%ebx) fxch %st(2) fsubrp %st,%st(1) flds 60(%ecx) fmuls 60(%ebx) fxch %st(2) subl $4,%esp faddp %st,%st(1) fxch %st(1) fsubrp %st,%st(1) addl $4,DITHERINDEX2 andl $0x0003fffc,DITHERINDEX2 movl DITHERNOISE2,%edi addl DITHERINDEX2,%edi fadds (%edi) /* fistpl and popl as a unit keep the stack unchanged */ fistpl (%esp) popl %eax cmpl $32767,%eax jg 1f cmpl $-32768,%eax jl 2f movw %ax,(%esi) jmp 4f 1: movw $32767,(%esi) jmp 3f 2: movw $-32768,(%esi) 3: /* incl %edi */ 4: .L54: addl $64,%ebx subl $-128,%ecx addl $4,%esi decl %ebp jnz .L55 flds (%ecx) fmuls (%ebx) flds 8(%ecx) fmuls 8(%ebx) flds 16(%ecx) fmuls 16(%ebx) fxch %st(2) faddp %st,%st(1) flds 24(%ecx) fmuls 24(%ebx) fxch %st(2) faddp %st,%st(1) flds 32(%ecx) fmuls 32(%ebx) fxch %st(2) faddp %st,%st(1) flds 40(%ecx) fmuls 40(%ebx) fxch %st(2) faddp %st,%st(1) flds 48(%ecx) fmuls 48(%ebx) fxch %st(2) faddp %st,%st(1) flds 56(%ecx) fmuls 56(%ebx) fxch %st(2) subl $4,%esp faddp %st,%st(1) fxch %st(1) faddp %st,%st(1) addl $4,DITHERINDEX2 andl $0x0003fffc,DITHERINDEX2 movl DITHERNOISE2,%edi addl DITHERINDEX2,%edi fadds (%edi) /* fistpl and popl as a unit keep the stack unchanged */ fistpl (%esp) popl %eax cmpl $32767,%eax jg 1f cmpl $-32768,%eax jl 2f movw %ax,(%esi) jmp 4f 1: movw $32767,(%esi) jmp 3f 2: movw $-32768,(%esi) 3: /* incl %edi */ 4: .L62: addl $-64,%ebx addl $4,%esi movl LOC0,%edx leal -128(%ecx,%edx,8),%ecx movl $15,%ebp .L68: flds -4(%ecx) fchs fmuls (%ebx) flds -8(%ecx) fmuls 4(%ebx) fxch %st(1) flds -12(%ecx) fmuls 8(%ebx) fxch %st(2) fsubrp %st,%st(1) flds -16(%ecx) fmuls 12(%ebx) fxch %st(2) fsubrp %st,%st(1) flds -20(%ecx) fmuls 16(%ebx) fxch %st(2) fsubrp %st,%st(1) flds -24(%ecx) fmuls 20(%ebx) fxch %st(2) fsubrp %st,%st(1) flds -28(%ecx) fmuls 24(%ebx) fxch %st(2) fsubrp %st,%st(1) flds -32(%ecx) fmuls 28(%ebx) fxch %st(2) fsubrp %st,%st(1) flds -36(%ecx) fmuls 32(%ebx) fxch %st(2) fsubrp %st,%st(1) flds -40(%ecx) fmuls 36(%ebx) fxch %st(2) fsubrp %st,%st(1) flds -44(%ecx) fmuls 40(%ebx) fxch %st(2) fsubrp %st,%st(1) flds -48(%ecx) fmuls 44(%ebx) fxch %st(2) fsubrp %st,%st(1) flds -52(%ecx) fmuls 48(%ebx) fxch %st(2) fsubrp %st,%st(1) flds -56(%ecx) fmuls 52(%ebx) fxch %st(2) fsubrp %st,%st(1) flds -60(%ecx) fmuls 56(%ebx) fxch %st(2) fsubrp %st,%st(1) flds (%ecx) fmuls 60(%ebx) fxch %st(2) subl $4,%esp fsubrp %st,%st(1) fxch %st(1) fsubrp %st,%st(1) addl $4,DITHERINDEX2 andl $0x0003fffc,DITHERINDEX2 movl DITHERNOISE2,%edi addl DITHERINDEX2,%edi fadds (%edi) /* fistpl and popl as a unit keep the stack unchanged */ fistpl (%esp) popl %eax cmpl $32767,%eax jg 1f cmpl $-32768,%eax jl 2f movw %ax,(%esi) jmp 4f 1: movw $32767,(%esi) jmp 3f 2: movw $-32768,(%esi) 3: /* incl %edi */ 4: .L67: addl $-64,%ebx addl $-128,%ecx addl $4,%esi decl %ebp jnz .L68 /* return ipv edi 0 in eax */ movl $0,%eax /* save ditherindex */ movl BO,%ebx movl DITHERINDEX,%esi movl %esi,4(%ebx); /* stack: 0=ebx 4=esi 8=edi 12=ebp 16,20,24,28=local 32=back 36=bandptr 40=channel 44=out 48=buffs 52=bo */ popl %ebx popl %esi popl %edi popl %ebp addl $16,%esp /* The stack must be now: 0=back 4=bandptr 8=channel 12=out 16=buffs 20=bo */ ret #if defined(PIC) && defined(__APPLE__) .section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5 L_dct64_i386: .indirect_symbol ASM_NAME(dct64_i386) hlt ; hlt ; hlt ; hlt ; hlt #endif NONEXEC_STACK