summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/score/cpu/sparc/asm.h1
-rw-r--r--cpukit/score/cpu/sparc/cpu_asm.S74
-rw-r--r--cpukit/score/cpu/sparc/rtems/asm.h1
-rw-r--r--cpukit/score/cpu/sparc/rtems/score/cpu.h10
-rw-r--r--cpukit/score/cpu/sparc/rtems/score/sparc.h6
5 files changed, 84 insertions, 8 deletions
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 { \