; $Id: bs3-cpu-basic-2-template.mac 105590 2024-08-05 23:03:19Z vboxsync $ ;; @file ; BS3Kit - bs3-cpu-basic-2 assembly template. ; ; ; 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 . ; ; 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" ; setup environment ;********************************************************************************************************************************* ;* Defined Constants And Macros * ;********************************************************************************************************************************* %ifnmacro BS3_CPUBAS2_UD_OFF %macro BS3_CPUBAS2_UD_OFF 1 BS3_GLOBAL_NAME_EX BS3_CMN_NM(%1) %+ _offUD, , 1 db BS3_CMN_NM(%1).again - BS3_CMN_NM(%1) %endmacro %endif %undef BS3_CPUBAS2_REF_LABEL_VIA_CS %if TMPL_BITS == 16 %define BS3_CPUBAS2_REF_LABEL_VIA_CS(a_Label) cs:a_Label %elif TMPL_BITS == 32 %define BS3_CPUBAS2_REF_LABEL_VIA_CS(a_Label) cs:a_Label wrt FLAT %elif TMPL_BITS == 64 %define BS3_CPUBAS2_REF_LABEL_VIA_CS(a_Label) a_Label wrt FLAT %else %error TMPL_BITS %endif ;; ; Macro for generating far jmp instruction w/o nasm adding REX.W prefixes. ; ; @param 1 The label of the memory pointer. ; @param 2 Prefix: 0: none, 1: 066h, 2: REX.W, 3: 066h REX.W %ifnmacro BS3_CPUBAS2_JMP_FAR_MEM_LABEL %macro BS3_CPUBAS2_JMP_FAR_MEM_LABEL 2 %if (%2) == 1 || (%2) == 3 db 066h ; o16/o32 %endif %if TMPL_BITS != 64 jmp far [BS3_CPUBAS2_REF_LABEL_VIA_CS(%1)] %elif TMPL_BITS == 64 ; 48FF2C25[040C0000] <3> jmp far [BS3_CPUBAS2_REF_LABLE_VIA_CS(.fpfn)] %if (%2) == 2 || (%2) == 3 db 048h ; REX.W %endif db 0ffh, 02ch, 025h dd %1 wrt FLAT %else %error TMPL_BITS %endif %endmacro %endif ;; ; Macro for generating far call instruction w/o nasm adding REX.W prefixes. ; ; @param 1 The label of the memory pointer. ; @param 2 Prefix: 0: none, 1: 066h, 2: REX.W, 3: 066h REX.W %ifnmacro BS3_CPUBAS2_CALL_FAR_MEM_LABEL %macro BS3_CPUBAS2_CALL_FAR_MEM_LABEL 2 %if (%2) == 1 || (%2) == 3 db 066h ; o16/o32 %endif %if TMPL_BITS != 64 call far [BS3_CPUBAS2_REF_LABEL_VIA_CS(%1)] %elif TMPL_BITS == 64 %if (%2) == 2 || (%2) == 3 db 048h ; REX.W %endif db 0ffh, 01ch, 025h ; call far [mem] dd %1 wrt FLAT %else %error TMPL_BITS %endif %endmacro %endif ;********************************************************************************************************************************* ;* External Symbols * ;********************************************************************************************************************************* TMPL_BEGIN_TEXT ; ; Test code snippets containing code which differs between 16-bit, 32-bit ; and 64-bit CPUs modes. ; %ifdef BS3_INSTANTIATING_CMN ; ; SIDT ; BS3_CPUBAS2_UD_OFF bs3CpuBasic2_sidt_bx_ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_sidt_bx_ud2, BS3_PBC_NEAR sidt [xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_sidt_bx_ud2) == 3) BS3_PROC_END_CMN bs3CpuBasic2_sidt_bx_ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_sidt_opsize_bx_ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_sidt_opsize_bx_ud2, BS3_PBC_NEAR db X86_OP_PRF_SIZE_OP sidt [xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_sidt_opsize_bx_ud2) == 4) BS3_PROC_END_CMN bs3CpuBasic2_sidt_opsize_bx_ud2 %if TMPL_BITS == 64 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_sidt_rexw_bx_ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_sidt_rexw_bx_ud2, BS3_PBC_NEAR db X86_OP_REX_W sidt [xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_sidt_rexw_bx_ud2) == 4) BS3_PROC_END_CMN bs3CpuBasic2_sidt_rexw_bx_ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_sidt_opsize_rexw_bx_ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_sidt_opsize_rexw_bx_ud2, BS3_PBC_NEAR db X86_OP_PRF_SIZE_OP db X86_OP_REX_W sidt [xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_sidt_opsize_rexw_bx_ud2) == 5) BS3_PROC_END_CMN bs3CpuBasic2_sidt_opsize_rexw_bx_ud2 %endif %if TMPL_BITS != 64 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_sidt_ss_bx_ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_sidt_ss_bx_ud2, BS3_PBC_NEAR sidt [ss:xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_sidt_ss_bx_ud2) == 4) BS3_PROC_END_CMN bs3CpuBasic2_sidt_ss_bx_ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_sidt_opsize_ss_bx_ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_sidt_opsize_ss_bx_ud2, BS3_PBC_NEAR db X86_OP_PRF_SIZE_OP sidt [ss:xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_sidt_opsize_ss_bx_ud2) == 5) BS3_PROC_END_CMN bs3CpuBasic2_sidt_opsize_ss_bx_ud2 %endif ; ; SGDT ; BS3_CPUBAS2_UD_OFF bs3CpuBasic2_sgdt_bx_ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_sgdt_bx_ud2, BS3_PBC_NEAR sgdt [xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_sgdt_bx_ud2) == 3) BS3_PROC_END_CMN bs3CpuBasic2_sgdt_bx_ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_sgdt_opsize_bx_ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_sgdt_opsize_bx_ud2, BS3_PBC_NEAR db X86_OP_PRF_SIZE_OP sgdt [xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_sgdt_opsize_bx_ud2) == 4) BS3_PROC_END_CMN bs3CpuBasic2_sgdt_opsize_bx_ud2 %if TMPL_BITS == 64 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_sgdt_rexw_bx_ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_sgdt_rexw_bx_ud2, BS3_PBC_NEAR db X86_OP_REX_W sgdt [xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_sgdt_rexw_bx_ud2) == 4) BS3_PROC_END_CMN bs3CpuBasic2_sgdt_rexw_bx_ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_sgdt_opsize_rexw_bx_ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_sgdt_opsize_rexw_bx_ud2, BS3_PBC_NEAR db X86_OP_PRF_SIZE_OP db X86_OP_REX_W sgdt [xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_sgdt_opsize_rexw_bx_ud2) == 5) BS3_PROC_END_CMN bs3CpuBasic2_sgdt_opsize_rexw_bx_ud2 %endif %if TMPL_BITS != 64 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_sgdt_ss_bx_ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_sgdt_ss_bx_ud2, BS3_PBC_NEAR sgdt [ss:xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_sgdt_ss_bx_ud2) == 4) BS3_PROC_END_CMN bs3CpuBasic2_sgdt_ss_bx_ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_sgdt_opsize_ss_bx_ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_sgdt_opsize_ss_bx_ud2, BS3_PBC_NEAR db X86_OP_PRF_SIZE_OP sgdt [ss:xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_sgdt_opsize_ss_bx_ud2) == 5) BS3_PROC_END_CMN bs3CpuBasic2_sgdt_opsize_ss_bx_ud2 %endif ; ; LIDT ; BS3_CPUBAS2_UD_OFF bs3CpuBasic2_lidt_bx__sidt_es_di__lidt_es_si__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_lidt_bx__sidt_es_di__lidt_es_si__ud2, BS3_PBC_NEAR lidt [xBX] sidt [BS3_NOT_64BIT(es:) xDI] lidt [BS3_NOT_64BIT(es:) xSI] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_lidt_bx__sidt_es_di__lidt_es_si__ud2) == BS3_IF_64BIT_OTHERWISE(9,11)) BS3_PROC_END_CMN bs3CpuBasic2_lidt_bx__sidt_es_di__lidt_es_si__ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_lidt_opsize_bx__sidt_es_di__lidt_es_si__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_lidt_opsize_bx__sidt_es_di__lidt_es_si__ud2, BS3_PBC_NEAR db X86_OP_PRF_SIZE_OP lidt [xBX] sidt [BS3_NOT_64BIT(es:) xDI] lidt [BS3_NOT_64BIT(es:) xSI] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_lidt_opsize_bx__sidt_es_di__lidt_es_si__ud2) == BS3_IF_64BIT_OTHERWISE(10,12)) BS3_PROC_END_CMN bs3CpuBasic2_lidt_opsize_bx__sidt_es_di__lidt_es_si__ud2 %if TMPL_BITS == 16 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_lidt_opsize_bx__sidt32_es_di__lidt_es_si__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_lidt_opsize_bx__sidt32_es_di__lidt_es_si__ud2, BS3_PBC_NEAR db X86_OP_PRF_SIZE_OP lidt [xBX] jmp dword BS3_SEL_R0_CS32:.in_32bit wrt FLAT BS3_SET_BITS 32 .in_32bit: sidt [es:edi] lidt [es:esi] jmp dword BS3_SEL_R0_CS16:.again wrt CGROUP16 BS3_SET_BITS 16 .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_lidt_opsize_bx__sidt32_es_di__lidt_es_si__ud2) == 27) BS3_PROC_END_CMN bs3CpuBasic2_lidt_opsize_bx__sidt32_es_di__lidt_es_si__ud2 %endif %if TMPL_BITS == 64 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_lidt_rexw_bx__sidt_es_di__lidt_es_si__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_lidt_rexw_bx__sidt_es_di__lidt_es_si__ud2, BS3_PBC_NEAR db X86_OP_REX_W lidt [xBX] sidt [xDI] lidt [xSI] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_lidt_rexw_bx__sidt_es_di__lidt_es_si__ud2) == 10) BS3_PROC_END_CMN bs3CpuBasic2_lidt_rexw_bx__sidt_es_di__lidt_es_si__ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_lidt_opsize_rexw_bx__sidt_es_di__lidt_es_si__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_lidt_opsize_rexw_bx__sidt_es_di__lidt_es_si__ud2, BS3_PBC_NEAR db X86_OP_PRF_SIZE_OP db X86_OP_REX_W lidt [xBX] sidt [xDI] lidt [xSI] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_lidt_opsize_rexw_bx__sidt_es_di__lidt_es_si__ud2) == 11) BS3_PROC_END_CMN bs3CpuBasic2_lidt_opsize_rexw_bx__sidt_es_di__lidt_es_si__ud2 %endif %if TMPL_BITS != 64 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_lidt_ss_bx__sidt_es_di__lidt_es_si__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_lidt_ss_bx__sidt_es_di__lidt_es_si__ud2, BS3_PBC_NEAR lidt [ss:xBX] sidt [BS3_NOT_64BIT(es:) xDI] lidt [BS3_NOT_64BIT(es:) xSI] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_lidt_ss_bx__sidt_es_di__lidt_es_si__ud2) == 12) BS3_PROC_END_CMN bs3CpuBasic2_lidt_ss_bx__sidt_es_di__lidt_es_si__ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_lidt_opsize_ss_bx__sidt_es_di__lidt_es_si__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_lidt_opsize_ss_bx__sidt_es_di__lidt_es_si__ud2, BS3_PBC_NEAR db X86_OP_PRF_SIZE_OP lidt [ss:xBX] sidt [BS3_NOT_64BIT(es:) xDI] lidt [BS3_NOT_64BIT(es:) xSI] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_lidt_opsize_ss_bx__sidt_es_di__lidt_es_si__ud2) == 13) BS3_PROC_END_CMN bs3CpuBasic2_lidt_opsize_ss_bx__sidt_es_di__lidt_es_si__ud2 %endif ; ; LGDT ; BS3_CPUBAS2_UD_OFF bs3CpuBasic2_lgdt_bx__sgdt_es_di__lgdt_es_si__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_lgdt_bx__sgdt_es_di__lgdt_es_si__ud2, BS3_PBC_NEAR lgdt [xBX] sgdt [BS3_NOT_64BIT(es:) xDI] lgdt [BS3_NOT_64BIT(es:) xSI] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_lgdt_bx__sgdt_es_di__lgdt_es_si__ud2) == BS3_IF_64BIT_OTHERWISE(9,11)) BS3_PROC_END_CMN bs3CpuBasic2_lgdt_bx__sgdt_es_di__lgdt_es_si__ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_lgdt_opsize_bx__sgdt_es_di__lgdt_es_si__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_lgdt_opsize_bx__sgdt_es_di__lgdt_es_si__ud2, BS3_PBC_NEAR db X86_OP_PRF_SIZE_OP lgdt [xBX] sgdt [BS3_NOT_64BIT(es:) xDI] lgdt [BS3_NOT_64BIT(es:) xSI] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_lgdt_opsize_bx__sgdt_es_di__lgdt_es_si__ud2) == BS3_IF_64BIT_OTHERWISE(10,12)) BS3_PROC_END_CMN bs3CpuBasic2_lgdt_opsize_bx__sgdt_es_di__lgdt_es_si__ud2 %if TMPL_BITS == 64 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_lgdt_rexw_bx__sgdt_es_di__lgdt_es_si__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_lgdt_rexw_bx__sgdt_es_di__lgdt_es_si__ud2, BS3_PBC_NEAR db X86_OP_REX_W lgdt [xBX] sgdt [xDI] lgdt [xSI] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_lgdt_rexw_bx__sgdt_es_di__lgdt_es_si__ud2) == 10) BS3_PROC_END_CMN bs3CpuBasic2_lgdt_rexw_bx__sgdt_es_di__lgdt_es_si__ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_lgdt_opsize_rexw_bx__sgdt_es_di__lgdt_es_si__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_lgdt_opsize_rexw_bx__sgdt_es_di__lgdt_es_si__ud2, BS3_PBC_NEAR db X86_OP_PRF_SIZE_OP db X86_OP_REX_W lgdt [xBX] sgdt [xDI] lgdt [xSI] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_lgdt_opsize_rexw_bx__sgdt_es_di__lgdt_es_si__ud2) == 11) BS3_PROC_END_CMN bs3CpuBasic2_lgdt_opsize_rexw_bx__sgdt_es_di__lgdt_es_si__ud2 %endif %if TMPL_BITS != 64 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_lgdt_ss_bx__sgdt_es_di__lgdt_es_si__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_lgdt_ss_bx__sgdt_es_di__lgdt_es_si__ud2, BS3_PBC_NEAR lgdt [ss:xBX] sgdt [BS3_NOT_64BIT(es:) xDI] lgdt [BS3_NOT_64BIT(es:) xSI] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_lgdt_ss_bx__sgdt_es_di__lgdt_es_si__ud2) == 12) BS3_PROC_END_CMN bs3CpuBasic2_lgdt_ss_bx__sgdt_es_di__lgdt_es_si__ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_lgdt_opsize_ss_bx__sgdt_es_di__lgdt_es_si__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_lgdt_opsize_ss_bx__sgdt_es_di__lgdt_es_si__ud2, BS3_PBC_NEAR db X86_OP_PRF_SIZE_OP lgdt [ss:xBX] sgdt [BS3_NOT_64BIT(es:) xDI] lgdt [BS3_NOT_64BIT(es:) xSI] .again: ud2 jmp .again AssertCompile(.again - BS3_CMN_NM(bs3CpuBasic2_lgdt_opsize_ss_bx__sgdt_es_di__lgdt_es_si__ud2) == 13) BS3_PROC_END_CMN bs3CpuBasic2_lgdt_opsize_ss_bx__sgdt_es_di__lgdt_es_si__ud2 %endif ; TMPL_BITS != 64 ; ; #PF & #AC ; ; For testing read access. BS3_CPUBAS2_UD_OFF bs3CpuBasic2_mov_ax_ds_bx__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_mov_ax_ds_bx__ud2, BS3_PBC_NEAR mov xAX, [xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_LAST_LABEL == 2 + (TMPL_BITS == 64)) BS3_PROC_END_CMN bs3CpuBasic2_mov_ax_ds_bx__ud2 ; For testing write access. BS3_CPUBAS2_UD_OFF bs3CpuBasic2_mov_ds_bx_ax__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_mov_ds_bx_ax__ud2, BS3_PBC_NEAR mov [xBX], xAX .again: ud2 jmp .again AssertCompile(.again - BS3_LAST_LABEL == 2 + (TMPL_BITS == 64)) BS3_PROC_END_CMN bs3CpuBasic2_mov_ds_bx_ax__ud2 ; For testing read+write access. BS3_CPUBAS2_UD_OFF bs3CpuBasic2_xchg_ds_bx_ax__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_xchg_ds_bx_ax__ud2, BS3_PBC_NEAR xchg [xBX], xAX .again: ud2 jmp .again AssertCompile(.again - BS3_LAST_LABEL == 2 + (TMPL_BITS == 64)) BS3_PROC_END_CMN bs3CpuBasic2_xchg_ds_bx_ax__ud2 ; Another read+write access test. BS3_CPUBAS2_UD_OFF bs3CpuBasic2_cmpxchg_ds_bx_cx__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_cmpxchg_ds_bx_cx__ud2, BS3_PBC_NEAR cmpxchg [xBX], xCX .again: ud2 jmp .again AssertCompile(.again - BS3_LAST_LABEL == 3 + (TMPL_BITS == 64)) BS3_PROC_END_CMN bs3CpuBasic2_cmpxchg_ds_bx_cx__ud2 ; For testing read access from an aborted instruction: DIV by zero BS3_CPUBAS2_UD_OFF bs3CpuBasic2_div_ds_bx__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_div_ds_bx__ud2, BS3_PBC_NEAR div xPRE [xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_LAST_LABEL == 2 + (TMPL_BITS == 64)) BS3_PROC_END_CMN bs3CpuBasic2_div_ds_bx__ud2 ; For testing FLD m80 alignment (#AC). BS3_CPUBAS2_UD_OFF bs3CpuBasic2_fninit_fld_ds_bx__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_fninit_fld_ds_bx__ud2, BS3_PBC_NEAR fninit ; make sure to not trigger a stack overflow. .actual_test_instruction: fld tword [xBX] .again: ud2 jmp .again AssertCompile(.actual_test_instruction - BS3_LAST_LABEL == 2) BS3_PROC_END_CMN bs3CpuBasic2_fninit_fld_ds_bx__ud2 ; For testing FBLD m80 alignment (#AC). BS3_CPUBAS2_UD_OFF bs3CpuBasic2_fninit_fbld_ds_bx__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_fninit_fbld_ds_bx__ud2, BS3_PBC_NEAR fninit ; make sure to not trigger a stack overflow. .actual_test_instruction: fbld tword [xBX] .again: ud2 jmp .again AssertCompile(.actual_test_instruction - BS3_LAST_LABEL == 2) BS3_PROC_END_CMN bs3CpuBasic2_fninit_fbld_ds_bx__ud2 ; For testing FST m80 alignment (#AC). BS3_CPUBAS2_UD_OFF bs3CpuBasic2_fninit_fldz_fstp_ds_bx__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_fninit_fldz_fstp_ds_bx__ud2, BS3_PBC_NEAR fninit ; make sure to not trigger a stack overflow. fldz ; make sure we've got something to store .actual_test_instruction: fstp tword [xBX] .again: ud2 jmp .again AssertCompile(.actual_test_instruction - BS3_LAST_LABEL == 4) BS3_PROC_END_CMN bs3CpuBasic2_fninit_fldz_fstp_ds_bx__ud2 ; For testing FXSAVE alignment (#AC/#GP). BS3_CPUBAS2_UD_OFF bs3CpuBasic2_fxsave_ds_bx__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_fxsave_ds_bx__ud2, BS3_PBC_NEAR fxsave [xBX] .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_fxsave_ds_bx__ud2 ; Two memory operands: push [mem] BS3_CPUBAS2_UD_OFF bs3CpuBasic2_push_ds_bx__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_push_ds_bx__ud2, BS3_PBC_NEAR push xPRE [xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_LAST_LABEL == 2) BS3_PROC_END_CMN bs3CpuBasic2_push_ds_bx__ud2 ; Two memory operands: pop [mem] BS3_CPUBAS2_UD_OFF bs3CpuBasic2_push_ax__pop_ds_bx__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_push_ax__pop_ds_bx__ud2, BS3_PBC_NEAR push xAX pop xPRE [xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_LAST_LABEL == 3) BS3_PROC_END_CMN bs3CpuBasic2_push_ax__pop_ds_bx__ud2 ; Two memory operands: call [mem] BS3_CPUBAS2_UD_OFF bs3CpuBasic2_call_ds_bx__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_call_ds_bx__ud2, BS3_PBC_NEAR call xPRE [xBX] .again: ud2 jmp .again AssertCompile(.again - BS3_LAST_LABEL == 2) BS3_PROC_END_CMN bs3CpuBasic2_call_ds_bx__ud2 ; For testing #GP vs #PF write BS3_CPUBAS2_UD_OFF bs3CpuBasic2_insb__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_insb__ud2, BS3_PBC_NEAR insb .again: ud2 jmp .again AssertCompile(.again - BS3_LAST_LABEL == 1) BS3_PROC_END_CMN bs3CpuBasic2_insb__ud2 ;********************************************************************************************************************************* ;* Non-far JMP & CALL Tests (simple ones). * ;********************************************************************************************************************************* ; jmp rel8 (forwards) BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmp_jb__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmp_jb__ud2, BS3_PBC_NEAR jmp short .again .post_jmp: times 7 int3 .again: ud2 int3 jmp .again AssertCompile(.post_jmp - BS3_LAST_LABEL == 2) BS3_PROC_END_CMN bs3CpuBasic2_jmp_jb__ud2 ; jmp rel8 (backwards) BS3_GLOBAL_NAME_EX RT_CONCAT(BS3_CMN_NM(bs3CpuBasic2_jmp_jb_back__ud2),.again), function, 2 ud2 times 7 int3 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmp_jb_back__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmp_jb_back__ud2, BS3_PBC_NEAR jmp short .again .post_jmp: int3 AssertCompile(.post_jmp - BS3_LAST_LABEL == 2) BS3_PROC_END_CMN bs3CpuBasic2_jmp_jb_back__ud2 ; jmp rel16 (forwards) BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmp_jv__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmp_jv__ud2, BS3_PBC_NEAR jmp near .again .post_jmp: times 9 int3 .again: ud2 int3 jmp .again %if TMPL_BITS == 16 AssertCompile(.post_jmp - BS3_LAST_LABEL == 3) %else AssertCompile(.post_jmp - BS3_LAST_LABEL == 5) %endif BS3_PROC_END_CMN bs3CpuBasic2_jmp_jv__ud2 ; jmp rel16 (backwards) BS3_GLOBAL_NAME_EX RT_CONCAT(BS3_CMN_NM(bs3CpuBasic2_jmp_jv_back__ud2),.again), function, 2 ud2 times 6 int3 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmp_jv_back__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmp_jv_back__ud2, BS3_PBC_NEAR jmp near .again .post_jmp: int3 %if TMPL_BITS == 16 AssertCompile(.post_jmp - BS3_LAST_LABEL == 3) %else AssertCompile(.post_jmp - BS3_LAST_LABEL == 5) %endif BS3_PROC_END_CMN bs3CpuBasic2_jmp_jv_back__ud2 ; jmp [indirect] BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmp_ind_mem__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmp_ind_mem__ud2, BS3_PBC_NEAR %if TMPL_BITS == 16 jmp [word cs:.npAgain] %elif TMPL_BITS == 32 jmp [dword cs:.npAgain] %else jmp [.npAgain] %endif .post_jmp: times 9 int3 .npAgain: %if TMPL_BITS == 16 dw BS3_TEXT16_WRT(.again) %else dd .again wrt FLAT %if TMPL_BITS == 64 dd 0 %endif %endif .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmp_ind_mem__ud2 ; jmp [xAX] BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmp_ind_xAX__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmp_ind_xAX__ud2, BS3_PBC_NEAR jmp xAX .post_jmp: times 17 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmp_ind_xAX__ud2 ; jmp [xDI] BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmp_ind_xDI__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmp_ind_xDI__ud2, BS3_PBC_NEAR jmp xDI .post_jmp: times 17 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmp_ind_xDI__ud2 %if TMPL_BITS == 64 ; jmp [xAX] BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmp_ind_r9__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmp_ind_r9__ud2, BS3_PBC_NEAR jmp r9 .post_jmp: times 17 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmp_ind_r9__ud2 %endif ; call rel16/32 (forwards) BS3_CPUBAS2_UD_OFF bs3CpuBasic2_call_jv__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_call_jv__ud2, BS3_PBC_NEAR call near .again .post_call: times 9 int3 .again: ud2 int3 jmp .again %if TMPL_BITS == 16 AssertCompile(.post_call - BS3_LAST_LABEL == 3) %else AssertCompile(.post_call - BS3_LAST_LABEL == 5) %endif BS3_PROC_END_CMN bs3CpuBasic2_call_jv__ud2 ; call rel16/32 (backwards) BS3_GLOBAL_NAME_EX RT_CONCAT(BS3_CMN_NM(bs3CpuBasic2_call_jv_back__ud2),.again), function, 2 ud2 times 6 int3 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_call_jv_back__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_call_jv_back__ud2, BS3_PBC_NEAR call near .again .post_call: int3 %if TMPL_BITS == 16 AssertCompile(.post_call - BS3_LAST_LABEL == 3) %else AssertCompile(.post_call - BS3_LAST_LABEL == 5) %endif BS3_PROC_END_CMN bs3CpuBasic2_call_jv_back__ud2 ; call [indirect] BS3_CPUBAS2_UD_OFF bs3CpuBasic2_call_ind_mem__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_call_ind_mem__ud2, BS3_PBC_NEAR %if TMPL_BITS == 16 call [word cs:.npAgain] %elif TMPL_BITS == 32 call [dword cs:.npAgain] %else call [.npAgain] %endif .post_call: times 9 int3 .npAgain: %if TMPL_BITS == 16 dw BS3_TEXT16_WRT(.again) %else dd .again wrt FLAT %if TMPL_BITS == 64 dd 0 %endif %endif .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_call_ind_mem__ud2 ; call [xAX] BS3_CPUBAS2_UD_OFF bs3CpuBasic2_call_ind_xAX__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_call_ind_xAX__ud2, BS3_PBC_NEAR call xAX .post_call: times 17 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_call_ind_xAX__ud2 ; call [xDI] BS3_CPUBAS2_UD_OFF bs3CpuBasic2_call_ind_xDI__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_call_ind_xDI__ud2, BS3_PBC_NEAR call xDI .post_call: times 17 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_call_ind_xDI__ud2 %if TMPL_BITS == 64 ; call [xAX] BS3_CPUBAS2_UD_OFF bs3CpuBasic2_call_ind_r9__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_call_ind_r9__ud2, BS3_PBC_NEAR call r9 .post_call: times 17 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_call_ind_r9__ud2 %endif ; ; When applying opsize, we need to put this in the 16-bit text segment to ; better control where we end up in 32-bit and 64-bit mode. ; ; Try keep the code out of the IVT and BIOS data area. We ASSUME that the ; BS3TEXT16 segment portion in this object file will be at the start of the ; image, so we won't waste much space padding up to offset 0x600. ; BS3_BEGIN_TEXT16 TMPL_BITS %if TMPL_BITS == 32 %assign here ($ - $$) %if here < 0x600 times (0x600 - here) int3 %endif %endif BS3_GLOBAL_NAME_EX BS3_CMN_NM(bs3CpuBasic2_jmp_opsize_begin), , 1 ; jmp rel8 (forwards) with opsize override. BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmp_jb_opsize__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmp_jb_opsize__ud2, BS3_PBC_NEAR db 66h jmp short .again .post_jmp: times 8 int3 .again: ud2 int3 jmp .again AssertCompile(.post_jmp - BS3_LAST_LABEL == 3) BS3_PROC_END_CMN bs3CpuBasic2_jmp_jb_opsize__ud2 ; jmp rel8 (backwards) with opsize override. BS3_GLOBAL_NAME_EX RT_CONCAT(BS3_CMN_NM(bs3CpuBasic2_jmp_jb_opsize_back__ud2),.again), function, 2 ud2 times 19 int3 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmp_jb_opsize_back__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmp_jb_opsize_back__ud2, BS3_PBC_NEAR db 66h jmp short .again .post_jmp: int3 AssertCompile(.post_jmp - BS3_LAST_LABEL == 3) BS3_PROC_END_CMN bs3CpuBasic2_jmp_jb_opsize_back__ud2 ; jmp rel16 (forwards) with opsize override. BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmp_jv_opsize__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmp_jv_opsize__ud2, BS3_PBC_NEAR db 66h, 0e9h ; o32 jmp near .again %if TMPL_BITS != 32 dd 11 %else dw 11 %endif .post_jmp: times 11 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmp_jv_opsize__ud2 ; jmp rel16 (backwards) with opsize override. BS3_GLOBAL_NAME_EX RT_CONCAT(BS3_CMN_NM(bs3CpuBasic2_jmp_jv_opsize_back__ud2),.again), function, 2 ud2 times 19 int3 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmp_jv_opsize_back__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmp_jv_opsize_back__ud2, BS3_PBC_NEAR %if TMPL_BITS != 32 db 66h, 0e9h ; o32 jmp near .again dd RT_CONCAT(BS3_CMN_NM(bs3CpuBasic2_jmp_jv_opsize_back__ud2),.again) - .post_jmp %else db 66h, 0e9h ; o16 jmp near .again dw RT_CONCAT(BS3_CMN_NM(bs3CpuBasic2_jmp_jv_opsize_back__ud2),.again) - .post_jmp %endif .post_jmp: int3 BS3_PROC_END_CMN bs3CpuBasic2_jmp_jv_opsize_back__ud2 ; jmp [indirect] BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmp_ind_mem_opsize__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmp_ind_mem_opsize__ud2, BS3_PBC_NEAR db 66h %if TMPL_BITS == 16 jmp [word cs:.npAgain] %elif TMPL_BITS == 32 jmp [dword cs:.npAgain wrt FLAT] %else jmp [.npAgain wrt FLAT] %endif .post_jmp: times 9 int3 .npAgain: %if TMPL_BITS == 16 dw BS3_TEXT16_WRT(.again) dw 0 %else dw .again wrt CGROUP16 dw 0faceh, 0f00dh, 07777h ; non-canonical address %endif .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmp_ind_mem_opsize__ud2 %if TMPL_BITS == 64 ; jmp [indirect] - 64-bit intel version BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmp_ind_mem_opsize__ud2__intel BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmp_ind_mem_opsize__ud2__intel, BS3_PBC_NEAR db 66h jmp [.npAgain wrt FLAT] .post_jmp: times 8 int3 .npAgain: dd .again wrt FLAT dd 0 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmp_ind_mem_opsize__ud2__intel %endif ; jmp [xAX] BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmp_ind_xAX_opsize__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmp_ind_xAX_opsize__ud2, BS3_PBC_NEAR db 66h jmp xAX .post_jmp: times 8 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmp_ind_xAX_opsize__ud2 ; call rel16/32 (forwards) with opsize override. BS3_CPUBAS2_UD_OFF bs3CpuBasic2_call_jv_opsize__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_call_jv_opsize__ud2, BS3_PBC_NEAR db 66h, 0e8h ; o32 jmp near .again %if TMPL_BITS != 32 dd 12 %else dw 12 %endif .post_call: times 12 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_call_jv_opsize__ud2 ; call rel16/32 (backwards) with opsize override. BS3_GLOBAL_NAME_EX RT_CONCAT(BS3_CMN_NM(bs3CpuBasic2_call_jv_opsize_back__ud2),.again), function, 2 ud2 times 19 int3 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_call_jv_opsize_back__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_call_jv_opsize_back__ud2, BS3_PBC_NEAR %if TMPL_BITS != 32 db 66h, 0e8h ; o32 call near .again dd RT_CONCAT(BS3_CMN_NM(bs3CpuBasic2_call_jv_opsize_back__ud2),.again) - .post_call %else db 66h, 0e8h ; o16 call near .again dw RT_CONCAT(BS3_CMN_NM(bs3CpuBasic2_call_jv_opsize_back__ud2),.again) - .post_call %endif .post_call: int3 BS3_PROC_END_CMN bs3CpuBasic2_call_jv_opsize_back__ud2 ; call [indirect] BS3_CPUBAS2_UD_OFF bs3CpuBasic2_call_ind_mem_opsize__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_call_ind_mem_opsize__ud2, BS3_PBC_NEAR db 66h %if TMPL_BITS == 16 call [word cs:.npAgain] %elif TMPL_BITS == 32 call [dword cs:.npAgain wrt FLAT] %else call [.npAgain wrt FLAT] %endif .post_call: times 9 int3 .npAgain: %if TMPL_BITS == 16 dw BS3_TEXT16_WRT(.again) dw 0 %else dw .again wrt CGROUP16 dw 0faceh, 0f00dh, 07777h ; non-canonical address %endif .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_call_ind_mem_opsize__ud2 %if TMPL_BITS == 64 ; call [indirect] - 64-bit intel version BS3_CPUBAS2_UD_OFF bs3CpuBasic2_call_ind_mem_opsize__ud2__intel BS3_PROC_BEGIN_CMN bs3CpuBasic2_call_ind_mem_opsize__ud2__intel, BS3_PBC_NEAR db 66h call [.npAgain wrt FLAT] .post_call: times 8 int3 .npAgain: dd .again wrt FLAT dd 0 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_call_ind_mem_opsize__ud2__intel %endif ; call [xAX] BS3_CPUBAS2_UD_OFF bs3CpuBasic2_call_ind_xAX_opsize__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_call_ind_xAX_opsize__ud2, BS3_PBC_NEAR db 66h call xAX .post_call: times 8 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_call_ind_xAX_opsize__ud2 ; ; Mark the end of the opsize jmp section. ; BS3_GLOBAL_NAME_EX BS3_CMN_NM(bs3CpuBasic2_jmp_opsize_end), , 1 int3 TMPL_BEGIN_TEXT ;********************************************************************************************************************************* ;* FAR JMP ABS * ;********************************************************************************************************************************* ; ; Mark the start of the opsize far jmp/call section. ; ; Here we also need to keep the 16-bit code out of the IVT and BIOS data area, ; not just the 32-bit and 64-bit code like for the above opsize cases. ; BS3_BEGIN_TEXT16 TMPL_BITS %assign here $-$$ %if here < 0x600 times (0x600 - here) int3 %endif BS3_GLOBAL_NAME_EX BS3_CMN_NM(bs3CpuBasic2_far_jmp_call_opsize_begin), , 1 int3 TMPL_BEGIN_TEXT %if TMPL_BITS == 16 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_ptr_rm__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_ptr_rm__ud2, BS3_PBC_NEAR db 0eah dw .again wrt CGROUP16 dw BS3_SEL_TEXT16 .post_jmp: times 2 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_ptr_rm__ud2 %endif %if TMPL_BITS != 64 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_ptr_same_r0__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_ptr_same_r0__ud2, BS3_PBC_NEAR db 0eah %if TMPL_BITS == 16 dw .again wrt CGROUP16 dw BS3_SEL_R0_CS16 %else dd .again wrt FLAT dw BS3_SEL_R0_CS32 %endif .post_jmp: times 7 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_ptr_same_r0__ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_ptr_same_r1__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_ptr_same_r1__ud2, BS3_PBC_NEAR db 0eah ; inter privilege jmp -> #GP(dst-cs) %if TMPL_BITS == 16 dw .again wrt CGROUP16 dw BS3_SEL_R1_CS16 | 1 %else dd .again wrt FLAT dw BS3_SEL_R1_CS32 | 1 %endif .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_ptr_same_r1__ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_ptr_same_r2__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_ptr_same_r2__ud2, BS3_PBC_NEAR db 0eah ; inter privilege jmp -> #GP(dst-cs) %if TMPL_BITS == 16 dw .again wrt CGROUP16 dw BS3_SEL_R2_CS16 | 2 %else dd .again wrt FLAT dw BS3_SEL_R2_CS32 | 2 %endif .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_ptr_same_r2__ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_ptr_same_r3__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_ptr_same_r3__ud2, BS3_PBC_NEAR db 0eah ; inter privilege jmp -> #GP(dst-cs) %if TMPL_BITS == 16 dw .again wrt CGROUP16 dw BS3_SEL_R3_CS16 | 3 %else dd .again wrt FLAT dw BS3_SEL_R3_CS32 | 3 %endif .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_ptr_same_r3__ud2 BS3_BEGIN_TEXT16 TMPL_BITS BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_ptr_opsize_flipbit_r0__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_ptr_opsize_flipbit_r0__ud2, BS3_PBC_NEAR db 066h, 0eah %if TMPL_BITS == 32 dw .again wrt CGROUP16 dw BS3_SEL_R0_CS16 %else dd .again wrt FLAT dw BS3_SEL_R0_CS32 %endif times 4 int3 .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_ptr_opsize_flipbit_r0__ud2 TMPL_BEGIN_TEXT ; Do a jmp to BS3_SEL_R0_CS64. Except for when we're in long mode, this will ; result in a 16-bit CS with zero base and 4G limit. BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_ptr_r0_cs64__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_ptr_r0_cs64__ud2, BS3_PBC_NEAR %if TMPL_BITS == 16 db 066h %endif db 0eah dd .jmp_target wrt FLAT dw BS3_SEL_R0_CS64 times 8 int3 .jmp_target: salc ; #UD in 64-bit mode .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_ptr_r0_cs64__ud2 BS3_BEGIN_TEXT16 TMPL_BITS ; Variation of the previous with a CS16 copy that has the L bit set, emulating ; pre-AMD64 software using the L bit for other stuff. (Don't run in long mode ; w/o copying the 3 bytes to the 0xxxxh memory range.) BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_ptr_r0_cs16l__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_ptr_r0_cs16l__ud2, BS3_PBC_NEAR %if TMPL_BITS != 16 db 066h %endif db 0eah dw .jmp_target wrt CGROUP16 dw BS3_SEL_SPARE_00 ; ASSUMES this is set up as CGROUP16 but with L=1. times 3 int3 .jmp_target: salc ; #UD in 64-bit mode .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_ptr_r0_cs16l__ud2 TMPL_BEGIN_TEXT %endif ; TMPL_BITS != 64 ;********************************************************************************************************************************* ;* FAR CALL ABS * ;********************************************************************************************************************************* %if TMPL_BITS == 16 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_ptr_rm__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_ptr_rm__ud2, BS3_PBC_NEAR db 09ah dw .again wrt CGROUP16 dw BS3_SEL_TEXT16 .post_call: times 2 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_ptr_rm__ud2 %endif %if TMPL_BITS != 64 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_ptr_same_r0__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_ptr_same_r0__ud2, BS3_PBC_NEAR db 09ah %if TMPL_BITS == 16 dw .again wrt CGROUP16 dw BS3_SEL_R0_CS16 %else dd .again wrt FLAT dw BS3_SEL_R0_CS32 %endif .post_call: times 7 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_ptr_same_r0__ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_ptr_same_r1__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_ptr_same_r1__ud2, BS3_PBC_NEAR db 09ah %if TMPL_BITS == 16 dw .again wrt CGROUP16 dw BS3_SEL_R1_CS16 | 1 %else dd .again wrt FLAT dw BS3_SEL_R1_CS32 | 1 %endif .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_ptr_same_r1__ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_ptr_same_r2__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_ptr_same_r2__ud2, BS3_PBC_NEAR db 09ah %if TMPL_BITS == 16 dw .again wrt CGROUP16 dw BS3_SEL_R2_CS16 | 2 %else dd .again wrt FLAT dw BS3_SEL_R2_CS32 | 2 %endif .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_ptr_same_r2__ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_ptr_same_r3__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_ptr_same_r3__ud2, BS3_PBC_NEAR db 09ah %if TMPL_BITS == 16 dw .again wrt CGROUP16 dw BS3_SEL_R3_CS16 | 3 %else dd .again wrt FLAT dw BS3_SEL_R3_CS32 | 3 %endif .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_ptr_same_r3__ud2 BS3_BEGIN_TEXT16 TMPL_BITS BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_ptr_opsize_flipbit_r0__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_ptr_opsize_flipbit_r0__ud2, BS3_PBC_NEAR db 066h, 09ah %if TMPL_BITS == 32 dw .again wrt CGROUP16 dw BS3_SEL_R0_CS16 %else dd .again wrt FLAT dw BS3_SEL_R0_CS32 %endif times 4 int3 .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_ptr_opsize_flipbit_r0__ud2 TMPL_BEGIN_TEXT ; Do a call to BS3_SEL_R0_CS64. Except for when we're in long mode, this will ; result in a 16-bit CS with zero base and 4G limit. BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_ptr_r0_cs64__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_ptr_r0_cs64__ud2, BS3_PBC_NEAR %if TMPL_BITS == 16 db 066h %endif db 09ah dd .call_target wrt FLAT dw BS3_SEL_R0_CS64 times 8 int3 .call_target: salc ; #UD in 64-bit mode .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_ptr_r0_cs64__ud2 BS3_BEGIN_TEXT16 TMPL_BITS ; Variation of the previous with a CS16 copy that has the L bit set, emulating ; pre-AMD64 software using the L bit for other stuff. (Don't run in long mode ; w/o copying the 3 bytes to the 0xxxxh memory range.) BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_ptr_r0_cs16l__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_ptr_r0_cs16l__ud2, BS3_PBC_NEAR %if TMPL_BITS != 16 db 066h %endif db 09ah dw .call_target wrt CGROUP16 dw BS3_SEL_SPARE_00 ; ASSUMES this is set up as CGROUP16 but with L=1. times 3 int3 .call_target: salc ; #UD in 64-bit mode .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_ptr_r0_cs16l__ud2 TMPL_BEGIN_TEXT %endif ; TMPL_BITS != 64 ;********************************************************************************************************************************* ;* INDIRECT FAR JMP * ;********************************************************************************************************************************* %if TMPL_BITS == 16 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_mem_rm__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_mem_rm__ud2, BS3_PBC_NEAR jmp far [BS3_CPUBAS2_REF_LABEL_VIA_CS(.fpfn)] int3 .fpfn: dw .again wrt CGROUP16 dw BS3_SEL_TEXT16 .post_jmp: times 2 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_mem_rm__ud2 %endif ;; ; Since AMD and Intel treat REX.W differently, we need two versions of the ; test functions here and use a macro to accomplish that. ; ; @param 1 Symbol suffix ; @param 2 0 for AMD, 1 for Intel. ; %ifnmacro jmpf_macro %macro jmpf_macro 2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_mem_same_r0__ud2 %+ %1 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_mem_same_r0__ud2 %+ %1, BS3_PBC_NEAR BS3_CPUBAS2_JMP_FAR_MEM_LABEL .fpfn, 2 .fpfn: %if TMPL_BITS == 16 dw .again wrt CGROUP16 dw BS3_SEL_R0_CS16 %elif TMPL_BITS == 32 dd .again wrt FLAT dw BS3_SEL_R0_CS32 %else dd .again wrt FLAT %if %2 != 0 dd 0fffff000h %endif dw BS3_SEL_R0_CS64 %endif .post_jmp: times 7 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_mem_same_r0__ud2 %+ %1 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_mem_same_r1__ud2 %+ %1 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_mem_same_r1__ud2 %+ %1, BS3_PBC_NEAR BS3_CPUBAS2_JMP_FAR_MEM_LABEL .fpfn, 2 .fpfn: %if TMPL_BITS == 16 dw .again wrt CGROUP16 dw BS3_SEL_R1_CS16 | 1 %elif TMPL_BITS == 32 dd .again wrt FLAT dw BS3_SEL_R1_CS32 | 1 %else dd .again wrt FLAT %if %2 != 0 dd 0fffff000h %endif dw BS3_SEL_R1_CS64 | 1 %endif .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_mem_same_r1__ud2 %+ %1 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_mem_same_r2__ud2 %+ %1 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_mem_same_r2__ud2 %+ %1, BS3_PBC_NEAR BS3_CPUBAS2_JMP_FAR_MEM_LABEL .fpfn, 0 .fpfn: %if TMPL_BITS == 16 dw .again wrt CGROUP16 dw BS3_SEL_R2_CS16 | 2 %elif TMPL_BITS == 32 dd .again wrt FLAT dw BS3_SEL_R2_CS32 | 2 %else dd .again wrt FLAT dw BS3_SEL_R2_CS64 | 2 %endif .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_mem_same_r2__ud2 %+ %1 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_mem_same_r3__ud2 %+ %1 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_mem_same_r3__ud2 %+ %1, BS3_PBC_NEAR BS3_CPUBAS2_JMP_FAR_MEM_LABEL .fpfn, 2 .fpfn: %if TMPL_BITS == 16 dw .again wrt CGROUP16 dw BS3_SEL_R3_CS16 | 3 %elif TMPL_BITS == 32 dd .again wrt FLAT dw BS3_SEL_R3_CS32 | 3 %else dd .again wrt FLAT %if %2 != 0 dd 0fffff000h %endif dw BS3_SEL_R3_CS64 | 3 %endif .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_mem_same_r3__ud2 %+ %1 BS3_BEGIN_TEXT16 TMPL_BITS BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_mem_r0_cs16__ud2 %+ %1 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_mem_r0_cs16__ud2 %+ %1, BS3_PBC_NEAR BS3_CPUBAS2_JMP_FAR_MEM_LABEL .fpfn, (TMPL_BITS != 16) ; TMPL_BITS != 16 ? 1 : 0 .fpfn: dw .again wrt CGROUP16 dw BS3_SEL_R0_CS16 times 4 int3 .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_mem_r0_cs16__ud2 %+ %1 TMPL_BEGIN_TEXT BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_mem_r0_cs32__ud2 %+ %1 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_mem_r0_cs32__ud2 %+ %1, BS3_PBC_NEAR BS3_CPUBAS2_JMP_FAR_MEM_LABEL .fpfn, (TMPL_BITS == 16) ; TMPL_BITS == 16 ? 1 : 0 .fpfn: dd .again wrt FLAT dw BS3_SEL_R0_CS32 times 4 int3 .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_mem_r0_cs32__ud2 %+ %1 ; Do a jmp to BS3_SEL_R0_CS64. Except for when we're in long mode, this will ; result in a 16-bit CS with zero base and 4G limit. BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_mem_r0_cs64__ud2 %+ %1 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_mem_r0_cs64__ud2 %+ %1, BS3_PBC_NEAR BS3_CPUBAS2_JMP_FAR_MEM_LABEL .fpfn, (2 - (TMPL_BITS == 16)) ; TMPL_BITS == 16 ? 1 : 2 .fpfn: dd .jmp_target wrt FLAT %if TMPL_BITS == 64 && %2 != 0 dd 0fffff000h %endif dw BS3_SEL_R0_CS64 times 8 int3 .jmp_target: %if TMPL_BITS != 64 salc ; #UD in 64-bit mode %endif .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_mem_r0_cs64__ud2 %+ %1 BS3_BEGIN_TEXT16 TMPL_BITS ; Variation of the previous with a CS16 copy that has the L bit set, emulating ; pre-AMD64 software using the L bit for other stuff. (Don't run _c16/32 in ; long mode w/o copying the 3 bytes to the 0xxxxh memory range.) ; The _c64 version will test that the base is ignored. BS3_CPUBAS2_UD_OFF bs3CpuBasic2_jmpf_mem_r0_cs16l__ud2 %+ %1 BS3_PROC_BEGIN_CMN bs3CpuBasic2_jmpf_mem_r0_cs16l__ud2 %+ %1, BS3_PBC_NEAR BS3_CPUBAS2_JMP_FAR_MEM_LABEL .fpfn, (TMPL_BITS == 32) ; TMPL_BITS == 32 ? 1 : 0 .fpfn: %if TMPL_BITS != 64 dw .jmp_target wrt CGROUP16 %else dd .jmp_target wrt FLAT %endif dw BS3_SEL_SPARE_00 ; ASSUMES this is set up as CGROUP16 but with L=1. times 3 int3 .jmp_target: %if TMPL_BITS != 64 salc ; #UD in 64-bit mode %endif .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_jmpf_mem_r0_cs16l__ud2 %+ %1 TMPL_BEGIN_TEXT %endmacro %endif ; Instantiate the above code jmpf_macro , 0 %if TMPL_BITS == 64 jmpf_macro _intel, 1 %endif ;********************************************************************************************************************************* ;* INDIRECT FAR CALL * ;********************************************************************************************************************************* %if TMPL_BITS == 16 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_mem_rm__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_mem_rm__ud2, BS3_PBC_NEAR call far [BS3_CPUBAS2_REF_LABEL_VIA_CS(.fpfn)] int3 .fpfn: dw .again wrt CGROUP16 dw BS3_SEL_TEXT16 .post_jmp: times 2 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_mem_rm__ud2 %endif ;; ; Since AMD and Intel treat REX.W differently, we need two versions of the ; test functions here and use a macro to accomplish that. ; ; @param 1 Symbol suffix ; @param 2 0 for AMD, 1 for Intel. ; %ifnmacro callf_macro %macro callf_macro 2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_mem_same_r0__ud2 %+ %1 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_mem_same_r0__ud2 %+ %1, BS3_PBC_NEAR BS3_CPUBAS2_CALL_FAR_MEM_LABEL .fpfn, 2 .fpfn: %if TMPL_BITS == 16 dw .again wrt CGROUP16 dw BS3_SEL_R0_CS16 %elif TMPL_BITS == 32 dd .again wrt FLAT dw BS3_SEL_R0_CS32 %else dd .again wrt FLAT %if %2 != 0 dd 0fffff000h %endif dw BS3_SEL_R0_CS64 %endif .post_call: times 7 int3 .again: ud2 int3 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_mem_same_r0__ud2 %+ %1 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_mem_same_r1__ud2 %+ %1 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_mem_same_r1__ud2 %+ %1, BS3_PBC_NEAR BS3_CPUBAS2_CALL_FAR_MEM_LABEL .fpfn, 2 .fpfn: %if TMPL_BITS == 16 dw .again wrt CGROUP16 dw BS3_SEL_R1_CS16 | 1 %elif TMPL_BITS == 32 dd .again wrt FLAT dw BS3_SEL_R1_CS32 | 1 %else dd .again wrt FLAT %if %2 != 0 dd 0fffff000h %endif dw BS3_SEL_R1_CS64 | 1 %endif .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_mem_same_r1__ud2 %+ %1 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_mem_same_r2__ud2 %+ %1 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_mem_same_r2__ud2 %+ %1, BS3_PBC_NEAR BS3_CPUBAS2_CALL_FAR_MEM_LABEL .fpfn, 0 .fpfn: %if TMPL_BITS == 16 dw .again wrt CGROUP16 dw BS3_SEL_R2_CS16 | 2 %elif TMPL_BITS == 32 dd .again wrt FLAT dw BS3_SEL_R2_CS32 | 2 %else dd .again wrt FLAT dw BS3_SEL_R2_CS64 | 2 %endif .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_mem_same_r2__ud2 %+ %1 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_mem_same_r3__ud2 %+ %1 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_mem_same_r3__ud2 %+ %1, BS3_PBC_NEAR BS3_CPUBAS2_CALL_FAR_MEM_LABEL .fpfn, 2 .fpfn: %if TMPL_BITS == 16 dw .again wrt CGROUP16 dw BS3_SEL_R3_CS16 | 3 %elif TMPL_BITS == 32 dd .again wrt FLAT dw BS3_SEL_R3_CS32 | 3 %else dd .again wrt FLAT %if %2 != 0 dd 0fffff000h %endif dw BS3_SEL_R3_CS64 | 3 %endif .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_mem_same_r3__ud2 %+ %1 BS3_BEGIN_TEXT16 TMPL_BITS BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_mem_r0_cs16__ud2 %+ %1 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_mem_r0_cs16__ud2 %+ %1, BS3_PBC_NEAR BS3_CPUBAS2_CALL_FAR_MEM_LABEL .fpfn, (TMPL_BITS != 16) ; (TMPL_BITS == 16 ? 0 : 1) .fpfn: dw .again wrt CGROUP16 dw BS3_SEL_R0_CS16 times 4 int3 .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_mem_r0_cs16__ud2 %+ %1 TMPL_BEGIN_TEXT BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_mem_r0_cs32__ud2 %+ %1 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_mem_r0_cs32__ud2 %+ %1, BS3_PBC_NEAR BS3_CPUBAS2_CALL_FAR_MEM_LABEL .fpfn, (TMPL_BITS == 16) ; (TMPL_BITS == 16 ? 1 : 0) .fpfn: dd .again wrt FLAT dw BS3_SEL_R0_CS32 times 4 int3 .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_mem_r0_cs32__ud2 %+ %1 ; Do a call to BS3_SEL_R0_CS64. Except for when we're in long mode, this will ; result in a 16-bit CS with zero base and 4G limit. BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_mem_r0_cs64__ud2 %+ %1 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_mem_r0_cs64__ud2 %+ %1, BS3_PBC_NEAR BS3_CPUBAS2_CALL_FAR_MEM_LABEL .fpfn, (2 - (TMPL_BITS == 16)) ; (TMPL_BITS == 16 ? 1 : 2) .fpfn: dd .call_target wrt FLAT %if TMPL_BITS == 64 && %2 != 0 dd 0fffff000h %endif dw BS3_SEL_R0_CS64 times 8 int3 .call_target: %if TMPL_BITS != 64 salc ; #UD in 64-bit mode %endif .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_mem_r0_cs64__ud2 %+ %1 BS3_BEGIN_TEXT16 TMPL_BITS ; Variation of the previous with a CS16 copy that has the L bit set, emulating ; pre-AMD64 software using the L bit for other stuff. (Don't run _c16/32 in ; long mode w/o copying the 3 bytes to the 0xxxxh memory range.) ; The _c64 version will test that the base is ignored. BS3_CPUBAS2_UD_OFF bs3CpuBasic2_callf_mem_r0_cs16l__ud2 %+ %1 BS3_PROC_BEGIN_CMN bs3CpuBasic2_callf_mem_r0_cs16l__ud2 %+ %1, BS3_PBC_NEAR BS3_CPUBAS2_CALL_FAR_MEM_LABEL .fpfn, (TMPL_BITS == 32) ; (TMPL_BITS == 32 ? 1 : 0) .fpfn: %if TMPL_BITS != 64 dw .call_target wrt CGROUP16 %else dd .call_target wrt FLAT %endif dw BS3_SEL_SPARE_00 ; ASSUMES this is set up as CGROUP16 but with L=1. times 3 int3 .call_target: %if TMPL_BITS != 64 salc ; #UD in 64-bit mode %endif .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_callf_mem_r0_cs16l__ud2 %+ %1 TMPL_BEGIN_TEXT %endmacro ; callf_macro %endif ; Instantiate the above code callf_macro , 0 %if TMPL_BITS == 64 callf_macro _intel, 1 %endif ; ; Mark the end of the opsize far jmp/call section. ; BS3_BEGIN_TEXT16 TMPL_BITS BS3_GLOBAL_NAME_EX BS3_CMN_NM(bs3CpuBasic2_far_jmp_call_opsize_end), , 1 int3 TMPL_BEGIN_TEXT ;********************************************************************************************************************************* ;* Near RET * ;********************************************************************************************************************************* BS3_GLOBAL_NAME_EX BS3_CMN_NM(bs3CpuBasic2_retn_begin), , 1 ;; ; Macro for emitting various retn Iw variants ; ; @param 1 Number of bytes to pop ; %ifnmacro retn_iw_macro %macro retn_iw_macro 1 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_retn_i %+ %1 %+ __ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_retn_i %+ %1 %+ __ud2, BS3_PBC_NEAR ret %1 .again: ud2 jmp .again AssertCompile(.again - BS3_LAST_LABEL == 3) BS3_PROC_END_CMN bs3CpuBasic2_retn_i %+ %1 %+ __ud2 %if TMPL_BITS == 64 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_retn_i %+ %1 %+ _rexw__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_retn_i %+ %1 %+ _rexw__ud2, BS3_PBC_NEAR db 048h ; REX.W ret %1 .again: ud2 jmp .again AssertCompile(.again - BS3_LAST_LABEL == 4) BS3_PROC_END_CMN bs3CpuBasic2_retn_i %+ %1 %+ _rexw__ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_retn_i %+ %1 %+ _opsize_rexw__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_retn_i %+ %1 %+ _opsize_rexw__ud2, BS3_PBC_NEAR db 66h, 048h ret %1 .again: ud2 jmp .again AssertCompile(.again - BS3_LAST_LABEL == 5) BS3_PROC_END_CMN bs3CpuBasic2_retn_i %+ %1 %+ _opsize_rexw__ud2 %endif %endmacro ; retn_iw_macro %endif ;; ; Macro for emitting various retn Iw variants with an opsize prefix. ; ; @param 1 Number of bytes to pop ; %ifnmacro retn_iw_opsize_macro %macro retn_iw_opsize_macro 1 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_retn_i %+ %1 %+ _opsize__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_retn_i %+ %1 %+ _opsize__ud2, BS3_PBC_NEAR db 66h ret %1 .again: ud2 jmp .again AssertCompile(.again - BS3_LAST_LABEL == 4) BS3_PROC_END_CMN bs3CpuBasic2_retn_i %+ %1 %+ _opsize__ud2 %if TMPL_BITS == 64 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_retn_i %+ %1 %+ _rexw_opsize__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_retn_i %+ %1 %+ _rexw_opsize__ud2, BS3_PBC_NEAR db 048h, 66h ret %1 .again: ud2 jmp .again AssertCompile(.again - BS3_LAST_LABEL == 5) BS3_PROC_END_CMN bs3CpuBasic2_retn_i %+ %1 %+ _rexw_opsize__ud2 %endif %endmacro ; retn_iw_opsize_macro %endif ; The no pop variant BS3_CPUBAS2_UD_OFF bs3CpuBasic2_retn__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_retn__ud2, BS3_PBC_NEAR ret .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_retn__ud2 retn_iw_macro 0 retn_iw_macro 24 retn_iw_macro 760 retn_iw_macro 5193 %if TMPL_BITS == 64 ; The no pop variant BS3_CPUBAS2_UD_OFF bs3CpuBasic2_retn_rexw__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_retn_rexw__ud2, BS3_PBC_NEAR db 048h ; REX.W ret .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_retn_rexw__ud2 BS3_CPUBAS2_UD_OFF bs3CpuBasic2_retn_opsize_rexw__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_retn_opsize_rexw__ud2, BS3_PBC_NEAR db 66h, 048h ret .again: ud2 jmp .again AssertCompile(.again - BS3_LAST_LABEL == 3) BS3_PROC_END_CMN bs3CpuBasic2_retn_opsize_rexw__ud2 %endif ; Mark the start of opsize tests as we end up below 64K in 32-bit and 64-bit when used. BS3_BEGIN_TEXT16 TMPL_BITS BS3_GLOBAL_NAME_EX BS3_CMN_NM(bs3CpuBasic2_retn_opsize_begin), , 1 int3 ; The no pop variant BS3_CPUBAS2_UD_OFF bs3CpuBasic2_retn_opsize__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_retn_opsize__ud2, BS3_PBC_NEAR db 66h ret .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_retn_opsize__ud2 %if TMPL_BITS == 64 ; The no pop variant BS3_CPUBAS2_UD_OFF bs3CpuBasic2_retn_rexw_opsize__ud2 BS3_PROC_BEGIN_CMN bs3CpuBasic2_retn_rexw_opsize__ud2, BS3_PBC_NEAR db 048h, 66h ret .again: ud2 jmp .again BS3_PROC_END_CMN bs3CpuBasic2_retn_rexw_opsize__ud2 %endif retn_iw_opsize_macro 0 retn_iw_opsize_macro 24 retn_iw_opsize_macro 760 retn_iw_opsize_macro 5193 ; End of opsize tests. BS3_GLOBAL_NAME_EX BS3_CMN_NM(bs3CpuBasic2_retn_opsize_end), , 1 int3 TMPL_BEGIN_TEXT BS3_GLOBAL_NAME_EX BS3_CMN_NM(bs3CpuBasic2_retn_end), , 1 int3 ;********************************************************************************************************************************* ;* FAR RET * ;********************************************************************************************************************************* BS3_PROC_BEGIN_CMN bs3CpuBasic2_retf, BS3_PBC_NEAR db 0cbh ; retf BS3_PROC_END_CMN bs3CpuBasic2_retf BS3_PROC_BEGIN_CMN bs3CpuBasic2_retf_opsize, BS3_PBC_NEAR db 066h, 0cbh ; o32/o16 retf BS3_PROC_END_CMN bs3CpuBasic2_retf_opsize BS3_PROC_BEGIN_CMN bs3CpuBasic2_retf_i32, BS3_PBC_NEAR db 0cah, 20h, 0 ; retf 32 BS3_PROC_END_CMN bs3CpuBasic2_retf_i32 BS3_PROC_BEGIN_CMN bs3CpuBasic2_retf_i32_opsize, BS3_PBC_NEAR db 066h, 0cah, 20h, 0 ; o32/o16 retf 32 BS3_PROC_END_CMN bs3CpuBasic2_retf_i32_opsize BS3_PROC_BEGIN_CMN bs3CpuBasic2_retf_i888, BS3_PBC_NEAR db 0cah, 78h, 03h ; retf 888 (0x378) BS3_PROC_END_CMN bs3CpuBasic2_retf_i888 %if TMPL_BITS == 64 BS3_PROC_BEGIN_CMN bs3CpuBasic2_retf_rexw, BS3_PBC_NEAR db 048h, 0cbh ; o64 retf BS3_PROC_END_CMN bs3CpuBasic2_retf_rexw BS3_PROC_BEGIN_CMN bs3CpuBasic2_retf_opsize_rexw, BS3_PBC_NEAR db 066h, 048h, 0cbh ; o16 o64 retf BS3_PROC_END_CMN bs3CpuBasic2_retf_opsize_rexw BS3_PROC_BEGIN_CMN bs3CpuBasic2_retf_rexw_opsize, BS3_PBC_NEAR db 048h, 066h, 0cbh ; o64 o16 retf BS3_PROC_END_CMN bs3CpuBasic2_retf_rexw_opsize BS3_PROC_BEGIN_CMN bs3CpuBasic2_retf_i24_rexw, BS3_PBC_NEAR db 048h, 0cah, 24, 0 ; o64 retf 24 BS3_PROC_END_CMN bs3CpuBasic2_retf_i24_rexw BS3_PROC_BEGIN_CMN bs3CpuBasic2_retf_i24_opsize_rexw, BS3_PBC_NEAR db 066h, 048h, 0cah, 24, 0 ; o16 o64 retf 24 BS3_PROC_END_CMN bs3CpuBasic2_retf_i24_opsize_rexw BS3_PROC_BEGIN_CMN bs3CpuBasic2_retf_i24_rexw_opsize, BS3_PBC_NEAR db 048h, 066h, 0cah, 24, 0 ; o64 o16 retf 24 BS3_PROC_END_CMN bs3CpuBasic2_retf_i24_rexw_opsize %endif ;********************************************************************************************************************************* ;* INVLPG 2/4 MB * ;********************************************************************************************************************************* %ifnmacro BS3_CPUBAS2_INVLPG %macro BS3_CPUBAS2_INVLPG 1 ;; ;; @param sBX Mapping area. ;; @param sDI Pointer to the PDE. ;; @param sDX 1st PDE value. ;; @param sSI 2nd PDE value. ;; @returns uint64_t - zero on success BS3_PROC_BEGIN_CMN bs3CpuBasic2_invlpg_ %+ %1 %+ mb, BS3_PBC_NEAR push xBP mov xBP, xSP push sBX ; xBP - xCB - sCB*1 push sDI ; xBP - xCB - sCB*2 push sDX ; xBP - xCB - sCB*3 push sSI ; xBP - xCB - sCB*4 %if TMPL_BITS == 16 push ds mov ax, BS3_SEL_R0_DS32 ; load flat DS and use 32-bit addressing for everything. mov ds, ax %endif ; ; Pass one: touch pages from bottom, invalidate from the top. ; mov ecx, %1 * 1024 * 1024 .loop1: ; Load TLB for [sBX] using 1st PDE value. mov [sDI], sDX invlpg [sBX] mov eax, [sBX] cmp eax, ebx je .loop1_test1_okay mov edx, 0x11 jmp .return_edx_or_ecx .loop1_test1_okay: ; Switch to the 2nd PDE value, invalidate and check that the value now changed to the 2nd page. mov [sDI], sSI invlpg [sBX + sCX - 1] mov eax, [sBX] sub eax, %1 * 1024 * 1024 ; the value we read is from the 2nd page, so subtract a page before comparing. cmp eax, ebx je .loop1_test2_okay mov edx, 0x12 jmp .return_edx_or_ecx .loop1_test2_okay: ; Advance add ebx, X86_PAGE_SIZE sub sCX, X86_PAGE_SIZE * 2 cmp sCX, -(%1 * 1024 * 1024 / 2) jg .loop1 ; ; Return (int3 back to test driver, actually). ; xor edx, edx xor eax, eax .return: int3 jmp .return .return_edx_or_ecx: or edx, ecx xchg eax, edx jmp .return BS3_PROC_END_CMN bs3CpuBasic2_invlpg_ %+ %1 %+ mb %endmacro %endif BS3_CPUBAS2_INVLPG 2 %if TMPL_BITS != 64 BS3_CPUBAS2_INVLPG 4 %endif ; %endif ; TMPL_BITS != 16 %endif ; BS3_INSTANTIATING_CMN %include "bs3kit-template-footer.mac" ; reset environment