According to Intel's manual [1], "If a value entered for CPUID.EAX is higher than the maximum input value for basic or extended function for that processor then the data for the highest basic information leaf is returned." Right now, libjpeg-turbo doesn't first check that leaf 07H is supported before attempting to use it, so the ostensible AVX2 bit (Bit 05) of the CPUID result might actually be Bit 05 from a lower leaf. That bit might be set, even if the CPU doesn't support AVX2. This commit modifies the x86 and x86-64 SIMD feature detection code so that it first checks whether CPUID leaf 07H is supported before attempting to use it to check for AVX2 instruction support. DRC: This commit should fix https://bugzilla.mozilla.org/show_bug.cgi?id=1520760 However, I have not personally been able to reproduce that issue, despite using a Nehalem (pre-AVX2) CPU on which the maximum CPUID leaf has been limited via a BIOS setting. Closes #348 [1] "Intel® 64 and IA-32 Architectures Software Developer's Manual, Volume 2 (2A, 2B, 2C & 2D): Instruction Set Reference, A-Z", https://software.intel.com/sites/default/files/managed/a4/60/325383-sdm-vol-2abcd.pdf, page 3-192.
138 lines
3.9 KiB
NASM
138 lines
3.9 KiB
NASM
;
|
|
; jsimdcpu.asm - SIMD instruction support check
|
|
;
|
|
; Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
|
|
; Copyright (C) 2016, D. R. Commander.
|
|
;
|
|
; Based on the x86 SIMD extension for IJG JPEG library
|
|
; Copyright (C) 1999-2006, MIYASAKA Masaru.
|
|
; For conditions of distribution and use, see copyright notice in jsimdext.inc
|
|
;
|
|
; This file should be assembled with NASM (Netwide Assembler),
|
|
; can *not* be assembled with Microsoft's MASM or any compatible
|
|
; assembler (including Borland's Turbo Assembler).
|
|
; NASM is available from http://nasm.sourceforge.net/ or
|
|
; http://sourceforge.net/project/showfiles.php?group_id=6208
|
|
;
|
|
; [TAB8]
|
|
|
|
%include "jsimdext.inc"
|
|
|
|
; --------------------------------------------------------------------------
|
|
SECTION SEG_TEXT
|
|
BITS 32
|
|
;
|
|
; Check if the CPU supports SIMD instructions
|
|
;
|
|
; GLOBAL(unsigned int)
|
|
; jpeg_simd_cpu_support(void)
|
|
;
|
|
|
|
align 32
|
|
GLOBAL_FUNCTION(jpeg_simd_cpu_support)
|
|
|
|
EXTN(jpeg_simd_cpu_support):
|
|
push ebx
|
|
; push ecx ; need not be preserved
|
|
; push edx ; need not be preserved
|
|
; push esi ; unused
|
|
push edi
|
|
|
|
xor edi, edi ; simd support flag
|
|
|
|
pushfd
|
|
pop eax
|
|
mov edx, eax
|
|
xor eax, 1<<21 ; flip ID bit in EFLAGS
|
|
push eax
|
|
popfd
|
|
pushfd
|
|
pop eax
|
|
xor eax, edx
|
|
jz near .return ; CPUID is not supported
|
|
|
|
; Check whether CPUID leaf 07H is supported
|
|
; (leaf 07H is used to check for AVX2 instruction support)
|
|
xor eax, eax
|
|
cpuid
|
|
test eax, eax
|
|
jz near .return
|
|
cmp eax, 7
|
|
jl short .no_avx2 ; Maximum leaf < 07H
|
|
|
|
; Check for AVX2 instruction support
|
|
mov eax, 7
|
|
xor ecx, ecx
|
|
cpuid
|
|
mov eax, ebx
|
|
test eax, 1<<5 ; bit5:AVX2
|
|
jz short .no_avx2
|
|
|
|
; Check for AVX2 O/S support
|
|
mov eax, 1
|
|
xor ecx, ecx
|
|
cpuid
|
|
test ecx, 1<<27
|
|
jz short .no_avx2 ; O/S does not support XSAVE
|
|
test ecx, 1<<28
|
|
jz short .no_avx2 ; CPU does not support AVX2
|
|
|
|
xor ecx, ecx
|
|
xgetbv
|
|
and eax, 6
|
|
cmp eax, 6 ; O/S does not manage XMM/YMM state
|
|
; using XSAVE
|
|
jnz short .no_avx2
|
|
|
|
or edi, JSIMD_AVX2
|
|
.no_avx2:
|
|
|
|
; Check CPUID leaf 01H for MMX, SSE, and SSE2 support
|
|
xor eax, eax
|
|
inc eax
|
|
cpuid
|
|
mov eax, edx ; eax = Standard feature flags
|
|
|
|
; Check for MMX instruction support
|
|
test eax, 1<<23 ; bit23:MMX
|
|
jz short .no_mmx
|
|
or edi, byte JSIMD_MMX
|
|
.no_mmx:
|
|
test eax, 1<<25 ; bit25:SSE
|
|
jz short .no_sse
|
|
or edi, byte JSIMD_SSE
|
|
.no_sse:
|
|
test eax, 1<<26 ; bit26:SSE2
|
|
jz short .no_sse2
|
|
or edi, byte JSIMD_SSE2
|
|
.no_sse2:
|
|
|
|
; Check for 3DNow! instruction support
|
|
mov eax, 0x80000000
|
|
cpuid
|
|
cmp eax, 0x80000000
|
|
jbe short .return
|
|
|
|
mov eax, 0x80000001
|
|
cpuid
|
|
mov eax, edx ; eax = Extended feature flags
|
|
|
|
test eax, 1<<31 ; bit31:3DNow!(vendor independent)
|
|
jz short .no_3dnow
|
|
or edi, byte JSIMD_3DNOW
|
|
.no_3dnow:
|
|
|
|
.return:
|
|
mov eax, edi
|
|
|
|
pop edi
|
|
; pop esi ; unused
|
|
; pop edx ; need not be preserved
|
|
; pop ecx ; need not be preserved
|
|
pop ebx
|
|
ret
|
|
|
|
; For some reason, the OS X linker does not honor the request to align the
|
|
; segment unless we do this.
|
|
align 32
|