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