/* * Copyright 2003-2007 Marcus Overhagen * Copyright 2007 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. */ #include "ByteSwap.h" #include #include #include "MixerDebug.h" static void swap_float(void *buffer, size_t bytecount); static void swap_int32(void *buffer, size_t bytecount); static void swap_int16(void *buffer, size_t bytecount); static void do_nothing(void *buffer, size_t bytecount); ByteSwap::ByteSwap(uint32 format) { switch (format) { case media_raw_audio_format::B_AUDIO_FLOAT: fFunc = &swap_float; break; case media_raw_audio_format::B_AUDIO_INT: fFunc = &swap_int32; break; case media_raw_audio_format::B_AUDIO_SHORT: fFunc = &swap_int16; break; default: fFunc = &do_nothing; break; } } ByteSwap::~ByteSwap() { } void do_nothing(void *buffer, size_t bytecount) { } #if __i386__ // #pragma mark - optimized for IA32 platform void swap_float(void *buffer, size_t bytecount) { // XXX Should be optimized swap_data(B_FLOAT_TYPE, buffer, bytecount, B_SWAP_ALWAYS); } void swap_int32(void *buffer, size_t bytecount) { // XXX Should be optimized swap_data(B_INT32_TYPE, buffer, bytecount, B_SWAP_ALWAYS); } void swap_int16(void *buffer, size_t bytecount) { // GCC FAQ: To write an asm which modifies an input operand but does // not output anything usable, specify that operand as an // output operand outputting to an unused dummy variable. uint32 dummy1; uint32 dummy2; // GCC is way too smart and will remove the complete asm statement // if we do not specify it as __volatile__. Don't remove that! __asm__ __volatile__ ( "pushl %%ebx \n\t" "movl %%eax, %%ebx \n\t" "movl %%edx, %%eax \n\t" "andl $0xFFFFFFE0,%%eax \n\t" "pushl %%eax \n\t" ".L_swap_loop: \n\t" "rolw $8,-32(%%ebx,%%eax) \n\t" "rolw $8,-30(%%ebx,%%eax) \n\t" "rolw $8,-28(%%ebx,%%eax) \n\t" "rolw $8,-26(%%ebx,%%eax) \n\t" "rolw $8,-24(%%ebx,%%eax) \n\t" "rolw $8,-22(%%ebx,%%eax) \n\t" "rolw $8,-20(%%ebx,%%eax) \n\t" "rolw $8,-18(%%ebx,%%eax) \n\t" "rolw $8,-16(%%ebx,%%eax) \n\t" "rolw $8,-14(%%ebx,%%eax) \n\t" "rolw $8,-12(%%ebx,%%eax) \n\t" "rolw $8,-10(%%ebx,%%eax) \n\t" "rolw $8,-8(%%ebx,%%eax) \n\t" "rolw $8,-6(%%ebx,%%eax) \n\t" "rolw $8,-4(%%ebx,%%eax) \n\t" "rolw $8,-2(%%ebx,%%eax) \n\t" "subl $32,%%eax \n\t" "jnz .L_swap_loop \n\t" "popl %%eax \n\t" "addl %%eax,%%ebx \n\t" "andl $0x1F,%%edx \n\t" "jz .L_swap_end \n\t" "addl %%ebx, %%edx \n\t" ".L_swap_loop_2: \n\t" "rolw $8,(%%ebx) \n\t" "addl $2,%%ebx \n\t" "cmpl %%edx,%%ebx \n\t" "jne .L_swap_loop_2 \n\t" ".L_swap_end: \n\t" "popl %%ebx \n\t" : "=a" (dummy1), "=d" (dummy2) : "d" (bytecount), "a" (buffer) : "cc", "memory"); } #else // !__i386__ // #pragma mark - generic versions void swap_float(void *buffer, size_t bytecount) { swap_data(B_FLOAT_TYPE, buffer, bytecount, B_SWAP_ALWAYS); } void swap_int32(void *buffer, size_t bytecount) { swap_data(B_INT32_TYPE, buffer, bytecount, B_SWAP_ALWAYS); } void swap_int16(void *buffer, size_t bytecount) { swap_data(B_INT16_TYPE, buffer, bytecount, B_SWAP_ALWAYS); } #endif