changeset 62:7a6ac9edc838 ecos-sw-2000-01-24

Merge from eCos master repository on 2000-01-24-19:43:49-GMT
author jlarmour
date Mon, 24 Jan 2000 21:43:17 +0000
parents e44112c47676
children 119e6e57c342
files packages/hal/arm/edb7xxx/current/ChangeLog packages/hal/arm/edb7xxx/current/include/hal_platform_extras.h packages/hal/arm/edb7xxx/current/misc/PKGconf.mak packages/hal/arm/edb7xxx/current/src/edb7xxx_misc.c packages/hal/common/current/ChangeLog packages/hal/common/current/include/pkgconf/hal.h packages/hal/i386/arch/current/ChangeLog packages/hal/i386/arch/current/include/hal_intr.h packages/hal/i386/linux/current/ChangeLog packages/hal/i386/linux/current/src/hal_diag.c packages/hal/i386/linux/current/src/hal_startup.c packages/hal/i386/linux/current/src/syscall-i386-linux-1.0.S packages/hal/mips/arch/current/ChangeLog packages/hal/mips/arch/current/include/arch.inc packages/hal/mips/arch/current/include/hal_arch.h packages/hal/mips/arch/current/include/pkgconf/hal_mips.h packages/hal/mips/arch/current/src/context.S packages/hal/mips/arch/current/src/hal_misc.c packages/hal/mips/arch/current/src/mipsfp.c packages/hal/mips/arch/current/src/vectors.S packages/hal/mips/jmr3904/current/ChangeLog packages/hal/mips/jmr3904/current/include/platform.inc packages/hal/mips/jmr3904/current/include/plf_stub.h packages/hal/mips/jmr3904/current/src/plf_misc.c packages/hal/mips/tx39/current/ChangeLog packages/hal/mips/tx39/current/include/pkgconf/hal_mips_tx39.h packages/hal/mips/tx39/current/include/var_arch.h packages/hal/mips/tx39/current/src/hal_diag.c packages/hal/mn10300/am31/current/ChangeLog packages/hal/mn10300/am31/current/include/variant.inc packages/hal/mn10300/stdeval1/current/ChangeLog packages/hal/mn10300/stdeval1/current/src/hal_diag.c packages/hal/mn10300/stdeval1/current/src/plf_misc.c packages/hal/powerpc/arch/current/ChangeLog packages/hal/powerpc/arch/current/src/hal_misc.c packages/hal/powerpc/mbx/current/ChangeLog packages/hal/powerpc/mbx/current/src/mbx.S packages/io/serial/current/ChangeLog packages/io/serial/current/include/serial.h packages/io/serial/current/src/arm/aeb_serial.c packages/io/serial/current/src/arm/cma230_serial.c packages/io/serial/current/src/arm/edb7xxx_serial.c packages/io/serial/current/src/arm/pid_serial_with_ints.c packages/io/serial/current/src/common/haldiag.c packages/io/serial/current/src/common/serial.c packages/io/serial/current/src/common/tty.c packages/io/serial/current/src/mips/tx3904_serial.c packages/io/serial/current/src/mn10300/mn10300_serial.c packages/io/serial/current/src/powerpc/cogent_serial_with_ints.c packages/io/serial/current/src/powerpc/quicc_smc_serial.c packages/io/serial/current/src/sparclite/sleb_sdtr.c packages/kernel/current/ChangeLog packages/kernel/current/include/clock.hxx packages/kernel/current/include/pkgconf/kernel.h packages/kernel/current/include/sched.hxx packages/kernel/current/src/sched/sched.cxx packages/kernel/current/src/sync/mutex.cxx packages/kernel/current/tests/PKGconf.mak packages/kernel/current/tests/mutex3.cxx packages/kernel/current/tests/stress_threads.c
diffstat 60 files changed, 1709 insertions(+), 476 deletions(-) [+]
line wrap: on
line diff
--- a/packages/hal/arm/edb7xxx/current/ChangeLog
+++ b/packages/hal/arm/edb7xxx/current/ChangeLog
@@ -1,3 +1,13 @@
+2000-01-03  Gary Thomas  <gthomas@cygnus.co.uk>
+
+	* src/edb7xxx_misc.c: Need to re-enable FIQ during software "refresh",
+	no matter what method is being used [implicit or explicit].
+
+1999-12-21  Gary Thomas  <gthomas@cygnus.co.uk>
+
+	* include/hal_platform_extras.h: Map in expansion segments (used
+	for ethernet and parallel port).
+
 1999-12-14  Jonathan Larmour  <jlarmour@cygnus.co.uk>
 
 	* support/Makefile: Update filenames from earlier source file change,
--- a/packages/hal/arm/edb7xxx/current/include/hal_platform_extras.h
+++ b/packages/hal/arm/edb7xxx/current/include/hal_platform_extras.h
@@ -135,8 +135,8 @@
         FILL_16M_SEGMENT(MMU_L1_TYPE_Fault,0x00)
         FILL_16M_SEGMENT(MMU_L1_TYPE_Fault,0x00)
         FILL_256M_SEGMENT(MMU_L1_TYPE_Fault)
-        FILL_256M_SEGMENT(MMU_L1_TYPE_Fault)
-        FILL_256M_SEGMENT(MMU_L1_TYPE_Fault)
+        FILL_256M_SEGMENT(EXPANSION2_PA|MMU_L1_TYPE_Section|MMU_AP_Any)
+        FILL_256M_SEGMENT(EXPANSION3_PA|MMU_L1_TYPE_Section|MMU_AP_Any)
         FILL_256M_SEGMENT(MMU_L1_TYPE_Fault)
         FILL_256M_SEGMENT(MMU_L1_TYPE_Fault)
         FILL_256M_SEGMENT(SRAM_PA|MMU_L1_TYPE_Section|MMU_AP_Any)
--- a/packages/hal/arm/edb7xxx/current/misc/PKGconf.mak
+++ b/packages/hal/arm/edb7xxx/current/misc/PKGconf.mak
@@ -47,8 +47,3 @@ ifdef CYG_HAL_STARTUP_STUBS
 gdb_module.bin: gdb_module.stamp
 	$(OBJCOPY) -O binary gdb_module$(EXEEXT) gdb_module.bin
 endif
-
-
-
-
-
--- a/packages/hal/arm/edb7xxx/current/src/edb7xxx_misc.c
+++ b/packages/hal/arm/edb7xxx/current/src/edb7xxx_misc.c
@@ -91,12 +91,6 @@ void hal_clock_initialize(cyg_uint32 per
 
 // This routine is called during a clock interrupt.
 
-#ifdef CYGHWR_HAL_ARM_EDB7XXX_SOFTWARE_DRAM_REFRESH
-#define DRAM_START    0x00000000
-#define DRAM_END      0x01000000
-#define DRAM_ROW_SIZE 0x00000400
-#define DRAM_REFRESH  (((DRAM_END-DRAM_START)/DRAM_ROW_SIZE)+99)/100
-
 static void __inline__
 enable_FIQ(void)
 {
@@ -105,13 +99,18 @@ enable_FIQ(void)
                   "msr cpsr,r0");
 }
 
