VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxRestore.asm@ 105590

Last change on this file since 105590 was 105099, checked in by vboxsync, 5 months ago

ValKit/bs3-cpu-weird-1: Made the push/pop testcase work in LM16 mode and enabled all the testcases. bugref:10715

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.7 KB
Line 
1; $Id: bs3-cmn-RegCtxRestore.asm 105099 2024-07-02 12:46:58Z vboxsync $
2;; @file
3; BS3Kit - Bs3RegCtxRestore.
4;
5
6;
7; Copyright (C) 2007-2023 Oracle and/or its affiliates.
8;
9; This file is part of VirtualBox base platform packages, as
10; available from https://www.virtualbox.org.
11;
12; This program is free software; you can redistribute it and/or
13; modify it under the terms of the GNU General Public License
14; as published by the Free Software Foundation, in version 3 of the
15; License.
16;
17; This program is distributed in the hope that it will be useful, but
18; WITHOUT ANY WARRANTY; without even the implied warranty of
19; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20; General Public License for more details.
21;
22; You should have received a copy of the GNU General Public License
23; along with this program; if not, see <https://www.gnu.org/licenses>.
24;
25; The contents of this file may alternatively be used under the terms
26; of the Common Development and Distribution License Version 1.0
27; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28; in the VirtualBox distribution, in which case the provisions of the
29; CDDL are applicable instead of those of the GPL.
30;
31; You may elect to license modified versions of this file under the
32; terms and conditions of either the GPL or the CDDL or both.
33;
34; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35;
36
37%include "bs3kit-template-header.mac"
38
39
40BS3_EXTERN_SYSTEM16 Bs3Gdt
41BS3_EXTERN_DATA16 g_bBs3CurrentMode
42BS3_EXTERN_DATA16 g_fBs3TrapNoV86Assist
43%if TMPL_BITS != 64
44BS3_EXTERN_DATA16 g_uBs3CpuDetected
45%endif
46TMPL_BEGIN_TEXT
47BS3_EXTERN_CMN Bs3Syscall
48BS3_EXTERN_CMN Bs3Panic
49TMPL_BEGIN_TEXT
50
51
52;;
53; Restores the given register context.
54;
55; @param pRegCtx
56; @param fFlags
57; @uses All registers and may trash stack immediately before the resume point.
58;
59; @note Only respects the BS3_MODE_CODE_MASK part of pRegCtx->bMode.
60;
61%if TMPL_BITS == 16
62BS3_PROC_BEGIN_CMN Bs3RegCtxRestore_aborts, BS3_PBC_FAR ; special entry point for when watcom applies __aborts
63BS3_PROC_BEGIN_CMN Bs3RegCtxRestore_aborts, BS3_PBC_NEAR ; special entry point for when watcom applies __aborts
64 CPU 8086
65 xor xAX, xAX
66 push xAX ; fake return address.
67 push xAX
68 jmp _Bs3RegCtxRestore_f16
69%elif TMPL_BITS == 32
70BS3_PROC_BEGIN_CMN Bs3RegCtxRestore_aborts, BS3_PBC_NEAR ; special entry point for when watcom applies __aborts
71 push 0feedfaceh ; fake return address.
72%endif
73BS3_PROC_BEGIN_CMN Bs3RegCtxRestore, BS3_PBC_HYBRID
74 BS3_CALL_CONV_PROLOG 2
75 push xBP
76 mov xBP, xSP
77
78 ;
79 ; If we're not in ring-0, ask the kernel to restore it for us (quicker
80 ; and less problematic if we're in a funny context right now with weird
81 ; CS or SS values).
82 ;
83%if TMPL_BITS == 16
84 cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM
85 je .in_ring0
86 cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_LM16
87 je .do_syscall_restore_ctx
88 test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86
89 jnz .do_syscall_restore_ctx
90%elif TMPL_BITS == 32
91 cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_LM32
92 je .do_syscall_restore_ctx
93%endif
94 mov ax, ss
95 test al, 3
96 jz .in_ring0
97
98.do_syscall_restore_ctx:
99%if TMPL_BITS != 16
100.do_syscall_restore_ctx_restore_ds:
101 mov cx, ds
102 mov xSI, [xBP + xCB*2]
103 movzx edx, word [xBP + xCB*3]
104 mov eax, BS3_SYSCALL_RESTORE_CTX
105%else
106 mov si, [bp + xCB + cbCurRetAddr]
107 mov cx, [bp + xCB + cbCurRetAddr + 2]
108 mov dx, [bp + xCB + cbCurRetAddr + sCB]
109 mov ax, BS3_SYSCALL_RESTORE_CTX
110%endif
111 call Bs3Syscall
112 call Bs3Panic
113
114%if TMPL_BITS == 16
115.do_syscall_restore_ctx_restore_ds:
116 push es
117 pop ds
118 jmp .do_syscall_restore_ctx
119%endif
120
121 ;
122 ; Prologue. Loads ES with BS3KIT_GRPNM_DATA16/FLAT (for g_bBs3CurrentMode
123 ; and g_uBs3CpuDetected), DS:xBX with pRegCtx and fFlags into xCX.
124 ;
125.in_ring0:
126%if TMPL_BITS == 16
127 mov ax, BS3_SEL_DATA16
128 mov es, ax
129 lds bx, [bp + xCB + cbCurRetAddr]
130 mov cx, [bp + xCB + cbCurRetAddr + sCB]
131%elif TMPL_BITS == 32
132 mov ax, BS3_SEL_R0_DS32
133 mov ds, ax
134 mov xBX, [xBP + xCB*2]
135 movzx xCX, word [xBP + xCB*3]
136%else
137 mov ax, BS3_SEL_R0_DS64
138 mov ds, ax
139 mov xBX, [xBP + xCB*2]
140 movzx xCX, word [xBP + xCB*3]
141%endif
142
143
144%if TMPL_BITS != 64
145 ; Restoring a 64-bit context is best done from 64-bit code.
146 mov al, [xBX + BS3REGCTX.bMode]
147 test al, BS3_MODE_CODE_64
148 jnz .do_syscall_restore_ctx_restore_ds
149%endif
150
151 ; The remainder must be done with interrupts disabled.
152 cli
153
154 ;
155 ; Update g_bs3CurrentMode.
156 ;
157%if TMPL_BITS == 64
158 mov al, [xBX + BS3REGCTX.bMode]
159%endif
160 and al, BS3_MODE_CODE_MASK
161 mov ah, [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_bBs3CurrentMode)]
162 and ah, ~BS3_MODE_CODE_MASK
163 or al, ah
164 mov [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_bBs3CurrentMode)], al
165
166 ;
167 ; Set g_fBs3TrapNoV86Assist if BS3REGCTXRESTORE_F_NO_V86_ASSIST specified.
168 ;
169 test cl, BS3REGCTXRESTORE_F_NO_V86_ASSIST
170 jz .no_f_no_v86_assist
171 mov byte [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_fBs3TrapNoV86Assist)], 1
172.no_f_no_v86_assist:
173
174%if TMPL_BITS == 16
175 ;
176 ; Check what the CPU can do.
177 ;
178 cmp byte [es:BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80386
179 jae .restore_full
180
181 ; Do the 80286 specifics first.
182 cmp byte [es:BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286
183 jb .restore_16_bit_ancient
184 CPU 286
185
186 lmsw [bx + BS3REGCTX.cr0]
187 cmp byte [es:BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM
188 je .restore_16_bit_ancient
189 lldt [bx + BS3REGCTX.ldtr]
190
191 ; TR - complicated because we need to clear the busy bit. ASSUMES GDT.
192 str ax
193 cmp ax, [bx + BS3REGCTX.tr]
194 je .skip_tr_286
195
196 mov di, word [xBX + BS3REGCTX.tr]
197 or di, di ; check for null.
198 jz .load_tr_286
199
200 push ds
201 push BS3_SEL_SYSTEM16
202 pop ds
203 add di, Bs3Gdt wrt BS3SYSTEM16
204 add di, X86DESCGENERIC_BIT_OFF_TYPE / 8
205 and byte [di], ~(X86_SEL_TYPE_SYS_TSS_BUSY_MASK << (X86DESCGENERIC_BIT_OFF_TYPE % 8))
206 pop ds
207
208.load_tr_286:
209 ltr [bx + BS3REGCTX.tr]
210.skip_tr_286:
211
212.restore_16_bit_ancient:
213 CPU 8086
214 ; Some general registers.
215 mov cx, [bx + BS3REGCTX.rcx]
216 mov dx, [bx + BS3REGCTX.rdx]
217
218 ; Do the return frame and final registers (keep short as we're not quite
219 ; NMI safe here if pRegCtx is on the stack).
220 cmp byte [es:BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM
221 mov di, [bx + BS3REGCTX.rsp]
222 je .restore_16_bit_same_privilege
223 cmp byte [bx + BS3REGCTX.bCpl], 0
224 je .restore_16_bit_same_privilege
225
226 mov ax, [bx + BS3REGCTX.ss]
227 push ax
228 mov ax, [bx + BS3REGCTX.rsp]
229 push ax
230 mov ax, [bx + BS3REGCTX.rflags]
231 push ax
232 mov ax, [bx + BS3REGCTX.cs]
233 push ax
234 mov ax, [bx + BS3REGCTX.rip]
235 push ax
236 mov ax, [bx + BS3REGCTX.ds]
237 push ax
238
239 mov si, [bx + BS3REGCTX.rsi]
240 mov di, [bx + BS3REGCTX.rdi]
241 mov es, [bx + BS3REGCTX.es]
242 mov ax, [bx + BS3REGCTX.rax]
243 mov bp, [bx + BS3REGCTX.rbp] ; restore late for better stacks.
244 mov bx, [bx + BS3REGCTX.rbx]
245
246 pop ds
247 iret
248
249.restore_16_bit_same_privilege:
250 sub di, 2*5 ; iret frame + pop ds
251 mov si, di
252 mov es, [bx + BS3REGCTX.ss] ; ES is target stack segment.
253 cld
254
255 mov ax, [bx + BS3REGCTX.ds]
256 stosw
257 mov ax, [bx + BS3REGCTX.rbp] ; Restore esp as late as possible for better stacks.
258 stosw
259 mov ax, [bx + BS3REGCTX.rip]
260 stosw
261 mov ax, [bx + BS3REGCTX.cs]
262 stosw
263 mov ax, [bx + BS3REGCTX.rflags]
264 stosw
265
266 mov di, [bx + BS3REGCTX.rdi]
267 mov es, [bx + BS3REGCTX.es]
268 mov ax, [bx + BS3REGCTX.rax]
269 mov ss, [bx + BS3REGCTX.ss]
270 mov sp, si
271 mov si, [bx + BS3REGCTX.rsi]
272 mov bx, [bx + BS3REGCTX.rbx]
273
274 pop ds
275 pop bp
276 iret
277
278 CPU 386
279%endif
280
281.restore_full:
282 ;
283 ; 80386 or later.
284 ; For 32-bit and 16-bit versions, we always use 32-bit iret.
285 ;
286
287 ; Restore control registers if they've changed.
288 test cl, BS3REGCTXRESTORE_F_SKIP_CRX
289 jnz .skip_control_regs
290 test byte [xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR0_IS_MSW | BS3REG_CTX_F_NO_CR2_CR3
291 jnz .skip_control_regs
292
293 test byte [xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4 ; (old 486s and 386s didn't have CR4)
294 jnz .skip_cr4
295%if TMPL_BITS != 64
296 test word [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_F_CPUID
297 jz .skip_cr4
298%endif
299 mov sAX, [xBX + BS3REGCTX.cr4]
300 mov sDX, cr4
301 cmp sAX, sDX
302 je .skip_cr4
303 mov cr4, sAX
304.skip_cr4:
305
306 mov sAX, [xBX + BS3REGCTX.cr0]
307 mov sDX, cr0
308 cmp sAX, sDX
309 je .skip_cr0
310 mov cr0, sAX
311.skip_cr0:
312
313 mov sAX, [xBX + BS3REGCTX.cr3]
314 mov sDX, cr3
315 cmp sAX, sDX
316 je .skip_cr3
317 mov cr3, sAX
318.skip_cr3:
319
320 mov sAX, [xBX + BS3REGCTX.cr2]
321 mov sDX, cr2
322 cmp sAX, sDX
323 je .skip_cr2
324 mov cr2, sAX
325.skip_cr2:
326
327 ;
328 ; Restore
329 ;
330%if TMPL_BITS != 64
331 ; We cannot restore ldtr and tr if we're in real-mode.
332 cmp byte [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM
333 je .skip_control_regs
334%endif
335 test byte [xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_TR_LDTR
336 jnz .skip_control_regs
337
338 ; LDTR
339 sldt ax
340 cmp ax, [xBX + BS3REGCTX.ldtr]
341 je .skip_ldtr
342 lldt [xBX + BS3REGCTX.ldtr]
343.skip_ldtr:
344
345 ; TR - complicated because we need to clear the busy bit. ASSUMES GDT.
346 str ax
347 cmp ax, [xBX + BS3REGCTX.tr]
348 je .skip_tr
349
350 movzx edi, word [xBX + BS3REGCTX.tr]
351 or edi, edi ; check for null.
352 jz .load_tr
353
354%if TMPL_BITS == 16
355 push ds
356 push BS3_SEL_SYSTEM16
357 pop ds
358 add xDI, Bs3Gdt wrt BS3SYSTEM16
359%else
360 add xDI, Bs3Gdt wrt FLAT
361%endif
362 add xDI, X86DESCGENERIC_BIT_OFF_TYPE / 8
363 and byte [xDI], ~(X86_SEL_TYPE_SYS_TSS_BUSY_MASK << (X86DESCGENERIC_BIT_OFF_TYPE % 8))
364%if TMPL_BITS == 16
365 pop ds
366%endif
367.load_tr:
368 ltr [xBX + BS3REGCTX.tr]
369.skip_tr:
370
371.skip_control_regs:
372
373
374%if TMPL_BITS == 64
375 ;
376 ; 64-bit returns are simple because ss:rsp are always restored.
377 ;
378 ; A small complication here when returning to a 16-bit stack (only
379 ; applicable to 16-bit and 32-bit code), iret doesn't touch the high
380 ; ESP bits and we can easily later end up with trap handlers
381 ; accessing memory never intended as stack.
382 ;
383 mov rcx, qword [xBX + BS3REGCTX.rsp] ; (also 1st param for conv call below)
384 cmp rcx, 0ffffh
385 ja .iretq_maybe_annoying_16bit_stack
386 cmp rsp, 0ffffh
387 ja .iretq_maybe_annoying_16bit_stack
388.iretq_ok:
389
390 movzx eax, word [xBX + BS3REGCTX.ss]
391 push rax
392 push qword [xBX + BS3REGCTX.rsp]
393 push qword [xBX + BS3REGCTX.rflags]
394 movzx eax, word [xBX + BS3REGCTX.cs]
395 push rax
396 push qword [xBX + BS3REGCTX.rip]
397
398.iretq_restore_regs_and_iret:
399 mov es, [xBX + BS3REGCTX.es]
400 mov fs, [xBX + BS3REGCTX.fs]
401 mov gs, [xBX + BS3REGCTX.gs]
402 mov rax, [xBX + BS3REGCTX.rax]
403 mov rdx, [xBX + BS3REGCTX.rdx]
404 mov rcx, [xBX + BS3REGCTX.rcx]
405 mov rsi, [xBX + BS3REGCTX.rsi]
406 mov rdi, [xBX + BS3REGCTX.rdi]
407 mov r8, [xBX + BS3REGCTX.r8]
408 mov r9, [xBX + BS3REGCTX.r9]
409 mov r10, [xBX + BS3REGCTX.r10]
410 mov r11, [xBX + BS3REGCTX.r11]
411 mov r12, [xBX + BS3REGCTX.r12]
412 mov r13, [xBX + BS3REGCTX.r13]
413 mov r14, [xBX + BS3REGCTX.r14]
414 mov r15, [xBX + BS3REGCTX.r15]
415 mov rbp, [xBX + BS3REGCTX.rbp] ; restore late for better stacks.
416 mov ds, [xBX + BS3REGCTX.ds]
417 mov rbx, [xBX + BS3REGCTX.rbx]
418 iretq
419
420.iretq_maybe_annoying_16bit_stack:
421 movzx edx, word [xBX + BS3REGCTX.ss] ; (also 2nd param for conv call below)
422 lar eax, dx
423 jnz .iretq_ok
424 test eax, X86LAR_F_D | X86LAR_F_L
425 jnz .iretq_ok ; Returning to a big or long SS needs not extra work.
426
427 lar eax, word [xBX + BS3REGCTX.cs]
428 jnz .iretq_ok
429 test eax, X86LAR_F_L
430 jnz .iretq_ok ; It doesn't matter when returning to 64-bit code.
431
432 ; Convert ss:sp to a flat address.
433 movzx ecx, cx ; 16-bit stacks are 16-bit, so chop the offset down.
434 BS3_EXTERN_CMN Bs3SelFar32ToFlat32NoClobber
435 call Bs3SelFar32ToFlat32NoClobber
436 mov rdi, rax
437
438 ; 2nd return frame (32-bit, same CPL).
439 mov eax, [xBX + BS3REGCTX.rflags]
440 mov [rdi - 4], eax
441 movzx eax, word [xBX + BS3REGCTX.cs]
442 mov [rdi - 8], eax
443 mov eax, [xBX + BS3REGCTX.rip]
444 mov [rdi - 12], eax
445 mov ecx, [xBX + BS3REGCTX.rsp]
446 sub cx, 12
447 mov [rdi - 16], ecx
448
449 ; 1st return frame.
450 movzx eax, word [xBX + BS3REGCTX.ss]
451 push rax ; new 16-bit SS
452 sub cx, 4
453 push rcx ; new esp
454 mov rax, [xBX + BS3REGCTX.rflags]
455 and rax, ~(X86_EFL_NT | X86_EFL_TF)
456 push rax ; rflags
457 AssertCompile(BS3_SEL_RING_SHIFT == 8)
458 mov eax, BS3_SEL_R0_CS32
459 add ah, [xBX + BS3REGCTX.bCpl]
460 or al, [xBX + BS3REGCTX.bCpl]
461 push rax ; 32-bit CS
462 push .iretq_pop_real_esp_and_iret_again wrt FLAT
463 jmp .iretq_restore_regs_and_iret
464
465 BS3_SET_BITS 32
466.iretq_pop_real_esp_and_iret_again:
467 pop esp
468 iretd
469 BS3_SET_BITS 64
470
471%else
472 ;
473 ; 32-bit/16-bit is more complicated as we have three different iret frames.
474 ;
475 mov al, [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_bBs3CurrentMode)]
476 cmp al, BS3_MODE_RM
477 je .iretd_same_cpl_rm
478
479 test dword [xBX + BS3REGCTX.rflags], X86_EFL_VM
480 jnz .restore_v8086
481
482 cmp byte [xBX + BS3REGCTX.bCpl], 0
483 je .iretd_same_cpl
484
485 ;
486 ; IRETD to different CPL. Frame includes ss:esp.
487 ;
488.iretd_different_cpl:
489 or eax, 0ffffffffh ; poison unused parts of segment pushes
490 mov ax, [xBX + BS3REGCTX.ss]
491 push eax
492 push dword [xBX + BS3REGCTX.rsp]
493 push dword [xBX + BS3REGCTX.rflags]
494 mov ax, [xBX + BS3REGCTX.cs]
495 push eax
496 push dword [xBX + BS3REGCTX.rip]
497 push dword [xBX + BS3REGCTX.rbp] ; Restore esp as late as possible for better stacks.
498 mov ax, [xBX + BS3REGCTX.ds]
499 push xAX
500
501 mov es, [xBX + BS3REGCTX.es]
502 mov fs, [xBX + BS3REGCTX.fs]
503 mov gs, [xBX + BS3REGCTX.gs]
504 mov eax, [xBX + BS3REGCTX.rax]
505 mov edx, [xBX + BS3REGCTX.rdx]
506 mov ecx, [xBX + BS3REGCTX.rcx]
507 mov esi, [xBX + BS3REGCTX.rsi]
508 %if TMPL_BITS == 16 ; if SS is 16-bit, we will not be able to restore the high word.
509;; @todo 16-bit stack will also mess us up in 32-bit code, so this needs fixing (see 64-bit above).
510 mov edi, [xBX + BS3REGCTX.rsp]
511 mov di, sp
512 mov esp, edi
513 %endif
514 mov edi, [xBX + BS3REGCTX.rdi]
515 mov ebx, [xBX + BS3REGCTX.rbx]
516
517 pop ds
518 pop ebp
519 iretd
520
521 ;
522 ; IRETD to same CPL (includes real mode).
523 ;
524.iretd_same_cpl_rm:
525 ; Use STOSD/ES:EDI to create the frame.
526 mov es, [xBX + BS3REGCTX.ss]
527 mov esi, [xBX + BS3REGCTX.rsp]
528 sub esi, 5*4
529 movzx edi, si
530 jmp .es_edi_is_pointing_to_return_frame_location
531
532.iretd_same_cpl:
533 ; Use STOSD/ES:EDI to create the frame.
534 mov es, [xBX + BS3REGCTX.ss]
535 mov edi, [xBX + BS3REGCTX.rsp]
536 sub edi, 5*4
537
538 ; Which part of the stack pointer is actually used depends on the SS.D/B bit.
539 lar eax, [xBX + BS3REGCTX.ss]
540 jnz .using_32_bit_stack_pointer
541 test eax, X86LAR_F_D
542 jnz .using_32_bit_stack_pointer
543.using_16_bit_stack_pointer:
544 mov esi, edi ; save rsp for later.
545 movzx edi, di
546 jmp .es_edi_is_pointing_to_return_frame_location
547.using_32_bit_stack_pointer:
548 mov esi, edi
549.es_edi_is_pointing_to_return_frame_location:
550 cld
551 mov ax, [xBX + BS3REGCTX.ds]
552 o32 stosd
553 mov eax, [xBX + BS3REGCTX.rbp] ; Restore esp as late as possible for better stacks.
554 o32 stosd
555 mov eax, [xBX + BS3REGCTX.rip]
556 o32 stosd
557 mov ax, [xBX + BS3REGCTX.cs]
558 o32 stosd
559 mov eax, [xBX + BS3REGCTX.rflags]
560 o32 stosd
561
562 mov es, [xBX + BS3REGCTX.es]
563 mov fs, [xBX + BS3REGCTX.fs]
564 mov gs, [xBX + BS3REGCTX.gs]
565 mov eax, [xBX + BS3REGCTX.rax]
566 mov edx, [xBX + BS3REGCTX.rdx]
567 mov ecx, [xBX + BS3REGCTX.rcx]
568 mov edi, [xBX + BS3REGCTX.rdi]
569 mov ebp, [xBX + BS3REGCTX.rbp] ; restore late for better stacks.
570
571 mov ss, [xBX + BS3REGCTX.ss]
572 mov esp, esi
573 mov esi, [xBX + BS3REGCTX.rsi]
574 mov ebx, [xBX + BS3REGCTX.rbx]
575
576 o32 pop ds
577 pop ebp
578 iretd
579
580 ;
581 ; IRETD to v8086 mode. Frame includes ss:esp and the 4 data segment registers.
582 ;
583.restore_v8086:
584 ; Create the return frame.
585 or eax, 0ffffffffh ; poison unused parts of segment pushes
586 mov eax, [xBX + BS3REGCTX.gs]
587 push eax
588 mov eax, [xBX + BS3REGCTX.fs]
589 push eax
590 mov eax, [xBX + BS3REGCTX.ds]
591 push eax
592 mov eax, [xBX + BS3REGCTX.es]
593 push eax
594 mov eax, [xBX + BS3REGCTX.ss]
595 push eax
596 push dword [xBX + BS3REGCTX.rsp]
597 push dword [xBX + BS3REGCTX.rflags]
598 mov ax, [xBX + BS3REGCTX.cs]
599 push eax
600 push dword [xBX + BS3REGCTX.rip]
601
602 ; Load registers.
603 mov eax, [xBX + BS3REGCTX.rax]
604 mov edx, [xBX + BS3REGCTX.rdx]
605 mov ecx, [xBX + BS3REGCTX.rcx]
606 mov esi, [xBX + BS3REGCTX.rsi]
607 mov edi, [xBX + BS3REGCTX.rdi]
608 mov ebp, [xBX + BS3REGCTX.rbp] ; restore late for better stacks.
609 mov ebx, [xBX + BS3REGCTX.rbx]
610
611 iretd
612%endif
613BS3_PROC_END_CMN Bs3RegCtxRestore
614
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette