From adade8c8ef30ed519322674c762d95663009c5d4 Mon Sep 17 00:00:00 2001 From: mbroyles Date: Mon, 3 Aug 2015 14:02:47 -0500 Subject: new ppe dir Change-Id: I43d54c18ac4f3bce90a4f26510e443a55c446bba Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/19509 Reviewed-by: William A. Bryan Tested-by: William A. Bryan --- src/ppe/pk/ppe42/ppe42_gcc.c | 329 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 src/ppe/pk/ppe42/ppe42_gcc.c (limited to 'src/ppe/pk/ppe42/ppe42_gcc.c') diff --git a/src/ppe/pk/ppe42/ppe42_gcc.c b/src/ppe/pk/ppe42/ppe42_gcc.c new file mode 100644 index 0000000..37674dc --- /dev/null +++ b/src/ppe/pk/ppe42/ppe42_gcc.c @@ -0,0 +1,329 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/ppe/pk/ppe42/ppe42_gcc.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +//----------------------------------------------------------------------------- +// *! (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; +} + + + + + + + + -- cgit v1.2.1