
/*
 * ctrl87.c
 */


#define __CONTROL87_C__


#include "../include/i386/ctrl87.h"
#include <config.h>

#ifdef __GNUC__
#ifdef __i386__
#ifndef NOASSEMBLY

/***** _control87 *****/
unsigned short
_control87 (unsigned short newcw, unsigned short mask)
{
    unsigned short cw;

    asm volatile ("                                                    \n\
      wait                                                          \n\
      fstcw  %0                                                       ": /* outputs */ "=m" (cw)
                  :             /* inputs */
        );

    if (mask) {                 /* mask is not 0 */
        asm volatile ("                                                  \n\
        mov    %2, %%ax                                             \n\
        mov    %3, %%cx                                             \n\
        and    %%cx, %%ax                                           \n\
        not    %%cx                                                 \n\
        nop                                                         \n\
        wait                                                        \n\
        mov    %1, %%dx                                             \n\
        and    %%cx, %%dx                                           \n\
        or     %%ax, %%dx                                           \n\
        mov    %%dx, %0                                             \n\
        wait                                                        \n\
        fldcw  %1                                                     ":
                      /* outputs */ "=m" (cw)
                      : /* inputs */ "m" (cw), "m" (newcw), "m" (mask)
                      : /* registers */ "ax", "cx", "dx"
            );
    }
    return cw;

}                               /* _control87 */
#endif
#endif
#endif

#ifdef __GNUC__
#ifdef __i386__
#if 0

/*
 * copy.c -- fast memcpy routines for Pentium using FPU
 * Copyright (c) 1995, 1996 Robert Krawitz <rlk@tiac.net>
 * and Gerhard Koerting (G.Koerting@techem.ruhr-uni-bochum.de)
 * Exception handling in kernel/userspace routines by Gerhard
 * Koerting.
 * May be used and redistributed under the terms of the GNU Public License
 */
#include <sys/types.h>

#define CACHELINE 32
#define CACHEMASK (CACHELINE - 1)
#define BIGMASK (~255)
#define SMALLMASK (~31)

void *
penium___zero_chunk (void *_to, size_t _bytes)
{
    unsigned long temp0, temp1;
    register unsigned long to asm ("di") = (unsigned long) _to;
    register unsigned long bytes asm ("dx") = (unsigned long) _bytes;
    char save[42];
    unsigned long zbuf[2] = { 0, 0 };
    temp0 = to & 7;
    if (temp0) {
        bytes -= temp0;
        asm __volatile__ ("cld\n\t" "rep; stosb\n\t":"=D" (to):"D" (to), "a" (0), "c" (temp0):"cx");
    }
    asm __volatile__ ("shrl $3, %0\n\t" "fstenv %4\n\t" "fstpt 32+%4\n\t" "movl (%1), %2\n\t" "fildq %3\n" "2:\n\t" "fstl (%1)\n\t" "addl $8, %1\n\t" "decl %0\n\t" "jne 2b\n\t" "fstpl %%st\n\t" "fldt 32+%4\n\t" "fldenv %4\n\t":"=&r" (temp0), "=&r" (to), "=&r" (temp1):"m" (*(char *) zbuf), "m" (*(char *) save), "0" (bytes), "1" (to));
    bytes &= 7;
    if (bytes) {
        asm __volatile__ ("shrl $2, %%ecx\n\t" "cld\n\t" "rep ; stosl\n\t" "testb $2,%%dl\n\t" "je 111f\n\t" "stosw\n" "111:\ttestb $1,%%dl\n\t" "je 112f\n\t" "stosb\n" "112:":"=D" (to):"D" (to), "a" (0), "c" (bytes), "d" (bytes):"cx", "memory");
    }
    return _to;
}

void *
pentium__memcpy_g (void *_to, const void *_from, size_t _bytes)
{
    register unsigned long from asm ("si") = (unsigned long) _from;
    register unsigned long to asm ("di") = (unsigned long) _to;
    register unsigned long bytes asm ("dx") = (unsigned long) _bytes;
    if (bytes >= 1024) {
        unsigned long temp0, temp1;
        char save[108];

        temp0 = to & 7;
        if (temp0) {
            bytes -= temp0;
            asm __volatile__ ("cld\n\t" "rep; movsb\n\t":"=D" (to), "=S" (from):"D" (to), "S" (from), "c" (temp0):"cx");
        }
        asm __volatile__ ("shrl $8, %0\n\t" "movl (%2), %3\n\t" "movl (%1), %3\n\t"
                          /*"fsave %4\n" */
                          "1:\n\t" "movl $4, %3\n" "2:\n\t" "fildq 0x0(%2)\n\t" "fildq 0x20(%2)\n\t" "fildq 0x40(%2)\n\t" "fildq 0x60(%2)\n\t" "fildq 0x80(%2)\n\t" "fildq 0xa0(%2)\n\t" "fildq 0xc0(%2)\n\t" "fildq 0xe0(%2)\n\t" "fxch\n\t" "fistpq 0xc0(%1)\n\t" "fistpq 0xe0(%1)\n\t" "fistpq 0xa0(%1)\n\t" "fistpq 0x80(%1)\n\t" "fistpq 0x60(%1)\n\t" "fistpq 0x40(%1)\n\t" "fistpq 0x20(%1)\n\t" "fistpq 0x0(%1)\n\t" "addl $8, %2\n\t" "addl $8, %1\n\t" "decl %3\n\t" "jne 2b\n\t" "addl $224, %2\n\t" "addl $224, %1\n\t" "decl %0\n\t" "jne 1b\n\t"
                          /*"frstor %4\n\t" */
                          :"=&r" (temp0), "=&r" (to), "=&r" (from), "=&r" (temp1):"m" (save[0]), "0" (bytes), "1" (to), "2" (from):"memory");
        bytes &= 255;
    }
    if (bytes) {
        asm __volatile__ ("shrl $2, %%ecx\n\t" "cld\n\t" "rep ; movsl\n\t" "testb $2,%%dl\n\t" "je 111f\n\t" "movsw\n" "111:\ttestb $1,%%dl\n\t" "je 112f\n\t" "movsb\n" "112:":"=D" (to), "=S" (from):"D" (to), "S" (from), "c" (bytes), "d" (bytes):"cx", "memory");
    }
    return _to;
}
#endif
#endif
#endif
