1;
2; jsimdcpu.asm - SIMD instruction support check
3;
4; Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
5; Copyright (C) 2016, D. R. Commander.
6;
7; Based on the x86 SIMD extension for IJG JPEG library
8; Copyright (C) 1999-2006, MIYASAKA Masaru.
9; For conditions of distribution and use, see copyright notice in jsimdext.inc
10;
11; This file should be assembled with NASM (Netwide Assembler),
12; can *not* be assembled with Microsoft's MASM or any compatible
13; assembler (including Borland's Turbo Assembler).
14; NASM is available from http://nasm.sourceforge.net/ or
15; http://sourceforge.net/project/showfiles.php?group_id=6208
16
17%include "jsimdext.inc"
18
19; --------------------------------------------------------------------------
20    SECTION     SEG_TEXT
21    BITS        32
22;
23; Check if the CPU supports SIMD instructions
24;
25; GLOBAL(unsigned int)
26; jpeg_simd_cpu_support(void)
27;
28
29    align       32
30    GLOBAL_FUNCTION(jpeg_simd_cpu_support)
31
32EXTN(jpeg_simd_cpu_support):
33    push        ebx
34;   push        ecx                     ; need not be preserved
35;   push        edx                     ; need not be preserved
36;   push        esi                     ; unused
37    push        edi
38
39    xor         edi, edi                ; simd support flag
40
41    pushfd
42    pop         eax
43    mov         edx, eax
44    xor         eax, 1<<21              ; flip ID bit in EFLAGS
45    push        eax
46    popfd
47    pushfd
48    pop         eax
49    xor         eax, edx
50    jz          near .return            ; CPUID is not supported
51
52    ; Check whether CPUID leaf 07H is supported
53    ; (leaf 07H is used to check for AVX2 instruction support)
54    xor         eax, eax
55    cpuid
56    test        eax, eax
57    jz          near .return
58    cmp         eax, 7
59    jl          short .no_avx2          ; Maximum leaf < 07H
60
61    ; Check for AVX2 instruction support
62    mov         eax, 7
63    xor         ecx, ecx
64    cpuid
65    mov         eax, ebx
66    test        eax, 1<<5               ; bit5:AVX2
67    jz          short .no_avx2
68
69    ; Check for AVX2 O/S support
70    mov         eax, 1
71    xor         ecx, ecx
72    cpuid
73    test        ecx, 1<<27
74    jz          short .no_avx2          ; O/S does not support XSAVE
75    test        ecx, 1<<28
76    jz          short .no_avx2          ; CPU does not support AVX2
77
78    xor         ecx, ecx
79    xgetbv
80    and         eax, 6
81    cmp         eax, 6                  ; O/S does not manage XMM/YMM state
82                                        ; using XSAVE
83    jnz         short .no_avx2
84
85    or          edi, JSIMD_AVX2
86.no_avx2:
87
88    ; Check CPUID leaf 01H for MMX, SSE, and SSE2 support
89    xor         eax, eax
90    inc         eax
91    cpuid
92    mov         eax, edx                ; eax = Standard feature flags
93
94    ; Check for MMX instruction support
95    test        eax, 1<<23              ; bit23:MMX
96    jz          short .no_mmx
97    or          edi, byte JSIMD_MMX
98.no_mmx:
99    test        eax, 1<<25              ; bit25:SSE
100    jz          short .no_sse
101    or          edi, byte JSIMD_SSE
102.no_sse:
103    test        eax, 1<<26              ; bit26:SSE2
104    jz          short .no_sse2
105    or          edi, byte JSIMD_SSE2
106.no_sse2:
107
108    ; Check for 3DNow! instruction support
109    mov         eax, 0x80000000
110    cpuid
111    cmp         eax, 0x80000000
112    jbe         short .return
113
114    mov         eax, 0x80000001
115    cpuid
116    mov         eax, edx                ; eax = Extended feature flags
117
118    test        eax, 1<<31              ; bit31:3DNow!(vendor independent)
119    jz          short .no_3dnow
120    or          edi, byte JSIMD_3DNOW
121.no_3dnow:
122
123.return:
124    mov         eax, edi
125
126    pop         edi
127;   pop         esi                     ; unused
128;   pop         edx                     ; need not be preserved
129;   pop         ecx                     ; need not be preserved
130    pop         ebx
131    ret
132
133; For some reason, the OS X linker does not honor the request to align the
134; segment unless we do this.
135    align       32
136