changeset 26:4741a3c3496a ecos-sw-1999-07-23

Merge from eCos master repository on 1999-07-23-05:47:06-BST
author jlarmour
date Fri, 23 Jul 1999 15:20:15 +0000
parents 9444713147c6
children 2994722c9199
files packages/hal/arm/arch/current/ChangeLog packages/hal/arm/arch/current/include/hal_intr.h packages/hal/arm/arch/current/src/vectors.S packages/hal/mips/arch/current/ChangeLog packages/hal/mips/arch/current/include/arch.inc packages/hal/mips/arch/current/include/mips-regs.h packages/hal/mips/arch/current/src/PKGconf.mak packages/hal/mips/arch/current/src/hal_misc.c packages/hal/mips/arch/current/src/mips-stub.c packages/hal/mips/arch/current/src/mipsfp.c packages/language/c/libc/current/ChangeLog packages/language/c/libc/current/include/stdio.h packages/language/c/libc/current/src/clibincl/stdiosupp.hxx packages/language/c/libc/current/src/stdio/common/stdioinlines.cxx packages/language/c/libc/current/src/stdio/input/fgetc.cxx packages/language/c/libc/current/src/stdio/output/fputc.cxx
diffstat 16 files changed, 848 insertions(+), 94 deletions(-) [+]
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  = &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 = (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