blob: b92c12a50a4a3984805e33240207328465552498 [file] [log] [blame]
Thom Johansen877ea482007-10-19 12:27:38 +00001/* fixed precision code. We use a combination of Sign 15.16 and Sign.31
2 precision here.
Michael Giacomellia16d0f32007-07-04 17:15:09 +00003
Thom Johansen877ea482007-10-19 12:27:38 +00004 The WMA decoder does not always follow this convention, and occasionally
5 renormalizes values to other formats in order to maximize precision.
6 However, only the two precisions above are provided in this file.
Michael Giacomellia16d0f32007-07-04 17:15:09 +00007
8*/
9
Marcoen Hirschbergb8753ff2007-10-01 13:46:07 +000010#include "types.h"
Michael Giacomellia16d0f32007-07-04 17:15:09 +000011
12#define PRECISION 16
13#define PRECISION64 16
14
15
16#define fixtof64(x) (float)((float)(x) / (float)(1 << PRECISION64)) //does not work on int64_t!
17#define ftofix32(x) ((fixed32)((x) * (float)(1 << PRECISION) + ((x) < 0 ? -0.5 : 0.5)))
18#define itofix64(x) (IntTo64(x))
19#define itofix32(x) ((x) << PRECISION)
20#define fixtoi32(x) ((x) >> PRECISION)
21#define fixtoi64(x) (IntFrom64(x))
22
23
24/*fixed functions*/
25
26fixed64 IntTo64(int x);
27int IntFrom64(fixed64 x);
28fixed32 Fixed32From64(fixed64 x);
29fixed64 Fixed32To64(fixed32 x);
30fixed64 fixmul64byfixed(fixed64 x, fixed32 y);
31fixed32 fixdiv32(fixed32 x, fixed32 y);
32fixed64 fixdiv64(fixed64 x, fixed64 y);
33fixed32 fixsqrt32(fixed32 x);
34fixed32 fixsin32(fixed32 x);
35fixed32 fixcos32(fixed32 x);
36long fsincos(unsigned long phase, fixed32 *cos);
37
Michael Giacomellia16d0f32007-07-04 17:15:09 +000038#ifdef CPU_ARM
39
Michael Giacomellia16d0f32007-07-04 17:15:09 +000040/*Sign-15.16 format */
41
42#define fixmul32(x, y) \
43 ({ int32_t __hi; \
44 uint32_t __lo; \
45 int32_t __result; \
46 asm ("smull %0, %1, %3, %4\n\t" \
47 "movs %0, %0, lsr %5\n\t" \
48 "adc %2, %0, %1, lsl %6" \
49 : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \
50 : "%r" (x), "r" (y), \
51 "M" (PRECISION), "M" (32 - PRECISION) \
52 : "cc"); \
53 __result; \
54 })
55
Thom Johansen877ea482007-10-19 12:27:38 +000056#define fixmul32b(x, y) \
Michael Giacomelli030dce62007-07-08 05:57:14 +000057 ({ int32_t __hi; \
58 uint32_t __lo; \
59 int32_t __result; \
60 asm ("smull %0, %1, %3, %4\n\t" \
Michael Giacomelli8159b9e2007-08-16 03:33:15 +000061 "movs %2, %1, lsl #1" \
Michael Giacomelli030dce62007-07-08 05:57:14 +000062 : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \
Michael Giacomelli8159b9e2007-08-16 03:33:15 +000063 : "%r" (x), "r" (y) \
Michael Giacomelli030dce62007-07-08 05:57:14 +000064 : "cc"); \
65 __result; \
66 })
67
Michael Giacomellife8ae102007-07-04 17:51:52 +000068#elif defined(CPU_COLDFIRE)
Thom Johansen877ea482007-10-19 12:27:38 +000069
Michael Giacomellife8ae102007-07-04 17:51:52 +000070static inline int32_t fixmul32(int32_t x, int32_t y)
71{
72#if PRECISION != 16
73#warning Coldfire fixmul32() only works for PRECISION == 16
74#endif
75 int32_t t1;
76 asm (
77 "mac.l %[x], %[y], %%acc0 \n" /* multiply */
78 "mulu.l %[y], %[x] \n" /* get lower half, avoid emac stall */
79 "movclr.l %%acc0, %[t1] \n" /* get higher half */
80 "lsr.l #1, %[t1] \n"
81 "move.w %[t1], %[x] \n"
82 "swap %[x] \n"
Thom Johansen877ea482007-10-19 12:27:38 +000083 : [t1] "=&d" (t1), [x] "+d" (x)
84 : [y] "d" (y)
Michael Giacomellife8ae102007-07-04 17:51:52 +000085 );
86 return x;
87}
Marcoen Hirschberg4d853ff2007-09-20 13:52:41 +000088
Thom Johansen877ea482007-10-19 12:27:38 +000089static inline int32_t fixmul32b(int32_t x, int32_t y)
90{
91 asm (
92 "mac.l %[x], %[y], %%acc0 \n" /* multiply */
93 "movclr.l %%acc0, %[x] \n" /* get higher half */
94 : [x] "+d" (x)
95 : [y] "d" (y)
96 );
97 return x;
98}
99
Michael Giacomellia16d0f32007-07-04 17:15:09 +0000100#else
Michael Giacomellife8ae102007-07-04 17:51:52 +0000101
Thom Johansen877ea482007-10-19 12:27:38 +0000102static inline fixed32 fixmul32(fixed32 x, fixed32 y)
103{
104 fixed64 temp;
105 temp = x;
106 temp *= y;
Michael Giacomellia16d0f32007-07-04 17:15:09 +0000107
Thom Johansen877ea482007-10-19 12:27:38 +0000108 temp >>= PRECISION;
109
110 return (fixed32)temp;
111}
112
113static inline fixed32 fixmul32b(fixed32 x, fixed32 y)
114{
115 fixed64 temp;
116
117 temp = x;
118 temp *= y;
119
120 temp >>= 31; //16+31-16 = 31 bits
121
122 return (fixed32)temp;
123}
124
125#endif
Marcoen Hirschberg1ddef372007-09-20 12:27:24 +0000126
127#ifdef CPU_ARM
128static inline
129void CMUL(fixed32 *x, fixed32 *y,
130 fixed32 a, fixed32 b,
131 fixed32 t, fixed32 v)
132{
133 /* This version loses one bit of precision. Could be solved at the cost
134 * of 2 extra cycles if it becomes an issue. */
135 int x1, y1, l;
136 asm(
137 "smull %[l], %[y1], %[b], %[t] \n"
138 "smlal %[l], %[y1], %[a], %[v] \n"
139 "rsb %[b], %[b], #0 \n"
140 "smull %[l], %[x1], %[a], %[t] \n"
141 "smlal %[l], %[x1], %[b], %[v] \n"
142 : [l] "=&r" (l), [x1]"=&r" (x1), [y1]"=&r" (y1), [b] "+r" (b)
143 : [a] "r" (a), [t] "r" (t), [v] "r" (v)
144 : "cc"
145 );
146 *x = x1 << 1;
147 *y = y1 << 1;
148}
149#elif defined CPU_COLDFIRE
150static inline
151void CMUL(fixed32 *x, fixed32 *y,
152 fixed32 a, fixed32 b,
153 fixed32 t, fixed32 v)
154{
155 asm volatile ("mac.l %[a], %[t], %%acc0;"
156 "msac.l %[b], %[v], %%acc0;"
157 "mac.l %[b], %[t], %%acc1;"
158 "mac.l %[a], %[v], %%acc1;"
159 "movclr.l %%acc0, %[a];"
160 "move.l %[a], (%[x]);"
161 "movclr.l %%acc1, %[a];"
162 "move.l %[a], (%[y]);"
163 : [a] "+&r" (a)
164 : [x] "a" (x), [y] "a" (y),
165 [b] "r" (b), [t] "r" (t), [v] "r" (v)
166 : "cc", "memory");
167}
168#else
Marcoen Hirschberg1ddef372007-09-20 12:27:24 +0000169static inline
170void CMUL(fixed32 *pre,
171 fixed32 *pim,
172 fixed32 are,
173 fixed32 aim,
174 fixed32 bre,
175 fixed32 bim)
176{
177 //int64_t x,y;
178 fixed32 _aref = are;
179 fixed32 _aimf = aim;
180 fixed32 _bref = bre;
181 fixed32 _bimf = bim;
182 fixed32 _r1 = fixmul32b(_bref, _aref);
183 fixed32 _r2 = fixmul32b(_bimf, _aimf);
184 fixed32 _r3 = fixmul32b(_bref, _aimf);
185 fixed32 _r4 = fixmul32b(_bimf, _aref);
186 *pre = _r1 - _r2;
187 *pim = _r3 + _r4;
188
189}
190#endif