]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/hal/synth/i386linux/v2_0/src/context.S
Initial revision
[karo-tx-redboot.git] / packages / hal / synth / i386linux / v2_0 / src / context.S
1 ##=============================================================================
2 ##
3 ##      context.S
4 ##
5 ##      x86 thread context manipulation.
6 ##
7 ##=============================================================================
8 #####ECOSGPLCOPYRIGHTBEGIN####
9 ## -------------------------------------------
10 ## This file is part of eCos, the Embedded Configurable Operating System.
11 ## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 ##
13 ## eCos is free software; you can redistribute it and/or modify it under
14 ## the terms of the GNU General Public License as published by the Free
15 ## Software Foundation; either version 2 or (at your option) any later version.
16 ##
17 ## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 ## WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 ## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 ## for more details.
21 ##
22 ## You should have received a copy of the GNU General Public License along
23 ## with eCos; if not, write to the Free Software Foundation, Inc.,
24 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 ##
26 ## As a special exception, if other files instantiate templates or use macros
27 ## or inline functions from this file, or you compile this file and link it
28 ## with other works to produce a work based on this file, this file does not
29 ## by itself cause the resulting work to be covered by the GNU General Public
30 ## License. However the source code for this file must still be made available
31 ## in accordance with section (3) of the GNU General Public License.
32 ##
33 ## This exception does not invalidate any other reasons why a work based on
34 ## this file might be covered by the GNU General Public License.
35 ##
36 ## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 ## at http://sources.redhat.com/ecos/ecos-license/
38 ## -------------------------------------------
39 #####ECOSGPLCOPYRIGHTEND####
40 ##=============================================================================
41 #######DESCRIPTIONBEGIN####
42 ##
43 ## Author(s):   jskov
44 ## Contributors:jskov, pjo, nickg, bartv
45 ## Date:        1999-03-11
46 ## Purpose:     CPU-specific code
47 ## Description: This file contains the code needed to manage the
48 ##              CPU on an i386/Linux synthetic target.
49 ##
50 ######DESCRIPTIONEND####
51 ##
52 ##=============================================================================
53
54 #include <cyg/hal/arch.inc>
55         
56 #------------------------------------------------------------------------------
57 # function declaration macro
58
59 #define FUNC_START(name)                        \
60         .globl name;                            \
61 name:   
62
63 #------------------------------------------------------------------------------
64 # Context switch and setjmp/longjmp support.        
65 # Based on PowerPC context.S, using data from SYSV ABI4, i386 
66 # supplement (page 37-38)
67 # http://www.sco.com/products/layered/develop/devspecs/abi386-4.pdf
68 #
69 # There is no need to worry about saving floating point context. If
70 # a switch occurs because of an interrupt/signal, the system will have
71 # saved the fpu state already before the signal handler was invoked,
72 # and the state will be returned when the signal handler returns i.e.
73 # when the interrupted thread is reactivated. If a context switch is
74 # voluntary, for example a call to cyg_thread_yield(), then according
75 # to the calling conventions all fpu registers are CALL_USED_REGISTERS
76 # (gcc/config/i386/i386.h) and will have been saved by the calling
77 # code.
78 #                
79 # FIXME: it may be appropriate to match eCos thread contexts
80 # more closely onto Linux sigcontexts - that might facilitate
81 # thread-aware debugging.
82                                         
83 # hal_thread_switch_context
84 # Switch thread contexts
85 # :     0(%esp) :     return address
86 # :     4(%esp) :     address of sp of next thread to execute
87 # :     8(%esp) :     address of sp save location of current thread
88 #
89 # %eax, %ecx, and %edx are ours to abuse.
90
91         .extern hal_interrupts_enabled
92         .extern hal_enable_interrupts
93                         
94 FUNC_START(hal_thread_switch_context)
95         movl    4(%esp),%eax            # next context ptr
96         movl    8(%esp),%edx            # this context ptr
97
98         # Make room on the stack for the context
99         movl    %esp,%ecx               # keep original SP
100         sub     $i386reg_context_size,%esp
101
102         # Save next context ptr in this context. Necessary because
103         # hal_thread_load_context expects to find the ptr on the stack,
104         # not in a register as on PPC.
105         movl    %eax,i386reg_next_context(%esp)
106
107         # Save registers
108         movl    %ecx,i386reg_esp(%esp)  # original esp
109         movl    %ebp,i386reg_ebp(%esp)
110         movl    %ebx,i386reg_ebx(%esp)
111         movl    %esi,i386reg_esi(%esp)
112         movl    %edi,i386reg_edi(%esp)
113
114         # And interrupt state
115         movl    hal_interrupts_enabled,%eax
116         movl    %eax,i386reg_interrupts(%esp)
117                 
118         # Store the context ptr
119         movl    %esp,(%edx)
120
121         # Now fall through to hal_thread_load_context
122         
123         
124 #------------------------------------------------------------------------------
125 # hal_thread_load_context
126 # Load thread context
127 # : 4(%esp) = i386reg_next_context(%esp) = address of sp of thread to execute
128 # Note that this function is also the second half of hal_thread_switch_context
129 # and is simply dropped into from it.
130 #
131 # %eax, %ecx, and %edx are ours to abuse.
132         
133 FUNC_START(hal_thread_load_context)
134
135         movl    i386reg_next_context(%esp),%eax # get new context ptr
136         movl    (%eax),%eax
137         
138         # Restore registers
139         movl    i386reg_ebp(%eax),%ebp
140         movl    i386reg_ebx(%eax),%ebx
141         movl    i386reg_esi(%eax),%esi
142         movl    i386reg_edi(%eax),%edi
143         movl    i386reg_esp(%eax),%esp
144
145         # And see what needs to happen about interrupts
146         movl    i386reg_interrupts(%eax),%eax
147         cmpl    hal_interrupts_enabled,%eax
148         je      interrupts_ok
149
150         # The saved interrupt state differs from the current one.
151         # If interrupts are supposed to be enabled then invoke
152         # hal_enable_interrupts. That can be done as a tail call.
153         # If interrupts are supposed to be disabled then just
154         # update the global variable.
155         cmpl    $0,%eax
156         jne     hal_enable_interrupts
157         movl    %eax,hal_interrupts_enabled
158                 
159 interrupts_ok:          
160         ret
161
162
163 #------------------------------------------------------------------------------
164 # HAL longjmp, setjmp implementations
165 # hal_setjmp saves only to callee save registers ebp, ebx, esi, edi and
166 # and esp+pc into buffer supplied in 4(esp)
167 # Note: These definitions are repeated in hal_arch.h. If changes are required
168 # remember to update both sets.
169
170 #define CYGARC_JMP_BUF_SP        0
171 #define CYGARC_JMP_BUF_EBP       1
172 #define CYGARC_JMP_BUF_EBX       2
173 #define CYGARC_JMP_BUF_ESI       3
174 #define CYGARC_JMP_BUF_EDI       4
175 #define CYGARC_JMP_BUF_PC        5
176
177 #define CYGARC_JMP_BUF_SIZE      6
178
179 FUNC_START(hal_setjmp)
180         # Get jmpbuf pointer
181         movl    4(%esp),%eax
182
183         # Save regular registers
184         movl    %ebp,CYGARC_JMP_BUF_EBP*4(%eax)
185         movl    %ebx,CYGARC_JMP_BUF_EBX*4(%eax)
186         movl    %esi,CYGARC_JMP_BUF_ESI*4(%eax)
187         movl    %edi,CYGARC_JMP_BUF_EDI*4(%eax)
188
189         # Stack and PC
190         movl    %esp,CYGARC_JMP_BUF_SP*4(%eax)
191         movl    0(%esp),%edx
192         movl    %edx,CYGARC_JMP_BUF_PC*4(%eax)
193
194         # Return 0
195         xor     %eax,%eax
196         ret
197
198         
199 # hal_longjmp loads state from 4(esp) and returns to PC stored in state
200
201 FUNC_START(hal_longjmp)
202         # Get return value
203         movl    8(%esp),%eax
204
205         # Get jmpbuf pointer
206         movl    4(%esp),%ecx
207         
208         # Restore regular registers
209         movl    CYGARC_JMP_BUF_EBP*4(%ecx),%ebp
210         movl    CYGARC_JMP_BUF_EBX*4(%ecx),%ebx
211         movl    CYGARC_JMP_BUF_ESI*4(%ecx),%esi
212         movl    CYGARC_JMP_BUF_EDI*4(%ecx),%edi
213         
214         # Restore stack pointer
215         movl    CYGARC_JMP_BUF_SP*4(%ecx),%esp
216
217         # Put return address on stack        
218         movl    CYGARC_JMP_BUF_PC*4(%ecx),%edx
219         movl    %edx,0(%esp)
220
221         ret
222
223 #------------------------------------------------------------------------------
224 # end of linux.S