Blame src/libmpg123/optimize.c

Packit c32a2d
/*
Packit c32a2d
	optimize: get a grip on the different optimizations
Packit c32a2d
Packit c32a2d
	copyright 2006-9 by the mpg123 project - free software under the terms of the LGPL 2.1
Packit c32a2d
	see COPYING and AUTHORS files in distribution or http://mpg123.org
Packit c32a2d
	initially written by Thomas Orgis, inspired by 3DNow stuff in mpg123.[hc]
Packit c32a2d
Packit c32a2d
	Currently, this file contains the struct and function to choose an optimization variant and works only when OPT_MULTI is in effect.
Packit c32a2d
*/
Packit c32a2d
Packit c32a2d
#define I_AM_OPTIMIZE
Packit c32a2d
#include "mpg123lib_intern.h" /* includes optimize.h */
Packit c32a2d
#include "debug.h"
Packit c32a2d
Packit c32a2d
#if ((defined OPT_X86) || (defined OPT_X86_64) || (defined OPT_NEON) || (defined OPT_NEON64)) && (defined OPT_MULTI)
Packit c32a2d
#include "getcpuflags.h"
Packit c32a2d
static struct cpuflags cpu_flags;
Packit c32a2d
#else
Packit c32a2d
/* Faking stuff for non-multi builds. The same code for synth function choice is used.
Packit c32a2d
   Just no runtime dependency of result... */
Packit c32a2d
#define cpu_flags nothing
Packit c32a2d
#define cpu_i586(s)     1
Packit c32a2d
#define cpu_fpu(s)      1
Packit c32a2d
#define cpu_mmx(s)      1
Packit c32a2d
#define cpu_3dnow(s)    1
Packit c32a2d
#define cpu_3dnowext(s) 1
Packit c32a2d
#define cpu_sse(s)      1
Packit c32a2d
#define cpu_sse2(s)     1
Packit c32a2d
#define cpu_sse3(s)     1
Packit c32a2d
#define cpu_avx(s)      1
Packit c32a2d
#define cpu_neon(s)     1
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
/* Ugly macros to build conditional synth function array values. */
Packit c32a2d
Packit c32a2d
#ifndef NO_8BIT
Packit c32a2d
#define IF8(synth) synth,
Packit c32a2d
#else
Packit c32a2d
#define IF8(synth)
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#ifndef NO_SYNTH32
Packit c32a2d
Packit c32a2d
#ifndef NO_REAL
Packit c32a2d
#define IFREAL(synth) synth,
Packit c32a2d
#else
Packit c32a2d
#define IFREAL(synth)
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#ifndef NO_32BIT
Packit c32a2d
#define IF32(synth) synth
Packit c32a2d
#else
Packit c32a2d
#define IF32(synth)
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#else
Packit c32a2d
Packit c32a2d
#define IFREAL(synth)
Packit c32a2d
#define IF32(synth)
Packit c32a2d
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#ifndef NO_16BIT
Packit c32a2d
#	define OUT_SYNTHS(synth_16, synth_8, synth_real, synth_32) { synth_16, IF8(synth_8) IFREAL(synth_real) IF32(synth_32) }
Packit c32a2d
#else
Packit c32a2d
#	define OUT_SYNTHS(synth_16, synth_8, synth_real, synth_32) { IF8(synth_8) IFREAL(synth_real) IF32(synth_32) }
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
/* The call of left and right plain synth, wrapped.
Packit c32a2d
   This may be replaced by a direct stereo optimized synth. */
Packit c32a2d
static int synth_stereo_wrap(real *bandPtr_l, real *bandPtr_r, mpg123_handle *fr)
Packit c32a2d
{
Packit c32a2d
	int clip;
Packit c32a2d
	clip  = (fr->synth)(bandPtr_l, 0, fr, 0);
Packit c32a2d
	clip += (fr->synth)(bandPtr_r, 1, fr, 1);
Packit c32a2d
	return clip;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static const struct synth_s synth_base =
Packit c32a2d
{
Packit c32a2d
	{ /* plain */
Packit c32a2d
		 OUT_SYNTHS(synth_1to1, synth_1to1_8bit, synth_1to1_real, synth_1to1_s32)
Packit c32a2d
#		ifndef NO_DOWNSAMPLE
Packit c32a2d
		,OUT_SYNTHS(synth_2to1, synth_2to1_8bit, synth_2to1_real, synth_2to1_s32)
Packit c32a2d
		,OUT_SYNTHS(synth_4to1, synth_4to1_8bit, synth_4to1_real, synth_4to1_s32)
Packit c32a2d
#		endif
Packit c32a2d
#		ifndef NO_NTOM
Packit c32a2d
		,OUT_SYNTHS(synth_ntom, synth_ntom_8bit, synth_ntom_real, synth_ntom_s32)
Packit c32a2d
#		endif
Packit c32a2d
	},
Packit c32a2d
	{ /* stereo, by default only wrappers over plain synth */
Packit c32a2d
		 OUT_SYNTHS(synth_stereo_wrap, synth_stereo_wrap, synth_stereo_wrap, synth_stereo_wrap)
Packit c32a2d
#		ifndef NO_DOWNSAMPLE
Packit c32a2d
		,OUT_SYNTHS(synth_stereo_wrap, synth_stereo_wrap, synth_stereo_wrap, synth_stereo_wrap)
Packit c32a2d
		,OUT_SYNTHS(synth_stereo_wrap, synth_stereo_wrap, synth_stereo_wrap, synth_stereo_wrap)
Packit c32a2d
#		endif
Packit c32a2d
#		ifndef NO_NTOM
Packit c32a2d
		,OUT_SYNTHS(synth_stereo_wrap, synth_stereo_wrap, synth_stereo_wrap, synth_stereo_wrap)
Packit c32a2d
#		endif
Packit c32a2d
	},
Packit c32a2d
	{ /* mono2stereo */
Packit c32a2d
		 OUT_SYNTHS(synth_1to1_m2s, synth_1to1_8bit_m2s, synth_1to1_real_m2s, synth_1to1_s32_m2s)
Packit c32a2d
#		ifndef NO_DOWNSAMPLE
Packit c32a2d
		,OUT_SYNTHS(synth_2to1_m2s, synth_2to1_8bit_m2s, synth_2to1_real_m2s, synth_2to1_s32_m2s)
Packit c32a2d
		,OUT_SYNTHS(synth_4to1_m2s, synth_4to1_8bit_m2s, synth_4to1_real_m2s, synth_4to1_s32_m2s)
Packit c32a2d
#		endif
Packit c32a2d
#		ifndef NO_NTOM
Packit c32a2d
		,OUT_SYNTHS(synth_ntom_m2s, synth_ntom_8bit_m2s, synth_ntom_real_m2s, synth_ntom_s32_m2s)
Packit c32a2d
#		endif
Packit c32a2d
	},
Packit c32a2d
	{ /* mono*/
Packit c32a2d
		 OUT_SYNTHS(synth_1to1_mono, synth_1to1_8bit_mono, synth_1to1_real_mono, synth_1to1_s32_mono)
Packit c32a2d
#		ifndef NO_DOWNSAMPLE
Packit c32a2d
		,OUT_SYNTHS(synth_2to1_mono, synth_2to1_8bit_mono, synth_2to1_real_mono, synth_2to1_s32_mono)
Packit c32a2d
		,OUT_SYNTHS(synth_4to1_mono, synth_4to1_8bit_mono, synth_4to1_real_mono, synth_4to1_s32_mono)
Packit c32a2d
#		endif
Packit c32a2d
#		ifndef NO_NTOM
Packit c32a2d
		,OUT_SYNTHS(synth_ntom_mono, synth_ntom_8bit_mono, synth_ntom_real_mono, synth_ntom_s32_mono)
Packit c32a2d
#endif
Packit c32a2d
	}
Packit c32a2d
};
Packit c32a2d
Packit c32a2d
#ifdef OPT_X86
Packit c32a2d
/* More plain synths for i386 */
Packit c32a2d
const func_synth plain_i386[r_limit][f_limit] =
Packit c32a2d
{ /* plain */
Packit c32a2d
	 OUT_SYNTHS(synth_1to1_i386, synth_1to1_8bit_i386, synth_1to1_real_i386, synth_1to1_s32_i386)
Packit c32a2d
#	ifndef NO_DOWNSAMPLE
Packit c32a2d
	,OUT_SYNTHS(synth_2to1_i386, synth_2to1_8bit_i386, synth_2to1_real_i386, synth_2to1_s32_i386)
Packit c32a2d
	,OUT_SYNTHS(synth_4to1_i386, synth_4to1_8bit_i386, synth_4to1_real_i386, synth_4to1_s32_i386)
Packit c32a2d
#	endif
Packit c32a2d
#	ifndef NO_NTOM
Packit c32a2d
	,OUT_SYNTHS(synth_ntom, synth_ntom_8bit, synth_ntom_real, synth_ntom_s32)
Packit c32a2d
#	endif
Packit c32a2d
};
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
Packit c32a2d
enum optdec defdec(void){ return defopt; }
Packit c32a2d
Packit c32a2d
enum optcla decclass(const enum optdec type)
Packit c32a2d
{
Packit c32a2d
	return
Packit c32a2d
	(
Packit c32a2d
		   type == mmx
Packit c32a2d
		|| type == sse
Packit c32a2d
		|| type == sse_vintage
Packit c32a2d
		|| type == dreidnowext
Packit c32a2d
		|| type == dreidnowext_vintage
Packit c32a2d
		|| type == x86_64
Packit c32a2d
		|| type == neon
Packit c32a2d
		|| type == neon64
Packit c32a2d
		|| type == avx
Packit c32a2d
	) ? mmxsse : normal;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static int find_synth(func_synth synth,  const func_synth synths[r_limit][f_limit])
Packit c32a2d
{
Packit c32a2d
	enum synth_resample ri;
Packit c32a2d
	enum synth_format   fi;
Packit c32a2d
	for(ri=0; ri
Packit c32a2d
	for(fi=0; fi
Packit c32a2d
	if(synth == synths[ri][fi])
Packit c32a2d
	return TRUE;
Packit c32a2d
Packit c32a2d
	return FALSE;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
Packit c32a2d
#if defined(OPT_SSE) || defined(OPT_SSE_VINTAGE)
Packit c32a2d
/* After knowing that it is either vintage or current SSE,
Packit c32a2d
   this separates the two. In case of non-OPT_MULTI, only one
Packit c32a2d
   of OPT_SSE and OPT_SSE_VINTAGE is active. */
Packit c32a2d
static enum optdec sse_or_vintage(mpg123_handle *fr)
Packit c32a2d
{
Packit c32a2d
	enum optdec type;
Packit c32a2d
	type = sse_vintage;
Packit c32a2d
#	ifdef OPT_SSE
Packit c32a2d
#	ifdef OPT_MULTI
Packit c32a2d
	if(fr->cpu_opts.the_dct36 == dct36_sse)
Packit c32a2d
#	endif
Packit c32a2d
	type = sse;
Packit c32a2d
#	endif
Packit c32a2d
	return type;
Packit c32a2d
}
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
/* Determine what kind of decoder is actually active
Packit c32a2d
   This depends on runtime choices which may cause fallback to i386 or generic code. */
Packit c32a2d
static int find_dectype(mpg123_handle *fr)
Packit c32a2d
{
Packit c32a2d
	enum optdec type = nodec;
Packit c32a2d
	/* Direct and indirect usage, 1to1 stereo decoding.
Packit c32a2d
	   Concentrating on the plain stereo synth should be fine, mono stuff is derived. */
Packit c32a2d
	func_synth basic_synth = fr->synth;
Packit c32a2d
#ifndef NO_8BIT
Packit c32a2d
#ifndef NO_16BIT
Packit c32a2d
	if(basic_synth == synth_1to1_8bit_wrap)
Packit c32a2d
	basic_synth = fr->synths.plain[r_1to1][f_16]; /* That is what's really below the surface. */
Packit c32a2d
#endif
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
	if(FALSE) ; /* Just to initialize the else if ladder. */
Packit c32a2d
#ifndef NO_16BIT
Packit c32a2d
#if defined(OPT_3DNOWEXT) || defined(OPT_3DNOWEXT_VINTAGE)
Packit c32a2d
	else if(basic_synth == synth_1to1_3dnowext)
Packit c32a2d
	{
Packit c32a2d
		type = dreidnowext;
Packit c32a2d
#		ifdef OPT_3DNOWEXT_VINTAGE
Packit c32a2d
#		ifdef OPT_MULTI
Packit c32a2d
		if(fr->cpu_opts.the_dct36 == dct36_3dnowext)
Packit c32a2d
#		endif
Packit c32a2d
		type = dreidnowext_vintage;
Packit c32a2d
#		endif
Packit c32a2d
	}
Packit c32a2d
#endif
Packit c32a2d
#if defined(OPT_SSE) || defined(OPT_SSE_VINTAGE)
Packit c32a2d
	else if(basic_synth == synth_1to1_sse)
Packit c32a2d
	{
Packit c32a2d
		type = sse_or_vintage(fr);
Packit c32a2d
	}
Packit c32a2d
#endif
Packit c32a2d
#if defined(OPT_3DNOW) || defined(OPT_3DNOW_VINTAGE)
Packit c32a2d
	else if(basic_synth == synth_1to1_3dnow)
Packit c32a2d
	{
Packit c32a2d
		type = dreidnow;
Packit c32a2d
#		ifdef OPT_3DNOW_VINTAGE
Packit c32a2d
#		ifdef OPT_MULTI
Packit c32a2d
		if(fr->cpu_opts.the_dct36 == dct36_3dnow)
Packit c32a2d
#		endif
Packit c32a2d
		type = dreidnow_vintage;
Packit c32a2d
#		endif
Packit c32a2d
	}
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_MMX
Packit c32a2d
	else if(basic_synth == synth_1to1_mmx) type = mmx;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_I586_DITHER
Packit c32a2d
	else if(basic_synth == synth_1to1_i586_dither) type = ifuenf_dither;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_I586
Packit c32a2d
	else if(basic_synth == synth_1to1_i586) type = ifuenf;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_ALTIVEC
Packit c32a2d
	else if(basic_synth == synth_1to1_altivec) type = altivec;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_X86_64
Packit c32a2d
	else if(basic_synth == synth_1to1_x86_64) type = x86_64;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_AVX
Packit c32a2d
	else if(basic_synth == synth_1to1_avx) type = avx;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_ARM
Packit c32a2d
	else if(basic_synth == synth_1to1_arm) type = arm;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_NEON
Packit c32a2d
	else if(basic_synth == synth_1to1_neon) type = neon;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_NEON64
Packit c32a2d
	else if(basic_synth == synth_1to1_neon64) type = neon64;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_GENERIC_DITHER
Packit c32a2d
	else if(basic_synth == synth_1to1_dither) type = generic_dither;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_DITHER /* either i586 or generic! */
Packit c32a2d
#ifndef NO_DOWNSAMPLE
Packit c32a2d
	else if
Packit c32a2d
	(
Packit c32a2d
		   basic_synth == synth_2to1_dither
Packit c32a2d
		|| basic_synth == synth_4to1_dither
Packit c32a2d
	) type = generic_dither;
Packit c32a2d
#endif
Packit c32a2d
#endif
Packit c32a2d
#endif /* 16bit */
Packit c32a2d
Packit c32a2d
#ifndef NO_SYNTH32
Packit c32a2d
Packit c32a2d
#ifndef NO_REAL
Packit c32a2d
#if defined(OPT_SSE) || defined(OPT_SSE_VINTAGE)
Packit c32a2d
	else if(basic_synth == synth_1to1_real_sse)
Packit c32a2d
	{
Packit c32a2d
		type = sse_or_vintage(fr);
Packit c32a2d
	}
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_X86_64
Packit c32a2d
	else if(basic_synth == synth_1to1_real_x86_64) type = x86_64;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_AVX
Packit c32a2d
	else if(basic_synth == synth_1to1_real_avx) type = avx;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_ALTIVEC
Packit c32a2d
	else if(basic_synth == synth_1to1_real_altivec) type = altivec;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_NEON
Packit c32a2d
	else if(basic_synth == synth_1to1_real_neon) type = neon;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_NEON64
Packit c32a2d
	else if(basic_synth == synth_1to1_real_neon64) type = neon64;
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#endif /* real */
Packit c32a2d
Packit c32a2d
#ifndef NO_32BIT
Packit c32a2d
#if defined(OPT_SSE) || defined(OPT_SSE_VINTAGE)
Packit c32a2d
	else if(basic_synth == synth_1to1_s32_sse)
Packit c32a2d
	{
Packit c32a2d
		type = sse_or_vintage(fr);
Packit c32a2d
	}
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_X86_64
Packit c32a2d
	else if(basic_synth == synth_1to1_s32_x86_64) type = x86_64;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_AVX
Packit c32a2d
	else if(basic_synth == synth_1to1_s32_avx) type = avx;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_ALTIVEC
Packit c32a2d
	else if(basic_synth == synth_1to1_s32_altivec) type = altivec;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_NEON
Packit c32a2d
	else if(basic_synth == synth_1to1_s32_neon) type = neon;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_NEON64
Packit c32a2d
	else if(basic_synth == synth_1to1_s32_neon64) type = neon64;
Packit c32a2d
#endif
Packit c32a2d
#endif /* 32bit */
Packit c32a2d
Packit c32a2d
#endif /* any 32 bit synth */
Packit c32a2d
Packit c32a2d
#ifdef OPT_X86
Packit c32a2d
	else if(find_synth(basic_synth, plain_i386))
Packit c32a2d
	type = idrei;
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
	else if(find_synth(basic_synth, synth_base.plain))
Packit c32a2d
	type = generic;
Packit c32a2d
Packit c32a2d
Packit c32a2d
Packit c32a2d
#ifdef OPT_I486
Packit c32a2d
	/* i486 is special ... the specific code is in use for 16bit 1to1 stereo
Packit c32a2d
	   otherwise we have i386 active... but still, the distinction doesn't matter*/
Packit c32a2d
	type = ivier;
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
	if(type != nodec)
Packit c32a2d
	{
Packit c32a2d
		fr->cpu_opts.type = type;
Packit c32a2d
		fr->cpu_opts.class = decclass(type);
Packit c32a2d
Packit c32a2d
		debug3("determined active decoder type %i (%s) of class %i", type, decname[type], fr->cpu_opts.class);
Packit c32a2d
		return MPG123_OK;
Packit c32a2d
	}
Packit c32a2d
	else
Packit c32a2d
	{
Packit c32a2d
		if(NOQUIET) error("Unable to determine active decoder type -- this is SERIOUS b0rkage!");
Packit c32a2d
Packit c32a2d
		fr->err = MPG123_BAD_DECODER_SETUP;
Packit c32a2d
		return MPG123_ERR;
Packit c32a2d
	}
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
/* set synth functions for current frame, optimizations handled by opt_* macros */
Packit c32a2d
int set_synth_functions(mpg123_handle *fr)
Packit c32a2d
{
Packit c32a2d
	enum synth_resample resample = r_none;
Packit c32a2d
	enum synth_format basic_format = f_none; /* Default is always 16bit, or whatever. */
Packit c32a2d
Packit c32a2d
	/* Select the basic output format, different from 16bit: 8bit, real. */
Packit c32a2d
	if(FALSE){}
Packit c32a2d
#ifndef NO_16BIT
Packit c32a2d
	else if(fr->af.dec_enc & MPG123_ENC_16)
Packit c32a2d
	basic_format = f_16;
Packit c32a2d
#endif
Packit c32a2d
#ifndef NO_8BIT
Packit c32a2d
	else if(fr->af.dec_enc & MPG123_ENC_8)
Packit c32a2d
	basic_format = f_8;
Packit c32a2d
#endif
Packit c32a2d
#ifndef NO_REAL
Packit c32a2d
	else if(fr->af.dec_enc & MPG123_ENC_FLOAT)
Packit c32a2d
	basic_format = f_real;
Packit c32a2d
#endif
Packit c32a2d
#ifndef NO_32BIT
Packit c32a2d
	/* 24 bit integer means decoding to 32 bit first. */
Packit c32a2d
	else if(fr->af.dec_enc & MPG123_ENC_32 || fr->af.dec_enc & MPG123_ENC_24)
Packit c32a2d
	basic_format = f_32;
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
	/* Make sure the chosen format is compiled into this lib. */
Packit c32a2d
	if(basic_format == f_none)
Packit c32a2d
	{
Packit c32a2d
		if(NOQUIET) error("set_synth_functions: This output format is disabled in this build!");
Packit c32a2d
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	/* Be explicit about downsampling variant. */
Packit c32a2d
	switch(fr->down_sample)
Packit c32a2d
	{
Packit c32a2d
		case 0: resample = r_1to1; break;
Packit c32a2d
#ifndef NO_DOWNSAMPLE
Packit c32a2d
		case 1: resample = r_2to1; break;
Packit c32a2d
		case 2: resample = r_4to1; break;
Packit c32a2d
#endif
Packit c32a2d
#ifndef NO_NTOM
Packit c32a2d
		case 3: resample = r_ntom; break;
Packit c32a2d
#endif
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	if(resample == r_none)
Packit c32a2d
	{
Packit c32a2d
		if(NOQUIET) error("set_synth_functions: This resampling mode is not supported in this build!");
Packit c32a2d
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	debug2("selecting synth: resample=%i format=%i", resample, basic_format);
Packit c32a2d
	/* Finally selecting the synth functions for stereo / mono. */
Packit c32a2d
	fr->synth = fr->synths.plain[resample][basic_format];
Packit c32a2d
	fr->synth_stereo = fr->synths.stereo[resample][basic_format];
Packit c32a2d
	fr->synth_mono = fr->af.channels==2
Packit c32a2d
		? fr->synths.mono2stereo[resample][basic_format] /* Mono MPEG file decoded to stereo. */
Packit c32a2d
		: fr->synths.mono[resample][basic_format];       /* Mono MPEG file decoded to mono. */
Packit c32a2d
Packit c32a2d
	if(find_dectype(fr) != MPG123_OK) /* Actually determine the currently active decoder breed. */
Packit c32a2d
	{
Packit c32a2d
		fr->err = MPG123_BAD_DECODER_SETUP;
Packit c32a2d
		return MPG123_ERR;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	if(frame_buffers(fr) != 0)
Packit c32a2d
	{
Packit c32a2d
		fr->err = MPG123_NO_BUFFERS;
Packit c32a2d
		if(NOQUIET) error("Failed to set up decoder buffers!");
Packit c32a2d
Packit c32a2d
		return MPG123_ERR;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
#ifndef NO_8BIT
Packit c32a2d
	if(basic_format == f_8)
Packit c32a2d
	{
Packit c32a2d
		if(make_conv16to8_table(fr) != 0)
Packit c32a2d
		{
Packit c32a2d
			if(NOQUIET) error("Failed to set up conv16to8 table!");
Packit c32a2d
			/* it's a bit more work to get proper error propagation up */
Packit c32a2d
			return -1;
Packit c32a2d
		}
Packit c32a2d
	}
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#ifdef OPT_MMXORSSE
Packit c32a2d
	/* Special treatment for MMX, SSE and 3DNowExt stuff.
Packit c32a2d
	   The real-decoding SSE for x86-64 uses normal tables! */
Packit c32a2d
	if(fr->cpu_opts.class == mmxsse
Packit c32a2d
#	ifndef NO_REAL
Packit c32a2d
	   && basic_format != f_real
Packit c32a2d
#	endif
Packit c32a2d
#	ifndef NO_32BIT
Packit c32a2d
	   && basic_format != f_32
Packit c32a2d
#	endif
Packit c32a2d
#	ifdef ACCURATE_ROUNDING
Packit c32a2d
	   && fr->cpu_opts.type != sse
Packit c32a2d
	   && fr->cpu_opts.type != sse_vintage
Packit c32a2d
	   && fr->cpu_opts.type != x86_64
Packit c32a2d
	   && fr->cpu_opts.type != neon
Packit c32a2d
	   && fr->cpu_opts.type != neon64
Packit c32a2d
	   && fr->cpu_opts.type != avx
Packit c32a2d
#	endif
Packit c32a2d
	  )
Packit c32a2d
	{
Packit c32a2d
#ifndef NO_LAYER3
Packit c32a2d
		init_layer3_stuff(fr, init_layer3_gainpow2_mmx);
Packit c32a2d
#endif
Packit c32a2d
#ifndef NO_LAYER12
Packit c32a2d
		init_layer12_stuff(fr, init_layer12_table_mmx);
Packit c32a2d
#endif
Packit c32a2d
		fr->make_decode_tables = make_decode_tables_mmx;
Packit c32a2d
	}
Packit c32a2d
	else
Packit c32a2d
#endif
Packit c32a2d
	{
Packit c32a2d
#ifndef NO_LAYER3
Packit c32a2d
		init_layer3_stuff(fr, init_layer3_gainpow2);
Packit c32a2d
#endif
Packit c32a2d
#ifndef NO_LAYER12
Packit c32a2d
		init_layer12_stuff(fr, init_layer12_table);
Packit c32a2d
#endif
Packit c32a2d
		fr->make_decode_tables = make_decode_tables;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	/* We allocated the table buffers just now, so (re)create the tables. */
Packit c32a2d
	fr->make_decode_tables(fr);
Packit c32a2d
Packit c32a2d
	return 0;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
int frame_cpu_opt(mpg123_handle *fr, const char* cpu)
Packit c32a2d
{
Packit c32a2d
	const char* chosen = ""; /* the chosen decoder opt as string */
Packit c32a2d
	enum optdec want_dec = nodec;
Packit c32a2d
	int done = 0;
Packit c32a2d
	int auto_choose = 0;
Packit c32a2d
#ifdef OPT_DITHER
Packit c32a2d
	int dithered = FALSE; /* If some dithered decoder is chosen. */
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
	want_dec = dectype(cpu);
Packit c32a2d
	auto_choose = want_dec == autodec;
Packit c32a2d
	/* Fill whole array of synth functions with generic code first. */
Packit c32a2d
	fr->synths = synth_base;
Packit c32a2d
Packit c32a2d
#ifndef OPT_MULTI
Packit c32a2d
	{
Packit c32a2d
		if(!auto_choose && want_dec != defopt)
Packit c32a2d
		{
Packit c32a2d
			if(NOQUIET) error2("you wanted decoder type %i, I only have %i", want_dec, defopt);
Packit c32a2d
		}
Packit c32a2d
		auto_choose = TRUE; /* There will be only one choice anyway. */
Packit c32a2d
	}
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
	fr->cpu_opts.type = nodec;
Packit c32a2d
#ifdef OPT_MULTI
Packit c32a2d
#ifndef NO_LAYER3
Packit c32a2d
#if (defined OPT_3DNOW_VINTAGE || defined OPT_3DNOWEXT_VINTAGE || defined OPT_SSE || defined OPT_X86_64 || defined OPT_AVX || defined OPT_NEON || defined OPT_NEON64)
Packit c32a2d
	fr->cpu_opts.the_dct36 = dct36;
Packit c32a2d
#endif
Packit c32a2d
#endif
Packit c32a2d
#endif
Packit c32a2d
	/* covers any i386+ cpu; they actually differ only in the synth_1to1 function, mostly... */
Packit c32a2d
#ifdef OPT_X86
Packit c32a2d
	if(cpu_i586(cpu_flags))
Packit c32a2d
	{
Packit c32a2d
#		ifdef OPT_MULTI
Packit c32a2d
		debug2("standard flags: 0x%08x\textended flags: 0x%08x", cpu_flags.std, cpu_flags.ext);
Packit c32a2d
#		endif
Packit c32a2d
#		ifdef OPT_SSE
Packit c32a2d
		if(   !done && (auto_choose || want_dec == sse)
Packit c32a2d
		   && cpu_sse(cpu_flags) && cpu_mmx(cpu_flags) )
Packit c32a2d
		{
Packit c32a2d
			chosen = dn_sse;
Packit c32a2d
			fr->cpu_opts.type = sse;
Packit c32a2d
#ifdef OPT_MULTI
Packit c32a2d
#			ifndef NO_LAYER3
Packit c32a2d
			/* if(cpu_fast_sse(cpu_flags)) */ fr->cpu_opts.the_dct36 = dct36_sse;
Packit c32a2d
#			endif
Packit c32a2d
#endif
Packit c32a2d
#			ifndef NO_16BIT
Packit c32a2d
			fr->synths.plain[r_1to1][f_16] = synth_1to1_sse;
Packit c32a2d
#			ifdef ACCURATE_ROUNDING
Packit c32a2d
			fr->synths.stereo[r_1to1][f_16] = synth_1to1_stereo_sse;
Packit c32a2d
#			endif
Packit c32a2d
#			endif
Packit c32a2d
#			ifndef NO_REAL
Packit c32a2d
			fr->synths.plain[r_1to1][f_real] = synth_1to1_real_sse;
Packit c32a2d
			fr->synths.stereo[r_1to1][f_real] = synth_1to1_real_stereo_sse;
Packit c32a2d
#			endif
Packit c32a2d
#			ifndef NO_32BIT
Packit c32a2d
			fr->synths.plain[r_1to1][f_32] = synth_1to1_s32_sse;
Packit c32a2d
			fr->synths.stereo[r_1to1][f_32] = synth_1to1_s32_stereo_sse;
Packit c32a2d
#			endif
Packit c32a2d
			done = 1;
Packit c32a2d
		}
Packit c32a2d
#		endif
Packit c32a2d
#		ifdef OPT_SSE_VINTAGE
Packit c32a2d
		if(   !done && (auto_choose || want_dec == sse_vintage)
Packit c32a2d
		   && cpu_sse(cpu_flags) && cpu_mmx(cpu_flags) )
Packit c32a2d
		{
Packit c32a2d
			chosen = dn_sse_vintage;
Packit c32a2d
			fr->cpu_opts.type = sse_vintage;
Packit c32a2d
#			ifndef NO_16BIT
Packit c32a2d
			fr->synths.plain[r_1to1][f_16] = synth_1to1_sse;
Packit c32a2d
#			ifdef ACCURATE_ROUNDING
Packit c32a2d
			fr->synths.stereo[r_1to1][f_16] = synth_1to1_stereo_sse;
Packit c32a2d
#			endif
Packit c32a2d
#			endif
Packit c32a2d
#			ifndef NO_REAL
Packit c32a2d
			fr->synths.plain[r_1to1][f_real] = synth_1to1_real_sse;
Packit c32a2d
			fr->synths.stereo[r_1to1][f_real] = synth_1to1_real_stereo_sse;
Packit c32a2d
#			endif
Packit c32a2d
#			ifndef NO_32BIT
Packit c32a2d
			fr->synths.plain[r_1to1][f_32] = synth_1to1_s32_sse;
Packit c32a2d
			fr->synths.stereo[r_1to1][f_32] = synth_1to1_s32_stereo_sse;
Packit c32a2d
#			endif
Packit c32a2d
			done = 1;
Packit c32a2d
		}
Packit c32a2d
#		endif
Packit c32a2d
#		ifdef OPT_3DNOWEXT
Packit c32a2d
		if(   !done && (auto_choose || want_dec == dreidnowext)
Packit c32a2d
		   && cpu_3dnow(cpu_flags)
Packit c32a2d
		   && cpu_3dnowext(cpu_flags)
Packit c32a2d
		   && cpu_mmx(cpu_flags) )
Packit c32a2d
		{
Packit c32a2d
			chosen = dn_dreidnowext;
Packit c32a2d
			fr->cpu_opts.type = dreidnowext;
Packit c32a2d
#			ifndef NO_16BIT
Packit c32a2d
			fr->synths.plain[r_1to1][f_16] = synth_1to1_3dnowext;
Packit c32a2d
#			endif
Packit c32a2d
			done = 1;
Packit c32a2d
		}
Packit c32a2d
#		endif
Packit c32a2d
#		ifdef OPT_3DNOWEXT_VINTAGE
Packit c32a2d
		if(   !done && (auto_choose || want_dec == dreidnowext_vintage)
Packit c32a2d
		   && cpu_3dnow(cpu_flags)
Packit c32a2d
		   && cpu_3dnowext(cpu_flags)
Packit c32a2d
		   && cpu_mmx(cpu_flags) )
Packit c32a2d
		{
Packit c32a2d
			chosen = dn_dreidnowext_vintage;
Packit c32a2d
			fr->cpu_opts.type = dreidnowext_vintage;
Packit c32a2d
#ifdef OPT_MULTI
Packit c32a2d
#			ifndef NO_LAYER3
Packit c32a2d
			fr->cpu_opts.the_dct36 = dct36_3dnowext;
Packit c32a2d
#			endif
Packit c32a2d
#endif
Packit c32a2d
#			ifndef NO_16BIT
Packit c32a2d
			fr->synths.plain[r_1to1][f_16] = synth_1to1_3dnowext;
Packit c32a2d
#			endif
Packit c32a2d
			done = 1;
Packit c32a2d
		}
Packit c32a2d
#		endif
Packit c32a2d
#		ifdef OPT_3DNOW
Packit c32a2d
		if(    !done && (auto_choose || want_dec == dreidnow)
Packit c32a2d
		    && cpu_3dnow(cpu_flags) && cpu_mmx(cpu_flags) )
Packit c32a2d
		{
Packit c32a2d
			chosen = dn_dreidnow;
Packit c32a2d
			fr->cpu_opts.type = dreidnow;
Packit c32a2d
#			ifndef NO_16BIT
Packit c32a2d
			fr->synths.plain[r_1to1][f_16] = synth_1to1_3dnow;
Packit c32a2d
#			endif
Packit c32a2d
			done = 1;
Packit c32a2d
		}
Packit c32a2d
#		endif
Packit c32a2d
#		ifdef OPT_3DNOW_VINTAGE
Packit c32a2d
		if(    !done && (auto_choose || want_dec == dreidnow_vintage)
Packit c32a2d
		    && cpu_3dnow(cpu_flags) && cpu_mmx(cpu_flags) )
Packit c32a2d
		{
Packit c32a2d
			chosen = dn_dreidnow_vintage;
Packit c32a2d
			fr->cpu_opts.type = dreidnow_vintage;
Packit c32a2d
#ifdef OPT_MULTI
Packit c32a2d
#			ifndef NO_LAYER3
Packit c32a2d
			fr->cpu_opts.the_dct36 = dct36_3dnow;
Packit c32a2d
#			endif
Packit c32a2d
#endif
Packit c32a2d
#			ifndef NO_16BIT
Packit c32a2d
			fr->synths.plain[r_1to1][f_16] = synth_1to1_3dnow;
Packit c32a2d
#			endif
Packit c32a2d
			done = 1;
Packit c32a2d
		}
Packit c32a2d
#		endif
Packit c32a2d
		#ifdef OPT_MMX
Packit c32a2d
		if(   !done && (auto_choose || want_dec == mmx)
Packit c32a2d
		   && cpu_mmx(cpu_flags) )
Packit c32a2d
		{
Packit c32a2d
			chosen = dn_mmx;
Packit c32a2d
			fr->cpu_opts.type = mmx;
Packit c32a2d
#			ifndef NO_16BIT
Packit c32a2d
			fr->synths.plain[r_1to1][f_16] = synth_1to1_mmx;
Packit c32a2d
#			endif
Packit c32a2d
			done = 1;
Packit c32a2d
		}
Packit c32a2d
		#endif
Packit c32a2d
		#ifdef OPT_I586
Packit c32a2d
		if(!done && (auto_choose || want_dec == ifuenf))
Packit c32a2d
		{
Packit c32a2d
			chosen = "i586/pentium";
Packit c32a2d
			fr->cpu_opts.type = ifuenf;
Packit c32a2d
#			ifndef NO_16BIT
Packit c32a2d
			fr->synths.plain[r_1to1][f_16] = synth_1to1_i586;
Packit c32a2d
#			endif
Packit c32a2d
			done = 1;
Packit c32a2d
		}
Packit c32a2d
		#endif
Packit c32a2d
		#ifdef OPT_I586_DITHER
Packit c32a2d
		if(!done && (auto_choose || want_dec == ifuenf_dither))
Packit c32a2d
		{
Packit c32a2d
			chosen = "dithered i586/pentium";
Packit c32a2d
			fr->cpu_opts.type = ifuenf_dither;
Packit c32a2d
			dithered = TRUE;
Packit c32a2d
#			ifndef NO_16BIT
Packit c32a2d
			fr->synths.plain[r_1to1][f_16] = synth_1to1_i586_dither;
Packit c32a2d
#			ifndef NO_DOWNSAMPLE
Packit c32a2d
			fr->synths.plain[r_2to1][f_16] = synth_2to1_dither;
Packit c32a2d
			fr->synths.plain[r_4to1][f_16] = synth_4to1_dither;
Packit c32a2d
#			endif
Packit c32a2d
#			endif
Packit c32a2d
			done = 1;
Packit c32a2d
		}
Packit c32a2d
		#endif
Packit c32a2d
	}
Packit c32a2d
	#ifdef OPT_I486
Packit c32a2d
	/* That won't cooperate in multi opt mode - forcing i486 in layer3.c
Packit c32a2d
	   But still... here it is... maybe for real use in future. */
Packit c32a2d
	if(!done && (auto_choose || want_dec == ivier))
Packit c32a2d
	{
Packit c32a2d
		chosen = dn_ivier;
Packit c32a2d
		fr->cpu_opts.type = ivier;
Packit c32a2d
		done = 1;
Packit c32a2d
	}
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_I386
Packit c32a2d
	if(!done && (auto_choose || want_dec == idrei))
Packit c32a2d
	{
Packit c32a2d
		chosen = dn_idrei;
Packit c32a2d
		fr->cpu_opts.type = idrei;
Packit c32a2d
		done = 1;
Packit c32a2d
	}
Packit c32a2d
	#endif
Packit c32a2d
Packit c32a2d
	if(done)
Packit c32a2d
	{
Packit c32a2d
		/*
Packit c32a2d
			We have chosen some x86 decoder... fillup some i386 stuff.
Packit c32a2d
			There is an open question about using dithered synth_1to1 for 8bit wrappers.
Packit c32a2d
			For quality it won't make sense, but wrapped i586_dither wrapped may still be faster...
Packit c32a2d
		*/
Packit c32a2d
		enum synth_resample ri;
Packit c32a2d
		enum synth_format   fi;
Packit c32a2d
#		ifndef NO_8BIT
Packit c32a2d
#		ifndef NO_16BIT /* possibility to use a 16->8 wrapper... */
Packit c32a2d
		if(fr->synths.plain[r_1to1][f_16] != synth_base.plain[r_1to1][f_16])
Packit c32a2d
		{
Packit c32a2d
			fr->synths.plain[r_1to1][f_8] = synth_1to1_8bit_wrap;
Packit c32a2d
			fr->synths.mono[r_1to1][f_8] = synth_1to1_8bit_wrap_mono;
Packit c32a2d
			fr->synths.mono2stereo[r_1to1][f_8] = synth_1to1_8bit_wrap_m2s;
Packit c32a2d
		}
Packit c32a2d
#		endif
Packit c32a2d
#		endif
Packit c32a2d
		for(ri=0; ri
Packit c32a2d
		for(fi=0; fi
Packit c32a2d
		{
Packit c32a2d
			if(fr->synths.plain[ri][fi] == synth_base.plain[ri][fi])
Packit c32a2d
			fr->synths.plain[ri][fi] = plain_i386[ri][fi];
Packit c32a2d
		}
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
#endif /* OPT_X86 */
Packit c32a2d
Packit c32a2d
#ifdef OPT_AVX
Packit c32a2d
	if(!done && (auto_choose || want_dec == avx) && cpu_avx(cpu_flags))
Packit c32a2d
	{
Packit c32a2d
		chosen = "x86-64 (AVX)";
Packit c32a2d
		fr->cpu_opts.type = avx;
Packit c32a2d
#ifdef OPT_MULTI
Packit c32a2d
#		ifndef NO_LAYER3
Packit c32a2d
		fr->cpu_opts.the_dct36 = dct36_avx;
Packit c32a2d
#		endif
Packit c32a2d
#endif
Packit c32a2d
#		ifndef NO_16BIT
Packit c32a2d
		fr->synths.plain[r_1to1][f_16] = synth_1to1_avx;
Packit c32a2d
		fr->synths.stereo[r_1to1][f_16] = synth_1to1_stereo_avx;
Packit c32a2d
#		endif
Packit c32a2d
#		ifndef NO_REAL
Packit c32a2d
		fr->synths.plain[r_1to1][f_real] = synth_1to1_real_avx;
Packit c32a2d
		fr->synths.stereo[r_1to1][f_real] = synth_1to1_fltst_avx;
Packit c32a2d
#		endif
Packit c32a2d
#		ifndef NO_32BIT
Packit c32a2d
		fr->synths.plain[r_1to1][f_32] = synth_1to1_s32_avx;
Packit c32a2d
		fr->synths.stereo[r_1to1][f_32] = synth_1to1_s32_stereo_avx;
Packit c32a2d
#		endif
Packit c32a2d
		done = 1;
Packit c32a2d
	}
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#ifdef OPT_X86_64
Packit c32a2d
	if(!done && (auto_choose || want_dec == x86_64))
Packit c32a2d
	{
Packit c32a2d
		chosen = "x86-64 (SSE)";
Packit c32a2d
		fr->cpu_opts.type = x86_64;
Packit c32a2d
#ifdef OPT_MULTI
Packit c32a2d
#		ifndef NO_LAYER3
Packit c32a2d
		fr->cpu_opts.the_dct36 = dct36_x86_64;
Packit c32a2d
#		endif
Packit c32a2d
#endif
Packit c32a2d
#		ifndef NO_16BIT
Packit c32a2d
		fr->synths.plain[r_1to1][f_16] = synth_1to1_x86_64;
Packit c32a2d
		fr->synths.stereo[r_1to1][f_16] = synth_1to1_stereo_x86_64;
Packit c32a2d
#		endif
Packit c32a2d
#		ifndef NO_REAL
Packit c32a2d
		fr->synths.plain[r_1to1][f_real] = synth_1to1_real_x86_64;
Packit c32a2d
		fr->synths.stereo[r_1to1][f_real] = synth_1to1_real_stereo_x86_64;
Packit c32a2d
#		endif
Packit c32a2d
#		ifndef NO_32BIT
Packit c32a2d
		fr->synths.plain[r_1to1][f_32] = synth_1to1_s32_x86_64;
Packit c32a2d
		fr->synths.stereo[r_1to1][f_32] = synth_1to1_s32_stereo_x86_64;
Packit c32a2d
#		endif
Packit c32a2d
		done = 1;
Packit c32a2d
	}
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#	ifdef OPT_ALTIVEC
Packit c32a2d
	if(!done && (auto_choose || want_dec == altivec))
Packit c32a2d
	{
Packit c32a2d
		chosen = dn_altivec;
Packit c32a2d
		fr->cpu_opts.type = altivec;
Packit c32a2d
#		ifndef NO_16BIT
Packit c32a2d
		fr->synths.plain[r_1to1][f_16] = synth_1to1_altivec;
Packit c32a2d
		fr->synths.stereo[r_1to1][f_16] = synth_1to1_stereo_altivec;
Packit c32a2d
#		endif
Packit c32a2d
#		ifndef NO_REAL
Packit c32a2d
		fr->synths.plain[r_1to1][f_real] = synth_1to1_real_altivec;
Packit c32a2d
		fr->synths.stereo[r_1to1][f_real] = synth_1to1_fltst_altivec;
Packit c32a2d
#		endif
Packit c32a2d
#		ifndef NO_32BIT
Packit c32a2d
		fr->synths.plain[r_1to1][f_32] = synth_1to1_s32_altivec;
Packit c32a2d
		fr->synths.stereo[r_1to1][f_32] = synth_1to1_s32_stereo_altivec;
Packit c32a2d
#		endif
Packit c32a2d
		done = 1;
Packit c32a2d
	}
Packit c32a2d
#	endif
Packit c32a2d
Packit c32a2d
#	ifdef OPT_NEON
Packit c32a2d
	if(!done && (auto_choose || want_dec == neon) && cpu_neon(cpu_flags))
Packit c32a2d
	{
Packit c32a2d
		chosen = dn_neon;
Packit c32a2d
		fr->cpu_opts.type = neon;
Packit c32a2d
#ifdef OPT_MULTI
Packit c32a2d
#		ifndef NO_LAYER3
Packit c32a2d
		fr->cpu_opts.the_dct36 = dct36_neon;
Packit c32a2d
#		endif
Packit c32a2d
#endif
Packit c32a2d
#		ifndef NO_16BIT
Packit c32a2d
		fr->synths.plain[r_1to1][f_16] = synth_1to1_neon;
Packit c32a2d
		fr->synths.stereo[r_1to1][f_16] = synth_1to1_stereo_neon;
Packit c32a2d
#		endif
Packit c32a2d
#		ifndef NO_REAL
Packit c32a2d
		fr->synths.plain[r_1to1][f_real] = synth_1to1_real_neon;
Packit c32a2d
		fr->synths.stereo[r_1to1][f_real] = synth_1to1_real_stereo_neon;
Packit c32a2d
#		endif
Packit c32a2d
#		ifndef NO_32BIT
Packit c32a2d
		fr->synths.plain[r_1to1][f_32] = synth_1to1_s32_neon;
Packit c32a2d
		fr->synths.stereo[r_1to1][f_32] = synth_1to1_s32_stereo_neon;
Packit c32a2d
#		endif
Packit c32a2d
		done = 1;
Packit c32a2d
	}
Packit c32a2d
#	endif
Packit c32a2d
Packit c32a2d
#	ifdef OPT_ARM
Packit c32a2d
	if(!done && (auto_choose || want_dec == arm))
Packit c32a2d
	{
Packit c32a2d
		chosen = dn_arm;
Packit c32a2d
		fr->cpu_opts.type = arm;
Packit c32a2d
#		ifndef NO_16BIT
Packit c32a2d
		fr->synths.plain[r_1to1][f_16] = synth_1to1_arm;
Packit c32a2d
#		endif
Packit c32a2d
		done = 1;
Packit c32a2d
	}
Packit c32a2d
#	endif
Packit c32a2d
Packit c32a2d
#	ifdef OPT_NEON64
Packit c32a2d
	if(!done && (auto_choose || want_dec == neon64) && cpu_neon(cpu_flags))
Packit c32a2d
	{
Packit c32a2d
		chosen = dn_neon64;
Packit c32a2d
		fr->cpu_opts.type = neon64;
Packit c32a2d
#ifdef OPT_MULTI
Packit c32a2d
#		ifndef NO_LAYER3
Packit c32a2d
		fr->cpu_opts.the_dct36 = dct36_neon64;
Packit c32a2d
#		endif
Packit c32a2d
#endif
Packit c32a2d
#		ifndef NO_16BIT
Packit c32a2d
		fr->synths.plain[r_1to1][f_16] = synth_1to1_neon64;
Packit c32a2d
		fr->synths.stereo[r_1to1][f_16] = synth_1to1_stereo_neon64;
Packit c32a2d
#		endif
Packit c32a2d
#		ifndef NO_REAL
Packit c32a2d
		fr->synths.plain[r_1to1][f_real] = synth_1to1_real_neon64;
Packit c32a2d
		fr->synths.stereo[r_1to1][f_real] = synth_1to1_fltst_neon64;
Packit c32a2d
#		endif
Packit c32a2d
#		ifndef NO_32BIT
Packit c32a2d
		fr->synths.plain[r_1to1][f_32] = synth_1to1_s32_neon64;
Packit c32a2d
		fr->synths.stereo[r_1to1][f_32] = synth_1to1_s32st_neon64;
Packit c32a2d
#		endif
Packit c32a2d
		done = 1;
Packit c32a2d
	}
Packit c32a2d
#	endif
Packit c32a2d
Packit c32a2d
#	ifdef OPT_GENERIC
Packit c32a2d
	if(!done && (auto_choose || want_dec == generic))
Packit c32a2d
	{
Packit c32a2d
		chosen = dn_generic;
Packit c32a2d
		fr->cpu_opts.type = generic;
Packit c32a2d
		done = 1;
Packit c32a2d
	}
Packit c32a2d
#	endif
Packit c32a2d
Packit c32a2d
#ifdef OPT_GENERIC_DITHER
Packit c32a2d
	if(!done && (auto_choose || want_dec == generic_dither))
Packit c32a2d
	{
Packit c32a2d
		chosen = "dithered generic";
Packit c32a2d
		fr->cpu_opts.type = generic_dither;
Packit c32a2d
		dithered = TRUE;
Packit c32a2d
#		ifndef NO_16BIT
Packit c32a2d
		fr->synths.plain[r_1to1][f_16] = synth_1to1_dither;
Packit c32a2d
#		ifndef NO_DOWNSAMPLE
Packit c32a2d
		fr->synths.plain[r_2to1][f_16] = synth_2to1_dither;
Packit c32a2d
		fr->synths.plain[r_4to1][f_16] = synth_4to1_dither;
Packit c32a2d
#		endif
Packit c32a2d
#		endif
Packit c32a2d
		done = 1;
Packit c32a2d
	}
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
	fr->cpu_opts.class = decclass(fr->cpu_opts.type);
Packit c32a2d
Packit c32a2d
#	ifndef NO_8BIT
Packit c32a2d
#	ifndef NO_16BIT /* possibility to use a 16->8 wrapper... */
Packit c32a2d
	/* Last chance to use some optimized routine via generic wrappers (for 8bit). */
Packit c32a2d
	if(     fr->cpu_opts.type != ifuenf_dither
Packit c32a2d
	     && fr->cpu_opts.type != generic_dither
Packit c32a2d
	     && fr->synths.plain[r_1to1][f_16] != synth_base.plain[r_1to1][f_16] )
Packit c32a2d
	{
Packit c32a2d
		fr->synths.plain[r_1to1][f_8] = synth_1to1_8bit_wrap;
Packit c32a2d
		fr->synths.mono[r_1to1][f_8] = synth_1to1_8bit_wrap_mono;
Packit c32a2d
		fr->synths.mono2stereo[r_1to1][f_8] = synth_1to1_8bit_wrap_m2s;
Packit c32a2d
	}
Packit c32a2d
#	endif
Packit c32a2d
#	endif
Packit c32a2d
Packit c32a2d
#ifdef OPT_DITHER
Packit c32a2d
	if(done && dithered)
Packit c32a2d
	{
Packit c32a2d
		/* run-time dither noise table generation */
Packit c32a2d
		if(!frame_dither_init(fr))
Packit c32a2d
		{
Packit c32a2d
			if(NOQUIET) error("Dither noise setup failed!");
Packit c32a2d
			return 0;
Packit c32a2d
		}
Packit c32a2d
	}
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
	if(done)
Packit c32a2d
	{
Packit c32a2d
		if(VERBOSE) fprintf(stderr, "Decoder: %s\n", chosen);
Packit c32a2d
		return 1;
Packit c32a2d
	}
Packit c32a2d
	else
Packit c32a2d
	{
Packit c32a2d
		if(NOQUIET) error("Could not set optimization!");
Packit c32a2d
		return 0;
Packit c32a2d
	}
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
enum optdec dectype(const char* decoder)
Packit c32a2d
{
Packit c32a2d
	enum optdec dt;
Packit c32a2d
	if(   (decoder == NULL)
Packit c32a2d
	   || (decoder[0] == 0) )
Packit c32a2d
	return autodec;
Packit c32a2d
Packit c32a2d
	for(dt=autodec; dt
Packit c32a2d
	if(!strcasecmp(decoder, decname[dt])) return dt;
Packit c32a2d
Packit c32a2d
	return nodec; /* If we found nothing... */
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
#ifdef OPT_MULTI
Packit c32a2d
Packit c32a2d
/* same number of entries as full list, but empty at beginning */
Packit c32a2d
static const char *mpg123_supported_decoder_list[] =
Packit c32a2d
{
Packit c32a2d
	#ifdef OPT_SSE
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_SSE_VINTAGE
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_3DNOWEXT
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_3DNOWEXT_VINTAGE
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_3DNOW
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_3DNOW_VINTAGE
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_MMX
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_I586
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_I586_DITHER
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_I486
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_I386
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_ALTIVEC
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_AVX
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_X86_64
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_ARM
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_NEON
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_NEON64
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_GENERIC_FLOAT
Packit c32a2d
	NULL,
Packit c32a2d
	#endif
Packit c32a2d
#	ifdef OPT_GENERIC
Packit c32a2d
	NULL,
Packit c32a2d
#	endif
Packit c32a2d
#	ifdef OPT_GENERIC_DITHER
Packit c32a2d
	NULL,
Packit c32a2d
#	endif
Packit c32a2d
	NULL
Packit c32a2d
};
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
static const char *mpg123_decoder_list[] =
Packit c32a2d
{
Packit c32a2d
	#ifdef OPT_SSE
Packit c32a2d
	dn_sse,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_SSE_VINTAGE
Packit c32a2d
	dn_sse_vintage,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_3DNOWEXT
Packit c32a2d
	dn_dreidnowext,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_3DNOWEXT_VINTAGE
Packit c32a2d
	dn_dreidnowext_vintage,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_3DNOW
Packit c32a2d
	dn_dreidnow,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_3DNOW_VINTAGE
Packit c32a2d
	dn_dreidnow_vintage,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_MMX
Packit c32a2d
	dn_mmx,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_I586
Packit c32a2d
	dn_ifuenf,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_I586_DITHER
Packit c32a2d
	dn_ifuenf_dither,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_I486
Packit c32a2d
	dn_ivier,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_I386
Packit c32a2d
	dn_idrei,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_ALTIVEC
Packit c32a2d
	dn_altivec,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_AVX
Packit c32a2d
	dn_avx,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_X86_64
Packit c32a2d
	dn_x86_64,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_ARM
Packit c32a2d
	dn_arm,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_NEON
Packit c32a2d
	dn_neon,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_NEON64
Packit c32a2d
	dn_neon64,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_GENERIC
Packit c32a2d
	dn_generic,
Packit c32a2d
	#endif
Packit c32a2d
	#ifdef OPT_GENERIC_DITHER
Packit c32a2d
	dn_generic_dither,
Packit c32a2d
	#endif
Packit c32a2d
	NULL
Packit c32a2d
};
Packit c32a2d
Packit c32a2d
void check_decoders(void )
Packit c32a2d
{
Packit c32a2d
#ifndef OPT_MULTI
Packit c32a2d
	/* In non-multi mode, only the full list (one entry) is used. */
Packit c32a2d
	return;
Packit c32a2d
#else
Packit c32a2d
	const char **d = mpg123_supported_decoder_list;
Packit c32a2d
#if (defined OPT_X86) || (defined OPT_X86_64) || (defined OPT_NEON) || (defined OPT_NEON64)
Packit c32a2d
	getcpuflags(&cpu_flags);
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_X86
Packit c32a2d
	if(cpu_i586(cpu_flags))
Packit c32a2d
	{
Packit c32a2d
		/* not yet: if(cpu_sse2(cpu_flags)) printf(" SSE2");
Packit c32a2d
		if(cpu_sse3(cpu_flags)) printf(" SSE3"); */
Packit c32a2d
#ifdef OPT_SSE
Packit c32a2d
		if(cpu_sse(cpu_flags)) *(d++) = dn_sse;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_SSE_VINTAGE
Packit c32a2d
		if(cpu_sse(cpu_flags)) *(d++) = dn_sse_vintage;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_3DNOWEXT
Packit c32a2d
		if(cpu_3dnowext(cpu_flags)) *(d++) = dn_dreidnowext;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_3DNOWEXT_VINTAGE
Packit c32a2d
		if(cpu_3dnowext(cpu_flags)) *(d++) = dn_dreidnowext_vintage;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_3DNOW
Packit c32a2d
		if(cpu_3dnow(cpu_flags)) *(d++) = dn_dreidnow;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_3DNOW_VINTAGE
Packit c32a2d
		if(cpu_3dnow(cpu_flags)) *(d++) = dn_dreidnow_vintage;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_MMX
Packit c32a2d
		if(cpu_mmx(cpu_flags)) *(d++) = dn_mmx;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_I586
Packit c32a2d
		*(d++) = dn_ifuenf;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_I586_DITHER
Packit c32a2d
		*(d++) = dn_ifuenf_dither;
Packit c32a2d
#endif
Packit c32a2d
	}
Packit c32a2d
#endif
Packit c32a2d
/* just assume that the i486 built is run on a i486 cpu... */
Packit c32a2d
#ifdef OPT_I486
Packit c32a2d
	*(d++) = dn_ivier;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_ALTIVEC
Packit c32a2d
	*(d++) = dn_altivec;
Packit c32a2d
#endif
Packit c32a2d
/* every supported x86 can do i386, any cpu can do generic */
Packit c32a2d
#ifdef OPT_I386
Packit c32a2d
	*(d++) = dn_idrei;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_AVX
Packit c32a2d
	if(cpu_avx(cpu_flags)) *(d++) = dn_avx;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_X86_64
Packit c32a2d
	*(d++) = dn_x86_64;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_ARM
Packit c32a2d
	*(d++) = dn_arm;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_NEON
Packit c32a2d
	if(cpu_neon(cpu_flags)) *(d++) = dn_neon;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_NEON64
Packit c32a2d
	if(cpu_neon(cpu_flags)) *(d++) = dn_neon64;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_GENERIC
Packit c32a2d
	*(d++) = dn_generic;
Packit c32a2d
#endif
Packit c32a2d
#ifdef OPT_GENERIC_DITHER
Packit c32a2d
	*(d++) = dn_generic_dither;
Packit c32a2d
#endif
Packit c32a2d
#endif /* ndef OPT_MULTI */
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
const char* attribute_align_arg mpg123_current_decoder(mpg123_handle *mh)
Packit c32a2d
{
Packit c32a2d
	if(mh == NULL) return NULL;
Packit c32a2d
Packit c32a2d
	return decname[mh->cpu_opts.type];
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
const char attribute_align_arg **mpg123_decoders(void){ return mpg123_decoder_list; }
Packit c32a2d
const char attribute_align_arg **mpg123_supported_decoders(void)
Packit c32a2d
{
Packit c32a2d
#ifdef OPT_MULTI
Packit c32a2d
	return mpg123_supported_decoder_list;
Packit c32a2d
#else
Packit c32a2d
	return mpg123_decoder_list;
Packit c32a2d
#endif
Packit c32a2d
}