root/common/lib/libc/arch/sparc64/string/strmacros.h
/*      $NetBSD: strmacros.h,v 1.1 2013/03/17 00:42:32 christos Exp $   */

/*
 * Copyright (c) 1996-2002 Eduardo Horvath
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *notice, this list of conditions and the following disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR  ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR  BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include <machine/asm.h>
#if defined(_KERNEL) && !defined(_RUMPKERNEL)
#define USE_BLOCK_STORE_LOAD    /* enable block load/store ops */
#include "assym.h"
#include <machine/param.h>
#include <machine/ctlreg.h>
#include <machine/psl.h>
#include <machine/frame.h>
#include <machine/intr.h>
#include <machine/locore.h>

#ifdef USE_BLOCK_STORE_LOAD

#define BLOCK_SIZE SPARC64_BLOCK_SIZE
#define BLOCK_ALIGN SPARC64_BLOCK_ALIGN

/*
 * The following routines allow fpu use in the kernel.
 *
 * They allocate a stack frame and use all local regs.  Extra
 * local storage can be requested by setting the siz parameter,
 * and can be accessed at %sp+CC64FSZ.
 */

#define ENABLE_FPU(siz)                                                 \
        save    %sp, -(CC64FSZ), %sp;   /* Allocate a stack frame */    \
        sethi   %hi(FPLWP), %l1;                                        \
        add     %fp, STKB-FS_SIZE, %l0;         /* Allocate a fpstate */\
        LDPTR   [%l1 + %lo(FPLWP)], %l2;        /* Load fplwp */        \
        andn    %l0, BLOCK_ALIGN, %l0;          /* Align it */          \
        clr     %l3;                            /* NULL fpstate */      \
        brz,pt  %l2, 1f;                        /* fplwp == NULL? */    \
         add    %l0, -STKB-CC64FSZ-(siz), %sp;  /* Set proper %sp */    \
        LDPTR   [%l2 + L_FPSTATE], %l3;                                 \
        brz,pn  %l3, 1f;        /* Make sure we have an fpstate */      \
         mov    %l3, %o0;                                               \
        call    _C_LABEL(savefpstate);  /* Save the old fpstate */      \
1:                                                                      \
         set    EINTSTACK-STKB, %l4;    /* Are we on intr stack? */     \
        cmp     %sp, %l4;                                               \
        bgu,pt  %xcc, 1f;                                               \
         set    INTSTACK-STKB, %l4;                                     \
        cmp     %sp, %l4;                                               \
        blu     %xcc, 1f;                                               \
0:                                                                      \
         sethi  %hi(_C_LABEL(lwp0)), %l4;       /* Yes, use lpw0 */     \
        ba,pt   %xcc, 2f; /* XXXX needs to change to CPUs idle proc */  \
         or     %l4, %lo(_C_LABEL(lwp0)), %l5;                          \
1:                                                                      \
        sethi   %hi(CURLWP), %l4;               /* Use curlwp */        \
        LDPTR   [%l4 + %lo(CURLWP)], %l5;                               \
        brz,pn  %l5, 0b; nop;   /* If curlwp is NULL need to use lwp0 */\
2:                                                                      \
        LDPTR   [%l5 + L_FPSTATE], %l6;         /* Save old fpstate */  \
        STPTR   %l0, [%l5 + L_FPSTATE];         /* Insert new fpstate */\
        STPTR   %l5, [%l1 + %lo(FPLWP)];        /* Set new fplwp */     \
        wr      %g0, FPRS_FEF, %fprs            /* Enable FPU */

/*
 * Weve saved our possible fpstate, now disable the fpu
 * and continue with life.
 */
#ifdef DEBUG
#define __CHECK_FPU                             \
        LDPTR   [%l5 + L_FPSTATE], %l7;         \
        cmp     %l7, %l0;                       \
        tnz     1;
#else
#define __CHECK_FPU
#endif
        
#define RESTORE_FPU                                                      \
        __CHECK_FPU                                                      \
        STPTR   %l2, [%l1 + %lo(FPLWP)];        /* Restore old fproc */  \
        wr      %g0, 0, %fprs;                  /* Disable fpu */        \
        brz,pt  %l3, 1f;                        /* Skip if no fpstate */ \
         STPTR  %l6, [%l5 + L_FPSTATE];         /* Restore old fpstate */\
                                                                         \
        mov     %l3, %o0;                                                \
        call    _C_LABEL(loadfpstate);          /* Reload orig fpstate */\
1:                                                                       \
         membar #Sync;                          /* Finish all FP ops */

#endif  /* USE_BLOCK_STORE_LOAD */

#ifdef USE_BLOCK_STORE_LOAD
#if 0
#define ASI_STORE       ASI_BLK_COMMIT_P
#else
#define ASI_STORE       ASI_BLK_P
#endif
#endif  /* USE_BLOCK_STORE_LOAD */
#endif /* _KERNEL && !_RUMPKERNEL */