summaryrefslogtreecommitdiff
path: root/ecos/packages/hal/powerpc/arch/current/src/context.S
blob: fd0f5b280ee02003a7775999d867fbdbe4d0e8fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
##=============================================================================
##
##      context.S
##
##      PowerPC context switch code
##
##=============================================================================
## ####ECOSGPLCOPYRIGHTBEGIN####                                            
## -------------------------------------------                              
## This file is part of eCos, the Embedded Configurable Operating System.   
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
##
## eCos is free software; you can redistribute it and/or modify it under    
## the terms of the GNU General Public License as published by the Free     
## Software Foundation; either version 2 or (at your option) any later      
## version.                                                                 
##
## eCos is distributed in the hope that it will be useful, but WITHOUT      
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
## for more details.                                                        
##
## You should have received a copy of the GNU General Public License        
## along with eCos; if not, write to the Free Software Foundation, Inc.,    
## 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
##
## As a special exception, if other files instantiate templates or use      
## macros or inline functions from this file, or you compile this file      
## and link it with other works to produce a work based on this file,       
## this file does not by itself cause the resulting work to be covered by   
## the GNU General Public License. However the source code for this file    
## must still be made available in accordance with section (3) of the GNU   
## General Public License v2.                                               
##
## This exception does not invalidate any other reasons why a work based    
## on this file might be covered by the GNU General Public License.         
## -------------------------------------------                              
## ####ECOSGPLCOPYRIGHTEND####                                              
##=============================================================================
#######DESCRIPTIONBEGIN####
##
## Author(s):   nickg
## Contributors:        nickg
## Date:        1998-04-27
## Purpose:     PowerPC context switch code
## Description: This file contains implementations of the thread context 
##              switch routines. It also contains the longjmp() and setjmp()
##              routines.
##
######DESCRIPTIONEND####
##
##=============================================================================

#include <pkgconf/hal.h>
        
#include <cyg/hal/arch.inc>
#include <cyg/hal/ppc_offsets.inc>

#------------------------------------------------------------------------------
# Configure to use either a minimal or maximal thread state
        
#ifdef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM

#define MIN_SAVE_REG    13
#define MAX_SAVE_REG    31

        .macro  save_special
        .endm

        .macro  load_special
        .endm
#else

#define MIN_SAVE_REG     6
#define MAX_SAVE_REG    31

        .macro  save_special
        mfxer   r6
        mfctr   r7
        stw     r6,CYGARC_PPCREG_XER(sp)
        stw     r7,CYGARC_PPCREG_CTR(sp)
        .endm

        .macro  load_special
        lwz     r6,CYGARC_PPCREG_XER(sp)
        lwz     r7,CYGARC_PPCREG_CTR(sp)
        mtxer   r6
        mtctr   r7
        .endm
                
#endif                  

#ifdef CYGHWR_HAL_POWERPC_FPU
#ifdef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM

#define MIN_CONTEXT_SAVE_FREG   14
#define MAX_CONTEXT_SAVE_FREG   31

#else

#define MIN_CONTEXT_SAVE_FREG    0
#define MAX_CONTEXT_SAVE_FREG   31

#endif
#endif
                
#------------------------------------------------------------------------------
# hal_thread_switch_context
# Switch thread contexts
# R3 = address of sp of next thread to execute
# R4 = address of sp save location of current thread

        
FUNC_START(hal_thread_switch_context)
        mr      r5,sp                   # R5 = saved stack pointer
        subi    sp,sp,CYGARC_PPC_CONTEXT_SIZE  # space for state

        # Save registers MIN..MAX
        .set    _reg,MIN_SAVE_REG
        .rept   MAX_SAVE_REG+1-MIN_SAVE_REG
        stw     _reg,(CYGARC_PPCREG_REGS+_reg*4)(sp)
        .set    _reg,_reg+1
        .endr

#ifdef CYGHWR_HAL_POWERPC_FPU
        # Save floating point MIN..MAX
        .set    _freg, MIN_CONTEXT_SAVE_FREG
        .rept   MAX_CONTEXT_SAVE_FREG+1-MIN_CONTEXT_SAVE_FREG
        stfd    _freg,(CYGARC_PPCREG_FREGS+_freg*8)(sp)
        .set    _freg, _freg+1
        .endr
#endif

        stw     r0,CYGARC_PPCREG_REGS+0*4(sp)  # R0
        stw     r5,CYGARC_PPCREG_REGS+1*4(sp)  # R5 = real SP, save in R1 slot
        stw     r2,CYGARC_PPCREG_REGS+2*4(sp)  # R2 = TOC

        # CR cannot be treated as a special register since GCC will only
        # do partial restore of CR at function exit, depending on which
        # of CR2, CR3, and CR4 have been used in the given function.
        mfcr    r5                      # save CR.
        stw     r5,CYGARC_PPCREG_CR(sp)

#ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT
        # Make the thread context look like an exception context if thread-
        # aware debugging is required. This state does not need restoring.
        mflr    r5
        stw     r5,CYGARC_PPCREG_PC(sp) # pc of caller
#endif

        mfmsr   r5
        stw     r5,CYGARC_PPCREG_MSR(sp)# msr (or PS)

        save_special                    # save special regs
        
        mflr    r5                      # save LR == return link for this fn
        stw     r5,CYGARC_PPCREG_LR(sp)
        
        stw     sp,0(r4)                # save SP into save location

        # Now load the destination thread by dropping through
        # to hal_thread_load_context
        
#------------------------------------------------------------------------------
# hal_thread_load_context
# Load thread context
# R3 = address of sp of next thread to execute
# Note that this function is also the second half of hal_thread_switch_context
# and is simply dropped into from it.
        
FUNC_START(hal_thread_load_context)
        
        lwz     sp,0(r3)                # load state directly into SP

        load_special                    # load special registers

        lwz     r5,CYGARC_PPCREG_CR(sp) # restore CR
        mtcr    r5

        lwz     r5,CYGARC_PPCREG_LR(sp) # get LR as set as return link
        mtlr    r5
                
        # Load registers MIN..MAX
        .set    _reg,MIN_SAVE_REG
        .rept   MAX_SAVE_REG+1-MIN_SAVE_REG
        lwz     _reg,(CYGARC_PPCREG_REGS+_reg*4)(sp)
        .set    _reg,_reg+1
        .endr

#ifdef CYGHWR_HAL_POWERPC_FPU
        # Load floating registers MIN..MAX
        .set    _freg, MIN_CONTEXT_SAVE_FREG
        .rept   MAX_CONTEXT_SAVE_FREG+1-MIN_CONTEXT_SAVE_FREG
        lfd     _freg,(CYGARC_PPCREG_FREGS+_freg*8)(sp)
        .set    _freg,_freg+1
        .endr
#endif

        lwz     r3,CYGARC_PPCREG_MSR(sp)       # merge interrupt state
        hal_cpu_int_merge r3,r2

        lwz     r0,CYGARC_PPCREG_REGS+0*4(sp)  # R0
        lwz     r2,CYGARC_PPCREG_REGS+2*4(sp)  # R2 = TOC
        lwz     r3,CYGARC_PPCREG_REGS+3*4(sp)  # load r3
        
        lwz     sp,CYGARC_PPCREG_REGS+1*4(sp)  # finally restore true SP
        
        blr                             # jump to LR
                        
#------------------------------------------------------------------------------
# HAL longjmp, setjmp implementations
# hal_setjmp saves only to callee save registers 13-31, r1[sp],r2, cr[2-4]
# and lr into buffer supplied in r3[arg0]

FUNC_START(hal_setjmp)
        mfcr    r5
        stw     r5, CYGARC_JMPBUF_CR(r3)
        mflr    r5
        stw     r5, CYGARC_JMPBUF_LR(r3)
        stw     r31,CYGARC_JMPBUF_R31(r3)
        stw     r30,CYGARC_JMPBUF_R30(r3)
        stw     r29,CYGARC_JMPBUF_R29(r3)
        stw     r28,CYGARC_JMPBUF_R28(r3)
        stw     r27,CYGARC_JMPBUF_R27(r3)
        stw     r26,CYGARC_JMPBUF_R26(r3)
        stw     r25,CYGARC_JMPBUF_R25(r3)
        stw     r24,CYGARC_JMPBUF_R24(r3)
        stw     r23,CYGARC_JMPBUF_R23(r3)
        stw     r22,CYGARC_JMPBUF_R22(r3)
        stw     r21,CYGARC_JMPBUF_R21(r3)
        stw     r20,CYGARC_JMPBUF_R20(r3)
        stw     r19,CYGARC_JMPBUF_R19(r3)
        stw     r18,CYGARC_JMPBUF_R18(r3)
        stw     r17,CYGARC_JMPBUF_R17(r3)
        stw     r16,CYGARC_JMPBUF_R16(r3)
        stw     r15,CYGARC_JMPBUF_R15(r3)
        stw     r14,CYGARC_JMPBUF_R14(r3)
        stw     r13,CYGARC_JMPBUF_R13(r3)
