source: rtems/cpukit/score/cpu/nios2/cpu_asm.S @ 5632f8d

4.104.11
Last change on this file since 5632f8d was 5632f8d, checked in by Joel Sherrill <joel.sherrill@…>, on Mar 27, 2010 at 3:02:21 PM

2010-03-27 Joel Sherrill <joel.sherrill@…>

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