From b73e57bffe6cf60b1817bb2fc244a2f0c602bd5c Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Fri, 9 Jul 1999 17:08:48 +0000 Subject: Patch from Jiri Gaisler : + interrupt masking correction + FPU rev.B workaround + minor erc32 related fixes --- cpukit/score/cpu/sparc/asm.h | 1 + cpukit/score/cpu/sparc/cpu_asm.S | 74 ++++++++++++++++++++++++++++-- cpukit/score/cpu/sparc/rtems/asm.h | 1 + cpukit/score/cpu/sparc/rtems/score/cpu.h | 10 ++-- cpukit/score/cpu/sparc/rtems/score/sparc.h | 6 ++- 5 files changed, 84 insertions(+), 8 deletions(-) (limited to 'cpukit/score/cpu/sparc') diff --git a/cpukit/score/cpu/sparc/asm.h b/cpukit/score/cpu/sparc/asm.h index e76fc27182..cdb906af58 100644 --- a/cpukit/score/cpu/sparc/asm.h +++ b/cpukit/score/cpu/sparc/asm.h @@ -44,6 +44,7 @@ /* XXX __USER_LABEL_PREFIX__ and __REGISTER_PREFIX__ do not work on gcc 2.7.0 */ /* XXX The following ifdef magic fixes the problem but results in a warning */ /* XXX when compiling assembly code. */ + #ifndef __USER_LABEL_PREFIX__ #define __USER_LABEL_PREFIX__ _ #endif diff --git a/cpukit/score/cpu/sparc/cpu_asm.S b/cpukit/score/cpu/sparc/cpu_asm.S index d980d4bff7..d96256694f 100644 --- a/cpukit/score/cpu/sparc/cpu_asm.S +++ b/cpukit/score/cpu/sparc/cpu_asm.S @@ -498,17 +498,85 @@ dont_switch_stacks: * when the interrupt handler returns. */ +/* This is a fix for ERC32 with FPU rev.B or rev.C */ + +#if defined(FPU_REVB) + + mov %l0, %g5 - subcc %l3, 0x11, %g0 + and %l3, 0x0ff, %g4 + subcc %g4, 0x08, %g0 + be fpu_revb + subcc %g4, 0x11, %g0 bl dont_fix_pil - subcc %l3, 0x1f, %g0 + subcc %g4, 0x1f, %g0 bg dont_fix_pil - sll %l3, 8, %g4 + sll %g4, 8, %g4 and %g4, SPARC_PSR_PIL_MASK, %g4 andn %l0, SPARC_PSR_PIL_MASK, %g5 or %g4, %g5, %g5 + srl %l0, 12, %g4 + andcc %g4, 1, %g0 + be dont_fix_pil + nop + ba,a enable_irq + + +fpu_revb: + srl %l0, 12, %g4 ! check if EF is set in %psr + andcc %g4, 1, %g0 + be dont_fix_pil ! if FPU disabled than continue as normal + and %l3, 0xff, %g4 + subcc %g4, 0x08, %g0 + bne enable_irq ! if not a FPU exception then do two fmovs + set __sparc_fq, %g4 + st %fsr, [%g4] ! if FQ is not empty and FQ[1] = fmovs + ld [%g4], %g4 ! than this is bug 3.14 + srl %g4, 13, %g4 + andcc %g4, 1, %g0 + be dont_fix_pil + set __sparc_fq, %g4 + std %fq, [%g4] + ld [%g4+4], %g4 + set 0x81a00020, %g5 + subcc %g4, %g5, %g0 + bne,a dont_fix_pil2 + wr %l0, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS **** + ba,a simple_return + +enable_irq: + or %g5, SPARC_PSR_PIL_MASK, %g4 + wr %g4, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS **** + nop; nop; nop + fmovs %f0, %f0 + ba dont_fix_pil + fmovs %f0, %f0 + + .data + .global __sparc_fq + .align 8 +__sparc_fq: + .word 0,0 + + .text +/* end of ERC32 FPU rev.B/C fix */ + +#else + + mov %l0, %g5 + subcc %g4, 0x11, %g0 + bl dont_fix_pil + subcc %g4, 0x1f, %g0 + bg dont_fix_pil + sll %g4, 8, %g4 + and %g4, SPARC_PSR_PIL_MASK, %g4 + andn %l0, SPARC_PSR_PIL_MASK, %g5 + or %g4, %g5, %g5 +#endif + dont_fix_pil: wr %g5, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS **** +dont_fix_pil2: /* * Vector to user's handler. diff --git a/cpukit/score/cpu/sparc/rtems/asm.h b/cpukit/score/cpu/sparc/rtems/asm.h index e76fc27182..cdb906af58 100644 --- a/cpukit/score/cpu/sparc/rtems/asm.h +++ b/cpukit/score/cpu/sparc/rtems/asm.h @@ -44,6 +44,7 @@ /* XXX __USER_LABEL_PREFIX__ and __REGISTER_PREFIX__ do not work on gcc 2.7.0 */ /* XXX The following ifdef magic fixes the problem but results in a warning */ /* XXX when compiling assembly code. */ + #ifndef __USER_LABEL_PREFIX__ #define __USER_LABEL_PREFIX__ _ #endif diff --git a/cpukit/score/cpu/sparc/rtems/score/cpu.h b/cpukit/score/cpu/sparc/rtems/score/cpu.h index cf50f035d6..7a55ae5d0d 100644 --- a/cpukit/score/cpu/sparc/rtems/score/cpu.h +++ b/cpukit/score/cpu/sparc/rtems/score/cpu.h @@ -725,6 +725,9 @@ SCORE_EXTERN unsigned8 _CPU_Trap_Table_area[ 8192 ] #ifndef ASM +extern unsigned int sparc_disable_interrupts(); +extern void sparc_enable_interrupts(); + /* ISR handler macros */ /* @@ -733,7 +736,7 @@ SCORE_EXTERN unsigned8 _CPU_Trap_Table_area[ 8192 ] */ #define _CPU_ISR_Disable( _level ) \ - sparc_disable_interrupts( _level ) + (_level) = sparc_disable_interrupts() /* * Enable interrupts to the previous level (returned by _CPU_ISR_Disable). @@ -743,7 +746,6 @@ SCORE_EXTERN unsigned8 _CPU_Trap_Table_area[ 8192 ] #define _CPU_ISR_Enable( _level ) \ sparc_enable_interrupts( _level ) - /* * This temporarily restores the interrupt to _level before immediately * disabling them again. This is used to divide long critical @@ -761,7 +763,7 @@ SCORE_EXTERN unsigned8 _CPU_Trap_Table_area[ 8192 ] */ #define _CPU_ISR_Set_level( _newlevel ) \ - sparc_set_interrupt_level( _newlevel ) + sparc_enable_interrupts( _newlevel << 8) unsigned32 _CPU_ISR_Get_level( void ); @@ -840,7 +842,7 @@ void _CPU_Context_Initialize( do { \ unsigned32 level; \ \ - sparc_disable_interrupts( level ); \ + level = sparc_disable_interrupts(); \ asm volatile ( "mov %0, %%g1 " : "=r" (level) : "0" (level) ); \ while (1); /* loop forever */ \ } while (0) diff --git a/cpukit/score/cpu/sparc/rtems/score/sparc.h b/cpukit/score/cpu/sparc/rtems/score/sparc.h index 283548728a..a8f2122c44 100644 --- a/cpukit/score/cpu/sparc/rtems/score/sparc.h +++ b/cpukit/score/cpu/sparc/rtems/score/sparc.h @@ -196,6 +196,7 @@ extern "C" { * */ +/* #define sparc_disable_interrupts( _level ) \ do { \ register unsigned int _newlevel; \ @@ -204,7 +205,7 @@ extern "C" { (_newlevel) = (_level) | SPARC_PSR_PIL_MASK; \ sparc_set_psr( _newlevel ); \ } while ( 0 ) - + #define sparc_enable_interrupts( _level ) \ do { \ unsigned int _tmp; \ @@ -214,6 +215,7 @@ extern "C" { _tmp |= (_level) & SPARC_PSR_PIL_MASK; \ sparc_set_psr( _tmp ); \ } while ( 0 ) +*/ #define sparc_flash_interrupts( _level ) \ do { \ @@ -223,6 +225,7 @@ extern "C" { sparc_disable_interrupts( _ignored ); \ } while ( 0 ) +/* #define sparc_set_interrupt_level( _new_level ) \ do { \ register unsigned32 _new_psr_level = 0; \ @@ -233,6 +236,7 @@ extern "C" { (((_new_level) << SPARC_PSR_PIL_BIT_POSITION) & SPARC_PSR_PIL_MASK); \ sparc_set_psr( _new_psr_level ); \ } while ( 0 ) +*/ #define sparc_get_interrupt_level( _level ) \ do { \ -- cgit v1.2.3