Cth converted the MMX audio mixing routines to VC++ syntax
authorSam Lantinga
Mon, 20 Jan 2003 16:01:20 +0000
changeset 57464fe373be3dc
parent 573 6c3fa3b5e397
child 575 1f6438c8df2c
Cth converted the MMX audio mixing routines to VC++ syntax
src/audio/Makefile.am
src/audio/SDL_mixer.c
src/audio/SDL_mixer_MMX_VC.c
src/audio/SDL_mixer_MMX_VC.h
     1.1 --- a/src/audio/Makefile.am	Mon Jan 20 02:34:04 2003 +0000
     1.2 +++ b/src/audio/Makefile.am	Mon Jan 20 16:01:20 2003 +0000
     1.3 @@ -24,7 +24,9 @@
     1.4  	SDL_wave.c		\
     1.5  	SDL_wave.h              \
     1.6  	SDL_mixer_MMX.c         \
     1.7 -	SDL_mixer_MMX.h
     1.8 +	SDL_mixer_MMX.h		\
     1.9 +	SDL_mixer_MMX_VC.c	\
    1.10 +	SDL_mixer_MMX_VC.h
    1.11  
    1.12  libaudio_la_SOURCES = $(COMMON_SRCS)
    1.13  libaudio_la_LIBADD = $(DRIVERS)
     2.1 --- a/src/audio/SDL_mixer.c	Mon Jan 20 02:34:04 2003 +0000
     2.2 +++ b/src/audio/SDL_mixer.c	Mon Jan 20 16:01:20 2003 +0000
     2.3 @@ -36,6 +36,7 @@
     2.4  #include "SDL_timer.h"
     2.5  #include "SDL_sysaudio.h"
     2.6  #include "SDL_mixer_MMX.h"
     2.7 +#include "SDL_mixer_MMX_VC.h"
     2.8  
     2.9  /* Function to check the CPU flags */
    2.10  #define MMX_CPU		0x800000
    2.11 @@ -147,7 +148,6 @@
    2.12  		break;
    2.13  
    2.14  		case AUDIO_S8: {
    2.15 -
    2.16  #if defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT)
    2.17  			if (CPU_Flags() & MMX_CPU)
    2.18  			{
    2.19 @@ -155,6 +155,13 @@
    2.20  			}
    2.21  			else
    2.22  #endif
    2.23 +#if defined(USE_ASM_MIXER_VC)
    2.24 +			if (SDL_IsMMX_VC())
    2.25 +			{
    2.26 +				SDL_MixAudio_MMX_S8_VC((char*)dst,(char*)src,(unsigned int)len,(int)volume);
    2.27 +			}
    2.28 +			else
    2.29 +#endif
    2.30  			{
    2.31  			Sint8 *dst8, *src8;
    2.32  			Sint8 src_sample;
    2.33 @@ -190,6 +197,12 @@
    2.34  				SDL_MixAudio_MMX_S16((char*)dst,(char*)src,(unsigned int)len,(int)volume);
    2.35  			}
    2.36  			else
    2.37 +#elif defined(USE_ASM_MIXER_VC)
    2.38 +			if (SDL_IsMMX_VC())
    2.39 +			{
    2.40 +				SDL_MixAudio_MMX_S16_VC((char*)dst,(char*)src,(unsigned int)len,(int)volume);
    2.41 +			}
    2.42 +			else
    2.43  #endif
    2.44  			{
    2.45  			Sint16 src1, src2;
    2.46 @@ -251,3 +264,4 @@
    2.47  			return;
    2.48  	}
    2.49  }
    2.50 +
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/audio/SDL_mixer_MMX_VC.c	Mon Jan 20 16:01:20 2003 +0000
     3.3 @@ -0,0 +1,205 @@
     3.4 +// MMX assembler version of SDL_MixAudio for signed little endian 16 bit samples and signed 8 bit samples
     3.5 +// Copyright 2002 Stephane Marchesin (stephane.marchesin@wanadoo.fr)
     3.6 +// Converted to Intel ASM notation by Cth
     3.7 +// This code is licensed under the LGPL (see COPYING for details)
     3.8 +// 
     3.9 +// Assumes buffer size in bytes is a multiple of 16
    3.10 +// Assumes SDL_MIX_MAXVOLUME = 128
    3.11 +
    3.12 +
    3.13 +////////////////////////////////////////////////
    3.14 +// Mixing for 16 bit signed buffers
    3.15 +////////////////////////////////////////////////
    3.16 +
    3.17 +#if defined(USE_ASM_MIXER_VC)
    3.18 +#include <windows.h>
    3.19 +#include <stdio.h>
    3.20 +
    3.21 +void SDL_MixAudio_MMX_S16_VC(char* dst,char* src,unsigned int nSize,int volume)
    3.22 +{
    3.23 +	__asm
    3.24 +	{
    3.25 +		align	16
    3.26 +
    3.27 +		push	edi
    3.28 +		push	esi
    3.29 +		push	ebx
    3.30 +		
    3.31 +		mov		edi, dst		// edi = dst
    3.32 +		mov		esi, src		// esi = src
    3.33 +		mov		eax, volume		// eax = volume
    3.34 +		mov		ebx, nSize		// ebx = size
    3.35 +		shr		ebx, 4			// process 16 bytes per iteration = 8 samples
    3.36 +		jz		endS16
    3.37 +		
    3.38 +		pxor	mm0, mm0
    3.39 +		movd	mm0, eax		//%%eax,%%mm0
    3.40 +		movq	mm1, mm0		//%%mm0,%%mm1
    3.41 +		psllq	mm0, 16			//$16,%%mm0
    3.42 +		por		mm0, mm1		//%%mm1,%%mm0
    3.43 +		psllq	mm0, 16			//$16,%%mm0
    3.44 +		por		mm0, mm1		//%%mm1,%%mm0
    3.45 +		psllq	mm0, 16			//$16,%%mm0
    3.46 +		por		mm0, mm1		//%%mm1,%%mm0			// mm0 = vol|vol|vol|vol
    3.47 +
    3.48 +mixloopS16:
    3.49 +		movq	mm1, [esi]		//(%%esi),%%mm1\n" // mm1 = a|b|c|d
    3.50 +		movq	mm2, mm1		//%%mm1,%%mm2\n" // mm2 = a|b|c|d
    3.51 +		movq	mm4, [esi + 8]	//8(%%esi),%%mm4\n" // mm4 = e|f|g|h
    3.52 +		// pre charger le buffer dst dans mm7
    3.53 +		movq	mm7, [edi]		//(%%edi),%%mm7\n" // mm7 = dst[0]"
    3.54 +		// multiplier par le volume
    3.55 +		pmullw	mm1, mm0		//%%mm0,%%mm1\n" // mm1 = l(a*v)|l(b*v)|l(c*v)|l(d*v)
    3.56 +		pmulhw	mm2, mm0		//%%mm0,%%mm2\n" // mm2 = h(a*v)|h(b*v)|h(c*v)|h(d*v)
    3.57 +		movq	mm5, mm4		//%%mm4,%%mm5\n" // mm5 = e|f|g|h
    3.58 +		pmullw	mm4, mm0		//%%mm0,%%mm4\n" // mm4 = l(e*v)|l(f*v)|l(g*v)|l(h*v)
    3.59 +		pmulhw	mm5, mm0		//%%mm0,%%mm5\n" // mm5 = h(e*v)|h(f*v)|h(g*v)|h(h*v)
    3.60 +		movq	mm3, mm1		//%%mm1,%%mm3\n" // mm3 = l(a*v)|l(b*v)|l(c*v)|l(d*v)
    3.61 +		punpckhwd	mm1, mm2	//%%mm2,%%mm1\n" // mm1 = a*v|b*v
    3.62 +		movq		mm6, mm4	//%%mm4,%%mm6\n" // mm6 = l(e*v)|l(f*v)|l(g*v)|l(h*v)
    3.63 +		punpcklwd	mm3, mm2	//%%mm2,%%mm3\n" // mm3 = c*v|d*v
    3.64 +		punpckhwd	mm4, mm5	//%%mm5,%%mm4\n" // mm4 = e*f|f*v
    3.65 +		punpcklwd	mm6, mm5	//%%mm5,%%mm6\n" // mm6 = g*v|h*v
    3.66 +		// pre charger le buffer dst dans mm5
    3.67 +		movq	mm5, [edi + 8]	//8(%%edi),%%mm5\n" // mm5 = dst[1]
    3.68 +		// diviser par 128
    3.69 +		psrad	mm1, 7			//$7,%%mm1\n" // mm1 = a*v/128|b*v/128 , 128 = SDL_MIX_MAXVOLUME
    3.70 +		add		esi, 16			//$16,%%esi\n"
    3.71 +		psrad	mm3, 7			//$7,%%mm3\n" // mm3 = c*v/128|d*v/128
    3.72 +		psrad	mm4, 7			//$7,%%mm4\n" // mm4 = e*v/128|f*v/128
    3.73 +		// mm1 = le sample avec le volume modifie
    3.74 +		packssdw	mm3, mm1	//%%mm1,%%mm3\n" // mm3 = s(a*v|b*v|c*v|d*v)
    3.75 +		psrad	mm6, 7			//$7,%%mm6\n" // mm6= g*v/128|h*v/128
    3.76 +		paddsw	mm3, mm7		//%%mm7,%%mm3\n" // mm3 = adjust_volume(src)+dst
    3.77 +		// mm4 = le sample avec le volume modifie
    3.78 +		packssdw	mm6, mm4	//%%mm4,%%mm6\n" // mm6 = s(e*v|f*v|g*v|h*v)
    3.79 +		movq	[edi], mm3		//%%mm3,(%%edi)\n"
    3.80 +		paddsw	mm6, mm5		//%%mm5,%%mm6\n" // mm6 = adjust_volume(src)+dst
    3.81 +		movq	[edi + 8], mm6	//%%mm6,8(%%edi)\n"
    3.82 +		add		edi, 16			//$16,%%edi\n"
    3.83 +		dec		ebx				//%%ebx\n"
    3.84 +		jnz mixloopS16
    3.85 +
    3.86 +ends16:
    3.87 +		emms
    3.88 +		
    3.89 +		pop		ebx
    3.90 +		pop		esi
    3.91 +		pop		edi
    3.92 +	}
    3.93 +
    3.94 +}
    3.95 +
    3.96 +////////////////////////////////////////////////
    3.97 +// Mixing for 8 bit signed buffers
    3.98 +////////////////////////////////////////////////
    3.99 +
   3.100 +void SDL_MixAudio_MMX_S8_VC(char* dst,char* src,unsigned int nSize,int volume)
   3.101 +{
   3.102 +	_asm
   3.103 +	{
   3.104 +		align 16
   3.105 +
   3.106 +		push	edi
   3.107 +		push	esi
   3.108 +		push	ebx
   3.109 +		
   3.110 +		mov		edi, dst	//movl	%0,%%edi	// edi = dst
   3.111 +		mov		esi, src	//%1,%%esi	// esi = src
   3.112 +		mov		eax, volume	//%3,%%eax	// eax = volume
   3.113 +
   3.114 +		movd	mm0, ebx	//%%ebx,%%mm0
   3.115 +		movq	mm1, mm0	//%%mm0,%%mm1
   3.116 +		psllq	mm0, 16		//$16,%%mm0
   3.117 +		por		mm0, mm1	//%%mm1,%%mm0
   3.118 +		psllq	mm0, 16		//$16,%%mm0
   3.119 +		por		mm0, mm1	//%%mm1,%%mm0
   3.120 +		psllq	mm0, 16		//$16,%%mm0
   3.121 +		por		mm0, mm1	//%%mm1,%%mm0
   3.122 +		
   3.123 +		mov		ebx, nSize	//%2,%%ebx	// ebx = size
   3.124 +		shr		ebx, 3		//$3,%%ebx	// process 8 bytes per iteration = 8 samples
   3.125 +		cmp		ebx, 0		//$0,%%ebx
   3.126 +		je		endS8
   3.127 +
   3.128 +mixloopS8:
   3.129 +		pxor	mm2, mm2	//%%mm2,%%mm2		// mm2 = 0
   3.130 +		movq	mm1, [esi]	//(%%esi),%%mm1	// mm1 = a|b|c|d|e|f|g|h
   3.131 +		movq	mm3, mm1	//%%mm1,%%mm3 	// mm3 = a|b|c|d|e|f|g|h
   3.132 +		// on va faire le "sign extension" en faisant un cmp avec 0 qui retourne 1 si <0, 0 si >0
   3.133 +		pcmpgtb		mm2, mm1	//%%mm1,%%mm2	// mm2 = 11111111|00000000|00000000....
   3.134 +		punpckhbw	mm1, mm2	//%%mm2,%%mm1	// mm1 = 0|a|0|b|0|c|0|d
   3.135 +		punpcklbw	mm3, mm2	//%%mm2,%%mm3	// mm3 = 0|e|0|f|0|g|0|h
   3.136 +		movq	mm2, [edi]	//(%%edi),%%mm2	// mm2 = destination
   3.137 +		pmullw	mm1, mm0	//%%mm0,%%mm1	// mm1 = v*a|v*b|v*c|v*d
   3.138 +		add		esi, 8		//$8,%%esi
   3.139 +		pmullw	mm3, mm0	//%%mm0,%%mm3	// mm3 = v*e|v*f|v*g|v*h
   3.140 +		psraw	mm1, 7		//$7,%%mm1		// mm1 = v*a/128|v*b/128|v*c/128|v*d/128 
   3.141 +		psraw	mm3, 7		//$7,%%mm3		// mm3 = v*e/128|v*f/128|v*g/128|v*h/128
   3.142 +		packsswb mm3, mm1	//%%mm1,%%mm3	// mm1 = v*a/128|v*b/128|v*c/128|v*d/128|v*e/128|v*f/128|v*g/128|v*h/128
   3.143 +		paddsb	mm3, mm2	//%%mm2,%%mm3	// add to destination buffer
   3.144 +		movq	[edi], mm3	//%%mm3,(%%edi)	// store back to ram
   3.145 +		add		edi, 8		//$8,%%edi
   3.146 +		dec		ebx			//%%ebx
   3.147 +		jnz		mixloopS8
   3.148 +		
   3.149 +endS8:
   3.150 +		emms
   3.151 +		
   3.152 +		pop		ebx
   3.153 +		pop		esi
   3.154 +		pop		edi
   3.155 +	}
   3.156 +}
   3.157 +
   3.158 +int _SDL_IsMMX_VC()
   3.159 +{
   3.160 +	// This	bit	flag can get set on	calling	cpuid
   3.161 +	// with	register eax set to	1
   3.162 +	const int _MMX_FEATURE_BIT = 0x00800000;
   3.163 +	DWORD dwFeature	= 0;
   3.164 +	__try {
   3.165 +			_asm {
   3.166 +				mov	eax,1
   3.167 +				cpuid
   3.168 +				mov	dwFeature,edx
   3.169 +			}
   3.170 +	} __except ( EXCEPTION_EXECUTE_HANDLER)	{
   3.171 +			return 0;
   3.172 +	}
   3.173 +	if (dwFeature &	_MMX_FEATURE_BIT) {
   3.174 +		__try {
   3.175 +			__asm {
   3.176 +				pxor mm0, mm0
   3.177 +				emms
   3.178 +			}
   3.179 +		} __except (EXCEPTION_EXECUTE_HANDLER) {
   3.180 +			return(0);
   3.181 +		}
   3.182 +		return 1;
   3.183 +	}
   3.184 +
   3.185 +	return 0;
   3.186 +}
   3.187 +
   3.188 +static int _notTwice = 2;
   3.189 +
   3.190 +int SDL_IsMMX_VC()
   3.191 +{
   3.192 +	if (_notTwice > 1)
   3.193 +	{
   3.194 +		_notTwice = _SDL_IsMMX_VC();
   3.195 +/*
   3.196 +#ifdef _DEBUG
   3.197 +		if (_notTwice)
   3.198 +			MessageBox( NULL, "Using MMX!!!", "Error", MB_OK | MB_ICONINFORMATION );
   3.199 +		else
   3.200 +			MessageBox( NULL, "Not sing MMX!!!", "Error", MB_OK | MB_ICONINFORMATION );
   3.201 +#endif
   3.202 +*/
   3.203 +	}
   3.204 +	return _notTwice;
   3.205 +}
   3.206 +
   3.207 +#endif
   3.208 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/audio/SDL_mixer_MMX_VC.h	Mon Jan 20 16:01:20 2003 +0000
     4.3 @@ -0,0 +1,15 @@
     4.4 +// headers for MMX assembler version of SDL_MixAudio
     4.5 +// Copyright 2002 Stephane Marchesin (stephane.marchesin@wanadoo.fr)
     4.6 +// Converted to Intel ASM notation by Cth
     4.7 +// This code is licensed under the LGPL (see COPYING for details)
     4.8 +// 
     4.9 +// Assumes buffer size in bytes is a multiple of 16
    4.10 +// Assumes SDL_MIX_MAXVOLUME = 128
    4.11 +
    4.12 +#if defined(USE_ASM_MIXER_VC)
    4.13 +void SDL_MixAudio_MMX_S16_VC(char* ,char* ,unsigned int ,int );
    4.14 +void SDL_MixAudio_MMX_S8_VC(char* ,char* ,unsigned int ,int );
    4.15 +int SDL_IsMMX_VC();
    4.16 +#endif
    4.17 +
    4.18 +