ObjFW  Check-in [1dbc2e0c76]

Overview
Comment:Provide MMX/SSE/AVX check methods only on x86(_64)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 1dbc2e0c76a6e8a5aad47afb0248844405374d2f0a6e847b600b7a5a7ab65a32
User & Date: js on 2015-10-17 12:01:06
Other Links: manifest | tags
Context
2015-10-17
12:17
Fix two forgotten instances of FD_SETSIZE on Win32 check-in: 3a9dbf5fee user: js tags: trunk
12:01
Provide MMX/SSE/AVX check methods only on x86(_64) check-in: 1dbc2e0c76 user: js tags: trunk
10:59
Add a port registry for the Wii check-in: ed4549ddd3 user: js tags: trunk
Changes

Modified src/OFSystemInfo.h from [579d6e7617] to [b1b706eed5].

82
83
84
85
86
87
88

89
90


91
92
93
94
95
96
97
98




99
100
101
102
103
104
105




106
107
108
109
110
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
139




140
141
142
143
144
145
146
147




148
149
150

151
152
153
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
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
179
180
181
182
183
184
185
186
187
188
189







+


+
+








+
+
+
+







+
+
+
+






+
+
+
+








+
+
+
+






+
+
+
+








+
+
+
+






+
+
+
+








+
+
+
+



+



 *
 * If the vendor could not be determined, nil is returned instead.
 *
 * @return The vendor of the CPU
 */
+ (nullable OFString*)CPUVendor;

#if defined(OF_X86_64_ASM) || defined(OF_X86_ASM) || defined(DOXYGEN)
/*!
 * @brief Returns whether the CPU supports MMX.
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports MMX
 */
+ (bool)supportsMMX;

/*!
 * @brief Returns whether the CPU supports SSE.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports SSE
 */
+ (bool)supportsSSE;

/*!
 * @brief Returns whether the CPU supports SSE2.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports SSE2
 */
+ (bool)supportsSSE2;

/*!
 * @brief Returns whether the CPU supports SSE3.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports SSE3
 */
+ (bool)supportsSSE3;

/*!
 * @brief Returns whether the CPU supports SSSE3.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports SSSE3
 */
+ (bool)supportsSSSE3;

/*!
 * @brief Returns whether the CPU supports SSE4.1.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports SSE4.1
 */
+ (bool)supportsSSE41;

/*!
 * @brief Returns whether the CPU supports SSE4.2.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports SSE4.2
 */
+ (bool)supportsSSE42;

/*!
 * @brief Returns whether the CPU supports AVX.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports AVX
 */
+ (bool)supportsAVX;

/*!
 * @brief Returns whether the CPU supports AVX2.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports AVX2
 */
+ (bool)supportsAVX2;
#endif
@end

OF_ASSUME_NONNULL_END

Modified src/OFSystemInfo.m from [2e4f49497d] to [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
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 cpuid_regs {
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 cpuid_regs OF_CONST_FUNC
cpuid(uint32_t eax, uint32_t ecx)
static OF_INLINE struct x86_regs OF_CONST_FUNC
x86_cpuid(uint32_t eax, uint32_t ecx)
{
	struct cpuid_regs regs;
	struct x86_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)
	);

	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)
	);
#else
	regs.eax = regs.ebx = regs.ecx = regs.edx = 0;
#endif

	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
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 cpuid_regs regs = cpuid(0, 0);
	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 (cpuid(1, 0).edx & (1 << 23));
	return (x86_cpuid(1, 0).edx & (1 << 23));
}

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

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

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

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

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

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

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

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