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