Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'libgloss/or1k/crt0.S')
-rw-r--r--libgloss/or1k/crt0.S149
1 files changed, 110 insertions, 39 deletions
diff --git a/libgloss/or1k/crt0.S b/libgloss/or1k/crt0.S
index ecaf9172f..74ddaacf7 100644
--- a/libgloss/or1k/crt0.S
+++ b/libgloss/or1k/crt0.S
@@ -66,14 +66,18 @@
// function
#define EXCEPTION_STACK_FRAME 136
+#define REDZONE 128
+
.extern _or1k_stack_top /* points to the next address after the stack */
.extern _or1k_stack_bottom /* points to the last address in the stack */
.extern _or1k_exception_stack_top
.extern _or1k_exception_stack_bottom
+ .extern _or1k_exception_level /* Nesting level of exceptions */
.section .data
.global _or1k_stack_size /* reserved stack size */
.global _or1k_exception_stack_size
+ .global _or1k_exception_level
_or1k_stack_size: .word STACK_SIZE
_or1k_exception_stack_size: .word EXCEPTION_STACK_SIZE
@@ -95,13 +99,35 @@ _or1k_exception_stack_size: .word EXCEPTION_STACK_SIZE
#define GPR_BUF_OFFSET(x) (x << 2)
#ifndef __OR1K_MULTICORE__
-#define CALL_EXCEPTION_HANDLER \
- /* store current stack pointer to address 4 */ \
+#define CALL_EXCEPTION_HANDLER(id) \
+ /* Store current stack pointer to address 4 */ \
l.sw 0x4(r0),r1; \
+ /* Load address of exception nesting level */ \
+ l.movhi r1,hi(_or1k_exception_level); \
+ l.ori r1,r1,lo(_or1k_exception_level); \
+ /* Load the current nesting level */ \
+ l.lwz r1,0(r1); \
+ /* Set flag if this is the outer (first) exception */ \
+ l.sfeq r1,r0; \
+ /* Branch to the code for nested exceptions */ \
+ OR1K_DELAYED_NOP( \
+ OR1K_INST(l.bnf .Lnested_##id) \
+ ); \
/* Load top of the exception stack */ \
l.movhi r1,hi(_or1k_exception_stack_top); \
l.ori r1,r1,lo(_or1k_exception_stack_top); \
- l.lwz r1,0(r1); \
+ OR1K_DELAYED( \
+ /* Load value from array to stack pointer */ \
+ OR1K_INST(l.lwz r1,0(r1)), \
+ /* and jump over the nested code */ \
+ OR1K_INST(l.j .Lnesting_done_##id) \
+ ); \
+.Lnested_##id: \
+ /* Load back the stack pointer */ \
+ l.lwz r1,0x4(r0)); \
+ /* Add redzone, nesting needs this */ \
+ l.addi r1,r1,-REDZONE; \
+.Lnesting_done_##id: \
/* Reserve red zone and context space */ \
l.addi r1,r1,-EXCEPTION_STACK_FRAME; \
/* Store GPR3 in context */ \
@@ -112,6 +138,15 @@ _or1k_exception_stack_size: .word EXCEPTION_STACK_SIZE
l.sw GPR_BUF_OFFSET(1)(r1),r3; \
/* Store GPR4 in the context */ \
l.sw GPR_BUF_OFFSET(4)(r1),r4; \
+ /* Load address of the exception level */ \
+ l.movhi r3,hi(_or1k_exception_level); \
+ l.ori r3,r3,lo(_or1k_exception_level); \
+ /* Load current value */ \
+ l.lwz r4,0(r3); \
+ /* Increment level */ \
+ l.addi r4,r4,1; \
+ /* Store back */ \
+ l.sw 0(r3),r4; \
/* Copy the current program counter as first */ \
/* argument for the exception handler. This */ \
/* is then used to determine the exception. */ \
@@ -124,11 +159,36 @@ _or1k_exception_stack_size: .word EXCEPTION_STACK_SIZE
OR1K_INST(l.j _or1k_exception_handler) \
)
#else
-#define CALL_EXCEPTION_HANDLER \
- /* store current stack pointer to shadow reg */ \
+#define CALL_EXCEPTION_HANDLER(id) \
+ /* Store current stack pointer to shadow reg */ \
l.mtspr r0,r1,SHADOW_REG(1); \
- /* store current GPR3 as we need it */ \
+ /* Store current GPR3 for temporary use */ \
l.mtspr r0,r3,SHADOW_REG(2); \
+ /* Store current GPR2 for the level pointer */ \
+ l.mtspr r0,r4,SHADOW_REG(3); \
+ /* Load nesting level of exceptions */ \
+ l.movhi r4,hi(_or1k_exception_level); \
+ l.ori r4,r4,lo(_or1k_exception_level); \
+ /* Load array pointer */ \
+ l.lwz r4,0(r4); \
+ /* Get core id */ \
+ l.mfspr r3,r0,OR1K_SPR_SYS_COREID_ADDR; \
+ /* Generate offset */ \
+ l.slli r3,r3,2; \
+ /* Generate core nesting level address */ \
+ l.add r4,r4,r3; \
+ /* Load nesting level */ \
+ l.lwz r3,0(r4); \
+ /* Increment nesting level */ \
+ l.addi r3,r3,1; \
+ /* Write back nesting level */ \
+ l.sw 0(r4),r3; \
+ /* Set flag if this is the outer (first) exception */ \
+ l.sfeqi r3,1; \
+ /* Branch to the code for nested exceptions */ \
+ OR1K_DELAYED_NOP( \
+ OR1K_INST(l.bnf .Lnested_##id) \
+ ); \
/* Load pointer to exception stack array */ \
l.movhi r1,hi(_or1k_exception_stack_core); \
l.ori r1,r1,lo(_or1k_exception_stack_core); \
@@ -137,10 +197,19 @@ _or1k_exception_stack_size: .word EXCEPTION_STACK_SIZE
l.mfspr r3,r0,OR1K_SPR_SYS_COREID_ADDR; \
/* Calculate offset in array */ \
l.slli r3,r3,2; \
- /* Load value from array to stack pointer */ \
l.add r1,r1,r3; \
- l.lwz r1,0(r1); \
- /* Reserve red zone and context space */ \
+ OR1K_DELAYED( \
+ /* Load value from array to stack pointer */ \
+ OR1K_INST(l.lwz r1,0(r1)), \
+ /* and jump over nested exception pointer */ \
+ OR1K_INST(l.j .Lnesting_done_##id) \
+ ); \
+.Lnested_##id: \
+ /* The stack pointer is still active */ \
+ /* Add redzone, nesting needs this */ \
+ l.addi r1,r1,-REDZONE; \
+.Lnesting_done_##id: \
+ /* Reserve context space */ \
l.addi r1,r1,-EXCEPTION_STACK_FRAME; \
/* Load back software's stack pointer */ \
l.mfspr r3,r0,SHADOW_REG(1); \
@@ -150,6 +219,8 @@ _or1k_exception_stack_size: .word EXCEPTION_STACK_SIZE
l.mfspr r3,r0,SHADOW_REG(2); \
/* Store this in the context */ \
l.sw GPR_BUF_OFFSET(3)(r1),r3; \
+ /* Load back GPR4 */ \
+ l.mfspr r4,r0,SHADOW_REG(3); \
/* Store GPR4 in the context */ \
l.sw GPR_BUF_OFFSET(4)(r1),r4; \
/* Copy the current program counter as first */ \
@@ -223,107 +294,107 @@ _or1k_reset:
OR1K_DELAYED_NOP(OR1K_INST(l.jr r4))
.org 0x200
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(2)
/* 0x300: Data Page Fault exception */
.org 0x300
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(3)
/* 0x400: Insn Page Fault exception */
.org 0x400
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(4)
/* 0x500: Timer exception */
.org 0x500
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(5)
/* 0x600: Aligment exception */
.org 0x600
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(6)
/* 0x700: Illegal insn exception */
.org 0x700
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(7)
/* 0x800: External interrupt exception */
.org 0x800
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(8)
/* 0x900: DTLB miss exception */
.org 0x900
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(9)
/* 0xa00: ITLB miss exception */
.org 0xa00
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(10)
/* 0xb00: Range exception */
.org 0xb00
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(11)
/* 0xc00: Syscall exception */
.org 0xc00
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(12)
/* 0xd00: Floating point exception */
.org 0xd00
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(13)
/* 0xe00: Trap exception */
.org 0xe00
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(14)
/* 0xf00: Reserved exceptions */
.org 0xf00
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(15)
.org 0x1000
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(16)
.org 0x1100
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(17)
.org 0x1200
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(18)
.org 0x1300
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(19)
.org 0x1400
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(20)
.org 0x1500
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(21)
.org 0x1600
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(22)
.org 0x1700
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(23)
.org 0x1800
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(24)
.org 0x1900
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(25)
.org 0x1a00
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(26)
.org 0x1b00
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(27)
.org 0x1c00
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(28)
.org 0x1d00
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(29)
.org 0x1e00
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(30)
.org 0x1f00
- CALL_EXCEPTION_HANDLER
+ CALL_EXCEPTION_HANDLER(31)
/* Pad to the end */
.org 0x1ffc