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

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

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

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