IEMAllAImpl.asm revision 58b7ab82f43487a8a838dbeb96387c0d27b527f1
881b5ff6bc55e1fb0f4ef42f9782ccec79c0a138vboxsync; $Id$
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync;; @file
ea7d33962ceb90ea90e67e427d60b5788f34268avboxsync; IEM - Instruction Implementation in Assembly.
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync;
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync; Copyright (C) 2011 Oracle Corporation
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync;
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync; This file is part of VirtualBox Open Source Edition (OSE), as
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync; available from http://www.virtualbox.org. This file is free software;
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync; you can redistribute it and/or modify it under the terms of the GNU
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync; General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; Header Files ;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync%include "VBox/asmdefs.mac"
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync%include "VBox/err.mac"
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync%include "iprt/x86.mac"
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
cf57145d4697dceca3f0542b370c20f7a2c5c6e8vboxsync; Defined Constants And Macros ;
cf57145d4697dceca3f0542b370c20f7a2c5c6e8vboxsync;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync
cf57145d4697dceca3f0542b370c20f7a2c5c6e8vboxsync;;
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync; RET XX / RET wrapper for fastcall.
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync%macro RET_FASTCALL 1
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync%ifdef RT_ARCH_X86
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync %ifdef RT_OS_WINDOWS
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync ret %1
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync %else
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync ret
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync %endif
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync%else
881b5ff6bc55e1fb0f4ef42f9782ccec79c0a138vboxsync ret
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync%endif
881b5ff6bc55e1fb0f4ef42f9782ccec79c0a138vboxsync%endmacro
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync
e52b0dfe3d9ead70e24f2ce4ed3faa6c79c00618vboxsync;;
e52b0dfe3d9ead70e24f2ce4ed3faa6c79c00618vboxsync; NAME for fastcall functions.
e52b0dfe3d9ead70e24f2ce4ed3faa6c79c00618vboxsync;
e52b0dfe3d9ead70e24f2ce4ed3faa6c79c00618vboxsync;; @todo 'global @fastcall@12' is still broken in yasm and requires dollar
e52b0dfe3d9ead70e24f2ce4ed3faa6c79c00618vboxsync; escaping (or whatever the dollar is good for here). Thus the ugly
e52b0dfe3d9ead70e24f2ce4ed3faa6c79c00618vboxsync; prefix argument.
e52b0dfe3d9ead70e24f2ce4ed3faa6c79c00618vboxsync;
e52b0dfe3d9ead70e24f2ce4ed3faa6c79c00618vboxsync%define NAME_FASTCALL(a_Name, a_cbArgs, a_Dollar) NAME(a_Name)
c320aee99660824809e157bbad368db3542a9e90vboxsync%ifdef RT_ARCH_X86
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %ifdef RT_OS_WINDOWS
c320aee99660824809e157bbad368db3542a9e90vboxsync %undef NAME_FASTCALL
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define NAME_FASTCALL(a_Name, a_cbArgs, a_Prefix) a_Prefix %+ a_Name %+ @ %+ a_cbArgs
c320aee99660824809e157bbad368db3542a9e90vboxsync %endif
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync%endif
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync;;
ea7d33962ceb90ea90e67e427d60b5788f34268avboxsync; BEGINPROC for fastcall functions.
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync; @param 1 The function name (C).
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync; @param 2 The argument size on x86.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync;
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync%macro BEGINPROC_FASTCALL 2
881b5ff6bc55e1fb0f4ef42f9782ccec79c0a138vboxsync %ifdef ASM_FORMAT_PE
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync export %1=NAME_FASTCALL(%1,%2,$@)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync %endif
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %ifdef __NASM__
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync %ifdef ASM_FORMAT_OMF
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync export NAME(%1) NAME_FASTCALL(%1,%2,$@)
f2af1be3e27a2fefe95332260d360f4b26cffbcfvboxsync %endif
f2af1be3e27a2fefe95332260d360f4b26cffbcfvboxsync %endif
f2af1be3e27a2fefe95332260d360f4b26cffbcfvboxsync %ifndef ASM_FORMAT_BIN
f2af1be3e27a2fefe95332260d360f4b26cffbcfvboxsync global NAME_FASTCALL(%1,%2,$@)
75d8fea43f2d7474d00172dcf906f7ab598a8c8fvboxsync %endif
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsyncNAME_FASTCALL(%1,%2,@):
75d8fea43f2d7474d00172dcf906f7ab598a8c8fvboxsync%endmacro
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync
eaae6c3ce81916ccc4e74af4b55972ba956cf5c8vboxsync
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync;
eaae6c3ce81916ccc4e74af4b55972ba956cf5c8vboxsync; We employ some macro assembly here to hid the calling convention differences.
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync;
eaae6c3ce81916ccc4e74af4b55972ba956cf5c8vboxsync%ifdef RT_ARCH_AMD64
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %macro PROLOGUE_1_ARGS 0
eaae6c3ce81916ccc4e74af4b55972ba956cf5c8vboxsync %endmacro
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %macro EPILOGUE_1_ARGS 1
f1c8438d14b7420eb2b916ef5981ac09faa4f6c4vboxsync ret
f1c8438d14b7420eb2b916ef5981ac09faa4f6c4vboxsync %endmacro
f1c8438d14b7420eb2b916ef5981ac09faa4f6c4vboxsync
f1c8438d14b7420eb2b916ef5981ac09faa4f6c4vboxsync %macro PROLOGUE_2_ARGS 0
b6dc9545438e63d05fff621e85ddb7dc39cf14e7vboxsync %endmacro
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %macro EPILOGUE_2_ARGS 1
b6dc9545438e63d05fff621e85ddb7dc39cf14e7vboxsync ret
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %endmacro
20593760b116c90f3e439552763eef632a3bbb17vboxsync
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %macro PROLOGUE_3_ARGS 0
20593760b116c90f3e439552763eef632a3bbb17vboxsync %endmacro
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %macro EPILOGUE_3_ARGS 1
46f5824f3e233b92bad1626932d5ce9522886f54vboxsync ret
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %endmacro
46f5824f3e233b92bad1626932d5ce9522886f54vboxsync
46f5824f3e233b92bad1626932d5ce9522886f54vboxsync %macro PROLOGUE_4_ARGS 0
46f5824f3e233b92bad1626932d5ce9522886f54vboxsync %endmacro
46f5824f3e233b92bad1626932d5ce9522886f54vboxsync %macro EPILOGUE_4_ARGS 1
881b5ff6bc55e1fb0f4ef42f9782ccec79c0a138vboxsync ret
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %endmacro
6fea4abcc6ee0f2797ac01ef79c374d506aedc02vboxsync
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %ifdef ASM_CALL64_GCC
881b5ff6bc55e1fb0f4ef42f9782ccec79c0a138vboxsync %define A0 rdi
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define A0_32 edi
881b5ff6bc55e1fb0f4ef42f9782ccec79c0a138vboxsync %define A0_16 di
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define A0_8 dil
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync
63e576f3c901db19ac9a11f2353025b66a6798eevboxsync %define A1 rsi
881b5ff6bc55e1fb0f4ef42f9782ccec79c0a138vboxsync %define A1_32 esi
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define A1_16 si
881b5ff6bc55e1fb0f4ef42f9782ccec79c0a138vboxsync %define A1_8 sil
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync
881b5ff6bc55e1fb0f4ef42f9782ccec79c0a138vboxsync %define A2 rdx
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define A2_32 edx
881b5ff6bc55e1fb0f4ef42f9782ccec79c0a138vboxsync %define A2_16 dx
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define A2_8 dl
0b4890533cbae4f30a0241d0780d4ff9daa304f4vboxsync
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define A3 rcx
0b4890533cbae4f30a0241d0780d4ff9daa304f4vboxsync %define A3_32 ecx
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define A3_16 cx
881b5ff6bc55e1fb0f4ef42f9782ccec79c0a138vboxsync %endif
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync
7e33622becf3d7cf9a2401ac0c53d315877f6e34vboxsync %ifdef ASM_CALL64_MSC
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define A0 rcx
7e33622becf3d7cf9a2401ac0c53d315877f6e34vboxsync %define A0_32 ecx
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define A0_16 cx
a1e9b93d4f2b32d7a2aac1fb6ee958e1d147197cvboxsync %define A0_8 cl
a1e9b93d4f2b32d7a2aac1fb6ee958e1d147197cvboxsync
a1e9b93d4f2b32d7a2aac1fb6ee958e1d147197cvboxsync %define A1 rdx
a1e9b93d4f2b32d7a2aac1fb6ee958e1d147197cvboxsync %define A1_32 edx
881b5ff6bc55e1fb0f4ef42f9782ccec79c0a138vboxsync %define A1_16 dx
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define A1_8 dl
20593760b116c90f3e439552763eef632a3bbb17vboxsync
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define A2 r8
20593760b116c90f3e439552763eef632a3bbb17vboxsync %define A2_32 r8d
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define A2_16 r8w
881b5ff6bc55e1fb0f4ef42f9782ccec79c0a138vboxsync %define A2_8 r8b
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync
8c3ab623787ffed571ef7a1fa8c1a98e22d28021vboxsync %define A3 r9
96d5bb6dc5895c648c1f60b3d4faef7b93404756vboxsync %define A3_32 r9d
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync %define A3_16 r9w
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %endif
881b5ff6bc55e1fb0f4ef42f9782ccec79c0a138vboxsync
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define T0 rax
881b5ff6bc55e1fb0f4ef42f9782ccec79c0a138vboxsync %define T0_32 eax
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define T0_16 ax
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync %define T0_8 al
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync
d1ae44110ca869b6cb4a708dc6d676e10f4167bavboxsync %define T1 r11
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define T1_32 r11d
2cf084f1df635fcf1e1e40547a96c33f723471cbvboxsync %define T1_16 r11w
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync %define T1_8 r11b
2cf084f1df635fcf1e1e40547a96c33f723471cbvboxsync
c0cb47bd8aa02fca08ff72a37ba5c65894241cbfvboxsync%else
0028894c239c48232c9e516e73ba2205d8438a6avboxsync ; x86
0028894c239c48232c9e516e73ba2205d8438a6avboxsync %macro PROLOGUE_1_ARGS 0
0028894c239c48232c9e516e73ba2205d8438a6avboxsync push edi
0028894c239c48232c9e516e73ba2205d8438a6avboxsync %endmacro
0028894c239c48232c9e516e73ba2205d8438a6avboxsync %macro EPILOGUE_1_ARGS 1
0028894c239c48232c9e516e73ba2205d8438a6avboxsync pop edi
0028894c239c48232c9e516e73ba2205d8438a6avboxsync ret %1
0028894c239c48232c9e516e73ba2205d8438a6avboxsync %endmacro
ac6ede0b256f7583f8673aef5347770437c003davboxsync
ac6ede0b256f7583f8673aef5347770437c003davboxsync %macro PROLOGUE_2_ARGS 0
ac6ede0b256f7583f8673aef5347770437c003davboxsync push edi
ac6ede0b256f7583f8673aef5347770437c003davboxsync %endmacro
ac6ede0b256f7583f8673aef5347770437c003davboxsync %macro EPILOGUE_2_ARGS 1
ac6ede0b256f7583f8673aef5347770437c003davboxsync pop edi
ac6ede0b256f7583f8673aef5347770437c003davboxsync ret %1
ac6ede0b256f7583f8673aef5347770437c003davboxsync %endmacro
ac6ede0b256f7583f8673aef5347770437c003davboxsync
ac6ede0b256f7583f8673aef5347770437c003davboxsync %macro PROLOGUE_3_ARGS 0
ac6ede0b256f7583f8673aef5347770437c003davboxsync push ebx
ac6ede0b256f7583f8673aef5347770437c003davboxsync mov ebx, [esp + 4 + 4]
ac6ede0b256f7583f8673aef5347770437c003davboxsync push edi
ac6ede0b256f7583f8673aef5347770437c003davboxsync %endmacro
ac6ede0b256f7583f8673aef5347770437c003davboxsync %macro EPILOGUE_3_ARGS 1
ac6ede0b256f7583f8673aef5347770437c003davboxsync pop edi
ac6ede0b256f7583f8673aef5347770437c003davboxsync pop ebx
ac6ede0b256f7583f8673aef5347770437c003davboxsync ret %1
ac6ede0b256f7583f8673aef5347770437c003davboxsync %endmacro
ac6ede0b256f7583f8673aef5347770437c003davboxsync
ac6ede0b256f7583f8673aef5347770437c003davboxsync %macro PROLOGUE_4_ARGS 0
ac6ede0b256f7583f8673aef5347770437c003davboxsync push ebx
ac6ede0b256f7583f8673aef5347770437c003davboxsync push edi
ac6ede0b256f7583f8673aef5347770437c003davboxsync push esi
ac6ede0b256f7583f8673aef5347770437c003davboxsync mov ebx, [esp + 12 + 4 + 0]
ac6ede0b256f7583f8673aef5347770437c003davboxsync mov esi, [esp + 12 + 4 + 4]
ac6ede0b256f7583f8673aef5347770437c003davboxsync %endmacro
ac6ede0b256f7583f8673aef5347770437c003davboxsync %macro EPILOGUE_4_ARGS 1
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync pop esi
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync pop edi
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync pop ebx
65b0f0cd3c38007138720b7eaa43c963a9ee1244vboxsync ret %1
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync %endmacro
%define A0 ecx
%define A0_32 ecx
%define A0_16 cx
%define A0_8 cl
%define A1 edx
%define A1_32 edx
%define A1_16 dx
%define A1_8 dl
%define A2 ebx
%define A2_32 ebx
%define A2_16 bx
%define A2_8 bl
%define A3 esi
%define A3_32 esi
%define A3_16 si
%define T0 eax
%define T0_32 eax
%define T0_16 ax
%define T0_8 al
%define T1 edi
%define T1_32 edi
%define T1_16 di
%endif
;;
; Load the relevant flags from [%1] if there are undefined flags (%3).
;
; @remarks Clobbers T0, stack. Changes EFLAGS.
; @param A2 The register pointing to the flags.
; @param 1 The parameter (A0..A3) pointing to the eflags.
; @param 2 The set of modified flags.
; @param 3 The set of undefined flags.
;
%macro IEM_MAYBE_LOAD_FLAGS 3
;%if (%3) != 0
pushf ; store current flags
mov T0_32, [%1] ; load the guest flags
and dword [xSP], ~(%2 | %3) ; mask out the modified and undefined flags
and T0_32, (%2 | %3) ; select the modified and undefined flags.
or [xSP], T0 ; merge guest flags with host flags.
popf ; load the mixed flags.
;%endif
%endmacro
;;
; Update the flag.
;
; @remarks Clobbers T0, T1, stack.
; @param 1 The register pointing to the EFLAGS.
; @param 2 The mask of modified flags to save.
; @param 3 The mask of undefined flags to (maybe) save.
;
%macro IEM_SAVE_FLAGS 3
%if (%2 | %3) != 0
pushf
pop T1
mov T0_32, [%1] ; flags
and T0_32, ~(%2 | %3) ; clear the modified & undefined flags.
and T1_32, (%2 | %3) ; select the modified and undefined flags.
or T0_32, T1_32 ; combine the flags.
mov [%1], T0_32 ; save the flags.
%endif
%endmacro
;;
; Macro for implementing a binary 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 Non-zero if there should be a locked version.
; @param 3 The modified flags.
; @param 4 The undefined flags.
;
%macro IEMIMPL_BIN_OP 4
BEGINCODE
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %3, %4
%1 byte [A0], A1_8
IEM_SAVE_FLAGS A2, %3, %4
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_ %+ %1 %+ _u8
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %3, %4
%1 word [A0], A1_16
IEM_SAVE_FLAGS A2, %3, %4
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_ %+ %1 %+ _u16
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %3, %4
%1 dword [A0], A1_32
IEM_SAVE_FLAGS A2, %3, %4
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_ %+ %1 %+ _u32
%ifdef RT_ARCH_AMD64
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %3, %4
%1 qword [A0], A1
IEM_SAVE_FLAGS A2, %3, %4
EPILOGUE_3_ARGS 8
ENDPROC iemAImpl_ %+ %1 %+ _u64
%else ; stub it for now - later, replace with hand coded stuff.
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
int3
ret
ENDPROC iemAImpl_ %+ %1 %+ _u64
%endif ; !RT_ARCH_AMD64
%if %2 != 0 ; locked versions requested?
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8_locked, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %3, %4
lock %1 byte [A0], A1_8
IEM_SAVE_FLAGS A2, %3, %4
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_ %+ %1 %+ _u8_locked
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16_locked, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %3, %4
lock %1 word [A0], A1_16
IEM_SAVE_FLAGS A2, %3, %4
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_ %+ %1 %+ _u16_locked
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32_locked, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %3, %4
lock %1 dword [A0], A1_32
IEM_SAVE_FLAGS A2, %3, %4
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_ %+ %1 %+ _u32_locked
%ifdef RT_ARCH_AMD64
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 16
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %3, %4
lock %1 qword [A0], A1
IEM_SAVE_FLAGS A2, %3, %4
EPILOGUE_3_ARGS 8
ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
%else ; stub it for now - later, replace with hand coded stuff.
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 16
int3
ret 8
ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
%endif ; !RT_ARCH_AMD64
%endif ; locked
%endmacro
; instr,lock,modified-flags.
IEMIMPL_BIN_OP add, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
IEMIMPL_BIN_OP adc, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
IEMIMPL_BIN_OP sub, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
IEMIMPL_BIN_OP sbb, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
IEMIMPL_BIN_OP or, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
IEMIMPL_BIN_OP xor, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
IEMIMPL_BIN_OP and, 1, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
IEMIMPL_BIN_OP cmp, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
IEMIMPL_BIN_OP test, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_PF | X86_EFL_CF), X86_EFL_AF,
;;
; Macro for implementing a bit operator.
;
; This will generate code for the 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 Non-zero if there should be a locked version.
; @param 3 The modified flags.
; @param 4 The undefined flags.
;
%macro IEMIMPL_BIT_OP 4
BEGINCODE
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %3, %4
%1 word [A0], A1_16
IEM_SAVE_FLAGS A2, %3, %4
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_ %+ %1 %+ _u16
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %3, %4
%1 dword [A0], A1_32
IEM_SAVE_FLAGS A2, %3, %4
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_ %+ %1 %+ _u32
%ifdef RT_ARCH_AMD64
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %3, %4
%1 qword [A0], A1
IEM_SAVE_FLAGS A2, %3, %4
EPILOGUE_3_ARGS 8
ENDPROC iemAImpl_ %+ %1 %+ _u64
%else ; stub it for now - later, replace with hand coded stuff.
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
int3
ret 8
ENDPROC iemAImpl_ %+ %1 %+ _u64
%endif ; !RT_ARCH_AMD64
%if %2 != 0 ; locked versions requested?
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16_locked, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %3, %4
lock %1 word [A0], A1_16
IEM_SAVE_FLAGS A2, %3, %4
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_ %+ %1 %+ _u16_locked
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32_locked, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %3, %4
lock %1 dword [A0], A1_32
IEM_SAVE_FLAGS A2, %3, %4
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_ %+ %1 %+ _u32_locked
%ifdef RT_ARCH_AMD64
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 16
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %3, %4
lock %1 qword [A0], A1
IEM_SAVE_FLAGS A2, %3, %4
EPILOGUE_3_ARGS 8
ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
%else ; stub it for now - later, replace with hand coded stuff.
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_locked, 16
int3
ret 8
ENDPROC iemAImpl_ %+ %1 %+ _u64_locked
%endif ; !RT_ARCH_AMD64
%endif ; locked
%endmacro
IEMIMPL_BIT_OP bt, 0, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
IEMIMPL_BIT_OP btc, 1, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
IEMIMPL_BIT_OP bts, 1, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
IEMIMPL_BIT_OP btr, 1, (X86_EFL_CF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
;;
; Macro for implementing a bit search operator.
;
; 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.
;
; 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_BIT_OP 3
BEGINCODE
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %2, %3
%1 T0_16, A1_16
mov [A0], T0_16
IEM_SAVE_FLAGS A2, %2, %3
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_ %+ %1 %+ _u16
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %2, %3
%1 T0_32, A1_32
mov [A0], T0_32
IEM_SAVE_FLAGS A2, %2, %3
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_ %+ %1 %+ _u32
%ifdef RT_ARCH_AMD64
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, %2, %3
%1 T0, A1
mov [A0], T0
IEM_SAVE_FLAGS A2, %2, %3
EPILOGUE_3_ARGS 8
ENDPROC iemAImpl_ %+ %1 %+ _u64
%else ; stub it for now - later, replace with hand coded stuff.
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 16
int3
ret 8
ENDPROC iemAImpl_ %+ %1 %+ _u64
%endif ; !RT_ARCH_AMD64
%endmacro
IEMIMPL_BIT_OP bsf, (X86_EFL_ZF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF)
IEMIMPL_BIT_OP bsr, (X86_EFL_ZF), (X86_EFL_OF | X86_EFL_SF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF)
;
; IMUL is also a similar but yet different case (no lock, no mem dst).
; The rDX:rAX variant of imul is handled together with mul further down.
;
BEGINCODE
BEGINPROC_FASTCALL iemAImpl_imul_two_u16, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
imul A1_16, word [A0]
mov [A0], A1_16
IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_imul_two_u16
BEGINPROC_FASTCALL iemAImpl_imul_two_u32, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
imul A1_32, dword [A0]
mov [A0], A1_32
IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_imul_two_u32
BEGINPROC_FASTCALL iemAImpl_imul_two_u64, 16
PROLOGUE_3_ARGS
%ifdef RT_ARCH_AMD64
IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
imul A1, qword [A0]
mov [A0], A1
IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_CF), (X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
%else
int3 ;; @todo implement me
%endif
EPILOGUE_3_ARGS 8
ENDPROC iemAImpl_imul_two_u64
;
; XCHG for memory operands. This implies locking. No flag changes.
;
; Each function takes two arguments, first the pointer to the memory,
; then the pointer to the register. They all return void.
;
BEGINCODE
BEGINPROC_FASTCALL iemAImpl_xchg_u8, 8
PROLOGUE_2_ARGS
mov T0_8, [A1]
xchg [A0], T0_8
mov [A1], T0_8
EPILOGUE_2_ARGS 0
ENDPROC iemAImpl_xchg_u8
BEGINPROC_FASTCALL iemAImpl_xchg_u16, 8
PROLOGUE_2_ARGS
mov T0_16, [A1]
xchg [A0], T0_16
mov [A1], T0_16
EPILOGUE_2_ARGS 0
ENDPROC iemAImpl_xchg_u16
BEGINPROC_FASTCALL iemAImpl_xchg_u32, 8
PROLOGUE_2_ARGS
mov T0_32, [A1]
xchg [A0], T0_32
mov [A1], T0_32
EPILOGUE_2_ARGS 0
ENDPROC iemAImpl_xchg_u32
BEGINPROC_FASTCALL iemAImpl_xchg_u64, 8
%ifdef RT_ARCH_AMD64
PROLOGUE_2_ARGS
mov T0, [A1]
xchg [A0], T0
mov [A1], T0
EPILOGUE_2_ARGS 0
%else
int3
ret 0
%endif
ENDPROC iemAImpl_xchg_u64
;
; XADD for memory operands.
;
; Each function takes three arguments, first the pointer to the
; memory/register, then the pointer to the register, and finally a pointer to
; eflags. They all return void.
;
BEGINCODE
BEGINPROC_FASTCALL iemAImpl_xadd_u8, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
mov T0_8, [A1]
xadd [A0], T0_8
mov [A1], T0_8
IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_xadd_u8
BEGINPROC_FASTCALL iemAImpl_xadd_u16, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
mov T0_16, [A1]
xadd [A0], T0_16
mov [A1], T0_16
IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_xadd_u16
BEGINPROC_FASTCALL iemAImpl_xadd_u32, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
mov T0_32, [A1]
xadd [A0], T0_32
mov [A1], T0_32
IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_xadd_u32
BEGINPROC_FASTCALL iemAImpl_xadd_u64, 12
%ifdef RT_ARCH_AMD64
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
mov T0, [A1]
xadd [A0], T0
mov [A1], T0
IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
EPILOGUE_3_ARGS 4
%else
int3
ret 4
%endif
ENDPROC iemAImpl_xadd_u64
BEGINPROC_FASTCALL iemAImpl_xadd_u8_locked, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
mov T0_8, [A1]
lock xadd [A0], T0_8
mov [A1], T0_8
IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_xadd_u8_locked
BEGINPROC_FASTCALL iemAImpl_xadd_u16_locked, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
mov T0_16, [A1]
lock xadd [A0], T0_16
mov [A1], T0_16
IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_xadd_u16_locked
BEGINPROC_FASTCALL iemAImpl_xadd_u32_locked, 12
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
mov T0_32, [A1]
lock xadd [A0], T0_32
mov [A1], T0_32
IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
EPILOGUE_3_ARGS 4
ENDPROC iemAImpl_xadd_u32_locked
BEGINPROC_FASTCALL iemAImpl_xadd_u64_locked, 12
%ifdef RT_ARCH_AMD64
PROLOGUE_3_ARGS
IEM_MAYBE_LOAD_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
mov T0, [A1]
lock xadd [A0], T0
mov [A1], T0
IEM_SAVE_FLAGS A2, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF), 0
EPILOGUE_3_ARGS 4
%else
int3
ret 4
%endif
ENDPROC iemAImpl_xadd_u64_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 0
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 0
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 0
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 0
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 0
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 0
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 0
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 0
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 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 4
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 4
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 4
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 4
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 8
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 8
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 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 4
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 8
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 8
ENDPROC iemAImpl_ %+ %1 %+ _u32
%ifdef RT_ARCH_AMD64
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 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_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)
;;
; 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.
;
; Makes ASSUMPTIONS about A0, A1, A2, A3, T0 and T1 assignments.
;
%macro IEMIMPL_DIV_OP 3
BEGINCODE
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u8, 12
PROLOGUE_3_ARGS
test A1_8, A1_8
jz .div_zero
;; @todo test for overflow
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 4
.div_zero:
mov eax, -1
jmp .return
ENDPROC iemAImpl_ %+ %1 %+ _u8
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 16
PROLOGUE_4_ARGS
test A1_16, A1_16
jz .div_zero
;; @todo test for overflow
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 8
.div_zero:
mov eax, -1
jmp .return
ENDPROC iemAImpl_ %+ %1 %+ _u16
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 16
PROLOGUE_4_ARGS
test A1_32, A1_32
jz .div_zero
;; @todo test for overflow
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 8
.div_zero:
mov eax, -1
jmp .return
ENDPROC iemAImpl_ %+ %1 %+ _u32
%ifdef RT_ARCH_AMD64
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
PROLOGUE_4_ARGS
test A1, A1
jz .div_zero
;; @todo test for overflow
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 12
.div_zero:
mov eax, -1
jmp .return
ENDPROC iemAImpl_ %+ %1 %+ _u64
%else ; stub it for now - later, replace with hand coded stuff.
BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20
int3
ret
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)
IEMIMPL_DIV_OP idiv, 0, (X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF)
;
; 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 0
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 0
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 0
%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 0
%endif
ENDPROC iemAImpl_bswap_u64
;;
; The state saved by FXSAVE.
; @todo move to x86.mac.
;
struc X86FXSTATE
.FCW resw 1
.FSW resw 1
.FTW resw 1
.FOP resw 1
.FPUIP resd 1
.CS resw 1
.Rsrvd1 resw 1
.FPUDP resd 1
.DS resw 1
.Rsrvd2 resw 1
.MXCSR resd 1
.MXCSR_MASK resd 1
.r0 resd 4
.r1 resd 4
.r2 resd 4
.r3 resd 4
.r4 resd 4
.r5 resd 4
.r6 resd 4
.r7 resd 4
.xmm0 resd 4
.xmm1 resd 4
.xmm2 resd 4
.xmm3 resd 4
.xmm4 resd 4
.xmm5 resd 4
.xmm6 resd 4
.xmm7 resd 4
.xmm8 resd 4
.xmm9 resd 4
.xmm10 resd 4
.xmm11 resd 4
.xmm12 resd 4
.xmm13 resd 4
.xmm14 resd 4
.xmm15 resd 4
.au32RsrvdRest resd 24
endstruc
%macro FPU_SAFE_INIT 1
fninit
movzx T0, word [%1 + X86FXSTATE.FCW]
or T0, X86_FCW_MASK_ALL
mov [xSP], T0
fldcw [xSP]
%endmacro
;;
; Need to move this as well somewhere better?
;
struc IEMFPURESULT
.r80Result resw 5
.FSW resw 1
endstruc
;;
; 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 The 32-bit floating point value to convert.
;
BEGINPROC_FASTCALL iemAImpl_fpu_r32_to_r80, 12
PROLOGUE_3_ARGS
sub xSP, 20h
FPU_SAFE_INIT A0
mov [xSP], A2
fld dword [xSP]
fnstsw word [A1 + IEMFPURESULT.FSW]
fstp tword [A1 + IEMFPURESULT.r80Result]
add xSP, 20h
EPILOGUE_3_ARGS 0
ENDPROC iemAImpl_fpu_r32_to_r80
;;
; 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 32-bit floating point value to convert.
;
BEGINPROC_FASTCALL iemAImpl_fpu_r64_to_r80, 12
PROLOGUE_3_ARGS
sub xSP, 20h
FPU_SAFE_INIT A0
fld qword [A2]
fnstsw word [A1 + IEMFPURESULT.FSW]
fstp tword [A1 + IEMFPURESULT.r80Result]
add xSP, 20h
EPILOGUE_3_ARGS 0
ENDPROC iemAImpl_fpu_r64_to_r80