summaryrefslogtreecommitdiffstats
path: root/src/VBox/ValidationKit/utils/cpu/cidet-instr-1.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/ValidationKit/utils/cpu/cidet-instr-1.cpp')
-rw-r--r--src/VBox/ValidationKit/utils/cpu/cidet-instr-1.cpp297
1 files changed, 297 insertions, 0 deletions
diff --git a/src/VBox/ValidationKit/utils/cpu/cidet-instr-1.cpp b/src/VBox/ValidationKit/utils/cpu/cidet-instr-1.cpp
new file mode 100644
index 00000000..4cbbd5db
--- /dev/null
+++ b/src/VBox/ValidationKit/utils/cpu/cidet-instr-1.cpp
@@ -0,0 +1,297 @@
+/* $Id: cidet-instr-1.cpp $ */
+/** @file
+ * CPU Instruction Decoding & Execution Tests - First bunch of instructions.
+ */
+
+/*
+ * Copyright (C) 2014-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include "cidet.h"
+#include <VBox/err.h>
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+/*
+ * Shorter defines for the EFLAGS to save table space.
+ */
+#undef CF
+#undef PF
+#undef AF
+#undef ZF
+#undef SF
+#undef OF
+
+#define CF X86_EFL_CF
+#define PF X86_EFL_PF
+#define AF X86_EFL_AF
+#define ZF X86_EFL_ZF
+#define SF X86_EFL_SF
+#define OF X86_EFL_OF
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+typedef struct CIDET2IN1OUTWITHFLAGSU8ENTRY
+{
+ uint8_t uIn1;
+ uint8_t uIn2;
+ uint16_t fEFlagsIn;
+ uint8_t uOut;
+ uint16_t fEFlagsOut;
+} CIDET2IN1OUTWITHFLAGSU8ENTRY;
+typedef CIDET2IN1OUTWITHFLAGSU8ENTRY const *PCCIDET2IN1OUTWITHFLAGSU8ENTRY;
+
+typedef struct CIDET2IN1OUTWITHFLAGSU16ENTRY
+{
+ uint16_t uIn1;
+ uint16_t uIn2;
+ uint16_t fEFlagsIn;
+ uint16_t uOut;
+ uint16_t fEFlagsOut;
+} CIDET2IN1OUTWITHFLAGSU16ENTRY;
+typedef CIDET2IN1OUTWITHFLAGSU16ENTRY const *PCCIDET2IN1OUTWITHFLAGSU16ENTRY;
+
+typedef struct CIDET2IN1OUTWITHFLAGSU32ENTRY
+{
+ uint32_t uIn1;
+ uint32_t uIn2;
+ uint16_t fEFlagsIn;
+ uint32_t uOut;
+ uint16_t fEFlagsOut;
+} CIDET2IN1OUTWITHFLAGSU32ENTRY;
+typedef CIDET2IN1OUTWITHFLAGSU32ENTRY const *PCCIDET2IN1OUTWITHFLAGSU32ENTRY;
+
+typedef struct CIDET2IN1OUTWITHFLAGSU64ENTRY
+{
+ uint64_t uIn1;
+ uint64_t uIn2;
+ uint16_t fEFlagsIn;
+ uint64_t uOut;
+ uint16_t fEFlagsOut;
+} CIDET2IN1OUTWITHFLAGSU64ENTRY;
+typedef CIDET2IN1OUTWITHFLAGSU64ENTRY const *PCCIDET2IN1OUTWITHFLAGSU64ENTRY;
+
+typedef struct CIDET2IN1OUTWITHFLAGS
+{
+ PCCIDET2IN1OUTWITHFLAGSU8ENTRY pa8Entries;
+ PCCIDET2IN1OUTWITHFLAGSU16ENTRY pa16Entries;
+ PCCIDET2IN1OUTWITHFLAGSU32ENTRY pa32Entries;
+ PCCIDET2IN1OUTWITHFLAGSU64ENTRY pa64Entries;
+ uint16_t c8Entries;
+ uint16_t c16Entries;
+ uint16_t c32Entries;
+ uint16_t c64Entries;
+ uint32_t fRelevantEFlags;
+} CIDET2IN1OUTWITHFLAGS;
+
+#define CIDET2IN1OUTWITHFLAGS_INITIALIZER(a_fRelevantEFlags) \
+ { \
+ &s_a8Results[0], &s_a16Results[0], &s_a32Results[0], &s_a64Results[0], \
+ RT_ELEMENTS(s_a8Results), RT_ELEMENTS(s_a16Results), RT_ELEMENTS(s_a32Results), RT_ELEMENTS(s_a64Results), \
+ (a_fRelevantEFlags) \
+ }
+
+
+/**
+ * Generic worker for a FNCIDETSETUPINOUT function with two GPR/MEM registers,
+ * storing result in the first and flags.
+ *
+ * @returns See FNCIDETSETUPINOUT.
+ * @param pThis The core CIDET state structure. The InCtx
+ * and ExpectedCtx members will be modified.
+ * @param fInvalid When set, get the next invalid operands that will
+ * cause exceptions/faults.
+ * @param pResults The result collection.
+ */
+static int CidetGenericIn2Out1WithFlags(PCIDETCORE pThis, bool fInvalid, CIDET2IN1OUTWITHFLAGS const *pResults)
+{
+ int rc;
+
+ Assert(pThis->idxMrmRegOp < 2);
+ Assert(pThis->idxMrmRmOp < 2);
+ Assert(pThis->idxMrmRmOp != pThis->idxMrmRegOp);
+ AssertCompile(RT_ELEMENTS(pThis->aiInOut) >= 4);
+
+ if (!fInvalid)
+ {
+ if ( !pThis->fHasRegCollisionDirect
+ && !pThis->fHasRegCollisionMem)
+ {
+ pThis->InCtx.rfl &= ~(uint64_t)pResults->fRelevantEFlags;
+ pThis->ExpectedCtx.rfl &= ~(uint64_t)pResults->fRelevantEFlags;
+ switch (pThis->aOperands[0].cb)
+ {
+ case 1:
+ {
+ uint16_t idx = ++pThis->aiInOut[0] % pResults->c8Entries;
+ PCCIDET2IN1OUTWITHFLAGSU8ENTRY pEntry = &pResults->pa8Entries[idx];
+ rc = idx ? VINF_SUCCESS : VINF_EOF;
+
+ *pThis->aOperands[0].In.pu8 = pEntry->uIn1;
+ *pThis->aOperands[1].In.pu8 = pEntry->uIn2;
+ pThis->InCtx.rfl |= pEntry->fEFlagsIn;
+
+ *pThis->aOperands[0].Expected.pu8 = pEntry->uOut;
+ *pThis->aOperands[1].Expected.pu8 = pEntry->uIn2;
+ pThis->ExpectedCtx.rfl |= pEntry->fEFlagsOut;
+ break;
+ }
+
+ case 2:
+ {
+ uint16_t idx = ++pThis->aiInOut[1] % pResults->c16Entries;
+ PCCIDET2IN1OUTWITHFLAGSU16ENTRY pEntry = &pResults->pa16Entries[idx];
+ rc = idx ? VINF_SUCCESS : VINF_EOF;
+
+ *pThis->aOperands[0].In.pu16 = pEntry->uIn1;
+ *pThis->aOperands[1].In.pu16 = pEntry->uIn2;
+ pThis->InCtx.rfl |= pEntry->fEFlagsIn;
+
+ *pThis->aOperands[0].Expected.pu16 = pEntry->uOut;
+ *pThis->aOperands[1].Expected.pu16 = pEntry->uIn2;
+ pThis->ExpectedCtx.rfl |= pEntry->fEFlagsOut;
+ break;
+ }
+
+ case 4:
+ {
+ uint16_t idx = ++pThis->aiInOut[2] % pResults->c32Entries;
+ PCCIDET2IN1OUTWITHFLAGSU32ENTRY pEntry = &pResults->pa32Entries[idx];
+ rc = idx ? VINF_SUCCESS : VINF_EOF;
+
+ *pThis->aOperands[0].In.pu32 = pEntry->uIn1;
+ *pThis->aOperands[1].In.pu32 = pEntry->uIn2;
+ pThis->InCtx.rfl |= pEntry->fEFlagsIn;
+
+ *pThis->aOperands[0].Expected.pu32 = pEntry->uOut;
+ if (!pThis->aOperands[0].fIsMem)
+ pThis->aOperands[0].Expected.pu32[1] = 0;
+ *pThis->aOperands[1].Expected.pu32 = pEntry->uIn2;
+ pThis->ExpectedCtx.rfl |= pEntry->fEFlagsOut;
+ break;
+ }
+
+ case 8:
+ {
+ uint16_t idx = ++pThis->aiInOut[3] % pResults->c64Entries;
+ PCCIDET2IN1OUTWITHFLAGSU64ENTRY pEntry = &pResults->pa64Entries[idx];
+ rc = idx ? VINF_SUCCESS : VINF_EOF;
+
+ *pThis->aOperands[0].In.pu64 = pEntry->uIn1;
+ *pThis->aOperands[1].In.pu64 = pEntry->uIn2;
+ pThis->InCtx.rfl |= pEntry->fEFlagsIn;
+
+ *pThis->aOperands[0].Expected.pu64 = pEntry->uOut;
+ *pThis->aOperands[1].Expected.pu64 = pEntry->uIn2;
+ pThis->ExpectedCtx.rfl |= pEntry->fEFlagsOut;
+ break;
+ }
+
+ default:
+ AssertFailed();
+ rc = VERR_INTERNAL_ERROR_3;
+ }
+ }
+ else
+ rc = VERR_NOT_SUPPORTED;
+ }
+ else
+ rc = VERR_NO_DATA;
+ return rc;
+}
+
+
+static DECLCALLBACK(int) cidetInOutAdd(PCIDETCORE pThis, bool fInvalid)
+{
+ static const CIDET2IN1OUTWITHFLAGSU8ENTRY s_a8Results[] =
+ {
+ { UINT8_C(0x00), UINT8_C(0x00), 0, UINT8_C(0x00), ZF | PF },
+ { UINT8_C(0xff), UINT8_C(0x01), 0, UINT8_C(0x00), CF | ZF | AF | PF },
+ { UINT8_C(0x7f), UINT8_C(0x80), 0, UINT8_C(0xff), SF | PF },
+ { UINT8_C(0x01), UINT8_C(0x01), 0, UINT8_C(0x02), 0 },
+ };
+ static const CIDET2IN1OUTWITHFLAGSU16ENTRY s_a16Results[] =
+ {
+ { UINT16_C(0x0000), UINT16_C(0x0000), 0, UINT16_C(0x0000), ZF | PF },
+ { UINT16_C(0xfefd), UINT16_C(0x0103), 0, UINT16_C(0x0000), CF | ZF | AF | PF },
+ { UINT16_C(0x8e7d), UINT16_C(0x7182), 0, UINT16_C(0xffff), SF | PF },
+ { UINT16_C(0x0001), UINT16_C(0x0001), 0, UINT16_C(0x0002), 0 },
+ };
+ static const CIDET2IN1OUTWITHFLAGSU32ENTRY s_a32Results[] =
+ {
+ { UINT32_C(0x00000000), UINT32_C(0x00000000), 0, UINT32_C(0x00000000), ZF | PF },
+ { UINT32_C(0xfefdfcfb), UINT32_C(0x01020305), 0, UINT32_C(0x00000000), CF | ZF | AF | PF },
+ { UINT32_C(0x8efdfcfb), UINT32_C(0x71020304), 0, UINT32_C(0xffffffff), SF | PF },
+ { UINT32_C(0x00000001), UINT32_C(0x00000001), 0, UINT32_C(0x00000002), 0 },
+ };
+ static const CIDET2IN1OUTWITHFLAGSU64ENTRY s_a64Results[] =
+ {
+ { UINT64_C(0x0000000000000000), UINT64_C(0x0000000000000000), 0, UINT64_C(0x0000000000000000), ZF | PF },
+ { UINT64_C(0xfefdfcfbfaf9f8f7), UINT64_C(0x0102030405060709), 0, UINT64_C(0x0000000000000000), CF | ZF | AF | PF },
+ { UINT64_C(0x7efdfcfbfaf9f8f7), UINT64_C(0x8102030405060708), 0, UINT64_C(0xffffffffffffffff), SF | PF },
+ { UINT64_C(0x0000000000000001), UINT64_C(0x0000000000000001), 0, UINT64_C(0x0000000000000002), 0 },
+ };
+ static const CIDET2IN1OUTWITHFLAGS s_Results = CIDET2IN1OUTWITHFLAGS_INITIALIZER(CF | PF | AF | SF | OF);
+ return CidetGenericIn2Out1WithFlags(pThis, fInvalid, &s_Results);
+}
+
+
+/** First bunch of instructions. */
+const CIDETINSTR g_aCidetInstructions1[] =
+{
+#if 1
+ {
+ "add Eb,Gb", cidetInOutAdd, 1, {0x00, 0, 0}, 0, 2,
+ { CIDET_OF_K_GPR | CIDET_OF_Z_BYTE | CIDET_OF_M_RM | CIDET_OF_A_RW,
+ CIDET_OF_K_GPR | CIDET_OF_Z_BYTE | CIDET_OF_M_REG | CIDET_OF_A_R,
+ 0, 0 }, CIDET_IF_MODRM
+ },
+#endif
+#if 1
+ {
+ "add Ev,Gv", cidetInOutAdd, 1, {0x01, 0, 0}, 0, 2,
+ { CIDET_OF_K_GPR | CIDET_OF_Z_VAR_WDQ | CIDET_OF_M_RM | CIDET_OF_A_RW,
+ CIDET_OF_K_GPR | CIDET_OF_Z_VAR_WDQ | CIDET_OF_M_REG | CIDET_OF_A_R,
+ 0, 0 }, CIDET_IF_MODRM
+ },
+#endif
+};
+/** Number of instruction in the g_aInstructions1 array. */
+const uint32_t g_cCidetInstructions1 = RT_ELEMENTS(g_aCidetInstructions1);
+