| 1 | /*************************************************************************** |
|---|
| 2 | * Copyright (c) 2003-2011, Broadcom Corporation |
|---|
| 3 | * All Rights Reserved |
|---|
| 4 | * Confidential Property of Broadcom Corporation |
|---|
| 5 | * |
|---|
| 6 | * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE |
|---|
| 7 | * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR |
|---|
| 8 | * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. |
|---|
| 9 | * |
|---|
| 10 | * $brcm_Workfile: bxdm_pp_fix33.c $ |
|---|
| 11 | * $brcm_Revision: Hydra_Software_Devel/1 $ |
|---|
| 12 | * $brcm_Date: 4/28/11 1:50p $ |
|---|
| 13 | * |
|---|
| 14 | * [File Description:] |
|---|
| 15 | * |
|---|
| 16 | * Revision History: |
|---|
| 17 | * |
|---|
| 18 | * $brcm_Log: /magnum/commonutils/xdm/bxdm_pp_fix33.c $ |
|---|
| 19 | * |
|---|
| 20 | * Hydra_Software_Devel/1 4/28/11 1:50p nilesh |
|---|
| 21 | * SW7405-5057: New fixed point math library with proper support for -2^32 |
|---|
| 22 | * to 2^32 values. |
|---|
| 23 | * |
|---|
| 24 | ***************************************************************************/ |
|---|
| 25 | |
|---|
| 26 | #include "bstd.h" |
|---|
| 27 | #include "bkni.h" |
|---|
| 28 | #include "bdbg.h" |
|---|
| 29 | |
|---|
| 30 | #include "bxdm_pp_fix33.h" |
|---|
| 31 | |
|---|
| 32 | BDBG_MODULE(BXDM_PP_FIX33); |
|---|
| 33 | |
|---|
| 34 | const char BXDM_PictureProvider_P_DISPMGR_FIX33_NODE[]="DMFIX33:\t""$brcm_Revision: Hydra_Software_Devel/1 $"; |
|---|
| 35 | |
|---|
| 36 | #define BXDM_PP_Fix33_RADIX 31 |
|---|
| 37 | |
|---|
| 38 | /* Convert to BXDM_PP_Fix33_t */ |
|---|
| 39 | BXDM_PP_Fix33_t BXDM_PP_Fix33_from_mixedfraction(const uint32_t uiWhole, const uint32_t uiNumerator, const uint32_t uiDenominator) |
|---|
| 40 | { |
|---|
| 41 | BXDM_PP_Fix33_t fixTemp = 0; |
|---|
| 42 | |
|---|
| 43 | fixTemp = uiWhole; |
|---|
| 44 | fixTemp <<= BXDM_PP_Fix33_RADIX; |
|---|
| 45 | |
|---|
| 46 | fixTemp |= (uint32_t) ( ( ( ((uint64_t) uiNumerator) * (((uint64_t)1) << (BXDM_PP_Fix33_RADIX)) ) / uiDenominator ) & 0x7FFFFFFF ); |
|---|
| 47 | |
|---|
| 48 | #if 0 |
|---|
| 49 | BKNI_Printf("%d %u/%u --> %016llx\n", |
|---|
| 50 | iWhole, |
|---|
| 51 | uiNumerator, |
|---|
| 52 | uiDenominator, |
|---|
| 53 | fixTemp |
|---|
| 54 | ); |
|---|
| 55 | #endif |
|---|
| 56 | |
|---|
| 57 | return fixTemp; |
|---|
| 58 | } |
|---|
| 59 | |
|---|
| 60 | BXDM_PP_Fix33_t BXDM_PP_Fix33_from_int32(const int32_t iValue) |
|---|
| 61 | { |
|---|
| 62 | return ((BXDM_PP_Fix33_t) iValue) << BXDM_PP_Fix33_RADIX; |
|---|
| 63 | } |
|---|
| 64 | |
|---|
| 65 | BXDM_PP_Fix33_t BXDM_PP_Fix33_from_uint32(const uint32_t uiValue) |
|---|
| 66 | { |
|---|
| 67 | return ((BXDM_PP_Fix33_t) uiValue) << BXDM_PP_Fix33_RADIX; |
|---|
| 68 | } |
|---|
| 69 | |
|---|
| 70 | /* BXDM_PP_Fix33_t math operations */ |
|---|
| 71 | BXDM_PP_Fix33_t BXDM_PP_Fix33_add(const BXDM_PP_Fix33_t fixOperand1, const BXDM_PP_Fix33_t fixOperand2) |
|---|
| 72 | { |
|---|
| 73 | return fixOperand1 + fixOperand2; |
|---|
| 74 | } |
|---|
| 75 | |
|---|
| 76 | BXDM_PP_Fix33_t BXDM_PP_Fix33_sub(const BXDM_PP_Fix33_t fixOperand1, const BXDM_PP_Fix33_t fixOperand2) |
|---|
| 77 | { |
|---|
| 78 | return fixOperand1 - fixOperand2; |
|---|
| 79 | } |
|---|
| 80 | |
|---|
| 81 | BXDM_PP_Fix33_t BXDM_PP_Fix33_mulu(const BXDM_PP_Fix33_t fixOperand1, uint32_t uiOperand2) |
|---|
| 82 | { |
|---|
| 83 | return fixOperand1 * uiOperand2; |
|---|
| 84 | } |
|---|
| 85 | |
|---|
| 86 | /* udivide64 copied from /BSEAV/linux/driver/build/97038/bsettop_udivdi3.c */ |
|---|
| 87 | static void udivide64(uint64_t n, uint64_t d, uint64_t *pResult, uint64_t *pRemainder) |
|---|
| 88 | { |
|---|
| 89 | uint64_t r = 0; |
|---|
| 90 | uint64_t rem = 0; |
|---|
| 91 | |
|---|
| 92 | if (n == 0) { |
|---|
| 93 | /* If n == 0, special case to 0 (0/x == 0) */ |
|---|
| 94 | r = 0; |
|---|
| 95 | rem = 0; |
|---|
| 96 | } else if (d > n) { |
|---|
| 97 | /* If d > n, special case to 0 (n would be the remainder) */ |
|---|
| 98 | r = 0; |
|---|
| 99 | rem = n; |
|---|
| 100 | } else if (n < (d*2)) { |
|---|
| 101 | /* If n < d*2, special case to 1 */ |
|---|
| 102 | r = 1; |
|---|
| 103 | rem = n-d; |
|---|
| 104 | } else if ((d <= (uint64_t)0x00000000FFFFFFFF) && (n <= (uint64_t)0x00000000FFFFFFFF)) { |
|---|
| 105 | /* If they are 32bit quantities, go ahead and perform a basic 32bit div instead */ |
|---|
| 106 | uint32_t n32 = (uint32_t)n; |
|---|
| 107 | uint32_t d32 = (uint32_t)d; |
|---|
| 108 | uint32_t r32 = n32/d32; |
|---|
| 109 | |
|---|
| 110 | r = r32; |
|---|
| 111 | |
|---|
| 112 | r32 = n32%d32; |
|---|
| 113 | rem = r32; |
|---|
| 114 | } else { /* Otherwise, complicated division time */ |
|---|
| 115 | |
|---|
| 116 | /* This segment of code is based on the routine by Ian Kaplan at |
|---|
| 117 | * http://www.bearcave.com/software/divide.htm, which was licensed at |
|---|
| 118 | * the time as: |
|---|
| 119 | * |
|---|
| 120 | * "Use of this program, for any purpose, is granted the author, Ian |
|---|
| 121 | * Kaplan, as long as this copyright notice is included in the source code |
|---|
| 122 | * or any source code derived from this program. The user assumes all |
|---|
| 123 | * responsibility for using this code. |
|---|
| 124 | * |
|---|
| 125 | * Ian Kaplan, October 1996 |
|---|
| 126 | */ |
|---|
| 127 | uint64_t t = 0, tmp = 0; |
|---|
| 128 | uint32_t bits = 64; |
|---|
| 129 | uint32_t ix; |
|---|
| 130 | |
|---|
| 131 | r = 0; |
|---|
| 132 | /* Figure out about what the order of the remainder would be, to shortcut |
|---|
| 133 | * a great deal of the math */ |
|---|
| 134 | while (rem < d) { |
|---|
| 135 | rem = (rem << 1) | (n>>63); |
|---|
| 136 | tmp = n; |
|---|
| 137 | n = n << 1; |
|---|
| 138 | bits--; |
|---|
| 139 | } |
|---|
| 140 | /* Undo the last step, since we just went one too far */ |
|---|
| 141 | n = tmp; |
|---|
| 142 | rem = rem >> 1; |
|---|
| 143 | bits++; |
|---|
| 144 | /* And now, buckle down and do the rest of the work */ |
|---|
| 145 | for (ix=0; ix < bits; ix++) { |
|---|
| 146 | rem = (rem << 1) | (n>>63); |
|---|
| 147 | tmp = rem - d; |
|---|
| 148 | t = !(tmp>>63); |
|---|
| 149 | n = n << 1; |
|---|
| 150 | r = (r << 1) | t; |
|---|
| 151 | if (t) { |
|---|
| 152 | rem = tmp; |
|---|
| 153 | } |
|---|
| 154 | } |
|---|
| 155 | /* End of code based on Ian Kaplan's work. */ |
|---|
| 156 | } |
|---|
| 157 | |
|---|
| 158 | *pResult = r; |
|---|
| 159 | *pRemainder = rem; |
|---|
| 160 | return; |
|---|
| 161 | } |
|---|
| 162 | |
|---|
| 163 | BXDM_PP_Fix33_t BXDM_PP_Fix33_divu(const BXDM_PP_Fix33_t fixOperand1, uint32_t uiOperand2) |
|---|
| 164 | { |
|---|
| 165 | #if 1 |
|---|
| 166 | /* Avoid 64-bit divide because linux kernel doesn't implement it */ |
|---|
| 167 | bool bNegative = false; |
|---|
| 168 | uint64_t uiNumerator; |
|---|
| 169 | uint64_t uiResult; |
|---|
| 170 | uint64_t uiRemainder; |
|---|
| 171 | BXDM_PP_Fix33_t fixResult; |
|---|
| 172 | |
|---|
| 173 | if ( fixOperand1 < 0 ) |
|---|
| 174 | { |
|---|
| 175 | bNegative = true; |
|---|
| 176 | uiNumerator = BXDM_PP_Fix33_neg(fixOperand1); |
|---|
| 177 | } |
|---|
| 178 | else |
|---|
| 179 | { |
|---|
| 180 | uiNumerator = fixOperand1; |
|---|
| 181 | } |
|---|
| 182 | |
|---|
| 183 | udivide64(uiNumerator, uiOperand2, &uiResult, &uiRemainder); |
|---|
| 184 | |
|---|
| 185 | fixResult = uiResult; |
|---|
| 186 | |
|---|
| 187 | if ( true == bNegative ) |
|---|
| 188 | { |
|---|
| 189 | fixResult = BXDM_PP_Fix33_neg(fixResult); |
|---|
| 190 | } |
|---|
| 191 | |
|---|
| 192 | return fixResult; |
|---|
| 193 | #else |
|---|
| 194 | return fixOperand1 / uiOperand2; |
|---|
| 195 | #endif |
|---|
| 196 | } |
|---|
| 197 | |
|---|
| 198 | BXDM_PP_Fix33_t BXDM_PP_Fix33_neg(const BXDM_PP_Fix33_t fixOperand) |
|---|
| 199 | { |
|---|
| 200 | return -fixOperand; |
|---|
| 201 | } |
|---|
| 202 | |
|---|
| 203 | /* Convert from BXDM_PP_Fix33_t */ |
|---|
| 204 | int32_t BXDM_PP_Fix33_to_int32(const BXDM_PP_Fix33_t fixValue) |
|---|
| 205 | { |
|---|
| 206 | if (fixValue >= 0) |
|---|
| 207 | { |
|---|
| 208 | return (((fixValue + (1 << (BXDM_PP_Fix33_RADIX-1))) << 1) >> 32); |
|---|
| 209 | } |
|---|
| 210 | else |
|---|
| 211 | { |
|---|
| 212 | return (((fixValue - (1 << (BXDM_PP_Fix33_RADIX-1))) << 1) >> 32); |
|---|
| 213 | } |
|---|
| 214 | } |
|---|
| 215 | |
|---|
| 216 | uint32_t BXDM_PP_Fix33_to_uint32(const BXDM_PP_Fix33_t fixValue) |
|---|
| 217 | { |
|---|
| 218 | return ((fixValue + (1 << (BXDM_PP_Fix33_RADIX-1))) >> BXDM_PP_Fix33_RADIX); |
|---|
| 219 | } |
|---|