blob: 198e79e335f9894adf2b9c5bf835820239e4077b [file] [log] [blame]
Michael Giacomelli132bc632007-10-29 23:16:41 +00001/****************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
Michael Giacomelli781c82c2007-10-29 23:22:33 +00009 * Copyright (C) 2007 Michael Giacomelli
Michael Giacomelli132bc632007-10-29 23:16:41 +000010 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000011 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
Michael Giacomelli132bc632007-10-29 23:16:41 +000015 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
Thom Johansen877ea482007-10-19 12:27:38 +000021/* fixed precision code. We use a combination of Sign 15.16 and Sign.31
22 precision here.
Michael Giacomellia16d0f32007-07-04 17:15:09 +000023
Thom Johansen877ea482007-10-19 12:27:38 +000024 The WMA decoder does not always follow this convention, and occasionally
25 renormalizes values to other formats in order to maximize precision.
26 However, only the two precisions above are provided in this file.
Michael Giacomellia16d0f32007-07-04 17:15:09 +000027
28*/
29
Marcoen Hirschbergb8753ff2007-10-01 13:46:07 +000030#include "types.h"
Michael Giacomellia16d0f32007-07-04 17:15:09 +000031
32#define PRECISION 16
33#define PRECISION64 16
34
35
36#define fixtof64(x) (float)((float)(x) / (float)(1 << PRECISION64)) //does not work on int64_t!
37#define ftofix32(x) ((fixed32)((x) * (float)(1 << PRECISION) + ((x) < 0 ? -0.5 : 0.5)))
38#define itofix64(x) (IntTo64(x))
39#define itofix32(x) ((x) << PRECISION)
40#define fixtoi32(x) ((x) >> PRECISION)
41#define fixtoi64(x) (IntFrom64(x))
42
43
44/*fixed functions*/
45
46fixed64 IntTo64(int x);
47int IntFrom64(fixed64 x);
48fixed32 Fixed32From64(fixed64 x);
49fixed64 Fixed32To64(fixed32 x);
50fixed64 fixmul64byfixed(fixed64 x, fixed32 y);
51fixed32 fixdiv32(fixed32 x, fixed32 y);
52fixed64 fixdiv64(fixed64 x, fixed64 y);
53fixed32 fixsqrt32(fixed32 x);
Michael Giacomellia16d0f32007-07-04 17:15:09 +000054long fsincos(unsigned long phase, fixed32 *cos);
55
Michael Giacomellia16d0f32007-07-04 17:15:09 +000056#ifdef CPU_ARM
57
Michael Giacomellia16d0f32007-07-04 17:15:09 +000058/*Sign-15.16 format */
59
60#define fixmul32(x, y) \
61 ({ int32_t __hi; \
62 uint32_t __lo; \
63 int32_t __result; \
64 asm ("smull %0, %1, %3, %4\n\t" \
65 "movs %0, %0, lsr %5\n\t" \
66 "adc %2, %0, %1, lsl %6" \
67 : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \
68 : "%r" (x), "r" (y), \
69 "M" (PRECISION), "M" (32 - PRECISION) \
70 : "cc"); \
71 __result; \
72 })
73
Thom Johansen877ea482007-10-19 12:27:38 +000074#define fixmul32b(x, y) \
Michael Giacomelli030dce62007-07-08 05:57:14 +000075 ({ int32_t __hi; \
76 uint32_t __lo; \
77 int32_t __result; \
78 asm ("smull %0, %1, %3, %4\n\t" \
Michael Giacomelli8159b9e2007-08-16 03:33:15 +000079 "movs %2, %1, lsl #1" \
Michael Giacomelli030dce62007-07-08 05:57:14 +000080 : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \
Michael Giacomelli8159b9e2007-08-16 03:33:15 +000081 : "%r" (x), "r" (y) \
Michael Giacomelli030dce62007-07-08 05:57:14 +000082 : "cc"); \
83 __result; \
84 })
85
Michael Giacomellife8ae102007-07-04 17:51:52 +000086#elif defined(CPU_COLDFIRE)
Thom Johansen877ea482007-10-19 12:27:38 +000087
Michael Giacomellife8ae102007-07-04 17:51:52 +000088static inline int32_t fixmul32(int32_t x, int32_t y)
89{
90#if PRECISION != 16
91#warning Coldfire fixmul32() only works for PRECISION == 16
92#endif
93 int32_t t1;
94 asm (
95 "mac.l %[x], %[y], %%acc0 \n" /* multiply */
96 "mulu.l %[y], %[x] \n" /* get lower half, avoid emac stall */
97 "movclr.l %%acc0, %[t1] \n" /* get higher half */
98 "lsr.l #1, %[t1] \n"
99 "move.w %[t1], %[x] \n"
100 "swap %[x] \n"
Thom Johansen877ea482007-10-19 12:27:38 +0000101 : [t1] "=&d" (t1), [x] "+d" (x)
102 : [y] "d" (y)
Michael Giacomellife8ae102007-07-04 17:51:52 +0000103 );
104 return x;
105}
Marcoen Hirschberg4d853ff2007-09-20 13:52:41 +0000106
Thom Johansen877ea482007-10-19 12:27:38 +0000107static inline int32_t fixmul32b(int32_t x, int32_t y)
108{
109 asm (
110 "mac.l %[x], %[y], %%acc0 \n" /* multiply */
111 "movclr.l %%acc0, %[x] \n" /* get higher half */
112 : [x] "+d" (x)
113 : [y] "d" (y)
114 );
115 return x;
116}
117
Michael Giacomellia16d0f32007-07-04 17:15:09 +0000118#else
Michael Giacomellife8ae102007-07-04 17:51:52 +0000119
Thom Johansen877ea482007-10-19 12:27:38 +0000120static inline fixed32 fixmul32(fixed32 x, fixed32 y)
121{
122 fixed64 temp;
123 temp = x;
124 temp *= y;
Michael Giacomellia16d0f32007-07-04 17:15:09 +0000125
Thom Johansen877ea482007-10-19 12:27:38 +0000126 temp >>= PRECISION;
127
128 return (fixed32)temp;
129}
130
131static inline fixed32 fixmul32b(fixed32 x, fixed32 y)
132{
133 fixed64 temp;
134
135 temp = x;
136 temp *= y;
137
138 temp >>= 31; //16+31-16 = 31 bits
139
140 return (fixed32)temp;
141}
142
143#endif
Marcoen Hirschberg1ddef372007-09-20 12:27:24 +0000144
145#ifdef CPU_ARM
146static inline
147void CMUL(fixed32 *x, fixed32 *y,
148 fixed32 a, fixed32 b,
149 fixed32 t, fixed32 v)
150{
151 /* This version loses one bit of precision. Could be solved at the cost
152 * of 2 extra cycles if it becomes an issue. */
153 int x1, y1, l;
154 asm(
155 "smull %[l], %[y1], %[b], %[t] \n"
156 "smlal %[l], %[y1], %[a], %[v] \n"
157 "rsb %[b], %[b], #0 \n"
158 "smull %[l], %[x1], %[a], %[t] \n"
159 "smlal %[l], %[x1], %[b], %[v] \n"
160 : [l] "=&r" (l), [x1]"=&r" (x1), [y1]"=&r" (y1), [b] "+r" (b)
161 : [a] "r" (a), [t] "r" (t), [v] "r" (v)
162 : "cc"
163 );
164 *x = x1 << 1;
165 *y = y1 << 1;
166}
167#elif defined CPU_COLDFIRE
168static inline
169void CMUL(fixed32 *x, fixed32 *y,
170 fixed32 a, fixed32 b,
171 fixed32 t, fixed32 v)
172{
173 asm volatile ("mac.l %[a], %[t], %%acc0;"
174 "msac.l %[b], %[v], %%acc0;"
175 "mac.l %[b], %[t], %%acc1;"
176 "mac.l %[a], %[v], %%acc1;"
177 "movclr.l %%acc0, %[a];"
178 "move.l %[a], (%[x]);"
179 "movclr.l %%acc1, %[a];"
180 "move.l %[a], (%[y]);"
181 : [a] "+&r" (a)
182 : [x] "a" (x), [y] "a" (y),
183 [b] "r" (b), [t] "r" (t), [v] "r" (v)
184 : "cc", "memory");
185}
186#else
Marcoen Hirschberg1ddef372007-09-20 12:27:24 +0000187static inline
188void CMUL(fixed32 *pre,
189 fixed32 *pim,
190 fixed32 are,
191 fixed32 aim,
192 fixed32 bre,
193 fixed32 bim)
194{
195 //int64_t x,y;
196 fixed32 _aref = are;
197 fixed32 _aimf = aim;
198 fixed32 _bref = bre;
199 fixed32 _bimf = bim;
200 fixed32 _r1 = fixmul32b(_bref, _aref);
201 fixed32 _r2 = fixmul32b(_bimf, _aimf);
202 fixed32 _r3 = fixmul32b(_bref, _aimf);
203 fixed32 _r4 = fixmul32b(_bimf, _aref);
204 *pre = _r1 - _r2;
205 *pim = _r3 + _r4;
206
207}
208#endif