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
16static void swap_float(void *buffer, size_t bytecount);
17static void swap_int32(void *buffer, size_t bytecount);
18static void swap_int16(void *buffer, size_t bytecount);
19static void do_nothing(void *buffer, size_t bytecount);
20
21
22ByteSwap::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
41ByteSwap::~ByteSwap()
42{
43}
44
45
46void
47do_nothing(void *buffer, size_t bytecount)
48{
49}
50
51
52#if __i386__
53// #pragma mark - optimized for IA32 platform
54
55
56void
57swap_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
64void
65swap_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
72void
73swap_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
129void
130swap_float(void *buffer, size_t bytecount)
131{
132	swap_data(B_FLOAT_TYPE, buffer, bytecount, B_SWAP_ALWAYS);
133}
134
135
136void
137swap_int32(void *buffer, size_t bytecount)
138{
139	swap_data(B_INT32_TYPE, buffer, bytecount, B_SWAP_ALWAYS);
140}
141
142
143void
144swap_int16(void *buffer, size_t bytecount)
145{
146	swap_data(B_INT16_TYPE, buffer, bytecount, B_SWAP_ALWAYS);
147}
148
149
150#endif
151