source: rtems/cpukit/score/cpu/avr/cpu_asm.S @ bfc76f9

4.11
Last change on this file since bfc76f9 was bfc76f9, checked in by Joel Sherrill <joel.sherrill@…>, on Jul 30, 2010 at 6:52:12 PM

2010-07-30 Gedare Bloom <giddyup44@…>

PR 1599/cpukit

  • cpu_asm.S: Rename _Context_Switch_necessary to _Thread_Dispatch_necessary to more properly reflect the intent.
  • Property mode set to 100644
File size: 10.0 KB
Line 
1/*  cpu_asm.c  ===> cpu_asm.S or cpu_asm.s
2 *
3 *  This file contains the basic algorithms for all assembly code used
4 *  in an specific CPU port of RTEMS.  These algorithms must be implemented
5 *  in assembly language
6 *
7 *  NOTE:  This is supposed to be a .S or .s file NOT a C file.
8 *
9 *  COPYRIGHT (c) 1989-2008.
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 *  $Id$
17 */
18
19/*
20 *  This is supposed to be an assembly file.  This means that system.h
21 *  and cpu.h should not be included in a "real" cpu_asm file.  An
22 *  implementation in assembly should include "cpu_asm.h>
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include <rtems/asm.h>
30#include <avr/sfr_defs.h>
31#include <rtems/score/percpu.h>
32
33
34#define jmpb_hi         r25
35#define jmpb_lo         r24
36#define val_hi          r23
37#define val_lo          r22
38
39#define ret_lo          r24
40#define ret_hi          r25
41
42        PUBLIC( setjmp )
43
44SYM( setjmp ):
45        X_movw          XL, jmpb_lo
46/*;save call-saved registers and frame pointer*/
47        .irp            .L_regno, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,28,29
48        st              X+, r\.L_regno
49        .endr
50/*;get return address*/
51       
52        pop             ZH
53        pop             ZL
54/*save stack pointer (after popping)*/
55       
56        in              ret_lo,         AVR_STACK_POINTER_LO_ADDR
57        st              X+, ret_lo
58       
59#ifdef _HAVE_AVR_STACK_POINTER_HI
60        in              ret_lo, AVR_STACK_POINTER_HI_ADDR
61        st              X+, ret_lo
62#else
63        st              X+, ret_lo
64#endif
65/*save status reg (I flag)*/
66        in              ret_lo, AVR_STATUS_ADDR
67        st              X+, ret_lo
68/*save return addr*/
69        st              X+, ZL
70        st              X+, ZH
71/*return zero*/
72        clr             ret_hi
73        clr             ret_lo
74        ijmp
75
76        .size           _U(setjmp),.-_U(setjmp)
77
78
79        .global _U(longjmp)
80        .type _U(longjmp), @function
81
82_U(longjmp):
83        X_movw          XL, jmpb_lo
84/*return value*/
85        X_movw          ret_lo, val_lo
86/*if zero, change to 1*/
87        cpi             ret_lo, 1
88        cpc             ret_hi, __zero_reg__
89        adc             ret_lo, __zero_reg__
90/*restore call-saved registers and frame pointer*/
91        .irp    .L_regno, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,28,29
92        ld      r\.L_regno, X+
93        .endr
94/*; restore stack pointer (SP value before the setjmp() call) and SREG*/
95        ld      ZL, X+
96        ld      ZH, X+
97        ld      __tmp_reg__, X+
98#if  defined (__AVR_XMEGA__) && __AVR_XMEGA__
99        /* A write to SPL will automatically disable interrupts for up to 4
100           instructions or until the next I/O memory write.     */
101        out     AVR_STATUS_ADDR, __tmp_reg__
102        out     AVR_STACK_POINTER_LO_ADDR, ZL
103        out     AVR_STACK_POINTER_HI_ADDR, ZH
104#else
105# ifdef _HAVE_AVR_STACK_POINTER_HI
106        /* interrupts disabled for shortest possible time (3 cycles) */
107        cli
108        out     AVR_STACK_POINTER_HI_ADDR, ZH
109# endif
110        /* Restore status register (including the interrupt enable flag).
111           Interrupts are re-enabled only after the next instruction.  */
112        out     AVR_STATUS_ADDR, __tmp_reg__
113        out     AVR_STACK_POINTER_LO_ADDR, ZL
114#endif
115  ; get return address and jump
116        ld      ZL, X+
117        ld      ZH, X+
118#if  defined(__AVR_3_BYTE_PC__) && __AVR_3_BYTE_PC__
119        ld      __tmp_reg__, X+
120.L_jmp3:
121        push    ZL
122        push    ZH
123        push    __tmp_reg__
124        ret
125#else
126        ijmp
127#endif
128        .size   _U(longjmp), . - _U(longjmp)
129
130
131
132/*
133 *  _CPU_Context_save_fp_context
134 *
135 *  This routine is responsible for saving the FP context
136 *  at *fp_context_ptr.  If the point to load the FP context
137 *  from is changed then the pointer is modified by this routine.
138 *
139 *  Sometimes a macro implementation of this is in cpu.h which dereferences
140 *  the ** and a similarly named routine in this file is passed something
141 *  like a (Context_Control_fp *).  The general rule on making this decision
142 *  is to avoid writing assembly language.
143 *
144 *  NO_CPU Specific Information:
145 *
146 *  XXX document implementation including references if appropriate
147
148
149void _CPU_Context_save_fp(
150  Context_Control_fp **fp_context_ptr
151)
152{
153}
154*/
155
156        PUBLIC(_CPU_Context_save_fp)
157
158SYM(_CPU_Context_save_fp):
159        ret
160
161
162       
163
164
165
166
167/*
168 *  _CPU_Context_restore_fp_context
169 *
170 *  This routine is responsible for restoring the FP context
171 *  at *fp_context_ptr.  If the point to load the FP context
172 *  from is changed then the pointer is modified by this routine.
173 *
174 *  Sometimes a macro implementation of this is in cpu.h which dereferences
175 *  the ** and a similarly named routine in this file is passed something
176 *  like a (Context_Control_fp *).  The general rule on making this decision
177 *  is to avoid writing assembly language.
178 *
179 *  NO_CPU Specific Information:
180 *
181 *  XXX document implementation including references if appropriate
182
183
184void _CPU_Context_restore_fp(
185  Context_Control_fp **fp_context_ptr
186)
187{
188}
189*/
190
191
192        PUBLIC(_CPU_Context_restore_fp)
193
194SYM(_CPU_Context_restore_fp):
195        ret
196
197
198
199/*  _CPU_Context_switch
200 *
201 *  This routine performs a normal non-FP context switch.
202 *
203 *  NO_CPU Specific Information:
204 *
205 *  XXX document implementation including references if appropriate
206 void _CPU_Context_switch(
207  Context_Control  *run,
208  Context_Control  *heir
209);
210
211*/
212
213        PUBLIC(_CPU_Context_switch)
214SYM(_CPU_Context_switch):
215        mov     r26, r24        /*r26,r27 is X*/
216        mov     r27, r25
217        mov     r24, r22
218        mov     r25, r23
219        /*save registers*/
220#if 1
221/*if this section is removed there is a problem.*/
222/*debug section start*/
223        pop     r22
224        pop     r23
225        push    r22
226        push    r23
227/*debug section end*/
228#endif
229
230        push    r2
231        push    r3
232        push    r4
233        push    r5
234        push    r6
235        push    r7
236        push    r8
237        push    r9
238        push    r10
239        push    r11
240        push    r12
241        push    r13
242        push    r14
243        push    r15
244        push    r16
245        push    r17
246
247        push    r28
248        push    r29
249
250        /*load sreg*/
251        lds     r23,0x5f  /*load sreg*/
252        /*disable interrupts*/
253        cli
254        /*load stack pointer*/
255        lds     r22,0x5d /*spl*/
256        lds     r21,0x5e /*sph*/
257        /*save sreg and sp to context struct*/
258
259        /*save low then high byte --- verify this delete when verified*/
260        st      X+, r22
261        st      X+, r21
262        st      X, r23
263
264        PUBLIC(_CPU_Context_restore)
265
266SYM(_CPU_Context_restore):
267        mov     r26,r24         /* R26/27 are X */
268        mov     r27,r25
269
270        /*restore stack pointer*/
271        ld      r25, X+
272        ld      r24, X+
273        sts     0x5E,r24  /*sph*/
274        sts     0x5D ,r25 /*spl*/
275        /*restore registers from stack*/
276
277
278        pop     r29
279        pop     r28
280
281
282        pop     r17
283        pop     r16
284        pop     r15
285        pop     r14
286        pop     r13
287        pop     r12
288        pop     r11
289        pop     r10
290        pop     r9
291        pop     r8
292        pop     r7
293        pop     r6
294        pop     r5
295        pop     r4
296        pop     r3
297        pop     r2
298
299        /*restore sreg*/
300        ld      r25, X
301        sts     0x5f,r25 /*sreg*/
302        pop     r30
303        pop     r31
304        IJMP
305        ret
306
307
308
309/*PAGE
310 *
311 *  _CPU_Context_Initialize
312 *
313 *  This kernel routine initializes the basic non-FP context area associated
314 *  with each thread.
315 *
316 *  Input parameters:
317 *    the_context  - pointer to the context area
318 *    stack_base   - address of memory for the SPARC
319 *    size         - size in bytes of the stack area
320 *    new_level    - interrupt level for this context area
321 *    entry_point  - the starting execution point for this this context
322 *    is_fp        - TRUE if this context is associated with an FP thread
323 *
324 *      the_context is in r25,r24
325 *      entry point is in r13,r12
326 *      stack base is in r23, r22
327 *      size is in r21, r20, r19,r18
328 *      newleve is in r14,r15, r16, 17
329 *
330 *
331 *  Output parameters: NONE
332 */
333
334        PUBLIC(_CPU_Context_Initialize)
335SYM(_CPU_Context_Initialize):
336        //save caller saved regs
337        PUSH    R10
338        PUSH    R11
339        PUSH    R12
340        PUSH    R13
341        PUSH    R14
342        PUSH    R15
343        PUSH    R16
344        PUSH    R17
345        PUSH    R28
346        PUSH    R29
347        //calculate new stack pointer
348        ADD     R22, R18
349        ADC     R23, R19
350        MOV     R26, R22
351        MOV     R27, R23
352        //Initialize stack with entry point
353        ST      -X, R13
354        ST      -X, R12
355        //store new stack pointer in context control
356        SBIW    R26, 0X13       /*subtract 33 to account for registers*/
357        MOV     R28, R24
358        MOV     R29, R25
359        STD     Y+1, R27        //save stack pointer high to context control
360        ST      Y, R26          //save stack pointer low to context control
361        //set interrupt level in new context
362        LDI     R18, 0          //set sreg in new context to zero
363        STD     Y+2, R18        //interrupts not enabled               
364        MOV     R18, R14
365        CPI     R18, 0
366        BRNE    NEW_LEVEL_ZERO
367        LDI     R18, 0X80       //set sreg in new context to 0x80
368        STD     Y+2, R18        //interupts enabled
369NEW_LEVEL_ZERO:
370        //restore caller saved regs
371        POP     R29
372        POP     R28
373        POP     R17
374        POP     R16
375        POP     R15
376        POP     R14
377        POP     R13
378        POP     R12
379        POP     R11
380        POP     R10
381        RET
382       
383
384
385/*  void __ISR_Handler()
386 *
387 *  This routine provides the RTEMS interrupt management.
388 *
389 *  NO_CPU Specific Information:
390 *
391 *  XXX document implementation including references if appropriate
392
393
394void _ISR_Handler(void)
395{
396
397*/
398   /*
399    *  This discussion ignores a lot of the ugly details in a real
400    *  implementation such as saving enough registers/state to be
401    *  able to do something real.  Keep in mind that the goal is
402    *  to invoke a user's ISR handler which is written in C and
403    *  uses a certain set of registers.
404    *
405    *  Also note that the exact order is to a large extent flexible.
406    *  Hardware will dictate a sequence for a certain subset of
407    *  _ISR_Handler while requirements for setting
408    */
409
410  /*
411   *  At entry to "common" _ISR_Handler, the vector number must be
412   *  available.  On some CPUs the hardware puts either the vector
413   *  number or the offset into the vector table for this ISR in a
414   *  known place.  If the hardware does not give us this information,
415   *  then the assembly portion of RTEMS for this port will contain
416   *  a set of distinct interrupt entry points which somehow place
417   *  the vector number in a known place (which is safe if another
418   *  interrupt nests this one) and branches to _ISR_Handler.
419   *
420   *  save some or all context on stack
421   *  may need to save some special interrupt information for exit
422   *
423   *  #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
424   *    if ( _ISR_Nest_level == 0 )
425   *      switch to software interrupt stack
426   *  #endif
427   *
428   *  _ISR_Nest_level++;
429   *
430   *  _Thread_Dispatch_disable_level++;
431   *
432   *  (*_ISR_Vector_table[ vector ])( vector );
433   *
434   *  _Thread_Dispatch_disable_level--;
435   *
436   *  --_ISR_Nest_level;
437   *
438   *  if ( _ISR_Nest_level )
439   *    goto the label "exit interrupt (simple case)"
440   *
441   *  if ( _Thread_Dispatch_disable_level )
442   *    goto the label "exit interrupt (simple case)"
443   *
444   *  if ( _Thread_Dispatch_necessary ) {
445   *    call _Thread_Dispatch() or prepare to return to _ISR_Dispatch
446   *    prepare to get out of interrupt
447   *    return from interrupt  (maybe to _ISR_Dispatch)
448   *
449   *  LABEL "exit interrupt (simple case):
450   *  #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
451   *    if outermost interrupt
452   *      restore stack
453   *  #endif
454   *  prepare to get out of interrupt
455   *  return from interrupt
456   */
457/*}    */
458        PUBLIC(_ISR_Handler)
459
460SYM(_ISR_Handler):
461        ret
Note: See TracBrowser for help on using the repository browser.