Merge pull request #21 from weltling/cpuid

[RFC] cpu: Add framework for CPU feature handling
This commit is contained in:
Dmitry Stogov 2023-04-17 10:35:29 +03:00 committed by GitHub
commit d26099c5ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 86 additions and 2 deletions

View File

@ -41,7 +41,8 @@ endif
OBJS_COMMON = $(BUILD_DIR)/ir.o $(BUILD_DIR)/ir_strtab.o $(BUILD_DIR)/ir_cfg.o \ OBJS_COMMON = $(BUILD_DIR)/ir.o $(BUILD_DIR)/ir_strtab.o $(BUILD_DIR)/ir_cfg.o \
$(BUILD_DIR)/ir_sccp.o $(BUILD_DIR)/ir_gcm.o $(BUILD_DIR)/ir_ra.o $(BUILD_DIR)/ir_emit.o \ $(BUILD_DIR)/ir_sccp.o $(BUILD_DIR)/ir_gcm.o $(BUILD_DIR)/ir_ra.o $(BUILD_DIR)/ir_emit.o \
$(BUILD_DIR)/ir_load.o $(BUILD_DIR)/ir_save.o $(BUILD_DIR)/ir_emit_c.o $(BUILD_DIR)/ir_dump.o \ $(BUILD_DIR)/ir_load.o $(BUILD_DIR)/ir_save.o $(BUILD_DIR)/ir_emit_c.o $(BUILD_DIR)/ir_dump.o \
$(BUILD_DIR)/ir_disasm.o $(BUILD_DIR)/ir_gdb.o $(BUILD_DIR)/ir_perf.o $(BUILD_DIR)/ir_check.o $(BUILD_DIR)/ir_disasm.o $(BUILD_DIR)/ir_gdb.o $(BUILD_DIR)/ir_perf.o $(BUILD_DIR)/ir_check.o \
$(BUILD_DIR)/ir_cpuinfo.o
OBJS_IR = $(BUILD_DIR)/ir_main.o OBJS_IR = $(BUILD_DIR)/ir_main.o
OBJS_IR_TEST = $(BUILD_DIR)/ir_test.o OBJS_IR_TEST = $(BUILD_DIR)/ir_test.o

2
ir.h
View File

@ -768,6 +768,8 @@ int ir_mem_protect(void *ptr, size_t size);
int ir_mem_unprotect(void *ptr, size_t size); int ir_mem_unprotect(void *ptr, size_t size);
int ir_mem_flush(void *ptr, size_t size); int ir_mem_flush(void *ptr, size_t size);
uint32_t ir_cpuinfo(void);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif

61
ir_cpuinfo.c Normal file
View File

@ -0,0 +1,61 @@
/*
* IR - Lightweight JIT Compilation Framework
* (CPU framework for x86)
* Copyright (C) 2023 by IR project.
* Authors: Anatol Belski <anbelski@linux.microsoft.com>
*/
#include "ir.h"
#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
#include "ir_x86.h"
#ifndef _WIN32
IR_ALWAYS_INLINE void ir_cpuid_ex(uint32_t info[4], uint32_t function, uint32_t index)
{
asm volatile("cpuid"
: "=a" (info[0]),
"=b" (info[1]),
"=c" (info[2]),
"=d" (info[3])
: "0" (function), "2" (index)
: "memory");
}
IR_ALWAYS_INLINE void ir_cpuid(uint32_t info[4], uint32_t function)
{
ir_cpuid_ex(info, function, 0);
}
#else
#define ir_cpuid_ex __cpuidex
#define ir_cpuid __cpuid
#endif
/* Intel SDM Vol. 2A */
uint32_t ir_cpuinfo(void)
{
uint32_t ret = 0;
uint32_t info_0x1[4] = {0}, info_0x7_0[4] = {0};
#define bit(mask, pos) (((mask) >> (pos)) & 1U)
ir_cpuid(info_0x1, 0x1);
if (bit(info_0x1[3], 26U)) ret |= IR_X86_SSE2;
if (bit(info_0x1[2], 0U)) ret |= IR_X86_SSE3;
if (bit(info_0x1[2], 9U)) ret |= IR_X86_SSSE3;
if (bit(info_0x1[2], 19U)) ret |= IR_X86_SSE41;
if (bit(info_0x1[2], 20U)) ret |= IR_X86_SSE42;
if (bit(info_0x1[2], 28U)) ret |= IR_X86_AVX;
ir_cpuid_ex(info_0x7_0, 0x7, 0);
if (bit(info_0x7_0[1], 5U)) ret |= IR_X86_AVX2;
#undef bit
return ret;
}
#else
uint32_t ir_cpuinfo(void)
{
return 0;
}
#endif /* IR_TARGET_X86 || IR_TARGET_X64 */

