Chameleon

Chameleon Commit Details

Date:2016-05-20 11:42:54 (4 years 12 days ago)
Author:zenith432
Commit:2822
Parents: 2821
Message:Optimize prf(), eliminate use of 64-bit divisors in libsa
Changes:
M/branches/zenith432/i386/libsa/prf.c
M/branches/zenith432/i386/libsa/strtol.c

File differences

branches/zenith432/i386/libsa/prf.c
5353
5454
5555
56
57
58
5659
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
5788
5889
5990
......
69100
70101
71102
103
72104
73105
74106
......
76108
77109
78110
79
111
80112
81
82
83
113
114
115
116
117
118
119
120
121
84122
85
123
124
125
126
127
128
129
130
131
86132
87133
88134
......
223269
224270
225271
226
272
227273
228
274
229275
230
276
231277
278
279
280
281
282
283
232284
233285
234286
235287
236288
237
238
239
240
289
241290
242291
243292
*
*/
#define DIVIDEND_LOW *(unsigned int*) dividend
#define DIVIDEND_HIGH ((unsigned int*) dividend)[1]
/*
* Divides 64-bit dividend by 32-bit divisor.
* Quotient stored in dividend, remainder returned.
* Assumes little-endian byte order.
* Assumes divisor is non-zero.
*/
unsigned int i386_unsigned_div(
unsigned long long* dividend,
unsigned int divisor
)
{
unsigned int high = DIVIDEND_HIGH;
if (high >= divisor)
{
__asm__ volatile ("xorl %%edx, %%edx; divl %2" : "=a"(DIVIDEND_HIGH), "=d"(high) : "r"(divisor), "a"(high));
}
else
{
DIVIDEND_HIGH = 0;
}
__asm__ volatile("divl %2" : "+a"(DIVIDEND_LOW), "+d"(high) : "r"(divisor));
return high;
}
#undef DIVIDEND_HIGH
#undef DIVIDEND_LOW
/*
* Printn prints a number n in base b.
* We don't use recursion to avoid deep kernel stacks.
*/
char prbuf[22];
register char *cp;
int width = 0, neg = 0;
static const char hexdig[] = "0123456789abcdef0123456789ABCDEF";
if ((flag & SIGNED) && (long long)n < 0)
{
n = (unsigned long long)(-(long long)n);
}
cp = prbuf;
do
if ((b & -b) == b)// b is a power of 2
{
*cp++ = "0123456789abcdef0123456789ABCDEF"[(flag & UCASE) + (int) (n%b)];
n /= b;
width++;
unsigned int log2b = (unsigned int) (__builtin_ctz((unsigned int) b) & 31);
unsigned int mask = (unsigned int) (b - 1);
do
{
*cp++ = hexdig[(flag & UCASE) + (int) (n & mask)];
n >>= log2b;
width++;
}
while (n);
}
while (n);
else// b is not a power of 2
{
do
{
*cp++ = hexdig[(flag & UCASE) + (int) i386_unsigned_div(&n, (unsigned int) b)];
width++;
}
while (n);
}
if (neg)
{
case 's':
s = va_arg(ap, const char*);
width = 0;
while (s && (c = *s++))
if (!putfn_p)
{
if (putfn_p)
while (s && (c = *s++))
{
(void)(*putfn_p)(c, putfn_arg);
width++;
}
len += ((width < minwidth) ? minwidth : width);
break;
}
while (s && (c = *s++))
{
(void)(*putfn_p)(c, putfn_arg);
len++;
width++;
}
while (width++ < minwidth)
{
if (putfn_p)
{
(void)(*putfn_p)(' ', putfn_arg);
}
(void)(*putfn_p)(' ', putfn_arg);
len++;
}
break;
branches/zenith432/i386/libsa/strtol.c
324324
325325
326326
327
327
328328
329
329330
330331
331332
......
365366
366367
367368
368
369
369
370
370371
371372
372373
register const char *s = nptr;
register unsigned long long acc;
register int c;
register unsigned long long qbase, cutoff;
/* register */ unsigned long long qbase, cutoff;
register int neg, any, cutlim;
extern unsigned int i386_unsigned_div(unsigned long long*, unsigned int);
/*
* See strtoq for comments as to the logic used.
}
qbase = (unsigned)base;
cutoff = (unsigned long long)UQUAD_MAX / qbase;
cutlim = (unsigned long long)UQUAD_MAX % qbase;
cutoff = (unsigned long long)UQUAD_MAX;
cutlim = (int) i386_unsigned_div(&cutoff, (unsigned int) base);
for (acc = 0, any = 0;; c = *s++)
{

Archive Download the corresponding diff file

Revision: 2822