1 /* Copyright (C) 2005 Analog Devices |
|
2 Author: Jean-Marc Valin */ |
|
3 /** |
|
4 @file fixed_bfin.h |
|
5 @brief Blackfin fixed-point operations |
|
6 */ |
|
7 /* |
|
8 Redistribution and use in source and binary forms, with or without |
|
9 modification, are permitted provided that the following conditions |
|
10 are met: |
|
11 |
|
12 - Redistributions of source code must retain the above copyright |
|
13 notice, this list of conditions and the following disclaimer. |
|
14 |
|
15 - Redistributions in binary form must reproduce the above copyright |
|
16 notice, this list of conditions and the following disclaimer in the |
|
17 documentation and/or other materials provided with the distribution. |
|
18 |
|
19 - Neither the name of the Xiph.org Foundation nor the names of its |
|
20 contributors may be used to endorse or promote products derived from |
|
21 this software without specific prior written permission. |
|
22 |
|
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
24 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
25 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
26 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR |
|
27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
|
28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|
29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
|
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
|
31 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
|
32 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
34 */ |
|
35 |
|
36 #ifndef FIXED_BFIN_H |
|
37 #define FIXED_BFIN_H |
|
38 |
|
39 #undef PDIV32_16 |
|
40 static inline spx_word16_t |
|
41 PDIV32_16 (spx_word32_t a, spx_word16_t b) |
|
42 { |
|
43 spx_word32_t res, bb; |
|
44 bb = b; |
|
45 a += b >> 1; |
|
46 __asm__ ("P0 = 15;\n\t" "R0 = %1;\n\t" "R1 = %2;\n\t" |
|
47 //"R0 = R0 + R1;\n\t" |
|
48 "R0 <<= 1;\n\t" "DIVS (R0, R1);\n\t" "LOOP divide%= LC0 = P0;\n\t" "LOOP_BEGIN divide%=;\n\t" "DIVQ (R0, R1);\n\t" "LOOP_END divide%=;\n\t" "R0 = R0.L;\n\t" "%0 = R0;\n\t":"=m" |
|
49 (res) |
|
50 : "m" (a), "m" (bb) |
|
51 : "P0", "R0", "R1", "cc"); |
|
52 return res; |
|
53 } |
|
54 |
|
55 #undef DIV32_16 |
|
56 static inline spx_word16_t |
|
57 DIV32_16 (spx_word32_t a, spx_word16_t b) |
|
58 { |
|
59 spx_word32_t res, bb; |
|
60 bb = b; |
|
61 /* Make the roundinf consistent with the C version |
|
62 (do we need to do that?) */ |
|
63 if (a < 0) |
|
64 a += (b - 1); |
|
65 __asm__ ("P0 = 15;\n\t" "R0 = %1;\n\t" "R1 = %2;\n\t" "R0 <<= 1;\n\t" "DIVS (R0, R1);\n\t" "LOOP divide%= LC0 = P0;\n\t" "LOOP_BEGIN divide%=;\n\t" "DIVQ (R0, R1);\n\t" "LOOP_END divide%=;\n\t" "R0 = R0.L;\n\t" "%0 = R0;\n\t":"=m" (res) |
|
66 : "m" (a), "m" (bb) |
|
67 : "P0", "R0", "R1", "cc"); |
|
68 return res; |
|
69 } |
|
70 |
|
71 #undef MAX16 |
|
72 static inline spx_word16_t |
|
73 MAX16 (spx_word16_t a, spx_word16_t b) |
|
74 { |
|
75 spx_word32_t res; |
|
76 __asm__ ("%1 = %1.L (X);\n\t" "%2 = %2.L (X);\n\t" "%0 = MAX(%1,%2);":"=d" (res) |
|
77 : "%d" (a), "d" (b) |
|
78 ); |
|
79 return res; |
|
80 } |
|
81 |
|
82 #undef MULT16_32_Q15 |
|
83 static inline spx_word32_t |
|
84 MULT16_32_Q15 (spx_word16_t a, spx_word32_t b) |
|
85 { |
|
86 spx_word32_t res; |
|
87 __asm__ ("A1 = %2.L*%1.L (M);\n\t" "A1 = A1 >>> 15;\n\t" "%0 = (A1 += %2.L*%1.H) ;\n\t":"=&W" (res), |
|
88 "=&d" |
|
89 (b) |
|
90 : "d" (a), "1" (b) |
|
91 : "A1"); |
|
92 return res; |
|
93 } |
|
94 |
|
95 #undef MAC16_32_Q15 |
|
96 static inline spx_word32_t |
|
97 MAC16_32_Q15 (spx_word32_t c, spx_word16_t a, spx_word32_t b) |
|
98 { |
|
99 spx_word32_t res; |
|
100 __asm__ ("A1 = %2.L*%1.L (M);\n\t" "A1 = A1 >>> 15;\n\t" "%0 = (A1 += %2.L*%1.H);\n\t" "%0 = %0 + %4;\n\t":"=&W" (res), |
|
101 "=&d" |
|
102 (b) |
|
103 : "d" (a), "1" (b), "d" (c) |
|
104 : "A1"); |
|
105 return res; |
|
106 } |
|
107 |
|
108 #undef MULT16_32_Q14 |
|
109 static inline spx_word32_t |
|
110 MULT16_32_Q14 (spx_word16_t a, spx_word32_t b) |
|
111 { |
|
112 spx_word32_t res; |
|
113 __asm__ ("%2 <<= 1;\n\t" "A1 = %1.L*%2.L (M);\n\t" "A1 = A1 >>> 15;\n\t" "%0 = (A1 += %1.L*%2.H);\n\t":"=W" (res), "=d" (a), |
|
114 "=d" |
|
115 (b) |
|
116 : "1" (a), "2" (b) |
|
117 : "A1"); |
|
118 return res; |
|
119 } |
|
120 |
|
121 #undef MAC16_32_Q14 |
|
122 static inline spx_word32_t |
|
123 MAC16_32_Q14 (spx_word32_t c, spx_word16_t a, spx_word32_t b) |
|
124 { |
|
125 spx_word32_t res; |
|
126 __asm__ ("%1 <<= 1;\n\t" "A1 = %2.L*%1.L (M);\n\t" "A1 = A1 >>> 15;\n\t" "%0 = (A1 += %2.L*%1.H);\n\t" "%0 = %0 + %4;\n\t":"=&W" (res), |
|
127 "=&d" |
|
128 (b) |
|
129 : "d" (a), "1" (b), "d" (c) |
|
130 : "A1"); |
|
131 return res; |
|
132 } |
|
133 |
|
134 #endif |
|