OpenCores
URL https://opencores.org/ocsvn/ao486/ao486/trunk

Subversion Repositories ao486

[/] [ao486/] [trunk/] [syn/] [components/] [sd_card/] [firmware/] [bsp/] [HAL/] [src/] [alt_exception_entry.S] - Blame information for rev 8

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 8 alfik
/******************************************************************************
2
*                                                                             *
3
* License Agreement                                                           *
4
*                                                                             *
5
* Copyright (c) 2003-2008 Altera Corporation, San Jose, California, USA.      *
6
* All rights reserved.                                                        *
7
*                                                                             *
8
* Permission is hereby granted, free of charge, to any person obtaining a     *
9
* copy of this software and associated documentation files (the "Software"),  *
10
* to deal in the Software without restriction, including without limitation   *
11
* the rights to use, copy, modify, merge, publish, distribute, sublicense,    *
12
* and/or sell copies of the Software, and to permit persons to whom the       *
13
* Software is furnished to do so, subject to the following conditions:        *
14
*                                                                             *
15
* The above copyright notice and this permission notice shall be included in  *
16
* all copies or substantial portions of the Software.                         *
17
*                                                                             *
18
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  *
19
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,    *
20
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
21
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER      *
22
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING     *
23
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER         *
24
* DEALINGS IN THE SOFTWARE.                                                   *
25
*                                                                             *
26
* This agreement shall be governed in all respects by the laws of the State   *
27
* of California and by the laws of the United States of America.              *
28
*                                                                             *
29
******************************************************************************/
30
 
31
#include "system.h"
32
 
33
/*
34
 * This is the exception entry point code, which saves all the caller saved
35
 * registers and then handles the appropriate exception.  It should be pulled
36
 * in using a .globl from all the exception handler routines.  This scheme is
37
 * used so that if an interrupt is never registered, then this code will not
38
 * appear in the generated executable, thereby improving code footprint.
39
 *
40
 * If an external interrpt controller (EIC) is present, it will supply an
41
 * interrupt vector address to the processor when an interrupt occurs. For
42
 * The Altera Vectored Interrupt Controller (VIC) driver will establish a
43
 * vector table and the processor will jump directly to the appropriate
44
 * table entry, funnel routine, and then user ISR. This will bypass this code
45
 * in entirety. This code might still be linked into a system with an EIC,
46
 * but would then be used only for non-interrupt exceptions.
47
 */
48
 
49
        /*
50
         * Explicitly allow the use of r1 (the assembler temporary register)
51
         * within this code. This register is normally reserved for the use of
52
         * the assembler.
53
         */
54
        .set noat
55
 
56
        /*
57
         * The top and bottom of the exception stack.
58
         */
59
#ifdef ALT_EXCEPTION_STACK
60
        .globl __alt_exception_stack_pointer
61
 
62
#ifdef ALT_STACK_CHECK
63
        .globl __alt_exception_stack_limit
64
 
65
        /*
66
         * Store the value of the stack limit after interrupt somewhere.
67
         */
68
        .globl  alt_exception_old_stack_limit
69
#endif /* ALT_STACK_CHECK */
70
#endif /* ALT_EXCEPTION_STACK */
71
 
72
/*
73
 * The code at alt_exception is located at the Nios II exception
74
 * handler address.
75
 */
76
        .section .exceptions.entry.label, "xa"
77
        .globl alt_exception
78
        .type alt_exception, @function
79
alt_exception:
80
 
81
        /*
82
         * The code for detecting a likely fatal ECC exception is
83
         * linked here before the normal exception handler code if required.
84
         * This is handled by the linker script and putting that code
85
         * in the .exceptions.entry.ecc_fatal section.
86
         */
87
 
88
        /*
89
         * Now start the normal exception handler code.
90
         */
91
        .section .exceptions.entry, "xa"
92
 
93
#ifdef ALT_EXCEPTION_STACK
94
#ifdef ALT_STACK_CHECK
95
        /*
96
         * When runtime stack checking is enabled, the et register
97
         * contains the stack limit. Save this in memory before
98
         * overwriting the et register.
99
         */
100
        stw   et, %gprel(alt_exception_old_stack_limit)(gp)
101
#endif /* ALT_STACK_CHECK */
102
 
103
        /*
104
         * Switch to the exception stack and save the current stack pointer
105
         * in memory. Uses the et register as a scratch register.
106
         */
107
        movhi et, %hi(__alt_exception_stack_pointer - 80)
108
        ori   et, et, %lo(__alt_exception_stack_pointer - 80)
109
        stw   sp, 76(et)
110
        mov   sp, et
111
 
112
#ifdef ALT_STACK_CHECK
113
        /*
114
         * Restore the stack limit from memory to the et register.
115
         */
116
        movhi et, %hi(__alt_exception_stack_limit)
117
        ori   et, et, %lo(__alt_exception_stack_limit)
118
        stw   et, %gprel(alt_stack_limit_value)(gp)
119
#endif /* ALT_STACK_CHECK */
120
 
