; ; jsimddjg.asm - SIMD instruction support check (for DJGPP V.2) ; ; 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 ; ; Last Modified : September 26, 2004 ; ; [TAB8] %include "jsimdext.inc" ; -------------------------------------------------------------------------- SECTION SEG_TEXT BITS 32 ; ; Check if the OS supports SIMD instructions (DJGPP V.2) ; ; GLOBAL(unsigned int) ; jpeg_simd_os_support (unsigned int simd) ; %define EXCEPTION_ILLEGAL_INSTRUCTION 6 ; vector number of #UD %define simd ebp+8 ; unsigned int simd %define mxcsr ebp-4 ; unsigned int mxcsr = 0x1F80 align 16 global EXTN(jpeg_simd_os_support) EXTN(jpeg_simd_os_support): push ebp mov ebp,esp push dword 0x1F80 ; default value of MXCSR register push ebx push DWORD [simd] ; simd_flags - modified from exception_handler mov bl, EXCEPTION_ILLEGAL_INSTRUCTION mov ax, 0x0202 ; Get Processor Exception Handler Vector int 0x31 ; DPMI function call push ecx ; selector of old exception handler push edx ; offset of old exception handler mov ecx,cs mov edx, exception_handler mov bl, EXCEPTION_ILLEGAL_INSTRUCTION mov ax, 0x0203 ; Set Processor Exception Handler Vector int 0x31 ; DPMI function call mov eax, DWORD [simd] ; If floating point emulation is enabled (CR0.EM = 1), ; executing an MMX/3DNow! instruction generates invalid ; opcode exception (#UD). push byte (.mmx_1 - .mmx_0) ; inst_bytes push byte (JSIMD_MMX | JSIMD_3DNOW) ; test_flags test eax, DWORD [esp] jz short .mmx_1 .mmx_0: emms ; executing MMX instruction .mmx_1: add esp, byte 8 push byte (.sse_1 - .sse_0) push byte (JSIMD_SSE | JSIMD_SSE2) test eax, DWORD [esp] jz short .sse_1 .sse_0: ldmxcsr DWORD [mxcsr] ; executing SSE instruction .sse_1: add esp, byte 8 pop edx ; offset of old exception handler pop ecx ; selector of old exception handler mov bl, EXCEPTION_ILLEGAL_INSTRUCTION mov ax, 0x0203 ; Set Processor Exception Handler Vector int 0x31 ; DPMI function call pop eax ; return simd_flags and eax, byte JSIMD_ALL pop ebx mov esp,ebp pop ebp ret ; -------------------------------------------------------------------------- ; ; LOCAL(void) far ; exception_handler (unsigned long error_code, ; void * context_eip, unsigned short context_cs, ; unsigned long context_eflags, ; void * context_esp, unsigned short context_ss); ; %define error_code esp+12+8 ; unsigned long error_code %define context_eip esp+12+12 ; void * context_eip %define context_cs esp+12+16 ; unsigned short context_cs %define context_eflags esp+12+20 ; unsigned long context_eflags %define context_esp esp+12+24 ; void * context_esp %define context_ss esp+12+28 ; unsigned short context_ss %define test_flags(b) (b)+0 %define inst_bytes(b) (b)+4 %define simd_flags(b) (b)+16 align 16 exception_handler: push eax push ecx push edx mov eax, POINTER [context_esp] mov ecx, DWORD [test_flags(eax)] mov edx, DWORD [inst_bytes(eax)] not ecx add POINTER [context_eip], edx ; next instruction and DWORD [simd_flags(eax)], ecx ; turn off flag pop edx pop ecx pop eax retf