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

4.104.114.84.95
Last change on this file since f172fc89 was 50f4487, checked in by Joel Sherrill <joel.sherrill@…>, on 08/09/06 at 20:58:11

2006-08-09 Kolja Waschk <waschk@…>

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