Skip to content

Commit a4ab7e2

Browse files
committed
Tune up C-library stubs
1 parent f2cb11f commit a4ab7e2

1 file changed

Lines changed: 102 additions & 0 deletions

File tree

  • ref_app/target/micros/xtensa_esp32_s3/startup/Std

ref_app/target/micros/xtensa_esp32_s3/startup/Std/StdLib.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,108 @@
2929

3030
extern "C" {
3131

32+
typedef signed long long DItype __attribute__((mode (DI)));
33+
typedef unsigned long long UDItype __attribute__((mode (DI)));
34+
typedef unsigned int USItype __attribute__((mode (SI)));
35+
36+
extern int __builtin_clzll(unsigned long long);
37+
38+
#define DWtype DItype
39+
#define UDWtype UDItype
40+
#define UWtype USItype
41+
42+
UDWtype __udivdi3 (UDWtype n, UDWtype d);
43+
UDWtype __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp);
44+
UDWtype __umoddi3 (UDWtype u, UDWtype v);
45+
46+
UDWtype __udivdi3 (UDWtype n, UDWtype d)
47+
{
48+
return __udivmoddi4 (n, d, (UDWtype *) 0);
49+
}
50+
51+
UDWtype __umoddi3 (UDWtype u, UDWtype v)
52+
{
53+
UDWtype w;
54+
55+
(void) __udivmoddi4 (u, v, &w);
56+
57+
return w;
58+
}
59+
60+
UDWtype __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
61+
{
62+
UDWtype q = 0, r = n, y = d;
63+
UWtype lz1, lz2, i, k;
64+
65+
// Implements align divisor shift dividend method. This algorithm
66+
// aligns the divisor under the dividend and then perform number of
67+
// test-subtract iterations which shift the dividend left. Number of
68+
// iterations is k + 1 where k is the number of bit positions the
69+
// divisor must be shifted left to align it under the dividend.
70+
// quotient bits can be saved in the rightmost positions of the dividend
71+
// as it shifts left on each test-subtract iteration.
72+
73+
if (y <= r)
74+
{
75+
lz1 = static_cast<USItype>(__builtin_clzll(static_cast<unsigned long long>(d)));
76+
lz2 = static_cast<USItype>(__builtin_clzll(static_cast<unsigned long long>(n)));
77+
78+
k = lz1 - lz2;
79+
y = (y << k);
80+
81+
// Dividend can exceed 2 ^ (width - 1) - 1 but still be less than the
82+
// aligned divisor. Normal iteration can drops the high order bit
83+
// of the dividend. Therefore, first test-subtract iteration is a
84+
// special case, saving its quotient bit in a separate location and
85+
// not shifting the dividend.
86+
87+
if (r >= y)
88+
{
89+
r = r - y;
90+
q = (1ULL << k);
91+
}
92+
93+
if (k > 0)
94+
{
95+
y = y >> 1;
96+
97+
// k additional iterations where k regular test subtract shift
98+
// dividend iterations are done.
99+
100+
i = k;
101+
102+
do
103+
{
104+
if (r >= y)
105+
{
106+
r = ((r - y) << 1) + 1;
107+
}
108+
else
109+
{
110+
r = (r << 1);
111+
}
112+
113+
i = i - 1;
114+
}
115+
while (i != 0);
116+
117+
// First quotient bit is combined with the quotient bits resulting
118+
// from the k regular iterations.
119+
120+
q = q + r;
121+
r = r >> k;
122+
q = q - (r << k);
123+
}
124+
}
125+
126+
if (rp)
127+
{
128+
*rp = r;
129+
}
130+
131+
return q;
132+
}
133+
32134
#if defined(__GNUC__)
33135
#pragma GCC diagnostic push
34136
#pragma GCC diagnostic ignored "-Wcast-align"

0 commit comments

Comments
 (0)