InstructionTestGen.py revision 54ed927d658674ced4387afbd1877a27cb975a76
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync#!/usr/bin/env python
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync# -*- coding: utf-8 -*-
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync# $Id$
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync"""
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsyncInstruction Test Generator.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync"""
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsyncfrom __future__ import print_function;
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync__copyright__ = \
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync"""
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsyncCopyright (C) 2012-2013 Oracle Corporation
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsyncOracle Corporation confidential
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsyncAll rights reserved
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync"""
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync__version__ = "$Revision$";
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync# pylint: disable=C0103,R0913
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# Standard python imports.
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsyncimport io;
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsyncimport os;
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsyncfrom optparse import OptionParser
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsyncimport random;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncimport sys;
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync## @name Exit codes
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync## @{
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsyncRTEXITCODE_SUCCESS = 0;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsyncRTEXITCODE_SYNTAX = 2;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync## @}
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync## @name Various C macros we're used to.
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync## @{
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsyncUINT8_MAX = 0xff
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsyncUINT16_MAX = 0xffff
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncUINT32_MAX = 0xffffffff
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncUINT64_MAX = 0xffffffffffffffff
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncdef RT_BIT_32(iBit): # pylint: disable=C0103
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ 32-bit one bit mask. """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return 1 << iBit;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncdef RT_BIT_64(iBit): # pylint: disable=C0103
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """ 64-bit one bit mask. """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return 1 << iBit;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync## @}
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync## @name ModR/M
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync## @{
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncX86_MODRM_RM_MASK = 0x07;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncX86_MODRM_REG_MASK = 0x38;
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsyncX86_MODRM_REG_SMASK = 0x07;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncX86_MODRM_REG_SHIFT = 3;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncX86_MODRM_MOD_MASK = 0xc0;
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncX86_MODRM_MOD_SMASK = 0x03;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncX86_MODRM_MOD_SHIFT = 6;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync## @}
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync## @name SIB
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync## @{
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncX86_SIB_BASE_MASK = 0x07;
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsyncX86_SIB_INDEX_MASK = 0x38;
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsyncX86_SIB_INDEX_SMASK = 0x07;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncX86_SIB_INDEX_SHIFT = 3;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncX86_SIB_SCALE_MASK = 0xc0;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncX86_SIB_SCALE_SMASK = 0x03;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncX86_SIB_SCALE_SHIFT = 6;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync## @}
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync## @name Prefixes
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync## @
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsyncX86_OP_PRF_CS = 0x2e;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncX86_OP_PRF_SS = 0x36;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncX86_OP_PRF_DS = 0x3e;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncX86_OP_PRF_ES = 0x26;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsyncX86_OP_PRF_FS = 0x64;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsyncX86_OP_PRF_GS = 0x65;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsyncX86_OP_PRF_SIZE_OP = 0x66;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncX86_OP_PRF_SIZE_ADDR = 0x67;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncX86_OP_PRF_LOCK = 0xf0;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncX86_OP_PRF_REPZ = 0xf2;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncX86_OP_PRF_REPNZ = 0xf3;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncX86_OP_REX_B = 0x41;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncX86_OP_REX_X = 0x42;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncX86_OP_REX_R = 0x44;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncX86_OP_REX_W = 0x48;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync## @}
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync## @name General registers
0c94a8282c9042b02f022302a3d987746140eab9vboxsync## @
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncX86_GREG_xAX = 0
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncX86_GREG_xCX = 1
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncX86_GREG_xDX = 2
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncX86_GREG_xBX = 3
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncX86_GREG_xSP = 4
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncX86_GREG_xBP = 5
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncX86_GREG_xSI = 6
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncX86_GREG_xDI = 7
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncX86_GREG_x8 = 8
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncX86_GREG_x9 = 9
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncX86_GREG_x10 = 10
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncX86_GREG_x11 = 11
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncX86_GREG_x12 = 12
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncX86_GREG_x13 = 13
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncX86_GREG_x14 = 14
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncX86_GREG_x15 = 15
0c94a8282c9042b02f022302a3d987746140eab9vboxsync## @}
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync## @name Register names.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync## @{
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncg_asGRegs64NoSp = ('rax', 'rcx', 'rdx', 'rbx', None, 'rbp', 'rsi', 'rdi', 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15');
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncg_asGRegs64 = ('rax', 'rcx', 'rdx', 'rbx', 'rsp', 'rbp', 'rsi', 'rdi', 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15');
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncg_asGRegs32NoSp = ('eax', 'ecx', 'edx', 'ebx', None, 'ebp', 'esi', 'edi',
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync 'r8d', 'r9d', 'r10d', 'r11d', 'r12d', 'r13d', 'r14d', 'r15d');
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncg_asGRegs32 = ('eax', 'ecx', 'edx', 'ebx', 'esp', 'ebp', 'esi', 'edi',
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync 'r8d', 'r9d', 'r10d', 'r11d', 'r12d', 'r13d', 'r14d', 'r15d');
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncg_asGRegs16NoSp = ('ax', 'cx', 'dx', 'bx', None, 'bp', 'si', 'di',
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync 'r8w', 'r9w', 'r10w', 'r11w', 'r12w', 'r13w', 'r14w', 'r15w');
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncg_asGRegs16 = ('ax', 'cx', 'dx', 'bx', 'sp', 'bp', 'si', 'di',
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync 'r8w', 'r9w', 'r10w', 'r11w', 'r12w', 'r13w', 'r14w', 'r15w');
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncg_asGRegs8 = ('al', 'cl', 'dl', 'bl', 'ah', 'ch', 'dh', 'bh');
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncg_asGRegs8Rex = ('al', 'cl', 'dl', 'bl', 'spl', 'bpl', 'sil', 'dil',
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync 'r8b', 'r9b', 'r10b', 'r11b', 'r12b', 'r13b', 'r14b', 'r15b',
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync 'ah', 'ch', 'dh', 'bh');
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync## @}
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync## @name Random
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync## @{
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncg_iMyRandSeed = int((os.urandom(4)).encode('hex'), 16);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#g_iMyRandSeed = 286523426;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#g_iMyRandSeed = 1994382324;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncg_oMyRand = random.Random(g_iMyRandSeed);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#g_oMyRand = random.SystemRandom();
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncdef randU8():
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ Unsigned 8-bit random number. """
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync return g_oMyRand.getrandbits(8);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncdef randU16():
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ Unsigned 16-bit random number. """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return g_oMyRand.getrandbits(16);
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncdef randU32():
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ Unsigned 32-bit random number. """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return g_oMyRand.getrandbits(32);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncdef randU64():
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync """ Unsigned 64-bit random number. """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return g_oMyRand.getrandbits(64);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncdef randUxx(cBits):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ Unsigned 8-, 16-, 32-, or 64-bit random number. """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return g_oMyRand.getrandbits(cBits);
1969e98a26e5b56b67fbe3b6bfa007f8f09e86ebvboxsync
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsyncdef randSxx(cBits):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ Signed 8-, 16-, 32-, or 64-bit random number. """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uVal = randUxx(cBits);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync iRet = uVal & ((1 << (cBits - 1)) - 1);
0c94a8282c9042b02f022302a3d987746140eab9vboxsync if iRet != uVal:
0c94a8282c9042b02f022302a3d987746140eab9vboxsync iRet = -iRet;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync return iRet;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncdef randUxxList(cBits, cElements):
0c94a8282c9042b02f022302a3d987746140eab9vboxsync """ List of unsigned 8-, 16-, 32-, or 64-bit random numbers. """
0c94a8282c9042b02f022302a3d987746140eab9vboxsync return [randUxx(cBits) for _ in range(cElements)];
0c94a8282c9042b02f022302a3d987746140eab9vboxsync## @}
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync## @name Instruction Emitter Helpers
0c94a8282c9042b02f022302a3d987746140eab9vboxsync## @{
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncdef calcRexPrefixForTwoModRmRegs(iReg, iRm, bOtherRexPrefixes = 0):
0c94a8282c9042b02f022302a3d987746140eab9vboxsync """
0c94a8282c9042b02f022302a3d987746140eab9vboxsync Calculates a rex prefix if neccessary given the two registers
0c94a8282c9042b02f022302a3d987746140eab9vboxsync and optional rex size prefixes.
0c94a8282c9042b02f022302a3d987746140eab9vboxsync Returns an empty array if not necessary.
0c94a8282c9042b02f022302a3d987746140eab9vboxsync """
0c94a8282c9042b02f022302a3d987746140eab9vboxsync bRex = bOtherRexPrefixes;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync if iReg >= 8:
0c94a8282c9042b02f022302a3d987746140eab9vboxsync bRex |= X86_OP_REX_R;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync if iRm >= 8:
0c94a8282c9042b02f022302a3d987746140eab9vboxsync bRex |= X86_OP_REX_B;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync if bRex == 0:
0c94a8282c9042b02f022302a3d987746140eab9vboxsync return [];
0c94a8282c9042b02f022302a3d987746140eab9vboxsync return [bRex,];
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncdef calcModRmForTwoRegs(iReg, iRm):
0c94a8282c9042b02f022302a3d987746140eab9vboxsync """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync Calculate the RM byte for two registers.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync Returns an array with one byte in it.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync bRm = (0x3 << X86_MODRM_MOD_SHIFT) \
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync | ((iReg << X86_MODRM_REG_SHIFT) & X86_MODRM_REG_MASK) \
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync | (iRm & X86_MODRM_RM_MASK);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return [bRm,];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync## @}
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync## @name Misc
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync## @{
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsyncdef convU32ToSigned(u32):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync """ Converts a 32-bit unsigned value to 32-bit signed. """
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if u32 < 0x80000000:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return u32;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return u32 - UINT32_MAX - 1;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsyncdef rotateLeftUxx(cBits, uVal, cShift):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ Rotate a xx-bit wide unsigned number to the left. """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync assert cShift < cBits;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if cBits == 16:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uMask = UINT16_MAX;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync elif cBits == 32:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uMask = UINT32_MAX;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync elif cBits == 64:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uMask = UINT64_MAX;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync else:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync assert cBits == 8;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uMask = UINT8_MAX;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uVal &= uMask;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uRet = (uVal << cShift) & uMask;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uRet |= (uVal >> (cBits - cShift));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return uRet;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncdef rotateRightUxx(cBits, uVal, cShift):
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync """ Rotate a xx-bit wide unsigned number to the right. """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync assert cShift < cBits;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if cBits == 16:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uMask = UINT16_MAX;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync elif cBits == 32:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uMask = UINT32_MAX;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync elif cBits == 64:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uMask = UINT64_MAX;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync else:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync assert cBits == 8;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uMask = UINT8_MAX;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uVal &= uMask;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uRet = (uVal >> cShift);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uRet |= (uVal << (cBits - cShift)) & uMask;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return uRet;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncdef gregName(iReg, cBits, fRexByteRegs = True):
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync """ Gets the name of a general register by index and width. """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if cBits == 64:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return g_asGRegs64[iReg];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if cBits == 32:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return g_asGRegs32[iReg];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if cBits == 16:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return g_asGRegs16[iReg];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync assert cBits == 8;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if fRexByteRegs:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return g_asGRegs8Rex[iReg];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return g_asGRegs8[iReg];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync## @}
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncclass TargetEnv(object):
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync Target Runtime Environment.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync ## @name CPU Modes
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync ## @{
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync ksCpuMode_Real = 'real';
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync ksCpuMode_Protect = 'prot';
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync ksCpuMode_Paged = 'paged';
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync ksCpuMode_Long = 'long';
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync ksCpuMode_V86 = 'v86';
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync ## @}
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync ## @name Instruction set.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync ## @{
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync ksInstrSet_16 = '16';
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync ksInstrSet_32 = '32';
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ksInstrSet_64 = '64';
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ## @}
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync def __init__(self, sName,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync sInstrSet = ksInstrSet_32,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync sCpuMode = ksCpuMode_Paged,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync iRing = 3,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync ):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.sName = sName;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.sInstrSet = sInstrSet;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.sCpuMode = sCpuMode;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.iRing = iRing;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.asGRegs = g_asGRegs64 if self.is64Bit() else g_asGRegs32;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.asGRegsNoSp = g_asGRegs64NoSp if self.is64Bit() else g_asGRegs32NoSp;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync def isUsingIprt(self):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ Whether it's an IPRT environment or not. """
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync return self.sName.startswith('iprt');
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync def is64Bit(self):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ Whether it's a 64-bit environment or not. """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return self.sInstrSet == self.ksInstrSet_64;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync def getDefOpBits(self):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ Get the default operand size as a bit count. """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if self.sInstrSet == self.ksInstrSet_16:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return 16;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return 32;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync def getDefOpBytes(self):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ Get the default operand size as a byte count. """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return self.getDefOpBits() / 8;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync def getMaxOpBits(self):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ Get the max operand size as a bit count. """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if self.sInstrSet == self.ksInstrSet_64:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return 64;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return 32;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync def getMaxOpBytes(self):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ Get the max operand size as a byte count. """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return self.getMaxOpBits() / 8;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync def getDefAddrBits(self):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ Get the default address size as a bit count. """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if self.sInstrSet == self.ksInstrSet_16:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return 16;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if self.sInstrSet == self.ksInstrSet_32:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return 32;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return 64;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync def getDefAddrBytes(self):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync """ Get the default address size as a byte count. """
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return self.getDefAddrBits() / 8;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync def getGRegCount(self, cbEffBytes = 4):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync """ Get the number of general registers. """
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if self.sInstrSet == self.ksInstrSet_64:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if cbEffBytes == 1:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return 16 + 4;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return 16;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return 8;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync def randGRegNoSp(self, cbEffBytes = 4):
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync """ Returns a random general register number, excluding the SP register. """
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync iReg = randU16() % self.getGRegCount(cbEffBytes);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync while iReg == X86_GREG_xSP:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync iReg = randU16() % self.getGRegCount(cbEffBytes);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return iReg;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync def randGRegNoSpList(self, cItems, cbEffBytes = 4):
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync """ List of randGRegNoSp values. """
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync aiRegs = [];
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync for _ in range(cItems):
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync aiRegs.append(self.randGRegNoSp(cbEffBytes));
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return aiRegs;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync def getAddrModes(self):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync """ Gets a list of addressing mode (16, 32, or/and 64). """
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if self.sInstrSet == self.ksInstrSet_16:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return [16, 32];
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if self.sInstrSet == self.ksInstrSet_32:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return [32, 16];
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return [64, 32];
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync def is8BitHighGReg(self, cbEffOp, iGReg):
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync """ Checks if the given register is a high 8-bit general register (AH, CH, DH or BH). """
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync assert cbEffOp in [1, 2, 4, 8];
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if cbEffOp == 1:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if iGReg >= 16:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return True;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if iGReg >= 4 and not self.is64Bit():
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return True;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return False;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync## Target environments.
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncg_dTargetEnvs = {
0c94a8282c9042b02f022302a3d987746140eab9vboxsync 'iprt-r3-32': TargetEnv('iprt-r3-32', TargetEnv.ksInstrSet_32, TargetEnv.ksCpuMode_Protect, 3),
0c94a8282c9042b02f022302a3d987746140eab9vboxsync 'iprt-r3-64': TargetEnv('iprt-r3-64', TargetEnv.ksInstrSet_64, TargetEnv.ksCpuMode_Long, 3),
0c94a8282c9042b02f022302a3d987746140eab9vboxsync 'bs2-r0-64': TargetEnv('bs2-r0-64', TargetEnv.ksInstrSet_64, TargetEnv.ksCpuMode_Long, 0),
0c94a8282c9042b02f022302a3d987746140eab9vboxsync};
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsyncclass InstrTestBase(object):
0c94a8282c9042b02f022302a3d987746140eab9vboxsync """
0c94a8282c9042b02f022302a3d987746140eab9vboxsync Base class for testing one instruction.
0c94a8282c9042b02f022302a3d987746140eab9vboxsync """
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync def __init__(self, sName, sInstr = None):
0c94a8282c9042b02f022302a3d987746140eab9vboxsync self.sName = sName;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync self.sInstr = sInstr if sInstr else sName.split()[0];
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync def isApplicable(self, oGen):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync """
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync Tests if the instruction test is applicable to the selected environment.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync """
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync _ = oGen;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return True;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync def generateTest(self, oGen, sTestFnName):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync Emits the test assembly code.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync """
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.write(';; @todo not implemented. This is for the linter: %s, %s\n' % (oGen, sTestFnName));
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return True;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync def generateInputs(self, cbEffOp, cbMaxOp, oGen, fLong = False):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ Generate a list of inputs. """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if fLong:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync #
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync # Try do extremes as well as different ranges of random numbers.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync #
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync auRet = [0, 1, ];
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if cbMaxOp >= 1:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync auRet += [ UINT8_MAX / 2, UINT8_MAX / 2 + 1, UINT8_MAX ];
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if cbMaxOp >= 2:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync auRet += [ UINT16_MAX / 2, UINT16_MAX / 2 + 1, UINT16_MAX ];
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if cbMaxOp >= 4:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync auRet += [ UINT32_MAX / 2, UINT32_MAX / 2 + 1, UINT32_MAX ];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if cbMaxOp >= 8:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync auRet += [ UINT64_MAX / 2, UINT64_MAX / 2 + 1, UINT64_MAX ];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if oGen.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny:
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync for cBits, cValues in ( (8, 4), (16, 4), (32, 8), (64, 8) ):
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync if cBits < cbMaxOp * 8:
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync auRet += randUxxList(cBits, cValues);
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync cWanted = 16;
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync elif oGen.oOptions.sTestSize == InstructionTestGen.ksTestSize_Medium:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync for cBits, cValues in ( (8, 8), (16, 8), (24, 2), (32, 16), (40, 1), (48, 1), (56, 1), (64, 16) ):
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if cBits < cbMaxOp * 8:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync auRet += randUxxList(cBits, cValues);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync cWanted = 64;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync else:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync for cBits, cValues in ( (8, 16), (16, 16), (24, 4), (32, 64), (40, 4), (48, 4), (56, 4), (64, 64) ):
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if cBits < cbMaxOp * 8:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync auRet += randUxxList(cBits, cValues);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync cWanted = 168;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if len(auRet) < cWanted:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync auRet += randUxxList(cbEffOp * 8, cWanted - len(auRet));
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync else:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync #
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync # Short list, just do some random numbers.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync #
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync auRet = [];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if oGen.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync auRet += randUxxList(cbMaxOp, 1);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync elif oGen.oOptions.sTestSize == InstructionTestGen.ksTestSize_Medium:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync auRet += randUxxList(cbMaxOp, 2);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync else:
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync auRet = [];
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync for cBits in (8, 16, 32, 64):
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync if cBits < cbMaxOp * 8:
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync auRet += randUxxList(cBits, 1);
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync return auRet;
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsyncclass InstrTest_MemOrGreg_2_Greg(InstrTestBase):
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync Instruction reading memory or general register and writing the result to a
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync general register.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync """
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync def __init__(self, sName, fnCalcResult, sInstr = None, acbOpVars = None):
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync InstrTestBase.__init__(self, sName, sInstr);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync self.fnCalcResult = fnCalcResult;
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync self.acbOpVars = [ 1, 2, 4, 8 ] if not acbOpVars else list(acbOpVars);
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync ## @name Test Instruction Writers
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync ## @{
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync def writeInstrGregGreg(self, cbEffOp, iOp1, iOp2, oGen):
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync """ Writes the instruction with two general registers as operands. """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync fRexByteRegs = oGen.oTarget.is64Bit();
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync oGen.write(' %s %s, %s\n'
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync % (self.sInstr, gregName(iOp1, cbEffOp * 8, fRexByteRegs), gregName(iOp2, cbEffOp * 8, fRexByteRegs),));
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync return True;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync def writeInstrGregPureRM(self, cbEffOp, iOp1, cAddrBits, iOp2, iMod, offDisp, oGen):
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync """ Writes the instruction with two general registers as operands. """
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync oGen.write(' ');
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if iOp2 == 13 and iMod == 0 and cAddrBits == 64:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync oGen.write('altrexb '); # Alternative encoding for rip relative addressing.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if cbEffOp == 8:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync oGen.write('%s %s, [' % (self.sInstr, g_asGRegs64[iOp1],));
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync elif cbEffOp == 4:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync oGen.write('%s %s, [' % (self.sInstr, g_asGRegs32[iOp1],));
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync elif cbEffOp == 2:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync oGen.write('%s %s, [' % (self.sInstr, g_asGRegs16[iOp1],));
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync elif cbEffOp == 1:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync oGen.write('%s %s, [' % (self.sInstr, g_asGRegs8Rex[iOp1],));
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync else:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync assert False;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if (iOp2 == 5 or iOp2 == 13) and iMod == 0:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write('VBINSTST_NAME(g_u%sData)' % (cbEffOp * 8,))
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if oGen.oTarget.is64Bit():
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(' wrt rip');
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync else:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if iMod == 1:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync oGen.write('byte %d + ' % (offDisp,));
0c94a8282c9042b02f022302a3d987746140eab9vboxsync elif iMod == 2:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write('dword %d + ' % (offDisp,));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync else:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync assert iMod == 0;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if cAddrBits == 64:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(g_asGRegs64[iOp2]);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync elif cAddrBits == 32:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(g_asGRegs32[iOp2]);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync elif cAddrBits == 16:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync assert False; ## @todo implement 16-bit addressing.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync assert False, str(cAddrBits);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.write(']\n');
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return True;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync def writeInstrGregSibLabel(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen):
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync """ Writes the instruction taking a register and a label (base only w/o reg), SIB form. """
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync assert offDisp is None; assert iBaseReg in [5, 13]; assert iIndexReg == 4; assert cAddrBits != 16;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if cAddrBits == 64:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync # Note! Cannot test this in 64-bit mode in any sensible way because the disp is 32-bit
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync # and we cannot (yet) make assumtions about where we're loaded.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync ## @todo Enable testing this in environments where we can make assumptions (boot sector).
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.write(' %s %s, [VBINSTST_NAME(g_u%sData) xWrtRIP]\n'
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync % ( self.sInstr, gregName(iOp1, cbEffOp * 8), cbEffOp * 8,));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync else:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(' altsibx%u %s %s, [VBINSTST_NAME(g_u%sData) xWrtRIP]\n'
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync % ( iScale, self.sInstr, gregName(iOp1, cbEffOp * 8), cbEffOp * 8,));
0c94a8282c9042b02f022302a3d987746140eab9vboxsync return True;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync def writeInstrGregSibScaledReg(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen):
0c94a8282c9042b02f022302a3d987746140eab9vboxsync """ Writes the instruction taking a register and disp+scaled register (no base reg), SIB form. """
0c94a8282c9042b02f022302a3d987746140eab9vboxsync assert iBaseReg in [5, 13]; assert iIndexReg != 4; assert cAddrBits != 16;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync # Note! Using altsibxN to force scaled encoding. This is only really a
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync # necessity for iScale=1, but doesn't hurt for the rest.
0c94a8282c9042b02f022302a3d987746140eab9vboxsync oGen.write(' altsibx%u %s %s, [%s * %#x'
0c94a8282c9042b02f022302a3d987746140eab9vboxsync % (iScale, self.sInstr, gregName(iOp1, cbEffOp * 8), gregName(iIndexReg, cAddrBits), iScale,));
0c94a8282c9042b02f022302a3d987746140eab9vboxsync if offDisp is not None:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync oGen.write(' + %#x' % (offDisp,));
0c94a8282c9042b02f022302a3d987746140eab9vboxsync oGen.write(']\n');
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync _ = iBaseReg;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return True;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync def writeInstrGregSibBase(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync """ Writes the instruction taking a register and base only (with reg), SIB form. """
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync oGen.write(' altsibx%u %s %s, [%s'
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync % (iScale, self.sInstr, gregName(iOp1, cbEffOp * 8), gregName(iBaseReg, cAddrBits),));
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if offDisp is not None:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync oGen.write(' + %#x' % (offDisp,));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(']\n');
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync _ = iIndexReg;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return True;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync def writeInstrGregSibBaseAndScaledReg(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen):
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync """ Writes tinstruction taking a register and full featured SIB form address. """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync # Note! From the looks of things, yasm will encode the following instructions the same way:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync # mov eax, [rsi*1 + rbx]
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync # mov eax, [rbx + rsi*1]
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync # So, when there are two registers involved, the '*1' selects
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync # which is index and which is base.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(' %s %s, [%s + %s * %u'
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync % ( self.sInstr, gregName(iOp1, cbEffOp * 8),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync gregName(iBaseReg, cAddrBits), gregName(iIndexReg, cAddrBits), iScale,));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if offDisp is not None:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(' + %#x' % (offDisp,));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(']\n');
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return True;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync ## @}
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync ## @name Memory setups
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync ## @{
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync def generateMemSetupReadByLabel(self, oGen, cbEffOp, uInput):
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync """ Sets up memory for a memory read. """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.pushConst(uInput);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(' call VBINSTST_NAME(Common_SetupMemReadU%u)\n' % (cbEffOp*8,));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return True;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync def generateMemSetupReadByReg(self, oGen, cAddrBits, cbEffOp, iReg1, uInput, offDisp = None):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync """ Sets up memory for a memory read indirectly addressed thru one register and optional displacement. """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.pushConst(uInput);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(' call VBINSTST_NAME(%s)\n'
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, iBaseReg = iReg1, offDisp = offDisp),));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iReg1],));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return True;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync def generateMemSetupReadByScaledReg(self, oGen, cAddrBits, cbEffOp, iIndexReg, iScale, uInput, offDisp = None):
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync """ Sets up memory for a memory read indirectly addressed thru one register and optional displacement. """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.pushConst(uInput);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(' call VBINSTST_NAME(%s)\n'
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, offDisp = offDisp, iIndexReg = iIndexReg, iScale = iScale),));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iIndexReg],));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return True;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync def generateMemSetupReadByBaseAndScaledReg(self, oGen, cAddrBits, cbEffOp, iBaseReg, iIndexReg, iScale, uInput, offDisp):
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync """ Sets up memory for a memory read indirectly addressed thru two registers with optional displacement. """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.pushConst(uInput);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(' call VBINSTST_NAME(%s)\n'
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, iBaseReg = iBaseReg, offDisp = offDisp,
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync iIndexReg = iIndexReg, iScale = iScale),));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iIndexReg],));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iBaseReg],));
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return True;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync def generateMemSetupPureRM(self, oGen, cAddrBits, cbEffOp, iOp2, iMod, uInput, offDisp = None):
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync """ Sets up memory for a pure R/M addressed read, iOp2 being the R/M value. """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.pushConst(uInput);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync assert offDisp is None or iMod != 0;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if (iOp2 != 5 and iOp2 != 13) or iMod != 0:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.write(' call VBINSTST_NAME(%s)\n'
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, iOp2, offDisp),));
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync else:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync oGen.write(' call VBINSTST_NAME(Common_SetupMemReadU%u)\n' % (cbEffOp*8,));
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iOp2],));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return True;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync ## @}
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync def generateOneStdTestGregGreg(self, oGen, cbEffOp, cbMaxOp, iOp1, iOp1X, iOp2, iOp2X, uInput, uResult):
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync """ Generate one standard instr greg,greg test. """
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2X], uInput,));
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if iOp1X != iOp2X:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iOp2X],));
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync self.writeInstrGregGreg(cbEffOp, iOp1, iOp2, oGen);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.pushConst(uResult);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(iOp1X, iOp2X if iOp1X != iOp2X else None),));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync _ = cbMaxOp;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return True;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync def generateOneStdTestGregGreg8BitHighPain(self, oGen, cbEffOp, cbMaxOp, iOp1, iOp2, uInput):
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync """ High 8-bit registers are a real pain! """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync assert oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1) or oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2);
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync # Figure out the register indexes of the max op sized regs involved.
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync iOp1X = iOp1 & 3;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync iOp2X = iOp2 & 3;
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync oGen.write(' ; iOp1=%u iOp1X=%u iOp2=%u iOp2X=%u\n' % (iOp1, iOp1X, iOp2, iOp2X,));
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync # Calculate unshifted result.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if iOp1X != iOp2X:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync uCur = oGen.auRegValues[iOp1X];
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync uCur = rotateRightUxx(cbMaxOp * 8, uCur, 8);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync else:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync uCur = uInput;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1) != oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2):
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1):
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uCur = rotateRightUxx(cbMaxOp * 8, uCur, 8);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync else:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uCur = rotateLeftUxx(cbMaxOp * 8, uCur, 8);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uResult = self.fnCalcResult(cbEffOp, uInput, uCur, oGen);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync # Rotate the input and/or result to match their max-op-sized registers.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync uInput = rotateLeftUxx(cbMaxOp * 8, uInput, 8);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1):
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uResult = rotateLeftUxx(cbMaxOp * 8, uResult, 8);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync # Hand it over to an overridable worker method.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return self.generateOneStdTestGregGreg(oGen, cbEffOp, cbMaxOp, iOp1, iOp1X, iOp2, iOp2X, uInput, uResult);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync def generateOneStdTestGregMemNoSib(self, oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, iOp2, uInput, uResult):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync """ Generate mode 0, 1 and 2 test for the R/M=iOp2. """
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if cAddrBits == 16:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync _ = cbMaxOp;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync iMod = 0; # No disp, except for i=5.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.generateMemSetupPureRM(oGen, cAddrBits, cbEffOp, iOp2, iMod, uInput);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.writeInstrGregPureRM(cbEffOp, iOp1, cAddrBits, iOp2, iMod, None, oGen);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.pushConst(uResult);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(iOp1, iOp2),));
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if iOp2 != 5 and iOp2 != 13:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync iMod = 1;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync for offDisp in oGen.getDispForMod(iMod):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync self.generateMemSetupPureRM(oGen, cAddrBits, cbEffOp, iOp2, iMod, uInput, offDisp);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync self.writeInstrGregPureRM(cbEffOp, iOp1, cAddrBits, iOp2, iMod, offDisp, oGen);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync oGen.pushConst(uResult);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(iOp1, iOp2),));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync iMod = 2;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync for offDisp in oGen.getDispForMod(iMod):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.generateMemSetupPureRM(oGen, cAddrBits, cbEffOp, iOp2, iMod, uInput, offDisp);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.writeInstrGregPureRM(cbEffOp, iOp1, cAddrBits, iOp2, iMod, offDisp, oGen);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.pushConst(uResult);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(iOp1, iOp2),));
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
9c9db71d639cf066ed41d49629d46d48bff4be2fvboxsync return True;
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync def generateOneStdTestGregMemSib(self, oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, iMod, # pylint: disable=R0913
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync iBaseReg, iIndexReg, iScale, uInput, uResult):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync """ Generate one SIB variations. """
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync for offDisp in oGen.getDispForMod(iMod, cbEffOp):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if ((iBaseReg == 5 or iBaseReg == 13) and iMod == 0):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if iIndexReg == 4:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if cAddrBits == 64:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync continue; # skipping.
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.generateMemSetupReadByLabel(oGen, cbEffOp, uInput);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.writeInstrGregSibLabel(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync sChecker = oGen.needGRegChecker(iOp1);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.generateMemSetupReadByScaledReg(oGen, cAddrBits, cbEffOp, iIndexReg, iScale, uInput, offDisp);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.writeInstrGregSibScaledReg(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync sChecker = oGen.needGRegChecker(iOp1, iIndexReg);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if iIndexReg == 4:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.generateMemSetupReadByReg(oGen, cAddrBits, cbEffOp, iBaseReg, uInput, offDisp);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.writeInstrGregSibBase(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync sChecker = oGen.needGRegChecker(iOp1, iBaseReg);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if iIndexReg == iBaseReg and iScale == 1 and offDisp is not None and (offDisp & 1):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if offDisp < 0: offDisp += 1;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else: offDisp -= 1;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.generateMemSetupReadByBaseAndScaledReg(oGen, cAddrBits, cbEffOp, iBaseReg,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync iIndexReg, iScale, uInput, offDisp);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.writeInstrGregSibBaseAndScaledReg(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync sChecker = oGen.needGRegChecker(iOp1, iBaseReg, iIndexReg);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.pushConst(uResult);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (sChecker,));
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync _ = cbMaxOp;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return True;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync def generateStdTestGregMemSib(self, oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, auInputs):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync """ Generate all SIB variations for the given iOp1 (reg) value. """
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync assert cAddrBits in [32, 64];
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync i = oGen.cSibBasePerRun;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync while i > 0:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync oGen.iSibBaseReg = (oGen.iSibBaseReg + 1) % oGen.oTarget.getGRegCount(cAddrBits / 8);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if oGen.iSibBaseReg == X86_GREG_xSP: # no RSP testing atm.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync continue;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync j = oGen.getSibIndexPerRun();
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync while j > 0:
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync oGen.iSibIndexReg = (oGen.iSibIndexReg + 1) % oGen.oTarget.getGRegCount(cAddrBits / 8);
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync if oGen.iSibIndexReg == iOp1 and oGen.iSibIndexReg != 4 and cAddrBits != cbMaxOp:
9c9db71d639cf066ed41d49629d46d48bff4be2fvboxsync continue; # Don't know the high bit of the address ending up the result - skip it for now.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync for iMod in [0, 1, 2]:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if oGen.iSibBaseReg == iOp1 \
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync and ((oGen.iSibBaseReg != 5 and oGen.iSibBaseReg != 13) or iMod != 0) \
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync and cAddrBits != cbMaxOp:
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync continue; # Don't know the high bit of the address ending up the result - skip it for now.
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync for _ in oGen.oSibScaleRange:
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync oGen.iSibScale *= 2;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if oGen.iSibScale > 8:
9c9db71d639cf066ed41d49629d46d48bff4be2fvboxsync oGen.iSibScale = 1;
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync for uInput in auInputs:
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync oGen.newSubTest();
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync uResult = self.fnCalcResult(cbEffOp, uInput, oGen.auRegValues[iOp1], oGen);
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync self.generateOneStdTestGregMemSib(oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, iMod,
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync oGen.iSibBaseReg, oGen.iSibIndexReg, oGen.iSibScale,
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync uInput, uResult);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync j -= 1;
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync i -= 1;
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync return True;
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync def generateStandardTests(self, oGen):
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync """ Generate standard tests. """
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync # Parameters.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync cbDefOp = oGen.oTarget.getDefOpBytes();
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync cbMaxOp = oGen.oTarget.getMaxOpBytes();
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync auShortInputs = self.generateInputs(cbDefOp, cbMaxOp, oGen);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync auLongInputs = self.generateInputs(cbDefOp, cbMaxOp, oGen, fLong = True);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync iLongOp1 = oGen.oTarget.randGRegNoSp();
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync iLongOp2 = oGen.oTarget.randGRegNoSp();
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # Register tests
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if True:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync for cbEffOp in self.acbOpVars:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if cbEffOp > cbMaxOp:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync continue;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oOp2Range = range(oGen.oTarget.getGRegCount(cbEffOp));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if oGen.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oOp2Range = [iLongOp2,];
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync oGen.write('; cbEffOp=%u\n' % (cbEffOp,));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync for iOp1 in range(oGen.oTarget.getGRegCount(cbEffOp)):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if iOp1 == X86_GREG_xSP:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync continue; # Cannot test xSP atm.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync for iOp2 in oOp2Range:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (iOp2 >= 16 and iOp1 in range(4, 16)) \
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync or (iOp1 >= 16 and iOp2 in range(4, 16)):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync continue; # Any REX encoding turns AH,CH,DH,BH regs into SPL,BPL,SIL,DIL.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if iOp2 == X86_GREG_xSP:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync continue; # Cannot test xSP atm.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oGen.write('; iOp2=%u cbEffOp=%u\n' % (iOp2, cbEffOp));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync for uInput in (auLongInputs if iOp1 == iLongOp1 and iOp2 == iLongOp2 else auShortInputs):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oGen.newSubTest();
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if not oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1) and not oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2):
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync uCur = oGen.auRegValues[iOp1 & 15] if iOp1 != iOp2 else uInput;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync uResult = self.fnCalcResult(cbEffOp, uInput, uCur, oGen);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync self.generateOneStdTestGregGreg(oGen, cbEffOp, cbMaxOp, iOp1, iOp1 & 15, iOp2, iOp2 & 15,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync uInput, uResult);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync else:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync self.generateOneStdTestGregGreg8BitHighPain(oGen, cbEffOp, cbMaxOp, iOp1, iOp2, uInput);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync # Memory test.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if True:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync for cAddrBits in oGen.oTarget.getAddrModes():
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync for cbEffOp in self.acbOpVars:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if cbEffOp > cbMaxOp:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync continue;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync for _ in oGen.getModRegRange(cbEffOp):
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync oGen.iModReg = (oGen.iModReg + 1) % oGen.oTarget.getGRegCount(cbEffOp);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if oGen.iModReg == X86_GREG_xSP:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync continue; # Cannot test xSP atm.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if oGen.iModReg > 15:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync continue; ## TODO AH,CH,DH,BH
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync auInputs = auLongInputs if oGen.iModReg == iLongOp1 else auShortInputs;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync for _ in oGen.oModRmRange:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync oGen.iModRm = (oGen.iModRm + 1) % oGen.oTarget.getGRegCount(cAddrBits * 8);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if oGen.iModRm != 4 or cAddrBits == 16:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync for uInput in auInputs:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync oGen.newSubTest();
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if oGen.iModReg == oGen.iModRm and oGen.iModRm != 5 \
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync and oGen.iModRm != 13 and cbEffOp != cbMaxOp:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync continue; # Don't know the high bit of the address ending up the result - skip it for now.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync uResult = self.fnCalcResult(cbEffOp, uInput, oGen.auRegValues[oGen.iModReg & 15], oGen);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync self.generateOneStdTestGregMemNoSib(oGen, cAddrBits, cbEffOp, cbMaxOp,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync oGen.iModReg, oGen.iModRm, uInput, uResult);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync else:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync # SIB - currently only short list of inputs or things may get seriously out of hand.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync self.generateStdTestGregMemSib(oGen, cAddrBits, cbEffOp, cbMaxOp, oGen.iModReg, auShortInputs);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync #break;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync #break;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return True;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync def generateTest(self, oGen, sTestFnName):
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync oGen.write('VBINSTST_BEGINPROC %s\n' % (sTestFnName,));
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync #oGen.write(' int3\n');
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync self.generateStandardTests(oGen);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync #oGen.write(' int3\n');
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync oGen.write(' ret\n');
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync oGen.write('VBINSTST_ENDPROC %s\n' % (sTestFnName,));
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return True;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsyncclass InstrTest_Mov_Gv_Ev(InstrTest_MemOrGreg_2_Greg):
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync """
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync Tests MOV Gv,Ev.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync """
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync def __init__(self):
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync InstrTest_MemOrGreg_2_Greg.__init__(self, 'mov Gv,Ev', self.calc_mov);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync @staticmethod
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync def calc_mov(cbEffOp, uInput, uCur, oGen):
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync """ Calculates the result of a mov instruction."""
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync if cbEffOp == 8:
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync return uInput & UINT64_MAX;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if cbEffOp == 4:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return uInput & UINT32_MAX;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if cbEffOp == 2:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return (uCur & 0xffffffffffff0000) | (uInput & UINT16_MAX);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync assert cbEffOp == 1; _ = oGen;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return (uCur & 0xffffffffffffff00) | (uInput & UINT8_MAX);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsyncclass InstrTest_MovSxD_Gv_Ev(InstrTest_MemOrGreg_2_Greg):
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync """
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync Tests MOVSXD Gv,Ev.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync """
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync def __init__(self):
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync InstrTest_MemOrGreg_2_Greg.__init__(self, 'movsxd Gv,Ev', self.calc_movsxd, acbOpVars = [ 8, 4, 2, ]);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync def writeInstrGregGreg(self, cbEffOp, iOp1, iOp2, oGen):
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if cbEffOp == 8:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync oGen.write(' %s %s, %s\n' % (self.sInstr, g_asGRegs64[iOp1], g_asGRegs32[iOp2]));
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync elif cbEffOp == 4 or cbEffOp == 2:
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync abInstr = [];
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync if cbEffOp != oGen.oTarget.getDefOpBytes():
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync abInstr.append(X86_OP_PRF_SIZE_OP);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync abInstr += calcRexPrefixForTwoModRmRegs(iOp1, iOp2);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync abInstr.append(0x63);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync abInstr += calcModRmForTwoRegs(iOp1, iOp2);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync oGen.writeInstrBytes(abInstr);
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync else:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync assert False;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync assert False;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync return True;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync def isApplicable(self, oGen):
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return oGen.oTarget.is64Bit();
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync @staticmethod
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync def calc_movsxd(cbEffOp, uInput, uCur, oGen):
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync """
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync Calculates the result of a movxsd instruction.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync Returns the result value (cbMaxOp sized).
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync """
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync _ = oGen;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if cbEffOp == 8 and (uInput & RT_BIT_32(31)):
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return (UINT32_MAX << 32) | (uInput & UINT32_MAX);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if cbEffOp == 2:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return (uCur & 0xffffffffffff0000) | (uInput & 0xffff);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync return uInput & UINT32_MAX;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsyncclass InstrTest_DivIDiv(InstrTestBase):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync """
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync Tests IDIV and DIV instructions.
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync """
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync def __init__(self, fIsIDiv):
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if not fIsIDiv:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync InstrTestBase.__init__(self, 'div Gv,Ev', 'div');
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync else:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync InstrTestBase.__init__(self, 'idiv Gv,Ev', 'idiv');
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync self.fIsIDiv = fIsIDiv;
e70bda5438c3582164d26f171a8bc8d3d7da1e12vboxsync
e70bda5438c3582164d26f171a8bc8d3d7da1e12vboxsync def generateInputsNoXcpt(self, cbEffOp, fLong = False):
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync """ Generate inputs for cbEffOp. Returns a list of pairs, dividen + divisor. """
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync # Test params.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync uStep = 1 << (cbEffOp * 8);
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync if self.fIsIDiv:
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync uStep /= 2;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync # edge tests
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync auRet = [];
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
e70bda5438c3582164d26f171a8bc8d3d7da1e12vboxsync uDivisor = 1 if fLong else 3;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync uDividend = uStep * uDivisor - 1;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync for i in range(5 if fLong else 3):
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync auRet.append([uDividend, uDivisor]);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if self.fIsIDiv:
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync auRet.append([-uDividend, -uDivisor]);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync auRet.append([-(uDividend + uDivisor - 1), uDivisor]);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync auRet.append([ (uDividend + uDivisor - 1), -uDivisor]);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if i <= 3 and fLong:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync auRet.append([uDividend - 1, uDivisor]);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if self.fIsIDiv:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync auRet.append([-(uDividend - 1), -uDivisor]);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync uDivisor += 1;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync uDividend += uStep;
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync uDivisor = uStep - 1;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync uDividend = uStep * uDivisor - 1;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync for _ in range(3 if fLong else 1):
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync auRet.append([uDividend, uDivisor]);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if self.fIsIDiv:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync auRet.append([-uDividend, -uDivisor]);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync uDivisor -= 1;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync uDividend -= uStep;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if self.fIsIDiv:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync uDivisor = -uStep;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync for _ in range(3 if fLong else 1):
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync auRet.append([uDivisor * (uDivisor - 1) - 1, uDivisor]);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync uDivisor += 1
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync uDivisor = uStep - 1;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync for _ in range(3 if fLong else 1):
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync auRet.append([-(uDivisor * (uDivisor + 1) - 1), uDivisor]);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync uDivisor -= 1
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync # random tests.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if self.fIsIDiv:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync for _ in range(6 if fLong else 2):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync while True:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uDivisor = randSxx(cbEffOp * 4);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if uDivisor == 0 or uDivisor >= uStep or uDivisor < -uStep:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync continue;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uDividend = randSxx(cbEffOp * 8);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uResult = uDividend / uDivisor;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if uResult >= uStep or uResult <= -uStep: # exclude difficulties
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync continue;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync break;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync auRet.append([uDividend, uDivisor]);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync else:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync for _ in range(6 if fLong else 2):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync while True:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uDivisor = randUxx(cbEffOp * 4);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if uDivisor == 0 or uDivisor >= uStep:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync continue;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uDividend = randUxx(cbEffOp * 8);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uResult = uDividend / uDivisor;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if uResult >= uStep:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync continue;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync break;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync auRet.append([uDividend, uDivisor]);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return auRet;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync def generateOneStdTestGreg(self, oGen, cbEffOp, iOp2, iDividend, iDivisor):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ Generate code of one '[I]DIV rDX:rAX,<GREG>' test. """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync cbMaxOp = oGen.oTarget.getMaxOpBytes();
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync fEffOp = ((1 << (cbEffOp *8) ) - 1);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync fMaxOp = UINT64_MAX if cbMaxOp == 8 else UINT32_MAX; assert cbMaxOp in [8, 4];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync fTopOp = fMaxOp - fEffOp;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync fFullOp1 = ((1 << (cbEffOp*16)) - 1);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uAX = iDividend & fFullOp1; # full with unsigned
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uDX = uAX >> (cbEffOp*8);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uAX &= fEffOp;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uOp2Val = iDivisor & fEffOp;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync iQuotient = iDividend / iDivisor;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync iReminder = iDividend % iDivisor;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if iReminder != 0 and iQuotient < 0: # python has different rounding rules for negative division.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync iQuotient += 1;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync iReminder -= iDivisor;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uAXResult = iQuotient & fEffOp;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uDXResult = iReminder & fEffOp;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if cbEffOp < cbMaxOp:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uAX |= randUxx(cbMaxOp * 8) & fTopOp;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uDX |= randUxx(cbMaxOp * 8) & fTopOp;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uOp2Val |= randUxx(cbMaxOp * 8) & fTopOp;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if cbEffOp < 4:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uAXResult |= uAX & fTopOp;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uDXResult |= uDX & fTopOp;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oGen.write(' ; iDividend=%#x (%d) iDivisor=%#x (%d)\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ' ; iQuotient=%#x (%d) iReminder=%#x (%d)\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync % ( iDividend & fFullOp1, iDividend, iDivisor & fEffOp, iDivisor,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync iQuotient & fEffOp, iQuotient, iReminder & fEffOp, iReminder, ));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[X86_GREG_xDX], uDX,));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[X86_GREG_xAX], uAX,));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2], uOp2Val,));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
8f7ee9e453c60b3b699799538a45950b35266665vboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iOp2],));
8f7ee9e453c60b3b699799538a45950b35266665vboxsync oGen.pushConst(uDXResult);
8f7ee9e453c60b3b699799538a45950b35266665vboxsync oGen.pushConst(uAXResult);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oGen.write(' %-4s %s\n' % (self.sInstr, gregName(iOp2, cbEffOp * 8),));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(X86_GREG_xAX, X86_GREG_xDX, iOp2),));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return True;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync def generateOneStdTestGreg8Bit(self, oGen, cbEffOp, iOp2, iDividend, iDivisor):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """ Generate code of one '[I]DIV AX,<GREG>' test (8-bit). """
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync cbMaxOp = oGen.oTarget.getMaxOpBytes();
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync fMaxOp = UINT64_MAX if cbMaxOp == 8 else UINT32_MAX; assert cbMaxOp in [8, 4];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync iOp2X = (iOp2 & 3) if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2) else iOp2;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync assert iOp2X != X86_GREG_xAX;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uAX = iDividend & UINT16_MAX; # full with unsigned
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uOp2Val = iDivisor & UINT8_MAX;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync iQuotient = iDividend / iDivisor;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync iReminder = iDividend % iDivisor;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if iReminder != 0 and iQuotient < 0: # python has different rounding rules for negative division.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync iQuotient += 1;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync iReminder -= iDivisor;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uAXResult = (iQuotient & UINT8_MAX) | ((iReminder & UINT8_MAX) << 8);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uAX |= randUxx(cbMaxOp * 8) & (fMaxOp - UINT16_MAX);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uAXResult |= uAX & (fMaxOp - UINT16_MAX);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync uOp2Val |= randUxx(cbMaxOp * 8) & (fMaxOp - UINT8_MAX);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if iOp2X != iOp2:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync uOp2Val = rotateLeftUxx(cbMaxOp * 8, uOp2Val, 8);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync oGen.write(' ; iDividend=%#x (%d) iDivisor=%#x (%d)\n'
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync ' ; iQuotient=%#x (%d) iReminder=%#x (%d)\n'
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync % ( iDividend & UINT16_MAX, iDividend, iDivisor & UINT8_MAX, iDivisor,
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync iQuotient & UINT8_MAX, iQuotient, iReminder & UINT8_MAX, iReminder, ));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[X86_GREG_xAX], uAX,));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2X], uOp2Val,));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iOp2X],));
8f7ee9e453c60b3b699799538a45950b35266665vboxsync oGen.pushConst(uAXResult);
8f7ee9e453c60b3b699799538a45950b35266665vboxsync
8f7ee9e453c60b3b699799538a45950b35266665vboxsync oGen.write(' %-4s %s\n' % (self.sInstr, gregName(iOp2, cbEffOp * 8),));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(X86_GREG_xAX, iOp2X),));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync return;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync def generateStandardTests(self, oGen):
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync """ Generates test that causes no exceptions. """
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync # Parameters.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync iLongOp2 = oGen.oTarget.randGRegNoSp();
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync # Register tests
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if True:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync for cbEffOp in ( 8, 4, 2, 1 ):
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if cbEffOp > oGen.oTarget.getMaxOpBytes():
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync continue;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync oGen.write('; cbEffOp=%u\n' % (cbEffOp,));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync oOp2Range = range(oGen.oTarget.getGRegCount(cbEffOp));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if oGen.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync oOp2Range = [iLongOp2,];
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync for iOp2 in oOp2Range:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if iOp2 == X86_GREG_xSP:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync continue; # Cannot test xSP atm.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if iOp2 == X86_GREG_xAX or (cbEffOp > 1 and iOp2 == X86_GREG_xDX):
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync continue; # Will overflow or be too complicated to get right.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if cbEffOp == 1 and iOp2 == (16 if oGen.oTarget.is64Bit() else 4):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync continue; # Avoid dividing by AH, same reasons as above.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync for iDividend, iDivisor in self.generateInputsNoXcpt(cbEffOp, iOp2 == iLongOp2):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oGen.newSubTest();
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if cbEffOp > 1:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.generateOneStdTestGreg(oGen, cbEffOp, iOp2, iDividend, iDivisor);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync else:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.generateOneStdTestGreg8Bit(oGen, cbEffOp, iOp2, iDividend, iDivisor);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ## Memory test.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync #if False:
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync # for cAddrBits in oGen.oTarget.getAddrModes():
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # for cbEffOp in self.acbOpVars:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # if cbEffOp > cbMaxOp:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # continue;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync #
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # auInputs = auLongInputs if oGen.iModReg == iLongOp1 else auShortInputs;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync # for _ in oGen.oModRmRange:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # oGen.iModRm = (oGen.iModRm + 1) % oGen.oTarget.getGRegCount(cAddrBits * 8);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # if oGen.iModRm != 4 or cAddrBits == 16:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # for uInput in auInputs:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # oGen.newSubTest();
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # if oGen.iModReg == oGen.iModRm and oGen.iModRm != 5 and oGen.iModRm != 13 and cbEffOp != cbMaxOp:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # continue; # Don't know the high bit of the address ending up the result - skip it for now.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # uResult = self.fnCalcResult(cbEffOp, uInput, oGen.auRegValues[oGen.iModReg & 15], oGen);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # self.generateOneStdTestGregMemNoSib(oGen, cAddrBits, cbEffOp, cbMaxOp,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # oGen.iModReg, oGen.iModRm, uInput, uResult);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # else:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # # SIB - currently only short list of inputs or things may get seriously out of hand.
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync # self.generateStdTestGregMemSib(oGen, cAddrBits, cbEffOp, cbMaxOp, oGen.iModReg, auShortInputs);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync #
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync return True;
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync def generateTest(self, oGen, sTestFnName):
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync oGen.write('VBINSTST_BEGINPROC %s\n' % (sTestFnName,));
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync #oGen.write(' int3\n');
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self.generateStandardTests(oGen);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync #oGen.write(' int3\n');
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync oGen.write(' ret\n');
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync oGen.write('VBINSTST_ENDPROC %s\n' % (sTestFnName,));
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync return True;
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync##
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# Instruction Tests.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncg_aoInstructionTests = [
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync InstrTest_Mov_Gv_Ev(),
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync #InstrTest_MovSxD_Gv_Ev(),
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync InstrTest_DivIDiv(fIsIDiv = False),
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync InstrTest_DivIDiv(fIsIDiv = True),
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncclass InstructionTestGen(object): # pylint: disable=R0902
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync Instruction Test Generator.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ## @name Test size
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ## @{
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ksTestSize_Large = 'large';
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ksTestSize_Medium = 'medium';
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ksTestSize_Tiny = 'tiny';
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ## @}
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync kasTestSizes = ( ksTestSize_Large, ksTestSize_Medium, ksTestSize_Tiny );
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync def __init__(self, oOptions):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.oOptions = oOptions;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.oTarget = g_dTargetEnvs[oOptions.sTargetEnv];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # Calculate the number of output files.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.cFiles = 1;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if len(g_aoInstructionTests) > self.oOptions.cInstrPerFile:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.cFiles = len(g_aoInstructionTests) / self.oOptions.cInstrPerFile;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if self.cFiles * self.oOptions.cInstrPerFile < len(g_aoInstructionTests):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.cFiles += 1;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # Fix the known register values.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.au64Regs = randUxxList(64, 16);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.au32Regs = [(self.au64Regs[i] & UINT32_MAX) for i in range(8)];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.au16Regs = [(self.au64Regs[i] & UINT16_MAX) for i in range(8)];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.auRegValues = self.au64Regs if self.oTarget.is64Bit() else self.au32Regs;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # Declare state variables used while generating.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.oFile = sys.stderr;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.iFile = -1;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.sFile = '';
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self._dCheckFns = dict();
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self._dMemSetupFns = dict();
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self._d64BitConsts = dict();
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # State variables used while generating test convenientely placed here (lazy bird)...
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.iModReg = 0;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.iModRm = 0;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.iSibBaseReg = 0;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.iSibIndexReg = 0;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.iSibScale = 1;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if self.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self._oModRegRange = range(2);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self._oModRegRange8 = range(2);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.oModRmRange = range(2);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.cSibBasePerRun = 1;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self._cSibIndexPerRun = 2;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.oSibScaleRange = range(1);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync elif self.oOptions.sTestSize == InstructionTestGen.ksTestSize_Medium:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self._oModRegRange = range( 5 if self.oTarget.is64Bit() else 4);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self._oModRegRange8 = range( 6 if self.oTarget.is64Bit() else 4);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self.oModRmRange = range(5);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self.cSibBasePerRun = 5;
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self._cSibIndexPerRun = 4
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self.oSibScaleRange = range(2);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync else:
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self._oModRegRange = range(16 if self.oTarget.is64Bit() else 8);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self._oModRegRange8 = range(20 if self.oTarget.is64Bit() else 8);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self.oModRmRange = range(16 if self.oTarget.is64Bit() else 8);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self.cSibBasePerRun = 8;
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self._cSibIndexPerRun = 9;
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self.oSibScaleRange = range(4);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self.iSibIndexRange = 0;
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync #
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync # Methods used by instruction tests.
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync #
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync def write(self, sText):
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync """ Writes to the current output file. """
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync return self.oFile.write(unicode(sText));
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync def writeln(self, sText):
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync """ Writes a line to the current output file. """
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self.write(sText);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync return self.write('\n');
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync def writeInstrBytes(self, abInstr):
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync """
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync Emits an instruction given as a sequence of bytes values.
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync """
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self.write(' db %#04x' % (abInstr[0],));
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync for i in range(1, len(abInstr)):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write(', %#04x' % (abInstr[i],));
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return self.write('\n');
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync def newSubTest(self):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync Indicates that a new subtest has started.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write(' mov dword [VBINSTST_NAME(g_uVBInsTstSubTestIndicator) xWrtRIP], __LINE__\n');
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return True;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync def needGRegChecker(self, iReg1, iReg2 = None, iReg3 = None):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync Records the need for a given register checker function, returning its label.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if iReg2 is not None:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if iReg3 is not None:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync sName = '%s_%s_%s' % (self.oTarget.asGRegs[iReg1], self.oTarget.asGRegs[iReg2], self.oTarget.asGRegs[iReg3],);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync else:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync sName = '%s_%s' % (self.oTarget.asGRegs[iReg1], self.oTarget.asGRegs[iReg2],);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync else:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync sName = '%s' % (self.oTarget.asGRegs[iReg1],);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync assert iReg3 is None;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if sName in self._dCheckFns:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self._dCheckFns[sName] += 1;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync else:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self._dCheckFns[sName] = 1;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return 'Common_Check_' + sName;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync def needGRegMemSetup(self, cAddrBits, cbEffOp, iBaseReg = None, offDisp = None, iIndexReg = None, iScale = 1):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync Records the need for a given register checker function, returning its label.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync assert cAddrBits in [64, 32, 16];
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync assert cbEffOp in [8, 4, 2, 1];
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync assert iScale in [1, 2, 4, 8];
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync sName = '%ubit_U%u' % (cAddrBits, cbEffOp * 8,);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if iBaseReg is not None:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync sName += '_%s' % (gregName(iBaseReg, cAddrBits),);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync sName += '_x%u' % (iScale,);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if iIndexReg is not None:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync sName += '_%s' % (gregName(iIndexReg, cAddrBits),);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if offDisp is not None:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync sName += '_%#010x' % (offDisp & UINT32_MAX, );
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if sName in self._dMemSetupFns:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self._dMemSetupFns[sName] += 1;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync else:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self._dMemSetupFns[sName] = 1;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync return 'Common_MemSetup_' + sName;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync def need64BitConstant(self, uVal):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync Records the need for a 64-bit constant, returning its label.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync These constants are pooled to attempt reduce the size of the whole thing.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync assert uVal >= 0 and uVal <= UINT64_MAX;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if uVal in self._d64BitConsts:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self._d64BitConsts[uVal] += 1;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync else:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self._d64BitConsts[uVal] = 1;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return 'g_u64Const_0x%016x' % (uVal, );
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync def pushConst(self, uResult):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync Emits a push constant value, taking care of high values on 64-bit hosts.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if self.oTarget.is64Bit() and uResult >= 0x80000000:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write(' push qword [%s wrt rip]\n' % (self.need64BitConstant(uResult),));
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync else:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write(' push dword 0x%x\n' % (uResult,));
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return True;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync def getDispForMod(self, iMod, cbAlignment = 1):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync Get a set of address dispositions for a given addressing mode.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync The alignment restriction is for SIB scaling.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync assert cbAlignment in [1, 2, 4, 8];
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if iMod == 0:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync aoffDisp = [ None, ];
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync elif iMod == 1:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync aoffDisp = [ 127 & ~(cbAlignment - 1), -128 ];
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync elif iMod == 2:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync aoffDisp = [ 2147483647 & ~(cbAlignment - 1), -2147483648 ];
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync else: assert False;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return aoffDisp;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync def getModRegRange(self, cbEffOp):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync The Mod R/M register range varies with the effective operand size, for
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync 8-bit registers we have 4 more.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if cbEffOp == 1:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return self._oModRegRange8;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return self._oModRegRange;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync def getSibIndexPerRun(self):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync We vary the SIB index test range a little to try cover more operand
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync combinations and avoid repeating the same ones.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.iSibIndexRange += 1;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.iSibIndexRange %= 3;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if self.iSibIndexRange == 0:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return self._cSibIndexPerRun - 1;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return self._cSibIndexPerRun;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync #
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync # Internal machinery.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync #
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync def _randInitIndexes(self):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync Initializes the Mod R/M and SIB state index with random numbers prior
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync to generating a test.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync Note! As with all other randomness and variations we do, we cannot
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync test all combinations for each and every instruction so we try
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync get coverage over time.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.iModReg = randU8();
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.iModRm = randU8();
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.iSibBaseReg = randU8();
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.iSibIndexReg = randU8();
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.iSibScale = 1 << (randU8() & 3);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.iSibIndexRange = randU8();
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return True;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync def _calcTestFunctionName(self, oInstrTest, iInstrTest):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync Calc a test function name for the given instruction test.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync sName = 'TestInstr%03u_%s' % (iInstrTest, oInstrTest.sName);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return sName.replace(',', '_').replace(' ', '_').replace('%', '_');
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync def _generateFileHeader(self, ):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync Writes the file header.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync Raises exception on trouble.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write('; $Id$\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ';; @file %s\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync '; Autogenerate by %s %s. DO NOT EDIT\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ';\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync '\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ';\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync '; Headers\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ';\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync '%%include "env-%s.mac"\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync % ( os.path.basename(self.sFile),
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync os.path.basename(__file__), __version__[11:-1],
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.oTarget.sName,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ) );
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync # Target environment specific init stuff.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync #
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync # Global variables.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync #
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write('\n\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ';\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync '; Globals\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ';\n');
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write('VBINSTST_BEGINDATA\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync 'VBINSTST_GLOBALNAME_EX g_pvLow16Mem4K, data hidden\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' dq 0\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync 'VBINSTST_GLOBALNAME_EX g_pvLow32Mem4K, data hidden\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' dq 0\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync 'VBINSTST_GLOBALNAME_EX g_pvMem4K, data hidden\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' dq 0\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync 'VBINSTST_GLOBALNAME_EX g_uVBInsTstSubTestIndicator, data hidden\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' dd 0\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync 'VBINSTST_BEGINCODE\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync );
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write('%ifdef RT_ARCH_AMD64\n');
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync for i in range(len(g_asGRegs64)):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write('g_u64KnownValue_%s: dq 0x%x\n' % (g_asGRegs64[i], self.au64Regs[i]));
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write('%endif\n\n')
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync #
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync # Common functions.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync #
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync # Loading common values.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write('\n\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync 'VBINSTST_BEGINPROC Common_LoadKnownValues\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync '%ifdef RT_ARCH_AMD64\n');
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync for i in range(len(g_asGRegs64NoSp)):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if g_asGRegs64NoSp[i]:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write(' mov %s, 0x%x\n' % (g_asGRegs64NoSp[i], self.au64Regs[i],));
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write('%else\n');
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync for i in range(8):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if g_asGRegs32NoSp[i]:
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync self.write(' mov %s, 0x%x\n' % (g_asGRegs32NoSp[i], self.au32Regs[i],));
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write('%endif\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' ret\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync 'VBINSTST_ENDPROC Common_LoadKnownValues\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync '\n');
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write('VBINSTST_BEGINPROC Common_CheckKnownValues\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync '%ifdef RT_ARCH_AMD64\n');
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync for i in range(len(g_asGRegs64NoSp)):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if g_asGRegs64NoSp[i]:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write(' cmp %s, [g_u64KnownValue_%s wrt rip]\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' je .ok_%u\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' push %u ; register number\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' push %s ; actual\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' push qword [g_u64KnownValue_%s wrt rip] ; expected\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' call VBINSTST_NAME(Common_BadValue)\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync '.ok_%u:\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync % ( g_asGRegs64NoSp[i], g_asGRegs64NoSp[i], i, i, g_asGRegs64NoSp[i], g_asGRegs64NoSp[i], i,));
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write('%else\n');
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync for i in range(8):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if g_asGRegs32NoSp[i]:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write(' cmp %s, 0x%x\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' je .ok_%u\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' push %u ; register number\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' push %s ; actual\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' push dword 0x%x ; expected\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' call VBINSTST_NAME(Common_BadValue)\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync '.ok_%u:\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync % ( g_asGRegs32NoSp[i], self.au32Regs[i], i, i, g_asGRegs32NoSp[i], self.au32Regs[i], i,));
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write('%endif\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' ret\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync 'VBINSTST_ENDPROC Common_CheckKnownValues\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync '\n');
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return True;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync def _generateMemSetupFunctions(self): # pylint: disable=R0915
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync Generates the memory setup functions.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync """
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync cDefAddrBits = self.oTarget.getDefAddrBits();
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync for sName in self._dMemSetupFns:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync # Unpack it.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync asParams = sName.split('_');
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync cAddrBits = int(asParams[0][:-3]); assert asParams[0][-3:] == 'bit';
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync cEffOpBits = int(asParams[1][1:]); assert asParams[1][0] == 'U';
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if cAddrBits == 64: asAddrGRegs = g_asGRegs64;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync elif cAddrBits == 32: asAddrGRegs = g_asGRegs32;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync else: asAddrGRegs = g_asGRegs16;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync i = 2;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync iBaseReg = None;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync sBaseReg = None;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if i < len(asParams) and asParams[i] in asAddrGRegs:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync sBaseReg = asParams[i];
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync iBaseReg = asAddrGRegs.index(sBaseReg);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync i += 1
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync assert i < len(asParams); assert asParams[i][0] == 'x';
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync iScale = iScale = int(asParams[i][1:]); assert iScale in [1, 2, 4, 8], '%u %s' % (iScale, sName);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync i += 1;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync sIndexReg = None;
8f7ee9e453c60b3b699799538a45950b35266665vboxsync iIndexReg = None;
8f7ee9e453c60b3b699799538a45950b35266665vboxsync if i < len(asParams) and asParams[i] in asAddrGRegs:
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync sIndexReg = asParams[i];
8f7ee9e453c60b3b699799538a45950b35266665vboxsync iIndexReg = asAddrGRegs.index(sIndexReg);
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync i += 1;
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync u32Disp = None;
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync if i < len(asParams) and len(asParams[i]) == 10:
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync u32Disp = long(asParams[i], 16);
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync i += 1;
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync assert i == len(asParams), 'i=%d len=%d len[i]=%d (%s)' % (i, len(asParams), len(asParams[i]), asParams[i],);
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync assert iScale == 1 or iIndexReg is not None;
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync # Find a temporary register.
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync iTmpReg1 = X86_GREG_xCX;
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync while iTmpReg1 in [iBaseReg, iIndexReg]:
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync iTmpReg1 += 1;
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync # Prologue.
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync self.write('\n\n'
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync '; cAddrBits=%s cEffOpBits=%s iBaseReg=%s u32Disp=%s iIndexReg=%s iScale=%s\n'
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync 'VBINSTST_BEGINPROC Common_MemSetup_%s\n'
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync ' MY_PUSH_FLAGS\n'
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync ' push %s\n'
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync % ( cAddrBits, cEffOpBits, iBaseReg, u32Disp, iIndexReg, iScale,
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync sName, self.oTarget.asGRegs[iTmpReg1], ));
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync # Figure out what to use.
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync if cEffOpBits == 64:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync sTmpReg1 = g_asGRegs64[iTmpReg1];
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync sDataVar = 'VBINSTST_NAME(g_u64Data)';
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync elif cEffOpBits == 32:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync sTmpReg1 = g_asGRegs32[iTmpReg1];
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync sDataVar = 'VBINSTST_NAME(g_u32Data)';
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync elif cEffOpBits == 16:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync sTmpReg1 = g_asGRegs16[iTmpReg1];
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync sDataVar = 'VBINSTST_NAME(g_u16Data)';
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync else:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync assert cEffOpBits == 8; assert iTmpReg1 < 4;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync sTmpReg1 = g_asGRegs8Rex[iTmpReg1];
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync sDataVar = 'VBINSTST_NAME(g_u8Data)';
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync # Special case: reg + reg * [2,4,8]
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if iBaseReg == iIndexReg and iBaseReg is not None and iScale != 1:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync iTmpReg2 = X86_GREG_xBP;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync while iTmpReg2 in [iBaseReg, iIndexReg, iTmpReg1]:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync iTmpReg2 += 1;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync sTmpReg2 = gregName(iTmpReg2, cAddrBits);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write(' push sAX\n'
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync ' push %s\n'
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync ' push sDX\n'
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync % (self.oTarget.asGRegs[iTmpReg2],));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if cAddrBits == 16:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write(' mov %s, [VBINSTST_NAME(g_pvLow16Mem4K) xWrtRIP]\n' % (sTmpReg2,));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync else:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write(' mov %s, [VBINSTST_NAME(g_pvLow32Mem4K) xWrtRIP]\n' % (sTmpReg2,));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write(' add %s, 0x200\n' % (sTmpReg2,));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync self.write(' mov %s, %s\n' % (gregName(X86_GREG_xAX, cAddrBits), sTmpReg2,));
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync if u32Disp is not None:
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync self.write(' sub %s, %d\n' % ( gregName(X86_GREG_xAX, cAddrBits), convU32ToSigned(u32Disp), ));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write(' xor edx, edx\n'
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync '%if xCB == 2\n'
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync ' push 0\n'
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync '%endif\n');
8f7ee9e453c60b3b699799538a45950b35266665vboxsync self.write(' push %u\n' % (iScale + 1,));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write(' div %s [xSP]\n' % ('qword' if cAddrBits == 64 else 'dword',));
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write(' sub %s, %s\n' % (sTmpReg2, gregName(X86_GREG_xDX, cAddrBits),));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write(' pop sDX\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' pop sDX\n'); # sTmpReg2 is eff address; sAX is sIndexReg value.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync # Note! sTmpReg1 can be xDX and that's no problem now.
0c94a8282c9042b02f022302a3d987746140eab9vboxsync self.write(' mov %s, [xSP + sCB*3 + MY_PUSH_FLAGS_SIZE + xCB]\n' % (sTmpReg1,));
0c94a8282c9042b02f022302a3d987746140eab9vboxsync self.write(' mov [%s], %s\n' % (sTmpReg2, sTmpReg1,)); # Value in place.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write(' pop %s\n' % (self.oTarget.asGRegs[iTmpReg2],));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if iBaseReg == X86_GREG_xAX:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write(' pop %s\n' % (self.oTarget.asGRegs[iTmpReg1],));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync else:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write(' mov %s, %s\n' % (sBaseReg, gregName(X86_GREG_xAX, cAddrBits),));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write(' pop sAX\n');
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync else:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync # Load the value and mem address, storing the value there.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync # Note! ASSUMES that the scale and disposition works fine together.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync sAddrReg = sBaseReg if sBaseReg is not None else sIndexReg;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write(' mov %s, [xSP + sCB + MY_PUSH_FLAGS_SIZE + xCB]\n' % (sTmpReg1,));
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if cAddrBits >= cDefAddrBits:
9c9db71d639cf066ed41d49629d46d48bff4be2fvboxsync self.write(' mov [%s xWrtRIP], %s\n' % (sDataVar, sTmpReg1,));
9c9db71d639cf066ed41d49629d46d48bff4be2fvboxsync self.write(' lea %s, [%s xWrtRIP]\n' % (sAddrReg, sDataVar,));
0c94a8282c9042b02f022302a3d987746140eab9vboxsync else:
0c94a8282c9042b02f022302a3d987746140eab9vboxsync if cAddrBits == 16:
0c94a8282c9042b02f022302a3d987746140eab9vboxsync self.write(' mov %s, [VBINSTST_NAME(g_pvLow16Mem4K) xWrtRIP]\n' % (sAddrReg,));
0c94a8282c9042b02f022302a3d987746140eab9vboxsync else:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write(' mov %s, [VBINSTST_NAME(g_pvLow32Mem4K) xWrtRIP]\n' % (sAddrReg,));
0c94a8282c9042b02f022302a3d987746140eab9vboxsync self.write(' add %s, %s\n' % (sAddrReg, (randU16() << cEffOpBits) & 0xfff, ));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write(' mov [%s], %s\n' % (sAddrReg, sTmpReg1, ));
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync # Adjust for disposition and scaling.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if u32Disp is not None:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write(' sub %s, %d\n' % ( sAddrReg, convU32ToSigned(u32Disp), ));
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if iIndexReg is not None:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if iBaseReg == iIndexReg:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync assert iScale == 1;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync assert u32Disp is None or (u32Disp & 1) == 0;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write(' shr %s, 1\n' % (sIndexReg,));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync elif sBaseReg is not None:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync uIdxRegVal = randUxx(cAddrBits);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if cAddrBits == 64:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write(' mov %s, %u\n'
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync ' sub %s, %s\n'
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync ' mov %s, %u\n'
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync % ( sIndexReg, (uIdxRegVal * iScale) & UINT64_MAX,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync sBaseReg, sIndexReg,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync sIndexReg, uIdxRegVal, ));
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync else:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync assert cAddrBits == 32;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write(' mov %s, %u\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' sub %s, %#06x\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync % ( sIndexReg, uIdxRegVal, sBaseReg, (uIdxRegVal * iScale) & UINT32_MAX, ));
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync elif iScale == 2:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync assert u32Disp is None or (u32Disp & 1) == 0;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync self.write(' shr %s, 1\n' % (sIndexReg,));
0c94a8282c9042b02f022302a3d987746140eab9vboxsync elif iScale == 4:
0c94a8282c9042b02f022302a3d987746140eab9vboxsync assert u32Disp is None or (u32Disp & 3) == 0;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync self.write(' shr %s, 2\n' % (sIndexReg,));
0c94a8282c9042b02f022302a3d987746140eab9vboxsync elif iScale == 8:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync assert u32Disp is None or (u32Disp & 7) == 0;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write(' shr %s, 3\n' % (sIndexReg,));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync else:
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync assert iScale == 1;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync # Set upper bits that's supposed to be unused.
0c94a8282c9042b02f022302a3d987746140eab9vboxsync if cDefAddrBits > cAddrBits or cAddrBits == 16:
0c94a8282c9042b02f022302a3d987746140eab9vboxsync if cDefAddrBits == 64:
0c94a8282c9042b02f022302a3d987746140eab9vboxsync assert cAddrBits == 32;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync if iBaseReg is not None:
0c94a8282c9042b02f022302a3d987746140eab9vboxsync self.write(' mov %s, %#018x\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' or %s, %s\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync % ( g_asGRegs64[iTmpReg1], randU64() & 0xffffffff00000000,
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync g_asGRegs64[iBaseReg], g_asGRegs64[iTmpReg1],));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if iIndexReg is not None and iIndexReg != iBaseReg:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write(' mov %s, %#018x\n'
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync ' or %s, %s\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync % ( g_asGRegs64[iTmpReg1], randU64() & 0xffffffff00000000,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync g_asGRegs64[iIndexReg], g_asGRegs64[iTmpReg1],));
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync else:
0c94a8282c9042b02f022302a3d987746140eab9vboxsync assert cDefAddrBits == 32; assert cAddrBits == 16; assert iIndexReg is None;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync if iBaseReg is not None:
0c94a8282c9042b02f022302a3d987746140eab9vboxsync self.write(' or %s, %#010x\n'
0c94a8282c9042b02f022302a3d987746140eab9vboxsync % ( g_asGRegs32[iBaseReg], randU32() & 0xffff0000, ));
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync # Epilogue.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write(' pop %s\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' MY_POP_FLAGS\n'
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync ' ret sCB\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync 'VBINSTST_ENDPROC Common_MemSetup_%s\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync % ( self.oTarget.asGRegs[iTmpReg1], sName,));
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync def _generateFileFooter(self):
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync """
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync Generates file footer.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync """
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync # Register checking functions.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync for sName in self._dCheckFns:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync asRegs = sName.split('_');
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync sPushSize = 'dword';
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # Prologue
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write('\n\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync '; Checks 1 or more register values, expected values pushed on the stack.\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync '; To save space, the callee cleans up the stack.'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync '; Ref count: %u\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync 'VBINSTST_BEGINPROC Common_Check_%s\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ' MY_PUSH_FLAGS\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync % ( self._dCheckFns[sName], sName, ) );
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # Register checks.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync for i in range(len(asRegs)):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync sReg = asRegs[i];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync iReg = self.oTarget.asGRegs.index(sReg);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync if i == asRegs.index(sReg): # Only check once, i.e. input = output reg.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.write(' cmp %s, [xSP + MY_PUSH_FLAGS_SIZE + xCB + sCB * %u]\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ' je .equal%u\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ' push %s %u ; register number\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ' push %s ; actual\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ' mov %s, [xSP + sCB*2 + MY_PUSH_FLAGS_SIZE + xCB + sCB * %u]\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ' push %s ; expected\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ' call VBINSTST_NAME(Common_BadValue)\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync '.equal%u:\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync % ( sReg, i, i, sPushSize, iReg, sReg, sReg, i, sReg, i, ) );
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync # Restore known register values and check the other registers.
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync for sReg in asRegs:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if self.oTarget.is64Bit():
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync self.write(' mov %s, [g_u64KnownValue_%s wrt rip]\n' % (sReg, sReg,));
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync else:
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync iReg = self.oTarget.asGRegs.index(sReg)
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync self.write(' mov %s, 0x%x\n' % (sReg, self.au32Regs[iReg],));
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self.write(' MY_POP_FLAGS\n'
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync ' call VBINSTST_NAME(Common_CheckKnownValues)\n'
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync ' ret sCB*%u\n'
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync 'VBINSTST_ENDPROC Common_Check_%s\n'
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync % (len(asRegs), sName,));
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync # memory setup functions
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self._generateMemSetupFunctions();
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync # 64-bit constants.
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync if len(self._d64BitConsts) > 0:
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self.write('\n\n'
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync ';\n'
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync '; 64-bit constants\n'
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync ';\n');
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync for uVal in self._d64BitConsts:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.write('g_u64Const_0x%016x: dq 0x%016x ; Ref count: %d\n' % (uVal, uVal, self._d64BitConsts[uVal], ) );
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync return True;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync def _generateTests(self):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync Generate the test cases.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync """
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync for self.iFile in range(self.cFiles):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if self.cFiles == 1:
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self.sFile = '%s.asm' % (self.oOptions.sOutputBase,)
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync else:
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.sFile = '%s-%u.asm' % (self.oOptions.sOutputBase, self.iFile)
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync self.oFile = sys.stdout;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if self.oOptions.sOutputBase != '-':
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync self.oFile = io.open(self.sFile, 'w', buffering = 65536, encoding = 'utf-8');
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self._generateFileHeader();
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # Calc the range.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync iInstrTestStart = self.iFile * self.oOptions.cInstrPerFile;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync iInstrTestEnd = iInstrTestStart + self.oOptions.cInstrPerFile;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if iInstrTestEnd > len(g_aoInstructionTests):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync iInstrTestEnd = len(g_aoInstructionTests);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # Generate the instruction tests.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync for iInstrTest in range(iInstrTestStart, iInstrTestEnd):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oInstrTest = g_aoInstructionTests[iInstrTest];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.write('\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync '\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ';\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync '; %s\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ';\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync % (oInstrTest.sName,));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self._randInitIndexes();
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oInstrTest.generateTest(self, self._calcTestFunctionName(oInstrTest, iInstrTest));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # Generate the main function.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.write('\n\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync 'VBINSTST_BEGINPROC TestInstrMain\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ' MY_PUSH_ALL\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ' sub xSP, 40h\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync '\n');
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync for iInstrTest in range(iInstrTestStart, iInstrTestEnd):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oInstrTest = g_aoInstructionTests[iInstrTest];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if oInstrTest.isApplicable(self):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.write('%%ifdef ASM_CALL64_GCC\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ' lea rdi, [.szInstr%03u wrt rip]\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync '%%elifdef ASM_CALL64_MSC\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ' lea rcx, [.szInstr%03u wrt rip]\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync '%%else\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ' mov xAX, .szInstr%03u\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ' mov [xSP], xAX\n'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync '%%endif\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' VBINSTST_CALL_FN_SUB_TEST\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' call VBINSTST_NAME(%s)\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync % ( iInstrTest, iInstrTest, iInstrTest, self._calcTestFunctionName(oInstrTest, iInstrTest)));
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write('\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' add xSP, 40h\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' MY_POP_ALL\n'
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync ' ret\n\n');
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync for iInstrTest in range(iInstrTestStart, iInstrTestEnd):
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync self.write('.szInstr%03u: db \'%s\', 0\n' % (iInstrTest, g_aoInstructionTests[iInstrTest].sName,));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.write('VBINSTST_ENDPROC TestInstrMain\n\n');
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self._generateFileFooter();
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if self.oOptions.sOutputBase != '-':
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.oFile.close();
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.oFile = None;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync self.sFile = '';
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return RTEXITCODE_SUCCESS;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync def _runMakefileMode(self):
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync Generate a list of output files on standard output.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if self.cFiles == 1:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync print('%s.asm' % (self.oOptions.sOutputBase,));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync else:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync print(' '.join('%s-%s.asm' % (self.oOptions.sOutputBase, i) for i in range(self.cFiles)));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return RTEXITCODE_SUCCESS;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync def run(self):
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync Generates the tests or whatever is required.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if self.oOptions.fMakefileMode:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return self._runMakefileMode();
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync sys.stderr.write('InstructionTestGen.py: Seed = %s\n' % (g_iMyRandSeed,));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return self._generateTests();
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync @staticmethod
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync def main():
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync """
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync Main function a la C/C++. Returns exit code.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync """
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync #
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync # Parse the command line.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync #
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oParser = OptionParser(version = __version__[11:-1].strip());
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oParser.add_option('--makefile-mode', dest = 'fMakefileMode', action = 'store_true', default = False,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync help = 'Special mode for use to output a list of output files for the benefit of '
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync 'the make program (kmk).');
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync oParser.add_option('--split', dest = 'cInstrPerFile', metavar = '<instr-per-file>', type = 'int', default = 9999999,
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync help = 'Number of instruction to test per output file.');
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oParser.add_option('--output-base', dest = 'sOutputBase', metavar = '<file>', default = None,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync help = 'The output file base name, no suffix please. Required.');
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oParser.add_option('--target', dest = 'sTargetEnv', metavar = '<target>',
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync default = 'iprt-r3-32',
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync choices = g_dTargetEnvs.keys(),
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync help = 'The target environment. Choices: %s'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync % (', '.join(sorted(g_dTargetEnvs.keys())),));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oParser.add_option('--test-size', dest = 'sTestSize', default = InstructionTestGen.ksTestSize_Medium,
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync choices = InstructionTestGen.kasTestSizes,
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync help = 'Selects the test size.');
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync (oOptions, asArgs) = oParser.parse_args();
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync if len(asArgs) > 0:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync oParser.print_help();
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return RTEXITCODE_SYNTAX
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync if oOptions.sOutputBase is None:
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync print('syntax error: Missing required option --output-base.', file = sys.stderr);
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync return RTEXITCODE_SYNTAX
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync #
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync # Instantiate the program class and run it.
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync #
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync oProgram = InstructionTestGen(oOptions);
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync return oProgram.run();
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncif __name__ == '__main__':
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync sys.exit(InstructionTestGen.main());
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync