#include "cpu-x86.h"
#include "sconv.h"
-#if !defined(__APPLE__) && defined (__i386__) || defined (__amd64__)
+#if (!defined(__APPLE__) && !defined(__FreeBSD__) && defined (__i386__)) || defined (__amd64__)
-static const PA_DECLARE_ALIGNED (16, float, one[4]) = { 1.0, 1.0, 1.0, 1.0 };
-static const PA_DECLARE_ALIGNED (16, float, mone[4]) = { -1.0, -1.0, -1.0, -1.0 };
-static const PA_DECLARE_ALIGNED (16, float, scale[4]) = { 0x7fff, 0x7fff, 0x7fff, 0x7fff };
+static const PA_DECLARE_ALIGNED (16, float, scale[4]) = { 0x8000, 0x8000, 0x8000, 0x8000 };
static void pa_sconv_s16le_from_f32ne_sse(unsigned n, const float *a, int16_t *b) {
pa_reg_x86 temp, i;
__asm__ __volatile__ (
" movaps %5, %%xmm5 \n\t"
- " movaps %6, %%xmm6 \n\t"
- " movaps %7, %%xmm7 \n\t"
" xor %0, %0 \n\t"
" mov %4, %1 \n\t"
"1: \n\t"
" movups (%q2, %0, 2), %%xmm0 \n\t" /* read 8 floats */
" movups 16(%q2, %0, 2), %%xmm2 \n\t"
- " minps %%xmm5, %%xmm0 \n\t" /* clamp to 1.0 */
- " minps %%xmm5, %%xmm2 \n\t"
- " maxps %%xmm6, %%xmm0 \n\t" /* clamp to -1.0 */
- " maxps %%xmm6, %%xmm2 \n\t"
- " mulps %%xmm7, %%xmm0 \n\t" /* *= 0x7fff */
- " mulps %%xmm7, %%xmm2 \n\t"
+ " mulps %%xmm5, %%xmm0 \n\t" /* *= 0x8000 */
+ " mulps %%xmm5, %%xmm2 \n\t"
" cvtps2pi %%xmm0, %%mm0 \n\t" /* low part to int */
" cvtps2pi %%xmm2, %%mm2 \n\t"
" packssdw %%mm1, %%mm0 \n\t" /* pack parts */
" packssdw %%mm3, %%mm2 \n\t"
" movq %%mm0, (%q3, %0) \n\t"
- " movq %%mm2, 8(%q3, %0) \n\t"
+ " movq %%mm2, 8(%q3, %0) \n\t"
" add $16, %0 \n\t"
" dec %1 \n\t"
"2: \n\t"
" mov %4, %1 \n\t" /* prepare for leftovers */
" and $7, %1 \n\t"
- " je 4f \n\t"
+ " je 5f \n\t"
"3: \n\t"
" movss (%q2, %0, 2), %%xmm0 \n\t"
- " minss %%xmm5, %%xmm0 \n\t"
- " maxss %%xmm6, %%xmm0 \n\t"
- " mulss %%xmm7, %%xmm0 \n\t"
+ " mulss %%xmm5, %%xmm0 \n\t"
+ " cvtss2si %%xmm0, %4 \n\t"
+ " add $0x8000, %4 \n\t" /* check for saturation */
+ " and $~0xffff, %4 \n\t"
" cvtss2si %%xmm0, %4 \n\t"
- " movw %w4, (%q3, %0) \n\t"
+ " je 4f \n\t"
+ " sar $31, %4 \n\t"
+ " xor $0x7fff, %4 \n\t"
+
+ "4: \n\t"
+ " movw %w4, (%q3, %0) \n\t" /* store leftover */
" add $2, %0 \n\t"
" dec %1 \n\t"
" jne 3b \n\t"
- "4: \n\t"
+ "5: \n\t"
" emms \n\t"
: "=&r" (i), "=&r" (temp)
- : "r" (a), "r" (b), "r" ((pa_reg_x86)n), "m" (*one), "m" (*mone), "m" (*scale)
+ : "r" (a), "r" (b), "r" ((pa_reg_x86)n), "m" (*scale)
: "cc", "memory"
);
}
__asm__ __volatile__ (
" movaps %5, %%xmm5 \n\t"
- " movaps %6, %%xmm6 \n\t"
- " movaps %7, %%xmm7 \n\t"
" xor %0, %0 \n\t"
" mov %4, %1 \n\t"
"1: \n\t"
" movups (%q2, %0, 2), %%xmm0 \n\t" /* read 8 floats */
" movups 16(%q2, %0, 2), %%xmm2 \n\t"
- " minps %%xmm5, %%xmm0 \n\t" /* clamp to 1.0 */
- " minps %%xmm5, %%xmm2 \n\t"
- " maxps %%xmm6, %%xmm0 \n\t" /* clamp to -1.0 */
- " maxps %%xmm6, %%xmm2 \n\t"
- " mulps %%xmm7, %%xmm0 \n\t" /* *= 0x7fff */
- " mulps %%xmm7, %%xmm2 \n\t"
+ " mulps %%xmm5, %%xmm0 \n\t" /* *= 0x8000 */
+ " mulps %%xmm5, %%xmm2 \n\t"
" cvtps2dq %%xmm0, %%xmm0 \n\t"
" cvtps2dq %%xmm2, %%xmm2 \n\t"
"2: \n\t"
" mov %4, %1 \n\t" /* prepare for leftovers */
" and $7, %1 \n\t"
- " je 4f \n\t"
+ " je 5f \n\t"
"3: \n\t"
" movss (%q2, %0, 2), %%xmm0 \n\t"
- " minss %%xmm5, %%xmm0 \n\t"
- " maxss %%xmm6, %%xmm0 \n\t"
- " mulss %%xmm7, %%xmm0 \n\t"
+ " mulss %%xmm5, %%xmm0 \n\t"
+ " cvtss2si %%xmm0, %4 \n\t"
+ " add $0x8000, %4 \n\t"
+ " and $~0xffff, %4 \n\t" /* check for saturation */
" cvtss2si %%xmm0, %4 \n\t"
- " movw %w4, (%q3, %0) \n\t"
+ " je 4f \n\t"
+ " sar $31, %4 \n\t"
+ " xor $0x7fff, %4 \n\t"
+
+ "4: \n\t"
+ " movw %w4, (%q3, %0) \n\t" /* store leftover */
" add $2, %0 \n\t"
" dec %1 \n\t"
" jne 3b \n\t"
- "4: \n\t"
+ "5: \n\t"
: "=&r" (i), "=&r" (temp)
- : "r" (a), "r" (b), "r" ((pa_reg_x86)n), "m" (*one), "m" (*mone), "m" (*scale)
+ : "r" (a), "r" (b), "r" ((pa_reg_x86)n), "m" (*scale)
: "cc", "memory"
);
}
-#undef RUN_TEST
-
-#ifdef RUN_TEST
-#define SAMPLES 1019
-#define TIMES 1000
-
-static void run_test(void) {
- int16_t samples[SAMPLES];
- int16_t samples_ref[SAMPLES];
- float floats[SAMPLES];
- int i;
- pa_usec_t start, stop;
- pa_convert_func_t func;
-
- printf("checking SSE %zd\n", sizeof(samples));
-
- memset(samples_ref, 0, sizeof(samples_ref));
- memset(samples, 0, sizeof(samples));
-
- for (i = 0; i < SAMPLES; i++) {
- floats[i] = 2.1f * (rand()/(float) RAND_MAX - 0.5f);
- }
-
- func = pa_get_convert_from_float32ne_function(PA_SAMPLE_S16LE);
- func(SAMPLES, floats, samples_ref);
- pa_sconv_s16le_from_f32ne_sse2(SAMPLES, floats, samples);
-
- for (i = 0; i < SAMPLES; i++) {
- if (samples[i] != samples_ref[i]) {
- printf ("%d: %04x != %04x (%f)\n", i, samples[i], samples_ref[i],
- floats[i]);
- }
- }
-
- start = pa_rtclock_now();
- for (i = 0; i < TIMES; i++) {
- pa_sconv_s16le_from_f32ne_sse2(SAMPLES, floats, samples);
- }
- stop = pa_rtclock_now();
- pa_log_info("SSE: %llu usec.", (long long unsigned int)(stop - start));
-
- start = pa_rtclock_now();
- for (i = 0; i < TIMES; i++) {
- func(SAMPLES, floats, samples_ref);
- }
- stop = pa_rtclock_now();
- pa_log_info("ref: %llu usec.", (long long unsigned int)(stop - start));
-}
-#endif
#endif /* defined (__i386__) || defined (__amd64__) */
-
void pa_convert_func_init_sse(pa_cpu_x86_flag_t flags) {
-#if !defined(__APPLE__) && defined (__i386__) || defined (__amd64__)
-
-#ifdef RUN_TEST
- run_test();
-#endif
+#if (!defined(__APPLE__) && !defined(__FreeBSD__) && defined (__i386__)) || defined (__amd64__)
if (flags & PA_CPU_X86_SSE2) {
pa_log_info("Initialising SSE2 optimized conversions.");
pa_set_convert_from_float32ne_function(PA_SAMPLE_S16LE, (pa_convert_func_t) pa_sconv_s16le_from_f32ne_sse2);
- } else {
+
+ } else if (flags & PA_CPU_X86_SSE) {
pa_log_info("Initialising SSE optimized conversions.");
pa_set_convert_from_float32ne_function(PA_SAMPLE_S16LE, (pa_convert_func_t) pa_sconv_s16le_from_f32ne_sse);
}