Blame src/pcm/pcm_dmix_x86_64.h

Packit Service db8eaa
/**
Packit Service db8eaa
 * \file pcm/pcm_dmix_x86_64.h
Packit Service db8eaa
 * \ingroup PCM_Plugins
Packit Service db8eaa
 * \brief PCM Direct Stream Mixing (dmix) Plugin Interface - X86-64 assembler code
Packit Service db8eaa
 * \author Takashi Iwai <tiwai@suse.de>
Packit Service db8eaa
 * \date 2003
Packit Service db8eaa
 */
Packit Service db8eaa
/*
Packit Service db8eaa
 *  PCM - Direct Stream Mixing
Packit Service db8eaa
 *  Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
Packit Service db8eaa
 *                        Takashi Iwai <tiwai@suse.de>
Packit Service db8eaa
 *
Packit Service db8eaa
 *
Packit Service db8eaa
 *   This library is free software; you can redistribute it and/or modify
Packit Service db8eaa
 *   it under the terms of the GNU Lesser General Public License as
Packit Service db8eaa
 *   published by the Free Software Foundation; either version 2.1 of
Packit Service db8eaa
 *   the License, or (at your option) any later version.
Packit Service db8eaa
 *
Packit Service db8eaa
 *   This program is distributed in the hope that it will be useful,
Packit Service db8eaa
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service db8eaa
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service db8eaa
 *   GNU Lesser General Public License for more details.
Packit Service db8eaa
 *
Packit Service db8eaa
 *   You should have received a copy of the GNU Lesser General Public
Packit Service db8eaa
 *   License along with this library; if not, write to the Free Software
Packit Service db8eaa
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit Service db8eaa
 *
Packit Service db8eaa
 */
Packit Service db8eaa
Packit Service db8eaa
#if defined(__GNUC__) && __GNUC__ < 5 && defined(__PIC__)
Packit Service db8eaa
#  define BOUNDED_RBX
Packit Service db8eaa
#endif
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 *  MMX optimized
Packit Service db8eaa
 */
Packit Service db8eaa
static void MIX_AREAS_16(unsigned int size,
Packit Service db8eaa
			 volatile signed short *dst, signed short *src,
Packit Service db8eaa
			 volatile signed int *sum, size_t dst_step,
Packit Service db8eaa
			 size_t src_step, size_t sum_step)