+#ifdef CYGHWR_HAL_ARM_EDB7XXX_SOFTWARE_DRAM_REFRESH
+#define DRAM_START    0x00000000
+#define DRAM_END      0x01000000
+#define DRAM_ROW_SIZE 0x00000400
+#define DRAM_REFRESH  (((DRAM_END-DRAM_START)/DRAM_ROW_SIZE)+99)/100
+
 static void
 do_DRAM_refresh(void)
 {
     static cyg_uint32 *row_ptr;
     volatile cyg_uint32 val;
     int i;
-    enable_FIQ();  // Should be safe here
     for (i = 0;  i < DRAM_REFRESH;  i++) {
         val = *row_ptr;
         row_ptr += DRAM_ROW_SIZE / sizeof(*row_ptr);
@@ -127,6 +126,7 @@ void hal_clock_reset(cyg_uint32 vector, 
         *tc2d = period;
         _period = period;
     }
+    enable_FIQ();  // Should be safe here
 #ifdef CYGHWR_HAL_ARM_EDB7XXX_SOFTWARE_DRAM_REFRESH
     do_DRAM_refresh();
 #else
--- a/packages/hal/common/current/ChangeLog
+++ b/packages/hal/common/current/ChangeLog
@@ -1,3 +1,11 @@
+1999-12-21  Jonathan Larmour  <jlarmour@cygnus.co.uk>
+
+	* include/pkgconf/hal.h: Rename all CYG_HAL_USE_ROM_MONITOR_GDB_STUBS
+	-> CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs
+	Rename all CYG_HAL_USE_ROM_MONITOR_CYGMON -> 
+	CYGSEM_HAL_USE_ROM_MONITOR_CygMon
+	Rename all CYG_HAL_USE_ROM_MONITOR -> CYGSEM_HAL_USE_ROM_MONITOR
+
 1999-11-20  Gary Thomas  <gthomas@cygnus.co.uk>
 
 	* include/pkgconf/hal.h (CYGSEM_HAL_INSTALL_MMU_TABLES): 
--- a/packages/hal/common/current/include/pkgconf/hal.h
+++ b/packages/hal/common/current/include/pkgconf/hal.h
@@ -456,12 +456,12 @@
 //#define CYG_HAL_USE_ROM_MONITOR
 
 #if defined(CYG_HAL_MIPS_TX39_JMR3904) && defined(CYG_HAL_STARTUP_RAM)
-#define CYG_HAL_USE_ROM_MONITOR
-#define CYG_HAL_USE_ROM_MONITOR_CYGMON
+#define CYGSEM_HAL_USE_ROM_MONITOR
+#define CYGSEM_HAL_USE_ROM_MONITOR_CygMon
 #endif
 #if defined(CYG_HAL_MN10300_AM31_STDEVAL1) && defined(CYG_HAL_STARTUP_RAM)
-#define CYG_HAL_USE_ROM_MONITOR
-#define CYG_HAL_USE_ROM_MONITOR_CYGMON
+#define CYGSEM_HAL_USE_ROM_MONITOR
+#define CYGSEM_HAL_USE_ROM_MONITOR_CygMon
 #endif
 
 #ifdef CYG_HAL_USE_ROM_MONITOR
@@ -516,7 +516,6 @@
 # define CYG_HAL_POWERPC_MPC603
 #endif
 
-
 #include CYGBLD_HAL_TARGET_H
 #include CYGBLD_HAL_PLATFORM_H 
 
--- a/packages/hal/i386/arch/current/ChangeLog
+++ b/packages/hal/i386/arch/current/ChangeLog
@@ -1,3 +1,13 @@
+2000-01-21  Jesper Skov  <jskov@cygnus.co.uk>
+
+	* include/hal_intr.h (HAL_INTERRUPT_MASK, HAL_INTERRUPT_UNMASK): 
+	Define.
+
+	(HAL_INTERRUPT_ACKNOWLEDGE): 
+	(HAL_CLOCK_RESET): 
+	Let acknowledge clear pending flag, but leave unblocking to
+	clients of the interrupt (i.e., RTC).
+
 1999-10-25  Jonathan Larmour  <jlarmour@cygnus.co.uk>
 
 	* src/i386.ld: Add asterisks to input section names to make them more
--- a/packages/hal/i386/arch/current/include/hal_intr.h
+++ b/packages/hal/i386/arch/current/include/hal_intr.h
@@ -164,6 +164,9 @@ externC void cyg_hal_default_interrupt_v
 externC void cyg_hal_default_exception_vsr(int vector);
 externC int  cyg_hal_sys_sigprocmask(int, const long*, long*);
 
+// FIXME: These should use block/unblock of the signals instead of
+//        cyg_hal_interrupts_disabled.
+
 #define HAL_ENABLE_INTERRUPTS()                                            \
     CYG_MACRO_START                                                        \
     cyg_ucount8 _i_;                                                       \
@@ -205,15 +208,9 @@ externC int  cyg_hal_sys_sigprocmask(int
     (_old_) = !cyg_hal_interrupts_disabled;     \
     CYG_MACRO_END
 
-// FIXME: Must interract with the disable/enable macro.
-// --proven 19981005
-#define LINUX_SIG_UNBLOCK 1
 #define HAL_INTERRUPT_ACKNOWLEDGE( _vector_ )                   \
     CYG_MACRO_START                                             \
-    long _old_, _new_;                                          \
-    _new_ = 0xffffffff;                                         \
     cyg_hal_interrupts_unhandled[_vector_] = 0;                 \
-    cyg_hal_sys_sigprocmask(LINUX_SIG_UNBLOCK, &_new_, &_old_); \
     CYG_MACRO_END
 
 #endif // ifdef CYGPKG_HAL_I386_LINUX
@@ -288,16 +285,20 @@ externC cyg_uint32 cyg_hal_default_isr(C
 
 #ifdef CYGPKG_HAL_I386_LINUX
 
+#define LINUX_SIG_BLOCK   0
+#define LINUX_SIG_UNBLOCK 1
 #define HAL_INTERRUPT_MASK( _vector_ )                          \
     CYG_MACRO_START                                             \
-    /* Use sigblock to mask a vector */                         \
-    CYG_EMPTY_STATEMENT;                                        \
+    long _old_, _new_;                                          \
+    _new_ = 1 << (_vector_);                                    \
+    cyg_hal_sys_sigprocmask(LINUX_SIG_BLOCK, &_new_, &_old_);   \
     CYG_MACRO_END
 
 #define HAL_INTERRUPT_UNMASK( _vector_ )                        \
     CYG_MACRO_START                                             \
-    /* Use sigunblock to mask a vector */                       \
-    CYG_EMPTY_STATEMENT;                                        \
+    long _old_, _new_;                                          \
+    _new_ = 1 << (_vector_);                                    \
+    cyg_hal_sys_sigprocmask(LINUX_SIG_UNBLOCK, &_new_, &_old_); \
     CYG_MACRO_END
 
 // The native linux port doesn't have configurable interrupts.
@@ -345,8 +346,9 @@ externC int cyg_hal_sys_getitimer(int, s
     cyg_hal_sys_setitimer(CYGNUM_HAL_TIMER_TYPE, &new_itimerval, &old); \
     CYG_MACRO_END
 
-// The clock reinitializes itself.
-#define HAL_CLOCK_RESET( _vector_, _period_ )
+// The sigalarm runs in one-shot mode. We have to re-enable it
+#define HAL_CLOCK_RESET( _vector_, _period_ ) \
+    HAL_INTERRUPT_UNMASK( _vector_ )
 
 // This timer counts down, so subtract from set value.
 #define HAL_CLOCK_READ( _pvalue_ )                                      \
--- a/packages/hal/i386/linux/current/ChangeLog
+++ b/packages/hal/i386/linux/current/ChangeLog
@@ -1,3 +1,11 @@
+2000-01-21  Jesper Skov  <jskov@cygnus.co.uk>
+        CR 902062-CR
+	* src/hal_diag.c:
+	* src/syscall-i386-linux-1.0.S: 
+	Sync after write.
+	
+	* src/hal_startup.c: Make signals NODEFER.
+
 1999-11-25  Gary Thomas  <gthomas@cygnus.co.uk>
 
 	* include/pkgconf/mlt_i386_linux_ram.h: New file(s).
--- a/packages/hal/i386/linux/current/src/hal_diag.c
+++ b/packages/hal/i386/linux/current/src/hal_diag.c
@@ -53,6 +53,7 @@ void hal_diag_init( void )
 
 externC unsigned long cyg_hal_sys_write(int, const void*, long);
 externC unsigned long cyg_hal_sys_read(int, void*, long);
+externC unsigned long cyg_hal_sys_fdatasync(int);
 
 // Write characters to a buffer which is flushed at newline/overflow to
 // improve performance.
@@ -65,6 +66,7 @@ void hal_diag_write_char(char __c)
 
     if ('\n' == __c || 128 == __index) {
         cyg_hal_sys_write(1, &__buffer[0], __index);
+        cyg_hal_sys_fdatasync(1);
         __index = 0;
     }
 }
--- a/packages/hal/i386/linux/current/src/hal_startup.c
+++ b/packages/hal/i386/linux/current/src/hal_startup.c
@@ -135,6 +135,14 @@ cyg_hal_default_isr(CYG_ADDRWORD vector,
 
 //-----------------------------------------------------------------------------
 // Initialization on the VSRs.
+
+// Mark signals NODEFER (i.e., allow a signal to interrupt a running
+// signal handler). This is necessary because we may switch to another
+// thread in the signal handler and thus delay (indefinitely) the
+// return of the "signal handler", postponing new signals during that
+// time.
+#define LINUX_SA_NODEFER    0x40000000
+
 struct hal_sigaction {
     void (*hal_handler)(int);
     long hal_mask;
@@ -155,13 +163,13 @@ externC void cyg_hal_isr_init(void)
     // Interrupt VSR setup
     act.hal_handler = cyg_hal_default_interrupt_vsr;
     act.hal_mask = 0;
-    act.hal_flags = 0;
+    act.hal_flags = LINUX_SA_NODEFER;
     cyg_hal_sys_sigaction(CYGNUM_HAL_INTERRUPT_RTC,  &act, &oact);
 
     // Exception VSR setup
     act.hal_handler = cyg_hal_default_exception_vsr;
     act.hal_mask = 0;
-    act.hal_flags = 0;
+    act.hal_flags = LINUX_SA_NODEFER;
     cyg_hal_sys_sigaction(CYGNUM_HAL_VECTOR_SIGSEGV, &act, &oact);
     cyg_hal_sys_sigaction(CYGNUM_HAL_VECTOR_SIGBUS,  &act, &oact);
     cyg_hal_sys_sigaction(CYGNUM_HAL_VECTOR_SIGFPE,  &act, &oact);
--- a/packages/hal/i386/linux/current/src/syscall-i386-linux-1.0.S
+++ b/packages/hal/i386/linux/current/src/syscall-i386-linux-1.0.S
@@ -347,7 +347,7 @@ NAME(x):                                
 //              read             3              newselect       142
 //              write            4              readv           145
 //              open             5              writev          146
-//              creat            8
+//              creat            8              fdatasync       148 
 //              link             9
 //              unlink          10
 //              execve          11
@@ -578,3 +578,7 @@ SYSCALL3(writev)
 //==========================================================================
 // machdep_sys_newselect()
 SYSCALL5(_newselect)
+
+//==========================================================================
+// machdep_sys_fdatasync()
+SYSCALL1(fdatasync)
--- a/packages/hal/mips/arch/current/ChangeLog
+++ b/packages/hal/mips/arch/current/ChangeLog
@@ -1,3 +1,44 @@
+2000-01-14  Nick Garnett  <nickg@cygnus.co.uk>
+
+	* include/hal_arch.h: 
+	* include/arch.inc: 
+	* src/vectors.S: 
+	* src/context.S: 
+	Several fixes to allow the GPRs to be saved
+	and restored as 64 bit values on some architectures. This is not
+	full 64 bit support since it only covers the GPRs, HI and LO,
+	there is more to be done in the CP0 registers (however it is a
+	start).
+
+1999-12-21  Jonathan Larmour  <jlarmour@cygnus.co.uk>
+
+	* src/vectors.S (__default_exception_vsr): Rename
+	CYG_HAL_USE_ROM_MONITOR_CYGMON -> CYGSEM_HAL_USE_ROM_MONITOR_CygMon
+	Rename CYG_HAL_ROM_MONITOR -> CYGSEM_HAL_ROM_MONITOR
+
+	* src/hal_misc.c (hal_default_isr): Rename CYG_HAL_USE_ROM_MONITOR_CYGMON
+	-> CYGSEM_HAL_USE_ROM_MONITOR_CygMon
+
+	* include/arch.inc: Rename CYG_HAL_USE_ROM_MONITOR ->
+	CYGSEM_HAL_USE_ROM_MONITOR
+
+1999-12-17  Jonathan Larmour  <jlarmour@cygnus.co.uk>
+
+	* src/mipsfp.c (flt2reg): New inline function to convert between
+	float union and register type
+	(reg2flt): Likewise in reverse
+	(cyg_hal_mips_process_fpe): Handle endianness correctly using the above
+	functions. Avoid possible aliasing problems with the compiler. Ensure
+	values are zeroed with the correct sign. Check for denormalized operands
+	for all remaining FPU opcodes.
+
+	* src/hal_misc.c (cyg_hal_exception_handler): Allow handling of
+	unimplemented operation FPU exceptions to be configurable
+	* include/pkgconf/hal_mips.h: Provide
+	CYGSEM_HAL_MIPS_EMULATE_UNIMPLEMENTED_FPU_OPS to do this
+
+	All the above required for cases 102817 and 102820
+
 1999-12-15  Jonathan Larmour  <jlarmour@cygnus.co.uk>
 
 	* include/hal_intr.h (CYGNUM_HAL_EXCEPTION_COUNT): Ensure you can
--- a/packages/hal/mips/arch/current/include/arch.inc
+++ b/packages/hal/mips/arch/current/include/arch.inc
@@ -56,7 +56,7 @@
 #ifndef INITIAL_SR
 
 #if defined(CYG_HAL_STARTUP_RAM)
-# if defined(CYG_HAL_MIPS_SIM) || !defined(CYG_HAL_USE_ROM_MONITOR)
+# if defined(CYG_HAL_MIPS_SIM) || !defined(CYGSEM_HAL_USE_ROM_MONITOR)
 #  define INITIAL_SR	0x1000ff00	/* CP0 usable, Ints enabled	*/
 # else
 #  define INITIAL_SR	0x1040ff00	/* as above + ROM vectors used	*/
@@ -87,6 +87,8 @@
 # define mips_regsize 	4
 #endif
 
+# define mips_regsize32	4
+
 #if defined(CYGHWR_HAL_MIPS_FPU)
 # if defined(CYGHWR_HAL_MIPS_FPU_64BIT)
 #  define mips_fpuregsize 8
@@ -104,19 +106,19 @@
 #ifdef CYGHWR_HAL_MIPS_FPU
 # define mipsreg_fpureg	(mipsreg_lo+mips_regsize)
 # define mipsreg_fcr31	(mipsreg_fpureg+(mips_fpuregsize*32))
-# define mipsreg_fppad  (mipsreg_fcr31+mips_regsize)
-# define mipsreg_vector	(mipsreg_fppad+mips_regsize)
+# define mipsreg_fppad  (mipsreg_fcr31+mips_regsize32)
+# define mipsreg_vector	(mipsreg_fppad+mips_regsize32)
 #else
-# define mipsreg_vector	(mipsreg_lo+mips_regsize)
+# define mipsreg_vector	(mipsreg_lo+mips_regsize32)
 #endif
-#define	mipsreg_pc	(mipsreg_vector+mips_regsize)
-#define	mipsreg_sr	(mipsreg_pc+mips_regsize)
-#define	mipsreg_cachectrl (mipsreg_sr+mips_regsize)
-#define	mipsreg_cause	(mipsreg_cachectrl+mips_regsize)
-#define	mipsreg_badvr	(mipsreg_cause+mips_regsize)
-#define	mipsreg_prid	(mipsreg_badvr+mips_regsize)
-#define	mipsreg_config	(mipsreg_prid+mips_regsize)
-#define	mipsreg_size	(mipsreg_config+mips_regsize)
+#define	mipsreg_pc	(mipsreg_vector+mips_regsize32)
+#define	mipsreg_sr	(mipsreg_pc+mips_regsize32)
+#define	mipsreg_cachectrl (mipsreg_sr+mips_regsize32)
+#define	mipsreg_cause	(mipsreg_cachectrl+mips_regsize32)
+#define	mipsreg_badvr	(mipsreg_cause+mips_regsize32)
+#define	mipsreg_prid	(mipsreg_badvr+mips_regsize32)
+#define	mipsreg_config	(mipsreg_prid+mips_regsize32)
+#define	mipsreg_size	(mipsreg_config+mips_regsize32)
 
 #define mips_exception_decrement	(mipsreg_size*2)
 
@@ -329,6 +331,81 @@ hal_intc_translation_table:
 #endif
 
 #------------------------------------------------------------------------------
+# Register save and restore macros. These expect a pointer to a CPU save state
+# area in the register \ptr. The GPR indicated by \reg will be saved into its
+# slot in that structure.
+
+#ifdef CYGHWR_HAL_MIPS_64BIT
+
+	.macro sgpr reg,ptr
+	sd	$\reg,(mipsreg_regs+\reg*mips_regsize)(\ptr)
+	.endm
+
+	.macro lgpr reg,ptr
+	ld	$\reg,(mipsreg_regs+\reg*mips_regsize)(\ptr)
+	.endm
+
+	.macro slo reg,ptr
+	sd	\reg,(mipsreg_lo)(\ptr)
+	.endm
+
+	.macro shi reg,ptr
+	sd	\reg,(mipsreg_hi)(\ptr)
+	.endm
+
+	.macro llo reg,ptr
+	ld	\reg,(mipsreg_lo)(\ptr)
+	.endm
+
+	.macro lhi reg,ptr
+	ld	\reg,(mipsreg_hi)(\ptr)
+	.endm
+
+	.macro ssp reg,ptr
+	sd	\reg,(mipsreg_regs+29*mips_regsize)(\ptr)
+	.endm
+
+	.macro lsp reg,ptr
+	ld	\reg,(mipsreg_regs+29*mips_regsize)(\ptr)
+	.endm
+
+#else
+
+	.macro sgpr reg,ptr
+	sw	$\reg,(mipsreg_regs+\reg*mips_regsize)(\ptr)
+	.endm
+
+	.macro lgpr reg,ptr
+	lw	$\reg,(mipsreg_regs+\reg*mips_regsize)(\ptr)
+	.endm
+
+	.macro slo reg,ptr
+	sw	\reg,(mipsreg_lo)(\ptr)
+	.endm
+
+	.macro shi reg,ptr
+	sw	\reg,(mipsreg_hi)(\ptr)
+	.endm
+
+	.macro llo reg,ptr
+	lw	\reg,(mipsreg_lo)(\ptr)
+	.endm
+
+	.macro lhi reg,ptr
+	lw	\reg,(mipsreg_hi)(\ptr)
+	.endm
+
+	.macro ssp reg,ptr
+	sw	\reg,(mipsreg_regs+29*mips_regsize)(\ptr)
+	.endm
+
+	.macro lsp reg,ptr
+	lw	\reg,(mipsreg_regs+29*mips_regsize)(\ptr)
+	.endm
+
+#endif
+
+#------------------------------------------------------------------------------
 # FPU macros.
 # The MIPS floating point unit essentially operates in two modes. In the first
 # it supplies 32 32bit FP registers that may be paired into 16 64 bit registers.
--- a/packages/hal/mips/arch/current/include/hal_arch.h
+++ b/packages/hal/mips/arch/current/include/hal_arch.h
@@ -49,9 +49,17 @@
 
 //--------------------------------------------------------------------------
 // Processor saved states:
-// The layout of this structure is also defined in "mips.inc", for assembly
+// The layout of this structure is also defined in "arch.inc", for assembly
 // code. Do not change this without changing that (or vice versa).
 
+#ifdef CYGHWR_HAL_MIPS_64BIT
+# define CYG_HAL_MIPS_REG CYG_WORD64
+# define CYG_HAL_MIPS_REG_SIZE 8
+#else
+# define CYG_HAL_MIPS_REG CYG_WORD32
+# define CYG_HAL_MIPS_REG_SIZE 4
+#endif
+
 #if defined(CYGHWR_HAL_MIPS_FPU)
 # if defined(CYGHWR_HAL_MIPS_FPU_64BIT)
 #  define CYG_HAL_FPU_REG CYG_WORD64
@@ -65,9 +73,9 @@
 typedef struct 
 {
     // These are common to all saved states
-    CYG_ADDRWORD        d[32];          /* Data regs                    */
-    CYG_ADDRWORD        hi;             /* hi word of mpy/div reg       */
-    CYG_ADDRWORD        lo;             /* lo word of mpy/div reg       */
+    CYG_HAL_MIPS_REG    d[32];          /* Data regs                    */
+    CYG_HAL_MIPS_REG    hi;             /* hi word of mpy/div reg       */
+    CYG_HAL_MIPS_REG    lo;             /* lo word of mpy/div reg       */
 #ifdef CYGHWR_HAL_MIPS_FPU
     CYG_HAL_FPU_REG     f[32];          /* FPU registers                */
     CYG_ADDRWORD        fcr31;          /* FPU control/status register  */
@@ -132,24 +140,24 @@ externC cyg_uint32 hal_msbit_index(cyg_u
 // _thread_ thread object address, passed as argument to entry point
 // _entry_ entry point address.
 // _id_ bit pattern used in initializing registers, for debugging.
-#define HAL_THREAD_INIT_CONTEXT( _sparg_, _thread_, _entry_, _id_ )        \
-{                                                                          \
-    register CYG_WORD _sp_ = ((CYG_WORD)_sparg_)-56;                       \
-    register HAL_SavedRegisters *_regs_;                                   \
-    int _i_;                                                               \
-    _sp_ = _sp_ & 0xFFFFFFF0;                                              \
+#define HAL_THREAD_INIT_CONTEXT( _sparg_, _thread_, _entry_, _id_ )                     \
+{                                                                                       \
+    register CYG_WORD _sp_ = ((CYG_WORD)_sparg_)-56;                                    \
+    register HAL_SavedRegisters *_regs_;                                                \
+    int _i_;                                                                            \
+    _sp_ = _sp_ & 0xFFFFFFF0;                                                           \
     _regs_ = (HAL_SavedRegisters *)(((_sp_) - sizeof(HAL_SavedRegisters))&0xFFFFFFF0);  \
-    for( _i_ = 0; _i_ < 32; _i_++ ) (_regs_)->d[_i_] = (_id_)|_i_;         \
-    HAL_THREAD_INIT_FPU_CONTEXT( _regs_, _id_ );                           \
-    (_regs_)->d[29] = (CYG_WORD)(_sp_);       /* SP = top of stack      */ \
-    (_regs_)->d[04] = (CYG_WORD)(_thread_);   /* R4 = arg1 = thread ptr */ \
-    (_regs_)->lo = 0;                         /* LO = 0                 */ \
-    (_regs_)->hi = 0;                         /* HI = 0                 */ \
-    (_regs_)->d[30] = (CYG_WORD)(_sp_);       /* FP = top of stack      */ \
-    (_regs_)->d[31] = (CYG_WORD)(_entry_);    /* LR(d[31]) = entry point*/ \
-    (_regs_)->pc = (CYG_WORD)(_entry_);       /* PC = entry point       */ \
-    (_regs_)->sr  = 0x00000001;               /* SR = ls 3 bits only    */ \
-    _sparg_ = (CYG_ADDRESS)_regs_;                                         \
+    for( _i_ = 0; _i_ < 32; _i_++ ) (_regs_)->d[_i_] = (_id_)|_i_;                      \
+    HAL_THREAD_INIT_FPU_CONTEXT( _regs_, _id_ );                                        \
+    (_regs_)->d[29] = (CYG_HAL_MIPS_REG)(_sp_);       /* SP = top of stack      */      \
+    (_regs_)->d[04] = (CYG_HAL_MIPS_REG)(_thread_);   /* R4 = arg1 = thread ptr */      \
+    (_regs_)->lo = 0;                                 /* LO = 0                 */      \
+    (_regs_)->hi = 0;                                 /* HI = 0                 */      \
+    (_regs_)->d[30] = (CYG_HAL_MIPS_REG)(_sp_);       /* FP = top of stack      */      \
+    (_regs_)->d[31] = (CYG_HAL_MIPS_REG)(_entry_);    /* RA(d[31]) = entry point*/      \
+    (_regs_)->pc = (CYG_WORD)(_entry_);               /* PC = entry point       */      \
+    (_regs_)->sr  = 0x00000001;                       /* SR = ls 3 bits only    */      \
+    _sparg_ = (CYG_ADDRESS)_regs_;                                                      \
 }
 
 //--------------------------------------------------------------------------
@@ -313,11 +321,6 @@ externC void hal_idle_thread_action(cyg_
 //           THEY ARE HOWEVER ENOUGH TO START PROGRAMMING.
 // YOU MUST MAKE YOUR STACKS LARGER IF YOU HAVE LARGE "AUTO" VARIABLES!
 
-// We define quite large stack needs for SPARClite, for it requires 576
-// bytes (144 words) to process an interrupt and thread-switch, and
-// momentarily, but needed in case of recursive interrupts, it needs 208
-// words - if a sequence of saves to push out other regsets is interrupted.
-
 // This is not a config option because it should not be adjusted except
 // under "enough rope" sort of disclaimers.
 
@@ -327,14 +330,14 @@ externC void hal_idle_thread_action(cyg_
 // Stack needed for a context switch:
 #if defined(CYGHWR_HAL_MIPS_FPU)
 # if defined(CYGHWR_HAL_MIPS_FPU_64BIT)
-#define CYGNUM_HAL_STACK_CONTEXT_SIZE (((32+12)*4)+(32*8))
+#define CYGNUM_HAL_STACK_CONTEXT_SIZE (((32+12)*CYG_HAL_MIPS_REG_SIZE)+(32*8))
 # elif defined(CYGHWR_HAL_MIPS_FPU_32BIT)
-#define CYGNUM_HAL_STACK_CONTEXT_SIZE (((32+12)*4)+(32*4))
+#define CYGNUM_HAL_STACK_CONTEXT_SIZE (((32+12)*CYG_HAL_MIPS_REG_SIZE)+(32*4))
 # else
 # error MIPS FPU register size not defined
 # endif
 #else
-#define CYGNUM_HAL_STACK_CONTEXT_SIZE ((32+10)*4)
+#define CYGNUM_HAL_STACK_CONTEXT_SIZE ((32+10)*CYG_HAL_MIPS_REG_SIZE)
 #endif
 
 
--- a/packages/hal/mips/arch/current/include/pkgconf/hal_mips.h
+++ b/packages/hal/mips/arch/current/include/pkgconf/hal_mips.h
@@ -76,9 +76,24 @@
            memory access speed settings."
    }
    
+   cdl_option CYGSEM_HAL_MIPS_EMULATE_UNIMPLEMENTED_FPU_OPS {
+       display  "Emulate unimplemented FPU opcodes"
+       type     boolean
+       parent   CYGPKG_HAL_MIPS
+       description "
+           Enabling this option will include a hook in the exception
+           processing so that Unimplemented Operation FPU exceptions
+           may be handled. This option has no effect if there is no
+           hardware floating-point unit. Note that not all situations
+           in which an exception is raised may be handled. If not, the
+           exception will be passed on as normal through the standard
+           exception delivery mechanism."
+   }
+   
    }}CFG_DATA */
 
 #define CYGHWR_HAL_MIPS_CPU_FREQ        50
+#define CYGSEM_HAL_MIPS_EMULATE_UNIMPLEMENTED_FPU_OPS
 
 /* -------------------------------------------------------------------*/
 /* If either the CTRLC or BREAK support options in hal.h are set      */
--- a/packages/hal/mips/arch/current/src/context.S
+++ b/packages/hal/mips/arch/current/src/context.S
@@ -58,48 +58,48 @@ hal_thread_switch_context:
 	# store GPRs
 	.set	noat
 #ifndef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
-	sw	$0,(mipsreg_regs+0*mips_regsize)(sp)
-	sw	$1,(mipsreg_regs+1*mips_regsize)(sp)
-	sw	$2,(mipsreg_regs+2*mips_regsize)(sp)
-	sw	$3,(mipsreg_regs+3*mips_regsize)(sp)
-	sw	$4,(mipsreg_regs+4*mips_regsize)(sp)
-	sw	$5,(mipsreg_regs+5*mips_regsize)(sp)
-	sw	$6,(mipsreg_regs+6*mips_regsize)(sp)
-	sw	$7,(mipsreg_regs+7*mips_regsize)(sp)
-	sw	$8,(mipsreg_regs+8*mips_regsize)(sp)
-	sw	$9,(mipsreg_regs+9*mips_regsize)(sp)
-	sw	$10,(mipsreg_regs+10*mips_regsize)(sp)
-	sw	$11,(mipsreg_regs+11*mips_regsize)(sp)
-	sw	$12,(mipsreg_regs+12*mips_regsize)(sp)
-	sw	$13,(mipsreg_regs+13*mips_regsize)(sp)
-	sw	$14,(mipsreg_regs+14*mips_regsize)(sp)
-	sw	$15,(mipsreg_regs+15*mips_regsize)(sp)
-	sw	$24,(mipsreg_regs+24*mips_regsize)(sp)
-	sw	$25,(mipsreg_regs+25*mips_regsize)(sp)
-	sw	$28,(mipsreg_regs+28*mips_regsize)(sp)	# == GP
+	sgpr	0,sp
+	sgpr	1,sp
+	sgpr	2,sp
+	sgpr	3,sp
+	sgpr	4,sp
+	sgpr	5,sp
+	sgpr	6,sp
+	sgpr	7,sp
+	sgpr	8,sp
+	sgpr	9,sp
+	sgpr	10,sp
+	sgpr	11,sp
+	sgpr	12,sp
+	sgpr	13,sp
+	sgpr	14,sp
+	sgpr	15,sp
+	sgpr	24,sp
+	sgpr	25,sp
+	sgpr	28,sp	# == GP
 #endif	
-	sw	$16,(mipsreg_regs+16*mips_regsize)(sp)
-	sw	$17,(mipsreg_regs+17*mips_regsize)(sp)	
-	sw	$18,(mipsreg_regs+18*mips_regsize)(sp)
-	sw	$19,(mipsreg_regs+19*mips_regsize)(sp)
-	sw	$20,(mipsreg_regs+20*mips_regsize)(sp)
-	sw	$21,(mipsreg_regs+21*mips_regsize)(sp)
-	sw	$22,(mipsreg_regs+22*mips_regsize)(sp)
-	sw	$23,(mipsreg_regs+23*mips_regsize)(sp)
-#	sw	$26,(mipsreg_regs+26*mips_regsize)(sp)	# == K0
-#	sw	$27,(mipsreg_regs+27*mips_regsize)(sp)	# == K1
-#	sw	$29,(mipsreg_regs+29*mips_regsize)(sp)	# == SP
-	sw	$30,(mipsreg_regs+30*mips_regsize)(sp)	# == FP
-	sw	$31,(mipsreg_regs+31*mips_regsize)(sp)	# == RA
-	sw	$31,(mipsreg_pc)(sp)		# == PC (to help with debugging)
+	sgpr	16,sp
+	sgpr	17,sp	
+	sgpr	18,sp
+	sgpr	19,sp
+	sgpr	20,sp
+	sgpr	21,sp
+	sgpr	22,sp
+	sgpr	23,sp
+#	sgpr	26,sp	# == K0
+#	sgpr	27,sp	# == K1
+#	sgpr	29,sp	# == SP
+	sgpr	30,sp	# == FP
+	sgpr	31,sp	# == RA
+	sgpr	31,sp	# == PC (to help with debugging)
 	.set	at
 	
 #ifndef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
 
 	mflo	t0				# save LO and HI regs
 	mfhi	t1
-	sw	t0,mipsreg_lo(sp)
-	sw	t1,mipsreg_hi(sp)
+	slo	t0,sp
+	shi	t1,sp
 	
 #endif
 
@@ -112,7 +112,7 @@ hal_thread_switch_context:
 #endif
 	
 	addi	t0,sp,mipsreg_size		# save SP in reg dump
-	sw	t0,(mipsreg_regs+29*mips_regsize)(sp)
+	ssp	t0,sp
 
 	mfc0	t1,status			# Save status register
 	sw	t1,mipsreg_sr(sp)
@@ -153,44 +153,44 @@ hal_thread_load_context:
 
 	# load GPRs
 	.set	noat
-#	lw	$0,(mipsreg_regs+0*mips_regsize)(sp)
-	lw	$4,(mipsreg_regs+4*mips_regsize)(sp)	# A0, must load for thread startup
+#	lgpr	0,sp
+	lgpr	4,sp	# A0, must load for thread startup
 #ifndef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
-	lw	$1,(mipsreg_regs+1*mips_regsize)(sp)
-	lw	$2,(mipsreg_regs+2*mips_regsize)(sp)
-	lw	$3,(mipsreg_regs+3*mips_regsize)(sp)
-	lw	$5,(mipsreg_regs+5*mips_regsize)(sp)
-	lw	$6,(mipsreg_regs+6*mips_regsize)(sp)
-	lw	$7,(mipsreg_regs+7*mips_regsize)(sp)
-	lw	$8,(mipsreg_regs+8*mips_regsize)(sp)
-	lw	$9,(mipsreg_regs+9*mips_regsize)(sp)
-	lw	$10,(mipsreg_regs+10*mips_regsize)(sp)
-	lw	$11,(mipsreg_regs+11*mips_regsize)(sp)
-	lw	$12,(mipsreg_regs+12*mips_regsize)(sp)
-	lw	$13,(mipsreg_regs+13*mips_regsize)(sp)
-	lw	$14,(mipsreg_regs+14*mips_regsize)(sp)
-	lw	$15,(mipsreg_regs+15*mips_regsize)(sp)
-	lw	$24,(mipsreg_regs+24*mips_regsize)(sp)
-	lw	$25,(mipsreg_regs+25*mips_regsize)(sp)
+	lgpr	1,sp
+	lgpr	2,sp
+	lgpr	3,sp
+	lgpr	5,sp
+	lgpr	6,sp
+	lgpr	7,sp
+	lgpr	8,sp
+	lgpr	9,sp
+	lgpr	10,sp
+	lgpr	11,sp
+	lgpr	12,sp
+	lgpr	13,sp
+	lgpr	14,sp
+	lgpr	15,sp
+	lgpr	24,sp
+	lgpr	25,sp
 #endif	
-	lw	$16,(mipsreg_regs+16*mips_regsize)(sp)
-	lw	$17,(mipsreg_regs+17*mips_regsize)(sp)
-	lw	$18,(mipsreg_regs+18*mips_regsize)(sp)
-	lw	$19,(mipsreg_regs+19*mips_regsize)(sp)
-	lw	$20,(mipsreg_regs+20*mips_regsize)(sp)
-	lw	$21,(mipsreg_regs+21*mips_regsize)(sp)
-	lw	$22,(mipsreg_regs+22*mips_regsize)(sp)
-	lw	$23,(mipsreg_regs+23*mips_regsize)(sp)
-#	lw	$26,(mipsreg_regs+26*mips_regsize)(sp)	# == K0
-#	lw	$27,(mipsreg_regs+27*mips_regsize)(sp)	# == K1
-#	lw	$28,(mipsreg_regs+28*mips_regsize)(sp)	# == GP
-#	lw	$29,(mipsreg_regs+29*mips_regsize)(sp)	# == SP
-	lw	$30,(mipsreg_regs+30*mips_regsize)(sp)	# == FP
-	lw	$31,(mipsreg_regs+31*mips_regsize)(sp)	# == RA
+	lgpr	16,sp
+	lgpr	17,sp
+	lgpr	18,sp
+	lgpr	19,sp
+	lgpr	20,sp
+	lgpr	21,sp
+	lgpr	22,sp
+	lgpr	23,sp
+#	lgpr	26,sp	# == K0
+#	lgpr	27,sp	# == K1
+#	lgpr	28,sp	# == GP
+#	lgpr	29,sp	# == SP
+	lgpr	30,sp	# == FP
+	lgpr	31,sp	# == RA
 	.set	at
 	
 	lw	a2,mipsreg_sr(sp)		# A2 = saved SR
-	lw	sp,(mipsreg_regs+29*mips_regsize)(sp)	# SP = saved SP
+	lsp	sp,sp				# SP = saved SP
 
 	hal_cpu_int_merge a2			# Merge with current SR
 	
--- a/packages/hal/mips/arch/current/src/hal_misc.c
+++ b/packages/hal/mips/arch/current/src/hal_misc.c
@@ -74,7 +74,8 @@ externC cyg_uint8 cyg_hal_mips_process_f
 
 externC cyg_uint32 cyg_hal_exception_handler(HAL_SavedRegisters *regs)
 {
-#ifdef  CYGHWR_HAL_MIPS_FPU
+#if defined(CYGHWR_HAL_MIPS_FPU) && \
+    defined(CYGSEM_HAL_MIPS_EMULATE_UNIMPLEMENTED_FPU_OPS)
     // We may be required to emulate certain unimplemented Floating Point
     // operations
 
@@ -137,7 +138,7 @@ externC cyg_uint32 hal_default_isr(CYG_A
         if( result != 0 ) return result;
     }
     
-#if defined(CYG_HAL_USE_ROM_MONITOR_CYGMON)
+#if defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)
 #if defined(HAL_DIAG_IRQ_CHECK)
     {
         cyg_uint32 ret;
@@ -147,7 +148,7 @@ externC cyg_uint32 hal_default_isr(CYG_A
             return ret;
     }
 #endif // def HAL_DIAG_IRQ_CHECK
-#endif // def CYG_HAL_USE_ROM_MONITOR
+#endif // def CYGSEM_HAL_USE_ROM_MONITOR_CygMon
 #endif
     
     CYG_TRACE1(true, "Interrupt: %d", vector);
--- a/packages/hal/mips/arch/current/src/mipsfp.c
+++ b/packages/hal/mips/arch/current/src/mipsfp.c
@@ -263,7 +263,27 @@ typedef enum {
 
 // FUNCTIONS
 
-#define issubnormal(_x_) ((_x_)->number.exponent == 0)
+#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__ void
+reg2flt( 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__ void
+flt2reg( 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.
@@ -355,13 +375,18 @@ cyg_hal_mips_process_fpe( HAL_SavedRegis
         case DIV_INSN:
 
             if (fp64bit) {
-                Cyg_libm_ieee_double_shape_type *s1, *s2;
+                Cyg_libm_ieee_double_shape_type s1, s2;
+
+                s1.asi64 = *srcreg1;
+                s2.asi64 = *srcreg2;
 
-                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;
+                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++;
                 }
 
@@ -371,59 +396,95 @@ cyg_hal_mips_process_fpe( HAL_SavedRegis
                 // 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;
+                else if (  issubnormal( s2 ) ) {  // flush to 0 and restart
+                    // but preserve sign
+                    if (s2.number.sign)
+                        s2.value = -0.0;
+                    else
+                        s2.value = 0.0;
+                    *srcreg2 = s2.asi64;
                     handled++;
                 }
+
             } else { // 32-bit
-                Cyg_libm_ieee_float_shape_type *s1, *s2;
+                Cyg_libm_ieee_float_shape_type s1, s2;
+
+                reg2flt( srcreg1, &s1 );
+                reg2flt( srcreg2, &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;
+                if ( issubnormal( s1 )) {  // flush to 0 and restart
+                    // but preserve sign
+                    if (s1.number.sign)
+                        s1.value = -0.0;
+                    else
+                        s1.value = 0.0;
+                    flt2reg( &s1, srcreg1 );
                     handled++;
                 }
-                else if (issubnormal(s2)) {  // flush to 0 and restart
-                    s2->value=0.0;
+                else if ( issubnormal( s2 ) ) {  // flush to 0 and restart
+                    // but preserve sign
+                    if (s2.number.sign)
+                        s2.value = -0.0;
+                    else
+                        s2.value = 0.0;
+                    flt2reg( &s2, srcreg2 );
                     handled++;
                 }
             }
             break;
 
         case SQRT_INSN:
-            if (fp64bit) {
-                Cyg_libm_ieee_double_shape_type *d, *s;
+            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;
+                d.asi64 = *dstreg;
+                s.asi64 = *srcreg1;
 
-                if (issubnormal(s)) {  // Sqrt of something tiny is 0
+                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;
+                    // so if it is subnormal, clear the source register instead
+                    if ( delay_slot ) {
+                        // but preserve sign
+                        if (s.number.sign)
+                            s.value = -0.0;
+                        else
+                            s.value = 0.0;
+                        *srcreg1 = s.asi64;
+                    } else {
+                        // but preserve sign
+                        if (s.number.sign)
+                            d.value = -0.0;
+                        else
+                            d.value = 0.0;
+                        *dstreg = d.asi64;
                         regs->pc += 4; // We've dealt with this so move on
                     }
                     handled++;
                 }
 
             } else { // 32-bit
-                Cyg_libm_ieee_float_shape_type *d, *s;
+                Cyg_libm_ieee_float_shape_type d, s;
 
-                d = (Cyg_libm_ieee_float_shape_type *)dstreg;
-                s = (Cyg_libm_ieee_float_shape_type *)srcreg1;
+                reg2flt( dstreg, &d );
+                reg2flt( srcreg1, &s );
 
-                if (issubnormal(s)) {  // Sqrt of something tiny is 0
+                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;
+                    // so if it is subnormal, clear the source register instead
+                    if ( delay_slot ) {
+                        // but preserve sign
+                        if (s.number.sign)
+                            s.value = -0.0;
+                        else
+                            s.value = 0.0;
+                        flt2reg( &s, srcreg1 );
+                    } else {
+                        // but preserve sign
+                        if (s.number.sign)
+                            d.value = -0.0;
+                        else
+                            d.value = 0.0;
+                        flt2reg( &d, dstreg );
                         regs->pc += 4; // We've dealt with this so move on
                     }
                     handled++;
@@ -433,85 +494,282 @@ cyg_hal_mips_process_fpe( HAL_SavedRegis
 
         case ABS_INSN:
             // We may as well do this right if we can
-            if (fp64bit) {
-                Cyg_libm_ieee_double_shape_type *d, *s;
+            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;
+                d.asi64 = *dstreg;
+                s.asi64 = *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;
+                // so if it is subnormal, clear the source register instead
+                if ( delay_slot ) {
+                    if ( issubnormal( s ) ) {
+                        // The sign is still important for abs in case
+                        // there are any further operations on the same
+                        // register
+                        if (s.number.sign)
+                            s.value = -0.0;
+                        else
+                            s.value = 0.0;
+                        *srcreg1 = s.asi64;
+                        handled++;
+                    }
                 } else {
-                    d->asi64 = s->asi64;
-                    d->number.sign = 0;
+                    d.asi64 = s.asi64;
+                    d.number.sign = 0;
+                    *dstreg = d.asi64;
                     regs->pc += 4;
+                    handled++;
                 }
             } else { // 32-bit
-                Cyg_libm_ieee_float_shape_type *d, *s;
+                Cyg_libm_ieee_float_shape_type d, s;
+
+                reg2flt( dstreg, &d );
+                reg2flt( srcreg1, &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 if it is subnormal, clear the source register instead
+                if ( delay_slot ) {
+                    if ( issubnormal( s ) ) {
+                        // The sign is still important for abs in case
+                        // there are any further operations on the same
+                        // register
+                        if (s.number.sign)
+                            s.value = -0.0;
+                        else
+                            s.value = 0.0;
+                        flt2reg( &s, srcreg1 );
+                        handled++;
+                    }
+                } else {
+                    d.asi32 = s.asi32;
+                    d.number.sign = 0;
+                    flt2reg( &d, dstreg );
+                    regs->pc += 4;
+                    handled++;
+                }
+            }
+            break;
+
+        case MOV_INSN:
+            // We may as well do this right if we can
+            if ( fp64bit ) {
+                Cyg_libm_ieee_double_shape_type d, s;
+
+                d.asi64 = *dstreg;
+                s.asi64 = *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;
+                // so if it is subnormal, clear the source register instead
+                if ( delay_slot ) {
+                    if ( issubnormal( s ) ) {
+                        // but preserve sign
+                        if (s.number.sign)
+                            s.value = -0.0;
+                        else
+                            s.value = 0.0;
+                        *srcreg1 = s.asi64;
+                        handled++;
+                    }
                 } else {
-                    d->asi32 = s->asi32;
-                    d->number.sign = 0;
+                    d.asi64 = s.asi64;
+                    *dstreg = d.asi64;
                     regs->pc += 4;
+                    handled++;
+                }
+            } else { // 32-bit
+                Cyg_libm_ieee_float_shape_type d, s;
+
+                reg2flt( dstreg, &d );
+                reg2flt( srcreg1, &s );
+
+                // if this is a delay slot, we can't restart properly
+                // so if it is subnormal, clear the source register instead
+                if ( delay_slot ) {
+                    if ( issubnormal( s ) ) {
+                        // The sign is still important for abs in case
+                        // there are any further operations on the same
+                        // register
+                        if (s.number.sign)
+                            s.value = -0.0;
+                        else
+                            s.value = 0.0;
+                        flt2reg( &s, srcreg1 );
+                        handled++;
+                    }
+                } else {
+                    d.asi32 = s.asi32;
+                    flt2reg( &d, dstreg );
+                    regs->pc += 4;
+                    handled++;
                 }
             }
-            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;
+            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;
+                d.asi64 = *dstreg;
+                s.asi64 = *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;
+                // so if it is subnormal, clear the source register instead
+                if ( delay_slot ) {
+                    if ( issubnormal( s ) ) {
+                        // but preserve sign
+                        if (s.number.sign)
+                            s.value = -0.0;
+                        else
+                            s.value = 0.0;
+                        *srcreg1 = s.asi64;
+                        handled++;
+                    }
                 } else {
-                    d->asi64 = s->asi64;
-                    d->number.sign = s->number.sign ? 0 : 1;
+                    d.asi64 = s.asi64;
+                    d.number.sign = s.number.sign ? 0 : 1;
+                    *dstreg = d.asi64;
                     regs->pc += 4;
+                    handled++;
                 }
             } else { // 32-bit
-                Cyg_libm_ieee_float_shape_type *d, *s;
+                Cyg_libm_ieee_float_shape_type d, s;
 
-                d = (Cyg_libm_ieee_float_shape_type *)dstreg;
-                s = (Cyg_libm_ieee_float_shape_type *)srcreg1;
+                reg2flt( dstreg, &d );
+                reg2flt( srcreg1, &s );
 
                 // if this is a delay slot, we can't restart properly
-                // so clear the source register instead
-                if (delay_slot) {
-                    s->value=0.0;
+                // so if it is subnormal, clear the source register instead
+                if ( delay_slot ) {
+                    if ( issubnormal( s ) ) {
+                        // but preserve sign
+                        if (s.number.sign)
+                            s.value = -0.0;
+                        else
+                            s.value = 0.0;
+                        flt2reg( &s, srcreg1 );
+                        handled++;
+                    }
                 } else {
-                    d->asi32 = s->asi32;
-                    d->number.sign = s->number.sign ? 0 : 1;
+                    d.asi32 = s.asi32;
+                    d.number.sign = s.number.sign ? 0 : 1;
+                    flt2reg( &d, dstreg );
                     regs->pc += 4;
+                    handled++;
                 }
             }
-            handled++;
+            break;
+
+        // We can't do much about floating-point to fixed-point arithmetic
+        // without emulating the FPU here ourselves!
+        // So simply zero denormalized numbers
+        case ROUNDL_INSN:
+        case TRUNCL_INSN:
+        case CEILL_INSN:
+        case FLOORL_INSN:
+        case ROUNDW_INSN:
+        case TRUNCW_INSN:
+        case CEILW_INSN:
+        case FLOORW_INSN:
+        case CVTS_INSN:
+        case CVTD_INSN:
+        case CVTW_INSN:
+        case CVTL_INSN:
+            
+            if ( fp64bit ) {
+                Cyg_libm_ieee_double_shape_type s;
+
+                s.asi64 = *srcreg1;
+
+                // just try and 0 the source register if it is subnormal
+                if ( issubnormal( s ) ) {
+                    // but preserve sign
+                    if (s.number.sign)
+                        s.value = -0.0;
+                    else
+                        s.value = 0.0;
+                    *srcreg1 = s.asi64;
+                    handled++;
+                }
+            } else { // 32-bit
+                Cyg_libm_ieee_float_shape_type s;
+
+                reg2flt( srcreg1, &s );
+
+                // just try and 0 the source register if it is subnormal
+                if ( issubnormal( s ) ) {
+                    // but preserve sign
+                    if (s.number.sign)
+                        s.value = -0.0;
+                    else
+                        s.value = 0.0;
+                    flt2reg( &s, srcreg1 );
+                    handled++;
+                }
+            }
             break;
 
         default:
+            // check for floating-point compare (C.cond.fmt)
+            if ( (insn & 0x30) == 0x30 ) {
+                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++;
+                    }
+                    
+                    if (  issubnormal( s2 ) ) {  // flush to 0 and restart
+                        // but preserve sign
+                        if (s2.number.sign)
+                            s2.value = -0.0;
+                        else
+                            s2.value = 0.0;
+                        *srcreg2 = s2.asi64;
+                        handled++;
+                    }
+                    
+                } else { // 32-bit
+                    Cyg_libm_ieee_float_shape_type s1, s2;
+                    
+                    reg2flt( srcreg1, &s1 );
+                    reg2flt( srcreg2, &s2 );
+                    
+                    if ( issubnormal( s1 )) {  // flush to 0 and restart
+                        // but preserve sign
+                        if (s1.number.sign)
+                            s1.value = -0.0;
+                        else
+                            s1.value = 0.0;
+                        flt2reg( &s1, srcreg1 );
+                        handled++;
+                    }
+                    if ( issubnormal( s2 ) ) {  // flush to 0 and restart
+                        // but preserve sign
+                        if (s2.number.sign)
+                            s2.value = -0.0;
+                        else
+                            s2.value = 0.0;
+                        flt2reg( &s2, srcreg2 );
+                        handled++;
+                    }
+                } // else 
+            } // if
             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 (computational_insn && !fixedpoint)
     
-    if (handled) {
+    if ( handled != 0) {
         // 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 |
@@ -520,7 +778,7 @@ cyg_hal_mips_process_fpe( HAL_SavedRegis
 
     }
 
-    CYG_REPORT_RETVAL(handled);
+    CYG_REPORT_RETVAL( handled );
     return handled;
 } // cyg_hal_mips_process_fpe()
 
--- a/packages/hal/mips/arch/current/src/vectors.S
+++ b/packages/hal/mips/arch/current/src/vectors.S
@@ -289,11 +289,11 @@ FUNC_START(__default_exception_vsr)
 
 	move	k1,sp			# K1 = original SP
 	
-#ifdef CYG_HAL_ROM_MONITOR
+#ifdef CYGSEM_HAL_ROM_MONITOR
 	# Switch to interrupt stack to handle exception
 	la	sp,__interrupt_stack
 #endif
-			
+
 	addi	sp,sp,-mips_exception_decrement
 				# space for registers + safety margin
 
@@ -301,47 +301,47 @@ FUNC_START(__default_exception_vsr)
 
 	# store GPRs
 	.set	noat
-	sw	$0,(mipsreg_regs+0*4)(sp)
-	sw	$1,(mipsreg_regs+1*4)(sp)
-	sw	$2,(mipsreg_regs+2*4)(sp)
-	sw	$3,(mipsreg_regs+3*4)(sp)
-	sw	$4,(mipsreg_regs+4*4)(sp)
-	sw	$5,(mipsreg_regs+5*4)(sp)
-	sw	$6,(mipsreg_regs+6*4)(sp)
-	sw	$7,(mipsreg_regs+7*4)(sp)
-	sw	$8,(mipsreg_regs+8*4)(sp)
-	sw	$9,(mipsreg_regs+9*4)(sp)
-	sw	$10,(mipsreg_regs+10*4)(sp)
-	sw	$11,(mipsreg_regs+11*4)(sp)
-	sw	$12,(mipsreg_regs+12*4)(sp)
-	sw	$13,(mipsreg_regs+13*4)(sp)
-	sw	$14,(mipsreg_regs+14*4)(sp)
-	sw	$15,(mipsreg_regs+15*4)(sp)
-	sw	$16,(mipsreg_regs+16*4)(sp)
-	sw	$17,(mipsreg_regs+17*4)(sp)
-	sw	$18,(mipsreg_regs+18*4)(sp)
-	sw	$19,(mipsreg_regs+19*4)(sp)
-	sw	$20,(mipsreg_regs+20*4)(sp)
-	sw	$21,(mipsreg_regs+21*4)(sp)
-	sw	$22,(mipsreg_regs+22*4)(sp)
-	sw	$23,(mipsreg_regs+23*4)(sp)
-	sw	$24,(mipsreg_regs+24*4)(sp)
-	sw	$25,(mipsreg_regs+25*4)(sp)
-#	sw	$26,(mipsreg_regs+26*4)(sp)	# == K0
-#	sw	$27,(mipsreg_regs+27*4)(sp)	# == K1
-	sw	$28,(mipsreg_regs+28*4)(sp)	# == GP
-#	sw	$29,(mipsreg_regs+29*4)(sp)	# == SP
-	sw	$30,(mipsreg_regs+30*4)(sp)	# == FP
-	sw	$31,(mipsreg_regs+31*4)(sp)	# == RA
+	sgpr	0,sp
+	sgpr	1,sp
+	sgpr	2,sp
+	sgpr	3,sp
+	sgpr	4,sp
+	sgpr	5,sp
+	sgpr	6,sp
+	sgpr	7,sp
+	sgpr	8,sp
+	sgpr	9,sp
+	sgpr	10,sp
+	sgpr	11,sp
+	sgpr	12,sp
+	sgpr	13,sp
+	sgpr	14,sp
+	sgpr	15,sp
+	sgpr	16,sp
+	sgpr	17,sp
+	sgpr	18,sp
+	sgpr	19,sp
+	sgpr	20,sp
+	sgpr	21,sp
+	sgpr	22,sp
+	sgpr	23,sp
+	sgpr	24,sp
+	sgpr	25,sp
+#	sgpr	26,sp	# == K0
+#	sgpr	27,sp	# == K1
+	sgpr	28,sp	# == GP
+#	sgpr	29,sp	# == SP
+	sgpr	30,sp	# == FP
+	sgpr	31,sp	# == RA
 	.set	at
 	
 	mfhi	a0
 	mflo	a1
-	sw	a0,mipsreg_hi(sp)
-	sw	a1,mipsreg_lo(sp)
+	shi	a0,sp
+	slo	a1,sp
 
 	# K1 contains original SP
-	sw	k1,(mipsreg_regs+29*4)(sp)	# store in reg dump	
+	ssp	k1,sp			# store in reg dump	
 	
 	# save remaining machine state registers	
 	mfc0	t0,cause
@@ -410,47 +410,47 @@ FUNC_START(__default_interrupt_vsr)
 
 	# store GPRs
 	.set	noat
-	sw	$0,(mipsreg_regs+0*4)(sp)
-	sw	$1,(mipsreg_regs+1*4)(sp)
-	sw	$2,(mipsreg_regs+2*4)(sp)
-	sw	$3,(mipsreg_regs+3*4)(sp)
-	sw	$4,(mipsreg_regs+4*4)(sp)
-	sw	$5,(mipsreg_regs+5*4)(sp)
-	sw	$6,(mipsreg_regs+6*4)(sp)
-	sw	$7,(mipsreg_regs+7*4)(sp)
-	sw	$8,(mipsreg_regs+8*4)(sp)
-	sw	$9,(mipsreg_regs+9*4)(sp)
-	sw	$10,(mipsreg_regs+10*4)(sp)
-	sw	$11,(mipsreg_regs+11*4)(sp)
-	sw	$12,(mipsreg_regs+12*4)(sp)
-	sw	$13,(mipsreg_regs+13*4)(sp)
-	sw	$14,(mipsreg_regs+14*4)(sp)
-	sw	$15,(mipsreg_regs+15*4)(sp)
-	sw	$16,(mipsreg_regs+16*4)(sp)
-	sw	$17,(mipsreg_regs+17*4)(sp)
-	sw	$18,(mipsreg_regs+18*4)(sp)
-	sw	$19,(mipsreg_regs+19*4)(sp)
-	sw	$20,(mipsreg_regs+20*4)(sp)
-	sw	$21,(mipsreg_regs+21*4)(sp)
-	sw	$22,(mipsreg_regs+22*4)(sp)
-	sw	$23,(mipsreg_regs+23*4)(sp)
-	sw	$24,(mipsreg_regs+24*4)(sp)
-	sw	$25,(mipsreg_regs+25*4)(sp)
-#	sw	$26,(mipsreg_regs+26*4)(sp)	# == K0
-#	sw	$27,(mipsreg_regs+27*4)(sp)	# == K1
-	sw	$28,(mipsreg_regs+28*4)(sp)	# == GP
-#	sw	$29,(mipsreg_regs+29*4)(sp)	# == SP
-	sw	$30,(mipsreg_regs+30*4)(sp)	# == FP
-	sw	$31,(mipsreg_regs+31*4)(sp)	# == RA
+	sgpr	0,sp
+	sgpr	1,sp
+	sgpr	2,sp
+	sgpr	3,sp
+	sgpr	4,sp
+	sgpr	5,sp
+	sgpr	6,sp
+	sgpr	7,sp
+	sgpr	8,sp
+	sgpr	9,sp
+	sgpr	10,sp
+	sgpr	11,sp
+	sgpr	12,sp
+	sgpr	13,sp
+	sgpr	14,sp
+	sgpr	15,sp
+	sgpr	16,sp
+	sgpr	17,sp
+	sgpr	18,sp
+	sgpr	19,sp
+	sgpr	20,sp
+	sgpr	21,sp
+	sgpr	22,sp
+	sgpr	23,sp
+	sgpr	24,sp
+	sgpr	25,sp
+#	sgpr	26,sp	# == K0
+#	sgpr	27,sp	# == K1
+	sgpr	28,sp	# == GP
+#	sgpr	29,sp	# == SP
+	sgpr	30,sp	# == FP
+	sgpr	31,sp	# == RA
 	.set	at
 	
 	mfhi	a0
 	mflo	a1
-	sw	a0,mipsreg_hi(sp)
-	sw	a1,mipsreg_lo(sp)
+	shi	a0,sp
+	slo	a1,sp
 
 	# K1 contains original SP
-	sw	k1,(mipsreg_regs+29*4)(sp)	# store in reg dump	
+	ssp	k1,sp			# store in reg dump	
 		
 	mfc0	t1,status
 	mfc0	t2,cachectrl
@@ -611,8 +611,8 @@ restore_state:
 	hal_fpu_load sp
 	
 	lw	t0,mipsreg_cachectrl(sp)
-	lw	t1,mipsreg_hi(sp)
-	lw	t2,mipsreg_lo(sp)
+	lhi	t1,sp
+	llo	t2,sp
 
 	mtc0	t0,cachectrl
 	mthi	t1
@@ -620,42 +620,42 @@ restore_state:
 
 	# load GPRs
 	.set	noat
-#	lw	$0,(mipsreg_regs+0*4)(sp)
-	lw	$1,(mipsreg_regs+1*4)(sp)
-	lw	$2,(mipsreg_regs+2*4)(sp)
-	lw	$3,(mipsreg_regs+3*4)(sp)
-	lw	$4,(mipsreg_regs+4*4)(sp)
-	lw	$5,(mipsreg_regs+5*4)(sp)
-	lw	$6,(mipsreg_regs+6*4)(sp)
-	lw	$7,(mipsreg_regs+7*4)(sp)
-	lw	$8,(mipsreg_regs+8*4)(sp)
-	lw	$9,(mipsreg_regs+9*4)(sp)
-	lw	$10,(mipsreg_regs+10*4)(sp)
-	lw	$11,(mipsreg_regs+11*4)(sp)
-	lw	$12,(mipsreg_regs+12*4)(sp)
-	lw	$13,(mipsreg_regs+13*4)(sp)
-	lw	$14,(mipsreg_regs+14*4)(sp)
-	lw	$15,(mipsreg_regs+15*4)(sp)
-	lw	$16,(mipsreg_regs+16*4)(sp)
-	lw	$17,(mipsreg_regs+17*4)(sp)
-	lw	$18,(mipsreg_regs+18*4)(sp)
-	lw	$19,(mipsreg_regs+19*4)(sp)
-	lw	$20,(mipsreg_regs+20*4)(sp)
-	lw	$21,(mipsreg_regs+21*4)(sp)
-	lw	$22,(mipsreg_regs+22*4)(sp)
-	lw	$23,(mipsreg_regs+23*4)(sp)
-	lw	$24,(mipsreg_regs+24*4)(sp)
-	lw	$25,(mipsreg_regs+25*4)(sp)
-#	lw	$26,(mipsreg_regs+26*4)(sp)	# == K0
-#	lw	$27,(mipsreg_regs+27*4)(sp)	# == K1
-	lw	$28,(mipsreg_regs+28*4)(sp)	# == GP
-#	lw	$29,(mipsreg_regs+29*4)(sp)	# == SP
-	lw	$30,(mipsreg_regs+30*4)(sp)	# == FP
-	lw	$31,(mipsreg_regs+31*4)(sp)	# == RA
+#	lgpr	0,sp
+	lgpr	1,sp
+	lgpr	2,sp
+	lgpr	3,sp
+	lgpr	4,sp
+	lgpr	5,sp
+	lgpr	6,sp
+	lgpr	7,sp
+	lgpr	8,sp
+	lgpr	9,sp
+	lgpr	10,sp
+	lgpr	11,sp
+	lgpr	12,sp
+	lgpr	13,sp
+	lgpr	14,sp
+	lgpr	15,sp
+	lgpr	16,sp
+	lgpr	17,sp
+	lgpr	18,sp
+	lgpr	19,sp
+	lgpr	20,sp
+	lgpr	21,sp
+	lgpr	22,sp
+	lgpr	23,sp
+	lgpr	24,sp
+	lgpr	25,sp
+#	lgpr	26,sp	# == K0
+#	lgpr	27,sp	# == K1
+	lgpr	28,sp	# == GP
+#	lgpr	29,sp	# == SP
+	lgpr	30,sp	# == FP
+	lgpr	31,sp	# == RA
 	.set	at
 
 
-#if defined(CYG_HAL_USE_ROM_MONITOR_CYGMON)
+#if defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)
 
         # If we have a Cygmon that wants to listen to network interrupts, then
         # the return code from the earlier call to hal_default_isr() will
@@ -685,7 +685,7 @@ restore_state:
 #endif
 	lw	k0,mipsreg_pc(sp)		# K0 = return PC
 	lw	k1,mipsreg_sr(sp)		# K1 = saved SR
-	lw	sp,(mipsreg_regs+29*4)(sp)	# load SP
+	lsp	sp,sp				# load SP
 
 	# Invoke CPU specific mechanism for returning from this
 	# exception
--- a/packages/hal/mips/jmr3904/current/ChangeLog
+++ b/packages/hal/mips/jmr3904/current/ChangeLog
@@ -1,3 +1,16 @@
+2000-01-24  Jesper Skov  <jskov@cygnus.co.uk>
+
+	* include/plf_stub.h: Include correct hal/platform header.
+
+1999-12-21  Jonathan Larmour  <jlarmour@cygnus.co.uk>
+
+	* src/plf_misc.c (hal_platform_init): Rename
+	CYG_HAL_USE_ROM_MONITOR_CYGMON -> CYGSEM_HAL_USE_ROM_MONITOR_CygMon
+	(cyg_hal_user_break): Likewise. Also rationalize a little.
+
+	* include/platform.inc: Rename CYG_HAL_USE_ROM_MONITOR ->
+	CYGSEM_HAL_USE_ROM_MONITOR
+
 1999-11-25  Gary Thomas  <gthomas@cygnus.co.uk>
 
 	* include/pkgconf/mlt_mips_tx39_jmr3904_rom.h: 
--- a/packages/hal/mips/jmr3904/current/include/platform.inc
+++ b/packages/hal/mips/jmr3904/current/include/platform.inc
@@ -55,7 +55,7 @@
 
 #if	defined(CYG_HAL_STARTUP_ROM) ||			\
 	(	defined(CYG_HAL_STARTUP_RAM) &&		\
-		!defined(CYG_HAL_USE_ROM_MONITOR))
+		!defined(CYGSEM_HAL_USE_ROM_MONITOR))
 	
 	# If we are starting up from ROM, or we are starting in
 	# RAM and NOT using a ROM monitor, initialize the VSR table.
@@ -85,7 +85,7 @@
 	sw	a1,33*4(a3)
 	.endm
 	
-#elif defined(CYG_HAL_STARTUP_RAM) && defined(CYG_HAL_USE_ROM_MONITOR)
+#elif defined(CYG_HAL_STARTUP_RAM) && defined(CYGSEM_HAL_USE_ROM_MONITOR)
 
 	# Initialize the VSR table entries
 	# We only take control of the interrupt vector,
@@ -116,7 +116,7 @@
 #if defined(CYG_HAL_MIPS_SIM) ||	\
     ( defined(CYG_HAL_MIPS_TX3904) &&	\
       defined(CYG_HAL_STARTUP_RAM) &&	\
-      !defined(CYG_HAL_USE_ROM_MONITOR) \
+      !defined(CYGSEM_HAL_USE_ROM_MONITOR) \
     )
 
 ## VSR table defined in linker script
--- a/packages/hal/mips/jmr3904/current/include/plf_stub.h
+++ b/packages/hal/mips/jmr3904/current/include/plf_stub.h
@@ -44,7 +44,7 @@
 //=============================================================================
 
 #include <pkgconf/hal.h>
-#include <pkgconf/hal_tx39_jmr3904.h>
+#include <pkgconf/hal_mips_tx39_jmr3904.h>
 
 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
 
--- a/packages/hal/mips/jmr3904/current/src/plf_misc.c
+++ b/packages/hal/mips/jmr3904/current/src/plf_misc.c
@@ -85,8 +85,7 @@ void hal_platform_init(void)
 #endif
         
 #if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT)   && \
-    defined(CYG_HAL_USE_ROM_MONITOR)            && \
-    defined(CYG_HAL_USE_ROM_MONITOR_CYGMON)
+    defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)
     {
         patch_dbg_syscalls( (void *)(&hal_vsr_table[0]) );
     }
@@ -108,14 +107,11 @@ cyg_bool cyg_hal_is_break(char *buf, int
 
 void cyg_hal_user_break( CYG_ADDRWORD *regs )
 {
-#if defined(CYG_HAL_USE_ROM_MONITOR) && defined(CYG_HAL_USE_ROM_MONITOR_CYGMON)
+#if defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)
     // The following code should be at the very start of this function so
     // that it can access the RA register before it is saved and reused.
     register CYG_WORD32 ra;
     asm volatile ( "move %0,$31;" : "=r" (ra) );
-#endif    
-    
-#if defined(CYG_HAL_USE_ROM_MONITOR) && defined(CYG_HAL_USE_ROM_MONITOR_CYGMON)
 
         {
             typedef void install_bpt_fn(void *epc);
--- a/packages/hal/mips/tx39/current/ChangeLog
+++ b/packages/hal/mips/tx39/current/ChangeLog
@@ -1,3 +1,13 @@
+1999-12-21  Jonathan Larmour  <jlarmour@cygnus.co.uk>
+
+	* include/var_arch.h: Rename CYG_HAL_USE_ROM_MONITOR_CYGMON ->
+	CYGSEM_HAL_USE_ROM_MONITOR_CygMon
+
+	* src/hal_diag.c: Likewise. Also CYG_HAL_USE_ROM_MONITOR -> 
+	CYGSEM_HAL_USE_ROM_MONITOR throughout
+
+	* include/pkgconf/hal_mips_tx39.h: Fix typo
+
 1999-10-26  Nick Garnett  <nickg@cygnus.co.uk>
 
 	* include/variant.inc: Added implementations of hal_intc_translate
--- a/packages/hal/mips/tx39/current/include/pkgconf/hal_mips_tx39.h
+++ b/packages/hal/mips/tx39/current/include/pkgconf/hal_mips_tx39.h
@@ -65,7 +65,7 @@
        parent  CYGPKG_HAL_MIPS_TX39
        type    radio
        description "
-           The TMPR3904F microprocessor. This is an emedded part that in
+           The TMPR3904F microprocessor. This is an embedded part that in
            addition to the TX39 processor core has built in peripherals
            such as memory controllers, DMA controllers, serial ports and
            timers/counters."               
--- a/packages/hal/mips/tx39/current/include/var_arch.h
+++ b/packages/hal/mips/tx39/current/include/var_arch.h
@@ -47,7 +47,7 @@
 #include <pkgconf/hal.h>
 #include <cyg/infra/cyg_type.h>
 
-#ifdef CYG_HAL_USE_ROM_MONITOR_CYGMON
+#ifdef CYGSEM_HAL_USE_ROM_MONITOR_CygMon
 externC int
 hal_diag_irq_check(int vector);
 
--- a/packages/hal/mips/tx39/current/src/hal_diag.c
+++ b/packages/hal/mips/tx39/current/src/hal_diag.c
@@ -57,7 +57,7 @@
 //#define CYG_KERNEL_DIAG_LCD
 #define CYG_KERNEL_DIAG_SERIAL0 // For ROM start but see immediately below:
 
-#if defined(CYG_HAL_USE_ROM_MONITOR_CYGMON)
+#if defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)
 #undef CYG_KERNEL_DIAG_SERIAL0
 #undef CYG_KERNEL_DIAG_LCD
 #define CYG_KERNEL_DIAG_CYGMON
@@ -107,7 +107,7 @@ void hal_diag_led(int x)
 
 void hal_diag_init()
 {
-#if defined(CYG_HAL_USE_ROM_MONITOR)
+#if defined(CYGSEM_HAL_USE_ROM_MONITOR)
 // If we are using the ROM monitor, it has already
 // initialized the serial line.
 #else
@@ -201,7 +201,7 @@ void hal_diag_write_char(char c)
 #endif
 {
 #ifdef CYG_KERNEL_DIAG_GDB    
-#if 0 //defined(CYG_HAL_USE_ROM_MONITOR)
+#if 0 //defined(CYGSEM_HAL_USE_ROM_MONITOR)
 
     typedef void rom_write_fn(char c);
     rom_write_fn *fn = ((rom_write_fn **)0x80000100)[63];
@@ -287,7 +287,7 @@ void hal_diag_read_char(char *c)
 {
     for(;;)
     {
-#if defined(CYG_KERNEL_DIAG_GDB) && defined(CYG_HAL_USE_ROM_MONITOR)
+#if defined(CYG_KERNEL_DIAG_GDB) && defined(CYGSEM_HAL_USE_ROM_MONITOR)
 
         typedef void rom_read_fn(char *c);
         rom_read_fn *fn = ((rom_read_fn **)0x80000100)[62];
@@ -307,7 +307,7 @@ void hal_diag_read_char(char *c)
             breakpoint();
             continue;
         }
-#elif defined(CYG_HAL_USE_ROM_MONITOR)
+#elif defined(CYGSEM_HAL_USE_ROM_MONITOR)
         if( *c == 3 )
         {
             // Ctrl-C: breakpoint.
--- a/packages/hal/mn10300/am31/current/ChangeLog
+++ b/packages/hal/mn10300/am31/current/ChangeLog
@@ -1,3 +1,9 @@
+1999-12-21  Jonathan Larmour  <jlarmour@cygnus.co.uk>
+
+	* include/variant.inc: Rename CYG_HAL_USE_ROM_MONITOR_CYGMON ->
+	CYGSEM_HAL_USE_ROM_MONITOR_CygMon
+	Rename CYG_HAL_USE_ROM_MONITOR -> CYGSEM_HAL_USE_ROM_MONITOR
+
 1999-10-06  Jonathan Larmour  <jlarmour@cygnus.co.uk>
 
 	* src/PKGconf.mak: Don't create extras.o here any more
--- a/packages/hal/mn10300/am31/current/include/variant.inc
+++ b/packages/hal/mn10300/am31/current/include/variant.inc
@@ -283,7 +283,7 @@ led_foo3:	.byte 0x00
 	mov	d0,(0,a0)	
 	mov	d0,(4,a0)
 	mov	d0,(8,a0)
-#ifndef CYG_HAL_USE_ROM_MONITOR_CYGMON
+#ifndef CYGSEM_HAL_USE_ROM_MONITOR_CygMon
 	# When using Cygmon, leave level 3 for GDB
 	# Ctrl-C interrupts.
 	mov	d0,(12,a0)	
@@ -304,7 +304,7 @@ led_foo3:	.byte 0x00
 
 #if !(defined(CYG_HAL_STARTUP_ROM)	 	|| \
 	defined(CYGPKG_HAL_MN10300_AM31_SIM)	|| \
-	!defined(CYG_HAL_USE_ROM_MONITOR))
+	!defined(CYGSEM_HAL_USE_ROM_MONITOR))
 
 #define CYG_HAL_MN10300_VSR_TABLE_DEFINED
 
--- a/packages/hal/mn10300/stdeval1/current/ChangeLog
+++ b/packages/hal/mn10300/stdeval1/current/ChangeLog
@@ -1,3 +1,13 @@
+1999-12-21  Jonathan Larmour  <jlarmour@cygnus.co.uk>
+
+	* src/plf_misc.c (hal_platform_init): Rename
+	CYG_HAL_USE_ROM_MONITOR_CYGMON -> CYGSEM_HAL_USE_ROM_MONITOR_CygMon
+	(cyg_hal_user_break): Rename CYG_HAL_USE_ROM_MONITOR_GDB_STUBS ->
+	CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs
+
+	* src/hal_diag.c: Likewise.  Rename CYG_HAL_USE_ROM_MONITOR_SLOAD
+	-> CYGSEM_HAL_USE_ROM_MONITOR_Sload throughout
+
 1999-11-25  Gary Thomas  <gthomas@cygnus.co.uk>
 
 	* include/pkgconf/mlt_mn10300_am31_stdeval1_rom.h: 
--- a/packages/hal/mn10300/stdeval1/current/src/hal_diag.c
+++ b/packages/hal/mn10300/stdeval1/current/src/hal_diag.c
@@ -64,7 +64,7 @@
 
 #  if defined(CYG_HAL_STARTUP_RAM)
 
-#   if defined(CYG_HAL_USE_ROM_MONITOR_CYGMON)
+#   if defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)
 
      // If loaded into RAM via CYGMON we diag via
      // serial 2 using GDB protocol
@@ -72,14 +72,14 @@
 #    define CYG_KERNEL_DIAG_SERIAL2
 #    define CYG_KERNEL_DIAG_GDB
 
-#   elif defined(CYG_HAL_USE_ROM_MONITOR_SLOAD)
+#   elif defined(CYGSEM_HAL_USE_ROM_MONITOR_Sload)
 
      // If loaded into RAM via SLOAD we diag via
      // serial 1
     
 #    define CYG_KERNEL_DIAG_SERIAL1
     
-#   elif defined(CYG_HAL_USE_ROM_MONITOR_GDB_STUBS)
+#   elif defined(CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs)
 
      // If loaded into RAM via GDB STUB ROM we diag via
      // serial 1 using GDB protocol
@@ -87,7 +87,7 @@
 #    define CYG_KERNEL_DIAG_SERIAL1
 #    define CYG_KERNEL_DIAG_GDB
     
-#   endif // defined(CYG_HAL_USE_ROM_MONITOR_CYGMON)
+#   endif // defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)
     
 #  elif defined(CYG_HAL_STARTUP_ROM)
 
@@ -335,7 +335,7 @@ void led(int x)
 
 void hal_diag_init_serial2(void)
 {
-#if !defined(CYG_HAL_USE_ROM_MONITOR_CYGMON)    
+#if !defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)
 
     // 16 and 22 translate to 38400 baud.
     *TIMER2_BR = 16;
--- a/packages/hal/mn10300/stdeval1/current/src/plf_misc.c
+++ b/packages/hal/mn10300/stdeval1/current/src/plf_misc.c
@@ -67,8 +67,7 @@ void hal_platform_init(void)
 
 #if defined(CYGPKG_KERNEL)                      && \
     defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT)   && \
-    defined(CYG_HAL_USE_ROM_MONITOR)            && \
-    defined(CYG_HAL_USE_ROM_MONITOR_CYGMON)
+    defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)
     {
         extern CYG_ADDRESS hal_virtual_vector_table[32];
         extern void patch_dbg_syscalls(void * vector);
@@ -92,7 +91,7 @@ cyg_bool cyg_hal_is_break(char *buf, int
 void cyg_hal_user_break( CYG_ADDRWORD *regs )
 {
 
-#if defined(CYG_HAL_USE_ROM_MONITOR) && defined(CYG_HAL_USE_ROM_MONITOR_GDB_STUBS)
+#if defined(CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs)
 
         {
             extern CYG_ADDRESS hal_virtual_vector_table[64];        
--- a/packages/hal/powerpc/arch/current/ChangeLog
+++ b/packages/hal/powerpc/arch/current/ChangeLog
@@ -1,3 +1,8 @@
+2000-01-24  Jesper Skov  <jskov@cygnus.co.uk>
+
+	* src/hal_misc.c: Depend on CYGSEM_HAL_ROM_MONITOR instead of
+	CYG_HAL_ROM_MONITOR.
+
 1999-09-28  Jesper Skov  <jskov@cygnus.co.uk>
 
 	* tests/intr0.c: Added some more debug output.
--- a/packages/hal/powerpc/arch/current/src/hal_misc.c
+++ b/packages/hal/powerpc/arch/current/src/hal_misc.c
@@ -478,7 +478,7 @@ externC void hal_MMU_init (void)
 #endif
 
 #ifdef CYGPKG_HAL_POWERPC_MBX           // Enable all caches for MBX860
-# ifndef CYG_HAL_ROM_MONITOR            // unless we are making a stub rom
+# ifndef CYGSEM_HAL_ROM_MONITOR         // unless we are making a stub rom
 #  define CYGPRI_INIT_CACHES 1
 #  define CYGPRI_ENABLE_CACHES 1
 # endif
--- a/packages/hal/powerpc/mbx/current/ChangeLog
+++ b/packages/hal/powerpc/mbx/current/ChangeLog
@@ -1,3 +1,7 @@
+2000-01-24  Jesper Skov  <jskov@cygnus.co.uk>
+	* src/mbx.S: Depend on CYGSEM_HAL_ROM_MONITOR instead of
+	CYG_HAL_ROM_MONITOR.
+
 1999-11-25  Gary Thomas  <gthomas@cygnus.co.uk>
 
 	* include/pkgconf/mlt_powerpc_mbx_rom.h: 
--- a/packages/hal/powerpc/mbx/current/src/mbx.S
+++ b/packages/hal/powerpc/mbx/current/src/mbx.S
@@ -71,7 +71,7 @@
 # define CYGPRI_DO_PROGRAM_UPMS
 #endif
 
-#if defined(CYGPRI_RAM_START_PROGRAMS_UPMS) && defined(CYG_HAL_ROM_MONITOR)
+#if defined(CYGPRI_RAM_START_PROGRAMS_UPMS) && defined(CYGSEM_HAL_ROM_MONITOR)
 /* use old tables in a StubROM build iff RAM start will reprogram them */
 # define CYGPRI_USE_OLD_UPM_TABLES
 #endif
@@ -558,7 +558,7 @@ FUNC_END( hal_hardware_init )
 #else // !CYGPRI_USE_OLD_UPM_TABLES: use the NEW TABLES
 
 	// for RAM startup or ROM application when NOT making a stub rom,
-	// ie. CYG_HAL_ROM_MONITOR not defined.
+	// ie. CYGSEM_HAL_ROM_MONITOR not defined.
 
 #ifdef __40MHZ
 	/* UPM contents for 40MHz clk. DRAM: EDO,4K,60ns */
@@ -611,7 +611,7 @@ FUNC_END( hal_hardware_init )
 	.long	0xffffc007, 0xffffc007, 0xffffc007, 0xffffc007
 #endif
 #endif	// OLD/NEW TABLES == CYGPRI_USE_OLD_UPM_TABLES or not.
-	// depending on CYG_HAL_ROM_MONITOR and whether RAM
+	// depending on CYGSEM_HAL_ROM_MONITOR and whether RAM
 	// start re-initializes.
 	
 __upmtbl_end:
--- a/packages/io/serial/current/ChangeLog
+++ b/packages/io/serial/current/ChangeLog
@@ -1,3 +1,32 @@
+2000-01-17  Gary Thomas  <gthomas@cygnus.co.uk>
+
+	* src/common/tty.c (tty_read): Avoid echoing "backspace/erase" at
+	start of line.
+
+2000-01-05  Gary Thomas  <gthomas@cygnus.co.uk>
+
+	* src/common/serial.c (serial_write): Avoid potential deadlock if
+	transmit start actually sends enough characters to signal cond wait.
+
+2000-01-03  Gary Thomas  <gthomas@cygnus.co.uk>
+
+	* include/serial.h: Fix namespace pollution - 
+	serial_devio => cyg_io_serial_devio
+	serial_callbacks => cyg_io_serial_callbacks
+
+	* src/mips/tx3904_serial.c: 
+	* src/mn10300/mn10300_serial.c: 
+	* src/powerpc/quicc_smc_serial.c: 
+	* src/powerpc/cogent_serial_with_ints.c: 
+	* src/sparclite/sleb_sdtr.c: 
+	* src/arm/aeb_serial.c: 
+	* src/arm/pid_serial_with_ints.c: 
+	* src/arm/edb7xxx_serial.c: 
+	* src/arm/cma230_serial.c: 
+	* src/common/haldiag.c: 
+	* src/common/serial.c: Fix namespace pollution - 
+	serial_devio => cyg_io_serial_devio
+
 1999-12-06  Gary Thomas  <gthomas@cygnus.co.uk>
 
 	* src/arm/pid_serial_with_ints.c (pid_serial_DSR): Add loop to handle
--- a/packages/io/serial/current/include/serial.h
+++ b/packages/io/serial/current/include/serial.h
@@ -69,7 +69,7 @@ serial_callbacks_t _l = {               
     _rcv_char                                           \
 };
 
-extern serial_callbacks_t serial_callbacks;
+extern serial_callbacks_t cyg_io_serial_callbacks;
 
 typedef struct {
     unsigned char           *data;
@@ -105,7 +105,7 @@ struct serial_channel {
                        _baud, _stop, _parity, _word_length, _flags)     \
 serial_channel _l = {                                                   \
     &_funs,                                                             \
-    &serial_callbacks,                                                  \
+    &cyg_io_serial_callbacks,                                           \
     &(_dev_priv),                                                       \
     CYG_SERIAL_INFO_INIT(_baud, _stop, _parity, _word_length, _flags),  \
 };
@@ -118,7 +118,7 @@ serial_channel _l = {                   
                        _in_buf, _in_buflen)                             \
 serial_channel _l = {                                                   \
     &_funs,                                                             \
-    &serial_callbacks,                                                  \
+    &cyg_io_serial_callbacks,                                           \
     &(_dev_priv),                                                       \
     CYG_SERIAL_INFO_INIT(_baud, _stop, _parity, _word_length, _flags),  \
     false,                                                              \
@@ -149,6 +149,6 @@ serial_funs _l = {                      
   _stop_xmit                                                            \
 };
 
-extern cyg_devio_table_t serial_devio;
+extern cyg_devio_table_t cyg_io_serial_devio;
 
 #endif // CYGONCE_SERIAL_H
--- a/packages/io/serial/current/src/arm/aeb_serial.c
+++ b/packages/io/serial/current/src/arm/aeb_serial.c
@@ -113,7 +113,7 @@ static SERIAL_CHANNEL(aeb_serial_channel
 DEVTAB_ENTRY(aeb_serial_io0, 
              CYGDAT_IO_SERIAL_ARM_AEB_SERIAL0_NAME,
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              aeb_serial_init, 
              aeb_serial_lookup,     // Serial driver may need initializing
              &aeb_serial_channel0
@@ -153,7 +153,7 @@ static SERIAL_CHANNEL(aeb_serial_channel
 DEVTAB_ENTRY(aeb_serial_io1, 
              CYGDAT_IO_SERIAL_ARM_AEB_SERIAL1_NAME,
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              aeb_serial_init, 
              aeb_serial_lookup,     // Serial driver may need initializing
              &aeb_serial_channel1
--- a/packages/io/serial/current/src/arm/cma230_serial.c
+++ b/packages/io/serial/current/src/arm/cma230_serial.c
@@ -114,7 +114,7 @@ static SERIAL_CHANNEL(cma230_serial_chan
 DEVTAB_ENTRY(cma230_serial_io0, 
              CYGDAT_IO_SERIAL_ARM_CMA230_SERIAL_A_NAME,
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              cma230_serial_init, 
              cma230_serial_lookup,     // Serial driver may need initializing
              &cma230_serial_channel0
@@ -154,7 +154,7 @@ static SERIAL_CHANNEL(cma230_serial_chan
 DEVTAB_ENTRY(cma230_serial_io1, 
              CYGDAT_IO_SERIAL_ARM_CMA230_SERIAL_B_NAME,
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              cma230_serial_init, 
              cma230_serial_lookup,     // Serial driver may need initializing
              &cma230_serial_channel1
--- a/packages/io/serial/current/src/arm/edb7xxx_serial.c
+++ b/packages/io/serial/current/src/arm/edb7xxx_serial.c
@@ -132,7 +132,7 @@ static SERIAL_CHANNEL(edb7xxx_serial_cha
 DEVTAB_ENTRY(edb7xxx_serial_io1, 
              CYGDAT_IO_SERIAL_ARM_EDB7XXX_SERIAL1_NAME,
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              edb7xxx_serial_init, 
              edb7xxx_serial_lookup,     // Serial driver may need initializing
              &edb7xxx_serial_channel1
@@ -177,7 +177,7 @@ static SERIAL_CHANNEL(edb7xxx_serial_cha
 DEVTAB_ENTRY(edb7xxx_serial_io2, 
              CYGDAT_IO_SERIAL_ARM_EDB7XXX_SERIAL2_NAME,
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              edb7xxx_serial_init, 
              edb7xxx_serial_lookup,     // Serial driver may need initializing
              &edb7xxx_serial_channel2
--- a/packages/io/serial/current/src/arm/pid_serial_with_ints.c
+++ b/packages/io/serial/current/src/arm/pid_serial_with_ints.c
@@ -111,7 +111,7 @@ static SERIAL_CHANNEL(pid_serial_channel
 DEVTAB_ENTRY(pid_serial_io0, 
              CYGDAT_IO_SERIAL_ARM_PID_SERIAL0_NAME,
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              pid_serial_init, 
              pid_serial_lookup,     // Serial driver may need initializing
              &pid_serial_channel0
@@ -150,7 +150,7 @@ static SERIAL_CHANNEL(pid_serial_channel
 DEVTAB_ENTRY(pid_serial_io1, 
              CYGDAT_IO_SERIAL_ARM_PID_SERIAL1_NAME,
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              pid_serial_init, 
              pid_serial_lookup,     // Serial driver may need initializing
              &pid_serial_channel1
--- a/packages/io/serial/current/src/common/haldiag.c
+++ b/packages/io/serial/current/src/common/haldiag.c
@@ -62,7 +62,7 @@ static SERIAL_FUNS(haldiag_funs,
     );
 
 static int _no_data;
-SERIAL_CHANNEL(haldiag_channel0,
+static SERIAL_CHANNEL(haldiag_channel0,
                haldiag_funs, 
                _no_data,
                CYG_SERIAL_BAUD_DEFAULT,
@@ -74,7 +74,7 @@ SERIAL_CHANNEL(haldiag_channel0,
 DEVTAB_ENTRY(haldiag_io0, 
              "/dev/haldiag",
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              haldiag_init, 
              0,                     // No initialization/lookup needed
              &haldiag_channel0);
--- a/packages/io/serial/current/src/common/serial.c
+++ b/packages/io/serial/current/src/common/serial.c
@@ -50,7 +50,7 @@ static Cyg_ErrNo serial_read(cyg_io_hand
 static Cyg_ErrNo serial_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *buf, cyg_uint32 *len);
 static Cyg_ErrNo serial_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *buf, cyg_uint32 *len);
 
-DEVIO_TABLE(serial_devio,
+DEVIO_TABLE(cyg_io_serial_devio,
             serial_write,
             serial_read,
             serial_get_config,
@@ -60,7 +60,7 @@ DEVIO_TABLE(serial_devio,
 static void serial_init(serial_channel *chan);
 static void serial_xmt_char(serial_channel *chan);
 static void serial_rcv_char(serial_channel *chan, unsigned char c);
-SERIAL_CALLBACKS(serial_callbacks, 
+SERIAL_CALLBACKS(cyg_io_serial_callbacks, 
                  serial_init, 
                  serial_xmt_char, 
                  serial_rcv_char);
@@ -121,9 +121,12 @@ serial_write(cyg_io_handle_t handle, con
                 cbuf->waiting = true;
                 // Buffer full - wait for space
                 (funs->start_xmit)(chan);  // Make sure xmit is running
-                cbuf->pending += size;  // Have this much more to send [eventually]
-                cyg_drv_cond_wait(&cbuf->wait);
-                cbuf->pending -= size;
+                if (cbuf->waiting) {
+                    // Note: 'start_xmit' may have obviated the need to wait :-)
+                    cbuf->pending += size;  // Have this much more to send [eventually]
+                    cyg_drv_cond_wait(&cbuf->wait);
+                    cbuf->pending -= size;
+                }
                 if (cbuf->abort) {
                     // Give up!
                     cbuf->abort = false;
--- a/packages/io/serial/current/src/common/tty.c
+++ b/packages/io/serial/current/src/common/tty.c
@@ -208,8 +208,9 @@ tty_read(cyg_io_handle_t handle, void *_
         if ((priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_BINARY) == 0) {
             if ((c == '\b') || (c == 0x7F)) {
                 size -= 2;  // erase one character + 'backspace' char
-                if (size < 0) size = 0;
-                if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_ECHO) {
+                if (size < 0) {
+                    size = 0;
+                } else if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_ECHO) {
                     clen = 3;
                     cyg_io_write(chan, "\b \b", &clen);
                 }
--- a/packages/io/serial/current/src/mips/tx3904_serial.c
+++ b/packages/io/serial/current/src/mips/tx3904_serial.c
@@ -325,7 +325,7 @@ static SERIAL_CHANNEL(tx3904_serial_chan
 DEVTAB_ENTRY(tx3904_serial_io0, 
              CYGDAT_IO_SERIAL_TX39_JMR3904_SERIAL0_NAME,
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              tx3904_serial_init, 
              tx3904_serial_lookup,     // Serial driver may need initializing
              &tx3904_serial_channel0
@@ -336,7 +336,7 @@ DEVTAB_ENTRY(tx3904_serial_io0,
 DEVTAB_ENTRY(tx3904_serial_io1, 
              CYGDAT_IO_SERIAL_TX39_JMR3904_SERIAL1_NAME,
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              tx3904_serial_init, 
              tx3904_serial_lookup,     // Serial driver may need initializing
              &tx3904_serial_channel1
--- a/packages/io/serial/current/src/mn10300/mn10300_serial.c
+++ b/packages/io/serial/current/src/mn10300/mn10300_serial.c
@@ -452,7 +452,7 @@ static SERIAL_CHANNEL(mn10300_serial_cha
 DEVTAB_ENTRY(mn10300_serial_io0, 
              CYGDAT_IO_SERIAL_MN10300_SERIAL0_NAME,
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              mn10300_serial_init, 
              mn10300_serial_lookup,     // Serial driver may need initializing
              &mn10300_serial_channel0
@@ -464,7 +464,7 @@ DEVTAB_ENTRY(mn10300_serial_io0,
 DEVTAB_ENTRY(mn10300_serial_io1, 
              CYGDAT_IO_SERIAL_MN10300_SERIAL1_NAME,
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              mn10300_serial_init, 
              mn10300_serial_lookup,     // Serial driver may need initializing
              &mn10300_serial_channel1
@@ -475,7 +475,7 @@ DEVTAB_ENTRY(mn10300_serial_io1,
 DEVTAB_ENTRY(mn10300_serial_io2, 
              CYGDAT_IO_SERIAL_MN10300_SERIAL2_NAME,
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              mn10300_serial_init, 
              mn10300_serial_lookup,     // Serial driver may need initializing
              &mn10300_serial_channel2
--- a/packages/io/serial/current/src/powerpc/cogent_serial_with_ints.c
+++ b/packages/io/serial/current/src/powerpc/cogent_serial_with_ints.c
@@ -130,7 +130,7 @@ static SERIAL_CHANNEL(cogent_serial_chan
 DEVTAB_ENTRY(cogent_serial_io0, 
              CYGDAT_IO_SERIAL_POWERPC_COGENT_SERIAL_A_NAME,
              0,                 // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              cogent_serial_init, 
              cogent_serial_lookup,     // Serial driver may need initializing
              &cogent_serial_channel0
@@ -172,7 +172,7 @@ static SERIAL_CHANNEL(cogent_serial_chan
 DEVTAB_ENTRY(cogent_serial_io1, 
              CYGDAT_IO_SERIAL_POWERPC_COGENT_SERIAL_B_NAME,
              0,                   // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              cogent_serial_init, 
              cogent_serial_lookup,     // Serial driver may need initializing
              &cogent_serial_channel1
--- a/packages/io/serial/current/src/powerpc/quicc_smc_serial.c
+++ b/packages/io/serial/current/src/powerpc/quicc_smc_serial.c
@@ -157,7 +157,7 @@ static unsigned char quicc_smc1_rxbuf[CY
 DEVTAB_ENTRY(quicc_smc_serial_io1, 
              CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_NAME,
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              quicc_smc_serial_init, 
              quicc_smc_serial_lookup,     // Serial driver may need initializing
              &quicc_smc_serial_channel1
@@ -201,7 +201,7 @@ static unsigned char quicc_smc2_rxbuf[CY
 DEVTAB_ENTRY(quicc_smc_serial_io2, 
              CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_NAME,
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              quicc_smc_serial_init, 
              quicc_smc_serial_lookup,     // Serial driver may need initializing
              &quicc_smc_serial_channel2
--- a/packages/io/serial/current/src/sparclite/sleb_sdtr.c
+++ b/packages/io/serial/current/src/sparclite/sleb_sdtr.c
@@ -121,7 +121,7 @@ static SERIAL_CHANNEL(sleb_sdtr_channel0
 DEVTAB_ENTRY(sleb_sdtr_io0, 
              CYGDAT_IO_SERIAL_SPARCLITE_SLEB_CON1_NAME,
              0,                     // Does not depend on a lower level interface
-             &serial_devio, 
+             &cyg_io_serial_devio, 
              sleb_sdtr_init, 
              sleb_sdtr_lookup,     // Serial driver may need initializing
              &sleb_sdtr_channel0
--- a/packages/kernel/current/ChangeLog
+++ b/packages/kernel/current/ChangeLog
@@ -1,3 +1,58 @@
+2000-01-19  Jesper Skov  <jskov@cygnus.co.uk>
+	CR 902054
+	* tests/stress_threads.c: Don't assert requested priority =
+	allocated. Allow some flexibility of handler priorities.
+
+2000-01-13  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* tests/mutex3.cxx (control_thread): Add a CYG_TEST_INIT();
+	Whoops!
+
+2000-01-11  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* tests/mutex3.cxx: New test case.  It tests mutex prio
+	inheritance - or not - in a multiple thread manner, depending only
+	on delays and the clock, so it tests that scheduling does the
+	right thing, rather than simply checking reported priorities.
+
+	* tests/PKGconf.mak: Add new kernel test mutex3, put in to test
+	RELAY prio inheritance extension.
+
+2000-01-11  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* include/pkgconf/kernel.h: New config option added,
+	(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE_RELAY).
+	It is a child of ..._PRIORITY_INHERITANCE_SIMPLE and is really
+	only there to turn off if you really want the old implementation.
+
+	* src/sync/mutex.cxx (unlock): Add call to
+	Cyg_SchedThread::relay_priority() when relinquishing the mutex, in
+	order to relay any raised priority to the new owner.  Also count
+	the mutex we are waiting for as well as those held for correct
+	recovery in the case of inheriting priority then being killed, for
+	example.
+
+	* include/sched.hxx (class Cyg_SchedThread::relay_priority): New
+	member function declared.
+
+	* src/sched/sched.cxx (Cyg_SchedThread::relay_priority): New
+	member function to implement pass-it-on or "discovered ceiling"
+	priority inheritance extension to the simple algorithm.  Also use
+	get_current_priority() in Cyg_SchedThread::inherit_priority() to
+	let this work.
+
+2000-01-11  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* include/clock.hxx (class Cyg_Counter::counter): make the counter
+	volatile, otherwise a busy-wait loop for the real time clock to
+	change never completes.
+
+1999-12-23  Hugo Tyson  <hmt@cygnus.co.uk>
+
+	* src/sched/sched.cxx (inherit_priority): Fix bug; inheriting a
+	2nd time would overwrite the saved initial_priority, so
+	disinheriting had no effect.
+
 1999-12-13  Jonathan Larmour  <jlarmour@cygnus.co.uk>
 
 	* tests/tm_basic.cxx (run_alarm_tests): Add new measurement of
@@ -2491,7 +2546,8 @@ Wed Mar 11 13:18:17 GMT 1998  Chris Prov
 // 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.
+// by Cygnus are Copyright (C) 1998,1999,2000 Cygnus Solutions.
+// All Rights Reserved.
 // -------------------------------------------
 //
 //####COPYRIGHTEND####
--- a/packages/kernel/current/include/clock.hxx
+++ b/packages/kernel/current/include/clock.hxx
@@ -25,7 +25,8 @@
 // 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.
+// by Cygnus are Copyright (C) 1998,1999,2000 Cygnus Solutions.
+// All Rights Reserved.
 // -------------------------------------------
 //
 //####COPYRIGHTEND####
@@ -72,7 +73,7 @@ class Cyg_Counter
     
 #endif
 
-    cyg_tick_count      counter;        // counter value
+    volatile cyg_tick_count counter;    // counter value
 
     cyg_uint32          increment;      // increment per tick
     
--- a/packages/kernel/current/include/pkgconf/kernel.h
+++ b/packages/kernel/current/include/pkgconf/kernel.h
@@ -24,7 +24,8 @@
 // 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.
+// by Cygnus are Copyright (C) 1998,1999,2000 Cygnus Solutions.
+// All Rights Reserved.
 // -------------------------------------------
 //
 //####COPYRIGHTEND####
@@ -723,6 +724,18 @@
      doc ref/ecos-ref/synchronization.html#MUTEXES
  }
 
+ cdl_option CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE_RELAY {
+     display    "Relay enhancement to simple mutex priority inheritance"
+     parent     CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE
+     description "
+         This option enables an extension to the simple implementation of
+         mutex priority inheritance whereby a thread releasing a mutex to a
+         waiting thread relays its own priority to the new owner if there
+         are still further threads waiting.  This can be viewed as a
+         discovered priority ceiling."
+     doc ref/ecos-ref/synchronization.html#MUTEXES
+ }
+
  cdl_option CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT {
      display    "Message box blocking put support"
      parent     CYGPKG_KERNEL_SYNCH
@@ -771,6 +784,7 @@
  */
 
 #define CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE
+#define CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE_RELAY
 #define CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
 #define CYGNUM_KERNEL_SYNCH_MBOX_QUEUE_SIZE     10
 #define CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT
--- a/packages/kernel/current/include/sched.hxx
+++ b/packages/kernel/current/include/sched.hxx
@@ -25,7 +25,8 @@
 // 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.
+// by Cygnus are Copyright (C) 1998,1999,2000 Cygnus Solutions.
+// All Rights Reserved.
 // -------------------------------------------
 //
 //####COPYRIGHTEND####
@@ -166,8 +167,10 @@ public:
 
 private:
 
-    // For all priority inheritance mechanisms we need to
-    // keep track of how many mutexes we have locked.
+    // For all priority inheritance mechanisms we need to keep track of how
+    // many mutexes we have locked, including one which we are waiting to
+    // lock, because we can inherit priority while sleeping just prior to
+    // wakeup.
     cyg_count32         mutex_count;
 
 public:    
@@ -194,6 +197,10 @@ public:
     // has higher priority than this.
     void inherit_priority( Cyg_Thread *thread);
 
+    // Relay the priority of the ex-owner thread or from the queue if it
+    // has a higher priority than ours.
+    void relay_priority( Cyg_Thread *ex_owner, Cyg_ThreadQueue *pqueue);
+
     // Lose priority inheritance
     void disinherit_priority();
     
--- a/packages/kernel/current/src/sched/sched.cxx
+++ b/packages/kernel/current/src/sched/sched.cxx
@@ -22,7 +22,8 @@
 // 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.
+// by Cygnus are Copyright (C) 1998,1999,2000 Cygnus Solutions.
+// All Rights Reserved.
 // -------------------------------------------
 //
 //####COPYRIGHTEND####
@@ -313,33 +314,59 @@ void Cyg_SchedThread::inherit_priority( 
     CYG_ASSERT( mutex_count > 0, "Non-positive mutex count");
     CYG_ASSERT( self != thread, "Trying to inherit from self!");
     
-    if( thread->get_priority() < priority )
+    // Compare with *current* priority in case thread has already
+    // inherited - for relay case below.
+    if( thread->get_current_priority() < priority )
     {
         cyg_priority mypri = priority;
+        cyg_bool already_inherited = priority_inherited;
 
-        if( !priority_inherited )
-        {
-            // If this is first inheritance, copy the old pri
-            // and set inherited flag. We do this after setting the
-            // pri since set_priority() is inheritance aware.
+        // If this is first inheritance, copy the old pri
+        // and set inherited flag. We clear it before setting the
+        // pri since set_priority() is inheritance aware.
+        // This is called with the sched locked, so no race conditions.
 
-            self->set_priority( thread->get_priority() );
-            priority_inherited = true,
+        priority_inherited = false;     // so that set_prio DTRT
+
+        self->set_priority( thread->get_current_priority() );            
+
+        if( !already_inherited )
             original_priority = mypri;
-        }
-        else
-        {
-            // Already in inherited state, and new pri is higher
-            // than old. Just change the pri.
-            
-            self->set_priority( thread->get_priority() );            
-        }
+
+        priority_inherited = true;      // regardless, because it is now
+
     }
 
 #endif
 }
 
 // -------------------------------------------------------------------------
+// Inherit the priority of the ex-owner thread or from the queue if it
+// has a higher priority than ours.
+
+void Cyg_SchedThread::relay_priority( Cyg_Thread *ex_owner, Cyg_ThreadQueue *pqueue)
+{
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE
+
+    // A simple implementation of priority inheritance.
+    // At its simplest, this member does nothing.
+
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE_RELAY
+
+    // If there is anyone else waiting, then the *new* owner inherits from
+    // the current one, since that is a maxima of the others waiting.
+    // (It's worth not doing if there's nobody waiting to prevent
+    // unneccessary priority skew.)  This could be viewed as a discovered
+    // priority ceiling.
+
+    if ( !pqueue->empty() )
+        inherit_priority( ex_owner );
+
+#endif
+#endif
+}
+
+// -------------------------------------------------------------------------
 // Lose a priority inheritance
 
 void Cyg_SchedThread::disinherit_priority()
@@ -357,6 +384,13 @@ void Cyg_SchedThread::disinherit_priorit
     // should be negligible. The most important advantage of this
     // algorithm is that it is fast and deterministic.
     
+    // The simplest algorithm also does not cause a 2nd owner (who waited)
+    // of a mutex to inherit from 3rd, 4th &c threads that are queueing up
+    // when it is awoken.  That limitation is avoided when
+    // CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE_RELAY is also
+    // enabled, see above, which passes the raised priority from one thread
+    // to the next along with the mutex, like a relay baton.
+
     Cyg_Thread *self = CYG_CLASSFROMBASE(Cyg_Thread,
                                          Cyg_SchedThread,
                                          this);
@@ -376,7 +410,7 @@ void Cyg_SchedThread::disinherit_priorit
 #endif    
 }
 
-#endif
+#endif // CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE of any kind
 
 // -------------------------------------------------------------------------
 // EOF sched/sched.cxx
--- a/packages/kernel/current/src/sync/mutex.cxx
+++ b/packages/kernel/current/src/sync/mutex.cxx
@@ -22,7 +22,8 @@
 // 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.
+// by Cygnus are Copyright (C) 1998,1999,2000 Cygnus Solutions.
+// All Rights Reserved.
 // -------------------------------------------
 //
 //####COPYRIGHTEND####
@@ -133,6 +134,12 @@ Cyg_Mutex::lock(void)
     // thread grabbing the mutex between the wakeup in unlock() and
     // this thread actually starting.
     
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE
+
+    self->count_mutex();
+
+#endif
+
     while( locked && result )
     {
         CYG_ASSERT( self != owner, "Locking mutex I already own");
@@ -182,14 +189,15 @@ Cyg_Mutex::lock(void)
         locked      = true;
         owner       = self;
 
-#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE
-
-        self->count_mutex();
-
-#endif
-
         CYG_INSTRUMENT_MUTEX(LOCKED, this, 0);
     }
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE
+    else
+    {
+        self->uncount_mutex();
+        self->disinherit_priority();
+    }
+#endif
     
     // Unlock the scheduler and maybe switch threads
     Cyg_Scheduler::unlock();
@@ -259,6 +267,32 @@ Cyg_Mutex::unlock(void)
     CYG_ASSERT( locked, "Unlock mutex that is not locked");
     CYG_ASSERT( owner == Cyg_Thread::self(), "Unlock mutex I do not own");
         
+    if( !queue.empty() ) {
+
+        // The queue is non-empty, so grab the next
+        // thread from it and wake it up.
+
+        Cyg_Thread *thread = queue.dequeue();
+
+        CYG_ASSERTCLASS( thread, "Bad thread pointer");
+
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE
+
+        // Give the owner-to-be a chance to inherit from the remaining
+        // queue or the relinquishing thread:
+
+        thread->relay_priority(owner, &queue);
+
+#endif
+
+        thread->set_wake_reason( Cyg_Thread::DONE );
+        
+        thread->wake();
+
+        CYG_INSTRUMENT_MUTEX(WAKE, this, thread);
+        
+    }
+
 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE
 
     owner->uncount_mutex();
@@ -269,23 +303,6 @@ Cyg_Mutex::unlock(void)
     locked      = false;
     owner       = NULL;
     
-    if( !queue.empty() ) {
-
-        // The queue is non-empty, so grab the next
-        // thread from it and wake it up.
-
-        Cyg_Thread *thread = queue.dequeue();
-
-        CYG_ASSERTCLASS( thread, "Bad thread pointer");
-
-        thread->set_wake_reason( Cyg_Thread::DONE );
-        
-        thread->wake();
-
-        CYG_INSTRUMENT_MUTEX(WAKE, this, thread);
-        
-    }
-
     CYG_ASSERTCLASS( this, "Bad this pointer");    
     
     // Unlock the scheduler and maybe switch threads
--- a/packages/kernel/current/tests/PKGconf.mak
+++ b/packages/kernel/current/tests/PKGconf.mak
@@ -22,7 +22,8 @@
 # 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.
+# by Cygnus are Copyright (C) 1998,1999,2000 Cygnus Solutions.
+# All Rights Reserved.
 # -------------------------------------------
 #
 #####COPYRIGHTEND####
@@ -37,7 +38,7 @@ TESTS	      := bin_sem0 bin_sem1 bin_sem
 	         kclock0 kclock1 kexcept1 kintr0 kmbox1 kmemfix1 kmemvar1 \
 		 kmutex0 kmutex1 ksched1 ksem0 ksem1 kflag0 kflag1 \
 		 kthread0 kthread1 mbox1 memfix1 memfix2 memvar1 memvar2\
-		 mutex0 mutex1 mutex2 sched1 sync2 sync3 \
+		 mutex0 mutex1 mutex2 mutex3 sched1 sync2 sync3 \
 		 thread0 thread1 thread2 release kill thread_gdb \
 		 tm_basic dhrystone
 
new file mode 100644
--- /dev/null
+++ b/packages/kernel/current/tests/mutex3.cxx
@@ -0,0 +1,562 @@
+//==========================================================================
+//
+//        mutex3.cxx
+//
+//        Mutex test 3 - priority inheritance
+//
+//==========================================================================
+//####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,2000 Cygnus Solutions.
+// All Rights Reserved.
+// -------------------------------------------
+//
+//####COPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     hmt
+// Contributors:  hmt
+// Date:          2000-01-06
+// Description:   Tests mutex priority inheritance
+//####DESCRIPTIONEND####
+
+#include <pkgconf/kernel.h>
+
+#include <cyg/kernel/sched.hxx>        // Cyg_Scheduler::start()
+#include <cyg/kernel/thread.hxx>       // Cyg_Thread
+
+#include <cyg/kernel/mutex.hxx>
+
+#include <cyg/infra/testcase.h>
+
+#include <cyg/kernel/sched.inl>
+#include <cyg/kernel/thread.inl>
+
+#include <cyg/infra/diag.h>             // diag_printf
+
+// ------------------------------------------------------------------------
+//
+// These checks should be enough; any other scheduler which has priorities
+// should manifest as having no priority inheritance, but otherwise fine,
+// so the test should work correctly.
+
+#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK) &&    \
+    (CYGNUM_KERNEL_SCHED_PRIORITIES > 20)
+
+// ------------------------------------------------------------------------
+// Management functions
+//
+// Stolen from testaux.hxx and copied in here because I want to be able to
+// reset the world also.
+
+#define NTHREADS 7
+
+static inline void *operator new(size_t size, void *ptr) { return ptr; };
+
+#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
+
+static Cyg_Thread *thread[NTHREADS] = { 0 };
+
+typedef CYG_WORD64 CYG_ALIGNMENT_TYPE;
+
+static CYG_ALIGNMENT_TYPE thread_obj[NTHREADS] [
+   (sizeof(Cyg_Thread)+sizeof(CYG_ALIGNMENT_TYPE)-1)
+     / sizeof(CYG_ALIGNMENT_TYPE)                     ];
+
+static CYG_ALIGNMENT_TYPE stack[NTHREADS] [
+   (STACKSIZE+sizeof(CYG_ALIGNMENT_TYPE)-1)
+     / sizeof(CYG_ALIGNMENT_TYPE)                     ];
+
+static int nthreads = 0;
+
+static Cyg_Thread *new_thread( cyg_thread_entry *entry,
+                               CYG_ADDRWORD data,
+                               CYG_ADDRWORD priority,
+                               int do_resume )
+{
+    CYG_ASSERT(nthreads < NTHREADS, 
+               "Attempt to create more than NTHREADS threads");
+
+    thread[nthreads] = new( (void *)&thread_obj[nthreads] )
+        Cyg_Thread(priority,
+                   entry, data, 
+                   NULL,                // no name
+                   (CYG_ADDRESS)stack[nthreads], STACKSIZE );
+
+    if ( do_resume )
+        thread[nthreads]->resume();
+
+    return thread[nthreads++];
+}
+
+
+static void kill_threads( void )
+{
+    CYG_ASSERT(nthreads <= NTHREADS, 
+               "More than NTHREADS threads");
+    CYG_ASSERT( Cyg_Thread::self() == thread[0],
+                "kill_threads() not called from thread 0");
+    while ( nthreads > 1 ) {
+        nthreads--;
+        if ( NULL != thread[nthreads] ) {
+            thread[nthreads]->kill();
+            thread[nthreads]->~Cyg_Thread();
+            thread[nthreads] = NULL;
+        }
+    }
+    CYG_ASSERT(nthreads == 1,
+               "No threads left");
+}
+
+// ------------------------------------------------------------------------
+
+#define DELAYFACTOR 1 // for debugging
+
+// ------------------------------------------------------------------------
+
+static Cyg_Mutex mutex;
+
+// These are for reporting back to the master thread
+volatile int got_it  = 0;
+volatile int t3ran   = 0;
+volatile int t3ended = 0;
+volatile int extras[4] = {0,0,0,0};
+    
+volatile int go_flag = 0; // but this one controls thread 3 from thread 2
+
+// ------------------------------------------------------------------------
+// 0 to 3 of these run generally to interfere with the other processing,
+// to cause multiple prio inheritances, and clashes in any orders.
+
+static void extra_thread( CYG_ADDRWORD data )
+{
+#define XINFO( z ) \
+    do { z[13] = '0' + data; CYG_TEST_INFO( z ); } while ( 0 )
+
+    static char running[]  = "Extra thread Xa running";
+    static char exiting[]  = "Extra thread Xa exiting";
+    static char resumed[]  = "Extra thread Xa resumed";
+    static char locked[]   = "Extra thread Xa locked";
+    static char unlocked[] = "Extra thread Xa unlocked";
+
+    XINFO( running );
+
+    Cyg_Thread *self = Cyg_Thread::self();
+
+    self->suspend();
+
+    XINFO( resumed );
+
+    mutex.lock();
+
+    XINFO( locked );
+
+    mutex.unlock();
+
+    XINFO( unlocked );
+
+    extras[ data ] ++;
+
+    XINFO( exiting );
+
+}
+
+// ------------------------------------------------------------------------
+
+static void t1( CYG_ADDRWORD data )
+{
+    Cyg_Thread *self = Cyg_Thread::self();
+
+    CYG_TEST_INFO( "Thread 1 running" );
+
+    self->suspend();
+
+    mutex.lock();
+
+    got_it++;
+
+    CYG_TEST_CHECK( 0 == t3ended, "T3 ended prematurely [T1,1]" );
+
+    mutex.unlock();
+
+    CYG_TEST_CHECK( 0 == t3ended, "T3 ended prematurely [T1,2]" );
+
+    // That's all.
+
+    CYG_TEST_INFO( "Thread 1 exit" );
+}
+
+// ------------------------------------------------------------------------
+
+static void t2( CYG_ADDRWORD data )
+{
+    Cyg_Thread *self = Cyg_Thread::self();
+    int i;
+    cyg_tick_count then, now;
+
+
+    CYG_TEST_INFO( "Thread 2 running" );
+
+    CYG_TEST_CHECK( 0 == (data & ~0x77), "Bad T2 arg: extra bits" );
+    CYG_TEST_CHECK( 0 == (data & (data >> 4)), "Bad T2 arg: overlap" );
+
+    self->suspend();
+
+    // depending on our config argument, optionally restart some of the
+    // extra threads to throw noise into the scheduler:
+    for ( i = 0; i < 3; i++ )
+        if ( (1 << i) & data )          // bits 0-2 control
+            thread[i+4]->resume();      // made sure extras are thread[4-6]
+
+    self->delay( DELAYFACTOR * 10 );    // let those threads run
+
+    Cyg_Scheduler::lock();              // do this next lot atomically
+
+    go_flag = 1;                        // unleash thread 3
+    thread[1]->resume();                // resume thread 1
+
+    // depending on our config argument, optionally restart some of the
+    // extra threads to throw noise into the scheduler at this later point:
+    for ( i = 4; i < 7; i++ )
+        if ( (1 << i) & data )          // bits 4-6 control
+            thread[i]->resume();        // made sure extras are thread[4-6]
+
+    Cyg_Scheduler::unlock();           // let scheduling proceed
+
+    // Need a delay (but not a CPU yield) to allow t3 to awaken and act on
+    // the go_flag, otherwise we check these details below too soon.
+    // Actually, waiting for the clock to tick a couple of times would be
+    // better, so that is what we will do.  Must be a busy-wait.
+    then = Cyg_Clock::real_time_clock->current_value();
+    do {
+        now = Cyg_Clock::real_time_clock->current_value();
+        // Wait longer than the delay in t3 waiting on go_flag
+    } while ( now < (then + 3) );
+
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE
+    CYG_TEST_INFO( "Checking for MUTEX_PRIORITY_INHERITANCE" );
+    CYG_TEST_CHECK( 1 == t3ran, "Thread 3 did not run" );
+    CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" );
+#else
+    CYG_TEST_INFO( "Checking for NO mutex_priority_inheritance" );
+    CYG_TEST_CHECK( 0 == t3ran, "Thread 3 DID run" );
+    CYG_TEST_CHECK( 0 == got_it, "Thread 1 DID get the mutex" );
+#endif
+
+    CYG_TEST_CHECK( 0 == t3ended, "Thread 3 ended prematurely [T2,1]" );
+
+    self->delay( DELAYFACTOR * 20 );    // let those threads run
+
+    CYG_TEST_CHECK( 1 == t3ran, "Thread 3 did not run" );
+    CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" );
+    CYG_TEST_CHECK( 1 == t3ended, "Thread 3 has not ended" );
+
+    for ( i = 0; i < 3; i++ )
+        if ( (1 << i) & (data | data >> 4) ) // bits 0-2 and 4-6 control
+            CYG_TEST_CHECK( 1 == extras[i+1], "Extra thread did not run" );
+        else
+            CYG_TEST_CHECK( 0 == extras[i+1], "Extra thread ran" );
+
+    CYG_TEST_PASS( "Thread 2 exiting, AOK" );
+    // That's all: restart the control thread.
+    thread[0]->resume();
+}
+
+// ------------------------------------------------------------------------
+
+static void t3( CYG_ADDRWORD data )
+{
+    Cyg_Thread *self = Cyg_Thread::self();
+
+    CYG_TEST_INFO( "Thread 3 running" );
+
+    mutex.lock();
+
+    self->delay( DELAYFACTOR * 5 );    // let thread 3a run
+
+    thread[2]->resume();                // resume thread 2
+
+    while ( 0 == go_flag )
+        self->delay(1);                 // wait until we are told to go
+
+    t3ran ++;                           // record the fact
+
+    CYG_TEST_CHECK( 0 == got_it, "Thread 1 claims to have got my mutex" );
+    
+    mutex.unlock();
+    
+    t3ended ++;                         // record that we came back
+
+    CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" );
+
+    CYG_TEST_INFO( "Thread 3 exit" );
+}
+
+// ------------------------------------------------------------------------
+
+static void control_thread( CYG_ADDRWORD data )
+{
+    Cyg_Thread *self = Cyg_Thread::self();
+    int i;
+
+    CYG_TEST_INIT();
+    CYG_TEST_INFO( "Control Thread running" );
+
+    // Go through the 27 possibilitied of resuming the extra threads
+    //     0: not at all
+    //     1: early in the process
+    //     2: later on
+    // which are represented by bits 0-3 and 4-6 resp in the argument to
+    // thread 2 (none set means no resume at all).
+    for ( i = 0; i < 27; i++ ) {
+        static int xx[] = { 0, 1, 16 };
+        int j = i % 3;
+        int k = (i / 3) % 3;
+        int l = (i / 9) % 3;
+
+        int d = xx[j] | (xx[k]<<1) | (xx[l]<<2) ;
+
+
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE
+        // If the simple scheme plus relay enhancement, or any other
+        // *complete* scheme, we can run all three ancillary threads no
+        // problem, so no special action here.
+
+#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE
+#ifndef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE_RELAY
+        // If the simple scheme but no relay enhancement:
+        if ( k )                        // Cannot run thread 2a nor 3a
+            break;                      //     if no priority relay.
+#endif
+#endif
+
+#else
+        // If no priority inheritance at all, running threads 1a and 2a is
+        // OK, but not thread 3a; it blocks the world.
+        if ( l )                        // Cannot run thread 3a if no
+            break;                      //     priority inheritance at all.
+#endif
+
+        mutex = Cyg_Mutex();            // Reinitialize this
+
+        got_it  = 0;
+        t3ran   = 0;
+        t3ended = 0;
+        for ( int z = 0; z < 4; z++ ) extras[z] = 0;
+        go_flag = 0;
+        
+        new_thread( t1, 0,  5, 1 );            // Slot 1
+        new_thread( t2, d, 10, 1 );            // Slot 2
+        new_thread( t3, 0, 15, 1 );            // Slot 3
+        
+        new_thread( extra_thread, 1,  8, j );  // Slot 4
+        new_thread( extra_thread, 2, 12, k );  // Slot 5
+        new_thread( extra_thread, 3, 17, l );  // Slot 6
+        
+        {
+            static char *a[] = { "inactive", "run early", "run late" };
+            diag_printf( "\n----- [%2d] New Cycle: 0x%02x, Threads 1a %s, 2a %s, 3a %s -----\n",
+                         i, d,  a[j], a[k], a[l] );
+        }
+
+        self->suspend();
+        
+        kill_threads();
+        mutex.~Cyg_Mutex();
+    }
+    CYG_TEST_EXIT( "Control Thread exit" );
+}
+
+// ------------------------------------------------------------------------
+
+externC void
+cyg_user_start( void )
+{ 
+    new_thread( control_thread, 0, 2, 1 );
+}
+
+#else // CYGVAR_KERNEL_COUNTERS_CLOCK &c
+
+externC void
+cyg_start( void )
+{
+    CYG_TEST_INIT();
+    CYG_TEST_PASS_FINISH("Mutex3 test requires:\n"
+                         "CYGVAR_KERNEL_COUNTERS_CLOCK &&\n"
+                         "(CYGNUM_KERNEL_SCHED_PRIORITIES > 20)\n");
+}
+#endif // CYGVAR_KERNEL_COUNTERS_CLOCK &c
+
+
+// ------------------------------------------------------------------------
+// Documentation: enclosed is the design of this test.
+//
+// It has been carefully constructed so that it does NOT use other kernel
+// facilities (aside from delay-task) to test that priority inheritance is
+// working, or not, as intended by the configuration.
+//
+// These notes describe the flow of control in one run of the test with the
+// ancillary tasks optionally interspersed.  The details of how those extra
+// tasks are or are not allowed to run are not described.
+// 
+// 
+// 
+// The only change in the test that depends on whether there is inheritance or
+// not is the check in thread 2 on "3-ran" and "got it" flags marked ****
+// 
+// 
+// volatile &c booleans:
+//         "got it"     = FALSE
+//         "3-ran"      = FALSE
+//         "3-ended"    = FALSE
+//         "extras"[3]  = FALSE
+// 
+// thread 1.  prio 5, self-suspend.
+// 
+// thread 1a, prio 8, self-suspend.
+// 
+// thread 2.  prio 10, self-suspend.
+// 
+// thread 2a, prio 12, self-suspend.
+// 
+// thread 3.  prio 15, runs, lock mutex, resume(2)
+// 
+// thread 3a, prio 17, self-suspend.
+// 
+//        2.  runs,
+//        2.  resume(3a) +++OPTIONAL
+//        2.  resume(2a) +++OPTIONAL
+//        2.  resume(1a) +++OPTIONAL
+//        [1a lock-fail]	thread 3->prio := 8
+// 
+//        [3. runs maybe, does the looping thing]
+// 
+//        2.  sleep a while...
+// 
+//        [2a lock-fail]	thread 3->prio := 12
+// 
+//        [3. runs maybe, does the looping thing]
+// 
+//        [3a lock-fail]   thread 3->prio unchanged
+// 
+//        [3. runs maybe, does the looping thing]
+// 
+//        2.  lock scheduler
+//        2.  set "go-flag"
+//        2.  resume(1)
+//        2.  resume(1a) +++OPTIONAL
+//        2.  resume(2a) +++OPTIONAL
+//        2.  resume(3a) +++OPTIONAL
+//        2.  unlock scheduler
+// 
+//        1.  runs, lock mutex - thread 3 has it locked
+//
+//        2.  busy-waits a bit for thread 3 to come out of its delay() loop.
+//            This must be a *busy*wait so that 3 can only run via the
+//            inherited raised priority.
+// 
+//        [xa. all do the same: lock mutex,                ]
+//        [xa. unlock mutex                                ]
+//        [xa. set a flag "extras"[x] to say we are done.  ]
+//        [xa. exit                                        ]
+// 
+// 
+// 
+// INHERIT
+// -------
+// 
+//                 thread 3->prio := 5
+// 
+//        3.  runs,
+//        3.  set a flag to say "3-ran",
+//        3.  loop with a sleep(1) until "go-flag" is set.
+//        3.  check "got it" is false,
+//        3.  then unlock mutex,
+// 
+//                 thread 3->prio := 15
+// 
+//        1.  runs, set a flag to say "got it",
+//        1.  check "3-ended" flag is false
+//        1.  unlock mutex,
+//        1.  check "3-ended" flag is still false
+//        1.  exit.
+// 
+//        [1a locks, unlocks, exits]
+// 
+//        2.  runs, check "3-ran" and "got it" flags are TRUE ****
+//        2.  check "3-ended" flag is false
+//        2.  sleeps for a while so that...
+// 
+//        [2a locks, unlocks, exits]
+//            
+//        3.  runs, set "3-ended" flag,
+//        3.  check "3-ran" and "got it" flags
+//        3.  exit
+// 
+//        [3a locks, unlocks, exits]
+// 
+//        2.  awakens, checks all flags true,
+//        2.  check that all "extra" threads that we started have indeed run
+//        2.  end of test.
+// 
+// 
+// 
+// 
+// NO-INHERIT
+// ----------
+//                 thread 1 is waiting on the mutex
+// 
+//        [1a lock-fail]
+// 
+//        2.  runs, checks that "3-ran" and "got it" flags are FALSE ****
+//        2.  check "3-ended" flag is false
+//        2.  sleeps for a while so that...
+// 
+//        [2a. lock-fail]
+//            
+//        3.  runs, set a flag to say "3-ran",
+//        3.  check "got it" is false,
+//        3.  then unlock mutex,
+// 
+//        1.  runs, set a flag to say "got it",
+//        1.  check "3-ended" flag is false
+//        1.  unlock mutex,
+//        1.  check "3-ended" flag is still false
+//        1.  exit.
+// 
+//        [1a locks, unlocks, exits]
+//        [2a locks, unlocks, exits]
+// 
+//        3.  runs, set "3-ended" flag,
+//        3.  check "3-ran" and "got it" flags
+//        3.  exit
+// 
+//        [3a locks, unlocks, exits]
+//                
+//        2.  awakens, checks all flags true, 
+//        2.  check that all "extra" threads that we started have indeed run
+//        2.  end of test.
+// 
+// 
+// (the end)
+// 
+// 
+// ------------------------------------------------------------------------
+
+// EOF mutex3.cxx
--- a/packages/kernel/current/tests/stress_threads.c
+++ b/packages/kernel/current/tests/stress_threads.c
@@ -93,7 +93,6 @@
 #define MAX_HANDLERS 4
 #define N_LISTENERS 1
 #define N_CLIENTS 1
-#define N_THREADS (N_MAIN+MAX_HANDLERS+N_LISTENERS+N_CLIENTS)
 
 #undef STACK_SIZE
 #undef STACK_SIZE_HANDLER
@@ -107,26 +106,47 @@
 #define MAX_HANDLERS 19
 #define N_LISTENERS 4
 #define N_CLIENTS 4
-#define N_THREADS (N_MAIN+MAX_HANDLERS+N_LISTENERS+N_CLIENTS)
 #endif
 
 /* Allocate priorities in this order. This ensures that handlers
    (which are the ones using the CPU) get enough CPU time to actually
-   complete their tasks. */
-//#define P_MAIN        0                       // This is defined by libc
-#define P_MAIN_PROGRAM  1
-#define P_BASE_HANDLER  2
-#define P_BASE_LISTENER (P_BASE_HANDLER+MAX_HANDLERS)
-#define P_BASE_CLIENT   (P_BASE_LISTENER+N_LISTENERS)
-#define P_MAX           (P_BASE_CLIENT+N_CLIENTS)
+   complete their tasks. 
+
+   The empty space ensures that if libc main() thread should happen to
+   be in the priority range of the handlers, no handlers are
+   accidently reduced so much in priority to get below
+   listeners/clients. */
+
+#define P_MAIN_PROGRAM    1
+#define P_MAIN_PROGRAM_E  (P_MAIN_PROGRAM+N_MAIN)
+
+#define P_BASE_HANDLER    (P_MAIN_PROGRAM_E)
+#define P_BASE_HANDLER_E  (P_BASE_HANDLER+MAX_HANDLERS)
 
+#define P_BASE_EMPTY      (P_BASE_HANDLER_E)
+#define P_BASE_EMPTY_E    (P_BASE_EMPTY+2)
 
-#if (CYGNUM_KERNEL_SCHED_PRIORITIES >= (P_MAX))
+#define P_BASE_LISTENER   (P_BASE_EMPTY_E)
+#define P_BASE_LISTENER_E (P_BASE_LISTENER+N_LISTENERS)
+
+#define P_BASE_CLIENT     (P_BASE_LISTENER_E)
+#define P_BASE_CLIENT_E   (P_BASE_CLIENT+N_CLIENTS)
+
+#define P_MAX             (P_BASE_CLIENT_E)
+
+/* Ensure there's room for what we request */
+#if (CYGNUM_KERNEL_SCHED_PRIORITIES >= P_MAX)
 
 /* if we use the bitmap scheduler we must make sure we don't use the
    same priority more than once, so we must store those already in use */
 static volatile char priority_in_use[P_MAX];
 
+/* We may not get the priority we ask for (scheduler may decide to ignore
+   schedule hint). So keep a table of priorities actually assigned to
+   the threads. This information may come in handy for debugging - it's
+   not actively used by the code. */
+static volatile int  priority_translation[P_MAX];
+
 /* now declare (and allocate space for) some kernel objects, like the
    threads we will use */
 cyg_thread main_thread_s;
@@ -200,7 +220,7 @@ struct s_statistics statistics;
 
 /* some function prototypes; those with the sc_ prefix are
    "statistics-collecting" versions of the cyg_ primitives */
-void sc_thread_create(
+cyg_addrword_t sc_thread_create(
     cyg_addrword_t      sched_info,             /* scheduling info (eg pri)  */
     cyg_thread_entry_t  *entry,                 /* entry point function      */
     cyg_addrword_t      entry_data,             /* entry data                */
@@ -249,9 +269,10 @@ main(void)
 
     /* initialize main thread */
     {
-        sc_thread_create(P_MAIN_PROGRAM, main_program, (cyg_addrword_t) 0,
-                         "main_program", (void *) main_stack, STACK_SIZE,
-                         &mainH, &main_thread_s);
+        priority_translation[P_MAIN_PROGRAM] =
+            sc_thread_create(P_MAIN_PROGRAM, main_program, (cyg_addrword_t) 0,
+                             "main_program", (void *) main_stack, STACK_SIZE,
+                             &mainH, &main_thread_s);
         priority_in_use[P_MAIN_PROGRAM]++;
     }
 
@@ -263,20 +284,22 @@ main(void)
     for (i = 0; i < N_LISTENERS; ++i) {
         int prio = P_BASE_LISTENER + i;
         char* name = &thread_name[prio][0];
-        sprintf(name, "listener-%02d/%02d", i, prio);
-        sc_thread_create(prio, listener_program, (cyg_addrword_t) i,
-                         name, (void *) listener_stack[i], STACK_SIZE,
-                         &listenerH[i], &listener_thread_s[i]);
+        sprintf(name, "listener-%02d", i);
+        priority_translation[prio] =
+            sc_thread_create(prio, listener_program, (cyg_addrword_t) i,
+                             name, (void *) listener_stack[i], STACK_SIZE,
+                             &listenerH[i], &listener_thread_s[i]);
         CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!");
         priority_in_use[prio]++;
     }
     for (i = 0; i < N_CLIENTS; ++i) {
         int prio = P_BASE_CLIENT + i;
         char* name = &thread_name[prio][0];
-        sprintf(name, "client-%02d/%02d", i, prio);
-        sc_thread_create(prio, client_program, (cyg_addrword_t) i,
-                         name, (void *) client_stack[i], STACK_SIZE,
-                         &(clientH[i]), &client_thread_s[i]);
+        sprintf(name, "client-%02d", i);
+        priority_translation[prio] =
+            sc_thread_create(prio, client_program, (cyg_addrword_t) i,
+                             name, (void *) client_stack[i], STACK_SIZE,
+                             &(clientH[i]), &client_thread_s[i]);
         CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!");
         priority_in_use[prio]++;
     }
@@ -477,11 +500,12 @@ void start_handler(void)
     name = &thread_name[prio][0];
     sprintf(name, "handler-%02d/%02d", handler_slot, prio);
 
-    sc_thread_create(prio, handler_program,
-                     (cyg_addrword_t) handler_slot,
-                     name, (void *) handler_stack[handler_slot],
-                     STACK_SIZE_HANDLER, &handlerH[handler_slot],
-                     &handler_thread_s[handler_slot]);
+    priority_translation[prio] =
+        sc_thread_create(prio, handler_program,
+                         (cyg_addrword_t) handler_slot,
+                         name, (void *) handler_stack[handler_slot],
+                         STACK_SIZE_HANDLER, &handlerH[handler_slot],
+                         &handler_thread_s[handler_slot]);
     cyg_thread_resume(handlerH[handler_slot]);
     ++statistics.handler_invocation_histogram[handler_slot];
 }
@@ -644,7 +668,7 @@ void death_alarm_func(cyg_handle_t alarm
 }
 
 /* now I write the sc_ versions of the cyg_functions */
-void sc_thread_create(
+cyg_addrword_t sc_thread_create(
     cyg_addrword_t      sched_info,            /* scheduling info (eg pri)  */
     cyg_thread_entry_t  *entry,                /* entry point function      */
     cyg_addrword_t      entry_data,            /* entry data                */
@@ -656,11 +680,11 @@ void sc_thread_create(
     )
 {
     ++statistics.thread_creations;
+
     cyg_thread_create(sched_info, entry, entry_data, name,
                       stack_base, stack_size, handle, thread);
 
-    CYG_ASSERT(cyg_thread_get_priority(*handle) == (cyg_priority_t) sched_info,
-               "Didn't get requested priority!");
+    return cyg_thread_get_priority(*handle);
 }