xref: /haiku/src/add-ons/media/media-add-ons/mixer/ByteSwap.cpp (revision 8195a5a835117ab2da405e0d477153570b75d921)
1 /*
2  * Copyright 2003-2007 Marcus Overhagen
3  * Copyright 2007 Haiku Inc. All rights reserved.
4  * Distributed under the terms of the MIT License.
5  */
6 #include "ByteSwap.h"
7 #include "MixerDebug.h"
8 
9 #include <ByteOrder.h>
10 #include <MediaDefs.h>
11 
12 static void swap_float(void *buffer, size_t bytecount);
13 static void swap_int32(void *buffer, size_t bytecount);
14 static void swap_int16(void *buffer, size_t bytecount);
15 static void do_nothing(void *buffer, size_t bytecount);
16 
17 ByteSwap::ByteSwap(uint32 format)
18 {
19 	switch (format) {
20 		case media_raw_audio_format::B_AUDIO_FLOAT:
21 			fFunc = &swap_float;
22 			break;
23 		case media_raw_audio_format::B_AUDIO_INT:
24 			fFunc = &swap_int32;
25 			break;
26 		case media_raw_audio_format::B_AUDIO_SHORT:
27 			fFunc = &swap_int16;
28 			break;
29 		default:
30 			fFunc = &do_nothing;
31 			break;
32 	}
33 }
34 
35 ByteSwap::~ByteSwap()
36 {
37 }
38 
39 void
40 do_nothing(void *buffer, size_t bytecount)
41 {
42 }
43 
44 #if __INTEL__
45 
46 // optimized for IA32 platform
47 
48 void
49 swap_float(void *buffer, size_t bytecount)
50 {
51 	// XXX Should be optimized
52 	swap_data(B_FLOAT_TYPE, buffer, bytecount, B_SWAP_ALWAYS);
53 }
54 
55 void
56 swap_int32(void *buffer, size_t bytecount)
57 {
58 	// XXX Should be optimized
59 	swap_data(B_INT32_TYPE, buffer, bytecount, B_SWAP_ALWAYS);
60 }
61 
62 void
63 swap_int16(void *buffer, size_t bytecount)
64 {
65 	// GCC FAQ: To write an asm which modifies an input operand but does
66 	//          not output anything usable, specify that operand as an
67 	//          output operand outputting to an unused dummy variable.
68 	uint32 dummy1;
69 	uint32 dummy2;
70 	 // GCC is way too smart and will remove the complete asm statement
71 	 // if we do not specify it as __volatile__. Don't remove that!
72 	__asm__ __volatile__ (
73 	"pushl	%%ebx	\n\t"
74 	"movl	%%eax, %%ebx	\n\t"
75 	"movl	%%edx, %%eax	\n\t"
76 	"andl   $0xFFFFFFE0,%%eax	\n\t"
77 	"pushl	%%eax	\n\t"
78 	".L_swap_loop: \n\t"
79 		"rolw	$8,-32(%%ebx,%%eax)	\n\t"
80 		"rolw	$8,-30(%%ebx,%%eax)	\n\t"
81 		"rolw	$8,-28(%%ebx,%%eax)	\n\t"
82 		"rolw	$8,-26(%%ebx,%%eax)	\n\t"
83 		"rolw	$8,-24(%%ebx,%%eax)	\n\t"
84 		"rolw	$8,-22(%%ebx,%%eax)	\n\t"
85 		"rolw	$8,-20(%%ebx,%%eax)	\n\t"
86 		"rolw	$8,-18(%%ebx,%%eax)	\n\t"
87 		"rolw	$8,-16(%%ebx,%%eax)	\n\t"
88 		"rolw	$8,-14(%%ebx,%%eax)	\n\t"
89 		"rolw	$8,-12(%%ebx,%%eax)	\n\t"
90 		"rolw	$8,-10(%%ebx,%%eax)	\n\t"
91 		"rolw	$8,-8(%%ebx,%%eax)	\n\t"
92 		"rolw	$8,-6(%%ebx,%%eax)	\n\t"
93 		"rolw	$8,-4(%%ebx,%%eax)	\n\t"
94 		"rolw	$8,-2(%%ebx,%%eax)	\n\t"
95 		"subl	$32,%%eax	\n\t"
96 		"jnz	.L_swap_loop	\n\t"
97 	"popl	%%eax	\n\t"
98 	"addl	%%eax,%%ebx	\n\t"
99 	"andl	$0x1F,%%edx	\n\t"
100 	"jz		.L_swap_end	\n\t"
101 	"addl	%%ebx, %%edx	\n\t"
102 	".L_swap_loop_2: \n\t"
103 		"rolw	$8,(%%ebx)	\n\t"
104 		"addl	$2,%%ebx	\n\t"
105 		"cmpl	%%edx,%%ebx	\n\t"
106 		"jne	.L_swap_loop_2 \n\t"
107 	".L_swap_end:	\n\t"
108 	"popl	%%ebx \n\t"
109 	: "=a" (dummy1), "=d" (dummy2)
110 	: "d" (bytecount), "a" (buffer)
111 	: "cc", "memory");
112 }
113 
114 #else
115 
116 // non optimized default versions, do not remove
117 
118 void
119 swap_float(void *buffer, size_t bytecount)
120 {
121 	swap_data(B_FLOAT_TYPE, buffer, bytecount, B_SWAP_ALWAYS);
122 }
123 
124 void
125 swap_int32(void *buffer, size_t bytecount)
126 {
127 	swap_data(B_INT32_TYPE, buffer, bytecount, B_SWAP_ALWAYS);
128 }
129 
130 void
131 swap_int16(void *buffer, size_t bytecount)
132 {
133 	swap_data(B_INT16_TYPE, buffer, bytecount, B_SWAP_ALWAYS);
134 }
135 #endif
136