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
|
/* cpu_asm.s
*
* This file contains all assembly code for the Intel i386 implementation
* of RTEMS.
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <asm.h>
/*
* Format of i386 Register structure
*/
.set REG_EFLAGS, 0
.set REG_ESP, REG_EFLAGS + 4
.set REG_EBP, REG_ESP + 4
.set REG_EBX, REG_EBP + 4
.set REG_ESI, REG_EBX + 4
.set REG_EDI, REG_ESI + 4
.set SIZE_REGS, REG_EDI + 4
BEGIN_CODE
/*
* void _CPU_Context_switch( run_context, heir_context )
*
* This routine performs a normal non-FP context.
*/
.p2align 1
PUBLIC (_CPU_Context_switch)
.set RUNCONTEXT_ARG, 4 # save context argument
.set HEIRCONTEXT_ARG, 8 # restore context argument
SYM (_CPU_Context_switch):
movl RUNCONTEXT_ARG(esp),eax # eax = running threads context
pushf # push eflags
popl REG_EFLAGS(eax) # save eflags
movl esp,REG_ESP(eax) # save stack pointer
movl ebp,REG_EBP(eax) # save base pointer
movl ebx,REG_EBX(eax) # save ebx
movl esi,REG_ESI(eax) # save source register
movl edi,REG_EDI(eax) # save destination register
movl HEIRCONTEXT_ARG(esp),eax # eax = heir threads context
restore:
pushl REG_EFLAGS(eax) # push eflags
popf # restore eflags
movl REG_ESP(eax),esp # restore stack pointer
movl REG_EBP(eax),ebp # restore base pointer
movl REG_EBX(eax),ebx # restore ebx
movl REG_ESI(eax),esi # restore source register
movl REG_EDI(eax),edi # restore destination register
ret
/*
* NOTE: May be unnecessary to reload some registers.
*/
/*
* void _CPU_Context_restore( new_context )
*
* This routine performs a normal non-FP context.
*/
PUBLIC (_CPU_Context_restore)
.set NEWCONTEXT_ARG, 4 # context to restore argument
SYM (_CPU_Context_restore):
movl NEWCONTEXT_ARG(esp),eax # eax = running threads context
jmp restore
/*PAGE
* void _CPU_Context_save_fp_context( &fp_context_ptr )
* void _CPU_Context_restore_fp_context( &fp_context_ptr )
*
* This section is used to context switch an i80287, i80387,
* the built-in coprocessor or the i80486 or compatible.
*/
.set FPCONTEXT_ARG, 4 # FP context argument
.p2align 1
PUBLIC (_CPU_Context_save_fp)
SYM (_CPU_Context_save_fp):
movl FPCONTEXT_ARG(esp),eax # eax = &ptr to FP context area
movl (eax),eax # eax = FP context area
fsave (eax) # save FP context
ret
.p2align 1
PUBLIC (_CPU_Context_restore_fp)
SYM (_CPU_Context_restore_fp):
movl FPCONTEXT_ARG(esp),eax # eax = &ptr to FP context area
movl (eax),eax # eax = FP context area
frstor (eax) # restore FP context
ret
/*
* GO32 does not require these segment related routines.
*/
#ifndef __GO32__
/*
* void *i386_Logical_to_physical(
* rtems_unsigned16 segment,
* void *address
* );
*
* Returns thirty-two bit physical address for segment:address.
*/
.set SEGMENT_ARG, 4
.set ADDRESS_ARG, 8
PUBLIC (i386_Logical_to_physical)
SYM (i386_Logical_to_physical):
xorl eax,eax # clear eax
movzwl SEGMENT_ARG(esp),ecx # ecx = segment value
movl $ SYM (_Global_descriptor_table),edx
# edx = address of our GDT
addl ecx,edx # edx = address of desired entry
movb 7(edx),ah # ah = base 31:24
movb 4(edx),al # al = base 23:16
shll $16,eax # move ax into correct bits
movw 2(edx),ax # ax = base 0:15
movl ADDRESS_ARG(esp),ecx # ecx = address to convert
addl eax,ecx # ecx = physical address equivalent
movl ecx,eax # eax = ecx
ret
/*
* void *i386_Physical_to_logical(
* rtems_unsigned16 segment,
* void *address
* );
*
* Returns thirty-two bit physical address for segment:address.
*/
/*
*.set SEGMENT_ARG, 4
*.set ADDRESS_ARG, 8 -- use sets from above
*/
PUBLIC (i386_Physical_to_logical)
SYM (i386_Physical_to_logical):
xorl eax,eax # clear eax
movzwl SEGMENT_ARG(esp),ecx # ecx = segment value
movl $ SYM (_Global_descriptor_table),edx
# edx = address of our GDT
addl ecx,edx # edx = address of desired entry
movb 7(edx),ah # ah = base 31:24
movb 4(edx),al # al = base 23:16
shll $16,eax # move ax into correct bits
movw 2(edx),ax # ax = base 0:15
movl ADDRESS_ARG(esp),ecx # ecx = address to convert
subl eax,ecx # ecx = logical address equivalent
movl ecx,eax # eax = ecx
ret
#endif /* __GO32__ */
END_CODE
END
|