My Project
Chargement...
Recherche...
Aucune correspondance
i386
arith64.c
Aller à la documentation de ce fichier.
1
// GCC 32/64-bit integer arithmetic support for 32-bit systems that can't link
2
// to libgcc.
3
4
// Function prototypes and descriptions are taken from
5
// https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html.
6
7
// This file may be #include'd by another file, so we try not to pollute the
8
// namespace and we don't import any headers.
9
10
// All functions must be resolvable by the linker and therefore can't be inline
11
// or static, even if they're #included into the file where they'll be used.
12
13
// For best performance we try to avoid branching. This makes the code a little
14
// weird in places.
15
16
// See https://github.com/glitchub/arith64 for more information.
17
// This software is released as-is into the public domain, as described at
18
// https://unlicense.org. Do whatever you like with it.
19
20
#include <
manux/arith64.h
>
21
22
// Return the absolute value of a.
23
// Note LLINT_MIN cannot be negated.
24
static
arith64_s64
__absvdi2(
arith64_s64
a
)
25
{
26
return
arith64_abs
(
a
);
27
}
28
29
// Return the result of shifting a left by b bits.
30
static
arith64_s64
__ashldi3(
arith64_s64
a
,
int
b
)
31
{
32
arith64_word
w = {.
s64
=
a
};
33
34
b
&= 63;
35
36
if
(
b
>= 32)
37
{
38
w.
u32
.
hi
= w.
u32
.
lo
<< (
b
- 32);
39
w.
u32
.
lo
= 0;
40
}
else
if
(
b
)
41
{
42
w.
u32
.
hi
= (w.
u32
.
lo
>> (32 -
b
)) | (w.
u32
.
hi
<<
b
);
43
w.
u32
.
lo
<<=
b
;
44
}
45
return
w.
s64
;
46
}
47
48
// Return the result of arithmetically shifting a right by b bits.
49
static
arith64_s64
__ashrdi3(
arith64_s64
a
,
int
b
)
50
{
51
arith64_word
w = {.
s64
=
a
};
52
53
b
&= 63;
54
55
if
(
b
>= 32)
56
{
57
w.
s32
.
lo
= w.
s32
.
hi
>> (
b
- 32);
58
w.
s32
.
hi
>>= 31;
// 0xFFFFFFFF or 0
59
}
else
if
(
b
)
60
{
61
w.
u32
.
lo
= (w.
u32
.
hi
<< (32 -
b
)) | (w.
u32
.
lo
>>
b
);
62
w.
s32
.
hi
>>=
b
;
63
}
64
return
w.
s64
;
65
}
66
67
// These functions return the number of leading 0-bits in a, starting at the
68
// most significant bit position. If a is zero, the result is undefined.
69
static
int
__clzsi2(
arith64_u32
a
)
70
{
71
int
b
, n = 0;
72
b
= !(
a
& 0xffff0000) << 4; n +=
b
;
a
<<=
b
;
73
b
= !(
a
& 0xff000000) << 3; n +=
b
;
a
<<=
b
;
74
b
= !(
a
& 0xf0000000) << 2; n +=
b
;
a
<<=
b
;
75
b
= !(
a
& 0xc0000000) << 1; n +=
b
;
a
<<=
b
;
76
return
n + !(
a
& 0x80000000);
77
}
78
79
static
int
__clzdi2(
arith64_u64
a
)
80
{
81
int
b
, n = 0;
82
b
= !(
a
& 0xffffffff00000000ULL) << 5; n +=
b
;
a
<<=
b
;
83
b
= !(
a
& 0xffff000000000000ULL) << 4; n +=
b
;
a
<<=
b
;
84
b
= !(
a
& 0xff00000000000000ULL) << 3; n +=
b
;
a
<<=
b
;
85
b
= !(
a
& 0xf000000000000000ULL) << 2; n +=
b
;
a
<<=
b
;
86
b
= !(
a
& 0xc000000000000000ULL) << 1; n +=
b
;
a
<<=
b
;
87
return
n + !(
a
& 0x8000000000000000ULL);
88
}
89
90
// These functions return the number of trailing 0-bits in a, starting at the
91
// least significant bit position. If a is zero, the result is undefined.
92
static
int
__ctzsi2(
arith64_u32
a
)
93
{
94
int
b
, n = 0;
95
b
= !(
a
& 0x0000ffff) << 4; n +=
b
;
a
>>=
b
;
96
b
= !(
a
& 0x000000ff) << 3; n +=
b
;
a
>>=
b
;
97
b
= !(
a
& 0x0000000f) << 2; n +=
b
;
a
>>=
b
;
98
b
= !(
a
& 0x00000003) << 1; n +=
b
;
a
>>=
b
;
99
return
n + !(
a
& 0x00000001);
100
}
101
102
static
int
__ctzdi2(
arith64_u64
a
)
103
{
104
int
b
, n = 0;
105
b
= !(
a
& 0x00000000ffffffffULL) << 5; n +=
b
;
a
>>=
b
;
106
b
= !(
a
& 0x000000000000ffffULL) << 4; n +=
b
;
a
>>=
b
;
107
b
= !(
a
& 0x00000000000000ffULL) << 3; n +=
b
;
a
>>=
b
;
108
b
= !(
a
& 0x000000000000000fULL) << 2; n +=
b
;
a
>>=
b
;
109
b
= !(
a
& 0x0000000000000003ULL) << 1; n +=
b
;
a
>>=
b
;
110
return
n + !(
a
& 0x0000000000000001ULL);
111
}
112
113
// Calculate both the quotient and remainder of the unsigned division of a and
114
// b. The return value is the quotient, and the remainder is placed in variable
115
// pointed to by c (if it's not NULL).
116
static
arith64_u64
__divmoddi4(
arith64_u64
a
,
arith64_u64
b
,
arith64_u64
*
c
)
117
{
118
if
(
b
>
a
)
// divisor > numerator?
119
{
120
if
(
c
) *
c
=
a
;
// remainder = numerator
121
return
0;
// quotient = 0
122
}
123
if
(!
arith64_hi
(
b
))
// divisor is 32-bit
124
{
125
if
(
b
== 0)
// divide by 0
126
{
127
volatile
char
x = 0; x = 1 / x;
// force an exception
128
}
129
if
(
b
== 1)
// divide by 1
130
{
131
if
(
c
) *
c
= 0;
// remainder = 0
132
return
a
;
// quotient = numerator
133
}
134
if
(!
arith64_hi
(
a
))
// numerator is also 32-bit
135
{
136
if
(
c
)
// use generic 32-bit operators
137
*
c
=
arith64_lo
(
a
) %
arith64_lo
(
b
);
138
return
arith64_lo
(
a
) /
arith64_lo
(
b
);
139
}
140
}
141
142
// let's do long division
143
char
bits = __clzdi2(
b
) - __clzdi2(
a
) + 1;
// number of bits to iterate (a and b are non-zero)
144
arith64_u64
rem =
a
>> bits;
// init remainder
145
a
<<= 64 - bits;
// shift numerator to the high bit
146
arith64_u64
wrap = 0;
// start with wrap = 0
147
while
(bits-- > 0)
// for each bit
148
{
149
rem = (rem << 1) | (
a
>> 63);
// shift numerator MSB to remainder LSB
150
a
= (
a
<< 1) | (wrap & 1);
// shift out the numerator, shift in wrap
151
wrap = ((
arith64_s64
)(
b
- rem - 1) >> 63);
// wrap = (b > rem) ? 0 : 0xffffffffffffffff (via sign extension)
152
rem -=
b
& wrap;
// if (wrap) rem -= b
153
}
154
if
(
c
) *
c
= rem;
// maybe set remainder
155
return
(
a
<< 1) | (wrap & 1);
// return the quotient
156
}
157
158
// Return the quotient of the signed division of a and b.
159
arith64_s64
__divdi3
(
arith64_s64
a
,
arith64_s64
b
)
160
{
161
arith64_u64
q = __divmoddi4(
arith64_abs
(
a
),
arith64_abs
(
b
), (
void
*)0);
162
return
arith64_neg
(q,
a
^
b
);
// negate q if a and b signs are different
163
}
164
165
// Return the index of the least significant 1-bit in a, or the value zero if a
166
// is zero. The least significant bit is index one.
167
static
int
__ffsdi2(
arith64_u64
a
)
168
{
169
return
a
? __ctzdi2(
a
) + 1 : 0;
170
}
171
172
// Return the result of logically shifting a right by b bits.
173
static
arith64_u64
__lshrdi3(
arith64_u64
a
,
int
b
)
174
{
175
arith64_word
w = {.
u64
=
a
};
176
177
b
&= 63;
178
179
if
(
b
>= 32)
180
{
181
w.
u32
.
lo
= w.
u32
.
hi
>> (
b
- 32);
182
w.
u32
.
hi
= 0;
183
}
else
if
(
b
)
184
{
185
w.
u32
.
lo
= (w.
u32
.
hi
<< (32 -
b
)) | (w.
u32
.
lo
>>
b
);
186
w.
u32
.
hi
>>=
b
;
187
}
188
return
w.
u64
;
189
}
190
191
// Return the remainder of the signed division of a and b.
192
arith64_s64
__moddi3
(
arith64_s64
a
,
arith64_s64
b
)
193
{
194
arith64_u64
r;
195
__divmoddi4(
arith64_abs
(
a
),
arith64_abs
(
b
), &r);
196
return
arith64_neg
(r,
a
);
// negate remainder if numerator is negative
197
}
198
199
// Return the number of bits set in a.
200
static
int
__popcountsi2(
arith64_u32
a
)
201
{
202
// collect sums into two low bytes
203
a
=
a
- ((
a
>> 1) & 0x55555555);
204
a
= ((
a
>> 2) & 0x33333333) + (
a
& 0x33333333);
205
a
= (
a
+ (
a
>> 4)) & 0x0F0F0F0F;
206
a
= (
a
+ (
a
>> 16));
207
// add the bytes, return bottom 6 bits
208
return
(
a
+ (
a
>> 8)) & 63;
209
}
210
211
// Return the number of bits set in a.
212
static
int
__popcountdi2(
arith64_u64
a
)
213
{
214
// collect sums into two low bytes
215
a
=
a
- ((
a
>> 1) & 0x5555555555555555ULL);
216
a
= ((
a
>> 2) & 0x3333333333333333ULL) + (
a
& 0x3333333333333333ULL);
217
a
= (
a
+ (
a
>> 4)) & 0x0F0F0F0F0F0F0F0FULL;
218
a
= (
a
+ (
a
>> 32));
219
a
= (
a
+ (
a
>> 16));
220
// add the bytes, return bottom 7 bits
221
return
(
a
+ (
a
>> 8)) & 127;
222
}
223
224
// Return the quotient of the unsigned division of a and b.
225
static
arith64_u64
__udivdi3(
arith64_u64
a
,
arith64_u64
b
)
226
{
227
return
__divmoddi4(
a
,
b
, (
void
*)0);
228
}
229
230
// Return the remainder of the unsigned division of a and b.
231
static
arith64_u64
__umoddi3(
arith64_u64
a
,
arith64_u64
b
)
232
{
233
arith64_u64
r;
234
__divmoddi4(
a
,
b
, &r);
235
return
r;
236
}
__divdi3
arith64_s64 __divdi3(arith64_s64 a, arith64_s64 b)
Definition
arith64.c:159
__moddi3
arith64_s64 __moddi3(arith64_s64 a, arith64_s64 b)
Definition
arith64.c:192
arith64.h
arith64_lo
#define arith64_lo(n)
Definition
arith64.h:35
arith64_u32
#define arith64_u32
Definition
arith64.h:8
arith64_hi
#define arith64_hi(n)
Definition
arith64.h:34
arith64_abs
#define arith64_abs(a)
Definition
arith64.h:39
arith64_s64
#define arith64_s64
Definition
arith64.h:7
arith64_u64
#define arith64_u64
Definition
arith64.h:6
arith64_neg
#define arith64_neg(a, b)
Definition
arith64.h:38
b
uint16_t b
Definition
main-bootreg.c:24
a
uint16_t a
Exemple de fonction de mise-à-jour d'un paramètre dans un registre.
Definition
main-bootreg.c:24
c
uint16_t c
Definition
main-bootreg.c:24
arith64_word
Definition
arith64.h:12
arith64_word::s32
struct arith64_word::@1 s32
arith64_word::u32
struct arith64_word::@0 u32
arith64_word::u64
arith64_u64 u64
Definition
arith64.h:13
arith64_word::lo
arith64_u32 lo
Definition
arith64.h:18
arith64_word::s64
arith64_s64 s64
Definition
arith64.h:14
arith64_word::hi
arith64_u32 hi
Definition
arith64.h:18
Généré par
1.9.8