1193326Sed/* Generic unsigned 32 bit division implementation.
2193326Sed   Copyright (C) 2009-2015 Free Software Foundation, Inc.
3193326Sed   Contributed by Embecosm on behalf of Adapteva, Inc.
4193326Sed
5193326SedThis file is part of GCC.
6193326Sed
7193326SedThis file is free software; you can redistribute it and/or modify it
8193326Sedunder the terms of the GNU General Public License as published by the
9193326SedFree Software Foundation; either version 3, or (at your option) any
10205219Srdivackylater version.
11205219Srdivacky
12193326SedThis file is distributed in the hope that it will be useful, but
13193326SedWITHOUT ANY WARRANTY; without even the implied warranty of
14193326SedMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15193326SedGeneral Public License for more details.
16193326Sed
17193326SedUnder Section 7 of GPL version 3, you are granted additional
18198092Srdivackypermissions described in the GCC Runtime Library Exception, version
19234353Sdim3.1, as published by the Free Software Foundation.
20193326Sed
21212904SdimYou should have received a copy of the GNU General Public License and
22202879Srdivackya copy of the GCC Runtime Library Exception along with this program;
23234353Sdimsee the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24234353Sdim<http://www.gnu.org/licenses/>.  */
25198092Srdivacky
26234353Sdimtypedef union { unsigned int i; float f; } fu;
27193326Sed
28193326Sedunsigned int __udivsi3 (unsigned int a, unsigned int b);
29193326Sed
30193326Sedunsigned int
31198092Srdivacky__udivsi3 (unsigned int a, unsigned int b)
32198092Srdivacky{
33198092Srdivacky  unsigned int d, t, s0, s1, s2, r0, r1;
34193326Sed  fu u0, u1, u2,  u1b, u2b;
35198092Srdivacky
36193326Sed  if (b > a)
37193326Sed    return 0;
38198092Srdivacky
39198092Srdivacky  /* Compute difference in number of bits in S0.  */
40206084Srdivacky  u0.i = 0x40000000;
41218893Sdim  u1b.i = u2b.i = u0.i;
42205219Srdivacky  u1.i = a;
43234353Sdim  u2.i = b;
44239462Sdim  u1.i = a | u0.i;
45234353Sdim  t = 0x4b800000 | ((a >> 23) & 0xffff);
46198092Srdivacky  if (a >> 23)
47195099Sed    {
48195099Sed      u1.i = t;
49195099Sed      u1b.i = 0x4b800000;
50198092Srdivacky    }
51195341Sed  u2.i = b | u0.i;
52198092Srdivacky  t = 0x4b800000 | ((b >> 23) & 0xffff);
53195099Sed  if (b >> 23)
54195099Sed    {
55195099Sed      u2.i = t;
56198092Srdivacky      u2b.i = 0x4b800000;
57198092Srdivacky    }
58195099Sed  u1.f = u1.f - u1b.f;
59195099Sed  u2.f = u2.f - u2b.f;
60198092Srdivacky  s1 = u1.i >> 23;
61195099Sed  s2 = u2.i >> 23;
62195099Sed  s0 = s1 - s2;
63198092Srdivacky
64198092Srdivacky  b <<= s0;
65195341Sed  d = b - 1;
66195341Sed
67195099Sed  r0 = 1 << s0;
68198092Srdivacky  r1 = 0;
69195099Sed  t = a - b;
70195099Sed  if (t <= a)
71195099Sed    {
72198092Srdivacky      a = t;
73195099Sed      r1 = r0;
74195099Sed    }
75195099Sed
76195099Sed#define STEP(n) case n: a += a; t = a - d; if (t <= a) a = t;
77195099Sed  switch (s0)
78195099Sed    {
79195099Sed    STEP (31)
80195099Sed    STEP (30)
81195099Sed    STEP (29)
82198092Srdivacky    STEP (28)
83195341Sed    STEP (27)
84195341Sed    STEP (26)
85195341Sed    STEP (25)
86195341Sed    STEP (24)
87195341Sed    STEP (23)
88198092Srdivacky    STEP (22)
89195341Sed    STEP (21)
90195341Sed    STEP (20)
91195341Sed    STEP (19)
92195341Sed    STEP (18)
93195341Sed    STEP (17)
94198092Srdivacky    STEP (16)
95195341Sed    STEP (15)
96195341Sed    STEP (14)
97198092Srdivacky    STEP (13)
98195099Sed    STEP (12)
99195099Sed    STEP (11)
100195099Sed    STEP (10)
101198092Srdivacky    STEP (9)
102239462Sdim    STEP (8)
103210299Sed    STEP (7)
104210299Sed    STEP (6)
105210299Sed    STEP (5)
106210299Sed    STEP (4)
107210299Sed    STEP (3)
108210299Sed    STEP (2)
109210299Sed    STEP (1)
110210299Sed    case 0: ;
111210299Sed    }
112210299Sed  r0 = r1 | (r0-1 & a);
113234353Sdim  return r0;
114239462Sdim}
115210299Sed