summaryrefslogtreecommitdiffstats
path: root/src/VBox/Disassembler/testcase
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
commitf8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch)
tree26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/Disassembler/testcase
parentInitial commit. (diff)
downloadvirtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.tar.xz
virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.zip
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Disassembler/testcase')
-rw-r--r--src/VBox/Disassembler/testcase/Makefile.kmk256
-rw-r--r--src/VBox/Disassembler/testcase/tstAsm.mac58
-rw-r--r--src/VBox/Disassembler/testcase/tstAsm3DNow-1.asm81
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmFnstsw-1.asm31
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmLock-1.asm675
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmLock-2.asm537
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmLock-3.asm46
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmMovFixedReg-1.asm103
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmMovSeg-1.asm48
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmMovzx-1.asm39
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmPop-1.asm36
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmPush-1.asm36
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmRegs-1.asm109
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmSignExtend-1.asm53
-rw-r--r--src/VBox/Disassembler/testcase/tstBinFnstsw-1.binbin0 -> 3 bytes
-rw-r--r--src/VBox/Disassembler/testcase/tstBinMovzx-1.bin1
-rw-r--r--src/VBox/Disassembler/testcase/tstDisasm-1.cpp190
-rw-r--r--src/VBox/Disassembler/testcase/tstDisasm-1A.asm422
-rw-r--r--src/VBox/Disassembler/testcase/tstDisasm-2.cpp683
19 files changed, 3404 insertions, 0 deletions
diff --git a/src/VBox/Disassembler/testcase/Makefile.kmk b/src/VBox/Disassembler/testcase/Makefile.kmk
new file mode 100644
index 00000000..3506b217
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/Makefile.kmk
@@ -0,0 +1,256 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-Makefile for the VBox Disassembler.
+#
+
+#
+# Copyright (C) 2006-2019 Oracle Corporation
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+#
+
+SUB_DEPTH = ../../../..
+include $(KBUILD_PATH)/subheader.kmk
+ifdef VBOX_WITH_TESTCASES
+
+
+PROGRAMS += tstDisasm-1
+tstDisasm-1_TEMPLATE = VBOXR3TSTEXE
+tstDisasm-1_DEFS = IN_DIS
+tstDisasm-1_SOURCES = \
+ tstDisasm-1.cpp \
+ tstDisasm-1A.asm
+tstDisasm-1_LIBS = \
+ $(PATH_STAGE_LIB)/DisasmR3$(VBOX_SUFF_LIB) \
+ $(LIB_RUNTIME)
+
+
+PROGRAMS += tstDisasm-2
+tstDisasm-2_TEMPLATE = VBOXR3TSTEXE
+tstDisasm-2_DEFS = IN_DIS
+tstDisasm-2_SOURCES = \
+ tstDisasm-2.cpp
+tstDisasm-2_LIBS = \
+ $(PATH_STAGE_LIB)/DisasmR3$(VBOX_SUFF_LIB) \
+ $(LIB_RUNTIME)
+
+# Tests that will be build, disassembled and re-build from disassembly.
+VBOX_DISAS_TESTS_BUILD = \
+ tstAsmFnstsw-1.asm \
+ tstAsmLock-1.asm \
+ tstAsmMovFixedReg-1.asm \
+ tstAsmMovSeg-1.asm \
+ tstAsmMovzx-1.asm \
+ tstAsmPop-1.asm \
+ tstAsmPush-1.asm \
+ tstAsmSignExtend-1.asm \
+ tstAsmRegs-1.asm \
+ tstAsm3DNow-1.asm \
+
+# Tests that only contains invalid/undefined instructions.
+VBOX_DISAS_TESTS_INVALID = \
+ tstAsmLock-2.asm \
+ tstAsmLock-3.asm
+
+# Tests that will be disassembled and re-build from disassembly (list of binaries).
+## @todo tstBinMovzx-1.bin: does C7 imply 32-bit reg in 16-bit mode, or what exactly does it do?
+VBOX_DISAS_TESTS_BINARIES := \
+ tstBinMovzx-1.bin \
+ tstBinFnstsw-1.bin
+ifeq ($(USER)x,bird)
+VBOX_DISAS_TESTS_BINARIES += \
+ tstBin-1.bin \
+ tstBin-2.bin \
+ tstBin-3.bin \
+ tstBin-4.bin \
+ tstBin-5.bin \
+ tstBin-6.bin
+# $(PATH_STAGE_BIN)/testcase/tstDisasm-2$(SUFF_EXEC)
+endif
+VBOX_DISAS_TESTS_BINARIES_NOT_16BIT := \
+ tstBinFnstsw-1.bin
+VBOX_DISAS_TESTS_BINARIES_NOT_32BIT :=
+VBOX_DISAS_TESTS_BINARIES_NOT_64BIT :=
+
+
+#
+# The gory bits...
+#
+
+# Where we put the output files from the testcases.
+VBOX_DISAS_TEST_OUT_DIR := $(PATH_TARGET)/Disassembler/testcase
+BLDDIRS += $(VBOX_DISAS_TEST_OUT_DIR)
+
+# Generate the rules for creating the .bin files.
+VBOX_DISAS_TESTS_BIN = $(VBOX_DISAS_TESTS_BUILD) $(VBOX_DISAS_TESTS_INVALID)
+VBOX_DISAS_TEST_CLEAN += $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/,\
+ $(VBOX_DISAS_TESTS_BIN:.asm=-16.bin)\
+ $(VBOX_DISAS_TESTS_BIN:.asm=-32.bin)\
+ $(VBOX_DISAS_TESTS_BIN:.asm=-64.bin))
+
+$(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BIN:.asm=-16.bin)): $(PATH_SUB_CURRENT)/$$(patsubst %-16.bin,%.asm,$$(notdir $$(@))) | $$(dir $$@)
+ @$(ECHO) "Assembling: $(<F) into $(@F)"
+ $(TOOL_YASM_AS) -f bin -a x86 --force-strict -DTEST_BITS=16 -o $@ $<
+
+$(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BIN:.asm=-32.bin)): $(PATH_SUB_CURRENT)/$$(patsubst %-32.bin,%.asm,$$(notdir $$(@))) | $$(dir $$@)
+ @$(ECHO) "Assembling: $(<F) into $(@F)"
+ $(TOOL_YASM_AS) -f bin -a x86 --force-strict -DTEST_BITS=32 -o $@ $<
+
+$(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BIN:.asm=-64.bin)): $(PATH_SUB_CURRENT)/$$(patsubst %-64.bin,%.asm,$$(notdir $$(@))) | $$(dir $$@)
+ @$(ECHO) "Assembling: $(<F) into $(@F)"
+ $(TOOL_YASM_AS) -f bin -a x86 --force-strict -DTEST_BITS=64 -o $@ $<
+
+
+# Generate the rules for the 'build' tests.
+VBOX_DISAS_TEST_CLEAN += $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/,\
+ $(VBOX_DISAS_TESTS_BUILD:.asm=-16-disas.asm)\
+ $(VBOX_DISAS_TESTS_BUILD:.asm=-32-disas.asm)\
+ $(VBOX_DISAS_TESTS_BUILD:.asm=-64-disas.asm))
+
+$(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BUILD:.asm=-16-disas.asm)): $$(subst -disas.asm,.bin,$$@) $$(tstDisasm-2_1_STAGE_TARGET) | $$(dir $$@)
+ @$(ECHO) "Generating: $(@F) from $(<F)"
+ $(REDIRECT) -E VBOX_LOG_DEST=nofile -o $@ -- $(tstDisasm-2_1_STAGE_TARGET) --style=yasm --cpumode=16 $<
+
+$(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BUILD:.asm=-32-disas.asm)): $$(subst -disas.asm,.bin,$$@) $$(tstDisasm-2_1_STAGE_TARGET) | $$(dir $$@)
+ @$(ECHO) "Generating: $(@F) from $(<F)"
+ $(REDIRECT) -E VBOX_LOG_DEST=nofile -o $@ -- $(tstDisasm-2_1_STAGE_TARGET) --style=yasm --cpumode=32 $<
+
+$(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BUILD:.asm=-64-disas.asm)): $$(subst -disas.asm,.bin,$$@) $$(tstDisasm-2_1_STAGE_TARGET) | $$(dir $$@)
+ @$(ECHO) "Generating: $(@F) from $(<F)"
+ $(REDIRECT) -E VBOX_LOG_DEST=nofile -o $@ -- $(tstDisasm-2_1_STAGE_TARGET) --style=yasm --cpumode=64 $<
+
+
+VBOX_DISAS_TEST_CLEAN += $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/,\
+ $(VBOX_DISAS_TESTS_BUILD:.asm=-16-disas.bin)\
+ $(VBOX_DISAS_TESTS_BUILD:.asm=-32-disas.bin)\
+ $(VBOX_DISAS_TESTS_BUILD:.asm=-64-disas.bin))
+
+$(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BUILD:.asm=-16-disas.bin)): $$(subst .bin,.asm,$$@) | $$(dir $$@)
+ @$(ECHO) "Re-assembling: $(<F) into $(@F)"
+ $(TOOL_YASM_AS) -f bin -a x86 --force-strict -DTEST_BITS=16 -o $@ $<
+
+$(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BUILD:.asm=-32-disas.bin)): $$(subst .bin,.asm,$$@) | $$(dir $$@)
+ @$(ECHO) "Re-assembling: $(<F) into $(@F)"
+ $(TOOL_YASM_AS) -f bin -a x86 --force-strict -DTEST_BITS=32 -o $@ $<
+
+$(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BUILD:.asm=-64-disas.bin)): $$(subst .bin,.asm,$$@) | $$(dir $$@)
+ @$(ECHO) "Re-assembling: $(<F) into $(@F)"
+ $(TOOL_YASM_AS) -f bin -a x86 --force-strict -DTEST_BITS=64 -o $@ $<
+
+
+VBOX_DISAS_TESTS += $(foreach test, $(VBOX_DISAS_TESTS_BUILD:.asm=), $(test)-16.tst $(test)-32.tst $(test)-64.tst)
+$(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/,\
+$(VBOX_DISAS_TESTS_BUILD:.asm=-16.tst)\
+$(VBOX_DISAS_TESTS_BUILD:.asm=-32.tst)\
+$(VBOX_DISAS_TESTS_BUILD:.asm=-64.tst) ): $$(subst .tst,-disas.bin,$$@) | $$(dir $$@)
+ @$(ECHO) "Verifying build: $(<F) and $(@F:.tst=.bin)"
+ @$(RM) -f $@
+ $(CMP) $(@:.tst=.bin) $<
+ @$(APPEND) $@ "done"
+ @$(ECHO) " PASSED: $(<F) [re-assembled]"
+
+
+
+# Generate the rules for the 'invalid' tests.
+VBOX_DISAS_TESTS += $(foreach test, $(VBOX_DISAS_TESTS_INVALID:.asm=), $(test)-16.tst $(test)-32.tst $(test)-64.tst)
+
+$(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_INVALID:.asm=-16.tst)): $$(patsubst %.tst,%.bin,$$@) $$(tstDisasm-2_1_STAGE_TARGET) | $$(dir $$@)
+ @$(ECHO) "TESTING: $(@F) [--undef-op=all]"
+ @$(RM) -f $@
+ $(REDIRECT) -E VBOX_LOG_DEST=nofile -- $(tstDisasm-2_1_STAGE_TARGET) --undef-op=all --cpumode=16 $<
+ @$(APPEND) $@ "done"
+ @$(ECHO) " PASSED: $(@F) [--undef-op=all]"
+
+$(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_INVALID:.asm=-32.tst)): $$(patsubst %.tst,%.bin,$$@) $$(tstDisasm-2_1_STAGE_TARGET) | $$(dir $$@)
+ @$(ECHO) "TESTING: $(@F) [--undef-op=all]"
+ @$(RM) -f $@
+ $(REDIRECT) -E VBOX_LOG_DEST=nofile -- $(tstDisasm-2_1_STAGE_TARGET) --undef-op=all --cpumode=32 $<
+ @$(APPEND) $@ "done"
+ @$(ECHO) " PASSED: $(@F) [--undef-op=all]"
+
+$(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_INVALID:.asm=-64.tst)): $$(patsubst %.tst,%.bin,$$@) $$(tstDisasm-2_1_STAGE_TARGET) | $$(dir $$@)
+ @$(ECHO) "TESTING: $(@F) [--undef-op=all]"
+ @$(RM) -f $@
+ $(REDIRECT) -E VBOX_LOG_DEST=nofile -- $(tstDisasm-2_1_STAGE_TARGET) --undef-op=all --cpumode=64 $<
+ @$(APPEND) $@ "done"
+ @$(ECHO) " PASSED: $(@F) [--undef-op=all]"
+
+
+# Generate the rules for the binary tests.
+define def_vbox_disas_binary_rules
+$(outbase).asm: $(full_binary) $$$$(tstDisasm-2_1_STAGE_TARGET) | $(VBOX_DISAS_TEST_OUT_DIR)/
+ @$$(ECHO) "Generating: $$(@F) from $$(<F)"
+ $$(REDIRECT) -E VBOX_LOG_DEST=nofile -o $$@ -- $$(tstDisasm-2_1_STAGE_TARGET) --style=yasm --cpumode=$(bits) --undef-op=db $$<
+
+$(outbase).bin + $(outbase).lst: $(outbase).asm
+ @$$(ECHO) "Re-assembling: $$(<F) into $$(@F)"
+ $$(TOOL_YASM_AS) -f bin -a x86 --force-strict -l $(outbase).lst -o $$@ $$<
+
+$(outbase).tst: $(outbase).bin
+ @$$(ECHO) "Verifying build: $$(<F) against $(not-dir $(full_binary))"
+ @$$(RM) -f $$@
+ $$(CMP) -l $(full_binary) $$<
+ @$$(APPEND) $$@ "done"
+ @$$(ECHO) " PASSED: $$(<F) [binary]"
+
+$(name).tst:: $(outbase).tst
+VBOX_DISAS_TEST_CLEAN += $(outbase).tst $(outbase).bin $(outbase).asm
+VBOX_DISAS_TESTS += $(name)-rebuild-$(bits).tst
+endef # def_vbox_disas_binary_rules
+
+define def_vbox_disas_binary
+local name := $(notdir $(basename $(binary)))
+local full_binary := $(abspathex $(binary),$(PATH_SUB_CURRENT))
+local outbase := $(VBOX_DISAS_TEST_OUT_DIR)/$(name)-rebuild-$(bits)
+$(eval $(def_vbox_disas_binary_rules))
+endef # def_vbox_disas_binary
+
+## @todo 64-bit is problematic because of bugs like POP RDI ending up as POP EDI (incorrect default opmode).
+#$(foreach bits, 64, $(foreach binary, $(VBOX_DISAS_TESTS_BINARIES), $(evalvalctx def_vbox_disas_binary)))
+$(foreach bits, 32 16, $(foreach binary, $(filter-out $(VBOX_DISAS_TESTS_BINARIES_NOT_$(bits)BIT), $(VBOX_DISAS_TESTS_BINARIES)) \
+ , $(evalvalctx def_vbox_disas_binary)))
+
+
+# Add the .tst to the clean up.
+VBOX_DISAS_TEST_CLEAN += $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS))
+OTHER_CLEAN += $(VBOX_DISAS_TEST_CLEAN)
+
+# We don't want any of the tests rules to run in parallel because the
+# output will be difficult to follow. Abusing VBOX_DISAS_TEST_CLEAN here...
+.NOTPARALLEL: $$(VBOX_DISAS_TEST_CLEAN)
+
+
+#
+# Add the tests to the target list for the testing pass.
+# (kBuild r1646)
+#
+TESTING += $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/,$(VBOX_DISAS_TESTS))
+
+
+#
+# The test aliases
+#
+# To run the tstAsmLock-3.asm test: kmk tstAsmLock-3.tst
+# To run the 64-bit tstAsmLock-3.asm test: kmk tstAsmLock-3-64.tst
+#
+define def_vbox_test_aliases
+local test_base := $(basename $(test))
+local test_root := $(patsubst %-16,%,$(patsubst %-32,%,$(patsubst %-64,%,$(test_base))))
+$(test_base).tst:: $(VBOX_DISAS_TEST_OUT_DIR)/$(test)
+$(test_root).tst:: $(test_base).tst
+$(test_base).o:: $(test_base).tst
+$(test_base).obj:: $(test_base).tst
+$(test_root).o:: $(test_root).tst
+$(test_root).obj:: $(test_root).tst
+endef
+$(foreach test,$(VBOX_DISAS_TESTS),$(evalvalctx def_vbox_test_aliases))
+
+endif # VBOX_WITH_TESTCASES
+include $(FILE_KBUILD_SUB_FOOTER)
+
diff --git a/src/VBox/Disassembler/testcase/tstAsm.mac b/src/VBox/Disassembler/testcase/tstAsm.mac
new file mode 100644
index 00000000..817e5ff3
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsm.mac
@@ -0,0 +1,58 @@
+; $Id: tstAsm.mac $
+;; @file
+; Disassembly testcase - Common header for the xREG macros.
+;
+
+;
+; Copyright (C) 2008-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+%if TEST_BITS == 64
+ %define xCB 8
+ %define xSP rsp
+ %define xBP rbp
+ %define xAX rax
+ %define xBX rbx
+ %define xCX rcx
+ %define xDX rdx
+ %define xDI rdi
+ %define xSI rsi
+%endif
+%if TEST_BITS == 32
+ %define xCB 4
+ %define xSP esp
+ %define xBP ebp
+ %define xAX eax
+ %define xBX ebx
+ %define xCX ecx
+ %define xDX edx
+ %define xDI edi
+ %define xSI esi
+%endif
+%if TEST_BITS == 16
+ %define xCB 2
+ %define xSP sp
+ %define xBP bp
+ %define xAX ax
+ %define xBX bx
+ %define xCX cx
+ %define xDX dx
+ %define xDI di
+ %define xSI si
+%endif
+%ifndef xCB
+ %error "TEST_BITS is missing or wrong."
+%endif
+
+%if __YASM_VERSION_ID__ >= 001020001h ; v1.2.0.1 and greater, make sure to exclude v1.2.0.0.
+ %define pmulhrwa pmulhrw
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsm3DNow-1.asm b/src/VBox/Disassembler/testcase/tstAsm3DNow-1.asm
new file mode 100644
index 00000000..6188a4a6
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsm3DNow-1.asm
@@ -0,0 +1,81 @@
+; $Id: tstAsm3DNow-1.asm $
+;; @file
+; Disassembly testcase - 3DNow!
+;
+
+;
+; Copyright (C) 2008-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+%include "tstAsm.mac"
+
+ BITS TEST_BITS
+
+ pavgusb mm1, mm0
+ pf2id mm5, mm4
+ pf2iw mm6, mm3
+ pfacc mm7, mm2
+ pfadd mm5, mm4
+ pfcmpeq mm6, mm3
+ pfcmpge mm2, mm7
+ pfcmpgt mm4, mm5
+ pfmax mm3, mm6
+ pfmin mm1, mm0
+ pfmul mm5, mm4
+ pmulhrwa mm3, mm6
+ pfnacc mm4, mm5
+ pfpnacc mm3, mm6
+ pfrcp mm0, mm1
+ pfrcpit1 mm2, mm7
+ pfrcpit2 mm4, mm5
+ pfrsqrt mm7, mm2
+ pfrsqit1 mm1, mm0
+ pfsub mm6, mm3
+ pfsubr mm0, mm1
+ pi2fd mm7, mm2
+ pi2fw mm0, mm1
+ pswapd mm2, mm7
+
+%if TEST_BITS == 16
+ %define SIB(extra)
+ %define SIB(extra)
+%else
+ %define SIB(extra) extra
+%endif
+ pf2id mm5, qword [ds:xSI SIB(+000101010h)]
+ pf2iw mm6, qword [fs:xSI SIB(+000101010h)]
+ pfacc mm7, qword [gs:xSI SIB(+000101010h)]
+ pfadd mm5, qword [ xSI SIB(+000101010h)]
+ pfcmpeq mm6, qword [ xDI SIB(*8+000101010h)]
+ pfcmpge mm2, qword [es:xSI SIB(+000100010h)]
+ pfcmpgt mm4, qword [es:xSI SIB(+000101010h)]
+ pfmax mm3, qword [es:xSI SIB(+000101010h)]
+ pfmin mm1, qword [es:xSI SIB(+000101010h)]
+ pfmul mm5, qword [es:xSI SIB(+000101000h)]
+ pfrcpit1 mm2, qword [es:xBP SIB(+000101510h)]
+%if TEST_BITS != 16
+ pavgusb mm1, qword [es:xAX SIB(+000000010h)]
+ pfpnacc mm3, qword [es:xDX SIB(+000102900h)]
+ pfrcp mm0, qword [es:xCX SIB(+000101020h)]
+ pmulhrwa mm3, qword [es:xAX SIB(+0ffffffffh)]
+ pfrcpit2 mm4, qword [es:xSP SIB(+000101310h)]
+%endif
+ pfnacc mm4, qword [es:xBX SIB(+000101010h)]
+ pfrsqrt mm7, qword [es:xSI SIB(+0f0106010h)]
+ pfrsqit1 mm1, qword [es:xDI SIB(+0001f1010h)]
+ pfsub mm6, qword [es:xSI SIB(*2)]
+ pfsubr mm0, qword [es:xSI SIB(*3)]
+ pi2fd mm7, qword [es:xSI SIB(*4)]
+ pi2fw mm0, qword [es:xSI SIB(*5)]
+ pswapd mm2, qword [es:xSI SIB(*8)]
+
+ pmulhrwa mm0, qword [ds:xBP SIB(+xDI*8+00f000001h)]
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmFnstsw-1.asm b/src/VBox/Disassembler/testcase/tstAsmFnstsw-1.asm
new file mode 100644
index 00000000..3815368f
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmFnstsw-1.asm
@@ -0,0 +1,31 @@
+; $Id: tstAsmFnstsw-1.asm $
+;; @file
+; Disassembly testcase - Valid fnstsw* instructitons.
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2008-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+%include "tstAsm.mac"
+ BITS TEST_BITS
+
+ fstsw ax
+ fnstsw ax
+ fstsw [xBX]
+ fnstsw [xBX]
+ fstsw [xBX+xDI]
+ fnstsw [xBX+xDI]
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmLock-1.asm b/src/VBox/Disassembler/testcase/tstAsmLock-1.asm
new file mode 100644
index 00000000..14245613
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmLock-1.asm
@@ -0,0 +1,675 @@
+; $Id: tstAsmLock-1.asm $
+;; @file
+; Disassembly testcase - Valid lock sequences and related instructions.
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2008-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+%include "tstAsm.mac"
+%if TEST_BITS == 64
+
+; The disassembler doesn't do imm32 right for 64-bit stuff, so disable it for now.
+; %define WITH_64_BIT_TESTS_IMM32
+
+; The cmpxchg16b/8b stuff isn't handled correctly in 64-bit mode. In the 8b case
+; it could be both yasm and the vbox disassembler. Have to check docs/gas/nasm.
+; %define WITH_64_BIT_TESTS_CMPXCHG16B
+
+; Seems there are some issues with the byte, word and dword variants of r8-15.
+; Again, this could be yasm issues too...
+; %define WITH_64_BIT_TESTS_BORKED_REGS
+
+ %define WITH_64_BIT_TESTS
+%endif
+
+ BITS TEST_BITS
+
+ ;
+ ; ADC
+ ;
+ ; 80 /2 ib ADC reg/mem8, imm8 - sans reg dst
+ lock adc byte [1000h], byte 8
+ lock adc byte [xBX], byte 8
+ lock adc byte [xDI], byte 8
+ ; 81 /2 i[wd] ADC reg/memX, immX - sans reg dst
+ lock adc word [1000h], word 090cch
+ lock adc word [xBX], word 090cch
+ lock adc word [xDI], word 090cch
+ lock adc dword [1000h], dword 0cc90cc90h
+ lock adc dword [xBX], dword 0cc90cc90h
+ lock adc dword [xDI], dword 0cc90cc90h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock adc qword [1000h], dword 0cc90cc90h
+ lock adc qword [rbx], dword 0cc90cc90h
+ lock adc qword [rdi], dword 0cc90cc90h
+ lock adc qword [r9], dword 0cc90cc90h
+%endif
+ ; 83 /2 ib ADC reg/memX, imm8 - sans reg dst
+ lock adc word [1000h], byte 07fh
+ lock adc word [xBX], byte 07fh
+ lock adc word [xDI], byte 07fh
+ lock adc dword [1000h], byte 07fh
+ lock adc dword [xBX], byte 07fh
+ lock adc dword [xDI], byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock adc qword [1000h], byte 07fh
+ lock adc qword [rbx], byte 07fh
+ lock adc qword [rdi], byte 07fh
+ lock adc qword [r10], byte 07fh
+%endif
+
+ ; 10 /r ADC reg/mem8, reg8 - sans reg dst
+ lock adc byte [1000h], bl
+ lock adc byte [xBX], bl
+ lock adc byte [xSI], bl
+ ; 11 /r ADC reg/memX, regX - sans reg dst
+ lock adc word [1000h], bx
+ lock adc word [xBX], bx
+ lock adc word [xSI], bx
+ lock adc dword [1000h], ebx
+ lock adc dword [xBX], ebx
+ lock adc dword [xSI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock adc qword [1000h], rbx
+ lock adc qword [rbx], rbx
+ lock adc qword [rsi], rbx
+ lock adc qword [r11], rbx
+%endif
+
+ ;
+ ; ADD
+ ;
+ ; 80 /0 ib ADD reg/mem8, imm8 - sans reg dst
+ lock add byte [1000h], byte 8
+ lock add byte [xBX], byte 8
+ lock add byte [xDI], byte 8
+ ; 81 /0 i[wd] ADD reg/memX, immX - sans reg dst
+ lock add word [1000h], word 090cch
+ lock add word [xBX], word 090cch
+ lock add word [xDI], word 090cch
+ lock add dword [1000h], dword 0cc90cc90h
+ lock add dword [xBX], dword 0cc90cc90h
+ lock add dword [xDI], dword 0cc90cc90h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock add qword [1000h], dword 0cc90cc90h
+ lock add qword [rbx], dword 0cc90cc90h
+ lock add qword [rdi], dword 0cc90cc90h
+ lock add qword [r9], dword 0cc90cc90h
+%endif
+ ; 83 /0 ib ADD reg/memX, imm8 - sans reg dst
+ lock add word [1000h], byte 07fh
+ lock add word [xBX], byte 07fh
+ lock add word [xDI], byte 07fh
+ lock add dword [1000h], byte 07fh
+ lock add dword [xBX], byte 07fh
+ lock add dword [xDI], byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock add qword [1000h], byte 07fh
+ lock add qword [rbx], byte 07fh
+ lock add qword [rdi], byte 07fh
+ lock add qword [r10], byte 07fh
+%endif
+
+ ; 00 /r ADD reg/mem8, reg8 - sans reg dst
+ lock add byte [1000h], bl
+ lock add byte [xBX], bl
+ lock add byte [xSI], bl
+ ; 01 /r ADD reg/memX, regX - sans reg dst
+ lock add word [1000h], bx
+ lock add word [xBX], bx
+ lock add word [xSI], bx
+ lock add dword [1000h], ebx
+ lock add dword [xBX], ebx
+ lock add dword [xSI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock add qword [1000h], rbx
+ lock add qword [rbx], rbx
+ lock add qword [rsi], rbx
+ lock add qword [r11], rbx
+%endif
+
+ ;
+ ; AND
+ ;
+ ; 80 /4 ib AND reg/mem8, imm8 - sans reg dst
+ lock and byte [1000h], byte 8
+ lock and byte [xBX], byte 8
+ lock and byte [xDI], byte 8
+ ; 81 /4 i[wd] AND reg/memX, immX - sans reg dst
+ lock and word [1000h], word 090cch
+ lock and word [xBX], word 090cch
+ lock and word [xDI], word 090cch
+ lock and dword [1000h], dword 0cc90cc90h
+ lock and dword [xBX], dword 0cc90cc90h
+ lock and dword [xDI], dword 0cc90cc90h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock and qword [1000h], dword 0cc90cc90h
+ lock and qword [rbx], dword 0cc90cc90h
+ lock and qword [rdi], dword 0cc90cc90h
+ lock and qword [r9], dword 0cc90cc90h
+%endif
+ ; 83 /4 ib AND reg/memX, imm8 - sans reg dst
+ lock and word [1000h], byte 07fh
+ lock and word [xBX], byte 07fh
+ lock and word [xDI], byte 07fh
+ lock and dword [1000h], byte 07fh
+ lock and dword [xBX], byte 07fh
+ lock and dword [xDI], byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock and qword [1000h], byte 07fh
+ lock and qword [rbx], byte 07fh
+ lock and qword [rdi], byte 07fh
+ lock and qword [r10], byte 07fh
+%endif
+
+ ; 20 /r AND reg/mem8, reg8 - sans reg dst
+ lock and byte [1000h], bl
+ lock and byte [xBX], bl
+ lock and byte [xSI], bl
+ ; 21 /r AND reg/memX, regX - sans reg dst
+ lock and word [1000h], bx
+ lock and word [xBX], bx
+ lock and word [xSI], bx
+ lock and dword [1000h], ebx
+ lock and dword [xBX], ebx
+ lock and dword [xSI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock and qword [1000h], rbx
+ lock and qword [rbx], rbx
+ lock and qword [rsi], rbx
+ lock and qword [r11], rbx
+%endif
+
+ ;
+ ; BTC
+ ;
+ ; 0f bb /r BTC reg/memX, regX (X != 8) - sans reg dst
+ lock btc word [20cch], bx
+ lock btc word [xBX], bx
+ lock btc word [xDI], bx
+ lock btc dword [20cch], ebx
+ lock btc dword [xBX], ebx
+ lock btc dword [xDI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock btc qword [20cch], rbx
+ lock btc qword [rdx], rbx
+ lock btc qword [rdi], r10
+ lock btc qword [r8], r12
+%endif
+ ; 0f ba /7 ib BTC reg/memX, imm8 (X != 8) - sans reg dst
+ lock btc word [20cch], 15
+ lock btc word [xBX], 15
+ lock btc word [xDI], 15
+ lock btc dword [20cch], 30
+ lock btc dword [xBX], 30
+ lock btc dword [xDI], 30
+%ifdef WITH_64_BIT_TESTS
+ lock btc qword [20cch], 60
+ lock btc qword [rdx], 60
+ lock btc qword [rdi], 60
+ lock btc qword [r9], 60
+ lock btc qword [r12], 60
+%endif
+
+ ;
+ ; BTR
+ ;
+ ; 0f b3 /r BTR reg/memX, regX (X != 8) - sans reg dst
+ lock btr word [20cch], bx
+ lock btr word [xBX], bx
+ lock btr word [xDI], bx
+ lock btr dword [20cch], ebx
+ lock btr dword [xBX], ebx
+ lock btr dword [xDI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock btr qword [20cch], rbx
+ lock btr qword [rdx], rbx
+ lock btr qword [rdi], r10
+ lock btr qword [r8], r12
+%endif
+ ; 0f ba /6 ib BTR reg/memX, imm8 (X != 8) - sans reg dst
+ lock btr word [20cch], 15
+ lock btr word [xBX], 15
+ lock btr word [xDI], 15
+ lock btr dword [20cch], 30
+ lock btr dword [xBX], 30
+ lock btr dword [xDI], 30
+%ifdef WITH_64_BIT_TESTS
+ lock btr qword [20cch], 60
+ lock btr qword [rdx], 60
+ lock btr qword [rdi], 60
+ lock btr qword [r9], 60
+ lock btr qword [r12], 60
+%endif
+
+ ;
+ ; BTS
+ ;
+ ; 0f ab /r BTS reg/memX, regX (X != 8) - sans reg dst
+ lock bts word [20cch], bx
+ lock bts word [xBX], bx
+ lock bts word [xDI], bx
+ lock bts dword [20cch], ebx
+ lock bts dword [xBX], ebx
+ lock bts dword [xDI], ebx
+%if TEST_BITS == 64
+ lock bts qword [20cch], rbx
+ lock bts qword [rdx], rbx
+ lock bts qword [rdi], r10
+ lock bts qword [r8], r12
+%endif
+ ; 0f ba /5 ib BTS reg/memX, imm8 (X != 8) - sans reg dst
+ lock bts word [20cch], 15
+ lock bts word [xBX], 15
+ lock bts word [xDI], 15
+ lock bts dword [20cch], 30
+ lock bts dword [xBX], 30
+ lock bts dword [xDI], 30
+%if TEST_BITS == 64
+ lock bts qword [20cch], 60
+ lock bts qword [rdx], 60
+ lock bts qword [rdi], 60
+ lock bts qword [r9], 60
+ lock bts qword [r12], 60
+%endif
+
+ ;
+ ; CMPXCHG
+ ;
+ ; 0f b0 /r CMPXCHG reg8/mem8, regX - with reg dst
+ lock cmpxchg byte [30cch], cl
+ lock cmpxchg byte [xBX], cl
+ lock cmpxchg byte [xSI], cl
+ ; 0f b1 /r CMPXCHG regX/memX, regX - with reg dst
+ lock cmpxchg word [30cch], cx
+ lock cmpxchg word [xBX], cx
+ lock cmpxchg word [xSI], cx
+ lock cmpxchg dword [30cch], ecx
+ lock cmpxchg dword [xBX], ecx
+ lock cmpxchg dword [xSI], ecx
+%ifdef WITH_64_BIT_TESTS
+ lock cmpxchg qword [30cch], rcx
+ lock cmpxchg qword [xBX], rcx
+ lock cmpxchg qword [xSI], rcx
+ lock cmpxchg qword [rdi], r8
+ lock cmpxchg qword [r12], r9
+%endif
+
+ ;
+ ; CMPXCHG8B
+ ; CMPXCHG16B
+ ;
+ ;; @todo get back to cmpxchg8b and cmpxchg16b.
+ lock cmpxchg8b qword [1000h]
+ lock cmpxchg8b qword [xDI]
+ lock cmpxchg8b qword [xDI+xBX]
+%ifdef WITH_64_BIT_TESTS_CMPXCHG16B
+ lock cmpxchg16b [1000h]
+ lock cmpxchg16b [xDI]
+ lock cmpxchg16b [xDI+xBX]
+%endif
+
+ ;
+ ; DEC
+ ;
+ ; fe /1 DEC reg8/mem8 - sans reg dst
+ lock dec byte [40cch]
+ lock dec byte [xBX]
+ lock dec byte [xSI]
+ ; ff /1 DEC regX/memX - sans reg dst
+ lock dec word [40cch]
+ lock dec word [xBX]
+ lock dec word [xSI]
+ lock dec dword [40cch]
+ lock dec dword [xBX]
+ lock dec dword [xSI]
+%ifdef WITH_64_BIT_TESTS
+ lock dec qword [40cch]
+ lock dec qword [xBX]
+ lock dec qword [xSI]
+ lock dec qword [r8]
+ lock dec qword [r12]
+%endif
+
+ ;
+ ; INC
+ ;
+ ; fe /0 INC reg8/mem8 - sans reg dst
+ lock inc byte [40cch]
+ lock inc byte [xBX]
+ lock inc byte [xSI]
+ ; ff /0 INC regX/memX - sans reg dst
+ lock inc word [40cch]
+ lock inc word [xBX]
+ lock inc word [xSI]
+ lock inc dword [40cch]
+ lock inc dword [xBX]
+ lock inc dword [xSI]
+%ifdef WITH_64_BIT_TESTS
+ lock inc qword [40cch]
+ lock inc qword [xBX]
+ lock inc qword [xSI]
+ lock inc qword [r8]
+ lock inc qword [r12]
+%endif
+
+ ;
+ ; NEG
+ ;
+ ; f6 /3 NEG reg8/mem8 - sans reg dst
+ lock neg byte [40cch]
+ lock neg byte [xBX]
+ lock neg byte [xSI]
+ ; f7 /3 NEG regX/memX - sans reg dst
+ lock neg word [40cch]
+ lock neg word [xBX]
+ lock neg word [xSI]
+ lock neg dword [40cch]
+ lock neg dword [xBX]
+ lock neg dword [xSI]
+%ifdef WITH_64_BIT_TESTS
+ lock neg qword [40cch]
+ lock neg qword [xBX]
+ lock neg qword [xSI]
+ lock neg qword [r8]
+ lock neg qword [r12]
+%endif
+
+ ;
+ ; NOT
+ ;
+ ; f6 /2 NOT reg8/mem8 - sans reg dst
+ lock not byte [40cch]
+ lock not byte [xBX]
+ lock not byte [xSI]
+ ; f7 /2 NOT regX/memX - sans reg dst
+ lock not word [40cch]
+ lock not word [xBX]
+ lock not word [xSI]
+ lock not dword [40cch]
+ lock not dword [xBX]
+ lock not dword [xSI]
+%ifdef WITH_64_BIT_TESTS
+ lock not qword [40cch]
+ lock not qword [xBX]
+ lock not qword [xSI]
+ lock not qword [r8]
+ lock not qword [r12]
+%endif
+
+ ;
+ ; OR
+ ;
+ ; 80 /1 ib OR reg/mem8, imm8 - sans reg dst
+ lock or byte [1000h], byte 8
+ lock or byte [xBX], byte 8
+ lock or byte [xDI], byte 8
+ ; 81 /1 i[wd] OR reg/memX, immX - sans reg dst
+ lock or word [1000h], word 090cch
+ lock or word [xBX], word 090cch
+ lock or word [xDI], word 090cch
+ lock or dword [1000h], dword 0cc90cc90h
+ lock or dword [xBX], dword 0cc90cc90h
+ lock or dword [xDI], dword 0cc90cc90h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock or qword [1000h], dword 0cc90cc90h
+ lock or qword [rbx], dword 0cc90cc90h
+ lock or qword [rdi], dword 0cc90cc90h
+ lock or qword [r9], dword 0cc90cc90h
+%endif
+ ; 83 /1 ib OR reg/memX, imm8 - sans reg dst
+ lock or word [1000h], byte 07fh
+ lock or word [xBX], byte 07fh
+ lock or word [xDI], byte 07fh
+ lock or dword [1000h], byte 07fh
+ lock or dword [xBX], byte 07fh
+ lock or dword [xDI], byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock or qword [1000h], byte 07fh
+ lock or qword [rbx], byte 07fh
+ lock or qword [rdi], byte 07fh
+ lock or qword [r10], byte 07fh
+%endif
+
+ ; 08 /r OR reg/mem8, reg8 - sans reg dst
+ lock or byte [1000h], bl
+ lock or byte [xBX], bl
+ lock or byte [xSI], bl
+ ; 09 /r OR reg/memX, regX - sans reg dst
+ lock or word [1000h], bx
+ lock or word [xBX], bx
+ lock or word [xSI], bx
+ lock or dword [1000h], ebx
+ lock or dword [xBX], ebx
+ lock or dword [xSI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock or qword [1000h], rbx
+ lock or qword [rbx], rbx
+ lock or qword [rsi], rbx
+ lock or qword [r11], rbx
+%endif
+
+ ;
+ ; SBB
+ ;
+ ; 80 /3 ib SBB reg/mem8, imm8 - sans reg dst
+ lock sbb byte [1000h], byte 8
+ lock sbb byte [xBX], byte 8
+ lock sbb byte [xDI], byte 8
+ ; 81 /3 i[wd] SBB reg/memX, immX - sans reg dst
+ lock sbb word [1000h], word 090cch
+ lock sbb word [xBX], word 090cch
+ lock sbb word [xDI], word 090cch
+ lock sbb dword [1000h], dword 0cc90cc90h
+ lock sbb dword [xBX], dword 0cc90cc90h
+ lock sbb dword [xDI], dword 0cc90cc90h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock sbb qword [1000h], dword 0cc90cc90h
+ lock sbb qword [rbx], dword 0cc90cc90h
+ lock sbb qword [rdi], dword 0cc90cc90h
+ lock sbb qword [r9], dword 0cc90cc90h
+%endif
+ ; 83 /3 ib SBB reg/memX, imm8 - sans reg dst
+ lock sbb word [1000h], byte 07fh
+ lock sbb word [xBX], byte 07fh
+ lock sbb word [xDI], byte 07fh
+ lock sbb dword [1000h], byte 07fh
+ lock sbb dword [xBX], byte 07fh
+ lock sbb dword [xDI], byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock sbb qword [1000h], byte 07fh
+ lock sbb qword [rbx], byte 07fh
+ lock sbb qword [rdi], byte 07fh
+ lock sbb qword [r10], byte 07fh
+%endif
+
+ ; 18 /r SBB reg/mem8, reg8 - sans reg dst
+ lock sbb byte [1000h], bl
+ lock sbb byte [xBX], bl
+ lock sbb byte [xSI], bl
+ ; 19 /r SBB reg/memX, regX - sans reg dst
+ lock sbb word [1000h], bx
+ lock sbb word [xBX], bx
+ lock sbb word [xSI], bx
+ lock sbb dword [1000h], ebx
+ lock sbb dword [xBX], ebx
+ lock sbb dword [xSI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock sbb qword [1000h], rbx
+ lock sbb qword [rbx], rbx
+ lock sbb qword [rsi], rbx
+ lock sbb qword [r11], rbx
+%endif
+
+ ;
+ ; SUB
+ ;
+ ; 80 /5 ib SUB reg/mem8, imm8 - sans reg dst
+ lock sub byte [1000h], byte 8
+ lock sub byte [xBX], byte 8
+ lock sub byte [xDI], byte 8
+ ; 81 /5 i[wd] SUB reg/memX, immX - sans reg dst
+ lock sub word [1000h], word 090cch
+ lock sub word [xBX], word 090cch
+ lock sub word [xDI], word 090cch
+ lock sub dword [1000h], dword 0cc90cc90h
+ lock sub dword [xBX], dword 0cc90cc90h
+ lock sub dword [xDI], dword 0cc90cc90h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock sub qword [1000h], dword 0cc90cc90h
+ lock sub qword [rbx], dword 0cc90cc90h
+ lock sub qword [rdi], dword 0cc90cc90h
+ lock sub qword [r9], dword 0cc90cc90h
+%endif
+ ; 83 /5 ib SUB reg/memX, imm8 - sans reg dst
+ lock sub word [1000h], byte 07fh
+ lock sub word [xBX], byte 07fh
+ lock sub word [xDI], byte 07fh
+ lock sub dword [1000h], byte 07fh
+ lock sub dword [xBX], byte 07fh
+ lock sub dword [xDI], byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock sub qword [1000h], byte 07fh
+ lock sub qword [rbx], byte 07fh
+ lock sub qword [rdi], byte 07fh
+ lock sub qword [r10], byte 07fh
+%endif
+
+ ; 28 /r SUB reg/mem8, reg8 - sans reg dst
+ lock sub byte [1000h], bl
+ lock sub byte [xBX], bl
+ lock sub byte [xSI], bl
+ ; 29 /r SUB reg/memX, regX - sans reg dst
+ lock sub word [1000h], bx
+ lock sub word [xBX], bx
+ lock sub word [xSI], bx
+ lock sub dword [1000h], ebx
+ lock sub dword [xBX], ebx
+ lock sub dword [xSI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock sub qword [1000h], rbx
+ lock sub qword [rbx], rbx
+ lock sub qword [rsi], rbx
+ lock sub qword [r11], rbx
+%endif
+
+ ;
+ ; XADD
+ ;
+ ; 0f c0 /r XADD reg/mem8, reg8 - sans reg dst
+ lock xadd byte [1000h], bl
+ lock xadd byte [xBX], bl
+ lock xadd byte [xDI], bl
+ ; 0f c1 /r XADD reg/memX, immX - sans reg dst
+ lock xadd word [1000h], cx
+ lock xadd word [xBX], cx
+ lock xadd word [xDI], cx
+ lock xadd dword [1000h], edx
+ lock xadd dword [xBX], edx
+ lock xadd dword [xDI], edx
+%ifdef WITH_64_BIT_TESTS
+ lock xadd qword [1000h], rbx
+ lock xadd qword [xBX], rbx
+ lock xadd qword [xDI], rbx
+ lock xadd qword [r8], rbx
+ lock xadd qword [r12], r8
+%endif
+
+ ;
+ ; XCHG
+ ;
+ ; Note: The operands can be switched around but the
+ ; encoding is the same.
+ ;
+ ; 86 /r XCHG reg/mem8, imm8 - sans reg dst
+ lock xchg byte [80cch], bl
+ lock xchg byte [xBX], bl
+ lock xchg byte [xSI], bl
+%ifdef WITH_64_BIT_TESTS_BORKED_REGS
+ lock xchg byte [rsi], r15b ; turns into r15l which yasm doesn't grok
+ lock xchg byte [r8], r15b ; ditto
+%endif
+ ; 87 /r XCHG reg/memX, immX - sans reg dst
+ lock xchg word [80cch], bx
+ lock xchg word [xBX], bx
+ lock xchg word [xSI], bx
+ lock xchg dword [80cch], ebx
+ lock xchg dword [xBX], ebx
+ lock xchg dword [xSI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock xchg qword [80cch], rbx
+ lock xchg qword [xBX], rbx
+ lock xchg qword [xSI], rbx
+ lock xchg qword [xSI], r15
+ %ifdef WITH_64_BIT_TESTS_BORKED_REGS
+ lock xchg dword [xSI], r15d ; turns into rdi
+ lock xchg word [xSI], r15w ; turns into rdi
+ %endif
+%endif
+
+ ;
+ ; XOR
+ ;
+ ; 80 /6 ib XOR reg/mem8, imm8 - sans reg dst
+ lock xor byte [1000h], byte 8
+ lock xor byte [xBX], byte 8
+ lock xor byte [xDI], byte 8
+ ; 81 /6 i[wd] XOR reg/memX, immX - sans reg dst
+ lock xor word [1000h], word 090cch
+ lock xor word [xBX], word 090cch
+ lock xor word [xDI], word 090cch
+ lock xor dword [1000h], dword 0cc90cc90h
+ lock xor dword [xBX], dword 0cc90cc90h
+ lock xor dword [xDI], dword 0cc90cc90h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock xor qword [1000h], dword 0cc90cc90h
+ lock xor qword [rbx], dword 0cc90cc90h
+ lock xor qword [rdi], dword 0cc90cc90h
+ lock xor qword [r9], dword 0cc90cc90h
+%endif
+ ; 83 /6 ib XOR reg/memX, imm8 - sans reg dst
+ lock xor word [1000h], byte 07fh
+ lock xor word [xBX], byte 07fh
+ lock xor word [xDI], byte 07fh
+ lock xor dword [1000h], byte 07fh
+ lock xor dword [xBX], byte 07fh
+ lock xor dword [xDI], byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock xor qword [1000h], byte 07fh
+ lock xor qword [rbx], byte 07fh
+ lock xor qword [rdi], byte 07fh
+ lock xor qword [r10], byte 07fh
+%endif
+
+ ; 30 /r XOR reg/mem8, reg8 - sans reg dst
+ lock xor byte [1000h], bl
+ lock xor byte [xBX], bl
+ lock xor byte [xSI], bl
+ ; 31 /r XOR reg/memX, regX - sans reg dst
+ lock xor word [1000h], bx
+ lock xor word [xBX], bx
+ lock xor word [xSI], bx
+ lock xor dword [1000h], ebx
+ lock xor dword [xBX], ebx
+ lock xor dword [xSI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock xor qword [1000h], rbx
+ lock xor qword [rbx], rbx
+ lock xor qword [rsi], rbx
+ lock xor qword [r11], rbx
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmLock-2.asm b/src/VBox/Disassembler/testcase/tstAsmLock-2.asm
new file mode 100644
index 00000000..856ede15
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmLock-2.asm
@@ -0,0 +1,537 @@
+; $Id: tstAsmLock-2.asm $
+;; @file
+; Disassembly testcase - Invalid invariants.
+;
+; The intention is to check in a binary using the --all-invalid mode
+; of tstDisasm-2.
+;
+; There are some regX, reg/memX variations that aren't tested as
+; they would require db'ing out the instructions (12 /r and 13 /r
+; for instance).
+;
+
+;
+; Copyright (C) 2008-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+%include "tstAsm.mac"
+%if TEST_BITS == 64
+; The disassembler doesn't do imm32 right for 64-bit stuff, so disable it for now.
+; %define WITH_64_BIT_TESTS_IMM32
+ %define WITH_64_BIT_TESTS
+%endif
+
+ BITS TEST_BITS
+
+ ;
+ ; ADC
+ ;
+ ; 14 ib ADC AL, imm8
+ lock adc al, byte 8
+ ; 15 i[wd] ADC [ER]AX, immX
+ lock adc ax, word 16
+ lock adc eax, dword 128
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock adc rax, dword 256
+ lock adc rax, dword 0cc90cc90h
+%endif
+ ; 80 /2 ib ADC reg/mem8, imm8 - with reg dst
+ lock adc cl, byte 8
+ ; 81 /2 i[wd] ADC reg/memX, immX - with reg dst
+ lock adc cx, word 1000h
+ lock adc ecx, dword 100000h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock adc rcx, dword 100000h
+%endif
+ ; 83 /2 ib ADC reg/memX, imm8 - with reg dst
+ lock adc cx, byte 07fh
+ lock adc ecx, byte 07fh
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock adc rcx, byte 07fh
+%endif
+
+ ; 10 /r ADC reg/mem8, reg8 - with reg dst
+ lock adc cl, bl
+ ; 11 /r ADC reg/memX, regX - with reg dst
+ lock adc cx, bx
+ lock adc ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock adc rcx, rbx
+%endif
+ ; 12 /r ADC reg8, reg/mem8
+ lock adc cl, [0badh]
+ ; 13 /r ADC regX, reg/memX
+ lock adc cx, [0badh]
+ lock adc ecx, [0badh]
+%ifdef WITH_64_BIT_TESTS
+ lock adc rcx, [0badh]
+%endif
+
+ ;
+ ; ADD
+ ;
+ ; 04 ib ADD AL, imm8
+ lock add al, byte 8
+ ; 05 i[wd] ADD [ER]AX, immX
+ lock add ax, word 16
+ lock add eax, dword 128
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock add rax, dword 256
+ lock add rax, dword 0cc90cc90h
+%endif
+ ; 80 /0 ib ADD reg/mem8, imm8 - with reg dst
+ lock add cl, byte 8
+ ; 81 /0 i[wd] ADD reg/memX, immX - with reg dst
+ lock add cx, word 1000h
+ lock add ecx, dword 100000h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock add rcx, dword 100000h
+%endif
+ ; 83 /0 ib ADD reg/memX, imm8 - with reg dst
+ lock add cx, byte 07fh
+ lock add ecx, byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock add rcx, byte 07fh
+%endif
+
+ ; 00 /r ADD reg/mem8, reg8 - with reg dst
+ lock add cl, bl
+ ; 01 /r ADD reg/memX, regX - with reg dst
+ lock add cx, bx
+ lock add ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock add rcx, rbx
+%endif
+ ; 02 /r ADD reg8, reg/mem8
+ lock add cl, [0badh]
+ ; 03 /r ADD regX, reg/memX
+ lock add cx, [0badh]
+ lock add ecx, [0badh]
+%ifdef WITH_64_BIT_TESTS
+ lock add rcx, [0badh]
+%endif
+
+ ;
+ ; AND
+ ;
+ ; 24 ib AND AL, imm8
+ lock and al, byte 8
+ ; 25 i[wd] AND [ER]AX, immX
+ lock and ax, word 16
+ lock and eax, dword 128
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock and rax, dword 256
+ lock and rax, dword 0cc90cc90h
+%endif
+ ; 80 /4 ib AND reg/mem8, imm8 - with reg dst
+ lock and cl, byte 8
+ ; 81 /4 i[wd] AND reg/memX, immX - with reg dst
+ lock and cx, word 1000h
+ lock and ecx, dword 100000h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock and rcx, dword 100000h
+%endif
+ ; 83 /4 ib AND reg/memX, imm8 - with reg dst
+ lock and cx, byte 07fh
+ lock and ecx, byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock and rcx, byte 07fh
+%endif
+
+ ; 20 /r AND reg/mem8, reg8 - with reg dst
+ lock and cl, bl
+ ; 21 /r AND reg/memX, regX - with reg dst
+ lock and cx, bx
+ lock and ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock and rcx, rbx
+%endif
+ ; 22 /r AND reg8, reg/mem8
+ lock and cl, [0badh]
+ ; 23 /r AND regX, reg/memX
+ lock and cx, [0badh]
+ lock and ecx, [0badh]
+%ifdef WITH_64_BIT_TESTS
+ lock and rcx, [0badh]
+%endif
+
+ ;
+ ; BTC
+ ;
+ ; 0f bb /r BTC reg/memX, regX (X != 8) - with reg dst
+ lock btc cx, bx
+ lock btc ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock btc rcx, rbx
+ lock btc r8, rbx
+ lock btc r10, r8
+%endif
+ ; 0f ba /7 ib BTC reg/memX, imm8 (X != 8) - with reg dst
+ lock btc cx, 15
+ lock btc ecx, 30
+%ifdef WITH_64_BIT_TESTS
+ lock btc rcx, 60
+ lock btc r8, 61
+ lock btc r10, 3
+%endif
+
+ ;
+ ; BTR
+ ;
+ ; 0f b3 /r BTR reg/memX, regX (X != 8) - with reg dst
+ lock btr cx, bx
+ lock btr ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock btr rcx, rbx
+ lock btr r8, rbx
+ lock btr r10, r8
+%endif
+ ; 0f ba /6 ib BTR reg/memX, imm8 (X != 8) - with reg dst
+ lock btr cx, 15
+ lock btr ecx, 30
+%ifdef WITH_64_BIT_TESTS
+ lock btr rcx, 60
+ lock btr r8, 61
+ lock btr r10, 3
+%endif
+
+ ;
+ ; BTS
+ ;
+ ; 0f ab /r BTS reg/memX, regX (X != 8) - with reg dst
+ lock bts cx, bx
+ lock bts ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock bts rcx, rbx
+ lock bts r8, rbx
+ lock bts r10, r8
+%endif
+ ; 0f ba /5 ib BTS reg/memX, imm8 (X != 8) - with reg dst
+ lock bts cx, 15
+ lock bts ecx, 30
+%ifdef WITH_64_BIT_TESTS
+ lock bts rcx, 60
+ lock bts r8, 61
+ lock bts r10, 3
+%endif
+
+ ;
+ ; CMPXCHG
+ ;
+ ; 0f b0 /r CMPXCHG reg8/mem8, regX - with reg dst
+ lock cmpxchg bl, cl
+ ; 0f b1 /r CMPXCHG regX/memX, regX - with reg dst
+ lock cmpxchg bx, cx
+ lock cmpxchg ebx, ecx
+%ifdef WITH_64_BIT_TESTS
+ lock cmpxchg rbx, rcx
+%endif
+
+ ;
+ ; CMPXCHG8B
+ ; CMPXCHG16B
+ ;
+ ; all valid.
+
+ ;
+ ; DEC
+ ;
+ ; fe /1 DEC reg8/mem8 - with reg dst
+ lock dec bl
+ ; ff /1 DEC regX/memX - with reg dst
+
+%if TEST_BITS != 64 ; cannot force these two in 32 and 16 bit mode.
+ db 066h, 0f0h, 0ffh, 0cbh
+ db 0f0h, 0ffh, 0cbh
+%else
+ lock dec bx
+ lock dec ebx
+ %ifdef WITH_64_BIT_TESTS
+ lock dec rbx
+ lock dec r8
+ lock dec r14
+ %endif
+%endif
+%if TEST_BITS != 64
+ ; 48 +rw DEC reg16
+ lock dec dx
+ ; 48 +rd DEC reg32
+ lock dec edx
+%endif
+
+ ;
+ ; INC
+ ;
+ ; fe /1 INC reg8/mem8 - with reg dst
+ lock inc bl
+ ; ff /1 INC regX/memX - with reg dst
+
+%if TEST_BITS != 64 ; cannot force these two in 32 and 16 bit mode.
+ db 066h, 0f0h, 0ffh, 0c3h
+ db 0f0h, 0ffh, 0c3h
+%else
+ lock inc bx
+ lock inc ebx
+ %ifdef WITH_64_BIT_TESTS
+ lock inc rbx
+ lock inc r8
+ lock inc r14
+ %endif
+%endif
+%if TEST_BITS != 64
+ ; 48 +rw INC reg16
+ lock inc dx
+ ; 48 +rd INC reg32
+ lock inc edx
+%endif
+
+ ;
+ ; NEG
+ ;
+ ; f6 /3 NEG reg8/mem8 - with reg dst
+ lock neg bl
+ ; f7 /3 NEG regX/memX - with reg dst
+ lock neg bx
+ lock neg ebx
+%ifdef WITH_64_BIT_TESTS
+ lock neg rbx
+ lock neg r8
+ lock neg r14
+%endif
+
+ ;
+ ; NOT
+ ;
+ ; f6 /2 NOT reg8/mem8 - with reg dst
+ lock not bl
+ ; f7 /2 NOT regX/memX - with reg dst
+ lock not bx
+ lock not ebx
+%ifdef WITH_64_BIT_TESTS
+ lock not rbx
+ lock not r8
+ lock not r14
+%endif
+
+ ;
+ ; OR
+ ;
+ ; 0C ib OR AL, imm8
+ lock or al, byte 8
+ ; 0D i[wd] OR [ER]AX, immX
+ lock or ax, word 16
+ lock or eax, dword 128
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock or rax, dword 256
+ lock or rax, dword 0cc90cc90h
+%endif
+ ; 80 /1 ib OR reg/mem8, imm8 - with reg dst
+ lock or cl, byte 8
+ ; 81 /1 i[wd] OR reg/memX, immX - with reg dst
+ lock or cx, word 1000h
+ lock or ecx, dword 100000h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock or rcx, dword 100000h
+%endif
+ ; 83 /1 ib OR reg/memX, imm8 - with reg dst
+ lock or cx, byte 07fh
+ lock or ecx, byte 07fh
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock or rcx, byte 07fh
+%endif
+ ; 08 /r OR reg/mem8, reg8 - with reg dst
+ lock or cl, bl
+ ; 09 /r OR reg/memX, regX - with reg dst
+ lock or cx, bx
+ lock or ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock or rcx, rbx
+%endif
+ ; 0A /r OR reg8, reg/mem8
+ lock or cl, [0badh]
+ ; 0B /r OR regX, reg/memX
+ lock or cx, [0badh]
+ lock or ecx, [0badh]
+%ifdef WITH_64_BIT_TESTS
+ lock or rcx, [0badh]
+%endif
+
+ ;
+ ; SBB
+ ;
+ ; 1C ib SBB AL, imm8
+ lock sbb al, byte 8
+ ; 1D i[wd] SBB [ER]AX, immX
+ lock sbb ax, word 16
+ lock sbb eax, dword 128
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock sbb rax, dword 256
+ lock sbb rax, dword 0cc90cc90h
+%endif
+ ; 80 /3 ib SBB reg/mem8, imm8 - with reg dst
+ lock sbb cl, byte 8
+ ; 81 /3 i[wd] SBB reg/memX, immX - with reg dst
+ lock sbb cx, word 1000h
+ lock sbb ecx, dword 100000h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock sbb rcx, dword 100000h
+%endif
+ ; 83 /3 ib SBB reg/memX, imm8 - with reg dst
+ lock sbb cx, byte 07fh
+ lock sbb ecx, byte 07fh
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock sbb rcx, byte 07fh
+%endif
+ ; 18 /r SBB reg/mem8, reg8 - with reg dst
+ lock sbb cl, bl
+ ; 19 /r SBB reg/memX, regX - with reg dst
+ lock sbb cx, bx
+ lock sbb ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock sbb rcx, rbx
+%endif
+ ; 1A /r SBB reg8, reg/mem8
+ lock sbb cl, [0badh]
+ ; 1B /r SBB regX, reg/memX
+ lock sbb cx, [0badh]
+ lock sbb ecx, [0badh]
+%ifdef WITH_64_BIT_TESTS
+ lock sbb rcx, [0badh]
+%endif
+
+ ;
+ ; SUB
+ ;
+ ; 2C ib SUB AL, imm8
+ lock sub al, byte 8
+ ; 2D i[wd] SUB [ER]AX, immX
+ lock sub ax, word 16
+ lock sub eax, dword 128
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock sub rax, dword 256
+ lock sub rax, dword 0cc90cc90h
+%endif
+ ; 80 /5 ib SUB reg/mem8, imm8 - with reg dst
+ lock sub cl, byte 8
+ ; 81 /5 i[wd] SUB reg/memX, immX - with reg dst
+ lock sub cx, word 1000h
+ lock sub ecx, dword 100000h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock sub rcx, dword 100000h
+%endif
+ ; 83 /5 ib SUB reg/memX, imm8 - with reg dst
+ lock sub cx, byte 07fh
+ lock sub ecx, byte 07fh
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock sub rcx, byte 07fh
+%endif
+ ; 28 /r SUB reg/mem8, reg8 - with reg dst
+ lock sub cl, bl
+ ; 29 /r SUB reg/memX, regX - with reg dst
+ lock sub cx, bx
+ lock sub ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock sub rcx, rbx
+%endif
+ ; 2A /r SUB reg8, reg/mem8
+ lock sub cl, [0badh]
+ ; 2B /r SUB regX, reg/memX
+ lock sub cx, [0badh]
+ lock sub ecx, [0badh]
+%ifdef WITH_64_BIT_TESTS
+ lock sub rcx, [0badh]
+%endif
+
+ ;
+ ; XADD
+ ;
+ ; 0f c0 /r XADD reg/mem8, reg8 - with reg dst
+ lock xadd al, bl
+ ; 0f c1 /r XADD reg/memX, immX - with reg dst
+ lock xadd cx, bx
+ lock xadd ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock xadd rcx, rbx
+ lock xadd r8, rbx
+ lock xadd r10, r8
+%endif
+
+ ;
+ ; XCHG
+ ;
+ ; Note: The operands can be switched around but the
+ ; encoding is the same.
+ ;
+ ; 90 +r[wdq] XCHG [RE]ax, regX
+ lock xchg ax, bx
+ lock xchg eax, ecx
+%ifdef WITH_64_BIT_TESTS
+ lock xchg rax, rcx
+ lock xchg rax, r10
+%endif
+ ; 86 /r XCHG reg/mem8, imm8 - with reg dst
+ lock xchg al, bl
+%ifdef WITH_64_BIT_TESTS
+ lock xchg r10b, cl
+ lock xchg r10b, r15b
+%endif
+ ; 87 /r XCHG reg/memX, immX - with reg dst
+ lock xchg ax, bx
+ lock xchg eax, ebx
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock xchg rax, rbx
+ lock xchg r12, rbx
+ lock xchg r14, r8
+%endif
+
+ ;
+ ; XOR
+ ;
+ ; 34 ib XOR AL, imm8
+ lock xor al, byte 8
+ ; 35 i[wd] XOR [ER]AX, immX
+ lock xor ax, word 16
+ lock xor eax, dword 128
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock xor rax, dword 256
+ lock xor rax, dword 0cc90cc90h
+%endif
+ ; 80 /6 ib XOR reg/mem8, imm8 - with reg dst
+ lock xor cl, byte 8
+ ; 81 /6 i[wd] XOR reg/memX, immX - with reg dst
+ lock xor cx, word 1000h
+ lock xor ecx, dword 100000h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock xor rcx, dword 100000h
+%endif
+ ; 83 /6 ib XOR reg/memX, imm8 - with reg dst
+ lock xor cx, byte 07fh
+ lock xor ecx, byte 07fh
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock xor rcx, byte 07fh
+%endif
+ ; 30 /r XOR reg/mem8, reg8 - with reg dst
+ lock xor cl, bl
+ ; 31 /r XOR reg/memX, regX - with reg dst
+ lock xor cx, bx
+ lock xor ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock xor rcx, rbx
+%endif
+ ; 32 /r XOR reg8, reg/mem8
+ lock xor cl, [0badh]
+ ; 33 /r XOR regX, reg/memX
+ lock xor cx, [0badh]
+ lock xor ecx, [0badh]
+%ifdef WITH_64_BIT_TESTS
+ lock xor rcx, [0badh]
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmLock-3.asm b/src/VBox/Disassembler/testcase/tstAsmLock-3.asm
new file mode 100644
index 00000000..9dade6ae
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmLock-3.asm
@@ -0,0 +1,46 @@
+; $Id: tstAsmLock-3.asm $
+;; @file
+; Disassembly testcase - Invalid lock sequences for non-locking instructions.
+;
+; The intention is to check in a binary using the --all-invalid mode
+; of tstDisasm-2.
+;
+
+;
+; Copyright (C) 2008-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+%include "tstAsm.mac"
+
+ BITS TEST_BITS
+
+ lock mov ebp, esp
+ lock mov byte [0], 0
+ lock mov word [0], 0
+ lock mov dword [0], 0
+ lock mov word [0], 01234h
+ lock mov dword [0], 012348765h
+ lock mov byte [ebx], 0
+ lock mov [ebx], eax
+ lock mov [ebx], ax
+ lock mov [ebx], al
+ lock mov [ebx], edx
+ lock mov [ebx], dx
+ lock mov [ebx], dl
+ lock ret
+%if TEST_BITS != 64
+ lock pop ebp
+ lock push esp
+%else
+ lock pop rbp
+ lock push rsp
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmMovFixedReg-1.asm b/src/VBox/Disassembler/testcase/tstAsmMovFixedReg-1.asm
new file mode 100644
index 00000000..8f22024d
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmMovFixedReg-1.asm
@@ -0,0 +1,103 @@
+; $Id: tstAsmMovFixedReg-1.asm $
+;; @file
+; Disassembly testcase - Valid mov immediate to fixed registers.
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2013-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+ BITS TEST_BITS
+
+ mov al, 01h
+ mov cl, 02h
+ mov dl, 03h
+ mov bl, 04h
+ mov ah, 05h
+ mov ch, 06h
+ mov dh, 07h
+ mov bh, 08h
+%if TEST_BITS == 64
+ mov spl, 09h
+ mov bpl, 0ah
+ mov sil, 0bh
+ mov dil, 0ch
+ mov r8b, 0dh
+ mov r9b, 0eh
+ mov r10b, 0fh
+ mov r11b, 010h
+ mov r12b, 011h
+ mov r13b, 012h
+ mov r14b, 013h
+ mov r15b, 014h
+%endif
+
+ mov ax, 0f701h
+ mov cx, 0f702h
+ mov dx, 0f703h
+ mov bx, 0f704h
+ mov sp, 0f705h
+ mov bp, 0f706h
+ mov si, 0f707h
+ mov di, 0f708h
+%if TEST_BITS == 64
+ mov r8w, 0f709h
+ mov r9w, 0f70ah
+ mov r10w, 0f70bh
+ mov r11w, 0f70ch
+ mov r12w, 0f70dh
+ mov r13w, 0f70eh
+ mov r14w, 0f70fh
+ mov r15w, 0f710h
+%endif
+
+ mov eax, 0beeff701h
+ mov ecx, 0beeff702h
+ mov edx, 0beeff703h
+ mov ebx, 0beeff704h
+ mov esp, 0beeff705h
+ mov ebp, 0beeff706h
+ mov esi, 0beeff707h
+ mov edi, 0beeff708h
+%if TEST_BITS == 64
+ mov r8d, 0beeff709h
+ mov r9d, 0beeff70ah
+ mov r10d, 0beeff70bh
+ mov r11d, 0beeff70ch
+ mov r12d, 0beeff70dh
+ mov r13d, 0beeff70eh
+ mov r14d, 0beeff70fh
+ mov r15d, 0beeff710h
+%endif
+
+%if TEST_BITS == 64
+ mov rax, 0feedbabef00df701h
+ mov rcx, 0feedbabef00df702h
+ mov rdx, 0feedbabef00df703h
+ mov rbx, 0feedbabef00df704h
+ mov rsp, 0feedbabef00df705h
+ mov rbp, 0feedbabef00df706h
+ mov rsi, 0feedbabef00df707h
+ mov rdi, 0feedbabef00df708h
+ mov r8, 0feedbabef00df709h
+ mov r9, 0feedbabef00df70ah
+ mov r10, 0feedbabef00df70bh
+ mov r11, 0feedbabef00df70ch
+ mov r12, 0feedbabef00df70dh
+ mov r13, 0feedbabef00df70eh
+ mov r14, 0feedbabef00df70fh
+ mov r15, 0feedbabef00df710h
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmMovSeg-1.asm b/src/VBox/Disassembler/testcase/tstAsmMovSeg-1.asm
new file mode 100644
index 00000000..c47837c4
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmMovSeg-1.asm
@@ -0,0 +1,48 @@
+; $Id: tstAsmMovSeg-1.asm $
+;; @file
+; Disassembly testcase - Valid mov from/to segment instructions.
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2008-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+ BITS TEST_BITS
+
+ mov fs, eax
+ mov fs, ax
+%if TEST_BITS == 64
+ mov fs, rax
+%endif
+
+ mov fs, [ebx]
+%if TEST_BITS != 64
+ mov fs, [bx]
+%else
+ mov fs, [rbx]
+%endif
+
+ mov ax, fs
+ mov eax, fs
+%if TEST_BITS == 64
+ mov rax, fs
+%endif
+
+ mov [ebx], fs
+%if TEST_BITS != 64
+ mov [bx], fs
+%else
+ mov [rbx], fs
+%endif
diff --git a/src/VBox/Disassembler/testcase/tstAsmMovzx-1.asm b/src/VBox/Disassembler/testcase/tstAsmMovzx-1.asm
new file mode 100644
index 00000000..a48761e0
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmMovzx-1.asm
@@ -0,0 +1,39 @@
+; $Id: tstAsmMovzx-1.asm $
+;; @file
+; Disassembly testcase - Valid movzx sequences and related instructions.
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2008-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+ BITS TEST_BITS
+
+ movzx ax, al
+ movzx eax, al
+ movzx ax, [ebx]
+ movzx eax, byte [ebx]
+ movzx eax, word [ebx]
+%if TEST_BITS != 64
+ movzx ax, [bx+si+8]
+ movzx eax, byte [bx+si+8]
+ movzx eax, word [bx+si+8]
+%else
+ movzx rax, al
+ movzx rax, ax
+ movzx rax, byte [rsi]
+ movzx rax, word [rsi]
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmPop-1.asm b/src/VBox/Disassembler/testcase/tstAsmPop-1.asm
new file mode 100644
index 00000000..fdad13e5
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmPop-1.asm
@@ -0,0 +1,36 @@
+; $Id: tstAsmPop-1.asm $
+;; @file
+; Disassembly testcase - Valid pop sequences and related instructions.
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2008-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+ BITS TEST_BITS
+%if TEST_BITS != 64
+ pop bp
+ pop ebp
+ pop word [bp]
+ pop dword [bp]
+ pop word [ebp]
+ pop dword [ebp]
+%else
+ %if 0 ; doesn't work yet
+ pop rbp
+ pop qword [rbp]
+ %endif
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmPush-1.asm b/src/VBox/Disassembler/testcase/tstAsmPush-1.asm
new file mode 100644
index 00000000..fdd97270
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmPush-1.asm
@@ -0,0 +1,36 @@
+; $Id: tstAsmPush-1.asm $
+;; @file
+; Disassembly testcase - Valid push sequences and related instructions.
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2008-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+ BITS TEST_BITS
+%if TEST_BITS != 64
+ push bp
+ push ebp
+ push word [bp]
+ push dword [bp]
+ push word [ebp]
+ push dword [ebp]
+%else
+ %if 0 ; doesn't work yet - default operand size is wrong?
+ push rbp
+ push qword [rbp]
+ %endif
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmRegs-1.asm b/src/VBox/Disassembler/testcase/tstAsmRegs-1.asm
new file mode 100644
index 00000000..74f135ca
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmRegs-1.asm
@@ -0,0 +1,109 @@
+; $Id: tstAsmRegs-1.asm $
+;; @file
+; Disassembly testcase - Accessing all the registers
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2008-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+%include "tstAsm.mac"
+
+ BITS TEST_BITS
+
+ ;; @todo
+ ; Missing a bunch of permutations and encoding variants
+ ;
+
+ mov al, al
+ mov al, ah
+ mov al, bl
+ mov al, bh
+ mov al, cl
+ mov al, ch
+ mov al, dl
+ mov al, dh
+%if TEST_BITS == 64
+ mov al, dil
+ mov al, sil
+ mov al, bpl
+ mov al, spl
+ mov al, r8b
+ mov al, r9b
+ mov al, r10b
+ mov al, r11b
+ mov al, r12b
+ mov al, r13b
+ mov al, r14b
+ mov al, r15b
+%endif
+
+ mov ax, ax
+ mov ax, bx
+ mov ax, cx
+ mov ax, dx
+ mov ax, si
+ mov ax, di
+ mov ax, bp
+ mov ax, sp
+%if TEST_BITS == 64
+ mov ax, r8w
+ mov ax, r9w
+ mov ax, r10w
+ mov ax, r11w
+ mov ax, r12w
+ mov ax, r13w
+ mov ax, r14w
+ mov ax, r15w
+%endif
+
+ mov eax, eax
+ mov eax, ebx
+ mov eax, ecx
+ mov eax, edx
+ mov eax, esi
+ mov eax, edi
+ mov eax, ebp
+ mov eax, esp
+%if TEST_BITS == 64
+ mov eax, r8d
+ mov eax, r9d
+ mov eax, r10d
+ mov eax, r11d
+ mov eax, r12d
+ mov eax, r13d
+ mov eax, r14d
+ mov eax, r15d
+%endif
+
+%if TEST_BITS == 64
+ mov rax, rax
+ mov rax, rbx
+ mov rax, rcx
+ mov rax, rdx
+ mov rax, rsi
+ mov rax, rdi
+ mov rax, rbp
+ mov rax, rsp
+ mov rax, r8
+ mov rax, r9
+ mov rax, r10
+ mov rax, r11
+ mov rax, r12
+ mov rax, r13
+ mov rax, r14
+ mov rax, r15
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmSignExtend-1.asm b/src/VBox/Disassembler/testcase/tstAsmSignExtend-1.asm
new file mode 100644
index 00000000..4553ef26
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmSignExtend-1.asm
@@ -0,0 +1,53 @@
+; $Id: tstAsmSignExtend-1.asm $
+;; @file
+; Disassembly testcase - Valid sign extension instructions.
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2008-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+%include "tstAsm.mac"
+ BITS TEST_BITS
+
+ movsx ax, al
+ movsx eax, al
+ movsx eax, ax
+
+ ;
+ ; ParseImmByteSX
+ ;
+
+ ; 83 /x
+ add eax, strict byte 8
+ add eax, strict byte -1
+ cmp ebx, strict byte -1
+
+ add ax, strict byte 8
+ add ax, strict byte -1
+ cmp bx, strict byte -1
+
+%if TEST_BITS == 64 ; check that these come out with qword values and not words or dwords.
+ add rax, strict byte 8
+ add rax, strict byte -1
+ cmp rbx, strict byte -1
+%endif
+
+ ; push %Ib
+ push strict byte -1
+ push strict byte -128
+ push strict byte 127
+
+ ;; @todo imul
diff --git a/src/VBox/Disassembler/testcase/tstBinFnstsw-1.bin b/src/VBox/Disassembler/testcase/tstBinFnstsw-1.bin
new file mode 100644
index 00000000..b23f6031
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstBinFnstsw-1.bin
Binary files differ
diff --git a/src/VBox/Disassembler/testcase/tstBinMovzx-1.bin b/src/VBox/Disassembler/testcase/tstBinMovzx-1.bin
new file mode 100644
index 00000000..e6db7adf
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstBinMovzx-1.bin
@@ -0,0 +1 @@
+·@ \ No newline at end of file
diff --git a/src/VBox/Disassembler/testcase/tstDisasm-1.cpp b/src/VBox/Disassembler/testcase/tstDisasm-1.cpp
new file mode 100644
index 00000000..8781f5c4
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstDisasm-1.cpp
@@ -0,0 +1,190 @@
+/* $Id: tstDisasm-1.cpp $ */
+/** @file
+ * VBox disassembler - Test application
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <VBox/dis.h>
+#include <iprt/test.h>
+#include <iprt/ctype.h>
+#include <iprt/string.h>
+#include <iprt/errcore.h>
+#include <iprt/time.h>
+
+
+DECLASM(int) TestProc32(void);
+DECLASM(int) TestProc32_EndProc(void);
+#ifndef RT_OS_OS2
+DECLASM(int) TestProc64(void);
+DECLASM(int) TestProc64_EndProc(void);
+#endif
+//uint8_t aCode16[] = { 0x66, 0x67, 0x89, 0x07 };
+
+static void testDisas(const char *pszSub, uint8_t const *pabInstrs, uintptr_t uEndPtr, DISCPUMODE enmDisCpuMode)
+{
+ RTTestISub(pszSub);
+ size_t const cbInstrs = uEndPtr - (uintptr_t)pabInstrs;
+ for (size_t off = 0; off < cbInstrs;)
+ {
+ uint32_t const cErrBefore = RTTestIErrorCount();
+ uint32_t cb = 1;
+ DISSTATE Dis;
+ char szOutput[256] = {0};
+ int rc = DISInstrToStr(&pabInstrs[off], enmDisCpuMode, &Dis, &cb, szOutput, sizeof(szOutput));
+
+ RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
+ RTTESTI_CHECK(cb == Dis.cbInstr);
+ RTTESTI_CHECK(cb > 0);
+ RTTESTI_CHECK(cb <= 16);
+ RTStrStripR(szOutput);
+ RTTESTI_CHECK(szOutput[0]);
+ if (szOutput[0])
+ {
+ char *pszBytes = strchr(szOutput, '[');
+ RTTESTI_CHECK(pszBytes);
+ if (pszBytes)
+ {
+ RTTESTI_CHECK(pszBytes[-1] == ' ');
+ RTTESTI_CHECK(RT_C_IS_XDIGIT(pszBytes[1]));
+ RTTESTI_CHECK(pszBytes[cb * 3] == ']');
+ RTTESTI_CHECK(pszBytes[cb * 3 + 1] == ' ');
+
+ size_t cch = strlen(szOutput);
+ RTTESTI_CHECK(szOutput[cch - 1] != ',');
+ }
+ }
+ if (cErrBefore != RTTestIErrorCount())
+ RTTestIFailureDetails("rc=%Rrc, off=%#x (%u) cbInstr=%u enmDisCpuMode=%d\n",
+ rc, off, off, Dis.cbInstr, enmDisCpuMode);
+ RTTestIPrintf(RTTESTLVL_ALWAYS, "%s\n", szOutput);
+
+ /* Check with size-only. */
+ uint32_t cbOnly = 1;
+ DISSTATE DisOnly;
+ rc = DISInstrWithPrefetchedBytes((uintptr_t)&pabInstrs[off], enmDisCpuMode, 0 /*fFilter - none */,
+ Dis.abInstr, Dis.cbCachedInstr, NULL, NULL, &DisOnly, &cbOnly);
+
+ RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
+ RTTESTI_CHECK(cbOnly == DisOnly.cbInstr);
+ RTTESTI_CHECK_MSG(cbOnly == cb, ("%#x vs %#x\n", cbOnly, cb));
+
+ off += cb;
+ }
+}
+
+
+static DECLCALLBACK(int) testReadBytes(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
+{
+ RT_NOREF1(cbMinRead);
+ memcpy(&pDis->abInstr[offInstr], (void *)((uintptr_t)pDis->uInstrAddr + offInstr), cbMaxRead);
+ pDis->cbCachedInstr = offInstr + cbMaxRead;
+ return VINF_SUCCESS;
+}
+
+
+static void testPerformance(const char *pszSub, uint8_t const *pabInstrs, uintptr_t uEndPtr, DISCPUMODE enmDisCpuMode)
+{
+ RTTestISubF("Performance - %s", pszSub);
+
+ size_t const cbInstrs = uEndPtr - (uintptr_t)pabInstrs;
+ uint64_t cInstrs = 0;
+ uint64_t nsStart = RTTimeNanoTS();
+ for (uint32_t i = 0; i < _512K; i++) /* the samples are way to small. :-) */
+ {
+ for (size_t off = 0; off < cbInstrs; cInstrs++)
+ {
+ uint32_t cb = 1;
+ DISSTATE Dis;
+ DISInstrWithReader((uintptr_t)&pabInstrs[off], enmDisCpuMode, testReadBytes, NULL, &Dis, &cb);
+ off += cb;
+ }
+ }
+ uint64_t cNsElapsed = RTTimeNanoTS() - nsStart;
+
+ RTTestIValueF(cNsElapsed, RTTESTUNIT_NS, "%s-Total", pszSub);
+ RTTestIValueF(cNsElapsed / cInstrs, RTTESTUNIT_NS_PER_CALL, "%s-per-instruction", pszSub);
+}
+
+void testTwo(void)
+{
+ static const struct
+ {
+ DISCPUMODE enmMode;
+ uint8_t abInstr[24];
+ uint8_t cbParam1;
+ uint8_t cbParam2;
+ uint8_t cbParam3;
+ } s_gInstrs[] =
+ {
+ { DISCPUMODE_64BIT, { 0x48, 0xc7, 0x03, 0x00, 0x00, 0x00, 0x00, }, 8, 8, 0, },
+ };
+ for (unsigned i = 0; i < RT_ELEMENTS(s_gInstrs); i++)
+ {
+ uint32_t cb = 1;
+ DISSTATE Dis;
+ int rc;
+ RTTESTI_CHECK_RC(rc = DISInstr(s_gInstrs[i].abInstr, s_gInstrs[i].enmMode, &Dis, &cb), VINF_SUCCESS);
+ if (rc == VINF_SUCCESS)
+ {
+ uint32_t cb2;
+ RTTESTI_CHECK_MSG((cb2 = DISGetParamSize(&Dis, &Dis.Param1)) == s_gInstrs[i].cbParam1,
+ ("%u: %#x vs %#x\n", i , cb2, s_gInstrs[i].cbParam1));
+ RTTESTI_CHECK_MSG((cb2 = DISGetParamSize(&Dis, &Dis.Param2)) == s_gInstrs[i].cbParam2,
+ ("%u: %#x vs %#x (%s)\n", i , cb2, s_gInstrs[i].cbParam2, Dis.pCurInstr->pszOpcode));
+ RTTESTI_CHECK_MSG((cb2 = DISGetParamSize(&Dis, &Dis.Param3)) == s_gInstrs[i].cbParam3,
+ ("%u: %#x vs %#x\n", i , cb2, s_gInstrs[i].cbParam3));
+ }
+ }
+}
+
+
+int main(int argc, char **argv)
+{
+ RT_NOREF2(argc, argv);
+ RTTEST hTest;
+ RTEXITCODE rcExit = RTTestInitAndCreate("tstDisasm", &hTest);
+ if (rcExit)
+ return rcExit;
+ RTTestBanner(hTest);
+
+ static const struct
+ {
+ const char *pszDesc;
+ uint8_t const *pbStart;
+ uintptr_t uEndPtr;
+ DISCPUMODE enmCpuMode;
+ } aSnippets[] =
+ {
+ { "32-bit", (uint8_t const *)(uintptr_t)TestProc32, (uintptr_t)&TestProc32_EndProc, DISCPUMODE_32BIT },
+ { "64-bit", (uint8_t const *)(uintptr_t)TestProc64, (uintptr_t)&TestProc64_EndProc, DISCPUMODE_64BIT },
+ };
+
+ for (unsigned i = 0; i < RT_ELEMENTS(aSnippets); i++)
+ testDisas(aSnippets[i].pszDesc, aSnippets[i].pbStart, aSnippets[i].uEndPtr, aSnippets[i].enmCpuMode);
+
+ testTwo();
+
+ if (RTTestIErrorCount() == 0)
+ {
+ for (unsigned i = 0; i < RT_ELEMENTS(aSnippets); i++)
+ testPerformance(aSnippets[i].pszDesc, aSnippets[i].pbStart, aSnippets[i].uEndPtr, aSnippets[i].enmCpuMode);
+ }
+
+ return RTTestSummaryAndDestroy(hTest);
+}
+
diff --git a/src/VBox/Disassembler/testcase/tstDisasm-1A.asm b/src/VBox/Disassembler/testcase/tstDisasm-1A.asm
new file mode 100644
index 00000000..7cece595
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstDisasm-1A.asm
@@ -0,0 +1,422 @@
+; $Id: tstDisasm-1A.asm $
+;; @file
+; VBox disassembler: Assembler test routines
+;
+
+;
+; Copyright (C) 2006-2019 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+
+;*******************************************************************************
+;* Header Files *
+;*******************************************************************************
+%include "iprt/asmdefs.mac"
+;%include "VBox/vmm/vm.mac"
+;%include "VBox/err.mac"
+;%include "VBox/vmm/stam.mac"
+;%include "iprt/x86.mac"
+
+BITS 32
+
+%if __YASM_VERSION_ID__ >= 001020001h ; v1.2.0.1 and greater, make sure to exclude v1.2.0.0.
+ %define pmulhrwa pmulhrw
+%endif
+
+
+BEGINCODE
+
+align 16
+BEGINPROC TestProc32
+ xor eax, eax
+ mov al, 4
+ lea edx, [4]
+ mov edx, 4
+ mov eax, 4
+ shl eax, 4
+ shl edx, 4
+ shr edx, 4
+ mov eax, edx
+ mov eax, ecx
+ mov edx, eax
+ mov ecx, eax
+ DB 0xF0, 0x0F, 0x22, 0xC0
+ DB 0xF0, 0x0F, 0x20, 0xC0
+ smsw word [edx+16]
+ ; invept eax, dqword [ecx]
+ DB 0x66, 0x0F, 0x38, 0x80, 0x1
+ ; invept eax, dqword [ecx]
+ DB 0x66, 0x0F, 0x38, 0x81, 0x1
+ mov eax, dword [ecx]
+ mov word [edi], 0123ah
+ movzx eax,byte [edx]
+ movzx eax,word [edx]
+ mov dword [es:ebx + 1234h], 0789h
+ mov word [fs:ebx + ecx], 0654h
+ mov byte [esi + eax*4], 054h
+ mov bl, byte [ds:ebp + 1234h]
+ mov al, [cs:1234h + ecx*8]
+ mov al, [cs:1234h]
+ mov ax, [cs:1234h]
+ mov eax, [cs:1234h]
+ lock cmpxchg [ecx], eax
+ lock cmpxchg [ecx], ax
+ lock cmpxchg [ecx], dl
+ movzx ESI,word [EAX]
+ in al, dx
+ in ax, dx
+ in eax, dx
+ mov ebx, [ecx + eax*4 + 17]
+ mov ebx, [ebp + eax*4 + 4]
+ mov ebx, [ebp + eax*4]
+ int 80h
+ in al, 60h
+ in ax, dx
+ out 64h, eax
+
+ movss xmm0, xmm1
+ movss xmm3, [eax]
+ movss [eax], xmm4
+ movsd xmm6, xmm1
+
+ pause
+ nop
+
+ ; 3Dnow!
+ pavgusb mm1, mm0
+ pf2id mm5, mm4
+ pf2iw mm6, mm3
+ pfacc mm7, mm2
+ pfadd mm5, mm4
+ pfcmpeq mm6, mm3
+ pfcmpge mm2, mm7
+ pfcmpgt mm4, mm5
+ pfmax mm3, mm6
+ pfmin mm1, mm0
+ pfmul mm5, mm4
+ pmulhrwa mm3, mm6
+ pfnacc mm4, mm5
+ pfpnacc mm3, mm6
+ pfrcp mm0, mm1
+ pfrcpit1 mm2, mm7
+ pfrcpit2 mm4, mm5
+ pfrsqrt mm7, mm2
+ pfrsqit1 mm1, mm0
+ pfsub mm6, mm3
+ pfsubr mm0, mm1
+ pi2fd mm7, mm2
+ pi2fw mm0, mm1
+ pswapd mm2, mm7
+
+ pavgusb mm1, qword [es:eax+000000010h]
+ pf2id mm5, qword [ds:esi+000101010h]
+ pf2iw mm6, qword [fs:esi+000101010h]
+ pfacc mm7, qword [gs:esi+000101010h]
+ pfadd mm5, qword [ esi+000101010h]
+ pfcmpeq mm6, qword [ edi*8+000101010h]
+ pfcmpge mm2, qword [es:esi+000100010h]
+ pfcmpgt mm4, qword [es:esi+000101010h]
+ pfmax mm3, qword [es:esi+000101010h]
+ pfmin mm1, qword [es:esi+000101010h]
+ pfmul mm5, qword [es:esi+000101000h]
+ pmulhrwa mm3, qword [es:eax+0ffffffffh]
+ pfnacc mm4, qword [es:ebx+000101010h]
+ pfpnacc mm3, qword [es:edx+000102900h]
+ pfrcp mm0, qword [es:ecx+000101020h]
+ pfrcpit1 mm2, qword [es:ebp+000101510h]
+ pfrcpit2 mm4, qword [es:esp+000101310h]
+ pfrsqrt mm7, qword [es:esi+0f0106010h]
+ pfrsqit1 mm1, qword [es:edi+0001f1010h]
+ pfsub mm6, qword [es:esi*2]
+ pfsubr mm0, qword [es:esi*3]
+ pi2fd mm7, qword [es:esi*4]
+ pi2fw mm0, qword [es:esi*5]
+ pswapd mm2, qword [es:esi*8]
+
+ pmulhrwa mm0, qword [ds:ebp+edi*8+00f000001h]
+
+ ; MMX
+ psubusb mm1, mm3
+ cvtpi2pd xmm0, mm3
+ paddd mm1, mm3
+ paddd xmm1, xmm3
+
+%if __YASM_VERSION_ID__ >= 001030000h ; Old yasm doesn't support the instructions below
+ adcx eax, ebx
+ adcx eax, [edi]
+
+ adox eax, ebx
+ adox eax, [edi]
+ adox eax, [edi + 1000h]
+
+ tzcnt ax, bx
+ tzcnt eax, ebx
+ tzcnt ax, [edi]
+ tzcnt eax, [edi]
+ tzcnt eax, [edi + 1000h]
+ vpmovsxbw ymm0, xmm1
+ vpmovzxbq ymm1, [100h]
+ vgatherqps xmm0,dword [eax+xmm0*2],xmm0
+ vgatherqpd xmm0,qword [eax+xmm0*2],xmm0
+%endif
+
+ movbe eax, [edi]
+ movbe ebx, [edi + 1000h]
+ movbe ax, [edi]
+ movbe [edi], eax
+
+ crc32 eax, bl
+ crc32 eax, bx
+ crc32 eax, ebx
+ crc32 eax, byte [edi]
+ crc32 eax, word [edi]
+ crc32 eax, dword [edi]
+
+ popcnt ax, bx
+ popcnt eax, ebx
+ popcnt ax, [edi]
+ popcnt eax, [edi]
+ popcnt eax, [edi + 1000h]
+
+ lzcnt ax, bx
+ lzcnt eax, ebx
+ lzcnt ax, [edi]
+ lzcnt eax, [edi]
+ lzcnt eax, [edi + 1000h]
+
+ vmread eax, ebx
+ vmwrite eax, ebx
+
+ movd mm0, [edi]
+ movq mm0, [edi]
+ movq mm0, mm1
+
+ vmovups xmm0, xmm1
+ vmovaps ymm0, ymm1
+ vunpcklps xmm0, xmm1, xmm2
+ vunpcklps ymm0, ymm1, ymm2
+
+ lddqu xmm1, [ds:ebp+edi*8+00f000001h]
+ vlddqu xmm1, [ds:ebp+edi*8+00f000001h]
+ vlddqu ymm1, [ds:ebp+edi*8+00f000001h]
+
+ vpmovsxbw xmm0,qword [0x100]
+ vbroadcastf128 ymm0,oword [0x100]
+
+ palignr mm0, mm1, 1
+ vpinsrb xmm0, xmm1, eax, 1
+ vpinsrb xmm0, xmm1, [100h], 1
+ vinsertps xmm0, xmm1, xmm2, 1
+ vinsertps xmm0, xmm1, [100h], 1
+
+ vblendvps xmm0, xmm1, xmm2, xmm3
+ vblendvps ymm0, ymm1, ymm2, ymm3
+
+ aesimc xmm0, xmm1
+
+ pmovzxbq xmm0, xmm1
+ pmovzxbq xmm1, [100h]
+
+ vfmaddsub132pd ymm1, ymm2, ymm3
+
+ENDPROC TestProc32
+
+
+%ifndef RT_OS_OS2
+BITS 64
+align 16
+BEGINPROC TestProc64
+ mov cr8, rax
+ mov cr8, rbx
+ mov [0xfffe0080], rax
+ mov [0xfffe0080], rbx
+ mov rax, cr8
+ mov rbx, cr8
+ mov rax, [0xfffe0080]
+ mov rbx, [0xfffe0080]
+ divsd xmm1, xmm0
+ ; invept rdi, dqword [rsi]
+ DB 0x66, 0x0F, 0x38, 0x80, 0x3E
+ ; invept rcx, dqword [rdx]
+ DB 0x66, 0x0F, 0x38, 0x80, 0xA
+ ;invvpid rdi, dqword [rsi]
+ DB 0x66, 0x0F, 0x38, 0x81, 0x3E
+ ; invvpid rcx, dqword [rdx]
+ DB 0x66, 0x0F, 0x38, 0x81, 0xA
+ mov rdi, [rsi]
+ mov rcx, [rdx]
+ db 48h
+ db 0c7h
+ db 42h
+ db 18h
+ db 20h
+ db 3eh
+ db 23h
+ db 80h
+ call qword [r8+10h]
+ ; test
+ db 48h
+ db 8bh
+ db 44h
+ db 0ah
+ db 0f8h
+ ;incorrectly assembled by yasm; REX.W should not be added!
+ ;test rax, dword 0cc90cc90h
+ db 8bh
+ db 04h
+ db 8dh
+ db 00h
+ db 00h
+ db 0feh
+ db 0ffh
+ mov qword [rcx+rdx], 0
+ mov dword [rcx+rdx], 0
+ and [r15], rax
+ movzx rcx, sil
+ and sil, 3
+ movzx ecx, ah
+ and ah, 3
+
+ sub rcx, 1234h
+ mov rax, qword [0cc90cc90h]
+ mov rax, qword [00c90cc90h]
+ mov rax, dword 0cc90cc90h
+ mov rax, qword 0ffffcc90cc90h
+
+ movzx rax,byte [edx]
+ movzx rax,word [edx]
+ movzx rax,byte [rdx]
+ lock cmpxchg [rcx], rax
+ lock cmpxchg [rcx], ax
+ lock cmpxchg [r15], dl
+ movzx RSI, word [R8]
+ in al, dx
+ in ax, dx
+ in eax, dx
+ mov rbx, [rcx + rax*4 + 17]
+ mov rbx, [rbp + rax*4 + 4]
+ mov rbx, [rbp + rax*4]
+ mov rbx, [ebp + eax*4]
+ int 80h
+ in al, 60h
+ in ax, dx
+ out 64h, eax
+
+ movss xmm0, xmm14
+ movsd xmm6, xmm1
+
+ movbe eax, [rdi]
+ movbe ax, [rdi]
+ movbe rax, [rdi]
+
+ crc32 eax, bl
+ crc32 eax, bx
+ crc32 eax, ebx
+ crc32 eax, byte [edi]
+ crc32 eax, word [edi]
+ crc32 eax, dword [edi]
+
+ crc32 rax, bl
+ crc32 rax, byte [rdi]
+ crc32 rax, qword [rdi]
+
+%if __YASM_VERSION_ID__ >= 001030000h ; Old yasm doesn't support the instructions below
+
+ adcx eax, ebx
+ adcx rax, rbx
+ adcx r8, r11
+ adcx r8d, edx
+
+ adox eax, ebx
+ adox eax, [edi]
+ adox eax, [edi + 1000h]
+
+ adox rax, rbx
+ adox rax, [rdi]
+ adox rax, [rdi + 1000h]
+ adox rax, [edi + 1000h]
+
+ tzcnt ax, bx
+ tzcnt eax, ebx
+ tzcnt rax, rbx
+ tzcnt ax, [edi]
+ tzcnt eax, [edi]
+ tzcnt eax, [edi + 1000h]
+
+ vpunpcklbw ymm1, ymm2, ymm3
+ vpmovsxbw ymm4,[0x100]
+ vgatherqpd xmm0,qword [rbx+xmm11*2],xmm2
+%endif
+
+ popcnt ax, bx
+ popcnt eax, ebx
+ popcnt rax, rbx
+ popcnt ax, [edi]
+ popcnt eax, [edi]
+ popcnt eax, [edi + 1000h]
+ popcnt rax, [rdi + 1000h]
+
+ lzcnt ax, bx
+ lzcnt eax, ebx
+ lzcnt rax, rbx
+ lzcnt ax, [edi]
+ lzcnt eax, [edi]
+ lzcnt eax, [edi + 1000h]
+ lzcnt eax, [rdi]
+ lzcnt ax, [rdi]
+ lzcnt rax, [rdi]
+ lzcnt r8d, [rdi]
+
+ vmread rax, rbx
+ vmwrite rax, rbx
+
+ getsec
+
+ movd mm0, [rdi]
+ movq mm0, [edi]
+ movq mm0, mm1
+
+ vmovups xmm0, xmm1
+ vmovaps ymm0, ymm1
+ vunpcklps xmm0, xmm1, xmm2
+ vunpcklps ymm0, ymm1, ymm2
+ vunpcklps ymm0, ymm10, ymm2
+
+ vmovups xmm5, xmm9
+
+ vcmpps xmm1, xmm2, xmm3, 12
+
+ lddqu xmm1, [ebp+edi*8+00f000001h]
+ vlddqu xmm1, [rbp+rdi*8+00f000001h]
+ vlddqu ymm1, [rbp+rdi*8+00f000001h]
+
+ vbroadcastf128 ymm0,oword [0x100]
+ vmovlps xmm0, xmm1, [100h]
+ vmovlps xmm0, xmm1, [eax + ebx]
+ vmovlps xmm0, xmm1, [rax + rbx]
+ vmovlps xmm10, xmm1, [rax]
+
+ vblendvpd xmm0, xmm1, [100h], xmm3
+
+ dpps xmm0, xmm1, 1
+
+ extractps eax, xmm2, 3
+ vzeroupper
+ vzeroall
+
+ movlps xmm0, [100h]
+ movlps xmm0, [eax + ebx]
+ movlps xmm10, [rax + rbx]
+ movhlps xmm0, xmm1
+
+ ret
+ENDPROC TestProc64
+%endif ; !OS2
+
diff --git a/src/VBox/Disassembler/testcase/tstDisasm-2.cpp b/src/VBox/Disassembler/testcase/tstDisasm-2.cpp
new file mode 100644
index 00000000..fc84c5e3
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstDisasm-2.cpp
@@ -0,0 +1,683 @@
+/* $Id: tstDisasm-2.cpp $ */
+/** @file
+ * Testcase - Generic Disassembler Tool.
+ */
+
+/*
+ * Copyright (C) 2008-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <VBox/dis.h>
+#include <VBox/err.h>
+#include <iprt/alloc.h>
+#include <iprt/assert.h>
+#include <iprt/initterm.h>
+#include <iprt/getopt.h>
+#include <iprt/file.h>
+#include <iprt/path.h>
+#include <iprt/stream.h>
+#include <iprt/string.h>
+#include <iprt/ctype.h>
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+typedef enum { kAsmStyle_Default, kAsmStyle_yasm, kAsmStyle_masm, kAsmStyle_gas, kAsmStyle_invalid } ASMSTYLE;
+typedef enum { kUndefOp_Fail, kUndefOp_All, kUndefOp_DefineByte, kUndefOp_End } UNDEFOPHANDLING;
+
+typedef struct MYDISSTATE
+{
+ DISSTATE Dis;
+ uint64_t uAddress; /**< The current instruction address. */
+ uint8_t *pbInstr; /**< The current instruction (pointer). */
+ uint32_t cbInstr; /**< The size of the current instruction. */
+ bool fUndefOp; /**< Whether the current instruction is really an undefined opcode.*/
+ UNDEFOPHANDLING enmUndefOp; /**< How to treat undefined opcodes. */
+ int rc; /**< Set if we hit EOF. */
+ size_t cbLeft; /**< The number of bytes left. (read) */
+ uint8_t *pbNext; /**< The next byte. (read) */
+ uint64_t uNextAddr; /**< The address of the next byte. (read) */
+ char szLine[256]; /**< The disassembler text output. */
+} MYDISSTATE;
+typedef MYDISSTATE *PMYDISSTATE;
+
+
+
+/**
+ * Default style.
+ *
+ * @param pState The disassembler state.
+ */
+static void MyDisasDefaultFormatter(PMYDISSTATE pState)
+{
+ RTPrintf("%s", pState->szLine);
+}
+
+
+/**
+ * Yasm style.
+ *
+ * @param pState The disassembler state.
+ */
+static void MyDisasYasmFormatter(PMYDISSTATE pState)
+{
+ char szTmp[256];
+#if 0
+ /* a very quick hack. */
+ strcpy(szTmp, RTStrStripL(strchr(pState->szLine, ':') + 1));
+
+ char *psz = strrchr(szTmp, '[');
+ *psz = '\0';
+ RTStrStripR(szTmp);
+
+ psz = strstr(szTmp, " ptr ");
+ if (psz)
+ memset(psz, ' ', 5);
+
+ char *pszEnd = strchr(szTmp, '\0');
+ while (pszEnd - &szTmp[0] < 71)
+ *pszEnd++ = ' ';
+ *pszEnd = '\0';
+
+#else
+ size_t cch = DISFormatYasmEx(&pState->Dis, szTmp, sizeof(szTmp),
+ DIS_FMT_FLAGS_STRICT | DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_COMMENT
+ | DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_COMMENT | DIS_FMT_FLAGS_BYTES_SPACED,
+ NULL, NULL);
+ Assert(cch < sizeof(szTmp));
+ while (cch < 71)
+ szTmp[cch++] = ' ';
+ szTmp[cch] = '\0';
+#endif
+
+ RTPrintf(" %s ; %s", szTmp, pState->szLine);
+}
+
+
+/**
+ * Masm style.
+ *
+ * @param pState The disassembler state.
+ */
+static void MyDisasMasmFormatter(PMYDISSTATE pState)
+{
+ RTPrintf("masm not implemented: %s", pState->szLine);
+}
+
+
+/**
+ * This is a temporary workaround for catching a few illegal opcodes
+ * that the disassembler is currently letting thru, just enough to make
+ * the assemblers happy.
+ *
+ * We're too close to a release to dare mess with these things now as
+ * they may consequences for performance and let alone introduce bugs.
+ *
+ * @returns true if it's valid. false if it isn't.
+ *
+ * @param pDis The disassembler output.
+ */
+static bool MyDisasIsValidInstruction(DISSTATE const *pDis)
+{
+ switch (pDis->pCurInstr->uOpcode)
+ {
+ /* These doesn't take memory operands. */
+ case OP_MOV_CR:
+ case OP_MOV_DR:
+ case OP_MOV_TR:
+ if (pDis->ModRM.Bits.Mod != 3)
+ return false;
+ break;
+
+ /* The 0x8f /0 variant of this instruction doesn't get its /r value verified. */
+ case OP_POP:
+ if ( pDis->bOpCode == 0x8f
+ && pDis->ModRM.Bits.Reg != 0)
+ return false;
+ break;
+
+ /* The 0xc6 /0 and 0xc7 /0 variants of this instruction don't get their /r values verified. */
+ case OP_MOV:
+ if ( ( pDis->bOpCode == 0xc6
+ || pDis->bOpCode == 0xc7)
+ && pDis->ModRM.Bits.Reg != 0)
+ return false;
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+
+/**
+ * @interface_method_impl{FNDISREADBYTES}
+ */
+static DECLCALLBACK(int) MyDisasInstrRead(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
+{
+ RT_NOREF1(cbMaxRead);
+ PMYDISSTATE pState = (PMYDISSTATE)pDis;
+ RTUINTPTR uSrcAddr = pState->Dis.uInstrAddr + offInstr;
+ if (RT_LIKELY( pState->uNextAddr == uSrcAddr
+ && pState->cbLeft >= cbMinRead))
+ {
+ /*
+ * Straight forward reading.
+ */
+ //size_t cbToRead = cbMaxRead;
+ size_t cbToRead = cbMinRead;
+ memcpy(&pState->Dis.abInstr[offInstr], pState->pbNext, cbToRead);
+ pState->Dis.cbCachedInstr = offInstr + (uint8_t)cbToRead;
+ pState->pbNext += cbToRead;
+ pState->cbLeft -= cbToRead;
+ pState->uNextAddr += cbToRead;
+ return VINF_SUCCESS;
+ }
+
+ if (pState->uNextAddr == uSrcAddr)
+ {
+ /*
+ * Reading too much.
+ */
+ if (pState->cbLeft > 0)
+ {
+ memcpy(&pState->Dis.abInstr[offInstr], pState->pbNext, pState->cbLeft);
+ offInstr += (uint8_t)pState->cbLeft;
+ cbMinRead -= (uint8_t)pState->cbLeft;
+ pState->pbNext += pState->cbLeft;
+ pState->uNextAddr += pState->cbLeft;
+ pState->cbLeft = 0;
+ }
+ memset(&pState->Dis.abInstr[offInstr], 0xcc, cbMinRead);
+ pState->rc = VERR_EOF;
+ }
+ else
+ {
+ /*
+ * Non-sequential read, that's an error.
+ */
+ RTStrmPrintf(g_pStdErr, "Reading before current instruction!\n");
+ memset(&pState->Dis.abInstr[offInstr], 0x90, cbMinRead);
+ pState->rc = VERR_INTERNAL_ERROR;
+ }
+ pState->Dis.cbCachedInstr = offInstr + cbMinRead;
+ return pState->rc;
+}
+
+
+/**
+ * Disassembles a block of memory.
+ *
+ * @returns VBox status code.
+ * @param argv0 Program name (for errors and warnings).
+ * @param enmCpuMode The cpu mode to disassemble in.
+ * @param uAddress The address we're starting to disassemble at.
+ * @param uHighlightAddr The address of the instruction that should be
+ * highlighted. Pass UINT64_MAX to keep quiet.
+ * @param pbFile Where to start disassemble.
+ * @param cbFile How much to disassemble.
+ * @param enmStyle The assembly output style.
+ * @param fListing Whether to print in a listing like mode.
+ * @param enmUndefOp How to deal with undefined opcodes.
+ */
+static int MyDisasmBlock(const char *argv0, DISCPUMODE enmCpuMode, uint64_t uAddress,
+ uint64_t uHighlightAddr, uint8_t *pbFile, size_t cbFile,
+ ASMSTYLE enmStyle, bool fListing, UNDEFOPHANDLING enmUndefOp)
+{
+ RT_NOREF1(fListing);
+
+ /*
+ * Initialize the CPU context.
+ */
+ MYDISSTATE State;
+ State.uAddress = uAddress;
+ State.pbInstr = pbFile;
+ State.cbInstr = 0;
+ State.enmUndefOp = enmUndefOp;
+ State.rc = VINF_SUCCESS;
+ State.cbLeft = cbFile;
+ State.pbNext = pbFile;
+ State.uNextAddr = uAddress;
+
+ void (*pfnFormatter)(PMYDISSTATE pState);
+ switch (enmStyle)
+ {
+ case kAsmStyle_Default:
+ pfnFormatter = MyDisasDefaultFormatter;
+ break;
+
+ case kAsmStyle_yasm:
+ RTPrintf(" BITS %d\n", enmCpuMode == DISCPUMODE_16BIT ? 16 : enmCpuMode == DISCPUMODE_32BIT ? 32 : 64);
+ pfnFormatter = MyDisasYasmFormatter;
+ break;
+
+ case kAsmStyle_masm:
+ pfnFormatter = MyDisasMasmFormatter;
+ break;
+
+ default:
+ AssertFailedReturn(VERR_INTERNAL_ERROR);
+ }
+
+ /*
+ * The loop.
+ */
+ int rcRet = VINF_SUCCESS;
+ while (State.cbLeft > 0)
+ {
+ /*
+ * Disassemble it.
+ */
+ State.cbInstr = 0;
+ State.cbLeft += State.pbNext - State.pbInstr;
+ State.uNextAddr = State.uAddress;
+ State.pbNext = State.pbInstr;
+
+ int rc = DISInstrToStrWithReader(State.uAddress, enmCpuMode, MyDisasInstrRead, &State,
+ &State.Dis, &State.cbInstr, State.szLine, sizeof(State.szLine));
+ if ( RT_SUCCESS(rc)
+ || ( ( rc == VERR_DIS_INVALID_OPCODE
+ || rc == VERR_DIS_GEN_FAILURE)
+ && State.enmUndefOp == kUndefOp_DefineByte))
+ {
+ State.fUndefOp = rc == VERR_DIS_INVALID_OPCODE
+ || rc == VERR_DIS_GEN_FAILURE
+ || State.Dis.pCurInstr->uOpcode == OP_INVALID
+ || State.Dis.pCurInstr->uOpcode == OP_ILLUD2
+ || ( State.enmUndefOp == kUndefOp_DefineByte
+ && !MyDisasIsValidInstruction(&State.Dis));
+ if (State.fUndefOp && State.enmUndefOp == kUndefOp_DefineByte)
+ {
+ if (!State.cbInstr)
+ {
+ State.Dis.abInstr[0] = 0;
+ State.Dis.pfnReadBytes(&State.Dis, 0, 1, 1);
+ State.cbInstr = 1;
+ }
+ RTPrintf(" db");
+ for (unsigned off = 0; off < State.cbInstr; off++)
+ RTPrintf(off ? ", %03xh" : " %03xh", State.Dis.abInstr[off]);
+ RTPrintf(" ; %s\n", State.szLine);
+ }
+ else if (!State.fUndefOp && State.enmUndefOp == kUndefOp_All)
+ {
+ RTPrintf("%s: error at %#RX64: unexpected valid instruction (op=%d)\n", argv0, State.uAddress, State.Dis.pCurInstr->uOpcode);
+ pfnFormatter(&State);
+ rcRet = VERR_GENERAL_FAILURE;
+ }
+ else if (State.fUndefOp && State.enmUndefOp == kUndefOp_Fail)
+ {
+ RTPrintf("%s: error at %#RX64: undefined opcode (op=%d)\n", argv0, State.uAddress, State.Dis.pCurInstr->uOpcode);
+ pfnFormatter(&State);
+ rcRet = VERR_GENERAL_FAILURE;
+ }
+ else
+ {
+ /* Use db for odd encodings that we can't make the assembler use. */
+ if ( State.enmUndefOp == kUndefOp_DefineByte
+ && DISFormatYasmIsOddEncoding(&State.Dis))
+ {
+ RTPrintf(" db");
+ for (unsigned off = 0; off < State.cbInstr; off++)
+ RTPrintf(off ? ", %03xh" : " %03xh", State.Dis.abInstr[off]);
+ RTPrintf(" ; ");
+ }
+
+ pfnFormatter(&State);
+ }
+ }
+ else
+ {
+ State.cbInstr = State.pbNext - State.pbInstr;
+ if (!State.cbLeft)
+ RTPrintf("%s: error at %#RX64: read beyond the end (%Rrc)\n", argv0, State.uAddress, rc);
+ else if (State.cbInstr)
+ RTPrintf("%s: error at %#RX64: %Rrc cbInstr=%d\n", argv0, State.uAddress, rc, State.cbInstr);
+ else
+ {
+ RTPrintf("%s: error at %#RX64: %Rrc cbInstr=%d!\n", argv0, State.uAddress, rc, State.cbInstr);
+ if (rcRet == VINF_SUCCESS)
+ rcRet = rc;
+ break;
+ }
+ }
+
+ /* Highlight this instruction? */
+ if (uHighlightAddr - State.uAddress < State.cbInstr)
+ RTPrintf("; ^^^^^^^^^^^^^^^^^^^^^\n");
+
+ /* Check that the size-only mode returns the smae size on success. */
+ if (RT_SUCCESS(rc))
+ {
+ uint32_t cbInstrOnly = 32;
+ uint8_t abInstr[sizeof(State.Dis.abInstr)];
+ memcpy(abInstr, State.Dis.abInstr, sizeof(State.Dis.abInstr));
+ int rcOnly = DISInstrWithPrefetchedBytes(State.uAddress, enmCpuMode, 0 /*fFilter - none */,
+ abInstr, State.Dis.cbCachedInstr, MyDisasInstrRead, &State,
+ &State.Dis, &cbInstrOnly);
+ if ( rcOnly != rc
+ || cbInstrOnly != State.cbInstr)
+ {
+ RTPrintf("; Instruction size only check failed rc=%Rrc cbInstrOnly=%#x exepcted %Rrc and %#x\n",
+ rcOnly, cbInstrOnly, rc, State.cbInstr);
+ rcRet = VERR_GENERAL_FAILURE;
+ break;
+ }
+ }
+
+ /* next */
+ State.uAddress += State.cbInstr;
+ State.pbInstr += State.cbInstr;
+ }
+
+ return rcRet;
+}
+
+/**
+ * Converts a hex char to a number.
+ *
+ * @returns 0..15 on success, -1 on failure.
+ * @param ch The character.
+ */
+static int HexDigitToNum(char ch)
+{
+ switch (ch)
+ {
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ case 'A':
+ case 'a': return 0xa;
+ case 'B':
+ case 'b': return 0xb;
+ case 'C':
+ case 'c': return 0xc;
+ case 'D':
+ case 'd': return 0xd;
+ case 'E':
+ case 'e': return 0xe;
+ case 'F':
+ case 'f': return 0xf;
+ default:
+ RTPrintf("error: Invalid hex digit '%c'\n", ch);
+ return -1;
+ }
+}
+
+/**
+ * Prints usage info.
+ *
+ * @returns 1.
+ * @param argv0 The program name.
+ */
+static int Usage(const char *argv0)
+{
+ RTStrmPrintf(g_pStdErr,
+"usage: %s [options] <file1> [file2..fileN]\n"
+" or: %s [options] <-x|--hex-bytes> <hex byte> [more hex..]\n"
+" or: %s <--help|-h>\n"
+"\n"
+"Options:\n"
+" --address|-a <address>\n"
+" The base address. Default: 0\n"
+" --max-bytes|-b <bytes>\n"
+" The maximum number of bytes to disassemble. Default: 1GB\n"
+" --cpumode|-c <16|32|64>\n"
+" The cpu mode. Default: 32\n"
+" --listing|-l, --no-listing|-L\n"
+" Enables or disables listing mode. Default: --no-listing\n"
+" --offset|-o <offset>\n"
+" The file offset at which to start disassembling. Default: 0\n"
+" --style|-s <default|yasm|masm>\n"
+" The assembly output style. Default: default\n"
+" --undef-op|-u <fail|all|db>\n"
+" How to treat undefined opcodes. Default: fail\n"
+ , argv0, argv0, argv0);
+ return 1;
+}
+
+
+int main(int argc, char **argv)
+{
+ RTR3InitExe(argc, &argv, 0);
+ const char * const argv0 = RTPathFilename(argv[0]);
+
+ /* options */
+ uint64_t uAddress = 0;
+ uint64_t uHighlightAddr = UINT64_MAX;
+ ASMSTYLE enmStyle = kAsmStyle_Default;
+ UNDEFOPHANDLING enmUndefOp = kUndefOp_Fail;
+ bool fListing = true;
+ DISCPUMODE enmCpuMode = DISCPUMODE_32BIT;
+ RTFOFF off = 0;
+ RTFOFF cbMax = _1G;
+ bool fHexBytes = false;
+
+ /*
+ * Parse arguments.
+ */
+ static const RTGETOPTDEF g_aOptions[] =
+ {
+ { "--address", 'a', RTGETOPT_REQ_UINT64 },
+ { "--cpumode", 'c', RTGETOPT_REQ_UINT32 },
+ { "--bytes", 'b', RTGETOPT_REQ_INT64 },
+ { "--listing", 'l', RTGETOPT_REQ_NOTHING },
+ { "--no-listing", 'L', RTGETOPT_REQ_NOTHING },
+ { "--offset", 'o', RTGETOPT_REQ_INT64 },
+ { "--style", 's', RTGETOPT_REQ_STRING },
+ { "--undef-op", 'u', RTGETOPT_REQ_STRING },
+ { "--hex-bytes", 'x', RTGETOPT_REQ_NOTHING },
+ };
+
+ int ch;
+ RTGETOPTUNION ValueUnion;
+ RTGETOPTSTATE GetState;
+ RTGetOptInit(&GetState, argc, argv, g_aOptions, RT_ELEMENTS(g_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
+ while ( (ch = RTGetOpt(&GetState, &ValueUnion))
+ && ch != VINF_GETOPT_NOT_OPTION)
+ {
+ switch (ch)
+ {
+ case 'a':
+ uAddress = ValueUnion.u64;
+ break;
+
+ case 'b':
+ cbMax = ValueUnion.i64;
+ break;
+
+ case 'c':
+ if (ValueUnion.u32 == 16)
+ enmCpuMode = DISCPUMODE_16BIT;
+ else if (ValueUnion.u32 == 32)
+ enmCpuMode = DISCPUMODE_32BIT;
+ else if (ValueUnion.u32 == 64)
+ enmCpuMode = DISCPUMODE_64BIT;
+ else
+ {
+ RTStrmPrintf(g_pStdErr, "%s: Invalid CPU mode value %RU32\n", argv0, ValueUnion.u32);
+ return 1;
+ }
+ break;
+
+ case 'h':
+ return Usage(argv0);
+
+ case 'l':
+ fListing = true;
+ break;
+
+ case 'L':
+ fListing = false;
+ break;
+
+ case 'o':
+ off = ValueUnion.i64;
+ break;
+
+ case 's':
+ if (!strcmp(ValueUnion.psz, "default"))
+ enmStyle = kAsmStyle_Default;
+ else if (!strcmp(ValueUnion.psz, "yasm"))
+ enmStyle = kAsmStyle_yasm;
+ else if (!strcmp(ValueUnion.psz, "masm"))
+ {
+ enmStyle = kAsmStyle_masm;
+ RTStrmPrintf(g_pStdErr, "%s: masm style isn't implemented yet\n", argv0);
+ return 1;
+ }
+ else
+ {
+ RTStrmPrintf(g_pStdErr, "%s: unknown assembly style: %s\n", argv0, ValueUnion.psz);
+ return 1;
+ }
+ break;
+
+ case 'u':
+ if (!strcmp(ValueUnion.psz, "fail"))
+ enmUndefOp = kUndefOp_Fail;
+ else if (!strcmp(ValueUnion.psz, "all"))
+ enmUndefOp = kUndefOp_All;
+ else if (!strcmp(ValueUnion.psz, "db"))
+ enmUndefOp = kUndefOp_DefineByte;
+ else
+ {
+ RTStrmPrintf(g_pStdErr, "%s: unknown undefined opcode handling method: %s\n", argv0, ValueUnion.psz);
+ return 1;
+ }
+ break;
+
+ case 'x':
+ fHexBytes = true;
+ break;
+
+ case 'V':
+ RTPrintf("$Revision: 127855 $\n");
+ return 0;
+
+ default:
+ return RTGetOptPrintError(ch, &ValueUnion);
+ }
+ }
+ int iArg = GetState.iNext - 1; /** @todo Not pretty, add RTGetOptInit flag for this. */
+ if (iArg >= argc)
+ return Usage(argv0);
+
+ int rc = VINF_SUCCESS;
+ if (fHexBytes)
+ {
+ /*
+ * Convert the remaining arguments from a hex byte string into
+ * a buffer that we disassemble.
+ */
+ size_t cb = 0;
+ uint8_t *pb = NULL;
+ for ( ; iArg < argc; iArg++)
+ {
+ char ch2;
+ const char *psz = argv[iArg];
+ while (*psz)
+ {
+ /** @todo this stuff belongs in IPRT, same stuff as mac address reading. Could be reused for IPv6 with a different item size.*/
+ /* skip white space, and for the benefit of linux panics '<' and '>'. */
+ while (RT_C_IS_SPACE(ch2 = *psz) || ch2 == '<' || ch2 == '>' || ch2 == ',' || ch2 == ';')
+ {
+ if (ch2 == '<')
+ uHighlightAddr = uAddress + cb;
+ psz++;
+ }
+
+ if (ch2 == '0' && (psz[1] == 'x' || psz[1] == 'X'))
+ {
+ psz += 2;
+ ch2 = *psz;
+ }
+
+ if (!ch2)
+ break;
+
+ /* one digit followed by a space or EOS, or two digits. */
+ int iNum = HexDigitToNum(*psz++);
+ if (iNum == -1)
+ return 1;
+ if (!RT_C_IS_SPACE(ch2 = *psz) && ch2 != '\0' && ch2 != '>' && ch2 != ',' && ch2 != ';')
+ {
+ int iDigit = HexDigitToNum(*psz++);
+ if (iDigit == -1)
+ return 1;
+ iNum = iNum * 16 + iDigit;
+ }
+
+ /* add the byte */
+ if (!(cb % 4 /*64*/))
+ {
+ pb = (uint8_t *)RTMemRealloc(pb, cb + 64);
+ if (!pb)
+ {
+ RTPrintf("%s: error: RTMemRealloc failed\n", argv[0]);
+ return 1;
+ }
+ }
+ pb[cb++] = (uint8_t)iNum;
+ }
+ }
+
+ /*
+ * Disassemble it.
+ */
+ rc = MyDisasmBlock(argv0, enmCpuMode, uAddress, uHighlightAddr, pb, cb, enmStyle, fListing, enmUndefOp);
+ }
+ else
+ {
+ /*
+ * Process the files.
+ */
+ for ( ; iArg < argc; iArg++)
+ {
+ /*
+ * Read the file into memory.
+ */
+ void *pvFile;
+ size_t cbFile;
+ rc = RTFileReadAllEx(argv[iArg], off, cbMax, RTFILE_RDALL_O_DENY_NONE, &pvFile, &cbFile);
+ if (RT_FAILURE(rc))
+ {
+ RTStrmPrintf(g_pStdErr, "%s: %s: %Rrc\n", argv0, argv[iArg], rc);
+ break;
+ }
+
+ /*
+ * Disassemble it.
+ */
+ rc = MyDisasmBlock(argv0, enmCpuMode, uAddress, uHighlightAddr, (uint8_t *)pvFile, cbFile, enmStyle, fListing, enmUndefOp);
+ RTFileReadAllFree(pvFile, cbFile);
+ if (RT_FAILURE(rc))
+ break;
+ }
+ }
+
+ return RT_SUCCESS(rc) ? 0 : 1;
+}
+