home *** CD-ROM | disk | FTP | other *** search
/ Geek 6 / Geek-006.iso / linux / video / xmovie-1.5.3.tar.gz / xmovie-1.5.3.tar / xmovie-1.5.3 / quicktime / mmx.h < prev    next >
C/C++ Source or Header  |  2000-11-29  |  23KB  |  727 lines

  1. /*    mmx.h
  2.  
  3.     MultiMedia eXtensions GCC interface library for IA32.
  4.  
  5.     To use this library, simply include this header file
  6.     and compile with GCC.  You MUST have inlining enabled
  7.     in order for mmx_ok() to work; this can be done by
  8.     simply using -O on the GCC command line.
  9.  
  10.     Compiling with -DMMX_TRACE will cause detailed trace
  11.     output to be sent to stderr for each mmx operation.
  12.     This adds lots of code, and obviously slows execution to
  13.     a crawl, but can be very useful for debugging.
  14.  
  15.     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
  16.     EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
  17.     LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  18.     AND FITNESS FOR ANY PARTICULAR PURPOSE.
  19.  
  20.     1997-98 by H. Dietz and R. Fisher
  21.  
  22.  History:
  23.     97-98*    R.Fisher    Early versions
  24.     980501    R.Fisher    Original Release
  25.     980611*    H.Dietz        Rewrite, correctly implementing inlines, and
  26.         R.Fisher     including direct register accesses.
  27.     980616    R.Fisher    Release of 980611 as 980616.
  28.     980714    R.Fisher    Minor corrections to Makefile, etc.
  29.     980715    R.Fisher    mmx_ok() now prevents optimizer from using
  30.                  clobbered values.
  31.                 mmx_ok() now checks if cpuid instruction is
  32.                  available before trying to use it.
  33.     980726*    R.Fisher    mm_support() searches for AMD 3DNow, Cyrix
  34.                  Extended MMX, and standard MMX.  It returns a
  35.                  value which is positive if any of these are
  36.                  supported, and can be masked with constants to
  37.                  see which.  mmx_ok() is now a call to this
  38.     980726*    R.Fisher    Added i2r support for shift functions
  39.     980919    R.Fisher    Fixed AMD extended feature recognition bug.
  40.     980921    R.Fisher    Added definition/check for _MMX_H.
  41.                 Added "float s[2]" to mmx_t for use with
  42.                   3DNow and EMMX.  So same mmx_t can be used.
  43.     981013    R.Fisher    Fixed cpuid function 1 bug (looked at wrong reg)
  44.                 Fixed psllq_i2r error in mmxtest.c
  45.  
  46.     * Unreleased (internal or interim) versions
  47.  
  48.  Notes:
  49.     It appears that the latest gas has the pand problem fixed, therefore
  50.       I'll undefine BROKEN_PAND by default.
  51.     String compares may be quicker than the multiple test/jumps in vendor
  52.       test sequence in mmx_ok(), but I'm not concerned with that right now.
  53.  
  54.  Acknowledgments:
  55.     Jussi Laako for pointing out the errors ultimately found to be
  56.       connected to the failure to notify the optimizer of clobbered values.
  57.     Roger Hardiman for reminding us that CPUID isn't everywhere, and that
  58.       someone may actually try to use this on a machine without CPUID.
  59.       Also for suggesting code for checking this.
  60.     Robert Dale for pointing out the AMD recognition bug.
  61.     Jimmy Mayfield and Carl Witty for pointing out the Intel recognition
  62.       bug.
  63.     Carl Witty for pointing out the psllq_i2r test bug.
  64. */
  65.  
  66. #ifndef _MMX_H
  67. #define _MMX_H
  68.  
  69. /*#define MMX_TRACE */
  70.  
  71. /*    Warning:  at this writing, the version of GAS packaged
  72.     with most Linux distributions does not handle the
  73.     parallel AND operation mnemonic correctly.  If the
  74.     symbol BROKEN_PAND is defined, a slower alternative
  75.     coding will be used.  If execution of mmxtest results
  76.     in an illegal instruction fault, define this symbol.
  77. */
  78. #undef    BROKEN_PAND
  79.  
  80.  
  81. /*    The type of an value that fits in an MMX register
  82.     (note that long long constant values MUST be suffixed
  83.      by LL and unsigned long long values by ULL, lest
  84.      they be truncated by the compiler)
  85. */
  86. typedef    union {
  87.     long long        q;    /* Quadword (64-bit) value */
  88.     unsigned long long    uq;    /* Unsigned Quadword */
  89.     int            d[2];    /* 2 Doubleword (32-bit) values */
  90.     unsigned int        ud[2];    /* 2 Unsigned Doubleword */
  91.     short            w[4];    /* 4 Word (16-bit) values */
  92.     unsigned short        uw[4];    /* 4 Unsigned Word */
  93.     char            b[8];    /* 8 Byte (8-bit) values */
  94.     unsigned char        ub[8];    /* 8 Unsigned Byte */
  95.     float            s[2];    /* Single-precision (32-bit) value */
  96. } mmx_t;
  97.  
  98.  
  99.  
  100. /*    Function to test if multimedia instructions are supported...
  101. */
  102. inline extern int
  103. mm_support(void)
  104. {
  105.     /* Returns 1 if MMX instructions are supported,
  106.        3 if Cyrix MMX and Extended MMX instructions are supported
  107.        5 if AMD MMX and 3DNow! instructions are supported
  108.        0 if hardware does not support any of these
  109.     */
  110.     register int rval = 0;
  111.  
  112.     __asm__ __volatile__ (
  113.         /* See if CPUID instruction is supported ... */
  114.         /* ... Get copies of EFLAGS into eax and ecx */
  115.         "pushf\n\t"
  116.         "popl %%eax\n\t"
  117.         "movl %%eax, %%ecx\n\t"
  118.  
  119.         /* ... Toggle the ID bit in one copy and store */
  120.         /*     to the EFLAGS reg */
  121.         "xorl $0x200000, %%eax\n\t"
  122.         "push %%eax\n\t"
  123.         "popf\n\t"
  124.  
  125.         /* ... Get the (hopefully modified) EFLAGS */
  126.         "pushf\n\t"
  127.         "popl %%eax\n\t"
  128.  
  129.         /* ... Compare and test result */
  130.         "xorl %%eax, %%ecx\n\t"
  131.         "testl $0x200000, %%ecx\n\t"
  132.         "jz NotSupported1\n\t"        /* Nothing supported */
  133.  
  134.  
  135.         /* Get standard CPUID information, and
  136.                go to a specific vendor section */
  137.         "movl $0, %%eax\n\t"
  138.         "cpuid\n\t"
  139.  
  140.         /* Check for Intel */
  141.         "cmpl $0x756e6547, %%ebx\n\t"
  142.         "jne TryAMD\n\t"
  143.         "cmpl $0x49656e69, %%edx\n\t"
  144.         "jne TryAMD\n\t"
  145.         "cmpl $0x6c65746e, %%ecx\n"
  146.         "jne TryAMD\n\t"
  147.         "jmp Intel\n\t"
  148.  
  149.         /* Check for AMD */
  150.         "\nTryAMD:\n\t"
  151.         "cmpl $0x68747541, %%ebx\n\t"
  152.         "jne TryCyrix\n\t"
  153.         "cmpl $0x69746e65, %%edx\n\t"
  154.         "jne TryCyrix\n\t"
  155.         "cmpl $0x444d4163, %%ecx\n"
  156.         "jne TryCyrix\n\t"
  157.         "jmp AMD\n\t"
  158.  
  159.         /* Check for Cyrix */
  160.         "\nTryCyrix:\n\t"
  161.         "cmpl $0x69727943, %%ebx\n\t"
  162.         "jne NotSupported2\n\t"
  163.         "cmpl $0x736e4978, %%edx\n\t"
  164.         "jne NotSupported3\n\t"
  165.         "cmpl $0x64616574, %%ecx\n\t"
  166.         "jne NotSupported4\n\t"
  167.         /* Drop through to Cyrix... */
  168.  
  169.  
  170.         /* Cyrix Section */
  171.         /* See if extended CPUID is supported */
  172.         "movl $0x80000000, %%eax\n\t"
  173.         "cpuid\n\t"
  174.         "cmpl $0x80000000, %%eax\n\t"
  175.         "jl MMXtest\n\t"    /* Try standard CPUID instead */
  176.  
  177.         /* Extended CPUID supported, so get extended features */
  178.         "movl $0x80000001, %%eax\n\t"
  179.         "cpuid\n\t"
  180.         "testl $0x00800000, %%eax\n\t"    /* Test for MMX */
  181.         "jz NotSupported5\n\t"        /* MMX not supported */
  182.         "testl $0x01000000, %%eax\n\t"    /* Test for Ext'd MMX */
  183.         "jnz EMMXSupported\n\t"
  184.         "movl $1, %0:\n\n\t"        /* MMX Supported */
  185.         "jmp Return\n\n"
  186.         "EMMXSupported:\n\t"
  187.         "movl $3, %0:\n\n\t"        /* EMMX and MMX Supported */
  188.         "jmp Return\n\t"
  189.  
  190.  
  191.         /* AMD Section */
  192.         "AMD:\n\t"
  193.  
  194.         /* See if extended CPUID is supported */
  195.         "movl $0x80000000, %%eax\n\t"
  196.         "cpuid\n\t"
  197.         "cmpl $0x80000000, %%eax\n\t"
  198.         "jl MMXtest\n\t"    /* Try standard CPUID instead */
  199.  
  200.         /* Extended CPUID supported, so get extended features */
  201.         "movl $0x80000001, %%eax\n\t"
  202.         "cpuid\n\t"
  203.         "testl $0x00800000, %%edx\n\t"    /* Test for MMX */
  204.         "jz NotSupported6\n\t"        /* MMX not supported */
  205.         "testl $0x80000000, %%edx\n\t"    /* Test for 3DNow! */
  206.         "jnz ThreeDNowSupported\n\t"
  207.         "movl $1, %0:\n\n\t"        /* MMX Supported */
  208.         "jmp Return\n\n"
  209.         "ThreeDNowSupported:\n\t"
  210.         "movl $5, %0:\n\n\t"        /* 3DNow! and MMX Supported */
  211.         "jmp Return\n\t"
  212.  
  213.  
  214.         /* Intel Section */
  215.         "Intel:\n\t"
  216.  
  217.         /* Check for MMX */
  218.         "MMXtest:\n\t"
  219.         "movl $1, %%eax\n\t"
  220.         "cpuid\n\t"
  221.         "testl $0x00800000, %%edx\n\t"    /* Test for MMX */
  222.         "jz NotSupported7\n\t"        /* MMX Not supported */
  223.         "movl $1, %0:\n\n\t"        /* MMX Supported */
  224.         "jmp Return\n\t"
  225.  
  226.         /* Nothing supported */
  227.         "\nNotSupported1:\n\t"
  228.         "#movl $101, %0:\n\n\t"
  229.         "\nNotSupported2:\n\t"
  230.         "#movl $102, %0:\n\n\t"
  231.         "\nNotSupported3:\n\t"
  232.         "#movl $103, %0:\n\n\t"
  233.         "\nNotSupported4:\n\t"
  234.         "#movl $104, %0:\n\n\t"
  235.         "\nNotSupported5:\n\t"
  236.         "#movl $105, %0:\n\n\t"
  237.         "\nNotSupported6:\n\t"
  238.         "#movl $106, %0:\n\n\t"
  239.         "\nNotSupported7:\n\t"
  240.         "#movl $107, %0:\n\n\t"
  241.         "movl $0, %0:\n\n\t"
  242.  
  243.         "Return:\n\t"
  244.         : "=a" (rval)
  245.         : /* no input */
  246.         : "eax", "ebx", "ecx", "edx"
  247.     );
  248.  
  249.     /* Return */
  250.     return(rval);
  251. }
  252.  
  253. /*    Function to test if mmx instructions are supported...
  254. */
  255. inline extern int
  256. mmx_ok(void)
  257. {
  258.     /* Returns 1 if MMX instructions are supported, 0 otherwise */
  259.     return ( mm_support() & 0x1 );
  260. }
  261.  
  262.  
  263. /*    Helper functions for the instruction macros that follow...
  264.     (note that memory-to-register, m2r, instructions are nearly
  265.      as efficient as register-to-register, r2r, instructions;
  266.      however, memory-to-memory instructions are really simulated
  267.      as a convenience, and are only 1/3 as efficient)
  268. */
  269. #ifdef    MMX_TRACE
  270.  
  271. /*    Include the stuff for printing a trace to stderr...
  272. */
  273.  
  274. #include <stdio.h>
  275.  
  276. #define    mmx_i2r(op, imm, reg) \
  277.     { \
  278.         mmx_t mmx_trace; \
  279.         mmx_trace = (imm); \
  280.         fprintf(stderr, #op "_i2r(" #imm "=0x%016llx, ", mmx_trace.q); \
  281.         __asm__ __volatile__ ("movq %%" #reg ", %0" \
  282.                       : "=X" (mmx_trace) \
  283.                       : /* nothing */ ); \
  284.         fprintf(stderr, #reg "=0x%016llx) => ", mmx_trace.q); \
  285.         __asm__ __volatile__ (#op " %0, %%" #reg \
  286.                       : /* nothing */ \
  287.                       : "X" (imm)); \
  288.         __asm__ __volatile__ ("movq %%" #reg ", %0" \
  289.                       : "=X" (mmx_trace) \
  290.                       : /* nothing */ ); \
  291.         fprintf(stderr, #reg "=0x%016llx\n", mmx_trace.q); \
  292.     }
  293.  
  294. #define    mmx_m2r(op, mem, reg) \
  295.     { \
  296.         mmx_t mmx_trace; \
  297.         mmx_trace = (mem); \
  298.         fprintf(stderr, #op "_m2r(" #mem "=0x%016llx, ", mmx_trace.q); \
  299.         __asm__ __volatile__ ("movq %%" #reg ", %0" \
  300.                       : "=X" (mmx_trace) \
  301.                       : /* nothing */ ); \
  302.         fprintf(stderr, #reg "=0x%016llx) => ", mmx_trace.q); \
  303.         __asm__ __volatile__ (#op " %0, %%" #reg \
  304.                       : /* nothing */ \
  305.                       : "X" (mem)); \
  306.         __asm__ __volatile__ ("movq %%" #reg ", %0" \
  307.                       : "=X" (mmx_trace) \
  308.                       : /* nothing */ ); \
  309.         fprintf(stderr, #reg "=0x%016llx\n", mmx_trace.q); \
  310.     }
  311.  
  312. #define    mmx_r2m(op, reg, mem) \
  313.     { \
  314.         mmx_t mmx_trace; \
  315.         __asm__ __volatile__ ("movq %%" #reg ", %0" \
  316.                       : "=X" (mmx_trace) \
  317.                       : /* nothing */ ); \
  318.         fprintf(stderr, #op "_r2m(" #reg "=0x%016llx, ", mmx_trace.q); \
  319.         mmx_trace = (mem); \
  320.         fprintf(stderr, #mem "=0x%016llx) => ", mmx_trace.q); \
  321.         __asm__ __volatile__ (#op " %%" #reg ", %0" \
  322.                       : "=X" (mem) \
  323.                       : /* nothing */ ); \
  324.         mmx_trace = (mem); \
  325.         fprintf(stderr, #mem "=0x%016llx\n", mmx_trace.q); \
  326.     }
  327.  
  328. #define    mmx_r2r(op, regs, regd) \
  329.     { \
  330.         mmx_t mmx_trace; \
  331.         __asm__ __volatile__ ("movq %%" #regs ", %0" \
  332.                       : "=X" (mmx_trace) \
  333.                       : /* nothing */ ); \
  334.         fprintf(stderr, #op "_r2r(" #regs "=0x%016llx, ", mmx_trace.q); \
  335.         __asm__ __volatile__ ("movq %%" #regd ", %0" \
  336.                       : "=X" (mmx_trace) \
  337.                       : /* nothing */ ); \
  338.         fprintf(stderr, #regd "=0x%016llx) => ", mmx_trace.q); \
  339.         __asm__ __volatile__ (#op " %" #regs ", %" #regd); \
  340.         __asm__ __volatile__ ("movq %%" #regd ", %0" \
  341.                       : "=X" (mmx_trace) \
  342.                       : /* nothing */ ); \
  343.         fprintf(stderr, #regd "=0x%016llx\n", mmx_trace.q); \
  344.     }
  345.  
  346. #define    mmx_m2m(op, mems, memd) \
  347.     { \
  348.         mmx_t mmx_trace; \
  349.         mmx_trace = (mems); \
  350.         fprintf(stderr, #op "_m2m(" #mems "=0x%016llx, ", mmx_trace.q); \
  351.         mmx_trace = (memd); \
  352.         fprintf(stderr, #memd "=0x%016llx) => ", mmx_trace.q); \
  353.         __asm__ __volatile__ ("movq %0, %%mm0\n\t" \
  354.                       #op " %1, %%mm0\n\t" \
  355.                       "movq %%mm0, %0" \
  356.                       : "=X" (memd) \
  357.                       : "X" (mems)); \
  358.         mmx_trace = (memd); \
  359.         fprintf(stderr, #memd "=0x%016llx\n", mmx_trace.q); \
  360.     }
  361.  
  362. #else
  363.  
  364. /*    These macros are a lot simpler without the tracing...
  365. */
  366.  
  367. #define    mmx_i2r(op, imm, reg) \
  368.     __asm__ __volatile__ (#op " $" #imm ", %%" #reg \
  369.                   : /* nothing */ \
  370.                   : /* nothing */);
  371.  
  372. #define    mmx_m2r(op, mem, reg) \
  373.     __asm__ __volatile__ (#op " %0, %%" #reg \
  374.                   : /* nothing */ \
  375.                   : "X" (mem))
  376.  
  377. #define    mmx_r2m(op, reg, mem) \
  378.     __asm__ __volatile__ (#op " %%" #reg ", %0" \
  379.                   : "=X" (mem) \
  380.                   : /* nothing */ )
  381.  
  382. #define    mmx_r2r(op, regs, regd) \
  383.     __asm__ __volatile__ (#op " %" #regs ", %" #regd)
  384.  
  385. #define    mmx_m2m(op, mems, memd) \
  386.     __asm__ __volatile__ ("movq %0, %%mm0\n\t" \
  387.                   #op " %1, %%mm0\n\t" \
  388.                   "movq %%mm0, %0" \
  389.                   : "=X" (memd) \
  390.                   : "X" (mems))
  391.  
  392. #endif
  393.  
  394.  
  395. /*    1x64 MOVe Quadword
  396.     (this is both a load and a store...
  397.      in fact, it is the only way to store)
  398. */
  399. #define    movq_m2r(var, reg)    mmx_m2r(movq, var, reg)
  400. #define    movq_r2m(reg, var)    mmx_r2m(movq, reg, var)
  401. #define    movq_r2r(regs, regd)    mmx_r2r(movq, regs, regd)
  402. #define    movq(vars, vard) \
  403.     __asm__ __volatile__ ("movq %1, %%mm0\n\t" \
  404.                   "movq %%mm0, %0" \
  405.                   : "=X" (vard) \
  406.                   : "X" (vars))
  407.  
  408.  
  409. /*    1x32 MOVe Doubleword
  410.     (like movq, this is both load and store...
  411.      but is most useful for moving things between
  412.      mmx registers and ordinary registers)
  413. */
  414. #define    movd_m2r(var, reg)    mmx_m2r(movd, var, reg)
  415. #define    movd_r2m(reg, var)    mmx_r2m(movd, reg, var)
  416. #define    movd_r2r(regs, regd)    mmx_r2r(movd, regs, regd)
  417. #define    movd(vars, vard) \
  418.     __asm__ __volatile__ ("movd %1, %%mm0\n\t" \
  419.                   "movd %%mm0, %0" \
  420.                   : "=X" (vard) \
  421.                   : "X" (vars))
  422.  
  423.  
  424. /*    2x32, 4x16, and 8x8 Parallel ADDs
  425. */
  426. #define    paddd_m2r(var, reg)    mmx_m2r(paddd, var, reg)
  427. #define    paddd_r2r(regs, regd)    mmx_r2r(paddd, regs, regd)
  428. #define    paddd(vars, vard)    mmx_m2m(paddd, vars, vard)
  429.  
  430. #define    paddw_m2r(var, reg)    mmx_m2r(paddw, var, reg)
  431. #define    paddw_r2r(regs, regd)    mmx_r2r(paddw, regs, regd)
  432. #define    paddw(vars, vard)    mmx_m2m(paddw, vars, vard)
  433.  
  434. #define    paddb_m2r(var, reg)    mmx_m2r(paddb, var, reg)
  435. #define    paddb_r2r(regs, regd)    mmx_r2r(paddb, regs, regd)
  436. #define    paddb(vars, vard)    mmx_m2m(paddb, vars, vard)
  437.  
  438.  
  439. /*    4x16 and 8x8 Parallel ADDs using Saturation arithmetic
  440. */
  441. #define    paddsw_m2r(var, reg)    mmx_m2r(paddsw, var, reg)
  442. #define    paddsw_r2r(regs, regd)    mmx_r2r(paddsw, regs, regd)
  443. #define    paddsw(vars, vard)    mmx_m2m(paddsw, vars, vard)
  444.  
  445. #define    paddsb_m2r(var, reg)    mmx_m2r(paddsb, var, reg)
  446. #define    paddsb_r2r(regs, regd)    mmx_r2r(paddsb, regs, regd)
  447. #define    paddsb(vars, vard)    mmx_m2m(paddsb, vars, vard)
  448.  
  449.  
  450. /*    4x16 and 8x8 Parallel ADDs using Unsigned Saturation arithmetic
  451. */
  452. #define    paddusw_m2r(var, reg)    mmx_m2r(paddusw, var, reg)
  453. #define    paddusw_r2r(regs, regd)    mmx_r2r(paddusw, regs, regd)
  454. #define    paddusw(vars, vard)    mmx_m2m(paddusw, vars, vard)
  455.  
  456. #define    paddusb_m2r(var, reg)    mmx_m2r(paddusb, var, reg)
  457. #define    paddusb_r2r(regs, regd)    mmx_r2r(paddusb, regs, regd)
  458. #define    paddusb(vars, vard)    mmx_m2m(paddusb, vars, vard)
  459.  
  460.  
  461. /*    2x32, 4x16, and 8x8 Parallel SUBs
  462. */
  463. #define    psubd_m2r(var, reg)    mmx_m2r(psubd, var, reg)
  464. #define    psubd_r2r(regs, regd)    mmx_r2r(psubd, regs, regd)
  465. #define    psubd(vars, vard)    mmx_m2m(psubd, vars, vard)
  466.  
  467. #define    psubw_m2r(var, reg)    mmx_m2r(psubw, var, reg)
  468. #define    psubw_r2r(regs, regd)    mmx_r2r(psubw, regs, regd)
  469. #define    psubw(vars, vard)    mmx_m2m(psubw, vars, vard)
  470.  
  471. #define    psubb_m2r(var, reg)    mmx_m2r(psubb, var, reg)
  472. #define    psubb_r2r(regs, regd)    mmx_r2r(psubb, regs, regd)
  473. #define    psubb(vars, vard)    mmx_m2m(psubb, vars, vard)
  474.  
  475.  
  476. /*    4x16 and 8x8 Parallel SUBs using Saturation arithmetic
  477. */
  478. #define    psubsw_m2r(var, reg)    mmx_m2r(psubsw, var, reg)
  479. #define    psubsw_r2r(regs, regd)    mmx_r2r(psubsw, regs, regd)
  480. #define    psubsw(vars, vard)    mmx_m2m(psubsw, vars, vard)
  481.  
  482. #define    psubsb_m2r(var, reg)    mmx_m2r(psubsb, var, reg)
  483. #define    psubsb_r2r(regs, regd)    mmx_r2r(psubsb, regs, regd)
  484. #define    psubsb(vars, vard)    mmx_m2m(psubsb, vars, vard)
  485.  
  486.  
  487. /*    4x16 and 8x8 Parallel SUBs using Unsigned Saturation arithmetic
  488. */
  489. #define    psubusw_m2r(var, reg)    mmx_m2r(psubusw, var, reg)
  490. #define    psubusw_r2r(regs, regd)    mmx_r2r(psubusw, regs, regd)
  491. #define    psubusw(vars, vard)    mmx_m2m(psubusw, vars, vard)
  492.  
  493. #define    psubusb_m2r(var, reg)    mmx_m2r(psubusb, var, reg)
  494. #define    psubusb_r2r(regs, regd)    mmx_r2r(psubusb, regs, regd)
  495. #define    psubusb(vars, vard)    mmx_m2m(psubusb, vars, vard)
  496.  
  497.  
  498. /*    4x16 Parallel MULs giving Low 4x16 portions of results
  499. */
  500. #define    pmullw_m2r(var, reg)    mmx_m2r(pmullw, var, reg)
  501. #define    pmullw_r2r(regs, regd)    mmx_r2r(pmullw, regs, regd)
  502. #define    pmullw(vars, vard)    mmx_m2m(pmullw, vars, vard)
  503.  
  504.  
  505. /*    4x16 Parallel MULs giving High 4x16 portions of results
  506. */
  507. #define    pmulhw_m2r(var, reg)    mmx_m2r(pmulhw, var, reg)
  508. #define    pmulhw_r2r(regs, regd)    mmx_r2r(pmulhw, regs, regd)
  509. #define    pmulhw(vars, vard)    mmx_m2m(pmulhw, vars, vard)
  510.  
  511.  
  512. /*    4x16->2x32 Parallel Mul-ADD
  513.     (muls like pmullw, then adds adjacent 16-bit fields
  514.      in the multiply result to make the final 2x32 result)
  515. */
  516. #define    pmaddwd_m2r(var, reg)    mmx_m2r(pmaddwd, var, reg)
  517. #define    pmaddwd_r2r(regs, regd)    mmx_r2r(pmaddwd, regs, regd)
  518. #define    pmaddwd(vars, vard)    mmx_m2m(pmaddwd, vars, vard)
  519.  
  520.  
  521. /*    1x64 bitwise AND
  522. */
  523. #ifdef    BROKEN_PAND
  524. #define    pand_m2r(var, reg) \
  525.     { \
  526.         mmx_m2r(pandn, (mmx_t) -1LL, reg); \
  527.         mmx_m2r(pandn, var, reg); \
  528.     }
  529. #define    pand_r2r(regs, regd) \
  530.     { \
  531.         mmx_m2r(pandn, (mmx_t) -1LL, regd); \
  532.         mmx_r2r(pandn, regs, regd) \
  533.     }
  534. #define    pand(vars, vard) \
  535.     { \
  536.         movq_m2r(vard, mm0); \
  537.         mmx_m2r(pandn, (mmx_t) -1LL, mm0); \
  538.         mmx_m2r(pandn, vars, mm0); \
  539.         movq_r2m(mm0, vard); \
  540.     }
  541. #else
  542. #define    pand_m2r(var, reg)    mmx_m2r(pand, var, reg)
  543. #define    pand_r2r(regs, regd)    mmx_r2r(pand, regs, regd)
  544. #define    pand(vars, vard)    mmx_m2m(pand, vars, vard)
  545. #endif
  546.  
  547.  
  548. /*    1x64 bitwise AND with Not the destination
  549. */
  550. #define    pandn_m2r(var, reg)    mmx_m2r(pandn, var, reg)
  551. #define    pandn_r2r(regs, regd)    mmx_r2r(pandn, regs, regd)
  552. #define    pandn(vars, vard)    mmx_m2m(pandn, vars, vard)
  553.  
  554.  
  555. /*    1x64 bitwise OR
  556. */
  557. #define    por_m2r(var, reg)    mmx_m2r(por, var, reg)
  558. #define    por_r2r(regs, regd)    mmx_r2r(por, regs, regd)
  559. #define    por(vars, vard)    mmx_m2m(por, vars, vard)
  560.  
  561.  
  562. /*    1x64 bitwise eXclusive OR
  563. */
  564. #define    pxor_m2r(var, reg)    mmx_m2r(pxor, var, reg)
  565. #define    pxor_r2r(regs, regd)    mmx_r2r(pxor, regs, regd)
  566. #define    pxor(vars, vard)    mmx_m2m(pxor, vars, vard)
  567.  
  568.  
  569. /*    2x32, 4x16, and 8x8 Parallel CoMPare for EQuality
  570.     (resulting fields are either 0 or -1)
  571. */
  572. #define    pcmpeqd_m2r(var, reg)    mmx_m2r(pcmpeqd, var, reg)
  573. #define    pcmpeqd_r2r(regs, regd)    mmx_r2r(pcmpeqd, regs, regd)
  574. #define    pcmpeqd(vars, vard)    mmx_m2m(pcmpeqd, vars, vard)
  575.  
  576. #define    pcmpeqw_m2r(var, reg)    mmx_m2r(pcmpeqw, var, reg)
  577. #define    pcmpeqw_r2r(regs, regd)    mmx_r2r(pcmpeqw, regs, regd)
  578. #define    pcmpeqw(vars, vard)    mmx_m2m(pcmpeqw, vars, vard)
  579.  
  580. #define    pcmpeqb_m2r(var, reg)    mmx_m2r(pcmpeqb, var, reg)
  581. #define    pcmpeqb_r2r(regs, regd)    mmx_r2r(pcmpeqb, regs, regd)
  582. #define    pcmpeqb(vars, vard)    mmx_m2m(pcmpeqb, vars, vard)
  583.  
  584.  
  585. /*    2x32, 4x16, and 8x8 Parallel CoMPare for Greater Than
  586.     (resulting fields are either 0 or -1)
  587. */
  588. #define    pcmpgtd_m2r(var, reg)    mmx_m2r(pcmpgtd, var, reg)
  589. #define    pcmpgtd_r2r(regs, regd)    mmx_r2r(pcmpgtd, regs, regd)
  590. #define    pcmpgtd(vars, vard)    mmx_m2m(pcmpgtd, vars, vard)
  591.  
  592. #define    pcmpgtw_m2r(var, reg)    mmx_m2r(pcmpgtw, var, reg)
  593. #define    pcmpgtw_r2r(regs, regd)    mmx_r2r(pcmpgtw, regs, regd)
  594. #define    pcmpgtw(vars, vard)    mmx_m2m(pcmpgtw, vars, vard)
  595.  
  596. #define    pcmpgtb_m2r(var, reg)    mmx_m2r(pcmpgtb, var, reg)
  597. #define    pcmpgtb_r2r(regs, regd)    mmx_r2r(pcmpgtb, regs, regd)
  598. #define    pcmpgtb(vars, vard)    mmx_m2m(pcmpgtb, vars, vard)
  599.  
  600.  
  601. /*    1x64, 2x32, and 4x16 Parallel Shift Left Logical
  602. */
  603. #define    psllq_i2r(imm, reg)    mmx_i2r(psllq, imm, reg)
  604. #define    psllq_m2r(var, reg)    mmx_m2r(psllq, var, reg)
  605. #define    psllq_r2r(regs, regd)    mmx_r2r(psllq, regs, regd)
  606. #define    psllq(vars, vard)    mmx_m2m(psllq, vars, vard)
  607.  
  608. #define    pslld_i2r(imm, reg)    mmx_i2r(pslld, imm, reg)
  609. #define    pslld_m2r(var, reg)    mmx_m2r(pslld, var, reg)
  610. #define    pslld_r2r(regs, regd)    mmx_r2r(pslld, regs, regd)
  611. #define    pslld(vars, vard)    mmx_m2m(pslld, vars, vard)
  612.  
  613. #define    psllw_i2r(imm, reg)    mmx_i2r(psllw, imm, reg)
  614. #define    psllw_m2r(var, reg)    mmx_m2r(psllw, var, reg)
  615. #define    psllw_r2r(regs, regd)    mmx_r2r(psllw, regs, regd)
  616. #define    psllw(vars, vard)    mmx_m2m(psllw, vars, vard)
  617.  
  618.  
  619. /*    1x64, 2x32, and 4x16 Parallel Shift Right Logical
  620. */
  621. #define    psrlq_i2r(imm, reg)    mmx_i2r(psrlq, imm, reg)
  622. #define    psrlq_m2r(var, reg)    mmx_m2r(psrlq, var, reg)
  623. #define    psrlq_r2r(regs, regd)    mmx_r2r(psrlq, regs, regd)
  624. #define    psrlq(vars, vard)    mmx_m2m(psrlq, vars, vard)
  625.  
  626. #define    psrld_i2r(imm, reg)    mmx_i2r(psrld, imm, reg)
  627. #define    psrld_m2r(var, reg)    mmx_m2r(psrld, var, reg)
  628. #define    psrld_r2r(regs, regd)    mmx_r2r(psrld, regs, regd)
  629. #define    psrld(vars, vard)    mmx_m2m(psrld, vars, vard)
  630.  
  631. #define    psrlw_i2r(imm, reg)    mmx_i2r(psrlw, imm, reg)
  632. #define    psrlw_m2r(var, reg)    mmx_m2r(psrlw, var, reg)
  633. #define    psrlw_r2r(regs, regd)    mmx_r2r(psrlw, regs, regd)
  634. #define    psrlw(vars, vard)    mmx_m2m(psrlw, vars, vard)
  635.  
  636.  
  637. /*    2x32 and 4x16 Parallel Shift Right Arithmetic
  638. */
  639. #define    psrad_i2r(imm, reg)    mmx_i2r(psrad, imm, reg)
  640. #define    psrad_m2r(var, reg)    mmx_m2r(psrad, var, reg)
  641. #define    psrad_r2r(regs, regd)    mmx_r2r(psrad, regs, regd)
  642. #define    psrad(vars, vard)    mmx_m2m(psrad, vars, vard)
  643.  
  644. #define    psraw_i2r(imm, reg)    mmx_i2r(psraw, imm, reg)
  645. #define    psraw_m2r(var, reg)    mmx_m2r(psraw, var, reg)
  646. #define    psraw_r2r(regs, regd)    mmx_r2r(psraw, regs, regd)
  647. #define    psraw(vars, vard)    mmx_m2m(psraw, vars, vard)
  648.  
  649.  
  650. /*    2x32->4x16 and 4x16->8x8 PACK and Signed Saturate
  651.     (packs source and dest fields into dest in that order)
  652. */
  653. #define    packssdw_m2r(var, reg)    mmx_m2r(packssdw, var, reg)
  654. #define    packssdw_r2r(regs, regd) mmx_r2r(packssdw, regs, regd)
  655. #define    packssdw(vars, vard)    mmx_m2m(packssdw, vars, vard)
  656.  
  657. #define    packsswb_m2r(var, reg)    mmx_m2r(packsswb, var, reg)
  658. #define    packsswb_r2r(regs, regd) mmx_r2r(packsswb, regs, regd)
  659. #define    packsswb(vars, vard)    mmx_m2m(packsswb, vars, vard)
  660.  
  661.  
  662. /*    4x16->8x8 PACK and Unsigned Saturate
  663.     (packs source and dest fields into dest in that order)
  664. */
  665. #define    packuswb_m2r(var, reg)    mmx_m2r(packuswb, var, reg)
  666. #define    packuswb_r2r(regs, regd) mmx_r2r(packuswb, regs, regd)
  667. #define    packuswb(vars, vard)    mmx_m2m(packuswb, vars, vard)
  668.  
  669.  
  670. /*    2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK Low
  671.     (interleaves low half of dest with low half of source
  672.      as padding in each result field)
  673. */
  674. #define    punpckldq_m2r(var, reg)    mmx_m2r(punpckldq, var, reg)
  675. #define    punpckldq_r2r(regs, regd) mmx_r2r(punpckldq, regs, regd)
  676. #define    punpckldq(vars, vard)    mmx_m2m(punpckldq, vars, vard)
  677.  
  678. #define    punpcklwd_m2r(var, reg)    mmx_m2r(punpcklwd, var, reg)
  679. #define    punpcklwd_r2r(regs, regd) mmx_r2r(punpcklwd, regs, regd)
  680. #define    punpcklwd(vars, vard)    mmx_m2m(punpcklwd, vars, vard)
  681.  
  682. #define    punpcklbw_m2r(var, reg)    mmx_m2r(punpcklbw, var, reg)
  683. #define    punpcklbw_r2r(regs, regd) mmx_r2r(punpcklbw, regs, regd)
  684. #define    punpcklbw(vars, vard)    mmx_m2m(punpcklbw, vars, vard)
  685.  
  686.  
  687. /*    2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK High
  688.     (interleaves high half of dest with high half of source
  689.      as padding in each result field)
  690. */
  691. #define    punpckhdq_m2r(var, reg)    mmx_m2r(punpckhdq, var, reg)
  692. #define    punpckhdq_r2r(regs, regd) mmx_r2r(punpckhdq, regs, regd)
  693. #define    punpckhdq(vars, vard)    mmx_m2m(punpckhdq, vars, vard)
  694.  
  695. #define    punpckhwd_m2r(var, reg)    mmx_m2r(punpckhwd, var, reg)
  696. #define    punpckhwd_r2r(regs, regd) mmx_r2r(punpckhwd, regs, regd)
  697. #define    punpckhwd(vars, vard)    mmx_m2m(punpckhwd, vars, vard)
  698.  
  699. #define    punpckhbw_m2r(var, reg)    mmx_m2r(punpckhbw, var, reg)
  700. #define    punpckhbw_r2r(regs, regd) mmx_r2r(punpckhbw, regs, regd)
  701. #define    punpckhbw(vars, vard)    mmx_m2m(punpckhbw, vars, vard)
  702.  
  703.  
  704. /*    Empty MMx State
  705.     (used to clean-up when going from mmx to float use
  706.      of the registers that are shared by both; note that
  707.      there is no float-to-mmx operation needed, because
  708.      only the float tag word info is corruptible)
  709. */
  710. #ifdef    MMX_TRACE
  711.  
  712. #define    emms() \
  713.     { \
  714.         fprintf(stderr, "emms()\n"); \
  715.         __asm__ __volatile__ ("emms"); \
  716.     }
  717.  
  718. #else
  719.  
  720. #define    emms()            __asm__ __volatile__ ("emms")
  721.  
  722. #endif
  723.  
  724. #endif
  725.  
  726.  
  727.