⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fpparchlib.c

📁 vxworks源码源码解读是学习vxworks的最佳途径
💻 C
字号:
/* fppArchLib.c - floating-point coprocessor support library *//* Copyright 1984-1993 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01g,21apr99,hdn  changed selector of the emulator exception handler.01f,14jun95,hdn  added support for fpp emulation library from USS.01e,25may95,ms   added fppRegsToCtx and fppCtxToRegs.01d,10aug93,hdn  added two global variables for fppProbeSup().01c,03jun93,hdn  updated to 5.1		  - moved fppInit(), fppCreateHook(), fppSwapHook(),		    fppTaskRegsShow() to src/all/fppLib.c.  		  - changed to pointer to floating-point register to 		    fppTasksRegs{S,G}et().		  - added arrays fpRegIndex[], fpCtlRegIndex[].		  - added fppArchTastInit().  		  - included regs.h, intLib.h.                  - changed functions to ansi style		  - changed VOID to void01b,29sep92,hdn  fixed a bug.01a,07apr92,hdn  written based on TRON version.*//*DESCRIPTIONThis library provides a low-level interface to the i80387coprocessor.  Routines fppTaskRegsShow(), fppTaskRegsSet(), andfppTaskRegsGet() inspect and set coprocessor registers on a per taskbasis.  The routine fppProbe() checks for the presence of thei80387 coprocessor.  With the exception of fppProbe(), the higherlevel facilities in dbgLib and usrLib should be used instead of theseroutines.INITIALIZATIONTo activate floating-point support, fppInit() must be called before anytasks using the coprocessor are spawned.  If INCLUDE_FLOATING_POINT isdefined in configAll.h, this is done by the root task, usrRoot(), inusrConfig.c.VX_FP_TASK OPTION Saving and restoring floating-point registers adds to the context switchtime of a task.Therefore, floating-point registers are \f2not\fP saved and restored for \f2every\fP task.  Only those tasks spawned with the task option VX_FP_TASKwill have floating-point registers saved and restored.\f3NOTE:\fP  If a task does any floating-point operations,it must be spawned with VX_FP_TASK.INTERRUPT LEVELFloating-point registers are \f2not\fP saved and restored for interruptservice routines connected with intConnect().  However, if necessary,an interrupt service routine can save and restore floating-point registersby calling routines in fppALib.  See the manual entry for intConnect() formore information.EXCEPTIONSThere are six FPU exceptions that can send an IRQ to the CPU.  They arecontrolled by Exception Mask bits of the Control Word register.  VxWorks disables them; theyare:    - Precision    - Overflow    - Underflow    - Division by zero    - Denormalized operand    - Invalid Operation  SEE ALSO: fppALib, intConnect(), i80387 User's Manual*/#include "vxWorks.h"#include "objLib.h"#include "taskLib.h"#include "taskArchLib.h"#include "memLib.h"#include "string.h"#include "iv.h"#include "intLib.h"#include "regs.h"#include "fppLib.h"/* externals */IMPORT USHORT excIdtSelector;IMPORT USHORT intIdtType;IMPORT void intVecSet2 (FUNCPTR * vec, FUNCPTR func, int idtGate, int idtSelector);/* globals */REG_INDEX fpRegName [] =    {    {"st0",	FPX_OFFSET(0)},    {"st1",	FPX_OFFSET(1)},    {"st2",	FPX_OFFSET(2)},    {"st3",	FPX_OFFSET(3)},    {"st4",	FPX_OFFSET(4)},    {"st5",	FPX_OFFSET(5)},    {"st6",	FPX_OFFSET(6)},    {"st7",	FPX_OFFSET(7)},    {NULL, 0},    };REG_INDEX fpCtlRegName [] =    {    {"fpcr",	FPCR},    {"fpsr",	FPSR},    {"fptag",	FPTAG},    {NULL, 0},    };int fppFsw = 0;int fppFcw = 0;VOIDFUNCPTR emu387Func	= NULL; /* function pointer to trap handler */VOIDFUNCPTR emuInitFunc	= NULL; /* function pointer to initializer *//* locals */LOCAL FP_CONTEXT fppInitContext;	/* initialized to initial fp context *//********************************************************************************* fppArchInit - initialize floating-point coprocessor support** This routine must be called before using the floating-point coprocessor.* It is typically called from fppInit().** NOMANUAL*/void fppArchInit (void)    {    fppCreateHookRtn = (FUNCPTR) NULL;    fppSave (&fppInitContext);		/* fppProbe() was called in fppInit() */    }/********************************************************************************* fppArchTaskCreateInit - initialize floating-point coprocessor support for task** INTERNAL* It might seem odd that we use a bcopy() to initialize the floating point* context when a fppSave() of an idle frame would accomplish the same thing* without the cost of a 324 byte data structure.  The problem is that we* are not guaranteed to have an idle frame.  Consider the following scenario:* a floating point task is midway through a floating point instruction when* it is preempted by a *non-floting point* task.  In this case the swap-in* hook does not save the coprocessor state as an optimization.  Now if we* create a floating point task the initial coprocessor frame would not be* idle but rather mid-instruction.  To make matters worse when get around* to saving the original fp task's floating point context frame, it would be* incorrectly saved as idle!  One solution would be to fppSave() once to* the original fp task's context, then fppSave() an idle frame to the new task,* and finally restore the old fp task's context (in case we return to it* before another fp task).  The problem with this approach is that it is* *slow* and considering the fact that preemption is locked, the 324 bytes* don't look so bad anymore.  Indeed, when this approach is adopted by all* architectures we will not need to lock out preemption anymore.** NOMANUAL*/void fppArchTaskCreateInit    (    FP_CONTEXT *pFpContext		/* pointer to FP_CONTEXT */    )    {    bcopy ((const char *) &fppInitContext, (char *)pFpContext,	   sizeof (FP_CONTEXT));    }/******************************************************************************** fppRegsToCtx - convert FPREG_SET to FP_CONTEXT.*/ void fppRegsToCtx    (    FPREG_SET *  pFpRegSet,             /* input -  fpp reg set */    FP_CONTEXT * pFpContext             /* output - fpp context */    )    {    int ix;    if (pFpContext->fpcr == 0)        return;                 /* invalid state frame */    /* normal/idle state */                for (ix = 0; ix < FP_NUM_REGS; ix++)        fppDtoDx ((DOUBLEX *)&pFpContext->fpx[ix],                   (double *)&pFpRegSet->fpx[ix]);    pFpContext->fpcr  = pFpRegSet->fpcr;    pFpContext->fpsr  = pFpRegSet->fpsr;    pFpContext->fptag = pFpRegSet->fptag;    }/******************************************************************************** fppCtxToRegs - convert FP_CONTEXT to FPREG_SET.*/ void fppCtxToRegs    (    FP_CONTEXT * pFpContext,            /* input -  fpp context */    FPREG_SET *  pFpRegSet              /* output - fpp register set */    )    {    int ix;    if (pFpContext->fpcr == 0)        return;                 /* invalid state frame */    /* normal/idle state */    for (ix = 0; ix < FP_NUM_REGS; ix++)        fppDxtoD ((double *)&pFpRegSet->fpx[ix],                   (DOUBLEX *)&pFpContext->fpx[ix]);    pFpRegSet->fpcr  = pFpContext->fpcr;    pFpRegSet->fpsr  = pFpContext->fpsr;    pFpRegSet->fptag = pFpContext->fptag;    }/********************************************************************************* fppTaskRegsGet - get the floating-point registers from a task TCB** This routine copies the floating-point registers of a task* (control, status, and tag) to the locations whose pointers are passed as* parameters.  The floating-point registers are copied in* an array containing the 8 registers.** NOTE* This routine only works well if <task> is not the calling task.  * If a task tries to get its own registers, the values will be stale * (i.e., left over from the last task switch).** RETURNS: OK, or ERROR if there is no floating-point * support or there is an invalid state.** SEE ALSO: fppTaskRegsSet()*/STATUS fppTaskRegsGet    (    int task,			/* task to get info about          */    FPREG_SET *pFpRegSet	/* pointer to floating-point register set */    )    {    FAST FP_CONTEXT *pFpContext;    FAST WIND_TCB *pTcb = taskTcb (task);    if (pTcb == NULL)	return (ERROR);    pFpContext = pTcb->pFpContext;    if (pFpContext == (FP_CONTEXT *)NULL)	return (ERROR);			/* no coprocessor support */    else if (pFpContext->fpcr == 0)	return (ERROR);			/* invalid state frame */    else	fppCtxToRegs (pFpContext, pFpRegSet);    return (OK);    }/********************************************************************************* fppTaskRegsSet - set the floating-point registers of a task ** This routine loads the specified values into the specified task TCB.* The 8 registers st0 - st7 are copied to the array <fpregs>.** RETURNS: OK, or ERROR if there is no floating-point* support or there is an invalid state.** SEE ALSO: fppTaskRegsGet()*/STATUS fppTaskRegsSet    (    int task,			/* task whose registers are to be set */    FPREG_SET *pFpRegSet	/* pointer to floating-point register set */    )    {    FAST WIND_TCB *pTcb = taskTcb (task);    FAST FP_CONTEXT *pFpContext;    if (pTcb == NULL)	return (ERROR);    pFpContext = pTcb->pFpContext;    if (pFpContext == (FP_CONTEXT *)NULL)	return (ERROR);			/* no coprocessor support */    else if (pFpContext->fpcr == 0)	return (ERROR);			/* invalid state frame */    else	fppRegsToCtx (pFpRegSet, pFpContext);    return (OK);    }/********************************************************************************* fppProbe - probe for the presence of a floating-point coprocessor** This routine determines whether there is an i80387* floating-point coprocessor in the system.** IMPLEMENTATION* This routine sets the illegal coprocessor op-code trap vector and executes* a coprocessor instruction.  If the instruction causes an exception,* fppProbe() will return ERROR.  Note that this routine saves and restores* the illegal coprocessor op-code trap vector that was present prior to this* call.** The probe is only performed the first time this routine is called.* The result is stored in a static and returned on subsequent* calls without actually probing.** RETURNS:* OK if the floating-point coprocessor is present, otherwise ERROR.*/STATUS fppProbe (void)    {    static int fppProbed = -2;		/* -2 = not done, -1 = ERROR, 0 = OK */    if (fppProbed == -2)	{	fppProbed = fppProbeSup ();	/* check ET bit in %cr0 */        if (fppProbed == ERROR)            {            if ((emuInitFunc != NULL) && (emu387Func != NULL))                {                intVecSet2 ((FUNCPTR *)IV_NO_DEVICE, (FUNCPTR)emu387Func,			    intIdtType, excIdtSelector);                (* emuInitFunc) ();             /* initialize the emulator */                fppProbed = OK;                 /* pretend as we have 80387 */                }            }	}    return (fppProbed);    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -