Blame libdjvu/MMX.cpp

Packit df99a1
//C-  -*- C++ -*-
Packit df99a1
//C- -------------------------------------------------------------------
Packit df99a1
//C- DjVuLibre-3.5
Packit df99a1
//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
Packit df99a1
//C- Copyright (c) 2001  AT&T
Packit df99a1
//C-
Packit df99a1
//C- This software is subject to, and may be distributed under, the
Packit df99a1
//C- GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- or (at your option) any later version. The license should have
Packit df99a1
//C- accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C-
Packit df99a1
//C- This program is distributed in the hope that it will be useful,
Packit df99a1
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit df99a1
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit df99a1
//C- GNU General Public License for more details.
Packit df99a1
//C- 
Packit df99a1
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
Packit df99a1
//C- Lizardtech Software.  Lizardtech Software has authorized us to
Packit df99a1
//C- replace the original DjVu(r) Reference Library notice by the following
Packit df99a1
//C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
Packit df99a1
//C-
Packit df99a1
//C-  ------------------------------------------------------------------
Packit df99a1
//C- | DjVu (r) Reference Library (v. 3.5)
Packit df99a1
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
Packit df99a1
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
Packit df99a1
//C- | 6,058,214 and patents pending.
Packit df99a1
//C- |
Packit df99a1
//C- | This software is subject to, and may be distributed under, the
Packit df99a1
//C- | GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- | or (at your option) any later version. The license should have
Packit df99a1
//C- | accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- | from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C- |
Packit df99a1
//C- | The computer code originally released by LizardTech under this
Packit df99a1
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
Packit df99a1
//C- | ORIGINAL CODE."  Subject to any third party intellectual property
Packit df99a1
//C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
Packit df99a1
//C- | non-exclusive license to make, use, sell, or otherwise dispose of 
Packit df99a1
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
Packit df99a1
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
Packit df99a1
//C- | General Public License.   This grant only confers the right to 
Packit df99a1
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
Packit df99a1
//C- | the extent such infringement is reasonably necessary to enable 
Packit df99a1
//C- | recipient to make, have made, practice, sell, or otherwise dispose 
Packit df99a1
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
Packit df99a1
//C- | any greater extent that may be necessary to utilize further 
Packit df99a1
//C- | modifications or combinations.
Packit df99a1
//C- |
Packit df99a1
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
Packit df99a1
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
Packit df99a1
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
Packit df99a1
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Packit df99a1
//C- +------------------------------------------------------------------
Packit df99a1
Packit df99a1
#ifdef HAVE_CONFIG_H
Packit df99a1
# include "config.h"
Packit df99a1
#endif
Packit df99a1
#if NEED_GNUG_PRAGMAS
Packit df99a1
# pragma implementation
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#include "MMX.h"
Packit df99a1
#include <stdio.h>
Packit df99a1
#include <stddef.h>
Packit df99a1
#include <stdlib.h>
Packit df99a1
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
namespace DJVU {
Packit df99a1
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
Packit df99a1
}
Packit df99a1
#endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
Packit df99a1
// ----------------------------------------
Packit df99a1
// PRINTING MMX REGISTERS (Debug)
Packit df99a1
Packit df99a1
Packit df99a1
#if defined(MMX) && defined(DEBUG)
Packit df99a1
extern "C" void
Packit df99a1
mmx_show()
Packit df99a1
{
Packit df99a1
  /* This function can be called from a debugger
Packit df99a1
     in order to visualize the contents of the MMX registers. */
Packit df99a1
  int mmregs[16];
Packit df99a1
  MMXra( movq,  mm0, &mmregs[0]);
Packit df99a1
  MMXra( movq,  mm1, &mmregs[2]);
Packit df99a1
  MMXra( movq,  mm2, &mmregs[4]);
Packit df99a1
  MMXra( movq,  mm3, &mmregs[6]);
Packit df99a1
  MMXra( movq,  mm4, &mmregs[8]);
Packit df99a1
  MMXra( movq,  mm5, &mmregs[10]);
Packit df99a1
  MMXra( movq,  mm6, &mmregs[12]);
Packit df99a1
  MMXra( movq,  mm7, &mmregs[14]);
Packit df99a1
  MMXemms;
Packit df99a1
  for (int i=0; i<8; i++)
Packit df99a1
    DjVuPrintMessageUTF8("mm%d: %08x%08x\n", i, 
Packit df99a1
           mmregs[i+i+1], mmregs[i+i]);
Packit df99a1
  MMXar( movq,  &mmregs[0], mm0);
Packit df99a1
  MMXar( movq,  &mmregs[2], mm1);
Packit df99a1
  MMXar( movq,  &mmregs[4], mm2);
Packit df99a1
  MMXar( movq,  &mmregs[6], mm3);
Packit df99a1
  MMXar( movq,  &mmregs[8], mm4);
Packit df99a1
  MMXar( movq,  &mmregs[10], mm5);
Packit df99a1
  MMXar( movq,  &mmregs[12], mm6);
Packit df99a1
  MMXar( movq,  &mmregs[14], mm7);
Packit df99a1
}
Packit df99a1
#endif
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// ----------------------------------------
Packit df99a1
// MMX ENABLE/DISABLE
Packit df99a1
Packit df99a1
// Default settings autodetect MMX.
Packit df99a1
// Use macro DISABLE_MMX to disable MMX by default.
Packit df99a1
Packit df99a1
#if defined(MMX) && !defined(DISABLE_MMX)
Packit df99a1
int MMXControl::mmxflag = -1;
Packit df99a1
#else
Packit df99a1
int MMXControl::mmxflag = 0;
Packit df99a1
#endif
Packit df99a1
Packit df99a1
int 
Packit df99a1
MMXControl::disable_mmx()
Packit df99a1
{
Packit df99a1
  mmxflag = 0;
Packit df99a1
  return mmxflag;
Packit df99a1
}
Packit df99a1
Packit df99a1
int 
Packit df99a1
MMXControl::enable_mmx()
Packit df99a1
{
Packit df99a1
  int cpuflags = 0;
Packit df99a1
  const char *envvar = getenv("LIBDJVU_DISABLE_MMX");
Packit df99a1
  if (envvar && envvar[0] && envvar[0]!='0')
Packit df99a1
    return ((mmxflag = 0));
Packit df99a1
  
Packit df99a1
#if defined(MMX) && defined(__GNUC__) && defined(__i386__)
Packit df99a1
  // Detection of MMX for GCC
Packit df99a1
  __asm__ volatile ("pushl %%ebx\n\t"
Packit df99a1
                    "pushfl\n\t"    
Packit df99a1
                    "popl %%ecx\n\t"
Packit df99a1
                    "xorl %%edx,%%edx\n\t"
Packit df99a1
                    // Check that CPUID exists
Packit df99a1
                    "movl %%ecx,%%eax\n\t"
Packit df99a1
                    "xorl $0x200000,%%eax\n\t"
Packit df99a1
                    "pushl %%eax\n\t"
Packit df99a1
                    "popfl\n\t"
Packit df99a1
                    "pushfl\n\t"
Packit df99a1
                    "popl %%eax\n\t"
Packit df99a1
                    "xorl %%ecx,%%eax\n\t"
Packit df99a1
                    "jz 1f\n\t"
Packit df99a1
                    "pushl %%ecx\n\t"
Packit df99a1
                    "popfl\n\t"
Packit df99a1
                    // Check that CR0:EM is clear
Packit df99a1
                    "smsw %%ax\n\t"
Packit df99a1
                    "andl $4,%%eax\n\t"
Packit df99a1
                    "jnz 1f\n\t"
Packit df99a1
                    // Execute CPUID
Packit df99a1
                    "movl $1,%%eax\n\t"
Packit df99a1
                    "cpuid\n"
Packit df99a1
                    // EBX contains magic when -fPIC is on.
Packit df99a1
		    "1:\tpopl %%ebx\n\t"
Packit df99a1
                    "movl %%edx, %0"
Packit df99a1
                    : "=m" (cpuflags) :
Packit df99a1
                    : "eax","ecx","edx");
Packit df99a1
#endif
Packit df99a1
#if defined(MMX) && defined(__GNUC__) && defined(__x86_64__)
Packit df99a1
  // Detection of MMX for GCC
Packit df99a1
  __asm__ volatile (// Check that CR0:EM is clear
Packit df99a1
                    "xorl %%edx,%%edx\n\t"
Packit df99a1
                    "smsw %%ax\n\t"
Packit df99a1
                    "andl $4,%%eax\n\t"
Packit df99a1
                    "jnz 1f\n\t"
Packit df99a1
                    // Execute CPUID
Packit df99a1
                    "movl $1,%%eax\n\t"
Packit df99a1
                    "cpuid\n"
Packit df99a1
                    // Finish
Packit df99a1
		    "1:\tmovl %%edx, %0"
Packit df99a1
                    : "=m" (cpuflags) :
Packit df99a1
                    : "eax","ebx","ecx","edx");
Packit df99a1
#endif
Packit df99a1
#if defined(MMX) && defined(_MSC_VER) && defined(_M_IX86)
Packit df99a1
  // Detection of MMX for MSVC 32 bits
Packit df99a1
  __asm {  pushfd
Packit df99a1
           pop     ecx
Packit df99a1
           xor     edx,edx
Packit df99a1
             ;// Check that CPUID exists
Packit df99a1
           mov     eax,ecx        
Packit df99a1
           xor     eax,0x200000
Packit df99a1
           push    eax
Packit df99a1
           popfd
Packit df99a1
           pushfd
Packit df99a1
           pop     eax
Packit df99a1
           xor     eax,ecx
Packit df99a1
           jz      fini
Packit df99a1
           push    ecx
Packit df99a1
           popfd
Packit df99a1
             ;// Check that CR0:EM is zero
Packit df99a1
           smsw    ax
Packit df99a1
           and     eax,4
Packit df99a1
           jnz     fini
Packit df99a1
             ;// Execute CPUID
Packit df99a1
           mov     eax,1
Packit df99a1
           _emit   0xf
Packit df99a1
           _emit   0xa2
Packit df99a1
         fini:
Packit df99a1
           mov     cpuflags,edx
Packit df99a1
             ;// MSVC determines clobbered registers by scanning the assembly code.
Packit df99a1
             ;// Since it does not know CPUID, it would not know that EBX is clobbered
Packit df99a1
             ;// without the dummy instruction below...
Packit df99a1
           xor     ebx,ebx
Packit df99a1
         }
Packit df99a1
#endif
Packit df99a1
  mmxflag = !!(cpuflags & 0x800000);
Packit df99a1
  return mmxflag;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
}
Packit df99a1
# ifndef NOT_USING_DJVU_NAMESPACE
Packit df99a1
using namespace DJVU;
Packit df99a1
# endif
Packit df99a1
#endif