ObjFW  Diff

Differences From Artifact [2e4f49497d]:

To Artifact [df1cd50578]:


43
44
45
46
47
48
49

50
51
52

53
54
55
56

57
58
59
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
88

89
90
91
92
93
94
95
#ifdef __HAIKU__
# include <FindDirectory.h>
#endif
#ifdef __QNX__
# include <sys/syspage.h>
#endif


struct cpuid_regs {
	uint32_t eax, ebx, ecx, edx;
};


static size_t pageSize;
static size_t numberOfCPUs;


static OF_INLINE struct cpuid_regs OF_CONST_FUNC
cpuid(uint32_t eax, uint32_t ecx)
{
	struct cpuid_regs regs;

#if defined(OF_X86_64_ASM)
	__asm__(
	    "cpuid"
	    : "=a"(regs.eax), "=b"(regs.ebx), "=c"(regs.ecx), "=d"(regs.edx)
	    : "a"(eax), "c"(ecx)
	);



#elif defined(OF_X86_ASM)





	/*
	 * This workaround is required by GCC when using -fPIC, as ebx is a
	 * special register in PIC code. Yes, GCC is indeed not able to just
	 * push a register onto the stack before the __asm__ block and to pop
	 * it afterwards.
	 */
	__asm__(
	    "pushl	%%ebx\n\t"
	    "cpuid\n\t"
	    "movl	%%ebx, %1\n\t"
	    "popl	%%ebx"
	    : "=a"(regs.eax), "=r"(regs.ebx), "=c"(regs.ecx), "=d"(regs.edx)
	    : "a"(eax), "c"(ecx)
	);
#else
	regs.eax = regs.ebx = regs.ecx = regs.edx = 0;
#endif

	return regs;
}


@implementation OFSystemInfo
+ (void)initialize
{
	if (self != [OFSystemInfo class])
		return;








>
|


>




>
|
|

|

<





>
>
>

>
>
>
>
>














<
<
<



>







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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
88
89
90
91
92



93
94
95
96
97
98
99
100
101
102
103
#ifdef __HAIKU__
# include <FindDirectory.h>
#endif
#ifdef __QNX__
# include <sys/syspage.h>
#endif

#if defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
struct x86_regs {
	uint32_t eax, ebx, ecx, edx;
};
#endif

static size_t pageSize;
static size_t numberOfCPUs;

#if defined(OF_X86_64_ASM)
static OF_INLINE struct x86_regs OF_CONST_FUNC
x86_cpuid(uint32_t eax, uint32_t ecx)
{
	struct x86_regs regs;


	__asm__(
	    "cpuid"
	    : "=a"(regs.eax), "=b"(regs.ebx), "=c"(regs.ecx), "=d"(regs.edx)
	    : "a"(eax), "c"(ecx)
	);

	return regs;
}
#elif defined(OF_X86_ASM)
static OF_INLINE struct x86_regs OF_CONST_FUNC
x86_cpuid(uint32_t eax, uint32_t ecx)
{
	struct x86_regs regs;

	/*
	 * This workaround is required by GCC when using -fPIC, as ebx is a
	 * special register in PIC code. Yes, GCC is indeed not able to just
	 * push a register onto the stack before the __asm__ block and to pop
	 * it afterwards.
	 */
	__asm__(
	    "pushl	%%ebx\n\t"
	    "cpuid\n\t"
	    "movl	%%ebx, %1\n\t"
	    "popl	%%ebx"
	    : "=a"(regs.eax), "=r"(regs.ebx), "=c"(regs.ecx), "=d"(regs.edx)
	    : "a"(eax), "c"(ecx)
	);




	return regs;
}
#endif

@implementation OFSystemInfo
+ (void)initialize
{
	if (self != [OFSystemInfo class])
		return;

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
359

360
	objc_autoreleasePoolPop(pool);
	return [var autorelease];
#endif
}

+ (OFString*)CPUVendor
{

	struct cpuid_regs regs = cpuid(0, 0);
	char buffer[12];

	if (regs.eax == 0)
		return nil;

	memcpy(buffer, &regs.ebx, 4);
	memcpy(buffer + 4, &regs.edx, 4);
	memcpy(buffer + 8, &regs.ecx, 4);

	return [OFString stringWithCString: buffer
				  encoding: OF_STRING_ENCODING_ASCII
				    length: 12];



}


+ (bool)supportsMMX
{
	return (cpuid(1, 0).edx & (1 << 23));
}

+ (bool)supportsSSE
{
	return (cpuid(1, 0).edx & (1 << 25));
}

+ (bool)supportsSSE2
{
	return (cpuid(1, 0).edx & (1 << 26));
}

+ (bool)supportsSSE3
{
	return (cpuid(1, 0).ecx & (1 << 0));
}

+ (bool)supportsSSSE3
{
	return (cpuid(1, 0).ecx & (1 << 9));
}

+ (bool)supportsSSE41
{
	return (cpuid(1, 0).ecx & (1 << 19));
}

+ (bool)supportsSSE42
{
	return (cpuid(1, 0).ecx & (1 << 20));
}

+ (bool)supportsAVX
{
	return (cpuid(1, 0).ecx & (1 << 28));
}

+ (bool)supportsAVX2
{
	return cpuid(0, 0).eax >= 7 && (cpuid(7, 0).ebx & (1 << 5));
}

@end







>
|












>
>
>


>


|




|




|




|




|




|




|




|




|

>

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
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
	objc_autoreleasePoolPop(pool);
	return [var autorelease];
#endif
}

+ (OFString*)CPUVendor
{
#if defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
	struct x86_regs regs = x86_cpuid(0, 0);
	char buffer[12];

	if (regs.eax == 0)
		return nil;

	memcpy(buffer, &regs.ebx, 4);
	memcpy(buffer + 4, &regs.edx, 4);
	memcpy(buffer + 8, &regs.ecx, 4);

	return [OFString stringWithCString: buffer
				  encoding: OF_STRING_ENCODING_ASCII
				    length: 12];
#else
	return nil;
#endif
}

#if defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
+ (bool)supportsMMX
{
	return (x86_cpuid(1, 0).edx & (1 << 23));
}

+ (bool)supportsSSE
{
	return (x86_cpuid(1, 0).edx & (1 << 25));
}

+ (bool)supportsSSE2
{
	return (x86_cpuid(1, 0).edx & (1 << 26));
}

+ (bool)supportsSSE3
{
	return (x86_cpuid(1, 0).ecx & (1 << 0));
}

+ (bool)supportsSSSE3
{
	return (x86_cpuid(1, 0).ecx & (1 << 9));
}

+ (bool)supportsSSE41
{
	return (x86_cpuid(1, 0).ecx & (1 << 19));
}

+ (bool)supportsSSE42
{
	return (x86_cpuid(1, 0).ecx & (1 << 20));
}

+ (bool)supportsAVX
{
	return (x86_cpuid(1, 0).ecx & (1 << 28));
}

+ (bool)supportsAVX2
{
	return x86_cpuid(0, 0).eax >= 7 && (x86_cpuid(7, 0).ebx & (1 << 5));
}
#endif
@end