diff options
Diffstat (limited to 'pk/ppe42/ppe42_gcc.c')
-rw-r--r-- | pk/ppe42/ppe42_gcc.c | 305 |
1 files changed, 0 insertions, 305 deletions
diff --git a/pk/ppe42/ppe42_gcc.c b/pk/ppe42/ppe42_gcc.c deleted file mode 100644 index 97c2979c..00000000 --- a/pk/ppe42/ppe42_gcc.c +++ /dev/null @@ -1,305 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42_gcc.h -/// \brief 32-bit PowerPC functions expected by GCC -/// -/// GCC expects certain built-in functions to be defined in the environment. -/// Since PK applications are statically linked, we must define these -/// functions ourselves to avoid a static link with the GCC libraries, which -/// would legaly require us to distribute (at least) the binary forms of PK -/// applications. -/// -/// We obviously had to look at some GCC library code to understand the -/// specifications of these routines. However, all of the code here is new - -/// no structure definitions or lines of executable code were copied from the -/// GCC sources. - -#include "pk.h" -#include "ppe42_gcc.h" - -/// A 64-bit logical right shift. -/// -/// Note that shifts with negative shift counts or shifts with shift counts -/// longer than 63 bits are undefined. - -uint64_t -__lshrdi3(uint64_t x, int i) -{ - Uint64 input, result; - - if (i == 0) { - return x; - } - - input.value = x; - - if (i >= 32) { - result.word[0] = 0; - result.word[1] = input.word[0] >> (i - 32); - } else { - result.word[0] = input.word[0] >> i; - result.word[1] = (input.word[1] >> i) | (input.word[0] << (32 - i)); - } - - return result.value; -} - - -/// A 64 bit arithmetic left shift. -/// -/// Note that shifts with negative shift counts or shifts with shift counts -/// longer than 63 bits are undefined. - -uint64_t -__ashldi3(uint64_t x, int i) -{ - Uint64 input, result; - - if (i == 0) { - return x; - } - - input.value = x; - - if (i >= 32) { - result.word[1] = 0; - result.word[0] = input.word[1] << (i - 32); - } else { - result.word[1] = input.word[1] << i; - result.word[0] = (input.word[0] << i) | (input.word[1] >> (32 - i)); - } - - return result.value ; - -} - - -/// A 64 bit arithmetic right shift. -/// -/// Note that shifts with negative shift counts or shifts with shift counts -/// longer than 63 bits are undefined. - -uint64_t -__ashrdi3(uint64_t x, int i) -{ - Int64 input, result; - - if (i == 0) { - return x; - } - - input.value = x; - - if (i >= 32) { - result.word[0] = input.word[0] >> 31; - result.word[1] = input.word[0] >> (i - 32); - } else { - result.word[0] = input.word[0] >> i; - result.word[1] = - (((uint32_t)input.word[1]) >> i) | - (input.word[0] << (32 - i)); - } - - return result.value ; - -} - - -/// 32-bit Population count - -// This is a well-known divide-and-conquer algorithm, e.g. look on Wikipedia -// under "Hamming Weight". The idea is to compute sums of adjacent bit -// segments in parallel, in place. - -int -__popcountsi2(uint32_t x) -{ - uint32_t m1 = 0x55555555; - uint32_t m2 = 0x33333333; - uint32_t m4 = 0x0f0f0f0f; - x -= (x >> 1) & m1; /* Sum pairs of bits */ - x = (x & m2) + ((x >> 2) & m2);/* Sum 4-bit segments */ - x = (x + (x >> 4)) & m4; /* Sum 8-bit segments */ - x += x >> 8; /* Sum 16-bit segments */ - return (x + (x >> 16)) & 0x3f; /* Final sum */ -} - - -/// 64-bit Population count - -int -__popcountdi2(uint64_t x) -{ - return __popcountsi2(x >> 32) + __popcountsi2(x & 0xffffffff); -} - - -// 64-bit divides -// -// For the unsigned case, note that divide by 0 returns quotient = remainder = -// 0. -// -// For the signed case, in general we perform the division on the absolute -// values and fix the signs of the quotient and remainder at the end. -// -// For the signed case, the convention in other libraries seems to be to -// ignore the case of the most-negative integer. Although it seems "wrong" to -// return the wrong answer when the right answer can be easily computed, in -// the interest of code size we follow the convention here and ignore the most -// negative integer. -// -// The assembler routine __ppe42_udiv64() assembles to ??? bytes. The full C -// routine __ppc_sdiv64 compiles to ??? bytes with the most-negative checks, -// but only ??? bytes as configured here. - -// For the signed cases, we need to handle the special case that the dividend -// or divisor is the most negative integer. -// -// If the dividend is the most negative integer, then dividing this integer by -// -1 would overflow as a positive quotient, so we set quotient and remainder -// to 0 in this case. For divide by 1, the quotient is the most negative -// integer. Otherwise we adjust the dividend by the absolute value of the -// divisor, then fix up the quotient later by adding or subtracting 1. -// -// If the divisor is the most negative integer, then the quotient is always 0 -// unless the dividend is also the most negative integer, in which case the -// quotient is 1 and the remainder is 0. -// - -uint64_t -__udivdi3(uint64_t u, uint64_t v) -{ - uint64_t quotient, remainder; - - __ppe42_udiv64(u, v, "ient, &remainder); - return quotient; -} - - -uint64_t -__umoddi3(uint64_t u, uint64_t v) -{ - uint64_t quotient, remainder; - - __ppe42_udiv64(u, v, "ient, &remainder); - return remainder; -} - - -#if 0 -#define INT64_T_MIN ((int64_t)(0x8000000000000000ull)) -#endif - -void -__ppe42_sdiv64(int64_t u, int64_t v, - int64_t *quotient, int64_t *remainder) -{ - int q_negate, r_negate; - uint64_t uu, uv; -#if 0 - int fixup = 0; -#endif - - q_negate = (u < 0) ^ (v < 0); - r_negate = (u < 0); - uu = (u < 0 ? -u : u); - uv = (v < 0 ? -v : v); - -#if 0 - if (u == INT64_T_MIN) { - if (v == -1) { - *quotient = 0; - *remainder = 0; - return; - } else if (v == 1) { - *quotient = INT64_T_MIN; - *remainder = 0; - return; - } else if (v == INT64_T_MIN) { - *quotient = 1; - *remainder = 0; - return; - } else { - fixup = 1; - u += (v < 0 ? -v : v); - } - } else if (v == INT64_T_MIN) { - *quotient = 0; - *remainder = u; - return; - } -#endif - - __ppe42_udiv64(uu, uv, (uint64_t *)quotient, (uint64_t *)remainder); - -#if 0 - if (fixup) { - *quotient += 1; - } -#endif - if (q_negate) { - *quotient = -(*quotient); - } - if (r_negate) { - *remainder = -(*remainder); - } -} - - -int64_t -__divdi3(int64_t u, int64_t v) -{ - int64_t quotient, remainder; - - __ppe42_sdiv64(u, v, "ient, &remainder); - return quotient; -} - - -int64_t -__moddi3(int64_t u, int64_t v) -{ - int64_t quotient, remainder; - - __ppe42_sdiv64(u, v, "ient, &remainder); - return remainder; -} - - -/// 64-bit unsigned compare as a function, returning 0 (<), 1 (==) or 2 (>). - -int -__ucmpdi2(uint64_t i_a, uint64_t i_b) -{ - Uint64 a, b; - int rv; - - a.value = i_a; - b.value = i_b; - - if (a.word[0] < b.word[0]) { - rv = 0; - } else if (a.word[0] > b.word[0]) { - rv = 2; - } else if (a.word[1] < b.word[1]) { - rv = 0; - } else if (a.word[1] > b.word[1]) { - rv = 2; - } else { - rv = 1; - } - - return rv; -} - - - - - - - - |