(root)/
gcc-13.2.0/
libgcc/
config/
visium/
lib2funcs.c
       1  /* Copyright (C) 2014-2023 Free Software Foundation, Inc.
       2  
       3  This file is part of GCC.
       4  
       5  GCC is free software; you can redistribute it and/or modify it under
       6  the terms of the GNU General Public License as published by the Free
       7  Software Foundation; either version 3, or (at your option) any later
       8  version.
       9  
      10  GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11  WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13  for more details.
      14  
      15  Under Section 7 of GPL version 3, you are granted additional
      16  permissions described in the GCC Runtime Library Exception, version
      17  3.1, as published by the Free Software Foundation.
      18  
      19  You should have received a copy of the GNU General Public License and
      20  a copy of the GCC Runtime Library Exception along with this program;
      21  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      22  <http://www.gnu.org/licenses/>.  */
      23  
      24  #include "tconfig.h"
      25  #include "tsystem.h"
      26  #include "coretypes.h"
      27  #include "tm.h"
      28  #include "libgcc_tm.h"
      29  
      30  #ifdef HAVE_GAS_HIDDEN
      31  #define ATTRIBUTE_HIDDEN  __attribute__ ((__visibility__ ("hidden")))
      32  #else
      33  #define ATTRIBUTE_HIDDEN
      34  #endif
      35  
      36  /* Work out the largest "word" size that we can deal with on this target.  */
      37  #if MIN_UNITS_PER_WORD > 4
      38  # define LIBGCC2_MAX_UNITS_PER_WORD 8
      39  #elif (MIN_UNITS_PER_WORD > 2 \
      40         || (MIN_UNITS_PER_WORD > 1 && __SIZEOF_LONG_LONG__ > 4))
      41  # define LIBGCC2_MAX_UNITS_PER_WORD 4
      42  #else
      43  # define LIBGCC2_MAX_UNITS_PER_WORD MIN_UNITS_PER_WORD
      44  #endif
      45  
      46  /* Work out what word size we are using for this compilation.
      47     The value can be set on the command line.  */
      48  #ifndef LIBGCC2_UNITS_PER_WORD
      49  #define LIBGCC2_UNITS_PER_WORD LIBGCC2_MAX_UNITS_PER_WORD
      50  #endif
      51  
      52  #if LIBGCC2_UNITS_PER_WORD <= LIBGCC2_MAX_UNITS_PER_WORD
      53  
      54  #include "libgcc2.h"
      55  
      56  /* umul_ppmm(high_prod, low_prod, multiplier, multiplicand) multiplies two
      57     UWtype integers MULTIPLIER and MULTIPLICAND, and generates a two UWtype
      58     word product in HIGH_PROD and LOW_PROD.  */
      59  
      60  #undef umul_ppmm
      61  #define umul_ppmm(wh, wl, u, v)			\
      62    do {						\
      63      /* Generate multu instruction.  */		\
      64      UDWtype __t = (UDWtype)(u) * (UDWtype)(v);	\
      65      (wl) = (UWtype)__t;				\
      66      (wh) = (UWtype)(__t >> W_TYPE_SIZE);	\
      67    } while (0)
      68  
      69  /* sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
      70     high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
      71     composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
      72     LOW_SUBTRAHEND_2 respectively.  The result is placed in HIGH_DIFFERENCE
      73     and LOW_DIFFERENCE.  Overflow (i.e. carry out) is not stored anywhere,
      74     and is lost.  */
      75  
      76  #undef sub_ddmmss
      77  #define sub_ddmmss(sh, sl, ah, al, bh, bl)		\
      78    __asm__ ("sub.l   %0,%2,%4\n\t"			\
      79  	   "subc.l  %1,%3,%5"				\
      80  	   : "=&r" (sl), "=r" (sh)			\
      81  	   : "r" (al), "r" (ah), "r" (bl), "r" (bh))
      82  
      83  /* udiv_qqrnnd(high_quotient, low_quotient, remainder, high_numerator,
      84     low_numerator, denominator) divides a UDWtype, composed by the UWtype
      85     HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
      86     in QUOTIENT and the remainder in REMAINDER.  */
      87  
      88  #define udiv_qqrnnd(qh, ql, r, nh, nl, d)	\
      89    __asm__ ("writemd %3,%4\n\t"			\
      90  	   "divdu   %5\n\t"			\
      91  	   "readmda %0\n\t"			\
      92  	   "readmdb %1\n\t"			\
      93  	   "readmdc %2"				\
      94  	   : "=r" (ql), "=r" (qh), "=r" (r)	\
      95  	   : "r" (nl), "r" (nh), "r" (d)	\
      96  	   : "mdb", "mdc")
      97  
      98  #if (defined (L_udivdi3) || defined (L_divdi3) || \
      99       defined (L_umoddi3) || defined (L_moddi3))
     100  #define L_udivmoddi4
     101  #endif
     102  
     103  #ifdef L_udivmoddi4
     104  
     105  #if (defined (L_udivdi3) || defined (L_divdi3) || \
     106       defined (L_umoddi3) || defined (L_moddi3))
     107  static inline __attribute__ ((__always_inline__))
     108  #endif
     109  UDWtype
     110  __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
     111  {
     112    const DWunion nn = {.ll = n};
     113    const DWunion dd = {.ll = d};
     114    DWunion rr;
     115    UWtype d0, d1, n0, n1, n2;
     116    UWtype q0, q1;
     117    UWtype b, bm;
     118  
     119    d0 = dd.s.low;
     120    d1 = dd.s.high;
     121    n0 = nn.s.low;
     122    n1 = nn.s.high;
     123  
     124    if (d1 == 0)
     125      {
     126        /* qq = NN / 0d */
     127  
     128        if (d0 == 0)
     129  	d0 = 1 / d0;	/* Divide intentionally by zero.  */
     130  
     131        udiv_qqrnnd (q1, q0, n0, n1, n0, d0);
     132  
     133        /* Remainder in n0.  */
     134  
     135        if (rp != 0)
     136  	{
     137  	  rr.s.low = n0;
     138  	  rr.s.high = 0;
     139  	  *rp = rr.ll;
     140  	}
     141      }
     142  
     143    else
     144      {
     145        if (d1 > n1)
     146  	{
     147  	  /* 00 = nn / DD */
     148  
     149  	  q0 = 0;
     150  	  q1 = 0;
     151  
     152  	  /* Remainder in n1n0.  */
     153  	  if (rp != 0)
     154  	    {
     155  	      rr.s.low = n0;
     156  	      rr.s.high = n1;
     157  	      *rp = rr.ll;
     158  	    }
     159  	}
     160        else
     161  	{
     162  	  /* 0q = NN / dd */
     163  
     164  	  count_leading_zeros (bm, d1);
     165  	  if (bm == 0)
     166  	    {
     167  	      /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
     168  		 conclude (the most significant bit of n1 is set) /\ (the
     169  		 quotient digit q0 = 0 or 1).
     170  
     171  		 This special case is necessary, not an optimization.  */
     172  
     173  	      /* The condition on the next line takes advantage of that
     174  		 n1 >= d1 (true due to program flow).  */
     175  	      if (n1 > d1 || n0 >= d0)
     176  		{
     177  		  q0 = 1;
     178  		  sub_ddmmss (n1, n0, n1, n0, d1, d0);
     179  		}
     180  	      else
     181  		q0 = 0;
     182  
     183  	      q1 = 0;
     184  
     185  	      if (rp != 0)
     186  		{
     187  		  rr.s.low = n0;
     188  		  rr.s.high = n1;
     189  		  *rp = rr.ll;
     190  		}
     191  	    }
     192  	  else
     193  	    {
     194  	      UWtype m1, m0;
     195  	      /* Normalize.  */
     196  
     197  	      b = W_TYPE_SIZE - bm;
     198  
     199  	      d1 = (d1 << bm) | (d0 >> b);
     200  	      d0 = d0 << bm;
     201  	      n2 = n1 >> b;
     202  	      n1 = (n1 << bm) | (n0 >> b);
     203  	      n0 = n0 << bm;
     204  
     205  	      udiv_qqrnnd (q1, q0, n1, n2, n1, d1);
     206  	      umul_ppmm (m1, m0, q0, d0);
     207  
     208  	      if (m1 > n1 || (m1 == n1 && m0 > n0))
     209  		{
     210  		  q0--;
     211  		  sub_ddmmss (m1, m0, m1, m0, d1, d0);
     212  		}
     213  
     214  	      /* Remainder in (n1n0 - m1m0) >> bm.  */
     215  	      if (rp != 0)
     216  		{
     217  		  sub_ddmmss (n1, n0, n1, n0, m1, m0);
     218  		  rr.s.low = (n1 << b) | (n0 >> bm);
     219  		  rr.s.high = n1 >> bm;
     220  		  *rp = rr.ll;
     221  		}
     222  	    }
     223  	}
     224      }
     225  
     226    const DWunion ww = {{.low = q0, .high = q1}};
     227    return ww.ll;
     228  }
     229  #endif
     230  
     231  #ifdef L_divdi3
     232  DWtype
     233  __divdi3 (DWtype u, DWtype v)
     234  {
     235    Wtype c = 0;
     236    DWunion uu = {.ll = u};
     237    DWunion vv = {.ll = v};
     238    DWtype w;
     239  
     240    if (uu.s.high < 0)
     241      c = ~c,
     242      uu.ll = -uu.ll;
     243    if (vv.s.high < 0)
     244      c = ~c,
     245      vv.ll = -vv.ll;
     246  
     247    w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
     248    if (c)
     249      w = -w;
     250  
     251    return w;
     252  }
     253  #endif
     254  
     255  #ifdef L_moddi3
     256  DWtype
     257  __moddi3 (DWtype u, DWtype v)
     258  {
     259    Wtype c = 0;
     260    DWunion uu = {.ll = u};
     261    DWunion vv = {.ll = v};
     262    DWtype w;
     263  
     264    if (uu.s.high < 0)
     265      c = ~c,
     266      uu.ll = -uu.ll;
     267    if (vv.s.high < 0)
     268      vv.ll = -vv.ll;
     269  
     270    (void) __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&w);
     271    if (c)
     272      w = -w;
     273  
     274    return w;
     275  }
     276  #endif
     277  
     278  #ifdef L_umoddi3
     279  UDWtype
     280  __umoddi3 (UDWtype u, UDWtype v)
     281  {
     282    UDWtype w;
     283  
     284    (void) __udivmoddi4 (u, v, &w);
     285  
     286    return w;
     287  }
     288  #endif
     289  
     290  #ifdef L_udivdi3
     291  UDWtype
     292  __udivdi3 (UDWtype n, UDWtype d)
     293  {
     294    return __udivmoddi4 (n, d, (UDWtype *) 0);
     295  }
     296  #endif
     297  
     298  #ifdef L_set_trampoline_parity
     299  #undef int
     300  extern void __set_trampoline_parity (UWtype *);
     301  
     302  static inline UWtype
     303  parity_bit (UWtype x)
     304  {
     305    x ^= x << 16;
     306    x ^= x << 8;
     307    x ^= x << 4;
     308    x ^= x << 2;
     309    x ^= x << 1;
     310    return x & ((UWtype) 1 << (W_TYPE_SIZE - 1));
     311  }
     312  
     313  void
     314  __set_trampoline_parity (UWtype *addr)
     315  {
     316    int i;
     317  
     318    for (i = 0;
     319         i < (__LIBGCC_TRAMPOLINE_SIZE__ * __CHAR_BIT__) / W_TYPE_SIZE;
     320         i++)
     321      addr[i] |= parity_bit (addr[i]);
     322  }
     323  #endif
     324  
     325  #endif /* LIBGCC2_UNITS_PER_WORD <= MIN_UNITS_PER_WORD */