#ifdef CYGHWR_HAL_POWERPC_FPU
        stfd    f31,CYGARC_JMPBUF_F31(r3)
        stfd    f30,CYGARC_JMPBUF_F30(r3)
        stfd    f29,CYGARC_JMPBUF_F29(r3)
        stfd    f28,CYGARC_JMPBUF_F28(r3)
        stfd    f27,CYGARC_JMPBUF_F27(r3)
        stfd    f26,CYGARC_JMPBUF_F26(r3)
        stfd    f25,CYGARC_JMPBUF_F25(r3)
        stfd    f24,CYGARC_JMPBUF_F24(r3)
        stfd    f23,CYGARC_JMPBUF_F23(r3)
        stfd    f22,CYGARC_JMPBUF_F22(r3)
        stfd    f21,CYGARC_JMPBUF_F21(r3)
        stfd    f20,CYGARC_JMPBUF_F20(r3)
        stfd    f19,CYGARC_JMPBUF_F19(r3)
        stfd    f18,CYGARC_JMPBUF_F18(r3)
        stfd    f17,CYGARC_JMPBUF_F17(r3)
        stfd    f16,CYGARC_JMPBUF_F16(r3)
        stfd    f15,CYGARC_JMPBUF_F15(r3)
        stfd    f14,CYGARC_JMPBUF_F14(r3)
#endif
        stw     r2, CYGARC_JMPBUF_R2(r3)        # TOC, optimize out?
        stw     sp, CYGARC_JMPBUF_SP(r3)
        li      r3,0            # return 0
        blr

# hal_longjmp loads state from r3[arg0] and returns
# to the setjmp caller with r4[arg1] as return value 

FUNC_START(hal_longjmp)
        lwz     r5,CYGARC_JMPBUF_CR(r3)
        mtcr    r5
        lwz     r5,CYGARC_JMPBUF_LR(r3)
        mtlr    r5
        lwz     r31,CYGARC_JMPBUF_R31(r3)
        lwz     r30,CYGARC_JMPBUF_R30(r3)
        lwz     r29,CYGARC_JMPBUF_R29(r3)
        lwz     r28,CYGARC_JMPBUF_R28(r3)
        lwz     r27,CYGARC_JMPBUF_R27(r3)
        lwz     r26,CYGARC_JMPBUF_R26(r3)
        lwz     r25,CYGARC_JMPBUF_R25(r3)
        lwz     r24,CYGARC_JMPBUF_R24(r3)
        lwz     r23,CYGARC_JMPBUF_R23(r3)
        lwz     r22,CYGARC_JMPBUF_R22(r3)
        lwz     r21,CYGARC_JMPBUF_R21(r3)
        lwz     r20,CYGARC_JMPBUF_R20(r3)
        lwz     r19,CYGARC_JMPBUF_R19(r3)
        lwz     r18,CYGARC_JMPBUF_R18(r3)
        lwz     r17,CYGARC_JMPBUF_R17(r3)
        lwz     r16,CYGARC_JMPBUF_R16(r3)
        lwz     r15,CYGARC_JMPBUF_R15(r3)
        lwz     r14,CYGARC_JMPBUF_R14(r3)
        lwz     r13,CYGARC_JMPBUF_R13(r3)
#ifdef CYGHWR_HAL_POWERPC_FPU
        lfd     f31,CYGARC_JMPBUF_F31(r3)
        lfd     f30,CYGARC_JMPBUF_F30(r3)
        lfd     f29,CYGARC_JMPBUF_F29(r3)
        lfd     f28,CYGARC_JMPBUF_F28(r3)
        lfd     f27,CYGARC_JMPBUF_F27(r3)
        lfd     f26,CYGARC_JMPBUF_F26(r3)
        lfd     f25,CYGARC_JMPBUF_F25(r3)
        lfd     f24,CYGARC_JMPBUF_F24(r3)
        lfd     f23,CYGARC_JMPBUF_F23(r3)
        lfd     f22,CYGARC_JMPBUF_F22(r3)
        lfd     f21,CYGARC_JMPBUF_F21(r3)
        lfd     f20,CYGARC_JMPBUF_F20(r3)
        lfd     f19,CYGARC_JMPBUF_F19(r3)
        lfd     f18,CYGARC_JMPBUF_F18(r3)
        lfd     f17,CYGARC_JMPBUF_F17(r3)
        lfd     f16,CYGARC_JMPBUF_F16(r3)
        lfd     f15,CYGARC_JMPBUF_F15(r3)
        lfd     f14,CYGARC_JMPBUF_F14(r3)
#endif
        lwz     r2, CYGARC_JMPBUF_R2(r3)
        lwz     sp, CYGARC_JMPBUF_SP(r3)
        mr      r3,r4           # return r4[arg1]
        blr

#------------------------------------------------------------------------------
# end of context.S