SyterKit 0.4.0.x
SyterKit is a bare-metal framework
Loading...
Searching...
No Matches
ruapu.h
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2024 nihui (https://github.com/nihui)
3// Copyright (c) 2024 kernelbin (https://github.com/kernelbin)
4//
5// ruapu --- detect cpu isa features with single-file
6
7#ifndef RUAPU_H
8#define RUAPU_H
9
10#ifdef __cplusplus
11extern "C" {
12#endif
13
15
16int ruapu_supports(const char *isa);
17
18const char *const *ruapu_rua();
19
20#ifdef RUAPU_IMPLEMENTATION
21
22#ifndef RUAPU_BAREMETAL
23#include <setjmp.h>
24#include <string.h>
25#endif// RUAPU_BAREMETAL
26
27#if defined _WIN32
28
29#include <windows.h>
30
31#if WINAPI_FAMILY == WINAPI_FAMILY_APP
32// uwp does not support veh :(
33#if defined(_MSC_VER)
34#pragma message("warning: ruapu does not support UWP yet.")
35#else
36#warning ruapu does not support UWP yet.
37#endif
38static int ruapu_detect_isa(const void *some_inst) {
39 (void) some_inst;
40 return 0;
41}
42#else // WINAPI_FAMILY == WINAPI_FAMILY_APP
43static int g_ruapu_sigill_caught = 0;
44static jmp_buf g_ruapu_jmpbuf;
45
46typedef const void *ruapu_some_inst;
47
48static LONG CALLBACK ruapu_catch_sigill(struct _EXCEPTION_POINTERS *ExceptionInfo) {
49 if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION) {
50 g_ruapu_sigill_caught = 1;
51 longjmp(g_ruapu_jmpbuf, -1);
52 }
53
54 return EXCEPTION_CONTINUE_SEARCH;
55}
56
57static int ruapu_detect_isa(const void *some_inst) {
58 g_ruapu_sigill_caught = 0;
59
60 PVOID eh = AddVectoredExceptionHandler(1, ruapu_catch_sigill);
61
62 if (setjmp(g_ruapu_jmpbuf) == 0) {
63 ((void (*)()) some_inst)();
64 }
65
66 RemoveVectoredExceptionHandler(eh);
67
68 return g_ruapu_sigill_caught ? 0 : 1;
69}
70#endif// WINAPI_FAMILY == WINAPI_FAMILY_APP
71
72#elif defined __ANDROID__ || defined __linux__ || defined __APPLE__ || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__
73#include <signal.h>
74
75static int g_ruapu_sigill_caught = 0;
76static sigjmp_buf g_ruapu_jmpbuf;
77
78typedef void (*ruapu_some_inst)();
79
80static void ruapu_catch_sigill(int signo, siginfo_t *si, void *data) {
81 (void) signo;
82 (void) si;
83 (void) data;
84
85 g_ruapu_sigill_caught = 1;
86 siglongjmp(g_ruapu_jmpbuf, -1);
87}
88
89static int ruapu_detect_isa(ruapu_some_inst some_inst) {
90 g_ruapu_sigill_caught = 0;
91
92 struct sigaction sa = {0};
93 struct sigaction old_sa;
94 sa.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
95 sa.sa_sigaction = ruapu_catch_sigill;
96 sigaction(SIGILL, &sa, &old_sa);
97
98 if (sigsetjmp(g_ruapu_jmpbuf, 1) == 0) {
99 some_inst();
100 }
101
102 sigaction(SIGILL, &old_sa, NULL);
103
104 return g_ruapu_sigill_caught ? 0 : 1;
105}
106
107#elif defined __SYTERKIT__// defined _WIN32 || defined __ANDROID__ || defined __linux__ || defined __APPLE__ || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__
108
109typedef void (*ruapu_some_inst)();
110#include <mmu.h>
111
112static int g_ruapu_sigill_caught = 0;
113
114void arm32_do_undefined_instruction(struct arm_regs_t *regs) {
115 g_ruapu_sigill_caught = 1;
116 regs->pc += 4;
117}
118
119static int ruapu_detect_isa(ruapu_some_inst some_inst) {
120 some_inst();
121 if (g_ruapu_sigill_caught) {
122 g_ruapu_sigill_caught = 0;
123 return 0;
124 } else {
125 return 1;
126 }
127}
128
129#endif// __SYTERKIT__
130
131#if defined _WIN32
132
133#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
134#ifdef _MSC_VER
135#define RUAPU_INSTCODE(isa, ...) __pragma(section(".text")) __declspec(allocate(".text")) static unsigned char ruapu_some_##isa[] = {__VA_ARGS__, 0xc3};
136#else
137#define RUAPU_INSTCODE(isa, ...) __attribute__((section(".text"))) static unsigned char ruapu_some_##isa[] = {__VA_ARGS__, 0xc3};
138#endif
139
140#elif __aarch64__ || defined(_M_ARM64)
141#ifdef _MSC_VER
142#define RUAPU_INSTCODE(isa, ...) __pragma(section(".text")) __declspec(allocate(".text")) static unsigned int ruapu_some_##isa[] = {__VA_ARGS__, 0xd65f03c0};
143#else
144#define RUAPU_INSTCODE(isa, ...) __attribute__((section(".text"))) static unsigned int ruapu_some_##isa[] = {__VA_ARGS__, 0xd65f03c0};
145#endif
146
147#elif __arm__ || defined(_M_ARM)
148#if __thumb__
149#ifdef _MSC_VER
150#define RUAPU_INSTCODE(isa, ...) __pragma(section(".text")) __declspec(allocate(".text")) static unsigned int ruapu_some_##isa[] = {__VA_ARGS__, 0x4770};
151#else
152#define RUAPU_INSTCODE(isa, ...) __attribute__((section(".text"))) static unsigned int ruapu_some_##isa[] = {__VA_ARGS__, 0x4770};
153#endif
154#else
155#ifdef _MSC_VER
156#define RUAPU_INSTCODE(isa, ...) __pragma(section(".text")) __declspec(allocate(".text")) static unsigned int ruapu_some_##isa[] = {__VA_ARGS__, 0xe12fff1e};
157#else
158#define RUAPU_INSTCODE(isa, ...) __attribute__((section(".text"))) static unsigned int ruapu_some_##isa[] = {__VA_ARGS__, 0xe12fff1e};
159#endif
160#endif
161
162#endif
163
164#else// defined _WIN32
165
166#if defined(__i386__) || defined(__x86_64__) || __s390x__
167#define RUAPU_INSTCODE(isa, ...) \
168 static void ruapu_some_##isa() { \
169 asm volatile(".byte " #__VA_ARGS__ \
170 : \
171 : \
172 :); \
173 }
174#elif __aarch64__ || __arm__ || __mips__ || __riscv || __loongarch__
175#define RUAPU_INSTCODE(isa, ...) \
176 static void ruapu_some_##isa() { \
177 asm volatile(".word " #__VA_ARGS__ \
178 : \
179 : \
180 :); \
181 }
182#elif __powerpc__
183#define RUAPU_INSTCODE(isa, ...) \
184 static void ruapu_some_##isa() { \
185 asm volatile(".long " #__VA_ARGS__ \
186 : \
187 : \
188 :); \
189 }
190#endif
191
192#endif// defined _WIN32
193
194#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
195RUAPU_INSTCODE(mmx, 0x0f, 0xdb, 0xc0) // pand mm0,mm0
196RUAPU_INSTCODE(sse, 0x0f, 0x54, 0xc0) // andps xmm0,xmm0
197RUAPU_INSTCODE(sse2, 0x66, 0x0f, 0xfe, 0xc0) // paddd xmm0,xmm0
198RUAPU_INSTCODE(sse3, 0xf2, 0x0f, 0x7c, 0xc0) // haddps xmm0,xmm0
199RUAPU_INSTCODE(ssse3, 0x66, 0x0f, 0x38, 0x06, 0xc0) // phsubd xmm0,xmm0
200RUAPU_INSTCODE(sse41, 0x66, 0x0f, 0x38, 0x3d, 0xc0) // pmaxsd xmm0,xmm0
201RUAPU_INSTCODE(sse42, 0x66, 0x0f, 0x38, 0x37, 0xc0) // pcmpgtq xmm0,xmm0
202RUAPU_INSTCODE(sse4a, 0x66, 0x0f, 0x79, 0xc0) // extrq xmm0,xmm0
203RUAPU_INSTCODE(xop, 0x8f, 0xe8, 0x78, 0xb6, 0xc0, 0x00) // vpmadcswd xmm0,xmm0,xmm0,xmm0
204RUAPU_INSTCODE(avx, 0xc5, 0xfc, 0x54, 0xc0) // vandps ymm0,ymm0,ymm0
205RUAPU_INSTCODE(f16c, 0xc4, 0xe2, 0x7d, 0x13, 0xc0) // vcvtph2ps ymm0,xmm0
206RUAPU_INSTCODE(fma, 0xc4, 0xe2, 0x7d, 0x98, 0xc0) // vfmadd132ps ymm0,ymm0,ymm0
207RUAPU_INSTCODE(fma4, 0xc4, 0xe3, 0xfd, 0x68, 0xc0, 0x00) // vfmaddps ymm0,ymm0,ymm0,ymm0
208RUAPU_INSTCODE(avx2, 0xc5, 0xfd, 0xfe, 0xc0) // vpaddd ymm0,ymm0,ymm0
209RUAPU_INSTCODE(avx512f, 0x62, 0xf1, 0x7c, 0x48, 0x58, 0xc0) // vaddps zmm0,zmm0,zmm0
210RUAPU_INSTCODE(avx512bw, 0x62, 0xf1, 0x7d, 0x48, 0xfd, 0xc0) // vpaddw zmm0,zmm0,zmm0
211RUAPU_INSTCODE(avx512cd, 0x62, 0xf2, 0xfd, 0x48, 0x44, 0xc0) // vplzcntq zmm0,zmm0
212RUAPU_INSTCODE(avx512dq, 0x62, 0xf1, 0x7c, 0x48, 0x54, 0xc0) // vandps zmm0,zmm0,zmm0
213RUAPU_INSTCODE(avx512vl, 0x62, 0xf2, 0xfd, 0x28, 0x1f, 0xc0) // vpabsq ymm0,ymm0
214RUAPU_INSTCODE(avx512vnni, 0x62, 0xf2, 0x7d, 0x48, 0x52, 0xc0) // vpdpwssd zmm0,zmm0,zmm0
215RUAPU_INSTCODE(avx512bf16, 0x62, 0xf2, 0x7e, 0x48, 0x52, 0xc0) // vdpbf16ps zmm0,zmm0,zmm0
216RUAPU_INSTCODE(avx512ifma, 0x62, 0xf2, 0xfd, 0x48, 0xb4, 0xc0) // vpmadd52luq zmm0,zmm0,zmm0
217RUAPU_INSTCODE(avx512vbmi, 0x62, 0xf2, 0x7d, 0x48, 0x75, 0xc0) // vpermi2b zmm0,zmm0,zmm0
218RUAPU_INSTCODE(avx512vbmi2, 0x62, 0xf2, 0x7d, 0x48, 0x71, 0xc0)// vpshldvd zmm0,zmm0,zmm0
219RUAPU_INSTCODE(avx512fp16, 0x62, 0xf6, 0x7d, 0x48, 0x98, 0xc0) // vfmadd132ph zmm0,zmm0,zmm0
220RUAPU_INSTCODE(avxvnni, 0xc4, 0xe2, 0x7d, 0x52, 0xc0) // vpdpwssd ymm0,ymm0,ymm0
221RUAPU_INSTCODE(avxvnniint8, 0xc4, 0xe2, 0x7f, 0x50, 0xc0) // vpdpbssd ymm0,ymm0,ymm0
222RUAPU_INSTCODE(avxifma, 0xc4, 0xe2, 0xfd, 0xb4, 0xc0) // vpmadd52luq ymm0,ymm0,ymm0
223
224#elif __aarch64__ || defined(_M_ARM64)
225RUAPU_INSTCODE(neon, 0x4e20d400) // fadd v0.4s,v0.4s,v0.4s
226RUAPU_INSTCODE(vfpv4, 0x1f000000) // fmadd s0,s0,s0,s0
227RUAPU_INSTCODE(cpuid, 0xd5380000) // mrs x0,midr_el1
228RUAPU_INSTCODE(asimdrdm, 0x6e808400)// sqrdmlah v0.4s,v0.4s,v0.4s
229RUAPU_INSTCODE(asimdhp, 0x0e401400) // fadd v0.4h,v0.4h,v0.4h
230RUAPU_INSTCODE(asimddp, 0x4e809400) // sdot v0.4h,v0.16b,v0.16b
231RUAPU_INSTCODE(asimdfhm, 0x4e20ec00)// fmlal v0.4s,v0.4h,v0.4h
232RUAPU_INSTCODE(bf16, 0x6e40ec00) // bfmmla v0.4h,v0.8h,v0.8h
233RUAPU_INSTCODE(i8mm, 0x4e80a400) // smmla v0.4h,v0.16b,v0.16b
234RUAPU_INSTCODE(mte, 0xd96003e0) // ldg x0,[sp]
235RUAPU_INSTCODE(sve, 0x65608000) // fmad z0.h,p0/m,z0.h,z0.h
236RUAPU_INSTCODE(sve2, 0x44405000) // smlslb z0.h,z0.b,z0.b
237RUAPU_INSTCODE(svebf16, 0x6460e400) // bfmmla z0.s,z0.h,z0.h
238RUAPU_INSTCODE(svei8mm, 0x45009800) // smmla z0.s,z0.b,z0.b
239RUAPU_INSTCODE(svef32mm, 0x64a0e400)// fmmla z0.s,z0.s,z0.s
240RUAPU_INSTCODE(pmull, 0x0e20e000) // pmull v0.8h,v0.8b,v0.8b
241RUAPU_INSTCODE(crc32, 0x1ac04000) // crc32b w0,w0,w0
242RUAPU_INSTCODE(aes, 0x4e285800) // aesd v0.16b,v0.16b
243RUAPU_INSTCODE(sha1, 0x5e280800) // sha1h s0,s0
244RUAPU_INSTCODE(sha2, 0x5e004000) // sha256h q0,q0,v0.4s
245RUAPU_INSTCODE(sha3, 0xce000000) // eor3 v0.16b, v0.16b, v0.16b, v0.16b
246RUAPU_INSTCODE(sha512, 0xce608000) // sha512h q0, q0, v0.2d
247RUAPU_INSTCODE(sm3, 0xce60c000) // sm3partw1 v0.4s, v0.4s, v0.4s
248RUAPU_INSTCODE(sm4, 0xcec08400) // sm4e v0.4s, v0.4s
249RUAPU_INSTCODE(amx, 0x00201220) // amx setup
250
251
252#elif __arm__ || defined(_M_ARM)
253#if __thumb__
254RUAPU_INSTCODE(edsp, 0xfb20, 0x0000) // smlad r0,r0,r0,r0
255RUAPU_INSTCODE(neon, 0xef00, 0x0d40) // vadd.f32 q0,q0,q0
256RUAPU_INSTCODE(vfpv4, 0xeea0, 0x0a00) // vfma.f32 s0,s0,s0
257RUAPU_INSTCODE(idiv, 0x2003, 0xfb90, 0xf0f0)// movs r0,#3 + sdiv r0,r0,r0
258#else
259RUAPU_INSTCODE(edsp, 0xe7000010) // smlad r0,r0,r0,r0
260RUAPU_INSTCODE(neon, 0xf2000d40) // vadd.f32 q0,q0,q0
261RUAPU_INSTCODE(vfpv4, 0xeea00a00) // vfma.f32 s0,s0,s0
262RUAPU_INSTCODE(idiv, 0xe3a00003, 0xe710f010)// movs r0,#3 + sdiv r0,r0,r0
263#endif
264
265#elif __mips__
266RUAPU_INSTCODE(msa, 0x7900001b)// fmadd.w $w0,$w0,$w0
267
268#elif __powerpc__
269RUAPU_INSTCODE(vsx, 0x104210c0)// vaddudm v2,v2,v2
270
271#elif __s390x__
272RUAPU_INSTCODE(zvector, 0xe7, 0x00, 0x02, 0x00, 0x00, 0x8f)// vfmasb v0,v0,v0,v0
273
274#elif __loongarch__
275RUAPU_INSTCODE(lsx, 0x700b0000) //vadd.w vr0, vr0, vr0
276RUAPU_INSTCODE(lasx, 0x740b0000)//xvadd.w xr0, xr0, xr0
277
278#elif __riscv
279RUAPU_INSTCODE(i, 0x00a50533) // add a0,a0,a0
280RUAPU_INSTCODE(m, 0x00200513, 0x02a50533, 0x02a54533)// addi a0,x0,2 mul a0,a0,a0 div a0,a0,a0
281RUAPU_INSTCODE(a, 0x100122af, 0x185122af) // lr.w t0,(sp) + sc.w t0,t0,(sp)
282RUAPU_INSTCODE(f, 0x10a57553) // fmul.s fa0,fa0,fa0
283RUAPU_INSTCODE(d, 0x12a57553) // fmul.d fa0,fa0,fa0
284RUAPU_INSTCODE(c, 0x0001952a) // add a0,a0,a0 + nop
285RUAPU_INSTCODE(zfa, 0xf0108053) // fli.s ft0, min
286RUAPU_INSTCODE(zfh, 0x04007053); // fadd.hs ft0, ft0, ft0
287RUAPU_INSTCODE(zfhmin, 0xe4000553) // fmv.x.h a0, ft0
288RUAPU_INSTCODE(zicsr, 0xc0102573); // csrr a0, time
289RUAPU_INSTCODE(zifencei, 0x0000100f); // fence.i
290RUAPU_INSTCODE(zmmul, 0x02a50533) // mul a0,a0,a0
291
292#endif
293
294#undef RUAPU_INSTCODE
295
296struct ruapu_isa_entry {
297 const char *isa;
298 ruapu_some_inst inst;
299};
300
301#define RUAPU_ISAENTRY(isa) {#isa, (ruapu_some_inst) ruapu_some_##isa},
302
303struct ruapu_isa_entry g_ruapu_isa_map[] = {
304
305#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
306 RUAPU_ISAENTRY(mmx) RUAPU_ISAENTRY(sse) RUAPU_ISAENTRY(sse2) RUAPU_ISAENTRY(sse3) RUAPU_ISAENTRY(ssse3) RUAPU_ISAENTRY(sse41) RUAPU_ISAENTRY(sse42) RUAPU_ISAENTRY(sse4a)
307 RUAPU_ISAENTRY(xop) RUAPU_ISAENTRY(avx) RUAPU_ISAENTRY(f16c) RUAPU_ISAENTRY(fma) RUAPU_ISAENTRY(fma4) RUAPU_ISAENTRY(avx2) RUAPU_ISAENTRY(avx512f)
308 RUAPU_ISAENTRY(avx512bw) RUAPU_ISAENTRY(avx512cd) RUAPU_ISAENTRY(avx512dq) RUAPU_ISAENTRY(avx512vl) RUAPU_ISAENTRY(avx512vnni) RUAPU_ISAENTRY(avx512bf16)
309 RUAPU_ISAENTRY(avx512ifma) RUAPU_ISAENTRY(avx512vbmi) RUAPU_ISAENTRY(avx512vbmi2) RUAPU_ISAENTRY(avx512fp16) RUAPU_ISAENTRY(avxvnni)
310 RUAPU_ISAENTRY(avxvnniint8) RUAPU_ISAENTRY(avxifma)
311
312#elif __aarch64__ || defined(_M_ARM64)
313 RUAPU_ISAENTRY(neon) RUAPU_ISAENTRY(vfpv4) RUAPU_ISAENTRY(cpuid) RUAPU_ISAENTRY(asimdrdm) RUAPU_ISAENTRY(asimdhp) RUAPU_ISAENTRY(asimddp) RUAPU_ISAENTRY(asimdfhm)
314 RUAPU_ISAENTRY(bf16) RUAPU_ISAENTRY(i8mm) RUAPU_ISAENTRY(mte) RUAPU_ISAENTRY(sve) RUAPU_ISAENTRY(sve2) RUAPU_ISAENTRY(svebf16) RUAPU_ISAENTRY(svei8mm)
315 RUAPU_ISAENTRY(svef32mm) RUAPU_ISAENTRY(pmull) RUAPU_ISAENTRY(crc32) RUAPU_ISAENTRY(aes) RUAPU_ISAENTRY(sha1) RUAPU_ISAENTRY(sha2) RUAPU_ISAENTRY(sha3)
316 RUAPU_ISAENTRY(sha512) RUAPU_ISAENTRY(sm3) RUAPU_ISAENTRY(sm4) RUAPU_ISAENTRY(amx)
317
318#elif __arm__ || defined(_M_ARM)
319 RUAPU_ISAENTRY(edsp) RUAPU_ISAENTRY(neon) RUAPU_ISAENTRY(vfpv4) RUAPU_ISAENTRY(idiv)
320
321#elif __mips__
322 RUAPU_ISAENTRY(msa)
323
324#elif __powerpc__
325 RUAPU_ISAENTRY(vsx)
326
327#elif __s390x__
328 RUAPU_ISAENTRY(zvector)
329
330#elif __loongarch__
331 RUAPU_ISAENTRY(lsx) RUAPU_ISAENTRY(lasx)
332
333#elif __riscv
334 RUAPU_ISAENTRY(i) RUAPU_ISAENTRY(m) RUAPU_ISAENTRY(a) RUAPU_ISAENTRY(f) RUAPU_ISAENTRY(d) RUAPU_ISAENTRY(c) RUAPU_ISAENTRY(zfa) RUAPU_ISAENTRY(zfh) RUAPU_ISAENTRY(zfhmin)
335 RUAPU_ISAENTRY(zicsr) RUAPU_ISAENTRY(zifencei) RUAPU_ISAENTRY(zmmul)
336
337#elif __openrisc__
338 RUAPU_ISAENTRY(orbis32) RUAPU_ISAENTRY(orbis64) RUAPU_ISAENTRY(orfpx32) RUAPU_ISAENTRY(orfpx64) RUAPU_ISAENTRY(orvdx64)
339
340#endif
341};
342
343#undef RUAPU_ISAENTRY
344
345const char *g_ruapu_isa_supported[sizeof(g_ruapu_isa_map) / sizeof(g_ruapu_isa_map[0]) + 1] = {0};
346
347#if defined __openrisc__
348static void ruapu_detect_openrisc_isa() {
350 uint16_t addr = U(0x0000);
351 asm volatile("l.mfspr %0, r0, %1"
352 : "=r"(value)
353 : "K"(addr));
354 size_t j = 0;
355 for (size_t i = 0; i < sizeof(g_ruapu_isa_map) / sizeof(g_ruapu_isa_map[0]); i++) {
356 int capable = ((value) >> (5 + i)) & 0x1;
357 if (capable) {
358 g_ruapu_isa_supported[j] = g_ruapu_isa_map[i].isa;
359 j++;
360 }
361 }
362 g_ruapu_isa_supported[j] = 0;
363}
364#endif
365
366void ruapu_init() {
367#if defined _WIN32 || defined __ANDROID__ || defined __linux__ || defined __APPLE__ || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __SYTERKIT__
368 size_t j = 0;
369 for (size_t i = 0; i < sizeof(g_ruapu_isa_map) / sizeof(g_ruapu_isa_map[0]); i++) {
370 int capable = ruapu_detect_isa(g_ruapu_isa_map[i].inst);
371 if (capable) {
372 g_ruapu_isa_supported[j] = g_ruapu_isa_map[i].isa;
373 j++;
374 }
375 }
376 g_ruapu_isa_supported[j] = 0;
377#elif defined __openrisc__
378 ruapu_detect_openrisc_isa();
379#else
380 // initialize g_ruapu_isa_map for baremetal here, default all zero
381 // there is still ruapu_some_XYZ() functions available
382 // but you have to work out your own signal handling
383#warning ruapu does not support your baremetal os yet
384#endif
385}
386
387int ruapu_supports(const char *isa) {
388 const char *const *isa_supported = g_ruapu_isa_supported;
389 while (*isa_supported) {
390 if (strcmp(*isa_supported, isa) == 0)
391 return 1;
392
393 isa_supported++;
394 }
395
396 return 0;
397}
398
399const char *const *ruapu_rua() {
400 return g_ruapu_isa_supported;
401}
402
403#endif// RUAPU_IMPLEMENTATION
404
405#ifdef __cplusplus
406}
407#endif
408
409#endif// RUAPU_H
#define NULL
Definition stddef.h:7
u32_t uint32_t
Definition stdint.h:13
u16_t uint16_t
Definition stdint.h:10
static uint8_t value
Definition io.h:144
int strcmp(const char *p1, const char *p2) __attribute__((optimize("O0")))
Compares the string pointed to by 'p1' to the string pointed to by 'p2'.
Definition string.c:46
const char *const * ruapu_rua()
void ruapu_init()
int ruapu_supports(const char *isa)
#define LONG
Default largest int is long.
Definition xformat.c:36
ARM32 register structure.
Definition mmu.h:28
uint32_t pc
Program counter (R15)
Definition mmu.h:34