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

4.104.115
Last change on this file since f086af89 was 05c1886, checked in by Ralf Corsepius <ralf.corsepius@…>, on 11/30/09 at 16:01:51

Whitespace removal.

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