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

Subversion Repositories ao486

[/] [ao486/] [trunk/] [syn/] [components/] [sd_card/] [software/] [exe_bsp/] [HAL/] [src/] [alt_exception_entry.S] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 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
 
61
        .globl __alt_exception_stack_pointer
62
 
63
#ifdef ALT_STACK_CHECK
64
 
65
        .globl __alt_exception_stack_limit
66
 
67
        /*
68
         * We need to store the value of the stack limit after interrupt somewhere.
69
         */
70
        .globl  alt_exception_old_stack_limit
71
 
72
#endif
73
#endif
74
 
75
        .section .exceptions.entry.label, "xa"
76
 
77
        .globl alt_exception
78
        .type alt_exception, @function
79
alt_exception:
80
 
81
        .section .exceptions.entry, "xa"
82
 
83
#ifdef ALT_EXCEPTION_STACK
84
 
85
#ifdef ALT_STACK_CHECK
86
        stw   et, %gprel(alt_exception_old_stack_limit)(gp)
87
#endif
88
 
89
        movhi et, %hiadj(__alt_exception_stack_pointer - 80)
90
        addi  et, et, %lo(__alt_exception_stack_pointer - 80)
91
        stw   sp, 76(et)
92
        mov   sp, et
93
 
94
#ifdef ALT_STACK_CHECK
95
        movhi et, %hiadj(__alt_exception_stack_limit)
96
        addi  et, et, %lo(__alt_exception_stack_limit)
97
        stw   et, %gprel(alt_stack_limit_value)(gp)
98
#endif
99
 
100
#else
101
        /*
102
         * Process an exception.  For all exceptions we must preserve all
103
         * caller saved registers on the stack (See the Nios2 ABI
104
         * documentation for details).
105
         */
106
 
107
        addi  sp, sp, -76
108
 
109
#ifdef ALT_STACK_CHECK
110
 
111
        bltu  sp, et, .Lstack_overflow
112
 
113
#endif
114
 
115
#endif
116
 
117
        stw   ra,  0(sp)
118
 
119
        /*
120
         * Leave a gap in the stack frame at 4(sp) for the muldiv handler to
121
         * store zero into.
122
         */
123
 
124
        stw   r1,   8(sp)
125
        stw   r2,  12(sp)
126
        stw   r3,  16(sp)
127
        stw   r4,  20(sp)
128
        stw   r5,  24(sp)
129
        stw   r6,  28(sp)
130
        stw   r7,  32(sp)
131
 
132
        rdctl r5, estatus
133
 
134
        stw   r8,  36(sp)
135
        stw   r9,  40(sp)
136
        stw   r10, 44(sp)
137
        stw   r11, 48(sp)
138
        stw   r12, 52(sp)
139
        stw   r13, 56(sp)
140
        stw   r14, 60(sp)
141
        stw   r15, 64(sp)
142
 
143
        /*
144
         * ea-4 contains the address of the instruction being executed
145
         * when the exception occured. For interrupt exceptions, we will
146
         * will be re-issue the isntruction. Store it in 72(sp)
147
         */
148
        stw   r5,  68(sp)  /* estatus */
149
        addi  r15, ea, -4  /* instruction that caused exception */
150
        stw   r15,  72(sp)
151
 
152
        /*
153
         * The interrupt testing code (.exceptions.irqtest) will be
154
         * linked here. If the Internal Interrupt Controller (IIC) is
155
         * present (an EIC is not present), the presense of an interrupt
156
         * is determined by examining CPU control registers or an interrupt
157
         * custom instruction, if present.
158
         *
159
         * If the IIC is used and an interrupt is active, the code linked
160
         * here will call the HAL IRQ handler (alt_irq_handler()) which
161
         * successively calls registered interrupt handler(s) until no
162
         * interrupts remain pending. It then jumps to .exceptions.exit. If
163
         * there is no interrupt then it continues to .exception.notirq, below.
164
         */
165
 
166
        .section .exceptions.notirq, "xa"
167
 
168
        /*
169
         * Prepare to service unimplemtned instructions or traps,
170
         * each of which is optionally inked into section .exceptions.soft,
171
         * which will preceed .exceptions.unknown below.
172
         *
173
         * Unlike interrupts, we want to skip the exception-causing instructon
174
         * upon completion, so we write ea (address of instruction *after*
175
         * the one where the exception occured) into 72(sp). The actual
176
         * instruction that caused the exception is written in r2, which these
177
         * handlers will utilize.
178
         */
179
        stw   ea,  72(sp)  /* Don't re-issue */
180
        ldw   r2, -4(ea)   /* Instruction that caused exception */
181
 
182
        /*
183
         * Other exception handling code, if enabled, will be linked here.
184
         * This includes unimplemted (multiply/divide) instruction support
185
         * (a BSP generaton option), and a trap handler (that would typically
186
         * be augmented with user-specific code). These are not linked in by
187
         * default.
188
         */
189
 
190
        /*
191
         * In the context of linker sections, "unknown" are all exceptions
192
         * not handled by the built-in handlers above (interupt, and trap or
193
         * unimplemented instruction decoding, if enabled).
194
         *
195
         * Advanced exception types can be serviced by registering a handler.
196
         * To do so, enable the "Enable Instruction-related Exception API" HAL
197
         * BSP setting. If this setting is disabled, this handler code will
198
         * either break (if the debug core is present) or enter an infinite
199
         * loop because we don't how how to handle the exception.
200
         */
201
        .section .exceptions.unknown
