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