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

📄 mipsfp.c

📁 eCos1.31版
💻 C
📖 第 1 页 / 共 2 页
字号:
//==========================================================================////      mipsfp.c////      HAL miscellaneous functions////==========================================================================//####COPYRIGHTBEGIN####//                                                                          // -------------------------------------------                              // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in         // compliance with the License.  You may obtain a copy of the License at    // http://www.redhat.com/                                                   //                                                                          // Software distributed under the License is distributed on an "AS IS"      // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the // License for the specific language governing rights and limitations under // the License.                                                             //                                                                          // The Original Code is eCos - Embedded Configurable Operating System,      // released September 30, 1998.                                             //                                                                          // The Initial Developer of the Original Code is Red Hat.                   // Portions created by Red Hat are                                          // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             // All Rights Reserved.                                                     // -------------------------------------------                              //                                                                          //####COPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):    jlarmour// Contributors: jlarmour// Date:         1999-07-13// Purpose:      Emulate unimplemented FP operations on MIPS architectures// Description:  This catches the unimplemented operation excetion only,//               and if possible deals with it so processing can continue//               as if the MIPS had a proper IEEE FPU//               ////####DESCRIPTIONEND####////========================================================================*/// CONFIGURATION#include <pkgconf/hal.h>#ifdef CYGHWR_HAL_MIPS_FPU// INCLUDES#include <cyg/infra/cyg_type.h>    // Standard eCos types#include <cyg/infra/cyg_ass.h>     // Standard eCos assertion support#include <cyg/infra/cyg_trac.h>    // Standard eCos tracing support#include <cyg/hal/hal_intr.h>      // HAL interrupt vectors#include <cyg/hal/hal_arch.h>      // Architecture types such as                                   // HAL_SavedRegisters#define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS#include <cyg/hal/mips-regs.h>     // MIPS register and bitmask definitions// TYPES// The following types were taken from <sys/ieeefp.h> from libm.#if (CYG_BYTEORDER == CYG_MSBFIRST) // Big endian// Note: there do not seem to be any current machines which are Big Endian but// have a mixed up double layout. typedef union {    cyg_int32 asi32[2];    cyg_int64 asi64;        double value;        struct     {        unsigned int sign : 1;        unsigned int exponent: 11;        unsigned int fraction0:4;        unsigned int fraction1:16;        unsigned int fraction2:16;        unsigned int fraction3:16;            } number;        struct     {        unsigned int sign : 1;        unsigned int exponent: 11;        unsigned int quiet:1;        unsigned int function0:3;        unsigned int function1:16;        unsigned int function2:16;        unsigned int function3:16;    } nan;        struct     {        cyg_uint32 msw;        cyg_uint32 lsw;    } parts;    } Cyg_libm_ieee_double_shape_type;typedef union{    cyg_int32 asi32;        float value;    struct     {        unsigned int sign : 1;        unsigned int exponent: 8;        unsigned int fraction0: 7;        unsigned int fraction1: 16;    } number;    struct     {        unsigned int sign:1;        unsigned int exponent:8;        unsigned int quiet:1;        unsigned int function0:6;        unsigned int function1:16;    } nan;    } Cyg_libm_ieee_float_shape_type;#else // Little endiantypedef union {    cyg_int32 asi32[2];    cyg_int64 asi64;        double value;    struct     {#if (CYG_DOUBLE_BYTEORDER == CYG_MSBFIRST) // Big endian        unsigned int fraction1:16;        unsigned int fraction0: 4;        unsigned int exponent :11;        unsigned int sign     : 1;        unsigned int fraction3:16;        unsigned int fraction2:16;#else        unsigned int fraction3:16;        unsigned int fraction2:16;        unsigned int fraction1:16;        unsigned int fraction0: 4;        unsigned int exponent :11;        unsigned int sign     : 1;#endif    } number;    struct     {#if (CYG_DOUBLE_BYTEORDER == CYG_MSBFIRST) // Big endian        unsigned int function1:16;        unsigned int function0:3;        unsigned int quiet:1;        unsigned int exponent: 11;        unsigned int sign : 1;        unsigned int function3:16;        unsigned int function2:16;#else        unsigned int function3:16;        unsigned int function2:16;        unsigned int function1:16;        unsigned int function0:3;        unsigned int quiet:1;        unsigned int exponent: 11;        unsigned int sign : 1;#endif    } nan;    struct     {#if (CYG_DOUBLE_BYTEORDER == CYG_MSBFIRST) // Big endian        cyg_uint32 msw;        cyg_uint32 lsw;#else        cyg_uint32 lsw;        cyg_uint32 msw;#endif    } parts;    } Cyg_libm_ieee_double_shape_type;typedef union{    cyg_int32 asi32;      float value;    struct     {        unsigned int fraction0: 7;        unsigned int fraction1: 16;        unsigned int exponent: 8;        unsigned int sign : 1;    } number;    struct     {        unsigned int function1:16;        unsigned int function0:6;        unsigned int quiet:1;        unsigned int exponent:8;        unsigned int sign:1;    } nan;} Cyg_libm_ieee_float_shape_type;#endif // little-endiantypedef enum {    ADD_INSN=0,       // 0    SUB_INSN,    MUL_INSN,    DIV_INSN,    SQRT_INSN,    ABS_INSN,         // 5    MOV_INSN,    NEG_INSN,    ROUNDL_INSN,    TRUNCL_INSN,    CEILL_INSN,       // 10    FLOORL_INSN,    ROUNDW_INSN,    TRUNCW_INSN,    CEILW_INSN,    FLOORW_INSN,      // 15    // ...    CVTS_INSN=32,    CVTD_INSN,    // ...    CVTW_INSN=36,    CVTL_INSN,    // ...    //     // 48-63 are floating point compare - treated separately    } fp_operation;typedef enum {    S_FORMAT=16,    D_FORMAT=17,    W_FORMAT=20,    L_FORMAT=21} fp_format;// FUNCTIONS#define issubnormal(_x_) ((_x_).number.exponent == 0)// These functions convert between single precision floating point numbers// represented in register or union form. This is required because endian-ness// matters when a 32-bit float is in a 64-bit register.static __inline__ voidreg2flt( CYG_HAL_FPU_REG *fpu_reg_p, Cyg_libm_ieee_float_shape_type *flt){#if defined(CYGHWR_HAL_MIPS_FPU_32BIT) || (CYG_BYTEORDER == CYG_LSBFIRST)    flt->asi32 = *(cyg_int32 *)fpu_reg_p;#else    flt->asi32 = *((cyg_int32 *)fpu_reg_p + 1);# endif} // reg2flt()static __inline__ voidflt2reg( Cyg_libm_ieee_float_shape_type *flt, CYG_HAL_FPU_REG *fpu_reg_p ){    *fpu_reg_p = flt->asi32;} // flt2reg()// This function returns non-zero if the exception has been handled// successfully.// FIXME: Arguably we should raise underflow exceptions in some of the cases// below e.g. sqrt(subnormal). And perhaps we should round appropriately to// +/- 2^^Emin if round to +/- infinity is enabled, as per the FS bit. Not sure.externC cyg_uint8cyg_hal_mips_process_fpe( HAL_SavedRegisters *regs ){    CYG_WORD insn;    CYG_HAL_FPU_REG *srcreg1, *srcreg2, *dstreg;    cyg_uint8 handled=0;    fp_format format;    cyg_uint8 fp64bit=0;             // true if format is 64bit, false if 32bit    cyg_uint8 fixedpoint=0;          // true if format is fixed point, false if                                     // floating point    cyg_uint8 computational_insn=1;  // computational FP instruction    cyg_bool delay_slot;             // did it happen in a delay slot    CYG_REPORT_FUNCNAMETYPE("cyg_hal_mips_process_fpe", "returning %d");    CYG_CHECK_DATA_PTR( regs,                    "cyg_hal_mips_process_fpe() called with invalid regs ptr");    CYG_PRECONDITION( (regs->vector>>2) == CYGNUM_HAL_VECTOR_FPE,                      "Asked to process non-FPE exception");    // First of all, we only handle the unimplemented operation exception    // here, so if we don't have that, we just exit    if ((regs->fcr31 & FCR31_CAUSE_E) == 0) {        CYG_REPORT_RETVAL(0);        return 0;    }    // Get the contents of the instruction that caused the exception. This    // may have been in a branch delay slot however, so we have to check    // the BD bit in the cause register first.    if (regs->cause & CAUSE_BD) {        insn = *(((CYG_WORD *) regs->pc) + 1);        delay_slot = true;    } else {        insn = *(CYG_WORD *) regs->pc;        delay_slot = false;    }    CYG_TRACE2(true, "exception at pc %08x containing %08x", regs->pc, insn);    CYG_ASSERT( (insn>>26) == 0x11,                "Instruction at pc doesn't have expected opcode COP1");    // Determine the format    format = (insn >> 21) & 0x1f;    switch (format)    {    case S_FORMAT:        break;    case D_FORMAT:        fp64bit++;        break;    case W_FORMAT:        fixedpoint++;        break;    case L_FORMAT:        fixedpoint++;        fp64bit++;        break;    default:        computational_insn=0;        break;    } // switch    // This module only emulates computational floating point instructions    if (computational_insn && !fixedpoint) {        // Decode the registers used        dstreg  = &regs->f[ (insn >>  6) & 0x1f ];        srcreg1 = &regs->f[ (insn >> 11) & 0x1f ];        srcreg2 = &regs->f[ (insn >> 16) & 0x1f ];            // Determine the operation requested        switch (insn & 0x3f)        {        case ADD_INSN:        case SUB_INSN:        case MUL_INSN:        case DIV_INSN:            if (fp64bit) {                Cyg_libm_ieee_double_shape_type s1, s2;                s1.asi64 = *srcreg1;                s2.asi64 = *srcreg2;                if ( issubnormal( s1 ) ) {  // flush to 0 and restart                    // but preserve sign                    if (s1.number.sign)                        s1.value = -0.0;                    else                        s1.value = 0.0;                    *srcreg1 = s1.asi64;                    handled++;                }                // We could try flushing both to 0 at the same time, but

⌨️ 快捷键说明

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