1314564Sdim/* Copyright (C) 2014-2020 Free Software Foundation, Inc. 2285101Semaste 3353358SdimThis file is part of GCC. 4353358Sdim 5353358SdimGCC is free software; you can redistribute it and/or modify it under 6285101Semastethe terms of the GNU General Public License as published by the Free 7296417SdimSoftware Foundation; either version 3, or (at your option) any later 8285101Semasteversion. 9296417Sdim 10296417SdimGCC is distributed in the hope that it will be useful, but WITHOUT ANY 11285101SemasteWARRANTY; without even the implied warranty of MERCHANTABILITY or 12314564SdimFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13327952Sdimfor more details. 14321369Sdim 15321369SdimUnder Section 7 of GPL version 3, you are granted additional 16285101Semastepermissions described in the GCC Runtime Library Exception, version 17314564Sdim3.1, as published by the Free Software Foundation. 18285101Semaste 19314564SdimYou should have received a copy of the GNU General Public License and 20314564Sdima copy of the GCC Runtime Library Exception along with this program; 21314564Sdimsee the files COPYING3 and COPYING.RUNTIME respectively. If not, see 22314564Sdim<http://www.gnu.org/licenses/>. */ 23327952Sdim 24285101Semaste#include "tconfig.h" 25314564Sdim#include "tsystem.h" 26285101Semaste#include "coretypes.h" 27314564Sdim#include "tm.h" 28314564Sdim#include "libgcc_tm.h" 29285101Semaste 30314564Sdim#ifdef HAVE_GAS_HIDDEN 31314564Sdim#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) 32285101Semaste#else 33314564Sdim#define ATTRIBUTE_HIDDEN 34285101Semaste#endif 35314564Sdim 36285101Semaste/* Work out the largest "word" size that we can deal with on this target. */ 37314564Sdim#if MIN_UNITS_PER_WORD > 4 38285101Semaste# define LIBGCC2_MAX_UNITS_PER_WORD 8 39285101Semaste#elif (MIN_UNITS_PER_WORD > 2 \ 40314564Sdim || (MIN_UNITS_PER_WORD > 1 && __SIZEOF_LONG_LONG__ > 4)) 41285101Semaste# define LIBGCC2_MAX_UNITS_PER_WORD 4 42314564Sdim#else 43285101Semaste# define LIBGCC2_MAX_UNITS_PER_WORD MIN_UNITS_PER_WORD 44314564Sdim#endif 45285101Semaste 46314564Sdim/* Work out what word size we are using for this compilation. 47285101Semaste The value can be set on the command line. */ 48285101Semaste#ifndef LIBGCC2_UNITS_PER_WORD 49314564Sdim#define LIBGCC2_UNITS_PER_WORD LIBGCC2_MAX_UNITS_PER_WORD 50314564Sdim#endif 51285101Semaste 52285101Semaste#if LIBGCC2_UNITS_PER_WORD <= LIBGCC2_MAX_UNITS_PER_WORD 53296417Sdim 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