IEMAllAImpl.asm revision 3861ee0eadb3980263ba12134f6d6130f3d411da
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; $Id$
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;; @file
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; IEM - Instruction Implementation in Assembly.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; Copyright (C) 2011-2012 Oracle Corporation
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; This file is part of VirtualBox Open Source Edition (OSE), as
df03c5ed15c9b5bf6d75fedcdf5057d3ffce8577vboxsync; available from http://www.virtualbox.org. This file is free software;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; you can redistribute it and/or modify it under the terms of the GNU
92a27575521748a392dcd1b996fce55b87411a00vboxsync; General Public License (GPL) as published by the Free Software
92a27575521748a392dcd1b996fce55b87411a00vboxsync; Foundation, in version 2 as it comes in the "COPYING" file of the
92a27575521748a392dcd1b996fce55b87411a00vboxsync; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
92a27575521748a392dcd1b996fce55b87411a00vboxsync; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
92a27575521748a392dcd1b996fce55b87411a00vboxsync;
92a27575521748a392dcd1b996fce55b87411a00vboxsync
92a27575521748a392dcd1b996fce55b87411a00vboxsync
92a27575521748a392dcd1b996fce55b87411a00vboxsync;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; Header Files ;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%include "VBox/asmdefs.mac"
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%include "VBox/err.mac"
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%include "iprt/x86.mac"
10cdf5733351fdcd857d439ca32189e812f18682vboxsync
10cdf5733351fdcd857d439ca32189e812f18682vboxsync
10cdf5733351fdcd857d439ca32189e812f18682vboxsync;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10cdf5733351fdcd857d439ca32189e812f18682vboxsync; Defined Constants And Macros ;
10cdf5733351fdcd857d439ca32189e812f18682vboxsync;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10cdf5733351fdcd857d439ca32189e812f18682vboxsync
10cdf5733351fdcd857d439ca32189e812f18682vboxsync;;
10cdf5733351fdcd857d439ca32189e812f18682vboxsync; RET XX / RET wrapper for fastcall.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;
10cdf5733351fdcd857d439ca32189e812f18682vboxsync%macro RET_FASTCALL 1
10cdf5733351fdcd857d439ca32189e812f18682vboxsync%ifdef RT_ARCH_X86
10cdf5733351fdcd857d439ca32189e812f18682vboxsync %ifdef RT_OS_WINDOWS
10cdf5733351fdcd857d439ca32189e812f18682vboxsync ret %1
10cdf5733351fdcd857d439ca32189e812f18682vboxsync %else
10cdf5733351fdcd857d439ca32189e812f18682vboxsync ret
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endif
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%else
cd9e4940318086a06a68bf301960563dcb72b939vboxsync ret
cd9e4940318086a06a68bf301960563dcb72b939vboxsync%endif
cd9e4940318086a06a68bf301960563dcb72b939vboxsync%endmacro
10cdf5733351fdcd857d439ca32189e812f18682vboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;;
10cdf5733351fdcd857d439ca32189e812f18682vboxsync; NAME for fastcall functions.
10cdf5733351fdcd857d439ca32189e812f18682vboxsync;
10cdf5733351fdcd857d439ca32189e812f18682vboxsync;; @todo 'global @fastcall@12' is still broken in yasm and requires dollar
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; escaping (or whatever the dollar is good for here). Thus the ugly
10cdf5733351fdcd857d439ca32189e812f18682vboxsync; prefix argument.
10cdf5733351fdcd857d439ca32189e812f18682vboxsync;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%define NAME_FASTCALL(a_Name, a_cbArgs, a_Prefix) NAME(a_Name)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%ifdef RT_ARCH_X86
10cdf5733351fdcd857d439ca32189e812f18682vboxsync %ifdef RT_OS_WINDOWS
10cdf5733351fdcd857d439ca32189e812f18682vboxsync %undef NAME_FASTCALL
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define NAME_FASTCALL(a_Name, a_cbArgs, a_Prefix) a_Prefix %+ a_Name %+ @ %+ a_cbArgs
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endif
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%endif
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; BEGINPROC for fastcall functions.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; @param 1 The function name (C).
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; @param 2 The argument size on x86.
cd9e4940318086a06a68bf301960563dcb72b939vboxsync;
10cdf5733351fdcd857d439ca32189e812f18682vboxsync%macro BEGINPROC_FASTCALL 2
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %ifdef ASM_FORMAT_PE
10cdf5733351fdcd857d439ca32189e812f18682vboxsync export %1=NAME_FASTCALL(%1,%2,$@)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endif
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %ifdef __NASM__
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %ifdef ASM_FORMAT_OMF
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync export NAME(%1) NAME_FASTCALL(%1,%2,$@)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endif
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endif
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %ifndef ASM_FORMAT_BIN
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync global NAME_FASTCALL(%1,%2,$@)
86abc60770f825f8c2ed4257675b50a08743b687vboxsync %endif
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncNAME_FASTCALL(%1,%2,@):
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync%endmacro
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync;
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync; We employ some macro assembly here to hid the calling convention differences.
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync;
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync%ifdef RT_ARCH_AMD64
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync %macro PROLOGUE_1_ARGS 0
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync %endmacro
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync %macro EPILOGUE_1_ARGS 0
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync ret
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync %endmacro
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync %macro EPILOGUE_1_ARGS_EX 0
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync ret
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync %endmacro
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %macro PROLOGUE_2_ARGS 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endmacro
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %macro EPILOGUE_2_ARGS 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync ret
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %endmacro
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %macro EPILOGUE_2_ARGS_EX 1
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync ret
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %endmacro
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %macro PROLOGUE_3_ARGS 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endmacro
86abc60770f825f8c2ed4257675b50a08743b687vboxsync %macro EPILOGUE_3_ARGS 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync ret
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endmacro
86abc60770f825f8c2ed4257675b50a08743b687vboxsync %macro EPILOGUE_3_ARGS_EX 1
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync ret
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %endmacro
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %macro PROLOGUE_4_ARGS 0
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %endmacro
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %macro EPILOGUE_4_ARGS 0
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync ret
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %endmacro
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %macro EPILOGUE_4_ARGS_EX 1
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync ret
360c39d88dfa26b17181b57ebafdb24c2a113c63vboxsync %endmacro
360c39d88dfa26b17181b57ebafdb24c2a113c63vboxsync
360c39d88dfa26b17181b57ebafdb24c2a113c63vboxsync %ifdef ASM_CALL64_GCC
360c39d88dfa26b17181b57ebafdb24c2a113c63vboxsync %define A0 rdi
360c39d88dfa26b17181b57ebafdb24c2a113c63vboxsync %define A0_32 edi
360c39d88dfa26b17181b57ebafdb24c2a113c63vboxsync %define A0_16 di
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %define A0_8 dil
02fb80eb0db13569db21d1ce5e0f3e0d5a6122aavboxsync
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %define A1 rsi
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %define A1_32 esi
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %define A1_16 si
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %define A1_8 sil
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %define A2 rdx
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync %define A2_32 edx
6967517de4be849f55b0141d6089add0eff2aa7bvboxsync %define A2_16 dx
6967517de4be849f55b0141d6089add0eff2aa7bvboxsync %define A2_8 dl
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync
86abc60770f825f8c2ed4257675b50a08743b687vboxsync %define A3 rcx
7b213bb002950f9fcf809f605cc584fa543481advboxsync %define A3_32 ecx
7b213bb002950f9fcf809f605cc584fa543481advboxsync %define A3_16 cx
7b213bb002950f9fcf809f605cc584fa543481advboxsync %endif
7b213bb002950f9fcf809f605cc584fa543481advboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %ifdef ASM_CALL64_MSC
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A0 rcx
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A0_32 ecx
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A0_16 cx
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A0_8 cl
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A1 rdx
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A1_32 edx
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A1_16 dx
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A1_8 dl
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A2 r8
cd9e4940318086a06a68bf301960563dcb72b939vboxsync %define A2_32 r8d
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A2_16 r8w
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A2_8 r8b
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A3 r9
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A3_32 r9d
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A3_16 r9w
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endif
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync %define T0 rax
cd9e4940318086a06a68bf301960563dcb72b939vboxsync %define T0_32 eax
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define T0_16 ax
cd9e4940318086a06a68bf301960563dcb72b939vboxsync %define T0_8 al
8364ffb7e421fa1ec2bd282ab4c52ac718873d46vboxsync
8364ffb7e421fa1ec2bd282ab4c52ac718873d46vboxsync %define T1 r11
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define T1_32 r11d
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define T1_16 r11w
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define T1_8 r11b
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%else
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync ; x86
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %macro PROLOGUE_1_ARGS 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync push edi
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endmacro
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %macro EPILOGUE_1_ARGS 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync pop edi
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync ret 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endmacro
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %macro EPILOGUE_1_ARGS_EX 1
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync pop edi
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync ret %1
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endmacro
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %macro PROLOGUE_2_ARGS 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync push edi
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endmacro
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %macro EPILOGUE_2_ARGS 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync pop edi
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync ret 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endmacro
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %macro EPILOGUE_2_ARGS_EX 1
c7a92d481aced08517570d43bf75e2a9f3a8aaeavboxsync pop edi
c7a92d481aced08517570d43bf75e2a9f3a8aaeavboxsync ret %1
c7a92d481aced08517570d43bf75e2a9f3a8aaeavboxsync %endmacro
c7a92d481aced08517570d43bf75e2a9f3a8aaeavboxsync
c7a92d481aced08517570d43bf75e2a9f3a8aaeavboxsync %macro PROLOGUE_3_ARGS 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync push ebx
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov ebx, [esp + 4 + 4]
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync push edi
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endmacro
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %macro EPILOGUE_3_ARGS_EX 1
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %if (%1) < 4
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %error "With three args, at least 4 bytes must be remove from the stack upon return (32-bit)."
c7a92d481aced08517570d43bf75e2a9f3a8aaeavboxsync %endif
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync pop edi
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync pop ebx
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync ret %1
08a80484275b5172ce23729ecccc934c6a92d201vboxsync %endmacro
08a80484275b5172ce23729ecccc934c6a92d201vboxsync %macro EPILOGUE_3_ARGS 0
08a80484275b5172ce23729ecccc934c6a92d201vboxsync EPILOGUE_3_ARGS_EX 4
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endmacro
86abc60770f825f8c2ed4257675b50a08743b687vboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %macro PROLOGUE_4_ARGS 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync push ebx
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync push edi
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync push esi
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync mov ebx, [esp + 12 + 4 + 0]
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync mov esi, [esp + 12 + 4 + 4]
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endmacro
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %macro EPILOGUE_4_ARGS_EX 1
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %if (%1) < 8
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %error "With four args, at least 8 bytes must be remove from the stack upon return (32-bit)."
fc148a6b23d25a87561beaffe0ba06c3ba93bf5avboxsync %endif
fc148a6b23d25a87561beaffe0ba06c3ba93bf5avboxsync pop esi
fc148a6b23d25a87561beaffe0ba06c3ba93bf5avboxsync pop edi
fc148a6b23d25a87561beaffe0ba06c3ba93bf5avboxsync pop ebx
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync ret %1
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %endmacro
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %macro EPILOGUE_4_ARGS 0
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync EPILOGUE_4_ARGS_EX 8
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %endmacro
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %define A0 ecx
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %define A0_32 ecx
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %define A0_16 cx
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %define A0_8 cl
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %define A1 edx
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %define A1_32 edx
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %define A1_16 dx
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %define A1_8 dl
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %define A2 ebx
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %define A2_32 ebx
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %define A2_16 bx
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %define A2_8 bl
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A3 esi
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A3_32 esi
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define A3_16 si
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %define T0 eax
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %define T0_32 eax
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %define T0_16 ax
bc8beda7587b16cafe7de7bea19149de1bd4b498vboxsync %define T0_8 al
bc8beda7587b16cafe7de7bea19149de1bd4b498vboxsync
59e30364f54880dd846c263711a2506d1182b1b5vboxsync %define T1 edi
59e30364f54880dd846c263711a2506d1182b1b5vboxsync %define T1_32 edi
59e30364f54880dd846c263711a2506d1182b1b5vboxsync %define T1_16 di
59e30364f54880dd846c263711a2506d1182b1b5vboxsync%endif
3acaac88e9a4c925226db26f0d374f9f4876b74fvboxsync
cc8517c11be66037a9873fa03f280e7742efed6dvboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; Load the relevant flags from [%1] if there are undefined flags (%3).
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; @remarks Clobbers T0, stack. Changes EFLAGS.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; @param A2 The register pointing to the flags.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; @param 1 The parameter (A0..A3) pointing to the eflags.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; @param 2 The set of modified flags.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; @param 3 The set of undefined flags.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%macro IEM_MAYBE_LOAD_FLAGS 3
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync ;%if (%3) != 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync pushf ; store current flags
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov T0_32, [%1] ; load the guest flags
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync and dword [xSP], ~(%2 | %3) ; mask out the modified and undefined flags
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync and T0_32, (%2 | %3) ; select the modified and undefined flags.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync or [xSP], T0 ; merge guest flags with host flags.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync popf ; load the mixed flags.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync ;%endif
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%endmacro
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; Update the flag.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; @remarks Clobbers T0, T1, stack.
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync; @param 1 The register pointing to the EFLAGS.
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync; @param 2 The mask of modified flags to save.
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync; @param 3 The mask of undefined flags to (maybe) save.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%macro IEM_SAVE_FLAGS 3
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %if (%2 | %3) != 0
08a56d5836eceeb24642b61eaa52a4edb0a7b482vboxsync pushf
08a56d5836eceeb24642b61eaa52a4edb0a7b482vboxsync pop T1
08a56d5836eceeb24642b61eaa52a4edb0a7b482vboxsync mov T0_32, [%1] ; flags
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync and T0_32, ~(%2 | %3) ; clear the modified & undefined flags.
3b3bc8a9383a065307e540b83fc3a3d6c548a082vboxsync and T1_32, (%2 | %3) ; select the modified and undefined flags.
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync or T0_32, T1_32 ; combine the flags.
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync mov [%1], T0_32 ; save the flags.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endif
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync%endmacro
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync;;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; Macro for implementing a binary operator.
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync;
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync; This will generate code for the 8, 16, 32 and 64 bit accesses with locked
3196a540aa11c41264b0e79857b879e4ab566f4bvboxsync; variants, except on 32-bit system where the 64-bit accesses requires hand
3196a540aa11c41264b0e79857b879e4ab566f4bvboxsync; coding.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync; All the functions takes a pointer to the destination memory operand in A0,
3196a540aa11c41264b0e79857b879e4ab566f4bvboxsync; the source register operand in A1 and a pointer to eflags in A2.
3196a540aa11c41264b0e79857b879e4ab566f4bvboxsync;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; @param 1 The instruction mnemonic.
16aeb8f83239d4a4a10ecac1fb46fe24a8bdbb66vboxsync; @param 2 Non-zero if there should be a locked version.
16aeb8f83239d4a4a10ecac1fb46fe24a8bdbb66vboxsync; @param 3 The modified flags.
16aeb8f83239d4a4a10ecac1fb46fe24a8bdbb66vboxsync; @param 4 The undefined flags.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%macro IEMIMPL_BIN_OP 4
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINCODE
2705a216ac12110a0813d671e230797c886b4788vboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 12
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync PROLOGUE_3_ARGS
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync IEM_MAYBE_LOAD_FLAGS A2, %3, %4
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync %1 byte [A0], A1_8
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync IEM_SAVE_FLAGS A2, %3, %4
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync EPILOGUE_3_ARGS
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsyncENDPROC iemAImpl_ %+ %1 %+ _u8
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 12
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync PROLOGUE_3_ARGS
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync IEM_MAYBE_LOAD_FLAGS A2, %3, %4
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync %1 word [A0], A1_16
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync IEM_SAVE_FLAGS A2, %3, %4
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync EPILOGUE_3_ARGS
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsyncENDPROC iemAImpl_ %+ %1 %+ _u16
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync
24b88f881835a6c392e72177f74f1d5e4544ba1evboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 12
f8244da4b4e02d8d4ce0669eeb4093e31c301888vboxsync PROLOGUE_3_ARGS
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync IEM_MAYBE_LOAD_FLAGS A2, %3, %4
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync %1 dword [A0], A1_32
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync IEM_SAVE_FLAGS A2, %3, %4
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync EPILOGUE_3_ARGS
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsyncENDPROC iemAImpl_ %+ %1 %+ _u32
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync %ifdef RT_ARCH_AMD64
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync PROLOGUE_3_ARGS
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync IEM_MAYBE_LOAD_FLAGS A2, %3, %4
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync %1 qword [A0], A1
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync IEM_SAVE_FLAGS A2, %3, %4
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync EPILOGUE_3_ARGS_EX 8
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsyncENDPROC iemAImpl_ %+ %1 %+ _u64
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync %else ; stub it for now - later, replace with hand coded stuff.
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync int3
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync ret
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncENDPROC iemAImpl_ %+ %1 %+ _u64
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync %endif ; !RT_ARCH_AMD64
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync %if %2 != 0 ; locked versions requested?
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8_locked, 12
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync PROLOGUE_3_ARGS
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync IEM_MAYBE_LOAD_FLAGS A2, %3, %4
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync lock %1 byte [A0], A1_8
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync IEM_SAVE_FLAGS A2, %3, %4
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync EPILOGUE_3_ARGS
bee07f28c146fb5313ea13d84dcd508d8f604a10vboxsyncENDPROC iemAImpl_ %+ %1 %+ _u8_locked
441e51789084e8795573747fec9f5108e8b54e98vboxsync
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16_locked, 12
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync PROLOGUE_3_ARGS
15ca5f803f0c1bfc86a224523ef482f8aa960388vboxsync IEM_MAYBE_LOAD_FLAGS A2, %3, %4
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync lock %1 word [A0], A1_16
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync IEM_SAVE_FLAGS A2, %3, %4
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync EPILOGUE_3_ARGS
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncENDPROC iemAImpl_ %+ %1 %+ _u16_locked
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32_locked, 12
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync PROLOGUE_3_ARGS
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync IEM_MAYBE_LOAD_FLAGS A2, %3, %4
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync lock %1 dword [A0], A1_32
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync IEM_SAVE_FLAGS A2, %3, %4
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync EPILOGUE_3_ARGS
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsyncENDPROC iemAImpl_ %+ %1 %+ _u32_locked
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync %ifdef RT_ARCH_AMD64
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 16
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync PROLOGUE_3_ARGS
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync IEM_MAYBE_LOAD_FLAGS A2, %3, %4
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync lock %1 qword [A0], A1
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync IEM_SAVE_FLAGS A2, %3, %4
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync EPILOGUE_3_ARGS_EX 8
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsyncENDPROC iemAImpl_ %+ %1 %+ _u64_locked
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync %else ; stub it for now - later, replace with hand coded stuff.
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 16
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync int3
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync ret 8
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncENDPROC iemAImpl_ %+ %1 %+ _u64_locked
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync %endif ; !RT_ARCH_AMD64
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync %endif ; locked
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync%endmacro
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync; instr,lock,modified-flags.
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncIEMIMPL_BIN_OP add, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncIEMIMPL_BIN_OP adc, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncIEMIMPL_BIN_OP sub, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncIEMIMPL_BIN_OP sbb, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncIEMIMPL_BIN_OP or, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncIEMIMPL_BIN_OP xor, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncIEMIMPL_BIN_OP and, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncIEMIMPL_BIN_OP cmp, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
1cc3bd5463294790ba54c78fde5313264185e50cvboxsyncIEMIMPL_BIN_OP test, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync
8d466f9285d86e81f927c2bf053a2eb7ec325746vboxsync
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync;;
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync; Macro for implementing a bit operator.
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync;
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync; This will generate code for the 16, 32 and 64 bit accesses with locked
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync; variants, except on 32-bit system where the 64-bit accesses requires hand
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync; coding.
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync;
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync; All the functions takes a pointer to the destination memory operand in A0,
2c76fd8cdec6f32663a03b16fb5871f7c54330a6vboxsync; the source register operand in A1 and a pointer to eflags in A2.
2c76fd8cdec6f32663a03b16fb5871f7c54330a6vboxsync;
2705a216ac12110a0813d671e230797c886b4788vboxsync; @param 1 The instruction mnemonic.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; @param 2 Non-zero if there should be a locked version.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; @param 3 The modified flags.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; @param 4 The undefined flags.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%macro IEMIMPL_BIT_OP 4
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINCODE
c7a92d481aced08517570d43bf75e2a9f3a8aaeavboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 12
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PROLOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_MAYBE_LOAD_FLAGS A2, %3, %4
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %1 word [A0], A1_16
42d36464aee6c81b4f206b6c02035587501ff67cvboxsync IEM_SAVE_FLAGS A2, %3, %4
c3e38cccf650831700227918a021e6c4097ace82vboxsync EPILOGUE_3_ARGS
42d36464aee6c81b4f206b6c02035587501ff67cvboxsyncENDPROC iemAImpl_ %+ %1 %+ _u16
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 12
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync PROLOGUE_3_ARGS
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync IEM_MAYBE_LOAD_FLAGS A2, %3, %4
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %1 dword [A0], A1_32
3b3bc8a9383a065307e540b83fc3a3d6c548a082vboxsync IEM_SAVE_FLAGS A2, %3, %4
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync EPILOGUE_3_ARGS
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsyncENDPROC iemAImpl_ %+ %1 %+ _u32
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync %ifdef RT_ARCH_AMD64
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync PROLOGUE_3_ARGS
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync IEM_MAYBE_LOAD_FLAGS A2, %3, %4
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %1 qword [A0], A1
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync IEM_SAVE_FLAGS A2, %3, %4
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync EPILOGUE_3_ARGS_EX 8
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_ %+ %1 %+ _u64
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %else ; stub it for now - later, replace with hand coded stuff.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync int3
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync ret 8
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_ %+ %1 %+ _u64
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endif ; !RT_ARCH_AMD64
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %if %2 != 0 ; locked versions requested?
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16_locked, 12
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PROLOGUE_3_ARGS
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync IEM_MAYBE_LOAD_FLAGS A2, %3, %4
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync lock %1 word [A0], A1_16
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync IEM_SAVE_FLAGS A2, %3, %4
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync EPILOGUE_3_ARGS
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsyncENDPROC iemAImpl_ %+ %1 %+ _u16_locked
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32_locked, 12
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync PROLOGUE_3_ARGS
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync IEM_MAYBE_LOAD_FLAGS A2, %3, %4
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync lock %1 dword [A0], A1_32
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync IEM_SAVE_FLAGS A2, %3, %4
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync EPILOGUE_3_ARGS
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsyncENDPROC iemAImpl_ %+ %1 %+ _u32_locked
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync %ifdef RT_ARCH_AMD64
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 16
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PROLOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_MAYBE_LOAD_FLAGS A2, %3, %4
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync lock %1 qword [A0], A1
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_SAVE_FLAGS A2, %3, %4
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync EPILOGUE_3_ARGS_EX 8
cd9e4940318086a06a68bf301960563dcb72b939vboxsyncENDPROC iemAImpl_ %+ %1 %+ _u64_locked
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %else ; stub it for now - later, replace with hand coded stuff.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 16
5857f4e58ce2ef50d7f0c450fe4897026f9a9c3dvboxsync int3
42dc09ee69e746b8641cfa190931a15ecfd7295cvboxsync ret 8
e0b91e4f93fb43371374df4aeb636dffea336056vboxsyncENDPROC iemAImpl_ %+ %1 %+ _u64_locked
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endif ; !RT_ARCH_AMD64
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endif ; locked
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%endmacro
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncIEMIMPL_BIT_OP bt, 0, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncIEMIMPL_BIT_OP btc, 1, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncIEMIMPL_BIT_OP bts, 1, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncIEMIMPL_BIT_OP btr, 1, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; Macro for implementing a bit search operator.
2705a216ac12110a0813d671e230797c886b4788vboxsync;
2705a216ac12110a0813d671e230797c886b4788vboxsync; This will generate code for the 16, 32 and 64 bit accesses, except on 32-bit
2705a216ac12110a0813d671e230797c886b4788vboxsync; system where the 64-bit accesses requires hand coding.
bcc95fabf162c0f743d7eaafb0d21f7ef967e9f4vboxsync;
2705a216ac12110a0813d671e230797c886b4788vboxsync; All the functions takes a pointer to the destination memory operand in A0,
2705a216ac12110a0813d671e230797c886b4788vboxsync; the source register operand in A1 and a pointer to eflags in A2.
2705a216ac12110a0813d671e230797c886b4788vboxsync;
2705a216ac12110a0813d671e230797c886b4788vboxsync; @param 1 The instruction mnemonic.
2705a216ac12110a0813d671e230797c886b4788vboxsync; @param 2 The modified flags.
2705a216ac12110a0813d671e230797c886b4788vboxsync; @param 3 The undefined flags.
2705a216ac12110a0813d671e230797c886b4788vboxsync;
2705a216ac12110a0813d671e230797c886b4788vboxsync%macro IEMIMPL_BIT_OP 3
de86a09bf42f7e7d80a0a5acf1e8e99d445be1d3vboxsyncBEGINCODE
c0da96af18c7b40ac5cfd7e7ea398a398540f224vboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 12
c0da96af18c7b40ac5cfd7e7ea398a398540f224vboxsync PROLOGUE_3_ARGS
c0da96af18c7b40ac5cfd7e7ea398a398540f224vboxsync IEM_MAYBE_LOAD_FLAGS A2, %2, %3
c0da96af18c7b40ac5cfd7e7ea398a398540f224vboxsync %1 T0_16, A1_16
c0da96af18c7b40ac5cfd7e7ea398a398540f224vboxsync jz .unchanged_dst
c0da96af18c7b40ac5cfd7e7ea398a398540f224vboxsync mov [A0], T0_16
c0da96af18c7b40ac5cfd7e7ea398a398540f224vboxsync.unchanged_dst:
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync IEM_SAVE_FLAGS A2, %2, %3
8e77372da4b53557362ee8ea967def86f7bed166vboxsync EPILOGUE_3_ARGS
8e77372da4b53557362ee8ea967def86f7bed166vboxsyncENDPROC iemAImpl_ %+ %1 %+ _u16
2705a216ac12110a0813d671e230797c886b4788vboxsync
2705a216ac12110a0813d671e230797c886b4788vboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 12
2705a216ac12110a0813d671e230797c886b4788vboxsync PROLOGUE_3_ARGS
2705a216ac12110a0813d671e230797c886b4788vboxsync IEM_MAYBE_LOAD_FLAGS A2, %2, %3
2705a216ac12110a0813d671e230797c886b4788vboxsync %1 T0_32, A1_32
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync jz .unchanged_dst
2705a216ac12110a0813d671e230797c886b4788vboxsync mov [A0], T0_32
2705a216ac12110a0813d671e230797c886b4788vboxsync.unchanged_dst:
2705a216ac12110a0813d671e230797c886b4788vboxsync IEM_SAVE_FLAGS A2, %2, %3
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync EPILOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_ %+ %1 %+ _u32
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %ifdef RT_ARCH_AMD64
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PROLOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_MAYBE_LOAD_FLAGS A2, %2, %3
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %1 T0, A1
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync jz .unchanged_dst
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov [A0], T0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync.unchanged_dst:
5c571d69a0355bedb9a401ce4de992a2b0ef3515vboxsync IEM_SAVE_FLAGS A2, %2, %3
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync EPILOGUE_3_ARGS_EX 8
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_ %+ %1 %+ _u64
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %else ; stub it for now - later, replace with hand coded stuff.
c0da96af18c7b40ac5cfd7e7ea398a398540f224vboxsyncBEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync int3
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync ret 8
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_ %+ %1 %+ _u64
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync %endif ; !RT_ARCH_AMD64
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%endmacro
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncIEMIMPL_BIT_OP bsf, (X86_EFL_ZF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF)
17aee8484f9e8699c2515d450552c622aea0889evboxsyncIEMIMPL_BIT_OP bsr, (X86_EFL_ZF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; IMUL is also a similar but yet different case (no lock, no mem dst).
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; The rDX:rAX variant of imul is handled together with mul further down.
17aee8484f9e8699c2515d450552c622aea0889evboxsync;
17aee8484f9e8699c2515d450552c622aea0889evboxsyncBEGINCODE
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_imul_two_u16, 12
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PROLOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync imul A1_16, word [A0]
17aee8484f9e8699c2515d450552c622aea0889evboxsync mov [A0], A1_16
17aee8484f9e8699c2515d450552c622aea0889evboxsync IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync EPILOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_imul_two_u16
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_imul_two_u32, 12
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PROLOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
17aee8484f9e8699c2515d450552c622aea0889evboxsync imul A1_32, dword [A0]
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov [A0], A1_32
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync EPILOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_imul_two_u32
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
17aee8484f9e8699c2515d450552c622aea0889evboxsyncBEGINPROC_FASTCALL iemAImpl_imul_two_u64, 16
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PROLOGUE_3_ARGS
41beaec6d563ed06201d5e42a0e8cf32c06b3388vboxsync%ifdef RT_ARCH_AMD64
0c657f93ac727a3a1644497331d86fbcbc3722aavboxsync IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync imul A1, qword [A0]
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov [A0], A1
42dc09ee69e746b8641cfa190931a15ecfd7295cvboxsync IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
42dc09ee69e746b8641cfa190931a15ecfd7295cvboxsync%else
42dc09ee69e746b8641cfa190931a15ecfd7295cvboxsync int3 ;; @todo implement me
ee6495ebe54829fea21ffbb6f1275315e72d4506vboxsync%endif
42dc09ee69e746b8641cfa190931a15ecfd7295cvboxsync EPILOGUE_3_ARGS_EX 8
98bfcb808aa93fe8b532eb38da1f15a795a85f6dvboxsyncENDPROC iemAImpl_imul_two_u64
98bfcb808aa93fe8b532eb38da1f15a795a85f6dvboxsync
42dc09ee69e746b8641cfa190931a15ecfd7295cvboxsync
42dc09ee69e746b8641cfa190931a15ecfd7295cvboxsync;
aebbe380e89aef2b57dbf7a30f70536c5d807b74vboxsync; XCHG for memory operands. This implies locking. No flag changes.
e0b91e4f93fb43371374df4aeb636dffea336056vboxsync;
17aee8484f9e8699c2515d450552c622aea0889evboxsync; Each function takes two arguments, first the pointer to the memory,
e0b91e4f93fb43371374df4aeb636dffea336056vboxsync; then the pointer to the register. They all return void.
e0b91e4f93fb43371374df4aeb636dffea336056vboxsync;
e0b91e4f93fb43371374df4aeb636dffea336056vboxsyncBEGINCODE
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_xchg_u8, 8
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PROLOGUE_2_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov T0_8, [A1]
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync xchg [A0], T0_8
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov [A1], T0_8
17aee8484f9e8699c2515d450552c622aea0889evboxsync EPILOGUE_2_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_xchg_u8
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_xchg_u16, 8
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PROLOGUE_2_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov T0_16, [A1]
17aee8484f9e8699c2515d450552c622aea0889evboxsync xchg [A0], T0_16
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov [A1], T0_16
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync EPILOGUE_2_ARGS
17aee8484f9e8699c2515d450552c622aea0889evboxsyncENDPROC iemAImpl_xchg_u16
17aee8484f9e8699c2515d450552c622aea0889evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_xchg_u32, 8
17aee8484f9e8699c2515d450552c622aea0889evboxsync PROLOGUE_2_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov T0_32, [A1]
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync xchg [A0], T0_32
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov [A1], T0_32
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync EPILOGUE_2_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_xchg_u32
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
17aee8484f9e8699c2515d450552c622aea0889evboxsyncBEGINPROC_FASTCALL iemAImpl_xchg_u64, 8
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%ifdef RT_ARCH_AMD64
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PROLOGUE_2_ARGS
cd9e4940318086a06a68bf301960563dcb72b939vboxsync mov T0, [A1]
cd9e4940318086a06a68bf301960563dcb72b939vboxsync xchg [A0], T0
cd9e4940318086a06a68bf301960563dcb72b939vboxsync mov [A1], T0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync EPILOGUE_2_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%else
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync int3
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync ret 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%endif
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_xchg_u64
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; XADD for memory operands.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; Each function takes three arguments, first the pointer to the
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; memory/register, then the pointer to the register, and finally a pointer to
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync; eflags. They all return void.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync;
17aee8484f9e8699c2515d450552c622aea0889evboxsyncBEGINCODE
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_xadd_u8, 12
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PROLOGUE_3_ARGS
cd9e4940318086a06a68bf301960563dcb72b939vboxsync IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov T0_8, [A1]
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync xadd [A0], T0_8
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync mov [A1], T0_8
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync EPILOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_xadd_u8
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_xadd_u16, 12
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PROLOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov T0_16, [A1]
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync xadd [A0], T0_16
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov [A1], T0_16
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync EPILOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_xadd_u16
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_xadd_u32, 12
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PROLOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov T0_32, [A1]
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync xadd [A0], T0_32
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov [A1], T0_32
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync EPILOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_xadd_u32
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_xadd_u64, 12
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%ifdef RT_ARCH_AMD64
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PROLOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov T0, [A1]
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync xadd [A0], T0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov [A1], T0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync EPILOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%else
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync int3
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync ret 4
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%endif
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_xadd_u64
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_xadd_u8_locked, 12
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PROLOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov T0_8, [A1]
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync lock xadd [A0], T0_8
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov [A1], T0_8
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
9300c669f18e40bb3bd8bb6a0f7efaeb2bbd790fvboxsync EPILOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_xadd_u8_locked
9300c669f18e40bb3bd8bb6a0f7efaeb2bbd790fvboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_xadd_u16_locked, 12
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PROLOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov T0_16, [A1]
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync lock xadd [A0], T0_16
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov [A1], T0_16
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync EPILOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_xadd_u16_locked
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncBEGINPROC_FASTCALL iemAImpl_xadd_u32_locked, 12
3196a540aa11c41264b0e79857b879e4ab566f4bvboxsync PROLOGUE_3_ARGS
3196a540aa11c41264b0e79857b879e4ab566f4bvboxsync IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
3196a540aa11c41264b0e79857b879e4ab566f4bvboxsync mov T0_32, [A1]
3196a540aa11c41264b0e79857b879e4ab566f4bvboxsync lock xadd [A0], T0_32
3196a540aa11c41264b0e79857b879e4ab566f4bvboxsync mov [A1], T0_32
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync EPILOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncENDPROC iemAImpl_xadd_u32_locked
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
17aee8484f9e8699c2515d450552c622aea0889evboxsyncBEGINPROC_FASTCALL iemAImpl_xadd_u64_locked, 12
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%ifdef RT_ARCH_AMD64
98bfcb808aa93fe8b532eb38da1f15a795a85f6dvboxsync PROLOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov T0, [A1]
17aee8484f9e8699c2515d450552c622aea0889evboxsync lock xadd [A0], T0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync mov [A1], T0
98bfcb808aa93fe8b532eb38da1f15a795a85f6dvboxsync IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync EPILOGUE_3_ARGS
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync%else
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync int3
772269936494ffaddd0750ba9e28e805ba81398cvboxsync ret 4
%endif
ENDPROC iemAImpl_xadd_u64_locked
;
; CMPXCHG8B.
;
; These are tricky register wise, so the code is duplicated for each calling
; convention.
;
; WARNING! This code make ASSUMPTIONS about which registers T1 and T0 are mapped to!
;
; C-proto:
; IEM_DECL_IMPL_DEF(void, iemAImpl_cmpxchg8b,(uint64_t *pu64Dst, PRTUINT64U pu64EaxEdx, PRTUINT64U pu64EbxEcx,
; uint32_t *pEFlags));
;
BEGINCODE
BEGINPROC_FASTCALL iemAImpl_cmpxchg8b, 16
%ifdef RT_ARCH_AMD64
%ifdef ASM_CALL64_MSC
push rbx
mov r11, rdx ; pu64EaxEdx (is also T1)
mov r10, rcx ; pu64Dst
mov ebx, [r8]
mov ecx, [r8 + 4]
IEM_MAYBE_LOAD_FLAGS r9, (X86_EFL_ZF), 0 ; clobbers T0 (eax)
mov eax, [r11]
mov edx, [r11 + 4]
lock cmpxchg8b [r10]
mov [r11], eax
mov [r11 + 4], edx
IEM_SAVE_FLAGS r9, (X86_EFL_ZF), 0 ; clobbers T0+T1 (eax, r11)
pop rbx
ret
%else
push rbx
mov r10, rcx ; pEFlags
mov r11, rdx ; pu64EbxEcx (is also T1)
mov ebx, [r11]
mov ecx, [r11 + 4]
IEM_MAYBE_LOAD_FLAGS r10, (X86_EFL_ZF), 0 ; clobbers T0 (eax)
mov eax, [rsi]
mov edx, [rsi + 4]
lock cmpxchg8b [rdi]
mov [rsi], eax
mov [rsi + 4], edx
IEM_SAVE_FLAGS r10, (X86_EFL_ZF), 0 ; clobbers T0+T1 (eax, r11)
pop rbx
ret
%endif
%else
push esi
push edi
push ebx
push ebp
mov edi, ecx ; pu64Dst
mov esi, edx ; pu64EaxEdx
mov ecx, [esp + 16 + 4 + 0] ; pu64EbxEcx
mov ebp, [esp + 16 + 4 + 4] ; pEFlags
mov ebx, [ecx]
mov ecx, [ecx + 4]
IEM_MAYBE_LOAD_FLAGS ebp, (X86_EFL_ZF), 0 ; clobbers T0 (eax)
mov eax, [esi]
mov edx, [esi + 4]
lock cmpxchg8b [edi]
mov [esi], eax
mov [esi + 4], edx
IEM_SAVE_FLAGS ebp, (X86_EFL_ZF), 0 ; clobbers T0+T1 (eax, edi)
pop ebp
pop ebx
pop edi
pop esi
ret 8
%endif
ENDPROC iemAImpl_cmpxchg8b
BEGINPROC_FASTCALL iemAImpl_cmpxchg8b_locked, 16
; Lazy bird always lock prefixes cmpxchg8b.
jmp NAME_FASTCALL(iemAImpl_cmpxchg8b,16,$@)
ENDPROC iemAImpl_cmpxchg8b_locked
;
; CMPXCHG.
;
; WARNING! This code make ASSUMPTIONS about which registers T1 and T0 are mapped to!
;
; C-proto:
; IEM_DECL_IMPL_DEF(void, iemAImpl_cmpxchg,(uintX_t *puXDst, uintX_t puEax, uintX_t uReg, uint32_t *pEFlags));
;
BEGINCODE
%macro IEMIMPL_CMPXCHG 2
BEGINPROC_FASTCALL iemAImpl_cmpxchg_u8 %+ %2, 16
PROLOGUE_4_ARGS
IEM_MAYBE_LOAD_FLAGS A3, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0 (eax)
mov al, [A1]
%1 cmpxchg [A0], A2_8
mov [A1], al
IEM_SAVE_FLAGS A3, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0+T1 (eax, r11/edi)
EPILOGUE_4_ARGS
ENDPROC iemAImpl_cmpxchg_u8 %+ %2
BEGINPROC_FASTCALL iemAImpl_cmpxchg_u16 %+ %2, 16
PROLOGUE_4_ARGS
IEM_MAYBE_LOAD_FLAGS A3, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0 (eax)
mov ax, [A1]
%1 cmpxchg [A0], A2_16
mov [A1], ax
IEM_SAVE_FLAGS A3, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0+T1 (eax, r11/edi)
EPILOGUE_4_ARGS
ENDPROC iemAImpl_cmpxchg_u16 %+ %2
BEGINPROC_FASTCALL iemAImpl_cmpxchg_u32 %+ %2, 16
PROLOGUE_4_ARGS
IEM_MAYBE_LOAD_FLAGS A3, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0 (eax)
mov eax, [A1]
%1 cmpxchg [A0], A2_32
mov [A1], eax
IEM_SAVE_FLAGS A3, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0+T1 (eax, r11/edi)
EPILOGUE_4_ARGS
ENDPROC iemAImpl_cmpxchg_u32 %+ %2
BEGINPROC_FASTCALL iemAImpl_cmpxchg_u64 %+ %2, 16
%ifdef RT_ARCH_AMD64
PROLOGUE_4_ARGS
IEM_MAYBE_LOAD_FLAGS A3, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0 (eax)
mov rax, [A1]
%1 cmpxchg [A0], A2
mov [A1], rax
IEM_SAVE_FLAGS A3, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0+T1 (eax, r11/edi)
EPILOGUE_4_ARGS
%else
;
; Must use cmpxchg8b here. See also iemAImpl_cmpxchg8b.
;
push esi
push edi
push ebx
push ebp
mov edi, ecx ; pu64Dst
mov esi, edx ; pu64Rax
mov ecx, [esp + 16 + 4 + 0] ; pu64Reg - Note! Pointer on 32-bit hosts!
mov ebp, [esp + 16 + 4 + 4] ; pEFlags
mov ebx, [ecx]
mov ecx, [ecx + 4]
IEM_MAYBE_LOAD_FLAGS ebp, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0 (eax)
mov eax, [esi]
mov edx, [esi + 4]
lock cmpxchg8b [edi]
; cmpxchg8b doesn't set CF, PF, AF, SF and OF, so we have to do that.
jz .cmpxchg8b_not_equal
cmp eax, eax ; just set the other flags.
.store:
mov [esi], eax
mov [esi + 4], edx
IEM_SAVE_FLAGS ebp, (X86_EFL_ZF | X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF), 0 ; clobbers T0+T1 (eax, edi)
pop ebp
pop ebx
pop edi
pop esi
ret 8
.cmpxchg8b_not_equal:
cmp [esi + 4], edx ;; @todo FIXME - verify 64-bit compare implementation
jne .store
cmp [esi], eax
jmp .store
%endif
ENDPROC iemAImpl_cmpxchg_u64 %+ %2
%endmacro ; IEMIMPL_CMPXCHG
IEMIMPL_CMPXCHG , ,
IEMIMPL_CMPXCHG lock, _locked
;;
; Macro for implementing a unary operator.
;
; This will generate code for the 8, 16, 32 and 64 bit accesses with locked
; variants, except on 32-bit system where the 64-bit accesses requires hand
; coding.
;
; All the functions takes a pointer to the destination memory operand in A0,
; the source register operand in A1 and a pointer to eflags in A2.
;
; @param 1 The instruction mnemonic.
; @param 2 The modified flags.
; @param 3 The undefined flags.
;
%macro IEMIMPL_UNARY_OP 3
BEGINCODE
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 8
PROLOGUE_2_ARGS
IEM_MAYBE_LOAD_FLAGS A1, %2, %3
%1 byte [A0]
IEM_SAVE_FLAGS A1, %2, %3
EPILOGUE_2_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u8
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8_locked, 8
PROLOGUE_2_ARGS
IEM_MAYBE_LOAD_FLAGS A1, %2, %3
lock %1 byte [A0]
IEM_SAVE_FLAGS A1, %2, %3
EPILOGUE_2_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u8_locked
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 8
PROLOGUE_2_ARGS
IEM_MAYBE_LOAD_FLAGS A1, %2, %3
%1 word [A0]
IEM_SAVE_FLAGS A1, %2, %3
EPILOGUE_2_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u16
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16_locked, 8
PROLOGUE_2_ARGS
IEM_MAYBE_LOAD_FLAGS A1, %2, %3
lock %1 word [A0]
IEM_SAVE_FLAGS A1, %2, %3
EPILOGUE_2_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u16_locked
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 8
PROLOGUE_2_ARGS
IEM_MAYBE_LOAD_FLAGS A1, %2, %3
%1 dword [A0]
IEM_SAVE_FLAGS A1, %2, %3
EPILOGUE_2_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u32
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32_locked, 8
PROLOGUE_2_ARGS
IEM_MAYBE_LOAD_FLAGS A1, %2, %3
lock %1 dword [A0]
IEM_SAVE_FLAGS A1, %2, %3
EPILOGUE_2_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u32_locked
%ifdef RT_ARCH_AMD64
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 8
PROLOGUE_2_ARGS
IEM_MAYBE_LOAD_FLAGS A1, %2, %3
%1 qword [A0]
IEM_SAVE_FLAGS A1, %2, %3
EPILOGUE_2_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u64
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 8
PROLOGUE_2_ARGS
IEM_MAYBE_LOAD_FLAGS A1, %2, %3
lock %1 qword [A0]
IEM_SAVE_FLAGS A1, %2, %3
EPILOGUE_2_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
%else
; stub them for now.
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 8
int3
ret 0
ENDPROC iemAImpl_ %+ %1 %+ _u64
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 8
int3
ret 0
ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
%endif
%endmacro
IEMIMPL_UNARY_OP inc, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF), 0
IEMIMPL_UNARY_OP dec, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF), 0
IEMIMPL_UNARY_OP neg, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
IEMIMPL_UNARY_OP not, 0, 0
;;
; Macro for implementing memory fence operation.
;
; No return value, no operands or anything.
;
; @param 1 The instruction.
;
%macro IEMIMPL_MEM_FENCE 1
BEGINCODE
BEGINPROC_FASTCALL iemAImpl_ %+ %1, 0
%1
ret
ENDPROC iemAImpl_ %+ %1
%endmacro
IEMIMPL_MEM_FENCE lfence
IEMIMPL_MEM_FENCE sfence
IEMIMPL_MEM_FENCE mfence
;;
; Alternative for non-SSE2 host.
;
BEGINPROC_FASTCALL iemAImpl_alt_mem_fence, 0
push xAX
xchg xAX, [xSP]
add xSP, xCB
ret
ENDPROC iemAImpl_alt_mem_fence
;;
; Macro for implementing a shift operation.
;
; This will generate code for the 8, 16, 32 and 64 bit accesses, except on
; 32-bit system where the 64-bit accesses requires hand coding.
;
; All the functions takes a pointer to the destination memory operand in A0,
; the shift count in A1 and a pointer to eflags in A2.
;
; @param 1 The instruction mnemonic.
; @param 2 The modified flags.
; @param 3 The undefined flags.
;
; Makes ASSUMPTIONS about A0, A1 and A2 assignments.
;
%macro IEMIMPL_SHIFT_OP 3
BEGINCODE
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %2, %3
%ifdef ASM_CALL64_GCC
mov cl, A1_8
%1 byte [A0], cl
%else
xchg A1, A0
%1 byte [A1], cl
%endif
IEM_SAVE_FLAGS A2, %2, %3
EPILOGUE_3_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u8
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %2, %3
%ifdef ASM_CALL64_GCC
mov cl, A1_8
%1 word [A0], cl
%else
xchg A1, A0
%1 word [A1], cl
%endif
IEM_SAVE_FLAGS A2, %2, %3
EPILOGUE_3_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u16
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %2, %3
%ifdef ASM_CALL64_GCC
mov cl, A1_8
%1 dword [A0], cl
%else
xchg A1, A0
%1 dword [A1], cl
%endif
IEM_SAVE_FLAGS A2, %2, %3
EPILOGUE_3_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u32
%ifdef RT_ARCH_AMD64
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %2, %3
%ifdef ASM_CALL64_GCC
mov cl, A1_8
%1 qword [A0], cl
%else
xchg A1, A0
%1 qword [A1], cl
%endif
IEM_SAVE_FLAGS A2, %2, %3
EPILOGUE_3_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u64
%else ; stub it for now - later, replace with hand coded stuff.
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 12
int3
ret 4
ENDPROC iemAImpl_ %+ %1 %+ _u64
%endif ; !RT_ARCH_AMD64
%endmacro
IEMIMPL_SHIFT_OP rol, (X86_EFL_OF | X86_EFL_CF), 0
IEMIMPL_SHIFT_OP ror, (X86_EFL_OF | X86_EFL_CF), 0
IEMIMPL_SHIFT_OP rcl, (X86_EFL_OF | X86_EFL_CF), 0
IEMIMPL_SHIFT_OP rcr, (X86_EFL_OF | X86_EFL_CF), 0
IEMIMPL_SHIFT_OP shl, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
IEMIMPL_SHIFT_OP shr, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
IEMIMPL_SHIFT_OP sar, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
;;
; Macro for implementing a double precision shift operation.
;
; This will generate code for the 16, 32 and 64 bit accesses, except on
; 32-bit system where the 64-bit accesses requires hand coding.
;
; The functions takes the destination operand (r/m) in A0, the source (reg) in
; A1, the shift count in A2 and a pointer to the eflags variable/register in A3.
;
; @param 1 The instruction mnemonic.
; @param 2 The modified flags.
; @param 3 The undefined flags.
;
; Makes ASSUMPTIONS about A0, A1, A2 and A3 assignments.
;
%macro IEMIMPL_SHIFT_DBL_OP 3
BEGINCODE
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 16
PROLOGUE_4_ARGS
IEM_MAYBE_LOAD_FLAGS A3, %2, %3
%ifdef ASM_CALL64_GCC
xchg A3, A2
%1 [A0], A1_16, cl
xchg A3, A2
%else
xchg A0, A2
%1 [A2], A1_16, cl
%endif
IEM_SAVE_FLAGS A3, %2, %3
EPILOGUE_4_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u16
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 16
PROLOGUE_4_ARGS
IEM_MAYBE_LOAD_FLAGS A3, %2, %3
%ifdef ASM_CALL64_GCC
xchg A3, A2
%1 [A0], A1_32, cl
xchg A3, A2
%else
xchg A0, A2
%1 [A2], A1_32, cl
%endif
IEM_SAVE_FLAGS A3, %2, %3
EPILOGUE_4_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u32
%ifdef RT_ARCH_AMD64
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
PROLOGUE_4_ARGS
IEM_MAYBE_LOAD_FLAGS A3, %2, %3
%ifdef ASM_CALL64_GCC
xchg A3, A2
%1 [A0], A1, cl
xchg A3, A2
%else
xchg A0, A2
%1 [A2], A1, cl
%endif
IEM_SAVE_FLAGS A3, %2, %3
EPILOGUE_4_ARGS_EX 12
ENDPROC iemAImpl_ %+ %1 %+ _u64
%else ; stub it for now - later, replace with hand coded stuff.
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
int3
ret 12
ENDPROC iemAImpl_ %+ %1 %+ _u64
%endif ; !RT_ARCH_AMD64
%endmacro
IEMIMPL_SHIFT_DBL_OP shld, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
IEMIMPL_SHIFT_DBL_OP shrd, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), (X86_EFL_AF)
;;
; Macro for implementing a multiplication operations.
;
; This will generate code for the 8, 16, 32 and 64 bit accesses, except on
; 32-bit system where the 64-bit accesses requires hand coding.
;
; The 8-bit function only operates on AX, so it takes no DX pointer. The other
; functions takes a pointer to rAX in A0, rDX in A1, the operand in A2 and a
; pointer to eflags in A3.
;
; The functions all return 0 so the caller can be used for div/idiv as well as
; for the mul/imul implementation.
;
; @param 1 The instruction mnemonic.
; @param 2 The modified flags.
; @param 3 The undefined flags.
;
; Makes ASSUMPTIONS about A0, A1, A2, A3, T0 and T1 assignments.
;
%macro IEMIMPL_MUL_OP 3
BEGINCODE
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %2, %3
mov al, [A0]
%1 A1_8
mov [A0], ax
IEM_SAVE_FLAGS A2, %2, %3
xor eax, eax
EPILOGUE_3_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u8
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 16
PROLOGUE_4_ARGS
IEM_MAYBE_LOAD_FLAGS A3, %2, %3
mov ax, [A0]
%ifdef ASM_CALL64_GCC
%1 A2_16
mov [A0], ax
mov [A1], dx
%else
mov T1, A1
%1 A2_16
mov [A0], ax
mov [T1], dx
%endif
IEM_SAVE_FLAGS A3, %2, %3
xor eax, eax
EPILOGUE_4_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u16
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 16
PROLOGUE_4_ARGS
IEM_MAYBE_LOAD_FLAGS A3, %2, %3
mov eax, [A0]
%ifdef ASM_CALL64_GCC
%1 A2_32
mov [A0], eax
mov [A1], edx
%else
mov T1, A1
%1 A2_32
mov [A0], eax
mov [T1], edx
%endif
IEM_SAVE_FLAGS A3, %2, %3
xor eax, eax
EPILOGUE_4_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u32
%ifdef RT_ARCH_AMD64 ; The 32-bit host version lives in IEMAllAImplC.cpp.
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
PROLOGUE_4_ARGS
IEM_MAYBE_LOAD_FLAGS A3, %2, %3
mov rax, [A0]
%ifdef ASM_CALL64_GCC
%1 A2
mov [A0], rax
mov [A1], rdx
%else
mov T1, A1
%1 A2
mov [A0], rax
mov [T1], rdx
%endif
IEM_SAVE_FLAGS A3, %2, %3
xor eax, eax
EPILOGUE_4_ARGS_EX 12
ENDPROC iemAImpl_ %+ %1 %+ _u64
%endif ; !RT_ARCH_AMD64
%endmacro
IEMIMPL_MUL_OP mul, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
IEMIMPL_MUL_OP imul, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
BEGINCODE
;;
; Worker function for negating a 32-bit number in T1:T0
; @uses None (T0,T1)
iemAImpl_negate_T0_T1_u32:
push 0
push 0
xchg T0_32, [xSP]
xchg T1_32, [xSP + xCB]
sub T0_32, [xSP]
sbb T1_32, [xSP + xCB]
add xSP, xCB*2
ret
%ifdef RT_ARCH_AMD64
;;
; Worker function for negating a 64-bit number in T1:T0
; @uses None (T0,T1)
iemAImpl_negate_T0_T1_u64:
push 0
push 0
xchg T0, [xSP]
xchg T1, [xSP + xCB]
sub T0, [xSP]
sbb T1, [xSP + xCB]
add xSP, xCB*2
ret
%endif
;;
; Macro for implementing a division operations.
;
; This will generate code for the 8, 16, 32 and 64 bit accesses, except on
; 32-bit system where the 64-bit accesses requires hand coding.
;
; The 8-bit function only operates on AX, so it takes no DX pointer. The other
; functions takes a pointer to rAX in A0, rDX in A1, the operand in A2 and a
; pointer to eflags in A3.
;
; The functions all return 0 on success and -1 if a divide error should be
; raised by the caller.
;
; @param 1 The instruction mnemonic.
; @param 2 The modified flags.
; @param 3 The undefined flags.
; @param 4 1 if signed, 0 if unsigned.
;
; Makes ASSUMPTIONS about A0, A1, A2, A3, T0 and T1 assignments.
;
%macro IEMIMPL_DIV_OP 4
BEGINCODE
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 12
PROLOGUE_3_ARGS
; div by chainsaw check.
test A1_8, A1_8
jz .div_zero
; Overflow check - unsigned division is simple to verify, haven't
; found a simple way to check signed division yet unfortunately.
%if %4 == 0
cmp [A0 + 1], A1_8
jae .div_overflow
%else
mov T0_16, [A0] ; T0 = dividend
mov T1, A1 ; T1 = saved divisor (because of missing T1_8 in 32-bit)
test A1_8, A1_8
js .divisor_negative
test T0_16, T0_16
jns .both_positive
neg T0_16
.one_of_each: ; OK range is 2^(result-with - 1) + (divisor - 1).
push T0 ; Start off like unsigned below.
shr T0_16, 7
cmp T0_8, A1_8
pop T0
jb .div_no_overflow
ja .div_overflow
and T0_8, 0x7f ; Special case for covering (divisor - 1).
cmp T0_8, A1_8
jae .div_overflow
jmp .div_no_overflow
.divisor_negative:
neg A1_8
test T0_16, T0_16
jns .one_of_each
neg T0_16
.both_positive: ; Same as unsigned shifted by sign indicator bit.
shr T0_16, 7
cmp T0_8, A1_8
jae .div_overflow
.div_no_overflow:
mov A1, T1 ; restore divisor
%endif
IEM_MAYBE_LOAD_FLAGS A2, %2, %3
mov ax, [A0]
%1 A1_8
mov [A0], ax
IEM_SAVE_FLAGS A2, %2, %3
xor eax, eax
.return:
EPILOGUE_3_ARGS
.div_zero:
.div_overflow:
mov eax, -1
jmp .return
ENDPROC iemAImpl_ %+ %1 %+ _u8
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 16
PROLOGUE_4_ARGS
; div by chainsaw check.
test A2_16, A2_16
jz .div_zero
; Overflow check - unsigned division is simple to verify, haven't
; found a simple way to check signed division yet unfortunately.
%if %4 == 0
cmp [A1], A2_16
jae .div_overflow
%else
mov T0_16, [A1]
shl T0_32, 16
mov T0_16, [A0] ; T0 = dividend
mov T1, A2 ; T1 = divisor
test T1_16, T1_16
js .divisor_negative
test T0_32, T0_32
jns .both_positive
neg T0_32
.one_of_each: ; OK range is 2^(result-with - 1) + (divisor - 1).
push T0 ; Start off like unsigned below.
shr T0_32, 15
cmp T0_16, T1_16
pop T0
jb .div_no_overflow
ja .div_overflow
and T0_16, 0x7fff ; Special case for covering (divisor - 1).
cmp T0_16, T1_16
jae .div_overflow
jmp .div_no_overflow
.divisor_negative:
neg T1_16
test T0_32, T0_32
jns .one_of_each
neg T0_32
.both_positive: ; Same as unsigned shifted by sign indicator bit.
shr T0_32, 15
cmp T0_16, T1_16
jae .div_overflow
.div_no_overflow:
%endif
IEM_MAYBE_LOAD_FLAGS A3, %2, %3
%ifdef ASM_CALL64_GCC
mov T1, A2
mov ax, [A0]
mov dx, [A1]
%1 T1_16
mov [A0], ax
mov [A1], dx
%else
mov T1, A1
mov ax, [A0]
mov dx, [T1]
%1 A2_16
mov [A0], ax
mov [T1], dx
%endif
IEM_SAVE_FLAGS A3, %2, %3
xor eax, eax
.return:
EPILOGUE_4_ARGS
.div_zero:
.div_overflow:
mov eax, -1
jmp .return
ENDPROC iemAImpl_ %+ %1 %+ _u16
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 16
PROLOGUE_4_ARGS
; div by chainsaw check.
test A2_32, A2_32
jz .div_zero
; Overflow check - unsigned division is simple to verify, haven't
; found a simple way to check signed division yet unfortunately.
%if %4 == 0
cmp [A1], A2_32
jae .div_overflow
%else
push A2 ; save A2 so we modify it (we out of regs on x86).
mov T0_32, [A0] ; T0 = dividend low
mov T1_32, [A1] ; T1 = dividend high
test A2_32, A2_32
js .divisor_negative
test T1_32, T1_32
jns .both_positive
call iemAImpl_negate_T0_T1_u32
.one_of_each: ; OK range is 2^(result-with - 1) + (divisor - 1).
push T0 ; Start off like unsigned below.
shl T1_32, 1
shr T0_32, 31
or T1_32, T0_32
cmp T1_32, A2_32
pop T0
jb .div_no_overflow
ja .div_overflow
and T0_32, 0x7fffffff ; Special case for covering (divisor - 1).
cmp T0_32, A2_32
jae .div_overflow
jmp .div_no_overflow
.divisor_negative:
neg A2_32
test T1_32, T1_32
jns .one_of_each
call iemAImpl_negate_T0_T1_u32
.both_positive: ; Same as unsigned shifted by sign indicator bit.
shl T1_32, 1
shr T0_32, 31
or T1_32, T0_32
cmp T1_32, A2_32
jae .div_overflow
.div_no_overflow:
pop A2
%endif
IEM_MAYBE_LOAD_FLAGS A3, %2, %3
mov eax, [A0]
%ifdef ASM_CALL64_GCC
mov T1, A2
mov eax, [A0]
mov edx, [A1]
%1 T1_32
mov [A0], eax
mov [A1], edx
%else
mov T1, A1
mov eax, [A0]
mov edx, [T1]
%1 A2_32
mov [A0], eax
mov [T1], edx
%endif
IEM_SAVE_FLAGS A3, %2, %3
xor eax, eax
.return:
EPILOGUE_4_ARGS
.div_overflow:
%if %4 != 0
pop A2
%endif
.div_zero:
mov eax, -1
jmp .return
ENDPROC iemAImpl_ %+ %1 %+ _u32
%ifdef RT_ARCH_AMD64 ; The 32-bit host version lives in IEMAllAImplC.cpp.
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
PROLOGUE_4_ARGS
test A2, A2
jz .div_zero
%if %4 == 0
cmp [A1], A2
jae .div_overflow
%else
push A2 ; save A2 so we modify it (we out of regs on x86).
mov T0, [A0] ; T0 = dividend low
mov T1, [A1] ; T1 = dividend high
test A2, A2
js .divisor_negative
test T1, T1
jns .both_positive
call iemAImpl_negate_T0_T1_u64
.one_of_each: ; OK range is 2^(result-with - 1) + (divisor - 1).
push T0 ; Start off like unsigned below.
shl T1, 1
shr T0, 63
or T1, T0
cmp T1, A2
pop T0
jb .div_no_overflow
ja .div_overflow
mov T1, 0x7fffffffffffffff
and T0, T1 ; Special case for covering (divisor - 1).
cmp T0, A2
jae .div_overflow
jmp .div_no_overflow
.divisor_negative:
neg A2
test T1, T1
jns .one_of_each
call iemAImpl_negate_T0_T1_u64
.both_positive: ; Same as unsigned shifted by sign indicator bit.
shl T1, 1
shr T0, 63
or T1, T0
cmp T1, A2
jae .div_overflow
.div_no_overflow:
pop A2
%endif
IEM_MAYBE_LOAD_FLAGS A3, %2, %3
mov rax, [A0]
%ifdef ASM_CALL64_GCC
mov T1, A2
mov rax, [A0]
mov rdx, [A1]
%1 T1
mov [A0], rax
mov [A1], rdx
%else
mov T1, A1
mov rax, [A0]
mov rdx, [T1]
%1 A2
mov [A0], rax
mov [T1], rdx
%endif
IEM_SAVE_FLAGS A3, %2, %3
xor eax, eax
.return:
EPILOGUE_4_ARGS_EX 12
.div_overflow:
%if %4 != 0
pop A2
%endif
.div_zero:
mov eax, -1
jmp .return
ENDPROC iemAImpl_ %+ %1 %+ _u64
%endif ; !RT_ARCH_AMD64
%endmacro
IEMIMPL_DIV_OP div, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
IEMIMPL_DIV_OP idiv, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 1
;
; BSWAP. No flag changes.
;
; Each function takes one argument, pointer to the value to bswap
; (input/output). They all return void.
;
BEGINPROC_FASTCALL iemAImpl_bswap_u16, 4
PROLOGUE_1_ARGS
mov T0_32, [A0] ; just in case any of the upper bits are used.
db 66h
bswap T0_32
mov [A0], T0_32
EPILOGUE_1_ARGS
ENDPROC iemAImpl_bswap_u16
BEGINPROC_FASTCALL iemAImpl_bswap_u32, 4
PROLOGUE_1_ARGS
mov T0_32, [A0]
bswap T0_32
mov [A0], T0_32
EPILOGUE_1_ARGS
ENDPROC iemAImpl_bswap_u32
BEGINPROC_FASTCALL iemAImpl_bswap_u64, 4
%ifdef RT_ARCH_AMD64
PROLOGUE_1_ARGS
mov T0, [A0]
bswap T0
mov [A0], T0
EPILOGUE_1_ARGS
%else
PROLOGUE_1_ARGS
mov T0, [A0]
mov T1, [A0 + 4]
bswap T0
bswap T1
mov [A0 + 4], T0
mov [A0], T1
EPILOGUE_1_ARGS
%endif
ENDPROC iemAImpl_bswap_u64
;;
; Initialize the FPU for the actual instruction being emulated, this means
; loading parts of the guest's control word and status word.
;
; @uses 24 bytes of stack.
; @param 1 Expression giving the address of the FXSTATE of the guest.
;
%macro FPU_LD_FXSTATE_FCW_AND_SAFE_FSW 1
fnstenv [xSP]
; FCW - for exception, precision and rounding control.
movzx T0, word [%1 + X86FXSTATE.FCW]
and T0, X86_FCW_MASK_ALL | X86_FCW_PC_MASK | X86_FCW_RC_MASK
mov [xSP + X86FSTENV32P.FCW], T0_16
; FSW - for undefined C0, C1, C2, and C3.
movzx T1, word [%1 + X86FXSTATE.FSW]
and T1, X86_FSW_C_MASK
movzx T0, word [xSP + X86FSTENV32P.FSW]
and T0, X86_FSW_TOP_MASK
or T0, T1
mov [xSP + X86FSTENV32P.FSW], T0_16
fldenv [xSP]
%endmacro
;;
; Need to move this as well somewhere better?
;
struc IEMFPURESULT
.r80Result resw 5
.FSW resw 1
endstruc
;;
; Need to move this as well somewhere better?
;
struc IEMFPURESULTTWO
.r80Result1 resw 5
.FSW resw 1
.r80Result2 resw 5
endstruc
;
;---------------------- 16-bit signed integer operations ----------------------
;
;;
; Converts a 16-bit floating point value to a 80-bit one (fpu register).
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a IEMFPURESULT for the output.
; @param A2 Pointer to the 16-bit floating point value to convert.
;
BEGINPROC_FASTCALL iemAImpl_fild_i16_to_r80, 12
PROLOGUE_3_ARGS
sub xSP, 20h
fninit
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
fild word [A2]
fnstsw word [A1 + IEMFPURESULT.FSW]
fnclex
fstp tword [A1 + IEMFPURESULT.r80Result]
fninit
add xSP, 20h
EPILOGUE_3_ARGS
ENDPROC iemAImpl_fild_i16_to_r80
;;
; Store a 80-bit floating point value (register) as a 16-bit signed integer (memory).
;
; @param A0 FPU context (fxsave).
; @param A1 Where to return the output FSW.
; @param A2 Where to store the 16-bit signed integer value.
; @param A3 Pointer to the 80-bit value.
;
BEGINPROC_FASTCALL iemAImpl_fist_r80_to_i16, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A3]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
fistp word [A2]
fnstsw word [A1]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_fist_r80_to_i16
;;
; Store a 80-bit floating point value (register) as a 16-bit signed integer
; (memory) with truncation.
;
; @param A0 FPU context (fxsave).
; @param A1 Where to return the output FSW.
; @param A2 Where to store the 16-bit signed integer value.
; @param A3 Pointer to the 80-bit value.
;
BEGINPROC_FASTCALL iemAImpl_fistt_r80_to_i16, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A3]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
fisttp dword [A2]
fnstsw word [A1]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_fistt_r80_to_i16
;;
; FPU instruction working on one 80-bit and one 16-bit signed integer value.
;
; @param 1 The instruction
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a IEMFPURESULT for the output.
; @param A2 Pointer to the 80-bit value.
; @param A3 Pointer to the 16-bit value.
;
%macro IEMIMPL_FPU_R80_BY_I16 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_i16, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A2]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
%1 word [A3]
fnstsw word [A1 + IEMFPURESULT.FSW]
fnclex
fstp tword [A1 + IEMFPURESULT.r80Result]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _r80_by_i16
%endmacro
IEMIMPL_FPU_R80_BY_I16 fiadd
IEMIMPL_FPU_R80_BY_I16 fimul
IEMIMPL_FPU_R80_BY_I16 fisub
IEMIMPL_FPU_R80_BY_I16 fisubr
IEMIMPL_FPU_R80_BY_I16 fidiv
IEMIMPL_FPU_R80_BY_I16 fidivr
;;
; FPU instruction working on one 80-bit and one 16-bit signed integer value,
; only returning FSW.
;
; @param 1 The instruction
;
; @param A0 FPU context (fxsave).
; @param A1 Where to store the output FSW.
; @param A2 Pointer to the 80-bit value.
; @param A3 Pointer to the 64-bit value.
;
%macro IEMIMPL_FPU_R80_BY_I16_FSW 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_i16, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A2]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
%1 word [A3]
fnstsw word [A1]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _r80_by_i16
%endmacro
IEMIMPL_FPU_R80_BY_I16_FSW ficom
;
;---------------------- 32-bit signed integer operations ----------------------
;
;;
; Converts a 32-bit floating point value to a 80-bit one (fpu register).
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a IEMFPURESULT for the output.
; @param A2 Pointer to the 32-bit floating point value to convert.
;
BEGINPROC_FASTCALL iemAImpl_fild_i32_to_r80, 12
PROLOGUE_3_ARGS
sub xSP, 20h
fninit
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
fild dword [A2]
fnstsw word [A1 + IEMFPURESULT.FSW]
fnclex
fstp tword [A1 + IEMFPURESULT.r80Result]
fninit
add xSP, 20h
EPILOGUE_3_ARGS
ENDPROC iemAImpl_fild_i32_to_r80
;;
; Store a 80-bit floating point value (register) as a 32-bit signed integer (memory).
;
; @param A0 FPU context (fxsave).
; @param A1 Where to return the output FSW.
; @param A2 Where to store the 32-bit signed integer value.
; @param A3 Pointer to the 80-bit value.
;
BEGINPROC_FASTCALL iemAImpl_fist_r80_to_i32, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A3]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
fistp dword [A2]
fnstsw word [A1]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_fist_r80_to_i32
;;
; Store a 80-bit floating point value (register) as a 32-bit signed integer
; (memory) with truncation.
;
; @param A0 FPU context (fxsave).
; @param A1 Where to return the output FSW.
; @param A2 Where to store the 32-bit signed integer value.
; @param A3 Pointer to the 80-bit value.
;
BEGINPROC_FASTCALL iemAImpl_fistt_r80_to_i32, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A3]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
fisttp dword [A2]
fnstsw word [A1]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_fistt_r80_to_i32
;;
; FPU instruction working on one 80-bit and one 32-bit signed integer value.
;
; @param 1 The instruction
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a IEMFPURESULT for the output.
; @param A2 Pointer to the 80-bit value.
; @param A3 Pointer to the 32-bit value.
;
%macro IEMIMPL_FPU_R80_BY_I32 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_i32, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A2]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
%1 dword [A3]
fnstsw word [A1 + IEMFPURESULT.FSW]
fnclex
fstp tword [A1 + IEMFPURESULT.r80Result]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _r80_by_i32
%endmacro
IEMIMPL_FPU_R80_BY_I32 fiadd
IEMIMPL_FPU_R80_BY_I32 fimul
IEMIMPL_FPU_R80_BY_I32 fisub
IEMIMPL_FPU_R80_BY_I32 fisubr
IEMIMPL_FPU_R80_BY_I32 fidiv
IEMIMPL_FPU_R80_BY_I32 fidivr
;;
; FPU instruction working on one 80-bit and one 32-bit signed integer value,
; only returning FSW.
;
; @param 1 The instruction
;
; @param A0 FPU context (fxsave).
; @param A1 Where to store the output FSW.
; @param A2 Pointer to the 80-bit value.
; @param A3 Pointer to the 64-bit value.
;
%macro IEMIMPL_FPU_R80_BY_I32_FSW 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_i32, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A2]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
%1 dword [A3]
fnstsw word [A1]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _r80_by_i32
%endmacro
IEMIMPL_FPU_R80_BY_I32_FSW ficom
;
;---------------------- 64-bit signed integer operations ----------------------
;
;;
; Converts a 64-bit floating point value to a 80-bit one (fpu register).
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a IEMFPURESULT for the output.
; @param A2 Pointer to the 64-bit floating point value to convert.
;
BEGINPROC_FASTCALL iemAImpl_fild_i64_to_r80, 12
PROLOGUE_3_ARGS
sub xSP, 20h
fninit
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
fild qword [A2]
fnstsw word [A1 + IEMFPURESULT.FSW]
fnclex
fstp tword [A1 + IEMFPURESULT.r80Result]
fninit
add xSP, 20h
EPILOGUE_3_ARGS
ENDPROC iemAImpl_fild_i64_to_r80
;;
; Store a 80-bit floating point value (register) as a 64-bit signed integer (memory).
;
; @param A0 FPU context (fxsave).
; @param A1 Where to return the output FSW.
; @param A2 Where to store the 64-bit signed integer value.
; @param A3 Pointer to the 80-bit value.
;
BEGINPROC_FASTCALL iemAImpl_fist_r80_to_i64, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A3]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
fistp qword [A2]
fnstsw word [A1]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_fist_r80_to_i64
;;
; Store a 80-bit floating point value (register) as a 64-bit signed integer
; (memory) with truncation.
;
; @param A0 FPU context (fxsave).
; @param A1 Where to return the output FSW.
; @param A2 Where to store the 64-bit signed integer value.
; @param A3 Pointer to the 80-bit value.
;
BEGINPROC_FASTCALL iemAImpl_fistt_r80_to_i64, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A3]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
fisttp qword [A2]
fnstsw word [A1]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_fistt_r80_to_i64
;
;---------------------- 32-bit floating point operations ----------------------
;
;;
; Converts a 32-bit floating point value to a 80-bit one (fpu register).
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a IEMFPURESULT for the output.
; @param A2 Pointer to the 32-bit floating point value to convert.
;
BEGINPROC_FASTCALL iemAImpl_fld_r32_to_r80, 12
PROLOGUE_3_ARGS
sub xSP, 20h
fninit
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
fld dword [A2]
fnstsw word [A1 + IEMFPURESULT.FSW]
fnclex
fstp tword [A1 + IEMFPURESULT.r80Result]
fninit
add xSP, 20h
EPILOGUE_3_ARGS
ENDPROC iemAImpl_fld_r32_to_r80
;;
; Store a 80-bit floating point value (register) as a 32-bit one (memory).
;
; @param A0 FPU context (fxsave).
; @param A1 Where to return the output FSW.
; @param A2 Where to store the 32-bit value.
; @param A3 Pointer to the 80-bit value.
;
BEGINPROC_FASTCALL iemAImpl_fst_r80_to_r32, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A3]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
fst dword [A2]
fnstsw word [A1]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_fst_r80_to_r32
;;
; FPU instruction working on one 80-bit and one 32-bit floating point value.
;
; @param 1 The instruction
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a IEMFPURESULT for the output.
; @param A2 Pointer to the 80-bit value.
; @param A3 Pointer to the 32-bit value.
;
%macro IEMIMPL_FPU_R80_BY_R32 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r32, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A2]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
%1 dword [A3]
fnstsw word [A1 + IEMFPURESULT.FSW]
fnclex
fstp tword [A1 + IEMFPURESULT.r80Result]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r32
%endmacro
IEMIMPL_FPU_R80_BY_R32 fadd
IEMIMPL_FPU_R80_BY_R32 fmul
IEMIMPL_FPU_R80_BY_R32 fsub
IEMIMPL_FPU_R80_BY_R32 fsubr
IEMIMPL_FPU_R80_BY_R32 fdiv
IEMIMPL_FPU_R80_BY_R32 fdivr
;;
; FPU instruction working on one 80-bit and one 32-bit floating point value,
; only returning FSW.
;
; @param 1 The instruction
;
; @param A0 FPU context (fxsave).
; @param A1 Where to store the output FSW.
; @param A2 Pointer to the 80-bit value.
; @param A3 Pointer to the 64-bit value.
;
%macro IEMIMPL_FPU_R80_BY_R32_FSW 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r32, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A2]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
%1 dword [A3]
fnstsw word [A1]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r32
%endmacro
IEMIMPL_FPU_R80_BY_R32_FSW fcom
;
;---------------------- 64-bit floating point operations ----------------------
;
;;
; Converts a 64-bit floating point value to a 80-bit one (fpu register).
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a IEMFPURESULT for the output.
; @param A2 Pointer to the 64-bit floating point value to convert.
;
BEGINPROC_FASTCALL iemAImpl_fld_r64_to_r80, 12
PROLOGUE_3_ARGS
sub xSP, 20h
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
fld qword [A2]
fnstsw word [A1 + IEMFPURESULT.FSW]
fnclex
fstp tword [A1 + IEMFPURESULT.r80Result]
fninit
add xSP, 20h
EPILOGUE_3_ARGS
ENDPROC iemAImpl_fld_r64_to_r80
;;
; Store a 80-bit floating point value (register) as a 64-bit one (memory).
;
; @param A0 FPU context (fxsave).
; @param A1 Where to return the output FSW.
; @param A2 Where to store the 64-bit value.
; @param A3 Pointer to the 80-bit value.
;
BEGINPROC_FASTCALL iemAImpl_fst_r80_to_r64, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A3]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
fst qword [A2]
fnstsw word [A1]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_fst_r80_to_r64
;;
; FPU instruction working on one 80-bit and one 64-bit floating point value.
;
; @param 1 The instruction
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a IEMFPURESULT for the output.
; @param A2 Pointer to the 80-bit value.
; @param A3 Pointer to the 64-bit value.
;
%macro IEMIMPL_FPU_R80_BY_R64 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r64, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A2]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
%1 qword [A3]
fnstsw word [A1 + IEMFPURESULT.FSW]
fnclex
fstp tword [A1 + IEMFPURESULT.r80Result]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r64
%endmacro
IEMIMPL_FPU_R80_BY_R64 fadd
IEMIMPL_FPU_R80_BY_R64 fmul
IEMIMPL_FPU_R80_BY_R64 fsub
IEMIMPL_FPU_R80_BY_R64 fsubr
IEMIMPL_FPU_R80_BY_R64 fdiv
IEMIMPL_FPU_R80_BY_R64 fdivr
;;
; FPU instruction working on one 80-bit and one 64-bit floating point value,
; only returning FSW.
;
; @param 1 The instruction
;
; @param A0 FPU context (fxsave).
; @param A1 Where to store the output FSW.
; @param A2 Pointer to the 80-bit value.
; @param A3 Pointer to the 64-bit value.
;
%macro IEMIMPL_FPU_R80_BY_R64_FSW 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r64, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A2]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
%1 qword [A3]
fnstsw word [A1]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r64
%endmacro
IEMIMPL_FPU_R80_BY_R64_FSW fcom
;
;---------------------- 80-bit floating point operations ----------------------
;
;;
; Loads a 80-bit floating point register value from memory.
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a IEMFPURESULT for the output.
; @param A2 Pointer to the 80-bit floating point value to load.
;
BEGINPROC_FASTCALL iemAImpl_fld_r80_from_r80, 12
PROLOGUE_3_ARGS
sub xSP, 20h
fninit
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
fld tword [A2]
fnstsw word [A1 + IEMFPURESULT.FSW]
fnclex
fstp tword [A1 + IEMFPURESULT.r80Result]
fninit
add xSP, 20h
EPILOGUE_3_ARGS
ENDPROC iemAImpl_fld_r80_from_r80
;;
; Store a 80-bit floating point register to memory
;
; @param A0 FPU context (fxsave).
; @param A1 Where to return the output FSW.
; @param A2 Where to store the 80-bit value.
; @param A3 Pointer to the 80-bit register value.
;
BEGINPROC_FASTCALL iemAImpl_fst_r80_to_r80, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A3]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
fstp tword [A2]
fnstsw word [A1]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_fst_r80_to_r80
;;
; FPU instruction working on two 80-bit floating point values.
;
; @param 1 The instruction
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a IEMFPURESULT for the output.
; @param A2 Pointer to the first 80-bit value (ST0)
; @param A3 Pointer to the second 80-bit value (STn).
;
%macro IEMIMPL_FPU_R80_BY_R80 2
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r80, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A3]
fld tword [A2]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
%1 %2
fnstsw word [A1 + IEMFPURESULT.FSW]
fnclex
fstp tword [A1 + IEMFPURESULT.r80Result]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r80
%endmacro
IEMIMPL_FPU_R80_BY_R80 fadd, {st0, st1}
IEMIMPL_FPU_R80_BY_R80 fmul, {st0, st1}
IEMIMPL_FPU_R80_BY_R80 fsub, {st0, st1}
IEMIMPL_FPU_R80_BY_R80 fsubr, {st0, st1}
IEMIMPL_FPU_R80_BY_R80 fdiv, {st0, st1}
IEMIMPL_FPU_R80_BY_R80 fdivr, {st0, st1}
IEMIMPL_FPU_R80_BY_R80 fprem, {}
IEMIMPL_FPU_R80_BY_R80 fprem1, {}
IEMIMPL_FPU_R80_BY_R80 fscale, {}
;;
; FPU instruction working on two 80-bit floating point values, ST1 and ST0,
; storing the result in ST1 and popping the stack.
;
; @param 1 The instruction
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a IEMFPURESULT for the output.
; @param A2 Pointer to the first 80-bit value (ST1).
; @param A3 Pointer to the second 80-bit value (ST0).
;
%macro IEMIMPL_FPU_R80_BY_R80_ST1_ST0_POP 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r80, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A2]
fld tword [A3]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
%1
fnstsw word [A1 + IEMFPURESULT.FSW]
fnclex
fstp tword [A1 + IEMFPURESULT.r80Result]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r80
%endmacro
IEMIMPL_FPU_R80_BY_R80_ST1_ST0_POP fpatan
IEMIMPL_FPU_R80_BY_R80_ST1_ST0_POP fyl2xp1
;;
; FPU instruction working on two 80-bit floating point values, only
; returning FSW.
;
; @param 1 The instruction
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a uint16_t for the resulting FSW.
; @param A2 Pointer to the first 80-bit value.
; @param A3 Pointer to the second 80-bit value.
;
%macro IEMIMPL_FPU_R80_BY_R80_FSW 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r80, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A3]
fld tword [A2]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
%1 st0, st1
fnstsw word [A1]
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r80
%endmacro
IEMIMPL_FPU_R80_BY_R80_FSW fcom
IEMIMPL_FPU_R80_BY_R80_FSW fucom
;;
; FPU instruction working on two 80-bit floating point values,
; returning FSW and EFLAGS (eax).
;
; @param 1 The instruction
;
; @returns EFLAGS in EAX.
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a uint16_t for the resulting FSW.
; @param A2 Pointer to the first 80-bit value.
; @param A3 Pointer to the second 80-bit value.
;
%macro IEMIMPL_FPU_R80_BY_R80_EFL 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r80, 16
PROLOGUE_4_ARGS
sub xSP, 20h
fninit
fld tword [A3]
fld tword [A2]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
%1 st1
fnstsw word [A1]
pushf
pop xAX
fninit
add xSP, 20h
EPILOGUE_4_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r80
%endmacro
IEMIMPL_FPU_R80_BY_R80_EFL fcomi
IEMIMPL_FPU_R80_BY_R80_EFL fucomi
;;
; FPU instruction working on one 80-bit floating point value.
;
; @param 1 The instruction
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a IEMFPURESULT for the output.
; @param A2 Pointer to the 80-bit value.
;
%macro IEMIMPL_FPU_R80 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80, 12
PROLOGUE_3_ARGS
sub xSP, 20h
fninit
fld tword [A2]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
%1
fnstsw word [A1 + IEMFPURESULT.FSW]
fnclex
fstp tword [A1 + IEMFPURESULT.r80Result]
fninit
add xSP, 20h
EPILOGUE_3_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _r80
%endmacro
IEMIMPL_FPU_R80 fchs
IEMIMPL_FPU_R80 fabs
IEMIMPL_FPU_R80 f2xm1
IEMIMPL_FPU_R80 fyl2x
IEMIMPL_FPU_R80 fsqrt
IEMIMPL_FPU_R80 frndint
IEMIMPL_FPU_R80 fsin
IEMIMPL_FPU_R80 fcos
;;
; FPU instruction working on one 80-bit floating point value, only
; returning FSW.
;
; @param 1 The instruction
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a uint16_t for the resulting FSW.
; @param A2 Pointer to the 80-bit value.
;
%macro IEMIMPL_FPU_R80_FSW 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80, 12
PROLOGUE_3_ARGS
sub xSP, 20h
fninit
fld tword [A2]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
%1
fnstsw word [A1]
fninit
add xSP, 20h
EPILOGUE_3_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _r80
%endmacro
IEMIMPL_FPU_R80_FSW ftst
IEMIMPL_FPU_R80_FSW fxam
;;
; FPU instruction loading a 80-bit floating point constant.
;
; @param 1 The instruction
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a IEMFPURESULT for the output.
;
%macro IEMIMPL_FPU_R80_CONST 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1, 8
PROLOGUE_2_ARGS
sub xSP, 20h
fninit
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
%1
fnstsw word [A1 + IEMFPURESULT.FSW]
fnclex
fstp tword [A1 + IEMFPURESULT.r80Result]
fninit
add xSP, 20h
EPILOGUE_2_ARGS
ENDPROC iemAImpl_ %+ %1 %+
%endmacro
IEMIMPL_FPU_R80_CONST fld1
IEMIMPL_FPU_R80_CONST fldl2t
IEMIMPL_FPU_R80_CONST fldl2e
IEMIMPL_FPU_R80_CONST fldpi
IEMIMPL_FPU_R80_CONST fldlg2
IEMIMPL_FPU_R80_CONST fldln2
IEMIMPL_FPU_R80_CONST fldz
;;
; FPU instruction working on one 80-bit floating point value, outputing two.
;
; @param 1 The instruction
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to a IEMFPURESULTTWO for the output.
; @param A2 Pointer to the 80-bit value.
;
%macro IEMIMPL_FPU_R80_R80 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_r80, 12
PROLOGUE_3_ARGS
sub xSP, 20h
fninit
fld tword [A2]
FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
%1
fnstsw word [A1 + IEMFPURESULTTWO.FSW]
fnclex
fstp tword [A1 + IEMFPURESULTTWO.r80Result2]
fnclex
fstp tword [A1 + IEMFPURESULTTWO.r80Result1]
fninit
add xSP, 20h
EPILOGUE_3_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _r80_r80
%endmacro
IEMIMPL_FPU_R80_R80 fptan
IEMIMPL_FPU_R80_R80 fxtract
IEMIMPL_FPU_R80_R80 fsincos
;---------------------- SSE and MMX Operations ----------------------
;; @todo what do we need to do for MMX?
%macro IEMIMPL_MMX_PROLOGUE 0
%endmacro
%macro IEMIMPL_MMX_EPILOGUE 0
%endmacro
;; @todo what do we need to do for SSE?
%macro IEMIMPL_SSE_PROLOGUE 0
%endmacro
%macro IEMIMPL_SSE_EPILOGUE 0
%endmacro
;;
; Media instruction working on two full sized registers.
;
; @param 1 The instruction
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to the first media register size operand (input/output).
; @param A2 Pointer to the second media register size operand (input).
;
%macro IEMIMPL_MEDIA_F2 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 12
PROLOGUE_3_ARGS
IEMIMPL_MMX_PROLOGUE
movq mm0, [A1]
movq mm1, [A2]
%1 mm0, mm1
movq [A1], mm0
IEMIMPL_MMX_EPILOGUE
EPILOGUE_3_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u64
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u128, 12
PROLOGUE_3_ARGS
IEMIMPL_SSE_PROLOGUE
movdqu xmm0, [A1]
movdqu xmm1, [A2]
%1 xmm0, xmm1
movdqu [A1], xmm0
IEMIMPL_SSE_EPILOGUE
EPILOGUE_3_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u128
%endmacro
IEMIMPL_MEDIA_F2 pxor
;;
; Media instruction working on one full sized and one half sized register (lower half).
;
; @param 1 The instruction
; @param 2 1 if MMX is included, 0 if not.
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to the first full sized media register operand (input/output).
; @param A2 Pointer to the second half sized media register operand (input).
;
%macro IEMIMPL_MEDIA_F1L1 2
%if %2 != 0
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 12
PROLOGUE_3_ARGS
IEMIMPL_MMX_PROLOGUE
movq mm0, [A1]
movd mm1, [A2]
%1 mm0, mm1
movq [A1], mm0
IEMIMPL_MMX_EPILOGUE
EPILOGUE_3_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u64
%endif
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u128, 12
PROLOGUE_3_ARGS
IEMIMPL_SSE_PROLOGUE
movdqu xmm0, [A1]
movq xmm1, [A2]
%1 xmm0, xmm1
movdqu [A1], xmm0
IEMIMPL_SSE_EPILOGUE
EPILOGUE_3_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u128
%endmacro
IEMIMPL_MEDIA_F1L1 punpcklbw, 1
IEMIMPL_MEDIA_F1L1 punpcklwd, 1
IEMIMPL_MEDIA_F1L1 punpckldq, 1
IEMIMPL_MEDIA_F1L1 punpcklqdq, 0
;;
; Media instruction working on one full sized and one half sized register (high half).
;
; @param 1 The instruction
; @param 2 1 if MMX is included, 0 if not.
;
; @param A0 FPU context (fxsave).
; @param A1 Pointer to the first full sized media register operand (input/output).
; @param A2 Pointer to the second full sized media register operand, where we
; will only use the upper half (input).
;
%macro IEMIMPL_MEDIA_F1H1 2
%if %2 != 0
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 12
PROLOGUE_3_ARGS
IEMIMPL_MMX_PROLOGUE
movq mm0, [A1]
movq mm1, [A2]
%1 mm0, mm1
movq [A1], mm0
IEMIMPL_MMX_EPILOGUE
EPILOGUE_3_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u64
%endif
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u128, 12
PROLOGUE_3_ARGS
IEMIMPL_SSE_PROLOGUE
movdqu xmm0, [A1]
movdqu xmm1, [A2]
%1 xmm0, xmm1
movdqu [A1], xmm0
IEMIMPL_SSE_EPILOGUE
EPILOGUE_3_ARGS
ENDPROC iemAImpl_ %+ %1 %+ _u128
%endmacro
IEMIMPL_MEDIA_F1L1 punpckhbw, 1
IEMIMPL_MEDIA_F1L1 punpckhwd, 1
IEMIMPL_MEDIA_F1L1 punpckhdq, 1
IEMIMPL_MEDIA_F1L1 punpckhqdq, 0
;
; Shufflers with evil 8-bit immediates.
;
BEGINPROC_FASTCALL iemAImpl_pshufw, 16
PROLOGUE_4_ARGS
IEMIMPL_MMX_PROLOGUE
movq mm0, [A1]
movq mm1, [A2]
lea T0, [A3 + A3*4] ; sizeof(pshufw+ret) == 5
lea T1, [.imm0 xWrtRIP]
lea T1, [T1 + T0]
call T1
movq [A1], mm0
IEMIMPL_MMX_EPILOGUE
EPILOGUE_4_ARGS
%assign bImm 0
%rep 256
.imm %+ bImm:
pshufw mm0, mm1, bImm
ret
%assign bImm bImm + 1
%endrep
.immEnd: ; 256*5 == 0x500
dw 0xfaff + (.immEnd - .imm0) ; will cause warning if entries are too big.
dw 0x104ff - (.immEnd - .imm0) ; will cause warning if entries are small big.
ENDPROC iemAImpl_pshufw
%macro IEMIMPL_MEDIA_SSE_PSHUFXX 1
BEGINPROC_FASTCALL iemAImpl_ %+ %1, 16
PROLOGUE_4_ARGS
IEMIMPL_SSE_PROLOGUE
movdqu xmm0, [A1]
movdqu xmm1, [A2]
lea T1, [.imm0 xWrtRIP]
lea T0, [A3 + A3*2] ; sizeof(pshufXX+ret) == 6: (A3 * 3) *2
lea T1, [T1 + T0*2]
call T1
movdqu [A1], xmm0
IEMIMPL_SSE_EPILOGUE
EPILOGUE_4_ARGS
%assign bImm 0
%rep 256
.imm %+ bImm:
%1 xmm0, xmm1, bImm
ret
%assign bImm bImm + 1
%endrep
.immEnd: ; 256*6 == 0x600
dw 0xf9ff + (.immEnd - .imm0) ; will cause warning if entries are too big.
dw 0x105ff - (.immEnd - .imm0) ; will cause warning if entries are small big.
ENDPROC iemAImpl_ %+ %1
%endmacro
IEMIMPL_MEDIA_SSE_PSHUFXX pshufhw
IEMIMPL_MEDIA_SSE_PSHUFXX pshuflw
IEMIMPL_MEDIA_SSE_PSHUFXX pshufd