Mercurial > ecos-v2_0-branch
changeset 26:4741a3c3496a ecos-sw-1999-07-23
Merge from eCos master repository on 1999-07-23-05:47:06-BST
line wrap: on
line diff
--- a/packages/hal/arm/arch/current/ChangeLog +++ b/packages/hal/arm/arch/current/ChangeLog @@ -1,3 +1,27 @@ +1999-07-21 Hugo Tyson <hmt@cygnus.co.uk> + + * src/vectors.S (vectors): Re-organize startup a little to support + ROMming of the image and stubrom creation. Withdraw publication + of cyg_startup_stack; it's necessary to do this a different way, + using... + + * include/hal_intr.h (hal_dram_size): reserve location 0x40 for + communicating DRAM size between boot ROMs and app during startup, + and remembering it within ROM startup. Platforms that don't need + this should zero the location. + +1999-07-19 Hugo Tyson <hmt@cygnus.co.uk> + + * src/vectors.S (cyg_startup_stack): Publish this object for + passing some DRAM size info around during startup. + Remove the unused [well, ignored] array hal_vsr_table - the VSR + table is defined to be at 0x20 by the code here in vectors.S + + * include/hal_intr.h (HAL_VSR_SET): define hal_vsr_table to be at + 0x20 where the hardware vectors actually read VSR entries from. + Renumber VSR symbols to match. Do not use the external + "hal_vsr_table" symbol. + 1999-07-14 Hugo Tyson <hmt@cygnus.co.uk> * src/vectors.S: Add some startup debug via a LED macro - which
--- a/packages/hal/arm/arch/current/include/hal_intr.h +++ b/packages/hal/arm/arch/current/include/hal_intr.h @@ -59,19 +59,18 @@ // These vectors correspond to VSRs. These values are the ones to use for // HAL_VSR_GET/SET -#define CYGNUM_HAL_VECTOR_RESERVED_0 0 -#define CYGNUM_HAL_VECTOR_RESET 1 -#define CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION 2 -#define CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT 3 -#define CYGNUM_HAL_VECTOR_ABORT_PREFETCH 4 -#define CYGNUM_HAL_VECTOR_ABORT_DATA 5 -#define CYGNUM_HAL_VECTOR_reserved 6 -#define CYGNUM_HAL_VECTOR_IRQ 7 -#define CYGNUM_HAL_VECTOR_FIQ 8 +#define CYGNUM_HAL_VECTOR_RESET 0 +#define CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION 1 +#define CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT 2 +#define CYGNUM_HAL_VECTOR_ABORT_PREFETCH 3 +#define CYGNUM_HAL_VECTOR_ABORT_DATA 4 +#define CYGNUM_HAL_VECTOR_reserved 5 +#define CYGNUM_HAL_VECTOR_IRQ 6 +#define CYGNUM_HAL_VECTOR_FIQ 7 #define CYGNUM_HAL_VSR_MIN 0 -#define CYGNUM_HAL_VSR_MAX 8 -#define CYGNUM_HAL_VSR_COUNT 9 +#define CYGNUM_HAL_VSR_MAX 7 +#define CYGNUM_HAL_VSR_COUNT 8 // Exception vectors. These are the values used when passed out to an // external exception handler using cyg_hal_deliver_exception() @@ -98,7 +97,16 @@ externC volatile CYG_ADDRWORD hal_inte externC volatile CYG_ADDRESS hal_interrupt_objects[CYGNUM_HAL_ISR_COUNT]; // VSR table -externC volatile CYG_ADDRESS hal_vsr_table[CYGNUM_HAL_VSR_COUNT]; +//externC volatile CYG_ADDRESS hal_vsr_table[CYGNUM_HAL_VSR_COUNT]; + +// actually, it is immediately after the hardware vectors +#define hal_vsr_table ((volatile CYG_ADDRESS *)(0x20)) + +// and followed by a DRAM size variable used during bootup. This is in a +// fixed location so that it can be shared between an eCos Stub ROM and a +// RAM start eCos app. Ie. so that RAM startup code knows DRAM size. +// If this variable is zero, RAM size is unknown/is the default. +#define hal_dram_size (*(CYG_WORD *)(0x40)) //-------------------------------------------------------------------------- // Default ISR
--- a/packages/hal/arm/arch/current/src/vectors.S +++ b/packages/hal/arm/arch/current/src/vectors.S @@ -104,15 +104,17 @@ // they are copied in pairs. .global vectors vectors: -UNMAPPED_PTR(reset_vector) -PTR(undefined_instruction) -PTR(software_interrupt) -PTR(abort_prefetch) -PTR(abort_data) - .word 0 -PTR(IRQ) -PTR(FIQ) -PTR(start) +UNMAPPED_PTR(reset_vector) // 0x20 +PTR(undefined_instruction) // 0x24 +PTR(software_interrupt) // 0x28 +PTR(abort_prefetch) // 0x2C +PTR(abort_data) // 0x30 + .word 0 // 0x34 +PTR(IRQ) // 0x38 +PTR(FIQ) // 0x3c +PTR(start) // This is copied to 0x28 for bootup // 0x40 + // location 0x40 is used for storing DRAM size if known + // for some platforms. .text // Startup code which will get the machine into supervisor mode @@ -128,12 +130,15 @@ reset_vector: beq start #endif + PLATFORM_SETUP1 // Early stage platform initialization + // which can set DRAM size at 0x40 + // see <cyg/hal/hal_platform_setup.h> + // We cannot access any LED registers until after PLATFORM_SETUP1 LED 7 - PLATFORM_SETUP1 // Early stage platform initialization - // see <cyg/hal/hal_platform_setup.h> - mov r0,#0 // move vectors + // We cannot perform a store until after PLATFORM_SETUP1 + str r0, [r0,#0x40] // DRAM size to zero => unknown ldr r1,.__exception_handlers ldr r2,[r1,#0x04] // undefined instruction str r2,[r0,#0x04] @@ -263,7 +268,7 @@ 2: bl initialize_stub #endif - LED 7 + LED 1 // This starts up the eCos kernel bl cyg_start @@ -720,12 +725,6 @@ init_flag: .extern hal_default_isr - .globl hal_vsr_table -hal_vsr_table: - .rept CYGNUM_HAL_VSR_COUNT - .long 0 // hal_default_isr - .endr - .globl hal_interrupt_handlers hal_interrupt_handlers: .rept CYGNUM_HAL_ISR_COUNT
--- a/packages/hal/mips/arch/current/ChangeLog +++ b/packages/hal/mips/arch/current/ChangeLog @@ -1,3 +1,34 @@ +1999-07-15 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * include/arch.inc (hal_fpu_save_caller): Save fcr31 first as + recommended by user's manual + (hal_fpu_load_caller): Similarly restore fcr31 last + + Rename CYG_HAL_MIPS_FSR_INIT to CYG_HAL_MIPS_FCSR_INIT since that's + closer to its documented name + + * include/mips-regs.h: + Add floating point register definitions, and bitfields/masks for FCR31 + in particular + + * src/mips-stub.c (__single_step): + Enable FP branch support if the hardware has an FPU. + + Change register access to FCR using HAL macro names from mips-regs.h + + When comparing branch tests with 0, cast the result of get_register() + to int so that it works on 64-bit MIPS targets even in 32-bit mode, + when GDB still insists REG_SIZE must be 8 (in which case negative + results would otherwise go positive) + + * src/mipsfp.c: New file to emulate unimplemented MIPS FP operations + * src/PKGconf.mak (COMPILE): compile it + + * src/hal_misc.c (exception_handler): If we have an FPU and get an FP + exception, call cyg_hal_mips_process_fpe() from mipsfp.c to process + it + + 1999-07-09 Jonathan Larmour <jlarmour@cygnus.co.uk> * include/mips.inc:
--- a/packages/hal/mips/arch/current/include/arch.inc +++ b/packages/hal/mips/arch/current/include/arch.inc @@ -341,8 +341,8 @@ hal_intc_translation_table: #error MIPS FPU register size not defined #endif -#ifndef CYG_HAL_MIPS_FSR_INIT -#define CYG_HAL_MIPS_FSR_INIT 0 +#ifndef CYG_HAL_MIPS_FCSR_INIT +#define CYG_HAL_MIPS_FCSR_INIT 0 #endif .macro hal_fpu_init @@ -355,7 +355,7 @@ hal_intc_translation_table: nop nop nop - la v0,CYG_HAL_MIPS_FSR_INIT # Get initial value for FSR + la v0,CYG_HAL_MIPS_FCSR_INIT # Get initial value for FCR31 ctc1 v0,$31 # set Fp control reg nop .endm @@ -363,6 +363,8 @@ hal_intc_translation_table: # Save the caller-saved registers as defined by the ABI. # These only really need saving during interrupts. .macro hal_fpu_save_caller regs + cfc1 v0,$31 + sw v0,mipsreg_fcr31(\regs) sfpr f0,(mipsreg_fpureg+0*mips_fpuregsize)(\regs) sfpr f1,(mipsreg_fpureg+1*mips_fpuregsize)(\regs) sfpr f2,(mipsreg_fpureg+2*mips_fpuregsize)(\regs) @@ -384,8 +386,6 @@ hal_intc_translation_table: sfpr f18,(mipsreg_fpureg+18*mips_fpuregsize)(\regs) sfpr f19,(mipsreg_fpureg+19*mips_fpuregsize)(\regs) sfpr f31,(mipsreg_fpureg+31*mips_fpuregsize)(\regs) - cfc1 v0,$31 - sw v0,mipsreg_fcr31(\regs) .endm # Save the callee-saved registers as defined by the ABI. @@ -413,8 +413,6 @@ hal_intc_translation_table: # Reload the caller-saved registers. .macro hal_fpu_load_caller regs - lw v0,mipsreg_fcr31(\regs) - ctc1 v0,$31 lfpr f0,(mipsreg_fpureg+0*mips_fpuregsize)(\regs) lfpr f1,(mipsreg_fpureg+1*mips_fpuregsize)(\regs) lfpr f2,(mipsreg_fpureg+2*mips_fpuregsize)(\regs) @@ -436,6 +434,8 @@ hal_intc_translation_table: lfpr f18,(mipsreg_fpureg+18*mips_fpuregsize)(\regs) lfpr f19,(mipsreg_fpureg+19*mips_fpuregsize)(\regs) lfpr f31,(mipsreg_fpureg+31*mips_fpuregsize)(\regs) + lw v0,mipsreg_fcr31(\regs) + ctc1 v0,$31 .endm # Reload the callee-saved registers.
--- a/packages/hal/mips/arch/current/include/mips-regs.h +++ b/packages/hal/mips/arch/current/include/mips-regs.h @@ -107,6 +107,41 @@ #define CAUSE 36 #define PC 37 +#define F0 38 +#define F1 39 +#define F2 40 +#define F3 41 +#define F4 42 +#define F5 43 +#define F6 44 +#define F7 45 +#define F8 46 +#define F9 47 +#define F10 48 +#define F11 49 +#define F12 50 +#define F13 51 +#define F14 52 +#define F15 53 +#define F16 54 +#define F17 55 +#define F18 56 +#define F19 57 +#define F20 58 +#define F21 59 +#define F22 60 +#define F23 61 +#define F24 62 +#define F25 63 +#define F26 64 +#define F27 65 +#define F28 66 +#define F29 67 +#define F30 68 +#define F31 69 + +#define FCR31 70 + /* System Control Coprocessor (CP0) exception processing registers */ #define C0_CONTEXT $4 /* Context */ #define C0_BADVADDR $8 /* Bad Virtual Address */ @@ -171,6 +206,36 @@ #define SR_EXL 0x00000002 /* exception level */ #define SR_IE 0x00000001 /* interrupt enable */ +/* Floating-point unit control/status register (FCR31) */ +#define FCR31_FS 0x01000000 /* Flush denormalized to zero */ +#define FCR31_C 0x00800000 /* FP compare result */ + +#define FCR31_CAUSE_E 0x00020000 /* Cause - unimplemented operation */ +#define FCR31_CAUSE_V 0x00010000 /* Cause - invalid operation */ +#define FCR31_CAUSE_Z 0x00008000 /* Cause - division by zero */ +#define FCR31_CAUSE_O 0x00004000 /* Cause - overflow */ +#define FCR31_CAUSE_U 0x00002000 /* Cause - underflow */ +#define FCR31_CAUSE_I 0x00001000 /* Cause - inexact operation */ + +#define FCR31_ENABLES_V 0x00000800 /* Enables - invalid operation */ +#define FCR31_ENABLES_Z 0x00000400 /* Enables - division by zero */ +#define FCR31_ENABLES_O 0x00000200 /* Enables - overflow */ +#define FCR31_ENABLES_U 0x00000100 /* Enables - underflow */ +#define FCR31_ENABLES_I 0x00000080 /* Enables - inexact operation */ + +#define FCR31_FLAGS_V 0x00000040 /* Flags - invalid operation */ +#define FCR31_FLAGS_Z 0x00000020 /* Flags - division by zero */ +#define FCR31_FLAGS_O 0x00000010 /* Flags - overflow */ +#define FCR31_FLAGS_U 0x00000008 /* Flags - underflow */ +#define FCR31_FLAGS_I 0x00000004 /* Flags - inexact operation */ + +#define FCR31_RMMASK 0x00000002 /* Rounding mode mask */ +#define FCR31_RM_RN 0 /* Round to nearest */ +#define FCR31_RM_RZ 1 /* Round to zero */ +#define FCR31_RM_RP 2 /* Round to +infinity */ +#define FCR31_RM_RM 3 /* Round to -infinity */ + + /* Cause register fields */ #define CAUSE_BD 0x80000000 /* Branch Delay */ #define CAUSE_CEMASK 0x30000000 /* Coprocessor Error */
--- a/packages/hal/mips/arch/current/src/PKGconf.mak +++ b/packages/hal/mips/arch/current/src/PKGconf.mak @@ -32,7 +32,7 @@ PACKAGE := hal_mips include ../../../../../pkgconf/pkgconf.mak LIBRARY := libtarget.a -COMPILE := hal_misc.c context.S mips-stub.c +COMPILE := hal_misc.c context.S mips-stub.c mipsfp.c OTHER_OBJS := OTHER_TARGETS := vectors.stamp OTHER_DEPS := $(PACKAGE)_vectors.d
--- a/packages/hal/mips/arch/current/src/hal_misc.c +++ b/packages/hal/mips/arch/current/src/hal_misc.c @@ -68,8 +68,24 @@ externC void __handle_exception (void); externC HAL_SavedRegisters *_hal_registers; +externC cyg_uint8 cyg_hal_mips_process_fpe( HAL_SavedRegisters *regs ); + externC void exception_handler(HAL_SavedRegisters *regs) { +#ifdef CYGHWR_HAL_MIPS_FPU + // We may be required to emulate certain unimplemented Floating Point + // operations + + if ((regs->vector>>2) == CYGNUM_HAL_VECTOR_FPE) { + + // cyg_hal_mips_process_fpe() returns non-zero if it could handle + // the exception successfully. If so, we just return + + if ( cyg_hal_mips_process_fpe(regs) ) + return; + } +#endif + #if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) // Set the pointer to the registers of the current exception
--- a/packages/hal/mips/arch/current/src/mips-stub.c +++ b/packages/hal/mips/arch/current/src/mips-stub.c @@ -195,7 +195,7 @@ void __single_step (void) case OP_BLTZL: case OP_BLTZAL: case OP_BLTZALL: - if (get_register (inst.IType.rs) < 0 ) + if ((int)get_register (inst.IType.rs) < 0 ) instrBuffer.targetAddr = (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4)); @@ -206,7 +206,7 @@ void __single_step (void) case OP_BGEZL: case OP_BGEZAL: case OP_BGEZALL: - if (get_register (inst.IType.rs) >= 0 ) + if ((int)get_register (inst.IType.rs) >= 0 ) instrBuffer.targetAddr = (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4)); @@ -243,7 +243,7 @@ void __single_step (void) break; case OP_BLEZ: case OP_BLEZL: - if (get_register (inst.IType.rs) <= 0) + if ((int)get_register (inst.IType.rs) <= 0) instrBuffer.targetAddr = (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4)); else @@ -251,20 +251,21 @@ void __single_step (void) break; case OP_BGTZ: case OP_BGTZL: - if (get_register (inst.IType.rs) > 0) + if ((int)get_register (inst.IType.rs) > 0) instrBuffer.targetAddr = (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4)); else instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); break; -#if 0 /* no floating point support at the moment */ +#ifdef CYGHWR_HAL_MIPS_FPU + case OP_COP1: if (inst.RType.rs == OP_BC) switch (inst.RType.rt) { case COPz_BCF: case COPz_BCFL: - if (get_register (FCSR) & CSR_C) + if (get_register (FCR31) & FCR31_C) instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); else instrBuffer.targetAddr = @@ -273,7 +274,7 @@ void __single_step (void) break; case COPz_BCT: case COPz_BCTL: - if (get_register (FCSR) & CSR_C) + if (get_register (FCR31) & FCR31_C) instrBuffer.targetAddr = (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4));
new file mode 100644 --- /dev/null +++ b/packages/hal/mips/arch/current/src/mipsfp.c @@ -0,0 +1,529 @@ +//========================================================================== +// +// mipsfp.c +// +// HAL miscellaneous functions +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Cygnus eCos Public License +// Version 1.0 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://sourceware.cygnus.com/ecos +// +// 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 Cygnus Operating System, released +// September 30, 1998. +// +// The Initial Developer of the Original Code is Cygnus. Portions created +// by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. 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 endian + +typedef 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-endian + +typedef 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) + +// 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_uint8 +cyg_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_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"); + + CYG_REPORT_FUNCNAMETYPE("cyg_hal_mips_process_fpe", "returning %d"); + + // 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 = ®s->f[ (insn >> 6) & 0x1f ]; + srcreg1 = ®s->f[ (insn >> 11) & 0x1f ]; + srcreg2 = ®s->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 = (Cyg_libm_ieee_double_shape_type *)srcreg1; + s2 = (Cyg_libm_ieee_double_shape_type *)srcreg2; + + if (issubnormal(s1)) { // flush to 0 and restart + s1->value=0.0; + handled++; + } + + // We could try flushing both to 0 at the same time, but + // that's inadvisable if both numbers are very small. + // Particularly if this is DIV_INSN, when we could therefore + // get 0/0 even when the program explicitly checked for + // denominator != 0. That's also why we check s1 first. + + else if (issubnormal(s2)) { // flush to 0 and restart + s2->value=0.0; + handled++; + } + } else { // 32-bit + Cyg_libm_ieee_float_shape_type *s1, *s2; + + s1 = (Cyg_libm_ieee_float_shape_type *)srcreg1; + s2 = (Cyg_libm_ieee_float_shape_type *)srcreg2; + + if (issubnormal(s1)) { // flush to 0 and restart + s1->value=0.0; + handled++; + } + else if (issubnormal(s2)) { // flush to 0 and restart + s2->value=0.0; + handled++; + } + } + break; + + case SQRT_INSN: + if (fp64bit) { + Cyg_libm_ieee_double_shape_type *d, *s; + + d = (Cyg_libm_ieee_double_shape_type *)dstreg; + s = (Cyg_libm_ieee_double_shape_type *)srcreg1; + + if (issubnormal(s)) { // Sqrt of something tiny is 0 + // if this is a delay slot, we can't restart properly + // so clear the source register instead + if (delay_slot) + s->value=0.0; + else { + d->value=0.0; + regs->pc += 4; // We've dealt with this so move on + } + handled++; + } + + } else { // 32-bit + Cyg_libm_ieee_float_shape_type *d, *s; + + d = (Cyg_libm_ieee_float_shape_type *)dstreg; + s = (Cyg_libm_ieee_float_shape_type *)srcreg1; + + if (issubnormal(s)) { // Sqrt of something tiny is 0 + // if this is a delay slot, we can't restart properly + // so clear the source register instead + if (delay_slot) + s->value=0.0; + else { + d->value=0.0; + regs->pc += 4; // We've dealt with this so move on + } + handled++; + } + } + break; + + case ABS_INSN: + // We may as well do this right if we can + if (fp64bit) { + Cyg_libm_ieee_double_shape_type *d, *s; + + d = (Cyg_libm_ieee_double_shape_type *)dstreg; + s = (Cyg_libm_ieee_double_shape_type *)srcreg1; + + // if this is a delay slot, we can't restart properly + // so clear the source register instead + if (delay_slot) { + s->value=0.0; + } else { + d->asi64 = s->asi64; + d->number.sign = 0; + regs->pc += 4; + } + } else { // 32-bit + Cyg_libm_ieee_float_shape_type *d, *s; + + d = (Cyg_libm_ieee_float_shape_type *)dstreg; + s = (Cyg_libm_ieee_float_shape_type *)srcreg1; + + // if this is a delay slot, we can't restart properly + // so clear the source register instead + if (delay_slot) { + s->value=0.0; + } else { + d->asi32 = s->asi32; + d->number.sign = 0; + regs->pc += 4; + } + } + handled++; + break; + + case NEG_INSN: + // We may as well do this right if we can + if (fp64bit) { + Cyg_libm_ieee_double_shape_type *d, *s; + + d = (Cyg_libm_ieee_double_shape_type *)dstreg; + s = (Cyg_libm_ieee_double_shape_type *)srcreg1; + + // if this is a delay slot, we can't restart properly + // so clear the source register instead + if (delay_slot) { + s->value=0.0; + } else { + d->asi64 = s->asi64; + d->number.sign = s->number.sign ? 0 : 1; + regs->pc += 4; + } + } else { // 32-bit + Cyg_libm_ieee_float_shape_type *d, *s; + + d = (Cyg_libm_ieee_float_shape_type *)dstreg; + s = (Cyg_libm_ieee_float_shape_type *)srcreg1; + + // if this is a delay slot, we can't restart properly + // so clear the source register instead + if (delay_slot) { + s->value=0.0; + } else { + d->asi32 = s->asi32; + d->number.sign = s->number.sign ? 0 : 1; + regs->pc += 4; + } + } + handled++; + break; + + default: + break; + } // switch + + // As well as all the other opcodes in the enum, there are also all + // the floating point compare operations between 48 and 63 + } + + if (handled) { + // We must clear the cause and flag bits before restoring FPCR31 + regs->fcr31 &= ~(FCR31_CAUSE_E | FCR31_CAUSE_V | FCR31_CAUSE_Z | + FCR31_CAUSE_O | FCR31_CAUSE_U | FCR31_CAUSE_I | + FCR31_FLAGS_V | FCR31_FLAGS_Z | + FCR31_FLAGS_O | FCR31_FLAGS_U | FCR31_FLAGS_I); + + } + + CYG_REPORT_RETVAL(handled); + return handled; +} // cyg_hal_mips_process_fpe() + +#endif // ifdef CYGHWR_HAL_MIPS_FPU + +// EOF mipsfp.c
--- a/packages/language/c/libc/current/ChangeLog +++ b/packages/language/c/libc/current/ChangeLog @@ -1,3 +1,25 @@ +1999-07-16 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * src/stdio/input/fgetc.cxx: + Include outline versions of getc() (actually just a symbol alias for + fgetc() ) and getchar() + Some minor clean-ups + Add tracing/assertions + + * src/stdio/input/fputc.cxx: + Likewise (except applied to putc() and putchar()) + + * src/stdio/common/stdioinlines.cxx (_puts): + Call fputc() not _fputc() + + * src/clibincl/stdiosupp.hxx: + Remove now obsolete prototypes for _fgetc() and _fputc() + + * include/stdio.h: + Don't bother with getc()/putc() macros any more, just call + them as functions + Include protos for getc(), putc(), getchar() and putchar() functions + 1999-06-11 Jonathan Larmour <jlarmour@cygnus.co.uk> * include/stdio.h: Make FILEs array types so they won't be
--- a/packages/language/c/libc/current/include/stdio.h +++ b/packages/language/c/libc/current/include/stdio.h @@ -192,21 +192,22 @@ externC int fputc( int /* c */, FILE * /* stream */ ); externC int -fputs( const char * /* str */, FILE * /* stream */ ); +putc( int /* c */, FILE * /* stream */ ); -// no function equivalent is required for these, so we can just #define -// them +externC int +putchar( int /* c */ ); -#define getc( __stream ) fgetc( __stream ) - -#define getchar() fgetc( stdin ) +externC int +fputs( const char * /* str */, FILE * /* stream */ ); externC char * gets( char * ); -#define putc(__c, __stream) fputc(__c, __stream) +externC int +getc( FILE * /* stream */ ); -#define putchar(__c) fputc(__c, stdout) +externC int +getchar( void ); externC int puts( const char * /* str */ ); @@ -214,6 +215,13 @@ puts( const char * /* str */ ); externC int ungetc( int /* c */, FILE * /* stream */ ); +// no function equivalent is required for getchar() or putchar(), so we can +// just #define them + +#define getchar() fgetc( stdin ) + +#define putchar(__c) fputc(__c, stdout) + //======================================================================== // ISO C 7.9.8 Direct input/output functions
--- a/packages/language/c/libc/current/src/clibincl/stdiosupp.hxx +++ b/packages/language/c/libc/current/src/clibincl/stdiosupp.hxx @@ -132,16 +132,10 @@ externC int // ISO C 7.9.7 Character input/output functions -externC int -_fgetc( FILE * /* stream */ ); - externC char * _fgets( char * /* str */, int /* length */, FILE * /* stream */ ); externC int -_fputc( int /* c */, FILE * /* stream */ ); - -externC int _fputs( const char * /* str */, FILE * /* stream */ ); externC char *
--- a/packages/language/c/libc/current/src/stdio/common/stdioinlines.cxx +++ b/packages/language/c/libc/current/src/stdio/common/stdioinlines.cxx @@ -147,7 +147,7 @@ externC int rc = _fputs( s, stdout ); if (rc >= 0) - rc = _fputc('\n', stdout ); + rc = fputc('\n', stdout ); return rc; } // _puts()
--- a/packages/language/c/libc/current/src/stdio/input/fgetc.cxx +++ b/packages/language/c/libc/current/src/stdio/input/fgetc.cxx @@ -2,7 +2,7 @@ // // fgetc.cxx // -// ANSI Stdio fgetc() function +// ISO C standard I/O get character functions // //=========================================================================== //####COPYRIGHTBEGIN#### @@ -29,10 +29,11 @@ //=========================================================================== //#####DESCRIPTIONBEGIN#### // -// Author(s): jlarmour -// Contributors: jlarmour -// Date: 1998-02-13 -// Purpose: +// Author(s): jlarmour +// Contributors: jlarmour +// Date: 1999-07-16 +// Purpose: Provide the fgetc() function. Also provides the function +// version of getc() and getchar() // Description: // Usage: // @@ -44,52 +45,82 @@ #include <pkgconf/libc.h> // Configuration header -// Include the C library? And do we want the stdio stuff? -#if defined(CYGPKG_LIBC) && defined(CYGPKG_LIBC_STDIO) +// Do we want the stdio stuff? +#ifdef CYGPKG_LIBC_STDIO // INCLUDES #include <cyg/infra/cyg_type.h> // Common project-wide type definitions +#include <cyg/infra/cyg_ass.h> // Standard eCos assertion support +#include <cyg/infra/cyg_trac.h> // Standard eCos tracing support #include <stddef.h> // NULL and size_t from compiler #include <stdio.h> // header for this file #include <errno.h> // error codes -#include "clibincl/stdiosupp.hxx" // Support functions for stdio #include "clibincl/stream.hxx" // Cyg_StdioStream -// EXPORTED SYMBOLS - -externC int -fgetc( FILE * ) CYGPRI_LIBC_WEAK_ALIAS("_fgetc"); - // FUNCTIONS externC int -_fgetc( FILE *stream ) +__fgetc( FILE *stream ) { Cyg_StdioStream *real_stream = (Cyg_StdioStream *)stream; cyg_ucount32 bytes_read; Cyg_ErrNo err; cyg_uint8 c; + + CYG_REPORT_FUNCNAMETYPE("__fgetc", "returning char %d"); + CYG_REPORT_FUNCARG1XV( stream ); + CYG_CHECK_DATA_PTR( stream, "stream is not a valid pointer" ); + err = real_stream->read( &c, 1, &bytes_read ); + // FIXME: Why do we need this? if (!err && !bytes_read) // if no err, but nothing to read, try again { real_stream->refill_read_buffer(); err = real_stream->read( &c, 1, &bytes_read ); } // if + CYG_ASSERT( 1 == bytes_read, "Didn't read 1 byte!" ); + if (err) { real_stream->set_error( err ); errno = err; + CYG_REPORT_RETVAL(EOF); return EOF; } // if + CYG_REPORT_RETVAL((int)c); return (int)c; -} // _fgetc() +} // __fgetc() + + +externC int +__getchar( void ) +{ + return fgetc( stdin ); +} // __getchar() + + +// EXPORTED SYMBOLS -#endif // if defined(CYGPKG_LIBC) && defined(CYGPKG_LIBC_STDIO) +externC int +fgetc( FILE * ) CYGBLD_ATTRIB_WEAK_ALIAS(__fgetc); + +// Also define getc() and getchar() even though they can be macros. +// Undefine the macros first though +#undef getc +#undef getchar + +externC int +getc( FILE * ) CYGBLD_ATTRIB_WEAK_ALIAS(__fgetc); + +externC int +getchar( void ) CYGBLD_ATTRIB_WEAK_ALIAS(__getchar); + +#endif // ifdef CYGPKG_LIBC_STDIO // EOF fgetc.cxx
--- a/packages/language/c/libc/current/src/stdio/output/fputc.cxx +++ b/packages/language/c/libc/current/src/stdio/output/fputc.cxx @@ -2,7 +2,7 @@ // // fputc.cxx // -// ANSI Stdio fputc() function +// ISO Standard I/O character output functions // //=========================================================================== //####COPYRIGHTBEGIN#### @@ -29,10 +29,11 @@ //=========================================================================== //#####DESCRIPTIONBEGIN#### // -// Author(s): jlarmour -// Contributors: jlarmour -// Date: 1998-02-13 -// Purpose: +// Author(s): jlarmour +// Contributors: jlarmour +// Date: 1999-07-16 +// Purpose: Provide the fputc() function. Also provides the function +// versions of putc() and putchar() // Description: // Usage: // @@ -44,46 +45,71 @@ #include <pkgconf/libc.h> // Configuration header -// Include the C library? And do we want the stdio stuff? -#if defined(CYGPKG_LIBC) && defined(CYGPKG_LIBC_STDIO) +// Do we want the stdio stuff? +#ifdef CYGPKG_LIBC_STDIO // INCLUDES #include <cyg/infra/cyg_type.h> // Common project-wide type definitions +#include <cyg/infra/cyg_ass.h> // Standard eCos assertion support +#include <cyg/infra/cyg_trac.h> // Standard eCos tracing support #include <stddef.h> // NULL and size_t from compiler #include <stdio.h> // header for this file #include <errno.h> // error codes -#include "clibincl/stdiosupp.hxx" // Support functions for stdio #include "clibincl/stream.hxx" // Cyg_StdioStream -// EXPORTED SYMBOLS - -externC int -fputc( int, FILE * ) CYGPRI_LIBC_WEAK_ALIAS("_fputc"); - // FUNCTIONS externC int -_fputc( int c, FILE *stream ) +__fputc( int c, FILE *stream ) { Cyg_StdioStream *real_stream = (Cyg_StdioStream *)stream; Cyg_ErrNo err; cyg_uint8 real_c = (cyg_uint8) c; + CYG_REPORT_FUNCNAMETYPE("__fputc", "wrote char %d"); + CYG_REPORT_FUNCARG2( "c = %d, stream=%08x", c, stream ); + + CYG_CHECK_DATA_PTR( stream, "stream is not a valid pointer" ); + err = real_stream->write_byte( real_c ); if (err) { real_stream->set_error( err ); errno = err; + CYG_REPORT_RETVAL(EOF); return EOF; } // if - + CYG_REPORT_RETVAL((int)real_c); return (int)real_c; -} // _fputc() +} // __fputc() + + +externC int +__putchar( int c ) +{ + return fputc( c, stdout ); +} // __putchar() + +// EXPORTED SYMBOLS -#endif // if defined(CYGPKG_LIBC) && defined(CYGPKG_LIBC_STDIO) +externC int +fputc( int, FILE * ) CYGBLD_ATTRIB_WEAK_ALIAS(__fputc); + +// Also define putc() and putchar() even though they can be macros. +// Undefine the macros first though +#undef putc +#undef putchar + +externC int +putc( int, FILE * ) CYGBLD_ATTRIB_WEAK_ALIAS(__fputc); + +externC int +putchar( int ) CYGBLD_ATTRIB_WEAK_ALIAS(__putchar); + +#endif // ifdef CYGPKG_LIBC_STDIO // EOF fputc.cxx
