1/* Copyright (C) 2014-2020 Free Software Foundation, Inc. 2 3This file is part of GCC. 4 5GCC is free software; you can redistribute it and/or modify it under 6the terms of the GNU General Public License as published by the Free 7Software Foundation; either version 3, or (at your option) any later 8version. 9 10GCC is distributed in the hope that it will be useful, but WITHOUT ANY 11WARRANTY; without even the implied warranty of MERCHANTABILITY or 12FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13for more details. 14 15Under Section 7 of GPL version 3, you are granted additional 16permissions described in the GCC Runtime Library Exception, version 173.1, as published by the Free Software Foundation. 18 19You should have received a copy of the GNU General Public License and 20a copy of the GCC Runtime Library Exception along with this program; 21see 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)) 107static inline __attribute__ ((__always_inline__)) 108#endif 109UDWtype 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 232DWtype 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 256DWtype 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 279UDWtype 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 291UDWtype 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 300extern void __set_trampoline_parity (UWtype *); 301 302static inline UWtype 303parity_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 313void 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 */ 326