Packit Service db8eaa
{
Packit Service db8eaa
#ifdef BOUNDED_RBX
Packit Service db8eaa
	unsigned long long old_rbx;
Packit Service db8eaa
#endif
Packit Service db8eaa
	/*
Packit Service db8eaa
	 *  RSI - src
Packit Service db8eaa
	 *  RDI - dst
Packit Service db8eaa
	 *  RBX - sum
Packit Service db8eaa
	 *  ECX - old sample
Packit Service db8eaa
	 *  EAX - sample / temporary
Packit Service db8eaa
	 *  EDX - temporary
Packit Service db8eaa
	 */
Packit Service db8eaa
	__asm__ __volatile__ (
Packit Service db8eaa
		"\n"
Packit Service db8eaa
#ifdef BOUNDED_RBX
Packit Service db8eaa
		"\tmovq %%rbx, %[old_rbx]\n"
Packit Service db8eaa
#endif
Packit Service db8eaa
		/*
Packit Service db8eaa
		 *  initialization, load RSI, RDI, RBX registers
Packit Service db8eaa
		 */
Packit Service db8eaa
#ifndef _ILP32
Packit Service db8eaa
		"\tmovq %[dst], %%rdi\n"
Packit Service db8eaa
		"\tmovq %[src], %%rsi\n"
Packit Service db8eaa
		"\tmovq %[sum], %%rbx\n"
Packit Service db8eaa
#else
Packit Service db8eaa
		"\tmovl %[dst], %%edi\n"
Packit Service db8eaa
		"\tmovl %[src], %%esi\n"
Packit Service db8eaa
		"\tmovl %[sum], %%ebx\n"
Packit Service db8eaa
#endif
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 * while (size-- > 0) {
Packit Service db8eaa
		 */
Packit Service db8eaa
		"\tcmpl $0, %[size]\n"
Packit Service db8eaa
		"jz 6f\n"
Packit Service db8eaa
Packit Service db8eaa
		"\t.p2align 4,,15\n"
Packit Service db8eaa
Packit Service db8eaa
		"1:"
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 *   sample = *src;
Packit Service db8eaa
		 *   sum_sample = *sum;
Packit Service db8eaa
		 *   if (cmpxchg(*dst, 0, 1) == 0)
Packit Service db8eaa
		 *     sample -= sum_sample;
Packit Service db8eaa
		 *   xadd(*sum, sample);
Packit Service db8eaa
		 */
Packit Service db8eaa
		"\tmovw $0, %%ax\n"
Packit Service db8eaa
		"\tmovw $1, %%cx\n"
Packit Service db8eaa
		"\tmovl (%%rbx), %%edx\n"
Packit Service db8eaa
		"\t" LOCK_PREFIX "cmpxchgw %%cx, (%%rdi)\n"
Packit Service db8eaa
		"\tmovswl (%%rsi), %%ecx\n"
Packit Service db8eaa
		"\tjnz 2f\n"
Packit Service db8eaa
		"\t" XSUB " %%edx, %%ecx\n"
Packit Service db8eaa
		"2:"
Packit Service db8eaa
		"\t" LOCK_PREFIX XADD " %%ecx, (%%rbx)\n"
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 *   do {
Packit Service db8eaa
		 *     sample = old_sample = *sum;
Packit Service db8eaa
		 *     saturate(v);
Packit Service db8eaa
		 *     *dst = sample;
Packit Service db8eaa
		 *   } while (v != *sum);
Packit Service db8eaa
		 */
Packit Service db8eaa
Packit Service db8eaa
		"3:"
Packit Service db8eaa
		"\tmovl (%%rbx), %%ecx\n"
Packit Service db8eaa
		"\tmovd %%ecx, %%mm0\n"
Packit Service db8eaa
		"\tpackssdw %%mm1, %%mm0\n"
Packit Service db8eaa
		"\tmovd %%mm0, %%eax\n"
Packit Service db8eaa
		"\tmovw %%ax, (%%rdi)\n"
Packit Service db8eaa
		"\tcmpl %%ecx, (%%rbx)\n"
Packit Service db8eaa
		"\tjnz 3b\n"
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 * while (size-- > 0)
Packit Service db8eaa
		 */
Packit Service db8eaa
#ifndef _ILP32
Packit Service db8eaa
		"\taddq %[dst_step], %%rdi\n"
Packit Service db8eaa
		"\taddq %[src_step], %%rsi\n"
Packit Service db8eaa
		"\taddq %[sum_step], %%rbx\n"
Packit Service db8eaa
#else
Packit Service db8eaa
		"\taddl %[dst_step], %%edi\n"
Packit Service db8eaa
		"\taddl %[src_step], %%esi\n"
Packit Service db8eaa
		"\taddl %[sum_step], %%ebx\n"
Packit Service db8eaa
#endif
Packit Service db8eaa
		"\tdecl %[size]\n"
Packit Service db8eaa
		"\tjnz 1b\n"
Packit Service db8eaa
Packit Service db8eaa
		"6:"
Packit Service db8eaa
Packit Service db8eaa
		"\temms\n"
Packit Service db8eaa
#ifdef BOUNDED_RBX
Packit Service db8eaa
		"\tmovq %[old_rbx], %%rbx\n"
Packit Service db8eaa
#endif
Packit Service db8eaa
		: [size] "+&rm" (size)
Packit Service db8eaa
#ifdef BOUNDED_RBX
Packit Service db8eaa
		  , [old_rbx] "=m" (old_rbx)
Packit Service db8eaa
#endif
Packit Service db8eaa
	        : [dst] "m" (dst), [src] "m" (src), [sum] "m" (sum),
Packit Service db8eaa
		  [dst_step] "im" (dst_step),  [src_step] "im" (src_step),
Packit Service db8eaa
		  [sum_step] "im" (sum_step)
Packit Service db8eaa
		: "rsi", "rdi", "edx", "ecx", "eax", "memory", "cc"
Packit Service db8eaa
#ifndef BOUNDED_RBX
Packit Service db8eaa
		  , "rbx"
Packit Service db8eaa
#endif
Packit Service db8eaa
#ifdef HAVE_MMX
Packit Service db8eaa
		  , "mm0"
Packit Service db8eaa
#else
Packit Service db8eaa
		  , "st", "st(1)", "st(2)", "st(3)",
Packit Service db8eaa
		  "st(4)", "st(5)", "st(6)", "st(7)"
Packit Service db8eaa
#endif
Packit Service db8eaa
	);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 *  32-bit version (24-bit resolution)
Packit Service db8eaa
 */
Packit Service db8eaa
static void MIX_AREAS_32(unsigned int size,
Packit Service db8eaa
			 volatile signed int *dst, signed int *src,
Packit Service db8eaa
			 volatile signed int *sum, size_t dst_step,
Packit Service db8eaa
			 size_t src_step, size_t sum_step)
Packit Service db8eaa
{
Packit Service db8eaa
#ifdef BOUNDED_RBX
Packit Service db8eaa
	unsigned long long old_rbx;
Packit Service db8eaa
#endif
Packit Service db8eaa
	/*
Packit Service db8eaa
	 *  RSI - src
Packit Service db8eaa
	 *  RDI - dst
Packit Service db8eaa
	 *  RBX - sum
Packit Service db8eaa
	 *  ECX - old sample
Packit Service db8eaa
	 *  EAX - sample / temporary
Packit Service db8eaa
	 *  EDX - temporary
Packit Service db8eaa
	 */
Packit Service db8eaa
	__asm__ __volatile__ (
Packit Service db8eaa
		"\n"
Packit Service db8eaa
#ifdef BOUNDED_RBX
Packit Service db8eaa
		"\tmovq %%rbx, %[old_rbx]\n"
Packit Service db8eaa
#endif
Packit Service db8eaa
		/*
Packit Service db8eaa
		 *  initialization, load RSI, RDI, RBX registers
Packit Service db8eaa
		 */
Packit Service db8eaa
#ifndef _ILP32
Packit Service db8eaa
		"\tmovq %[dst], %%rdi\n"
Packit Service db8eaa
		"\tmovq %[src], %%rsi\n"
Packit Service db8eaa
		"\tmovq %[sum], %%rbx\n"
Packit Service db8eaa
#else
Packit Service db8eaa
		"\tmovl %[dst], %%edi\n"
Packit Service db8eaa
		"\tmovl %[src], %%esi\n"
Packit Service db8eaa
		"\tmovl %[sum], %%ebx\n"
Packit Service db8eaa
#endif
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 * while (size-- > 0) {
Packit Service db8eaa
		 */
Packit Service db8eaa
		"\tcmpl $0, %[size]\n"
Packit Service db8eaa
		"jz 6f\n"
Packit Service db8eaa
Packit Service db8eaa
		"\t.p2align 4,,15\n"
Packit Service db8eaa
Packit Service db8eaa
		"1:"
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 *   sample = *src;
Packit Service db8eaa
		 *   sum_sample = *sum;
Packit Service db8eaa
		 *   if (cmpxchg(*dst, 0, 1) == 0)
Packit Service db8eaa
		 *     sample -= sum_sample;
Packit Service db8eaa
		 *   xadd(*sum, sample);
Packit Service db8eaa
		 */
Packit Service db8eaa
		"\tmovl $0, %%eax\n"
Packit Service db8eaa
		"\tmovl $1, %%ecx\n"
Packit Service db8eaa
		"\tmovl (%%rbx), %%edx\n"
Packit Service db8eaa
		"\t" LOCK_PREFIX "cmpxchgl %%ecx, (%%rdi)\n"
Packit Service db8eaa
		"\tjnz 2f\n"
Packit Service db8eaa
		"\tmovl (%%rsi), %%ecx\n"
Packit Service db8eaa
		/* sample >>= 8 */
Packit Service db8eaa
		"\tsarl $8, %%ecx\n"
Packit Service db8eaa
		"\t" XSUB " %%edx, %%ecx\n"
Packit Service db8eaa
		"\tjmp 21f\n"
Packit Service db8eaa
		"2:"
Packit Service db8eaa
		"\tmovl (%%rsi), %%ecx\n"
Packit Service db8eaa
		/* sample >>= 8 */
Packit Service db8eaa
		"\tsarl $8, %%ecx\n"
Packit Service db8eaa
		"21:"
Packit Service db8eaa
		"\t" LOCK_PREFIX XADD " %%ecx, (%%rbx)\n"
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 *   do {
Packit Service db8eaa
		 *     sample = old_sample = *sum;
Packit Service db8eaa
		 *     saturate(v);
Packit Service db8eaa
		 *     *dst = sample;
Packit Service db8eaa
		 *   } while (v != *sum);
Packit Service db8eaa
		 */
Packit Service db8eaa
Packit Service db8eaa
		"3:"
Packit Service db8eaa
		"\tmovl (%%rbx), %%ecx\n"
Packit Service db8eaa
		/*
Packit Service db8eaa
		 *  if (sample > 0x7fff00)
Packit Service db8eaa
		 */
Packit Service db8eaa
		"\tmovl $0x7fffff, %%eax\n"
Packit Service db8eaa
		"\tcmpl %%eax, %%ecx\n"
Packit Service db8eaa
		"\tjg 4f\n"
Packit Service db8eaa
		/*
Packit Service db8eaa
		 *  if (sample < -0x800000)
Packit Service db8eaa
		 */
Packit Service db8eaa
		"\tmovl $-0x800000, %%eax\n"
Packit Service db8eaa
		"\tcmpl %%eax, %%ecx\n"
Packit Service db8eaa
		"\tjl 4f\n"
Packit Service db8eaa
		"\tmovl %%ecx, %%eax\n"
Packit Service db8eaa
		"4:"
Packit Service db8eaa
		/*
Packit Service db8eaa
		 *  sample <<= 8;
Packit Service db8eaa
		 */
Packit Service db8eaa
		"\tsall $8, %%eax\n"
Packit Service db8eaa
		"\tmovl %%eax, (%%rdi)\n"
Packit Service db8eaa
		"\tcmpl %%ecx, (%%rbx)\n"
Packit Service db8eaa
		"\tjnz 3b\n"
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 * while (size-- > 0)
Packit Service db8eaa
		 */
Packit Service db8eaa
#ifndef _ILP32
Packit Service db8eaa
		"\taddq %[dst_step], %%rdi\n"
Packit Service db8eaa
		"\taddq %[src_step], %%rsi\n"
Packit Service db8eaa
		"\taddq %[sum_step], %%rbx\n"
Packit Service db8eaa
#else
Packit Service db8eaa
		"\taddl %[dst_step], %%edi\n"
Packit Service db8eaa
		"\taddl %[src_step], %%esi\n"
Packit Service db8eaa
		"\taddl %[sum_step], %%ebx\n"
Packit Service db8eaa
#endif
Packit Service db8eaa
		"\tdecl %[size]\n"
Packit Service db8eaa
		"\tjnz 1b\n"
Packit Service db8eaa
Packit Service db8eaa
		"6:"
Packit Service db8eaa
#ifdef BOUNDED_RBX
Packit Service db8eaa
		"\tmovq %[old_rbx], %%rbx\n"
Packit Service db8eaa
#endif
Packit Service db8eaa
		: [size] "+&rm" (size)
Packit Service db8eaa
#ifdef BOUNDED_RBX
Packit Service db8eaa
		  , [old_rbx] "=m" (old_rbx)
Packit Service db8eaa
#endif
Packit Service db8eaa
	        : [dst] "m" (dst), [src] "m" (src), [sum] "m" (sum),
Packit Service db8eaa
		  [dst_step] "im" (dst_step),  [src_step] "im" (src_step),
Packit Service db8eaa
		  [sum_step] "im" (sum_step)
Packit Service db8eaa
		: "rsi", "rdi", "edx", "ecx", "eax", "memory", "cc"
Packit Service db8eaa
#ifndef BOUNDED_RBX
Packit Service db8eaa
		  , "rbx"
Packit Service db8eaa
#endif
Packit Service db8eaa
	);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 *  24-bit version
Packit Service db8eaa
 */
Packit Service db8eaa
static void MIX_AREAS_24(unsigned int size,
Packit Service db8eaa
			 volatile unsigned char *dst, unsigned char *src,
Packit Service db8eaa
			 volatile signed int *sum, size_t dst_step,
Packit Service db8eaa
			 size_t src_step, size_t sum_step)
Packit Service db8eaa
{
Packit Service db8eaa
#ifdef BOUNDED_RBX
Packit Service db8eaa
	unsigned long long old_rbx;
Packit Service db8eaa
#endif
Packit Service db8eaa
	/*
Packit Service db8eaa
	 *  RSI - src
Packit Service db8eaa
	 *  RDI - dst
Packit Service db8eaa
	 *  RBX - sum
Packit Service db8eaa
	 *  ECX - old sample
Packit Service db8eaa
	 *  EAX - sample / temporary
Packit Service db8eaa
	 *  EDX - temporary
Packit Service db8eaa
	 */
Packit Service db8eaa
	__asm__ __volatile__ (
Packit Service db8eaa
		"\n"
Packit Service db8eaa
#ifdef BOUNDED_RBX
Packit Service db8eaa
		"\tmovq %%rbx, %[old_rbx]\n"
Packit Service db8eaa
#endif
Packit Service db8eaa
		/*
Packit Service db8eaa
		 *  initialization, load RSI, RDI, RBX registers
Packit Service db8eaa
		 */
Packit Service db8eaa
#ifndef _ILP32
Packit Service db8eaa
		"\tmovq %[dst], %%rdi\n"
Packit Service db8eaa
		"\tmovq %[src], %%rsi\n"
Packit Service db8eaa
		"\tmovq %[sum], %%rbx\n"
Packit Service db8eaa
#else
Packit Service db8eaa
		"\tmovl %[dst], %%edi\n"
Packit Service db8eaa
		"\tmovl %[src], %%esi\n"
Packit Service db8eaa
		"\tmovl %[sum], %%ebx\n"
Packit Service db8eaa
#endif
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 * while (size-- > 0) {
Packit Service db8eaa
		 */
Packit Service db8eaa
		"\tcmpl $0, %[size]\n"
Packit Service db8eaa
		"jz 6f\n"
Packit Service db8eaa
Packit Service db8eaa
		"\t.p2align 4,,15\n"
Packit Service db8eaa
Packit Service db8eaa
		"1:"
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 *   sample = *src;
Packit Service db8eaa
		 *   sum_sample = *sum;
Packit Service db8eaa
		 *   if (test_and_set_bit(0, dst) == 0)
Packit Service db8eaa
		 *     sample -= sum_sample;
Packit Service db8eaa
		 *   *sum += sample;
Packit Service db8eaa
		 */
Packit Service db8eaa
		"\tmovsbl 2(%%rsi), %%eax\n"
Packit Service db8eaa
		"\tmovzwl (%%rsi), %%ecx\n"
Packit Service db8eaa
		"\tmovl (%%rbx), %%edx\n"
Packit Service db8eaa
		"\tsall $16, %%eax\n"
Packit Service db8eaa
		"\torl %%eax, %%ecx\n"
Packit Service db8eaa
		"\t" LOCK_PREFIX "btsw $0, (%%rdi)\n"
Packit Service db8eaa
		"\tjc 2f\n"
Packit Service db8eaa
		"\t" XSUB " %%edx, %%ecx\n"
Packit Service db8eaa
		"2:"
Packit Service db8eaa
		"\t" LOCK_PREFIX XADD " %%ecx, (%%rbx)\n"
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 *   do {
Packit Service db8eaa
		 *     sample = old_sample = *sum;
Packit Service db8eaa
		 *     saturate(sample);
Packit Service db8eaa
		 *     *dst = sample | 1;
Packit Service db8eaa
		 *   } while (old_sample != *sum);
Packit Service db8eaa
		 */
Packit Service db8eaa
Packit Service db8eaa
		"3:"
Packit Service db8eaa
		"\tmovl (%%rbx), %%ecx\n"
Packit Service db8eaa
Packit Service db8eaa
		"\tmovl $0x7fffff, %%eax\n"
Packit Service db8eaa
		"\tmovl $-0x7fffff, %%edx\n"
Packit Service db8eaa
		"\tcmpl %%eax, %%ecx\n"
Packit Service db8eaa
		"\tcmovng %%ecx, %%eax\n"
Packit Service db8eaa
		"\tcmpl %%edx, %%ecx\n"
Packit Service db8eaa
		"\tcmovl %%edx, %%eax\n"
Packit Service db8eaa
Packit Service db8eaa
		"\torl $1, %%eax\n"
Packit Service db8eaa
		"\tmovw %%ax, (%%rdi)\n"
Packit Service db8eaa
		"\tshrl $16, %%eax\n"
Packit Service db8eaa
		"\tmovb %%al, 2(%%rdi)\n"
Packit Service db8eaa
Packit Service db8eaa
		"\tcmpl %%ecx, (%%rbx)\n"
Packit Service db8eaa
		"\tjnz 3b\n"
Packit Service db8eaa
Packit Service db8eaa
		/*
Packit Service db8eaa
		 * while (size-- > 0)
Packit Service db8eaa
		 */
Packit Service db8eaa
#ifndef _ILP32
Packit Service db8eaa
		"\taddq %[dst_step], %%rdi\n"
Packit Service db8eaa
		"\taddq %[src_step], %%rsi\n"
Packit Service db8eaa
		"\taddq %[sum_step], %%rbx\n"
Packit Service db8eaa
#else
Packit Service db8eaa
		"\taddl %[dst_step], %%edi\n"
Packit Service db8eaa
		"\taddl %[src_step], %%esi\n"
Packit Service db8eaa
		"\taddl %[sum_step], %%ebx\n"
Packit Service db8eaa
#endif
Packit Service db8eaa
		"\tdecl %[size]\n"
Packit Service db8eaa
		"\tjnz 1b\n"
Packit Service db8eaa
Packit Service db8eaa
		"6:"
Packit Service db8eaa
#ifdef BOUNDED_RBX
Packit Service db8eaa
		"\tmovq %[old_rbx], %%rbx\n"
Packit Service db8eaa
#endif
Packit Service db8eaa
		: [size] "+&rm" (size)
Packit Service db8eaa
#ifdef BOUNDED_RBX
Packit Service db8eaa
		  , [old_rbx] "=m" (old_rbx)
Packit Service db8eaa
#endif
Packit Service db8eaa
	        : [dst] "m" (dst), [src] "m" (src), [sum] "m" (sum),
Packit Service db8eaa
		  [dst_step] "im" (dst_step),  [src_step] "im" (src_step),
Packit Service db8eaa
		  [sum_step] "im" (sum_step)
Packit Service db8eaa
		: "rsi", "rdi", "edx", "ecx", "eax", "memory", "cc"
Packit Service db8eaa
#ifndef BOUNDED_RBX
Packit Service db8eaa
		  , "rbx"
Packit Service db8eaa
#endif
Packit Service db8eaa
	);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
#ifdef BOUNDED_RBX
Packit Service db8eaa
#  undef BOUNDED_RBX
Packit Service db8eaa
#endif