• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2004-2010 NXP Software
3  * Copyright (C) 2010 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #ifndef _LVM_MACROS_H_
19 #define _LVM_MACROS_H_
20 
21 /**********************************************************************************
22    MUL32x32INTO32(A,B,C,ShiftR)
23         C = (A * B) >> ShiftR
24 
25         A, B and C are all 32 bit SIGNED numbers and ShiftR can vary from 0 to 64
26 
27         The user has to take care that C does not overflow.  The result in case
28         of overflow is undefined.
29 
30 ***********************************************************************************/
31 #define MUL32x32INTO32(A, B, C, ShiftR)                                                        \
32     {                                                                                          \
33         LVM_INT32 MUL32x32INTO32_temp, MUL32x32INTO32_temp2, MUL32x32INTO32_mask,              \
34                 MUL32x32INTO32_HH, MUL32x32INTO32_HL, MUL32x32INTO32_LH, MUL32x32INTO32_LL;    \
35         LVM_INT32 shiftValue;                                                                  \
36         shiftValue = (ShiftR);                                                                 \
37         MUL32x32INTO32_mask = 0x0000FFFF;                                                      \
38         MUL32x32INTO32_HH = ((LVM_INT32)((LVM_INT16)((A) >> 16)) * ((LVM_INT16)((B) >> 16)));  \
39         MUL32x32INTO32_HL = ((LVM_INT32)((B)&MUL32x32INTO32_mask) * ((LVM_INT16)((A) >> 16))); \
40         MUL32x32INTO32_LH = ((LVM_INT32)((A)&MUL32x32INTO32_mask) * ((LVM_INT16)((B) >> 16))); \
41         MUL32x32INTO32_LL =                                                                    \
42                 (LVM_INT32)((A)&MUL32x32INTO32_mask) * (LVM_INT32)((B)&MUL32x32INTO32_mask);   \
43         MUL32x32INTO32_temp = (LVM_INT32)(MUL32x32INTO32_HL & MUL32x32INTO32_mask) +           \
44                               (LVM_INT32)(MUL32x32INTO32_LH & MUL32x32INTO32_mask) +           \
45                               (LVM_INT32)((MUL32x32INTO32_LL >> 16) & MUL32x32INTO32_mask);    \
46         MUL32x32INTO32_HH = MUL32x32INTO32_HH + (LVM_INT32)(MUL32x32INTO32_HL >> 16) +         \
47                             (LVM_INT32)(MUL32x32INTO32_LH >> 16) +                             \
48                             (LVM_INT32)(MUL32x32INTO32_temp >> 16);                            \
49         MUL32x32INTO32_LL = MUL32x32INTO32_LL + (LVM_INT32)(MUL32x32INTO32_HL << 16) +         \
50                             (LVM_INT32)(MUL32x32INTO32_LH << 16);                              \
51         if (shiftValue < 32) {                                                                 \
52             MUL32x32INTO32_HH = MUL32x32INTO32_HH << (32 - shiftValue);                        \
53             MUL32x32INTO32_mask = ((LVM_INT32)1 << (32 - shiftValue)) - 1;                     \
54             MUL32x32INTO32_LL = (MUL32x32INTO32_LL >> shiftValue) & MUL32x32INTO32_mask;       \
55             MUL32x32INTO32_temp2 = MUL32x32INTO32_HH | MUL32x32INTO32_LL;                      \
56         } else {                                                                               \
57             MUL32x32INTO32_temp2 = (LVM_INT32)MUL32x32INTO32_HH >> (shiftValue - 32);          \
58         }                                                                                      \
59         (C) = MUL32x32INTO32_temp2;                                                            \
60     }
61 
62 /**********************************************************************************
63    MUL32x16INTO32(A,B,C,ShiftR)
64         C = (A * B) >> ShiftR
65 
66         A and C are 32 bit SIGNED numbers.  B is a 16 bit SIGNED number.
67         ShiftR can vary from 0 to 48
68 
69         The user has to take care that C does not overflow.  The result in case
70         of overflow is undefined.
71 
72 ***********************************************************************************/
73 #define MUL32x16INTO32(A, B, C, ShiftR)                                                          \
74     {                                                                                            \
75         LVM_INT32 MUL32x16INTO32_mask, MUL32x16INTO32_HH, MUL32x16INTO32_LL;                     \
76         LVM_INT32 shiftValue;                                                                    \
77         shiftValue = (ShiftR);                                                                   \
78         MUL32x16INTO32_mask = 0x0000FFFF;                                                        \
79         MUL32x16INTO32_HH = ((LVM_INT32)(B) * ((LVM_INT16)((A) >> 16)));                         \
80         MUL32x16INTO32_LL = ((LVM_INT32)((A)&MUL32x16INTO32_mask) * (B));                        \
81         if (shiftValue < 16) {                                                                   \
82             MUL32x16INTO32_HH = (LVM_INT32)((LVM_UINT32)MUL32x16INTO32_HH << (16 - shiftValue)); \
83             (C) = MUL32x16INTO32_HH + (LVM_INT32)(MUL32x16INTO32_LL >> shiftValue);              \
84         } else if (shiftValue < 32) {                                                            \
85             MUL32x16INTO32_HH = (LVM_INT32)(MUL32x16INTO32_HH >> (shiftValue - 16));             \
86             (C) = MUL32x16INTO32_HH + (LVM_INT32)(MUL32x16INTO32_LL >> shiftValue);              \
87         } else {                                                                                 \
88             (C) = MUL32x16INTO32_HH >> (shiftValue - 16);                                        \
89         }                                                                                        \
90     }
91 
92 /**********************************************************************************
93    ADD2_SAT_32x32(A,B,C)
94         C = SAT(A + B)
95 
96         A,B and C are 32 bit SIGNED numbers.
97 ***********************************************************************************/
98 #define ADD2_SAT_32x32(A, B, C)                  \
99     {                                            \
100         (C) = (A) + (B);                         \
101         if ((((C) ^ (A)) & ((C) ^ (B))) >> 31) { \
102             if ((A) < 0)                         \
103                 (C) = 0x80000000l;               \
104             else                                 \
105                 (C) = 0x7FFFFFFFl;               \
106         }                                        \
107     }
108 
109 #endif /* _LVM_MACROS_H_ */
110 
111 /*** End of file ******************************************************************/
112