View File

@ -7,6 +7,9 @@
#include "ir.h" #include "ir.h"
#include "ir_builder.h" #include "ir_builder.h"
#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
# include "ir_x86.h"
#endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifndef _WIN32 #ifndef _WIN32
@ -94,6 +97,9 @@ int main(int argc, char **argv)
int opt_level = 2; int opt_level = 2;
uint32_t mflags = 0; uint32_t mflags = 0;
uint64_t debug_regset = 0xffffffffffffffff; uint64_t debug_regset = 0xffffffffffffffff;
#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
uint32_t cpuinfo = ir_cpuinfo();
#endif
ir_consistency_check(); ir_consistency_check();
@ -109,6 +115,12 @@ int main(int argc, char **argv)
/* pass */ /* pass */
} }
} else if (strcmp(argv[i], "-mavx") == 0) { } else if (strcmp(argv[i], "-mavx") == 0) {
#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
if (!(cpuinfo & IR_X86_AVX)) {
fprintf(stderr, "ERROR: CPU doesn't support AVX instruction set)\n");
return 1;
}
#endif
mflags |= IR_AVX; mflags |= IR_AVX;
} else if (strcmp(argv[i], "-muse-fp") == 0) { } else if (strcmp(argv[i], "-muse-fp") == 0) {
mflags |= IR_USE_FRAME_POINTER; mflags |= IR_USE_FRAME_POINTER;

View File

@ -221,4 +221,12 @@ struct _ir_target_constraints {
int8_t hints[IR_MAX_REG_ARGS + 3]; int8_t hints[IR_MAX_REG_ARGS + 3];
}; };
#define IR_X86_SSE2 (1<<0)
#define IR_X86_SSE3 (1<<1)
#define IR_X86_SSSE3 (1<<2)
#define IR_X86_SSE41 (1<<3)
#define IR_X86_SSE42 (1<<4)
#define IR_X86_AVX (1<<5)
#define IR_X86_AVX2 (1<<6)
#endif /* IR_X86_H */ #endif /* IR_X86_H */

View File

@ -65,7 +65,7 @@ LIBS=psapi.lib capstone.lib
OBJS_COMMON=$(BUILD_DIR)\ir.obj $(BUILD_DIR)\ir_strtab.obj $(BUILD_DIR)\ir_cfg.obj \ OBJS_COMMON=$(BUILD_DIR)\ir.obj $(BUILD_DIR)\ir_strtab.obj $(BUILD_DIR)\ir_cfg.obj \
$(BUILD_DIR)\ir_sccp.obj $(BUILD_DIR)\ir_gcm.obj $(BUILD_DIR)\ir_ra.obj $(BUILD_DIR)\ir_emit.obj \ $(BUILD_DIR)\ir_sccp.obj $(BUILD_DIR)\ir_gcm.obj $(BUILD_DIR)\ir_ra.obj $(BUILD_DIR)\ir_emit.obj \
$(BUILD_DIR)\ir_load.obj $(BUILD_DIR)\ir_save.obj $(BUILD_DIR)\ir_emit_c.obj $(BUILD_DIR)\ir_dump.obj \ $(BUILD_DIR)\ir_load.obj $(BUILD_DIR)\ir_save.obj $(BUILD_DIR)\ir_emit_c.obj $(BUILD_DIR)\ir_dump.obj \
$(BUILD_DIR)\ir_disasm.obj $(BUILD_DIR)\ir_check.obj $(BUILD_DIR)\ir_disasm.obj $(BUILD_DIR)\ir_check.obj $(BUILD_DIR)\ir_cpuinfo.obj
OBJS_IR = $(BUILD_DIR)\ir_main.obj OBJS_IR = $(BUILD_DIR)\ir_main.obj
OBJS_IR_TEST = $(BUILD_DIR)\ir_test.obj OBJS_IR_TEST = $(BUILD_DIR)\ir_test.obj