summaryrefslogtreecommitdiffstats
path: root/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesHlp.asm
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesHlp.asm')
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesHlp.asm1139
1 files changed, 1139 insertions, 0 deletions
diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesHlp.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesHlp.asm
new file mode 100644
index 00000000..cb4b19f1
--- /dev/null
+++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesHlp.asm
@@ -0,0 +1,1139 @@
+; $Id: bs3-mode-TestDoModesHlp.asm $
+;; @file
+; BS3Kit - Bs3TestDoModes helpers
+;
+
+;
+; Copyright (C) 2007-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+;*********************************************************************************************************************************
+;* Header Files *
+;*********************************************************************************************************************************
+%include "bs3kit-template-header.mac"
+
+
+;*********************************************************************************************************************************
+;* Defined Constants And Macros *
+;*********************************************************************************************************************************
+;
+; We put most of this mess in the RMTEXT16 segment when in real mode.
+;
+%if TMPL_MODE == BS3_MODE_RM
+ %define MY_BEGIN_TEXT BS3_BEGIN_RMTEXT16
+ %define MY_BEGIN_TEXT16 BS3_BEGIN_RMTEXT16
+ %define MY_TEXT16_WRT(a_Label) a_Label wrt BS3GROUPRMTEXT16
+%else
+ %define MY_BEGIN_TEXT TMPL_BEGIN_TEXT
+ %define MY_BEGIN_TEXT16 BS3_BEGIN_TEXT16
+ %define MY_TEXT16_WRT(a_Label) BS3_TEXT16_WRT(a_Label)
+%endif
+
+
+;*********************************************************************************************************************************
+;* External Symbols *
+;*********************************************************************************************************************************
+%if TMPL_MODE == BS3_MODE_RM
+BS3_BEGIN_TEXT16_FARSTUBS
+extern TMPL_FAR_NM(Bs3SwitchToRM)
+extern TMPL_FAR_NM(Bs3SwitchToPE16)
+extern TMPL_FAR_NM(Bs3SwitchToPE16_32)
+extern TMPL_FAR_NM(Bs3SwitchToPE16_V86)
+extern TMPL_FAR_NM(Bs3SwitchToPE32)
+extern TMPL_FAR_NM(Bs3SwitchToPE32_16)
+extern TMPL_FAR_NM(Bs3SwitchToPEV86)
+extern TMPL_FAR_NM(Bs3SwitchToPP16)
+extern TMPL_FAR_NM(Bs3SwitchToPP16_32)
+extern TMPL_FAR_NM(Bs3SwitchToPP16_V86)
+extern TMPL_FAR_NM(Bs3SwitchToPP32)
+extern TMPL_FAR_NM(Bs3SwitchToPP32_16)
+extern TMPL_FAR_NM(Bs3SwitchToPPV86)
+extern TMPL_FAR_NM(Bs3SwitchToPAE16)
+extern TMPL_FAR_NM(Bs3SwitchToPAE16_32)
+extern TMPL_FAR_NM(Bs3SwitchToPAE16_V86)
+extern TMPL_FAR_NM(Bs3SwitchToPAE32)
+extern TMPL_FAR_NM(Bs3SwitchToPAE32_16)
+extern TMPL_FAR_NM(Bs3SwitchToPAEV86)
+extern TMPL_FAR_NM(Bs3SwitchToLM16)
+extern TMPL_FAR_NM(Bs3SwitchToLM32)
+extern TMPL_FAR_NM(Bs3SwitchToLM64)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_rm_far)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pe16_far)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pe16_v86_far)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pe32_16_far)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pev86_far)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pp16_far)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pp16_v86_far)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pp32_16_far)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_ppv86_far)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pae16_far)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pae16_v86_far)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pae32_16_far)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_paev86_far)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_lm16_far)
+%else
+BS3_BEGIN_TEXT16
+extern TMPL_NM(Bs3SwitchToRM)
+extern TMPL_NM(Bs3SwitchToPE16)
+extern TMPL_NM(Bs3SwitchToPE16_32)
+extern TMPL_NM(Bs3SwitchToPE16_V86)
+extern TMPL_NM(Bs3SwitchToPE32)
+extern TMPL_NM(Bs3SwitchToPE32_16)
+extern TMPL_NM(Bs3SwitchToPEV86)
+extern TMPL_NM(Bs3SwitchToPP16)
+extern TMPL_NM(Bs3SwitchToPP16_32)
+extern TMPL_NM(Bs3SwitchToPP16_V86)
+extern TMPL_NM(Bs3SwitchToPP32)
+extern TMPL_NM(Bs3SwitchToPP32_16)
+extern TMPL_NM(Bs3SwitchToPPV86)
+extern TMPL_NM(Bs3SwitchToPAE16)
+extern TMPL_NM(Bs3SwitchToPAE16_32)
+extern TMPL_NM(Bs3SwitchToPAE16_V86)
+extern TMPL_NM(Bs3SwitchToPAE32)
+extern TMPL_NM(Bs3SwitchToPAE32_16)
+extern TMPL_NM(Bs3SwitchToPAEV86)
+extern TMPL_NM(Bs3SwitchToLM16)
+extern TMPL_NM(Bs3SwitchToLM32)
+extern TMPL_NM(Bs3SwitchToLM64)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_rm)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe16)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe16_v86)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe32_16)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pev86)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp16)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp16_v86)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp32_16)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_ppv86)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae16)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae16_v86)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae32_16)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_paev86)
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_lm16)
+%endif
+BS3_BEGIN_TEXT16
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe16_32):wrt BS3FLAT
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe32):wrt BS3FLAT
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp16_32):wrt BS3FLAT
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp32):wrt BS3FLAT
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae16_32):wrt BS3FLAT
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae32):wrt BS3FLAT
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_lm32):wrt BS3FLAT
+extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_lm64):wrt BS3FLAT
+
+
+MY_BEGIN_TEXT16 ; need the group definition
+MY_BEGIN_TEXT
+
+;;
+; Shared prologue code.
+; @param xAX Where to jump to for the main event.
+;
+BS3_GLOBAL_NAME_EX TMPL_NM(bs3TestCallDoerPrologue), , 0
+ BS3_CALL_CONV_PROLOG 1
+ push xBP
+ mov xBP, xSP
+ xPUSHF
+
+ ; Save non-volatile registers so the DO function doesn't have to.
+ push xBX
+ push xCX
+ push xDX
+ push xSI
+ push xDI
+%if TMPL_BITS != 64
+ push ds
+ push es
+ push ss
+ %if TMPL_BITS != 16
+ push fs
+ push gs
+ %endif
+%endif
+%if TMPL_BITS == 64
+ push r8
+ push r9
+ push r10
+ push r11
+ push r12
+ push r13
+ push r14
+ push r15
+%endif
+
+ ; Jump to the main code.
+ jmp xAX
+
+;;
+; Shared epilogue code.
+; @param xAX Return code.
+;
+BS3_GLOBAL_NAME_EX TMPL_NM(bs3TestCallDoerEpilogue), , 0
+ ; Restore registers.
+%if TMPL_BITS == 16
+ sub bp, (1+5+3)*2
+ mov sp, bp
+%elif TMPL_BITS == 32
+ lea xSP, [xBP - (1+5+5)*4]
+%else
+ lea xSP, [xBP - (1+5+8)*8]
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop r11
+ pop r10
+ pop r9
+ pop r8
+%endif
+%if TMPL_BITS != 64
+ %if TMPL_BITS != 16
+ pop gs
+ pop fs
+ %endif
+ pop ss
+ pop es
+ pop ds
+%endif
+ pop xDI
+ pop xSI
+ pop xDX
+ pop xCX
+ pop xBX
+ xPOPF
+ pop xBP
+ ret
+
+;
+; For checking that the mode switching macros doesn't screw up GPRs.
+; Note! Does not work on pre 286 hardware! So, for debugging only.
+;
+%if 0
+ %macro STRICT_SAVE_REGS 0
+ movzx esp, sp
+ sub esp, BS3REGCTX_size
+ mov [esp + BS3REGCTX.rax], eax
+ mov dword [esp + BS3REGCTX.rax+4], 0xdead0000
+ mov [esp + BS3REGCTX.rcx], ecx
+ mov dword [esp + BS3REGCTX.rcx+4], 0xdead0001
+ mov [esp + BS3REGCTX.rdx], edx
+ mov dword [esp + BS3REGCTX.rdx+4], 0xdead0002
+ mov [esp + BS3REGCTX.rbx], ebx
+ mov dword [esp + BS3REGCTX.rbx+4], 0xdead0003
+ mov [esp + BS3REGCTX.rbp], ebp
+ mov [esp + BS3REGCTX.rsp], esp
+ mov [esp + BS3REGCTX.rsi], esi
+ mov [esp + BS3REGCTX.rdi], edi
+ %endmacro
+
+ %macro STRICT_CHECK_REGS 0
+%%_esp: cmp [esp + BS3REGCTX.rsp], esp
+ jne %%_esp
+%%_eax: cmp [esp + BS3REGCTX.rax], eax
+ jne %%_eax
+%%_ecx: mov [esp + BS3REGCTX.rcx], ecx
+ jne %%_ecx
+%%_edx: cmp [esp + BS3REGCTX.rdx], edx
+ jne %%_edx
+%%_ebx: cmp [esp + BS3REGCTX.rbx], ebx
+ jne %%_ebx
+%%_ebp: cmp [esp + BS3REGCTX.rbp], ebp
+ jne %%_ebp
+%%_esi: cmp [esp + BS3REGCTX.rsi], esi
+ jne %%_esi
+%%_edi: cmp [esp + BS3REGCTX.rdi], edi
+ jne %%_edi
+ add esp, BS3REGCTX_size
+ %endmacro
+%else
+
+ %macro STRICT_SAVE_REGS 0
+ %endmacro
+ %macro STRICT_CHECK_REGS 0
+ %endmacro
+%endif
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Real mode
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInRM(uint16_t offBs3Text16);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInRM, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+MY_BEGIN_TEXT16
+BS3_SET_BITS TMPL_BITS
+BS3_GLOBAL_LOCAL_LABEL .doit
+ mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer.
+ mov dx, [xBP + xCB + cbCurRetAddr + 2]
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToRM)
+%else
+ call TMPL_NM(Bs3SwitchToRM)
+%endif
+ BS3_SET_BITS 16
+ STRICT_CHECK_REGS
+
+ mov cx, BS3_MODE_RM
+ push cx
+ push cs
+ mov cx, .return
+ push cx
+ push dx
+ push ax
+ retf
+.return:
+
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_rm_far)
+%else
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_rm)
+%endif
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+MY_BEGIN_TEXT
+BS3_PROC_END_MODE Bs3TestCallDoerInRM
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Unpage protection mode.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPE16(uint16_t offBs3Text16);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPE16, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+MY_BEGIN_TEXT16
+BS3_SET_BITS TMPL_BITS
+BS3_GLOBAL_LOCAL_LABEL .doit
+ mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer.
+ mov dx, [xBP + xCB + cbCurRetAddr + 2]
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPE16)
+%else
+ call TMPL_NM(Bs3SwitchToPE16)
+%endif
+ BS3_SET_BITS 16
+ STRICT_CHECK_REGS
+
+ push BS3_MODE_PE16
+ push cs
+ push .return
+ push dx
+ push ax
+ retf
+.return:
+
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pe16_far)
+%else
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe16)
+%endif
+ BS3_SET_BITS TMPL_BITS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+MY_BEGIN_TEXT
+BS3_PROC_END_MODE Bs3TestCallDoerInPE16
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPE16_32(uint32_t FlatWorkerAddr, uint8_t bMode);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPE16_32, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+.doit:
+ mov eax, [xBP + xCB + cbCurRetAddr] ; Load function pointer.
+ movzx edx, byte [xBP + xCB + cbCurRetAddr + sCB] ; bMode
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPE16_32)
+%else
+ call TMPL_NM(Bs3SwitchToPE16_32)
+%endif
+ BS3_SET_BITS 32
+ STRICT_CHECK_REGS
+
+ push edx ; bMode
+ call eax
+
+ STRICT_SAVE_REGS
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe16_32)
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+BS3_PROC_END_MODE Bs3TestCallDoerInPE16_32
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPE16_V86(uint16_t offBs3Text16);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPE16_V86, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+MY_BEGIN_TEXT16
+BS3_SET_BITS TMPL_BITS
+BS3_GLOBAL_LOCAL_LABEL .doit
+ mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer.
+ mov dx, [xBP + xCB + cbCurRetAddr + 2]
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPE16_V86)
+%else
+ call TMPL_NM(Bs3SwitchToPE16_V86)
+%endif
+ BS3_SET_BITS 16
+ STRICT_CHECK_REGS
+
+ push BS3_MODE_PE16_V86
+ push cs
+ push .return
+ push dx
+ push ax
+ retf
+.return:
+
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pe16_v86_far)
+%else
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe16_v86)
+%endif
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+MY_BEGIN_TEXT
+BS3_PROC_END_MODE Bs3TestCallDoerInPE16_V86
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPE32(uint32_t FlatWorkerAddr, uint8_t bMode);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPE32, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+.doit:
+ mov eax, [xBP + xCB + cbCurRetAddr] ; Load function pointer.
+ movzx edx, byte [xBP + xCB + cbCurRetAddr + sCB] ; bMode
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPE32)
+%else
+ call TMPL_NM(Bs3SwitchToPE32)
+%endif
+ BS3_SET_BITS 32
+ STRICT_CHECK_REGS
+
+ push edx ; bMode
+ call eax
+
+ STRICT_SAVE_REGS
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe32)
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+BS3_PROC_END_MODE Bs3TestCallDoerInPE32
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPE32_16(uint16_t offBs3Text16);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPE32_16, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+MY_BEGIN_TEXT16
+BS3_SET_BITS TMPL_BITS
+BS3_GLOBAL_LOCAL_LABEL .doit
+ mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer.
+ mov dx, [xBP + xCB + cbCurRetAddr + 2]
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPE32_16)
+%else
+ call TMPL_NM(Bs3SwitchToPE32_16)
+%endif
+ BS3_SET_BITS 16
+ STRICT_CHECK_REGS
+
+ push BS3_MODE_PE32_16
+ push cs
+ push .return
+ push dx
+ push ax
+ retf
+.return:
+
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pe32_16_far)
+%else
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe32_16)
+%endif
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+MY_BEGIN_TEXT
+BS3_PROC_END_MODE Bs3TestCallDoerInPE32_16
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPEV86(uint16_t offBs3Text16);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPEV86, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+MY_BEGIN_TEXT16
+BS3_SET_BITS TMPL_BITS
+BS3_GLOBAL_LOCAL_LABEL .doit
+ mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer.
+ mov dx, [xBP + xCB + cbCurRetAddr + 2]
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPEV86)
+%else
+ call TMPL_NM(Bs3SwitchToPEV86)
+%endif
+ BS3_SET_BITS 16
+ STRICT_CHECK_REGS
+
+ push BS3_MODE_PEV86
+ push cs
+ push .return
+ push dx
+ push ax
+ retf
+.return:
+
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pev86_far)
+%else
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pev86)
+%endif
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+MY_BEGIN_TEXT
+BS3_PROC_END_MODE Bs3TestCallDoerInPEV86
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Page protection mode.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPP16(uint16_t offBs3Text16);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPP16, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+MY_BEGIN_TEXT16
+BS3_SET_BITS TMPL_BITS
+BS3_GLOBAL_LOCAL_LABEL .doit
+ mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer.
+ mov dx, [xBP + xCB + cbCurRetAddr + 2]
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPP16)
+%else
+ call TMPL_NM(Bs3SwitchToPP16)
+%endif
+ BS3_SET_BITS 16
+ STRICT_CHECK_REGS
+
+ push BS3_MODE_PP16
+ push cs
+ push .return
+ push dx
+ push ax
+ retf
+.return:
+
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pp16_far)
+%else
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp16)
+%endif
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+MY_BEGIN_TEXT
+BS3_PROC_END_MODE Bs3TestCallDoerInPP16
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPP16_32(uint32_t uFlatWorkerAddr, uint8_t bMode);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPP16_32, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+.doit:
+ mov eax, [xBP + xCB + cbCurRetAddr] ; Load function pointer.
+ movzx edx, byte [xBP + xCB + cbCurRetAddr + sCB] ; bMode
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPP16_32)
+%else
+ call TMPL_NM(Bs3SwitchToPP16_32)
+%endif
+ BS3_SET_BITS 32
+ STRICT_CHECK_REGS
+
+ push edx
+ call eax
+
+ STRICT_SAVE_REGS
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp16_32)
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+BS3_PROC_END_MODE Bs3TestCallDoerInPP16_32
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPP16_V86(uint16_t offBs3Text16);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPP16_V86, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+MY_BEGIN_TEXT16
+BS3_SET_BITS TMPL_BITS
+BS3_GLOBAL_LOCAL_LABEL .doit
+ mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer.
+ mov dx, [xBP + xCB + cbCurRetAddr + 2]
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPP16_V86)
+%else
+ call TMPL_NM(Bs3SwitchToPP16_V86)
+%endif
+ BS3_SET_BITS 16
+ STRICT_CHECK_REGS
+
+ push BS3_MODE_PP16_V86
+ push cs
+ push .return
+ push dx
+ push ax
+ retf
+.return:
+
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pp16_v86_far)
+%else
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp16_v86)
+%endif
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+MY_BEGIN_TEXT
+BS3_PROC_END_MODE Bs3TestCallDoerInPP16_V86
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPP32(uint32_t uFlatWorkerAddr, uint8_t bMode);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPP32, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+.doit:
+ mov eax, [xBP + xCB + cbCurRetAddr] ; Load function pointer.
+ movzx edx, byte [xBP + xCB + cbCurRetAddr + sCB] ; bMode
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPP32)
+%else
+ call TMPL_NM(Bs3SwitchToPP32)
+%endif
+ BS3_SET_BITS 32
+ STRICT_CHECK_REGS
+
+ push edx ; bMode
+ call eax
+
+ STRICT_SAVE_REGS
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp32)
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+BS3_PROC_END_MODE Bs3TestCallDoerInPP32
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPP32_16(uint16_t offBs3Text16);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPP32_16, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+MY_BEGIN_TEXT16
+BS3_SET_BITS TMPL_BITS
+BS3_GLOBAL_LOCAL_LABEL .doit
+ mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer.
+ mov dx, [xBP + xCB + cbCurRetAddr + 2]
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPP32_16)
+%else
+ call TMPL_NM(Bs3SwitchToPP32_16)
+%endif
+ BS3_SET_BITS 16
+ STRICT_CHECK_REGS
+
+ push BS3_MODE_PP32_16
+ push cs
+ push .return
+ push dx
+ push ax
+ retf
+.return:
+
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pp32_16_far)
+%else
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp32_16)
+%endif
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+MY_BEGIN_TEXT
+BS3_PROC_END_MODE Bs3TestCallDoerInPP32_16
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPPV86(uint16_t offBs3Text16);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPPV86, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+MY_BEGIN_TEXT16
+BS3_SET_BITS TMPL_BITS
+BS3_GLOBAL_LOCAL_LABEL .doit
+ mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer.
+ mov dx, [xBP + xCB + cbCurRetAddr + 2]
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPPV86)
+%else
+ call TMPL_NM(Bs3SwitchToPPV86)
+%endif
+ BS3_SET_BITS 16
+ STRICT_CHECK_REGS
+
+ push BS3_MODE_PPV86
+ push cs
+ push .return
+ push dx
+ push ax
+ retf
+.return:
+
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_ppv86_far)
+%else
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_ppv86)
+%endif
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+MY_BEGIN_TEXT
+BS3_PROC_END_MODE Bs3TestCallDoerInPPV86
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; PAE paged protection mode.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPAE16(uint16_t offBs3Text16);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPAE16, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+MY_BEGIN_TEXT16
+BS3_SET_BITS TMPL_BITS
+BS3_GLOBAL_LOCAL_LABEL .doit
+ mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer.
+ mov dx, [xBP + xCB + cbCurRetAddr + 2]
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPAE16)
+%else
+ call TMPL_NM(Bs3SwitchToPAE16)
+%endif
+ BS3_SET_BITS 16
+ STRICT_CHECK_REGS
+
+ push BS3_MODE_PAE16
+ push cs
+ push .return
+ push dx
+ push ax
+ retf
+.return:
+
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pae16_far)
+%else
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae16)
+%endif
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+MY_BEGIN_TEXT
+BS3_PROC_END_MODE Bs3TestCallDoerInPAE16
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPAE16_32(uint32_t uFlatWorkerAddr, uint8_t bMode);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPAE16_32, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+.doit:
+ mov eax, [xBP + xCB + cbCurRetAddr] ; Load function pointer.
+ movzx edx, byte [xBP + xCB + cbCurRetAddr + sCB] ; bMode
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPAE16_32)
+%else
+ call TMPL_NM(Bs3SwitchToPAE16_32)
+%endif
+ BS3_SET_BITS 32
+ STRICT_CHECK_REGS
+
+ push edx ; bMode
+ call eax
+
+ STRICT_SAVE_REGS
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae16_32)
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+BS3_PROC_END_MODE Bs3TestCallDoerInPAE16_32
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPAE16_V86(uint16_t offBs3Text16);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPAE16_V86, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+MY_BEGIN_TEXT16
+BS3_SET_BITS TMPL_BITS
+BS3_GLOBAL_LOCAL_LABEL .doit
+ mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer.
+ mov dx, [xBP + xCB + cbCurRetAddr + 2]
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPAE16_V86)
+%else
+ call TMPL_NM(Bs3SwitchToPAE16_V86)
+%endif
+ BS3_SET_BITS 16
+ STRICT_CHECK_REGS
+
+ push BS3_MODE_PAE16_V86
+ push cs
+ push .return
+ push dx
+ push ax
+ retf
+.return:
+
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pae16_v86_far)
+%else
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae16_v86)
+%endif
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+MY_BEGIN_TEXT
+BS3_PROC_END_MODE Bs3TestCallDoerInPAE16_V86
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPAE32(uint32_t uFlatWorkerAddr, uint8_t bMode);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPAE32, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+.doit:
+ mov eax, [xBP + xCB + cbCurRetAddr] ; Load function pointer.
+ movzx edx, byte [xBP + xCB + cbCurRetAddr + sCB] ; bMode
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPAE32)
+%else
+ call TMPL_NM(Bs3SwitchToPAE32)
+%endif
+ BS3_SET_BITS 32
+ STRICT_CHECK_REGS
+
+ push edx ; bMode
+ call eax
+
+ STRICT_SAVE_REGS
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae32)
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+BS3_PROC_END_MODE Bs3TestCallDoerInPAE32
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPAE32_16(uint16_t offBs3Text16);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPAE32_16, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+MY_BEGIN_TEXT16
+BS3_SET_BITS TMPL_BITS
+BS3_GLOBAL_LOCAL_LABEL .doit
+ mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer.
+ mov dx, [xBP + xCB + cbCurRetAddr + 2]
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPAE32_16)
+%else
+ call TMPL_NM(Bs3SwitchToPAE32_16)
+%endif
+ BS3_SET_BITS 16
+ STRICT_CHECK_REGS
+
+ push BS3_MODE_PAE32_16
+ push cs
+ push .return
+ push dx
+ push ax
+ retf
+.return:
+
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pae32_16_far)
+%else
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae32_16)
+%endif
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+MY_BEGIN_TEXT
+BS3_PROC_END_MODE Bs3TestCallDoerInPAE32_16
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPAEV86(uint16_t offBs3Text16);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPAEV86, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+MY_BEGIN_TEXT16
+BS3_SET_BITS TMPL_BITS
+BS3_GLOBAL_LOCAL_LABEL .doit
+ mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer.
+ mov dx, [xBP + xCB + cbCurRetAddr + 2]
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToPAEV86)
+%else
+ call TMPL_NM(Bs3SwitchToPAEV86)
+%endif
+ BS3_SET_BITS 16
+ STRICT_CHECK_REGS
+
+ push BS3_MODE_PAEV86
+ push cs
+ push .return
+ push dx
+ push ax
+ retf
+.return:
+
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_paev86_far)
+%else
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_paev86)
+%endif
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+MY_BEGIN_TEXT
+BS3_PROC_END_MODE Bs3TestCallDoerInPAEV86
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Long mode
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInLM16(uint16_t offBs3Text16);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInLM16, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+MY_BEGIN_TEXT16
+BS3_SET_BITS TMPL_BITS
+BS3_GLOBAL_LOCAL_LABEL .doit
+ mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer.
+ mov dx, [xBP + xCB + cbCurRetAddr + 2]
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToLM16)
+%else
+ call TMPL_NM(Bs3SwitchToLM16)
+%endif
+ BS3_SET_BITS 16
+ STRICT_CHECK_REGS
+
+ push BS3_MODE_LM16
+ push cs
+ push .return
+ push dx
+ push ax
+ retf
+.return:
+
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_lm16_far)
+%else
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_lm16)
+%endif
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+MY_BEGIN_TEXT
+BS3_PROC_END_MODE Bs3TestCallDoerInLM16
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInLM32(uint16_t offBs3Text16);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInLM32, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+.doit:
+ mov eax, [xBP + xCB + cbCurRetAddr] ; Load function pointer.
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToLM32)
+%else
+ call TMPL_NM(Bs3SwitchToLM32)
+%endif
+ BS3_SET_BITS 32
+ STRICT_CHECK_REGS
+
+ and esp, ~03h
+ push BS3_MODE_LM32
+ call eax
+
+ STRICT_SAVE_REGS
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_lm32)
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+BS3_PROC_END_MODE Bs3TestCallDoerInLM32
+
+;;
+; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInLM64(uint32_t uFlatWorkerAddr, uint8_t bMode);
+; @uses rax
+BS3_PROC_BEGIN_MODE Bs3TestCallDoerInLM64, BS3_PBC_NEAR
+ BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit))
+ jmp TMPL_NM(bs3TestCallDoerPrologue)
+.doit:
+ mov eax, [xBP + xCB + cbCurRetAddr] ; Load function pointer.
+ movzx edx, byte [xBP + xCB + cbCurRetAddr + sCB] ; bMode
+
+ ; Mode switch, make the call, switch back.
+ STRICT_SAVE_REGS
+%if TMPL_MODE == BS3_MODE_RM
+ call far TMPL_FAR_NM(Bs3SwitchToLM64)
+%else
+ call TMPL_NM(Bs3SwitchToLM64)
+%endif
+ BS3_SET_BITS 64
+ STRICT_CHECK_REGS
+
+ and rsp, ~0fh
+ sub rsp, 18h
+ push rdx ; bMode
+ BS3_CALL rax, 1
+
+ STRICT_SAVE_REGS
+ call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_lm64)
+ BS3_SET_BITS TMPL_BITS
+ STRICT_CHECK_REGS
+ jmp TMPL_NM(bs3TestCallDoerEpilogue)
+BS3_PROC_END_MODE Bs3TestCallDoerInLM64
+