202
#ifdef ALT_INCLUDE_INSTRUCTION_RELATED_EXCEPTION_API
203
        /*
204
         * The C-based HAL routine alt_instruction_exception_entry() will
205
         * attempt to service the exception by calling a user-registered
206
         * exception handler using alt_instruction_exception_register().
207
         * If no handler was registered it will either break (if the
208
         * debugger is present) or go into an infinite loop since the
209
         * handling behavior is undefined; in that case we will not return here.
210
         */
211
 
212
        /* Load exception-causing address as first argument (r4) */
213
        addi   r4, ea, -4
214
 
215
        /* Call the instruction-exception entry */
216
        call   alt_instruction_exception_entry
217
 
218
        /*
219
         * If alt_instruction_exception_entry() returned, the exception was
220
         * serviced by a user-registered routine. Its return code (now in r2)
221
         * indicates whether to re-issue or skip the exception-causing
222
         * instruction
223
         *
224
         * Return code was 0: Skip. The instruction after the exception is
225
         * already stored in 72(sp).
226
         */
227
        bne   r2, r0, .Lexception_exit
228
 
229
        /*
230
         * Otherwise, modify 72(sp) to re-issue the instruction that caused the
231
         * exception.
232
         */
233
        addi  r15, ea, -4  /* instruction that caused exception */
234
        stw   r15,  72(sp)
235
 
236
#else /* ALT_INCLUDE_INSTRUCTION_RELATED_EXCEPTION_API disabled */
237
 
238
        /*
239
         * We got here because an instruction-related exception occured, but the
240
         * handler API was not compiled in. We do not presume to know how to
241
         * handle it. If the debugger is present, break, otherwise hang.
242
         *
243
         *  If you get here then one of the following could have happened:
244
         *
245
         *  - An instruction-generated exception occured, and the processor
246
         *    does not have the extra exceptions feature enabled, or you
247
         *    have not registered a handler using
248
         *    alt_instruction_exception_register()
249
         *
250
         *  Some examples of instruction-generated exceptions and why they
251
         *  might occur:
252
         *
253
         *  - Your program could have been compiled for a full-featured
254
         *    Nios II core, but it is running on a smaller core, and
255
         *    instruction emulation has been disabled by defining
256
         *    ALT_NO_INSTRUCTION_EMULATION.
257
         *
258
         *    You can work around the problem by re-enabling instruction
259
         *    emulation, or you can figure out why your program is being
260
         *    compiled for a system other than the one that it is running on.
261
         *
262
         *  - Your program has executed a trap instruction, but has not
263
         *    implemented a handler for this instruction.
264
         *
265
         *  - Your program has executed an illegal instruction (one which is
266
         *    not defined in the instruction set).
267
         *
268
         *  - Your processor includes an MMU or MPU, and you have enabled it
269
         *    before registering an exception handler to service exceptions it
270
         *    generates.
271
         *
272
         * The problem could also be hardware related:
273
         *  - If your hardware is broken and is generating spurious interrupts
274
         *    (a peripheral which negates its interrupt output before its
275
         *    interrupt handler has been executed will cause spurious
276
         *    interrupts)
277
         */
278
#ifdef NIOS2_HAS_DEBUG_STUB
279
       /*
280
        *  Either tell the user now (if there is a debugger attached) or go into
281
        *  the debug monitor which will loop until a debugger is attached.
282
        */
283
        break
284
#else
285
       /*
286
        *  If there is no debug stub then a BREAK will probably cause a reboot.
287
        *  An infinate loop will probably be more useful.
288
        */
289
0:
290
        br   0b
291
#endif /* NIOS2_HAS_DEBUG_STUB */
292
 
293
#endif /* ALT_INCLUDE_INSTRUCTION_RELATED_EXCEPTION_API */
294
 
295
        .section .exceptions.exit.label
296
.Lexception_exit:
297
 
298
        .section .exceptions.exit, "xa"
299
 
300
        /*
301
         * Restore the saved registers, so that all general purpose registers
302
         * have been restored to their state at the time the interrupt occured.
303
         */
304
 
305
        ldw   r5,  68(sp)
306
        ldw   ea,  72(sp)  /* This becomes the PC once eret is executed */
307
        ldw   ra,   0(sp)
308
 
309
        wrctl estatus, r5
310
 
311
        ldw   r1,   8(sp)
312
        ldw   r2,  12(sp)
313
        ldw   r3,  16(sp)
314
        ldw   r4,  20(sp)
315
        ldw   r5,  24(sp)
316
        ldw   r6,  28(sp)
317
        ldw   r7,  32(sp)
318
 
319
#ifdef ALT_EXCEPTION_STACK
320
#ifdef ALT_STACK_CHECK
321
        ldw   et, %gprel(alt_exception_old_stack_limit)(gp)
322
#endif
323
#endif
324
 
325
        ldw   r8,  36(sp)
326
        ldw   r9,  40(sp)
327
        ldw   r10, 44(sp)
328
        ldw   r11, 48(sp)
329
        ldw   r12, 52(sp)
330
        ldw   r13, 56(sp)
331
        ldw   r14, 60(sp)
332
        ldw   r15, 64(sp)
333
 
334
#ifdef ALT_EXCEPTION_STACK
335
 
336
#ifdef ALT_STACK_CHECK
337
        stw   et, %gprel(alt_stack_limit_value)(gp)
338
        stw   zero, %gprel(alt_exception_old_stack_limit)(gp)
339
#endif
340
 
341
        ldw   sp,  76(sp)
342
 
343
#else
344
        addi  sp, sp, 76
345
 
346
#endif
347
 
348
        /*
349
         * Return to the interrupted instruction.
350
         */
351
 
352
        eret
353
 
354
#ifdef ALT_STACK_CHECK
355
 
356
.Lstack_overflow:
357
        break 3
358
 
359
#endif
360
 

powered by: WebSVN 2.1.0

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