121
#else /* ALT_EXCEPTION_STACK disabled */
122
        /*
123
         * Reserve space on normal stack for registers about to be pushed.
124
         */
125
        addi  sp, sp, -76
126
 
127
#ifdef ALT_STACK_CHECK
128
        /* Ensure stack didn't just overflow. */
129
        bltu  sp, et, .Lstack_overflow
130
#endif /* ALT_STACK_CHECK */
131
 
132
#endif /* ALT_EXCEPTION_STACK */
133
 
134
        /*
135
         * Process an exception.  For all exceptions we must preserve all
136
         * caller saved registers on the stack (See the Nios II ABI
137
         * documentation for details).
138
         *
139
         * Leave a gap in the stack frame at 4(sp) for the muldiv handler to
140
         * store zero into.
141
         */
142
        stw   ra,  0(sp)
143
        stw   r1,   8(sp)
144
        stw   r2,  12(sp)
145
        stw   r3,  16(sp)
146
        stw   r4,  20(sp)
147
        stw   r5,  24(sp)
148
        stw   r6,  28(sp)
149
        stw   r7,  32(sp)
150
        rdctl r5, estatus   /* Read early to avoid usage stall */
151
        stw   r8,  36(sp)
152
        stw   r9,  40(sp)
153
        stw   r10, 44(sp)
154
        stw   r11, 48(sp)
155
        stw   r12, 52(sp)
156
        stw   r13, 56(sp)
157
        stw   r14, 60(sp)
158
        stw   r15, 64(sp)
159
 
160
        /*
161
         * ea-4 contains the address of the instruction being executed
162
         * when the exception occured. For interrupt exceptions, we will
163
         * will be re-issue the isntruction. Store it in 72(sp)
164
         */
165
        stw   r5,  68(sp)  /* estatus */
166
        addi  r15, ea, -4  /* instruction that caused exception */
167
        stw   r15,  72(sp)
168
 
169
        /*
170
         * The interrupt testing code (.exceptions.irqtest) will be
171
         * linked here. If the Internal Interrupt Controller (IIC) is
172
         * present (an EIC is not present), the presense of an interrupt
173
         * is determined by examining CPU control registers or an interrupt
174
         * custom instruction, if present.
175
         *
176
         * If the IIC is used and an interrupt is active, the code linked
177
         * here will call the HAL IRQ handler (alt_irq_handler()) which
178
         * successively calls registered interrupt handler(s) until no
179
         * interrupts remain pending. It then jumps to .exceptions.exit. If
180
         * there is no interrupt then it continues to .exception.notirq, below.
181
         */
182
 
183
        .section .exceptions.notirq, "xa"
184
 
185
        /*
186
         * Prepare to service unimplemtned instructions or traps,
187
         * each of which is optionally inked into section .exceptions.soft,
188
         * which will preceed .exceptions.unknown below.
189
         *
190
         * Unlike interrupts, we want to skip the exception-causing instructon
191
         * upon completion, so we write ea (address of instruction *after*
192
         * the one where the exception occured) into 72(sp). The actual
193
         * instruction that caused the exception is written in r2, which these
194
         * handlers will utilize.
195
         */
196
        stw   ea,  72(sp)  /* Don't re-issue */
197
        ldw   r2, -4(ea)   /* Instruction that caused exception */
198
 
199
        /*
200
         * Other exception handling code, if enabled, will be linked here.
201
         * This includes unimplemted (multiply/divide) instruction support
202
         * (a BSP generaton option), and a trap handler (that would typically
203
         * be augmented with user-specific code). These are not linked in by
204
         * default.
205
         */
206
 
207
        /*
208
         * In the context of linker sections, "unknown" are all exceptions
209
         * not handled by the built-in handlers above (interupt, and trap or
210
         * unimplemented instruction decoding, if enabled).
211
         *
212
         * Advanced exception types can be serviced by registering a handler.
213
         * To do so, enable the "Enable Instruction-related Exception API" HAL
214
         * BSP setting. If this setting is disabled, this handler code will
215
         * either break (if the debug core is present) or enter an infinite
216
         * loop because we don't how how to handle the exception.
217
         */
218
        .section .exceptions.unknown
219
#ifdef ALT_INCLUDE_INSTRUCTION_RELATED_EXCEPTION_API
220
        /*
221
         * The C-based HAL routine alt_instruction_exception_entry() will
222
         * attempt to service the exception by calling a user-registered
223
         * exception handler using alt_instruction_exception_register().
224
         * If no handler was registered it will either break (if the
225
         * debugger is present) or go into an infinite loop since the
226
         * handling behavior is undefined; in that case we will not return here.
227
         */
228
 
229
        /* Load exception-causing address as first argument (r4) */
230
        addi   r4, ea, -4
231
 
232
        /* Call the instruction-exception entry */
233
        call   alt_instruction_exception_entry
234
 
235
        /*
236
         * If alt_instruction_exception_entry() returned, the exception was
237
         * serviced by a user-registered routine. Its return code (now in r2)
238
         * indicates whether to re-issue or skip the exception-causing
239
         * instruction
240
         *
241
         * Return code was 0: Skip. The instruction after the exception is
242
         * already stored in 72(sp).
243
         */
