Chameleon

Chameleon Commit Details

Date:2016-06-15 22:15:23 (7 years 10 months ago)
Author:ErmaC
Commit:2825
Parents: 2824
Message:Merce latest Zenith432 improvements - Add unsigned, long and long long support to prf() - Add %%, %i, %p and %n support to prf() - Optimize prf(), eliminate use of 64-bit divisors in libsa - print (null) for null string - Add memcpy_interruptible() for smooth countdown()
Changes:
M/branches/ErmaC/Enoch/i386/libsa/prf.c
M/branches/ErmaC/Enoch/i386/libsa/strtol.c
M/branches/ErmaC/Enoch/i386/libsaio/biosfn.c
M/branches/ErmaC/Enoch/i386/boot2/drivers.c
M/branches/ErmaC/Enoch/i386/boot2/boot.c
M/branches/ErmaC/Enoch/i386/boot2/gui.c
M/branches/ErmaC/Enoch/i386/libsaio/cpu.c

File differences

branches/ErmaC/Enoch/i386/libsaio/cpu.c
251251
252252
253253
254
254
255255
256256
257257
......
272272
273273
274274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
275359
276360
277361
......
529613
530614
531615
616
617
618
532619
533620
534621
}
// Bronya C1E fix
void post_startup_cpu_fixups(void)
static void post_startup_cpu_fixups(void)
{
/*
* Some AMD processors support C1E state. Entering this state will
}
/*
* Large memcpy() into MMIO space can take longer than 1 clock tick (55ms).
* The timer interrupt must remain responsive when updating VRAM so
* as not to miss timer interrupts during countdown().
*
* If interrupts are enabled, use normal memcpy.
*
* If interrupts are disabled, breaks memcpy down
* into 128K chunks, times itself and makes a bios
* real-mode call every 25 msec in order to service
* pending interrupts.
*
* -- zenith432, May 22nd, 2016
*/
void* memcpy_interruptible(void* dst, const void* src, size_t len)
{
uint64_t tscFreq, lastTsc;
uint32_t eflags, threshold;
ptrdiff_t offset;
const size_t chunk = 131072U;// 128K
if (len <= chunk)
{
/*
* Short memcpy - use normal.
*/
return memcpy(dst, src, len);
}
__asm__ volatile("pushfl; popl %0" : "=r"(eflags));
if (eflags & 0x200U)
{
/*
* Interrupts are enabled - use normal memcpy.
*/
return memcpy(dst, src, len);
}
tscFreq = Platform.CPU.TSCFrequency;
if ((uint32_t) (tscFreq >> 32))
{
/*
* If TSC Frequency >= 2 ** 32, use a default time threshold.
*/
threshold = (~0U) / 40U;
}
else if (!(uint32_t) tscFreq)
{
/*
* If early on and TSC Frequency hasn't been estimated yet,
* use normal memcpy.
*/
return memcpy(dst, src, len);
}
else
{
threshold = ((uint32_t) tscFreq) / 40U;
}
/*
* Do the work
*/
offset = 0;
lastTsc = rdtsc64();
do
{
(void) memcpy((char*) dst + offset, (const char*) src + offset, chunk);
offset += (ptrdiff_t) chunk;
len -= chunk;
if ((rdtsc64() - lastTsc) < threshold)
{
continue;
}
(void) readKeyboardStatus();// visit real-mode
lastTsc = rdtsc64();
}
while (len > chunk);
if (len)
{
(void) memcpy((char*) dst + offset, (const char*) src + offset, len);
}
return dst;
}
/*
* Calculates the FSB and CPU frequencies using specific MSRs for each CPU
* - multi. is read from a specific MSR. In the case of Intel, there is:
* a max multi. (used to calculate the FSB freq.),
p->CPU.NoThreads= (uint32_t)bitfield((uint32_t)msr, 15, 0);
break;
case CPUID_MODEL_ATOM_3700:
p->CPU.NoCores= 4;
p->CPU.NoThreads= 4;
break;
case CPUID_MODEL_ATOM:
p->CPU.NoCores= 2;
p->CPU.NoThreads= 2;
branches/ErmaC/Enoch/i386/libsaio/biosfn.c
10781078
10791079
10801080
1081
10811082
10821083
bb.intno = 0x15;
bb.eax.rr = 0x2401;
bios(&bb);
// return !bb.flags.cf;
}
*/
branches/ErmaC/Enoch/i386/boot2/drivers.c
256256
257257
258258
259
259
260260
261261
262262
{
verbose("Attempting to loading drivers from standard repositories:\n");
if ( (gMacOSVersion[3] == '9') || ((gMacOSVersion[3] == '1') && ((gMacOSVersion[4] == '0') || gMacOSVersion[4] == '1' ) )) // issue 352
if ( (gMacOSVersion[3] == '9') || ((gMacOSVersion[3] == '1') && ((gMacOSVersion[4] == '0') || (gMacOSVersion[4] == '1') || (gMacOSVersion[4] == '2') ) )) // issue 352
{
verbose("\t- Third party extensions search path: /Library/Extensions\n");
strlcpy(gExtensionsSpec, dirSpec, 4087); /* 4096 - sizeof("Library/") mean 4096 - 9 = 4087 */
branches/ErmaC/Enoch/i386/boot2/boot.c
863863
864864
865865
866
866
867867
868868
869869
870870
871871
872
872873
873874
874875
// bootFile must start with a / if it not start with a device name
if (!bootFileWithDevice && (bootInfo->bootFile)[0] != '/')
{
if ( MacOSVerCurrent < MacOSVer2Int("10.10") ) // Micky1979 - Is prior to Yosemite 10.10
if ( MacOSVerCurrent < MacOSVer2Int("10.10") ) // Mavericks and older
{
snprintf(bootFile, sizeof(bootFile), "/%s", bootInfo->bootFile); // append a leading /
}
else
{
// Yosemite and newer
snprintf(bootFile, sizeof(bootFile), kDefaultKernelPathForYos"%s", bootInfo->bootFile); // Yosemite or El Capitan
}
}
branches/ErmaC/Enoch/i386/boot2/gui.c
13411341
13421342
13431343
1344
13441345
13451346
1346
1347
13471348
13481349
13491350
static inline void vramwrite (void *data, int width, int height)
{
extern void* memcpy_interruptible(void*, const void*, size_t);
if (VIDEO (depth) == 32 && VIDEO (rowBytes) == gui.backbuffer->width * 4)
{
memcpy((uint8_t *)vram, gui.backbuffer->pixels, VIDEO (rowBytes)*VIDEO (height));
memcpy_interruptible((uint8_t *)vram, gui.backbuffer->pixels, VIDEO (rowBytes)*VIDEO (height));
}
else
{
branches/ErmaC/Enoch/i386/libsa/prf.c
3838
3939
4040
41
41
4242
4343
4444
45
45
46
4647
4748
4849
......
5253
5354
5455
56
57
58
5559
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
5688
5789
5890
59
60
61
62
63
91
92
93
94
95
96
97
98
6499
65
100
66101
67102
103
68104
69
105
106
70107
71
108
72109
73110
74
75
76
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
77139
78
79
80
81
82
83140
84
85
86
141
142
143
144
145
146
147
87148
88
149
89150
151
90152
91153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
92179
93
94
95
180
181
182
96183
97
184
98185
99
100
101
186
187
188
102189
103190
104191
105
192
193
106194
107195
108196
......
110198
111199
112200
113
201
114202
115203
116204
117205
206
207
118208
119209
120
210
211
121212
213
214
215
216
122217
123218
124219
......
149244
150245
151246
247
248
249
250
152251
153252
154253
155254
156255
157
256
158257
159
258
259
260
261
262
263
264
265
266
160267
161
162268
163269
164
165
166
270
271
272
273
274
275
276
277
278
167279
168
280
169281
282
283
284
285
286
287
170288
171289
172290
173291
174292
175
176
177
178
293
179294
180295
181296
182297
183298
184299
185
300
186301
187302
188303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
189321
190322
191323
192
193324
194325
*@(#)prf.c7.1 (Berkeley) 6/5/86
*/
#include <sys/param.h>
#include <stdarg.h>
#define SPACE1
#define ZERO2
#define UCASE 16
#define UCASE16
#define SIGNED32
/*
* Scaled down version of C Library printf.
*
*/
#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.
*/
static void printn(n, b, flag, minwidth, putfn_p, putfn_arg)
u_long n;
int b, flag, minwidth;
void (*putfn_p)();
void *putfn_arg;
static int printn(
unsigned long long n,
int b,
int flag,
int minwidth,
int (*putfn_p)(),
void* putfn_arg
)
{
char prbuf[11];
char prbuf[22];
register char *cp;
int width = 0, neg = 0;
static const char hexdig[] = "0123456789abcdef0123456789ABCDEF";
if (b == 10 && (int)n < 0) {
if ((flag & SIGNED) && (long long)n < 0)
{
neg = 1;
n = (unsigned)(-(int)n);
n = (unsigned long long)(-(long long)n);
}
cp = prbuf;
do {
*cp++ = "0123456789abcdef0123456789ABCDEF"[(flag & UCASE) + n%b];
n /= b;
if ((b & -b) == b)// b is a power of 2
{
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);
}
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)
{
if (putfn_p)
{
(void)(*putfn_p)('-', putfn_arg);
}
width++;
} while (n);
if (neg) {
(*putfn_p)('-', putfn_arg);
width++;
}
while (width++ < minwidth)
(*putfn_p)( (flag & ZERO) ? '0' : ' ', putfn_arg);
if (!putfn_p)
{
return (width < minwidth) ? minwidth : width;
}
for (;width < minwidth; width++)
(void)(*putfn_p)( (flag & ZERO) ? '0' : ' ', putfn_arg);
do
(*putfn_p)(*--cp, putfn_arg);
(void)(*putfn_p)(*--cp, putfn_arg);
while (cp > prbuf);
return width;
}
/*
* Printp prints a pointer.
*/
static int printp(
const void* p,
int minwidth,
int (*putfn_p)(),
void* putfn_arg
)
{
int width = 0;
if (p)
{
if (putfn_p)
{
(void)(*putfn_p)('0', putfn_arg);
(void)(*putfn_p)('x', putfn_arg);
}
width = 2;
minwidth = ((minwidth >= 2) ? (minwidth - 2) : 0);
}
return width + printn((unsigned long long) p, 16, ZERO, minwidth, putfn_p, putfn_arg);
}
int prf(
char *fmt,
unsigned int *adx,
void (*putfn_p)(),
const char *fmt,
va_list ap,
int (*putfn_p)(),
void *putfn_arg
)
)
{
int b, c, len =0;
char *s;
int flag = 0, width = 0;
int b, c, len = 0;
const char *s;
int flag, width, ells;
int minwidth;
loop:
while ((c = *fmt++) != '%') {
while ((c = *fmt++) != '%')
{
if(c == '\0')
{
return len;
if (putfn_p)
{
(*putfn_p)(c, putfn_arg);
(void)(*putfn_p)(c, putfn_arg);
}
len++;
}
minwidth = 0;
flag = 0;
ells = 0;
again:
c = *fmt++;
switch (c) {
switch (c)
{
case 'l':
if (ells < 2)
{
++ells;
}
goto again;
case ' ':
flag |= SPACE;
b = 16;
goto number;
case 'd':
case 'i':
flag |= SIGNED;
/* fall through */
case 'u':
b = 10;
goto number;
case 'o': case 'O':
b = 8;
number:
if (putfn_p)
switch (ells)
{
printn((u_long)*adx, b, flag, minwidth, putfn_p, putfn_arg);
case 2:
len += printn(va_arg(ap, unsigned long long), b, flag, minwidth, putfn_p, putfn_arg);
break;
case 1:
len += printn(va_arg(ap, unsigned long), b, flag, minwidth, putfn_p, putfn_arg);
break;
default:
len += printn(va_arg(ap, unsigned int), b, flag, minwidth, putfn_p, putfn_arg);
break;
}
len++;
break;
case 's':
s = (char *)*adx;
while ((c = *s++)) {
if (putfn_p)
s = va_arg(ap, const char*);
if (!s)
{
s = "(null)";
}
width = 0;
if (!putfn_p)
{
while ((c = *s++))
{
(*putfn_p)(c, putfn_arg);
width++;
}
len += ((width < minwidth) ? minwidth : width);
break;
}
while ((c = *s++))
{
(void)(*putfn_p)(c, putfn_arg);
len++;
width++;
}
while (width++ < minwidth)
{
if (putfn_p)
{
(*putfn_p)(' ', putfn_arg);
}
(void)(*putfn_p)(' ', putfn_arg);
len++;
}
break;
case 'c':
if (putfn_p)
{
(*putfn_p)((char)*adx, putfn_arg);
(void)(*putfn_p)((char) va_arg(ap, int), putfn_arg);
}
len++;
break;
case '%':
if (putfn_p)
{
(void)(*putfn_p)('%', putfn_arg);
}
len++;
break;
case 'p':
len += printp(va_arg(ap, const void*), minwidth, putfn_p, putfn_arg);
break;
case 'n':
s = va_arg(ap, const char*);
if (s)
{
*(int*) s = len;
}
break;
default:
break;
}
adx++;
goto loop;
}
branches/ErmaC/Enoch/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: 2825