123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- /* Generic signed 32 bit division implementation.
- Copyright (C) 2009-2022 Free Software Foundation, Inc.
- Contributed by Embecosm on behalf of Adapteva, Inc.
- This file is part of GCC.
- This file is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 3, or (at your option) any
- later version.
- This file is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- Under Section 7 of GPL version 3, you are granted additional
- permissions described in the GCC Runtime Library Exception, version
- 3.1, as published by the Free Software Foundation.
- You should have received a copy of the GNU General Public License and
- a copy of the GCC Runtime Library Exception along with this program;
- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- <http://www.gnu.org/licenses/>. */
- typedef union { unsigned int i; float f; } fu;
- /* Although the semantics of the function ask for signed / unsigned inputs,
- for the actual implementation we use unsigned numbers. */
- unsigned int __divsi3 (unsigned int a, unsigned int b);
- unsigned int
- __divsi3 (unsigned int a, unsigned int b)
- {
- unsigned int sign = (int) (a ^ b) >> 31;
- unsigned int d, t, s0, s1, s2, r0, r1;
- fu u0, u1, u2, u1b, u2b;
- a = abs (a);
- b = abs (b);
- if (b > a)
- return 0;
- /* Compute difference in number of bits in S0. */
- u0.i = 0x40000000;
- u1b.i = u2b.i = u0.i;
- u1.i = a;
- u2.i = b;
- u1.i = a | u0.i;
- t = 0x4b800000 | ((a >> 23) & 0xffff);
- if (a >> 23)
- {
- u1.i = t;
- u1b.i = 0x4b800000;
- }
- u2.i = b | u0.i;
- t = 0x4b800000 | ((b >> 23) & 0xffff);
- if (b >> 23)
- {
- u2.i = t;
- u2b.i = 0x4b800000;
- }
- u1.f = u1.f - u1b.f;
- u2.f = u2.f - u2b.f;
- s1 = u1.i >> 23;
- s2 = u2.i >> 23;
- s0 = s1 - s2;
- b <<= s0;
- d = b - 1;
- r0 = 1 << s0;
- r1 = 0;
- t = a - b;
- if (t <= a)
- {
- a = t;
- r1 = r0;
- }
- #define STEP(n) case n: a += a; t = a - d; if (t <= a) a = t;
- switch (s0)
- {
- STEP (31)
- STEP (30)
- STEP (29)
- STEP (28)
- STEP (27)
- STEP (26)
- STEP (25)
- STEP (24)
- STEP (23)
- STEP (22)
- STEP (21)
- STEP (20)
- STEP (19)
- STEP (18)
- STEP (17)
- STEP (16)
- STEP (15)
- STEP (14)
- STEP (13)
- STEP (12)
- STEP (11)
- STEP (10)
- STEP (9)
- STEP (8)
- STEP (7)
- STEP (6)
- STEP (5)
- STEP (4)
- STEP (3)
- STEP (2)
- STEP (1)
- case 0: ;
- }
- r0 = r1 | (r0-1 & a);
- return (r0 ^ sign) - sign;
- }
|