source: rtems/cpukit/score/cpu/nios2/cpu_asm.S @ 80f7732

4.104.11
Last change on this file since 80f7732 was 80f7732, checked in by Ralf Corsepius <ralf.corsepius@…>, on Dec 2, 2009 at 9:48:25 AM

Whitespace removal.

  • Property mode set to 100644
File size: 8.1 KB
Line 
1/*
2 *  $Id$
3 *
4 *  This file contains all assembly code for the
5 *  NIOS2 implementation of RTEMS.
6 *
7 *  Copyright (c) 2006 Kolja Waschk (rtemsdev/ixo.de)
8 *
9 *  Derived from no_cpu/cpu_asm.S, copyright (c) 1989-1999,
10 *    On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.com/license/LICENSE.
15 *
16 */
17
18#include <rtems/asm.h>
19#include <rtems/score/cpu_asm.h>
20
21    .set noat
22
23/* ===================================================================== */
24
25/*
26 *  void _CPU_Context_switch( run_context, heir_context )
27 *  void _CPU_Context_restore( run_context, heir_context )
28 *
29 *  This routine performs a normal non-FP context switch.
30 */
31
32    .globl _CPU_Context_switch
33
34_CPU_Context_switch:
35
36    rdctl r6, status
37    stw r16,  0(r4)
38    stw r17,  4(r4)
39    stw r18,  8(r4)
40    stw r19, 12(r4)
41    stw r20, 16(r4)
42    stw r21, 20(r4)
43    stw r22, 24(r4)
44    stw r23, 28(r4)
45    stw gp,  32(r4)
46    stw fp,  36(r4)
47    stw sp,  40(r4)
48    stw ra,  44(r4)
49    /* r6 saved status */
50    stw r6,  48(r4)
51
52_CPU_Context_switch_restore:
53
54    ldw r16,  0(r5)
55    ldw r17,  4(r5)
56    ldw r18,  8(r5)
57    ldw r19, 12(r5)
58    ldw r20, 16(r5)
59    ldw r21, 20(r5)
60    ldw r22, 24(r5)
61    ldw r23, 28(r5)
62    ldw gp,  32(r5)
63    ldw fp,  36(r5)
64    ldw sp,  40(r5)
65
66    /* Disable interrupts */
67    wrctl status, r0
68
69    ldw ea,  44(r5)
70    ldw at,  48(r5)
71    /* FIXME: Always have interrupts enabled when we return from Context_switch */
72    ori at, at, 1
73    wrctl estatus, at
74
75    eret
76
77    .globl _CPU_Context_restore
78
79_CPU_Context_restore:
80
81    /* Copy first to second arg, then re-use 2nd half of Context_switch */
82    mov r5, r4
83    br  _CPU_Context_switch_restore
84
85
86/* ===================================================================== */
87
88    .globl _exception_vector
89
90_exception_vector:
91
92    /*
93     * First, re-wind so we're pointed to the instruction where the exception
94     * occurred.
95     */
96
97    addi ea, ea, -4
98
99    /*
100     * Now test to determine the cause of the exception.
101     */
102
103    /* TODO: Look at [ea] if there was an unknown/trap instruction */
104
105    /* If interrupts are globally disabled, it certainly was no interrupt */
106    rdctl et, estatus
107    andi et, et, 1
108    beq et, zero, _Exception_Handler
109
110    /* If no interrupts are pending, it was a software exception */
111    rdctl et, ipending
112    beq et, zero, _Exception_Handler
113
114    /*
115     * Falling through to here means that this was a hardware interrupt.
116     */
117
118    br _ISR_Handler
119
120/* =====================================================================
121 * Exception handler:
122 *   Responsible for unimplemented instructions and other software
123 *   exceptions. Not responsible for hardware interrupts. Currently,
124 *   software exceptions are regarded as error conditions, and the
125 *   handling isn't perfect. */
126
127_Exception_Handler:
128
129    /* stw et, 108(sp') => stw et, -20(sp) */
130    stw et, -20(sp)
131    mov et, sp
132    addi sp, sp, -128
133
134    stw r1,   0(sp)
135    stw r2,   4(sp)
136    stw r3,   8(sp)
137
138    rdctl r1, estatus
139    rdctl r2, ienable
140    rdctl r3, ipending
141
142    stw r4,   12(sp)
143    stw r5,   16(sp)
144    stw r6,   20(sp)
145    stw r7,   24(sp)
146    stw r8,   28(sp)
147    stw r9,   32(sp)
148    stw r10,  36(sp)
149    stw r11,  40(sp)
150    stw r12,  44(sp)
151    stw r13,  48(sp)
152    stw r14,  52(sp)
153    stw r15,  56(sp)
154    stw r16,  60(sp)
155    stw r17,  64(sp)
156    stw r18,  68(sp)
157    stw r19,  72(sp)
158    stw r20,  76(sp)
159    stw r21,  80(sp)
160    stw r22,  84(sp)
161    stw r23,  88(sp)
162    stw gp,   92(sp)
163    stw fp,   96(sp)
164    /* sp */
165    stw et,  100(sp)
166    stw ra,  104(sp)
167    /* stw et,  108(sp) */
168    stw ea,  112(sp)
169
170    /* status */
171    stw r1, 116(sp)
172    /* ienable */
173    stw r2, 120(sp)
174    /* ipending */
175    stw r3, 124(sp)
176
177    /*
178     * Restore the global pointer.
179     */
180
181    movhi gp, %hiadj(_gp)
182    addi gp, gp, %lo(_gp)
183
184    /*
185     * Pass a pointer to the stack frame as the input argument of the
186     * exception handler (CPU_Exception_frame *).
187     */
188
189    mov r4, sp
190
191    /*
192     * Call the exception handler.
193     */
194
195    .extern __Exception_Handler
196    call __Exception_Handler
197
198stuck_in_exception:
199    br stuck_in_exception
200
201    /*
202     * Restore the saved registers, so that all general purpose registers
203     * have been restored to their state at the time the interrupt occured.
204     */
205
206    ldw r1,   0(sp)
207    ldw r2,   4(sp)
208    ldw r3,   8(sp)
209    ldw r4,   12(sp)
210    ldw r5,   16(sp)
211    ldw r6,   20(sp)
212    ldw r7,   24(sp)
213    ldw r8,   28(sp)
214    ldw r9,   32(sp)
215    ldw r10,  36(sp)
216    ldw r11,  40(sp)
217    ldw r12,  44(sp)
218    ldw r13,  48(sp)
219    ldw r14,  52(sp)
220    ldw r15,  56(sp)
221    ldw r16,  60(sp)
222    ldw r17,  64(sp)
223    ldw r18,  68(sp)
224    ldw r19,  72(sp)
225    ldw r20,  76(sp)
226    ldw r21,  80(sp)
227    ldw r22,  84(sp)
228    ldw r23,  88(sp)
229    ldw gp,   92(sp)
230    ldw fp,   96(sp)
231    ldw ra,  104(sp)
232
233    /* Disable interrupts */
234    wrctl status, r0
235
236    ldw ea,  112(sp)
237    ldw et,  116(sp)
238
239    /* FIXME: Enable interrupts after exception processing */
240    ori et, et, 1
241    wrctl estatus, et
242    ldw et,  108(sp)
243
244    /* Restore stack pointer */
245    ldw sp,  100(sp)
246
247    eret
248
249/* ===================================================================== */
250
251    .section .text
252
253_ISR_Handler:
254
255    /*
256     * Process an external hardware interrupt.
257     *
258     * First, preserve all callee saved registers on
259     * the stack. (See the Nios2 ABI documentation for details).
260     *
261     * Do we really need to save all?
262     *
263     * If this is interrupting a task (and not another interrupt),
264     * everything is saved into the task's stack, thus putting us
265     * in a situation similar to when the task calls a subroutine
266     * (and only the CPU_Context_Control subset needs to be changed)
267     */
268
269    rdctl et, estatus
270
271    /* Keep this in the same order as CPU_Interrupt_frame: */
272
273    addi sp, sp, -76
274    stw r1,  0(sp)
275    stw r2,  4(sp)
276    stw r3,  8(sp)
277    stw r4,  12(sp)
278    stw r5,  16(sp)
279    stw r6,  20(sp)
280    stw r7,  24(sp)
281    stw r8,  28(sp)
282    stw r9,  32(sp)
283    stw r10, 36(sp)
284    stw r11, 40(sp)
285    stw r12, 44(sp)
286    stw r13, 48(sp)
287    stw r14, 52(sp)
288    stw r15, 56(sp)
289    stw ra,  60(sp)
290    stw gp,  64(sp)
291    /* et contains status */
292    stw et,  68(sp)
293    stw ea,  72(sp)
294
295    /*
296     * Obtain a bitlist of the pending interrupts.
297     */
298
299    rdctl et, ipending
300
301    /*
302     * Restore the global pointer to the expected value.
303     */
304
305    movhi gp, %hiadj(_gp)
306    addi gp, gp, %lo(_gp)
307
308    /*
309     * Search through the bit list stored in r24(et) to find the first enabled
310     * bit. The offset of this bit is the index of the interrupt that is
311     * to be handled.
312     */
313
314    mov r4, zero
3156:
316    andi r3, r24, 1
317    bne r3, zero, 7f
318    addi r4, r4, 1
319    srli r24, r24, 1
320    br 6b
3217:
322
323    /*
324     * Having located the interrupt source, r4 contains the index of the
325     * interrupt to be handled. r5, the 2nd argument to the function,
326     * will point to the CPU_Interrupt_frame.
327     */
328
329    mov     r5, sp
330
331    .extern __ISR_Handler
332    call    __ISR_Handler
333
334    /*
335     * Now that the interrupt processing is complete, prepare to return to
336     * the interrupted code.
337     */
338
339    /*
340     * Restore the saved registers, so that all general purpose registers
341     * have been restored to their state at the time the interrupt occured.
342     */
343
344    ldw r1,   0(sp)
345    ldw r2,   4(sp)
346    ldw r3,   8(sp)
347    ldw r4,  12(sp)
348    ldw r5,  16(sp)
349    ldw r6,  20(sp)
350    ldw r7,  24(sp)
351    ldw r8,  28(sp)
352    ldw r9,  32(sp)
353    ldw r10, 36(sp)
354    ldw r11, 40(sp)
355    ldw r12, 44(sp)
356    ldw r13, 48(sp)
357    ldw r14, 52(sp)
358    ldw r15, 56(sp)
359    ldw ra,  60(sp)
360    ldw gp,  64(sp)
361
362    /* Disable interrupts */
363    wrctl status, r0
364
365    /* Restore the exception registers */
366
367    /* load saved ea into ea */
368    ldw ea,  72(sp)
369    /* load saved estatus into et */
370    ldw et,  68(sp)
371    /* Always have interrupts enabled when we return from interrupt */
372    ori et, et, 1
373    wrctl estatus, et
374    /* Restore the stack pointer */
375    addi sp, sp, 76
376
377    /*
378     * Return to the interrupted instruction.
379     */
380    eret
381
382
Note: See TracBrowser for help on using the repository browser.