Update the copyright notice format
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / Ia32 / CpuAsm.S
CommitLineData
c2fd60f0 1#------------------------------------------------------------------------------\r
2#*\r
01a1c0fc
HT
3#* Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>\r
4#* This program and the accompanying materials\r
c2fd60f0 5#* are licensed and made available under the terms and conditions of the BSD License\r
6#* which accompanies this distribution. The full text of the license may be found at\r
7#* http://opensource.org/licenses/bsd-license.php\r
8#*\r
9#* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10#* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11#*\r
12#* CpuAsm.S\r
13#*\r
14#* Abstract:\r
15#*\r
16#------------------------------------------------------------------------------\r
17\r
18\r
19#.MMX\r
20#.XMM\r
21\r
22#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions\r
23\r
24\r
25#\r
26# point to the external interrupt vector table\r
27#\r
28ExternalVectorTablePtr:\r
29 .byte 0, 0, 0, 0\r
30\r
31ASM_GLOBAL ASM_PFX(InitializeExternalVectorTablePtr)\r
32ASM_PFX(InitializeExternalVectorTablePtr):\r
33 movl 4(%esp), %eax\r
34 movl %eax, ExternalVectorTablePtr\r
35 ret\r
36\r
37#------------------------------------------------------------------------------\r
38# VOID\r
39# SetCodeSelector (\r
40# UINT16 Selector\r
41# );\r
42#------------------------------------------------------------------------------\r
43ASM_GLOBAL ASM_PFX(SetCodeSelector)\r
44ASM_PFX(SetCodeSelector):\r
45 movl 4(%esp), %ecx\r
46 subl $0x10, %esp \r
47 leal setCodeSelectorLongJump, %eax \r
48 movl %eax, (%esp)\r
49 movw %cx, 4(%esp)\r
50 .byte 0xFF, 0x2C, 0x24 # jmp *(%esp) note:(FWORD jmp) \r
51setCodeSelectorLongJump:\r
52 addl $0x10, %esp \r
53 ret\r
54\r
55#------------------------------------------------------------------------------\r
56# VOID\r
57# SetDataSelectors (\r
58# UINT16 Selector\r
59# );\r
60#------------------------------------------------------------------------------\r
61ASM_GLOBAL ASM_PFX(SetDataSelectors)\r
62ASM_PFX(SetDataSelectors):\r
63 movl 4(%esp), %ecx\r
64 movw %cx, %ss\r
65 movw %cx, %ds\r
66 movw %cx, %es\r
67 movw %cx, %fs\r
68 movw %cx, %gs\r
69 ret\r
70\r
71#---------------------------------------;\r
72# CommonInterruptEntry ;\r
73#---------------------------------------;\r
74# The follow algorithm is used for the common interrupt routine.\r
75\r
76ASM_GLOBAL ASM_PFX(CommonInterruptEntry)\r
77ASM_PFX(CommonInterruptEntry):\r
78 cli\r
79 #\r
80 # All interrupt handlers are invoked through interrupt gates, so\r
81 # IF flag automatically cleared at the entry point\r
82 #\r
83\r
84 #\r
85 # Calculate vector number\r
86 #\r
87 # Get the return address of call, actually, it is the\r
88 # address of vector number.\r
89 #\r
90 xchgl (%esp), %ecx\r
91 movw (%ecx), %cx\r
92 andl $0x0FFFF, %ecx\r
93 cmpl $32, %ecx # Intel reserved vector for exceptions?\r
94 jae NoErrorCode\r
95 bt %ecx, ASM_PFX(mErrorCodeFlag)\r
96 jc HasErrorCode\r
97\r
98NoErrorCode:\r
99\r
100 #\r
101 # Stack:\r
102 # +---------------------+\r
103 # + EFlags +\r
104 # +---------------------+\r
105 # + CS +\r
106 # +---------------------+\r
107 # + EIP +\r
108 # +---------------------+\r
109 # + ECX +\r
110 # +---------------------+ <-- ESP\r
111 #\r
112 # Registers:\r
113 # ECX - Vector Number\r
114 #\r
115\r
116 #\r
117 # Put Vector Number on stack\r
118 #\r
119 pushl %ecx\r
120\r
121 #\r
122 # Put 0 (dummy) error code on stack, and restore ECX\r
123 #\r
124 xorl %ecx, %ecx # ECX = 0\r
125 xchgl 4(%esp), %ecx\r
126\r
127 jmp ErrorCodeAndVectorOnStack\r
128\r
129HasErrorCode:\r
130\r
131 #\r
132 # Stack:\r
133 # +---------------------+\r
134 # + EFlags +\r
135 # +---------------------+\r
136 # + CS +\r
137 # +---------------------+\r
138 # + EIP +\r
139 # +---------------------+\r
140 # + Error Code +\r
141 # +---------------------+\r
142 # + ECX +\r
143 # +---------------------+ <-- ESP\r
144 #\r
145 # Registers:\r
146 # ECX - Vector Number\r
147 #\r
148\r
149 #\r
150 # Put Vector Number on stack and restore ECX\r
151 #\r
152 xchgl (%esp), %ecx \r
153\r
154 #\r
155 # Fall through to join main routine code\r
156 # at ErrorCodeAndVectorOnStack\r
157 #\r
158CommonInterruptEntry_al_0000:\r
159 jmp CommonInterruptEntry_al_0000\r
160\r
161ErrorCodeAndVectorOnStack:\r
162 pushl %ebp\r
163 movl %esp, %ebp\r
164\r
165 #\r
166 # Stack:\r
167 # +---------------------+\r
168 # + EFlags +\r
169 # +---------------------+\r
170 # + CS +\r
171 # +---------------------+\r
172 # + EIP +\r
173 # +---------------------+\r
174 # + Error Code +\r
175 # +---------------------+\r
176 # + Vector Number +\r
177 # +---------------------+\r
178 # + EBP +\r
179 # +---------------------+ <-- EBP\r
180 #\r
181\r
182 #\r
183 # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32\r
184 # is 16-byte aligned\r
185 #\r
186 andl $0x0fffffff0, %esp \r
187 subl $12, %esp\r
188\r
189#; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
190 pushl %eax\r
191 pushl %ecx\r
192 pushl %edx\r
193 pushl %ebx\r
194 leal 24(%ebp), %ecx\r
195 pushl %ecx # ESP\r
196 pushl (%ebp) # EBP\r
197 pushl %esi\r
198 pushl %edi\r
199\r
200#; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
201 movl %ss, %eax\r
202 pushl %eax\r
203 movzwl 16(%ebp), %eax \r
204 pushl %eax\r
205 movl %ds, %eax\r
206 pushl %eax\r
207 movl %es, %eax\r
208 pushl %eax\r
209 movl %fs, %eax\r
210 pushl %eax\r
211 movl %gs, %eax\r
212 pushl %eax\r
213\r
214#; UINT32 Eip;\r
215 movl 12(%ebp), %eax\r
216 pushl %eax\r
217\r
218#; UINT32 Gdtr[2], Idtr[2];\r
219 subl $8, %esp\r
220 sidt (%esp)\r
221 movl 2(%esp), %eax\r
222 xchgl (%esp), %eax\r
223 andl $0x0FFFF, %eax \r
224 movl %eax, 4(%esp)\r
225\r
226 subl $8, %esp\r
227 sgdt (%esp)\r
228 movl 2(%esp), %eax\r
229 xchgl (%esp), %eax\r
230 andl $0x0FFFF, %eax \r
231 movl %eax, 4(%esp)\r
232\r
233#; UINT32 Ldtr, Tr;\r
234 xorl %eax, %eax\r
235 str %ax\r
236 pushl %eax\r
237 sldt %ax\r
238 pushl %eax\r
239\r
240#; UINT32 EFlags;\r
241 movl 20(%ebp), %eax\r
242 pushl %eax\r
243\r
244#; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
245 movl %cr4, %eax\r
246 orl $0x208, %eax\r
247 movl %eax, %cr4\r
248 pushl %eax\r
249 movl %cr3, %eax\r
250 pushl %eax\r
251 movl %cr2, %eax\r
252 pushl %eax\r
253 xorl %eax, %eax\r
254 pushl %eax\r
255 movl %cr0, %eax\r
256 pushl %eax\r
257\r
258#; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
259 movl %dr7, %eax\r
260 pushl %eax\r
261#; clear Dr7 while executing debugger itself\r
262 xorl %eax, %eax\r
263 movl %eax, %dr7\r
264\r
265 movl %dr6, %eax\r
266 pushl %eax\r
267#; insure all status bits in dr6 are clear...\r
268 xorl %eax, %eax\r
269 movl %eax, %dr6\r
270\r
271 movl %dr3, %eax\r
272 pushl %eax\r
273 movl %dr2, %eax\r
274 pushl %eax\r
275 movl %dr1, %eax\r
276 pushl %eax\r
277 movl %dr0, %eax\r
278 pushl %eax\r
279\r
280#; FX_SAVE_STATE_IA32 FxSaveState;\r
281 subl $512, %esp\r
282 movl %esp, %edi\r
283 .byte 0x0f, 0x0ae, 0x07 #fxsave [edi]\r
284\r
285#; UINT32 ExceptionData;\r
286 pushl 8(%ebp)\r
287\r
288#; call into exception handler\r
289 movl ExternalVectorTablePtr, %eax # get the interrupt vectors base\r
290 orl %eax, %eax # NULL?\r
291 jz nullExternalExceptionHandler\r
292\r
293 mov 4(%ebp), %ecx\r
294 movl (%eax,%ecx,4), %eax\r
295 orl %eax, %eax # NULL?\r
296 jz nullExternalExceptionHandler\r
297\r
298#; Prepare parameter and call\r
299 movl %esp, %edx\r
300 pushl %edx\r
301 movl 4(%ebp), %edx\r
302 pushl %edx\r
303\r
304 #\r
305 # Call External Exception Handler\r
306 #\r
307 call *%eax\r
308 addl $8, %esp\r
309\r
310nullExternalExceptionHandler:\r
311\r
312 cli\r
313#; UINT32 ExceptionData;\r
314 addl $4, %esp\r
315\r
316#; FX_SAVE_STATE_IA32 FxSaveState;\r
317 movl %esp, %esi\r
318 .byte 0x0f, 0x0ae, 0x0e # fxrstor [esi]\r
319 addl $512, %esp\r
320\r
321#; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
322 popl %eax\r
323 movl %eax, %dr0\r
324 popl %eax\r
325 movl %eax, %dr1\r
326 popl %eax\r
327 movl %eax, %dr2\r
328 popl %eax\r
329 movl %eax, %dr3\r
330#; skip restore of dr6. We cleared dr6 during the context save.\r
331 addl $4, %esp\r
332 popl %eax\r
333 movl %eax, %dr7\r
334\r
335#; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
336 popl %eax\r
337 movl %eax, %cr0\r
338 addl $4, %esp # not for Cr1\r
339 popl %eax\r
340 movl %eax, %cr2\r
341 popl %eax\r
342 movl %eax, %cr3\r
343 popl %eax\r
344 movl %eax, %cr4\r
345\r
346#; UINT32 EFlags;\r
347 popl 20(%ebp)\r
348\r
349#; UINT32 Ldtr, Tr;\r
350#; UINT32 Gdtr[2], Idtr[2];\r
351#; Best not let anyone mess with these particular registers...\r
352 addl $24, %esp\r
353\r
354#; UINT32 Eip;\r
355 popl 12(%ebp)\r
356\r
357#; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
358#; NOTE - modified segment registers could hang the debugger... We\r
359#; could attempt to insulate ourselves against this possibility,\r
360#; but that poses risks as well.\r
361#;\r
362 popl %gs\r
363 popl %fs\r
364 popl %es\r
365 popl %ds\r
366 popl 16(%ebp)\r
367 popl %ss\r
368\r
369#; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
370 popl %edi\r
371 popl %esi\r
372 addl $4, %esp # not for ebp\r
373 addl $4, %esp # not for esp\r
374 popl %ebx\r
375 popl %edx\r
376 popl %ecx\r
377 popl %eax\r
378\r
379 movl %ebp, %esp\r
380 popl %ebp\r
381 addl $8, %esp\r
382 iretl\r
383\r
384\r
385#END\r
386\r