244
        bne   r2, r0, .Lexception_exit
245
 
246
        /*
247
         * Otherwise, modify 72(sp) to re-issue the instruction that caused the
248
         * exception.
249
         */
250
        addi  r15, ea, -4  /* instruction that caused exception */
251
        stw   r15,  72(sp)
252
 
253
#else /* ALT_INCLUDE_INSTRUCTION_RELATED_EXCEPTION_API disabled */
254
 
255
        /*
256
         * We got here because an instruction-related exception occured, but the
257
         * handler API was not compiled in. We do not presume to know how to
258
         * handle it. If the debugger is present, break, otherwise hang.
259
         *
260
         *  If you get here then one of the following could have happened:
261
         *
262
         *  - An instruction-generated exception occured, and the processor
263
         *    does not have the extra exceptions feature enabled, or you
264
         *    have not registered a handler using
265
         *    alt_instruction_exception_register()
266
         *
267
         *  Some examples of instruction-generated exceptions and why they
268
         *  might occur:
269
         *
270
         *  - Your program could have been compiled for a full-featured
271
         *    Nios II core, but it is running on a smaller core, and
272
         *    instruction emulation has been disabled by defining
273
         *    ALT_NO_INSTRUCTION_EMULATION.
274
         *
275
         *    You can work around the problem by re-enabling instruction
276
         *    emulation, or you can figure out why your program is being
277
         *    compiled for a system other than the one that it is running on.
278
         *
279
         *  - Your program has executed a trap instruction, but has not
280
         *    implemented a handler for this instruction.
281
         *
282
         *  - Your program has executed an illegal instruction (one which is
283
         *    not defined in the instruction set).
284
         *
285
         *  - Your processor includes an MMU or MPU, and you have enabled it
286
         *    before registering an exception handler to service exceptions it
287
         *    generates.
288
         *
289
         * The problem could also be hardware related:
290
         *  - If your hardware is broken and is generating spurious interrupts
291
         *    (a peripheral which negates its interrupt output before its
292
         *    interrupt handler has been executed will cause spurious
293
         *    interrupts)
294
         */
295
alt_exception_unknown:
296
#ifdef NIOS2_HAS_DEBUG_STUB
297
       /*
298
        *  Either tell the user now (if there is a debugger attached) or go into
299
        *  the debug monitor which will loop until a debugger is attached.
300
        */
301
        break
302
#else /* NIOS2_HAS_DEBUG_STUB disabled */
303
       /*
304
        *  If there is no debug stub, an infinite loop is more useful.
305
        */
306
        br   alt_exception_unknown
307
#endif /* NIOS2_HAS_DEBUG_STUB */
308
#endif /* ALT_INCLUDE_INSTRUCTION_RELATED_EXCEPTION_API */
309
 
310
        .section .exceptions.exit.label
311
.Lexception_exit:
312
 
313
        .section .exceptions.exit, "xa"
314
 
315
        /*
316
         * Restore the saved registers, so that all general purpose registers
317
         * have been restored to their state at the time the interrupt occured.
318
         */
319
 
320
        ldw   r5,  68(sp)
321
        ldw   ea,  72(sp)  /* This becomes the PC once eret is executed */
322
        ldw   ra,   0(sp)
323
 
324
        wrctl estatus, r5
325
 
326
        ldw   r1,   8(sp)
327
        ldw   r2,  12(sp)
328
        ldw   r3,  16(sp)
329
        ldw   r4,  20(sp)
330
        ldw   r5,  24(sp)
331
        ldw   r6,  28(sp)
332
        ldw   r7,  32(sp)
333
 
334
#if defined(ALT_EXCEPTION_STACK) && defined(ALT_STACK_CHECK)
335
        ldw   et, %gprel(alt_exception_old_stack_limit)(gp)
336
#endif
337
 
338
        ldw   r8,  36(sp)
339
        ldw   r9,  40(sp)
340
        ldw   r10, 44(sp)
341
        ldw   r11, 48(sp)
342
        ldw   r12, 52(sp)
343
        ldw   r13, 56(sp)
344
        ldw   r14, 60(sp)
345
        ldw   r15, 64(sp)
346
 
347
#ifdef ALT_EXCEPTION_STACK
348
#ifdef ALT_STACK_CHECK
349
        stw   et, %gprel(alt_stack_limit_value)(gp)
350
        stw   zero, %gprel(alt_exception_old_stack_limit)(gp)
351
#endif /* ALT_STACK_CHECK */
352
        ldw   sp,  76(sp)
353
#else /* ALT_EXCEPTION_STACK disabled */
354
        addi  sp, sp, 76
355
#endif /* ALT_EXCEPTION_STACK */
356
 
357
        /*
358
         * Return to the interrupted instruction.
359
         */
360
 
361
        eret
362
 
363
#ifdef ALT_STACK_CHECK
364
.Lstack_overflow:
365
        break 3
366
#endif /* ALT_STACK_CHECK */
367
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.