diff options
author | Oneric <oneric@oneric.stub> | 2022-03-15 23:00:05 +0100 |
---|---|---|
committer | Oneric <oneric@oneric.stub> | 2022-03-27 22:28:59 +0200 |
commit | 725da4729b99c98ee94ffe49a253650450a64f4d (patch) | |
tree | da00de4821a99ca1ab0c8ccbf902ff3c91f54dac | |
parent | 9608c8c838e1046601c27f6473e23654fedf1716 (diff) | |
download | libass-725da4729b99c98ee94ffe49a253650450a64f4d.tar.bz2 libass-725da4729b99c98ee94ffe49a253650450a64f4d.tar.xz |
asm/x86: check if cpuid is available before usage
The cpuid instruction was only introduced after i486, meaning
there are ix86 CPUs on which our default configuration will
build but crash during runtime when cpuid is executed.
To avoid this, check for the instructions availability by
testing if bit 21 of EFLAGS is writable as documented by
AMD, Cyrix, Intel and NexGen.
AMD, p.165:
https://www.amd.com/system/files/TechDocs/24594.pdf
Cyrix, p.10:
https://www.ardent-tool.com/CPU/docs/Cyrix/MII/94329_2.pdf
Intel, ch.3 p.190:
https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
NexGen:
https://www.ardent-tool.com/CPU/docs/NexGen/cpuid.pdf
-rw-r--r-- | libass/ass_utils.c | 3 | ||||
-rw-r--r-- | libass/x86/cpuid.asm | 24 | ||||
-rw-r--r-- | libass/x86/cpuid.h | 1 |
3 files changed, 28 insertions, 0 deletions
diff --git a/libass/ass_utils.c b/libass/ass_utils.c index 0acc891..a9db9be 100644 --- a/libass/ass_utils.c +++ b/libass/ass_utils.c @@ -40,6 +40,9 @@ void ass_cpu_capabilities(bool *sse2, bool *avx2) *sse2 = false; *avx2 = false; + if (!ass_has_cpuid()) + return; + uint32_t eax = 0, ebx, ecx, edx; ass_get_cpuid(&eax, &ebx, &ecx, &edx); uint32_t max_leaf = eax; diff --git a/libass/x86/cpuid.asm b/libass/x86/cpuid.asm index 09b3e77..b27d906 100644 --- a/libass/x86/cpuid.asm +++ b/libass/x86/cpuid.asm @@ -23,6 +23,30 @@ SECTION .text ;------------------------------------------------------------------------------ +; uint32_t has_cpuid( void ); +;------------------------------------------------------------------------------ + +INIT_XMM +cglobal has_cpuid, 0, 0, 0 +%if ARCH_X86_64 + mov eax, 1 +%else + pushfd + pop ecx + mov eax, ecx + xor eax, 0x00200000 + push eax + popfd + pushfd + pop eax + xor eax, ecx + and eax, 0x00200000 ; non-zero if bit is writable + push ecx ; Restore original EFLAGS + popfd +%endif + RET + +;------------------------------------------------------------------------------ ; void get_cpuid( uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); ;------------------------------------------------------------------------------ diff --git a/libass/x86/cpuid.h b/libass/x86/cpuid.h index ab50292..0218cde 100644 --- a/libass/x86/cpuid.h +++ b/libass/x86/cpuid.h @@ -21,6 +21,7 @@ #include <stdint.h> +uint32_t ass_has_cpuid( void ); void ass_get_cpuid( uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); void ass_get_xgetbv( uint32_t op, uint32_t *eax, uint32_t *edx ); |