917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#!/usr/bin/env python
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync# -*- coding: utf-8 -*-
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync# $Id$
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync"""
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncInstruction Test Generator.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync"""
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncfrom __future__ import print_function;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync__copyright__ = \
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync"""
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncCopyright (C) 2012-2013 Oracle Corporation
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
01bceecc7f7484a8820c77b884bb91cdefc97390vboxsyncThis file is part of VirtualBox Open Source Edition (OSE), as
01bceecc7f7484a8820c77b884bb91cdefc97390vboxsyncavailable from http://www.virtualbox.org. This file is free software;
01bceecc7f7484a8820c77b884bb91cdefc97390vboxsyncyou can redistribute it and/or modify it under the terms of the GNU
01bceecc7f7484a8820c77b884bb91cdefc97390vboxsyncGeneral Public License (GPL) as published by the Free Software
01bceecc7f7484a8820c77b884bb91cdefc97390vboxsyncFoundation, in version 2 as it comes in the "COPYING" file of the
01bceecc7f7484a8820c77b884bb91cdefc97390vboxsyncVirtualBox OSE distribution. VirtualBox OSE is distributed in the
01bceecc7f7484a8820c77b884bb91cdefc97390vboxsynchope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync"""
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync__version__ = "$Revision$";
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync# pylint: disable=C0103,R0913
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync# Standard python imports.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncimport io;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncimport os;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncfrom optparse import OptionParser
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncimport random;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncimport sys;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @name Exit codes
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @{
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncRTEXITCODE_SUCCESS = 0;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncRTEXITCODE_SYNTAX = 2;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @name Various C macros we're used to.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @{
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncUINT8_MAX = 0xff
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncUINT16_MAX = 0xffff
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncUINT32_MAX = 0xffffffff
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncUINT64_MAX = 0xffffffffffffffff
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncdef RT_BIT_32(iBit): # pylint: disable=C0103
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ 32-bit one bit mask. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return 1 << iBit;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncdef RT_BIT_64(iBit): # pylint: disable=C0103
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ 64-bit one bit mask. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return 1 << iBit;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @name ModR/M
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @{
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_MODRM_RM_MASK = 0x07;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_MODRM_REG_MASK = 0x38;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_MODRM_REG_SMASK = 0x07;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_MODRM_REG_SHIFT = 3;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_MODRM_MOD_MASK = 0xc0;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_MODRM_MOD_SMASK = 0x03;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_MODRM_MOD_SHIFT = 6;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @name SIB
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @{
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_SIB_BASE_MASK = 0x07;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_SIB_INDEX_MASK = 0x38;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_SIB_INDEX_SMASK = 0x07;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_SIB_INDEX_SHIFT = 3;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_SIB_SCALE_MASK = 0xc0;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_SIB_SCALE_SMASK = 0x03;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_SIB_SCALE_SHIFT = 6;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync## @name Prefixes
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_OP_PRF_CS = 0x2e;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_OP_PRF_SS = 0x36;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_OP_PRF_DS = 0x3e;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_OP_PRF_ES = 0x26;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_OP_PRF_FS = 0x64;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_OP_PRF_GS = 0x65;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_OP_PRF_SIZE_OP = 0x66;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_OP_PRF_SIZE_ADDR = 0x67;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_OP_PRF_LOCK = 0xf0;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_OP_PRF_REPZ = 0xf2;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_OP_PRF_REPNZ = 0xf3;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_OP_REX_B = 0x41;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_OP_REX_X = 0x42;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_OP_REX_R = 0x44;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncX86_OP_REX_W = 0x48;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync## @name General registers
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync## @
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncX86_GREG_xAX = 0
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncX86_GREG_xCX = 1
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncX86_GREG_xDX = 2
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncX86_GREG_xBX = 3
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncX86_GREG_xSP = 4
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncX86_GREG_xBP = 5
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncX86_GREG_xSI = 6
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncX86_GREG_xDI = 7
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncX86_GREG_x8 = 8
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncX86_GREG_x9 = 9
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncX86_GREG_x10 = 10
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncX86_GREG_x11 = 11
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncX86_GREG_x12 = 12
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncX86_GREG_x13 = 13
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncX86_GREG_x14 = 14
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncX86_GREG_x15 = 15
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync## @}
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @name Register names.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @{
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncg_asGRegs64NoSp = ('rax', 'rcx', 'rdx', 'rbx', None, 'rbp', 'rsi', 'rdi', 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncg_asGRegs64 = ('rax', 'rcx', 'rdx', 'rbx', 'rsp', 'rbp', 'rsi', 'rdi', 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncg_asGRegs32NoSp = ('eax', 'ecx', 'edx', 'ebx', None, 'ebp', 'esi', 'edi',
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync 'r8d', 'r9d', 'r10d', 'r11d', 'r12d', 'r13d', 'r14d', 'r15d');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncg_asGRegs32 = ('eax', 'ecx', 'edx', 'ebx', 'esp', 'ebp', 'esi', 'edi',
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync 'r8d', 'r9d', 'r10d', 'r11d', 'r12d', 'r13d', 'r14d', 'r15d');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncg_asGRegs16NoSp = ('ax', 'cx', 'dx', 'bx', None, 'bp', 'si', 'di',
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync 'r8w', 'r9w', 'r10w', 'r11w', 'r12w', 'r13w', 'r14w', 'r15w');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncg_asGRegs16 = ('ax', 'cx', 'dx', 'bx', 'sp', 'bp', 'si', 'di',
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync 'r8w', 'r9w', 'r10w', 'r11w', 'r12w', 'r13w', 'r14w', 'r15w');
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsyncg_asGRegs8 = ('al', 'cl', 'dl', 'bl', 'ah', 'ch', 'dh', 'bh');
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsyncg_asGRegs8Rex = ('al', 'cl', 'dl', 'bl', 'spl', 'bpl', 'sil', 'dil',
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync 'r8b', 'r9b', 'r10b', 'r11b', 'r12b', 'r13b', 'r14b', 'r15b',
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync 'ah', 'ch', 'dh', 'bh');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync## @name EFLAGS/RFLAGS/EFLAGS
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync## @{
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_CF = RT_BIT_32(0);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_CF_BIT = 0;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_1 = RT_BIT_32(1);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_PF = RT_BIT_32(2);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_AF = RT_BIT_32(4);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_AF_BIT = 4;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_ZF = RT_BIT_32(6);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_ZF_BIT = 6;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_SF = RT_BIT_32(7);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_SF_BIT = 7;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_TF = RT_BIT_32(8);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_IF = RT_BIT_32(9);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_DF = RT_BIT_32(10);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_OF = RT_BIT_32(11);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_OF_BIT = 11;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_IOPL = (RT_BIT_32(12) | RT_BIT_32(13));
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_NT = RT_BIT_32(14);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_RF = RT_BIT_32(16);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_VM = RT_BIT_32(17);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_AC = RT_BIT_32(18);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_VIF = RT_BIT_32(19);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_VIP = RT_BIT_32(20);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_ID = RT_BIT_32(21);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_LIVE_MASK = 0x003f7fd5;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_RA1_MASK = RT_BIT_32(1);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_IOPL_SHIFT = 12;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncX86_EFL_STATUS_BITS = ( X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF );
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync## @}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @name Random
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @{
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsyncg_iMyRandSeed = int((os.urandom(4)).encode('hex'), 16);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync#g_iMyRandSeed = 286523426;
08fc4eb537ed24136b05660d0aa038b336516961vboxsync#g_iMyRandSeed = 1994382324;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsyncg_oMyRand = random.Random(g_iMyRandSeed);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync#g_oMyRand = random.SystemRandom();
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsyncdef randU8():
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync """ Unsigned 8-bit random number. """
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync return g_oMyRand.getrandbits(8);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncdef randU16():
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ Unsigned 16-bit random number. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return g_oMyRand.getrandbits(16);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncdef randU32():
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ Unsigned 32-bit random number. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return g_oMyRand.getrandbits(32);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncdef randU64():
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ Unsigned 64-bit random number. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return g_oMyRand.getrandbits(64);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncdef randUxx(cBits):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ Unsigned 8-, 16-, 32-, or 64-bit random number. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return g_oMyRand.getrandbits(cBits);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsyncdef randSxx(cBits):
54ed927d658674ced4387afbd1877a27cb975a76vboxsync """ Signed 8-, 16-, 32-, or 64-bit random number. """
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uVal = randUxx(cBits);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync iRet = uVal & ((1 << (cBits - 1)) - 1);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if iRet != uVal:
54ed927d658674ced4387afbd1877a27cb975a76vboxsync iRet = -iRet;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync return iRet;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncdef randUxxList(cBits, cElements):
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync """ List of unsigned 8-, 16-, 32-, or 64-bit random numbers. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return [randUxx(cBits) for _ in range(cElements)];
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @name Instruction Emitter Helpers
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @{
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncdef calcRexPrefixForTwoModRmRegs(iReg, iRm, bOtherRexPrefixes = 0):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Calculates a rex prefix if neccessary given the two registers
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync and optional rex size prefixes.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Returns an empty array if not necessary.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync bRex = bOtherRexPrefixes;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if iReg >= 8:
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync bRex |= X86_OP_REX_R;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if iRm >= 8:
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync bRex |= X86_OP_REX_B;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if bRex == 0:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return [];
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return [bRex,];
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncdef calcModRmForTwoRegs(iReg, iRm):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Calculate the RM byte for two registers.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Returns an array with one byte in it.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync bRm = (0x3 << X86_MODRM_MOD_SHIFT) \
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync | ((iReg << X86_MODRM_REG_SHIFT) & X86_MODRM_REG_MASK) \
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync | (iRm & X86_MODRM_RM_MASK);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return [bRm,];
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## @}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync## @name Misc
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync## @{
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsyncdef convU32ToSigned(u32):
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync """ Converts a 32-bit unsigned value to 32-bit signed. """
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync if u32 < 0x80000000:
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync return u32;
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync return u32 - UINT32_MAX - 1;
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncdef rotateLeftUxx(cBits, uVal, cShift):
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync """ Rotate a xx-bit wide unsigned number to the left. """
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync assert cShift < cBits;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if cBits == 16:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uMask = UINT16_MAX;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync elif cBits == 32:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uMask = UINT32_MAX;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync elif cBits == 64:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uMask = UINT64_MAX;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync else:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync assert cBits == 8;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uMask = UINT8_MAX;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uVal &= uMask;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uRet = (uVal << cShift) & uMask;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uRet |= (uVal >> (cBits - cShift));
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync return uRet;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsyncdef rotateRightUxx(cBits, uVal, cShift):
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync """ Rotate a xx-bit wide unsigned number to the right. """
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync assert cShift < cBits;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if cBits == 16:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uMask = UINT16_MAX;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync elif cBits == 32:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uMask = UINT32_MAX;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync elif cBits == 64:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uMask = UINT64_MAX;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync else:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync assert cBits == 8;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uMask = UINT8_MAX;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uVal &= uMask;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uRet = (uVal >> cShift);
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uRet |= (uVal << (cBits - cShift)) & uMask;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync return uRet;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsyncdef gregName(iReg, cBits, fRexByteRegs = True):
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync """ Gets the name of a general register by index and width. """
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync if cBits == 64:
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync return g_asGRegs64[iReg];
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync if cBits == 32:
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync return g_asGRegs32[iReg];
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync if cBits == 16:
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync return g_asGRegs16[iReg];
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync assert cBits == 8;
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync if fRexByteRegs:
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync return g_asGRegs8Rex[iReg];
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync return g_asGRegs8[iReg];
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync## @}
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncclass TargetEnv(object):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Target Runtime Environment.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ## @name CPU Modes
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ## @{
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ksCpuMode_Real = 'real';
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ksCpuMode_Protect = 'prot';
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ksCpuMode_Paged = 'paged';
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ksCpuMode_Long = 'long';
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ksCpuMode_V86 = 'v86';
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ## @}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ## @name Instruction set.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ## @{
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ksInstrSet_16 = '16';
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ksInstrSet_32 = '32';
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ksInstrSet_64 = '64';
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ## @}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def __init__(self, sName,
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync sInstrSet = ksInstrSet_32,
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync sCpuMode = ksCpuMode_Paged,
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync iRing = 3,
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.sName = sName;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.sInstrSet = sInstrSet;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.sCpuMode = sCpuMode;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.iRing = iRing;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.asGRegs = g_asGRegs64 if self.is64Bit() else g_asGRegs32;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.asGRegsNoSp = g_asGRegs64NoSp if self.is64Bit() else g_asGRegs32NoSp;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def isUsingIprt(self):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ Whether it's an IPRT environment or not. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return self.sName.startswith('iprt');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def is64Bit(self):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ Whether it's a 64-bit environment or not. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return self.sInstrSet == self.ksInstrSet_64;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def getDefOpBits(self):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ Get the default operand size as a bit count. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if self.sInstrSet == self.ksInstrSet_16:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return 16;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return 32;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def getDefOpBytes(self):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ Get the default operand size as a byte count. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return self.getDefOpBits() / 8;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def getMaxOpBits(self):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ Get the max operand size as a bit count. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if self.sInstrSet == self.ksInstrSet_64:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return 64;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return 32;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def getMaxOpBytes(self):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ Get the max operand size as a byte count. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return self.getMaxOpBits() / 8;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync def getDefAddrBits(self):
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync """ Get the default address size as a bit count. """
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync if self.sInstrSet == self.ksInstrSet_16:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync return 16;
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync if self.sInstrSet == self.ksInstrSet_32:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync return 32;
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync return 64;
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync def getDefAddrBytes(self):
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync """ Get the default address size as a byte count. """
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync return self.getDefAddrBits() / 8;
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync def getGRegCount(self, cbEffBytes = 4):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ Get the number of general registers. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if self.sInstrSet == self.ksInstrSet_64:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if cbEffBytes == 1:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync return 16 + 4;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return 16;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return 8;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
72e9ef1022a910facbd4a232500026befd944d95vboxsync def randGRegNoSp(self, cbEffBytes = 4):
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync """ Returns a random general register number, excluding the SP register. """
72e9ef1022a910facbd4a232500026befd944d95vboxsync iReg = randU16() % self.getGRegCount(cbEffBytes);
72e9ef1022a910facbd4a232500026befd944d95vboxsync while iReg == X86_GREG_xSP:
72e9ef1022a910facbd4a232500026befd944d95vboxsync iReg = randU16() % self.getGRegCount(cbEffBytes);
72e9ef1022a910facbd4a232500026befd944d95vboxsync return iReg;
72e9ef1022a910facbd4a232500026befd944d95vboxsync
72e9ef1022a910facbd4a232500026befd944d95vboxsync def randGRegNoSpList(self, cItems, cbEffBytes = 4):
72e9ef1022a910facbd4a232500026befd944d95vboxsync """ List of randGRegNoSp values. """
72e9ef1022a910facbd4a232500026befd944d95vboxsync aiRegs = [];
54ed927d658674ced4387afbd1877a27cb975a76vboxsync for _ in range(cItems):
72e9ef1022a910facbd4a232500026befd944d95vboxsync aiRegs.append(self.randGRegNoSp(cbEffBytes));
72e9ef1022a910facbd4a232500026befd944d95vboxsync return aiRegs;
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync
270236340676d2385b27ea992e07fcb643bb78b6vboxsync def getAddrModes(self):
270236340676d2385b27ea992e07fcb643bb78b6vboxsync """ Gets a list of addressing mode (16, 32, or/and 64). """
270236340676d2385b27ea992e07fcb643bb78b6vboxsync if self.sInstrSet == self.ksInstrSet_16:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync return [16, 32];
270236340676d2385b27ea992e07fcb643bb78b6vboxsync if self.sInstrSet == self.ksInstrSet_32:
270236340676d2385b27ea992e07fcb643bb78b6vboxsync return [32, 16];
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync return [64, 32];
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync def is8BitHighGReg(self, cbEffOp, iGReg):
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync """ Checks if the given register is a high 8-bit general register (AH, CH, DH or BH). """
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync assert cbEffOp in [1, 2, 4, 8];
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if cbEffOp == 1:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if iGReg >= 16:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync return True;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if iGReg >= 4 and not self.is64Bit():
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync return True;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync return False;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync def gregNameBits(self, iReg, cBits):
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync """ Gets the name of the given register for the specified width (bits). """
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync return gregName(iReg, cBits, self.is64Bit());
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync def gregNameBytes(self, iReg, cbWidth):
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync """ Gets the name of the given register for the specified with (in bytes). """
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync return gregName(iReg, cbWidth * 8, self.is64Bit());
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync## Target environments.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncg_dTargetEnvs = {
81a042b394e569219fd7bf5c66281e6afc2212a3vboxsync 'iprt-r3-32': TargetEnv('iprt-r3-32', TargetEnv.ksInstrSet_32, TargetEnv.ksCpuMode_Protect, 3),
81a042b394e569219fd7bf5c66281e6afc2212a3vboxsync 'iprt-r3-64': TargetEnv('iprt-r3-64', TargetEnv.ksInstrSet_64, TargetEnv.ksCpuMode_Long, 3),
81a042b394e569219fd7bf5c66281e6afc2212a3vboxsync 'bs2-r0-64': TargetEnv('bs2-r0-64', TargetEnv.ksInstrSet_64, TargetEnv.ksCpuMode_Long, 0),
81a042b394e569219fd7bf5c66281e6afc2212a3vboxsync 'bs2-r0-64-big': TargetEnv('bs2-r0-64-big', TargetEnv.ksInstrSet_64, TargetEnv.ksCpuMode_Long, 0),
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync 'bs2-r0-32-big': TargetEnv('bs2-r0-32-big', TargetEnv.ksInstrSet_32, TargetEnv.ksCpuMode_Protect, 0),
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync};
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsyncclass InstrTestBase(object):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Base class for testing one instruction.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def __init__(self, sName, sInstr = None):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.sName = sName;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.sInstr = sInstr if sInstr else sName.split()[0];
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync def isApplicable(self, oGen):
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync """
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync Tests if the instruction test is applicable to the selected environment.
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync """
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync _ = oGen;
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync return True;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def generateTest(self, oGen, sTestFnName):
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync """
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync Emits the test assembly code.
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync oGen.write(';; @todo not implemented. This is for the linter: %s, %s\n' % (oGen, sTestFnName));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return True;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync def generateInputs(self, cbEffOp, cbMaxOp, oGen, fLong = False):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ Generate a list of inputs. """
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if fLong:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync #
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync # Try do extremes as well as different ranges of random numbers.
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync #
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync auRet = [0, 1, ];
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if cbMaxOp >= 1:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync auRet += [ UINT8_MAX / 2, UINT8_MAX / 2 + 1, UINT8_MAX ];
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if cbMaxOp >= 2:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync auRet += [ UINT16_MAX / 2, UINT16_MAX / 2 + 1, UINT16_MAX ];
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if cbMaxOp >= 4:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync auRet += [ UINT32_MAX / 2, UINT32_MAX / 2 + 1, UINT32_MAX ];
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if cbMaxOp >= 8:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync auRet += [ UINT64_MAX / 2, UINT64_MAX / 2 + 1, UINT64_MAX ];
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if oGen.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync for cBits, cValues in ( (8, 4), (16, 4), (32, 8), (64, 8) ):
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if cBits < cbMaxOp * 8:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync auRet += randUxxList(cBits, cValues);
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync cWanted = 16;
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync elif oGen.oOptions.sTestSize == InstructionTestGen.ksTestSize_Medium:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync for cBits, cValues in ( (8, 8), (16, 8), (24, 2), (32, 16), (40, 1), (48, 1), (56, 1), (64, 16) ):
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if cBits < cbMaxOp * 8:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync auRet += randUxxList(cBits, cValues);
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync cWanted = 64;
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync else:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync for cBits, cValues in ( (8, 16), (16, 16), (24, 4), (32, 64), (40, 4), (48, 4), (56, 4), (64, 64) ):
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if cBits < cbMaxOp * 8:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync auRet += randUxxList(cBits, cValues);
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync cWanted = 168;
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if len(auRet) < cWanted:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync auRet += randUxxList(cbEffOp * 8, cWanted - len(auRet));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync else:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync #
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync # Short list, just do some random numbers.
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync #
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync auRet = [];
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if oGen.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync auRet += randUxxList(cbMaxOp, 1);
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync elif oGen.oOptions.sTestSize == InstructionTestGen.ksTestSize_Medium:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync auRet += randUxxList(cbMaxOp, 2);
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync else:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync auRet = [];
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync for cBits in (8, 16, 32, 64):
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if cBits < cbMaxOp * 8:
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync auRet += randUxxList(cBits, 1);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return auRet;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
270236340676d2385b27ea992e07fcb643bb78b6vboxsync
270236340676d2385b27ea992e07fcb643bb78b6vboxsyncclass InstrTest_MemOrGreg_2_Greg(InstrTestBase):
270236340676d2385b27ea992e07fcb643bb78b6vboxsync """
270236340676d2385b27ea992e07fcb643bb78b6vboxsync Instruction reading memory or general register and writing the result to a
270236340676d2385b27ea992e07fcb643bb78b6vboxsync general register.
270236340676d2385b27ea992e07fcb643bb78b6vboxsync """
270236340676d2385b27ea992e07fcb643bb78b6vboxsync
270236340676d2385b27ea992e07fcb643bb78b6vboxsync def __init__(self, sName, fnCalcResult, sInstr = None, acbOpVars = None):
270236340676d2385b27ea992e07fcb643bb78b6vboxsync InstrTestBase.__init__(self, sName, sInstr);
270236340676d2385b27ea992e07fcb643bb78b6vboxsync self.fnCalcResult = fnCalcResult;
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync self.acbOpVars = [ 1, 2, 4, 8 ] if not acbOpVars else list(acbOpVars);
2fd6ecdd81cabe2dae6f05dd8b5c3c584f03231bvboxsync self.fTestRegForm = True;
2fd6ecdd81cabe2dae6f05dd8b5c3c584f03231bvboxsync self.fTestMemForm = True;
270236340676d2385b27ea992e07fcb643bb78b6vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync ## @name Test Instruction Writers
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync ## @{
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def writeInstrGregGreg(self, cbEffOp, iOp1, iOp2, oGen):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ Writes the instruction with two general registers as operands. """
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync oGen.write(' %s %s, %s\n'
c744a417746b736ef91efc38f5e4ee099293f141vboxsync % ( self.sInstr, oGen.gregNameBytes(iOp1, cbEffOp), oGen.gregNameBytes(iOp2, cbEffOp),));
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync return True;
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync def writeInstrGregPureRM(self, cbEffOp, iOp1, cAddrBits, iOp2, iMod, offDisp, oGen):
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync """ Writes the instruction with two general registers as operands. """
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync oGen.write(' ');
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync if iOp2 == 13 and iMod == 0 and cAddrBits == 64:
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync oGen.write('altrexb '); # Alternative encoding for rip relative addressing.
c744a417746b736ef91efc38f5e4ee099293f141vboxsync oGen.write('%s %s, [' % (self.sInstr, oGen.gregNameBytes(iOp1, cbEffOp),));
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync if (iOp2 == 5 or iOp2 == 13) and iMod == 0:
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync oGen.write('VBINSTST_NAME(g_u%sData)' % (cbEffOp * 8,))
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync if oGen.oTarget.is64Bit():
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync oGen.write(' wrt rip');
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync else:
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync if iMod == 1:
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync oGen.write('byte %d + ' % (offDisp,));
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync elif iMod == 2:
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync oGen.write('dword %d + ' % (offDisp,));
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync else:
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync assert iMod == 0;
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync if cAddrBits == 64:
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync oGen.write(g_asGRegs64[iOp2]);
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync elif cAddrBits == 32:
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync oGen.write(g_asGRegs32[iOp2]);
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync elif cAddrBits == 16:
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync assert False; ## @todo implement 16-bit addressing.
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync else:
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync assert False, str(cAddrBits);
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync oGen.write(']\n');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return True;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync def writeInstrGregSibLabel(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen):
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync """ Writes the instruction taking a register and a label (base only w/o reg), SIB form. """
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync assert offDisp is None; assert iBaseReg in [5, 13]; assert iIndexReg == 4; assert cAddrBits != 16;
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync if cAddrBits == 64:
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync # Note! Cannot test this in 64-bit mode in any sensible way because the disp is 32-bit
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync # and we cannot (yet) make assumtions about where we're loaded.
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync ## @todo Enable testing this in environments where we can make assumptions (boot sector).
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync oGen.write(' %s %s, [VBINSTST_NAME(g_u%sData) xWrtRIP]\n'
c744a417746b736ef91efc38f5e4ee099293f141vboxsync % ( self.sInstr, oGen.gregNameBytes(iOp1, cbEffOp), cbEffOp * 8,));
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync else:
c744a417746b736ef91efc38f5e4ee099293f141vboxsync oGen.write(' altsibx%u %s %s, [VBINSTST_NAME(g_u%sData) xWrtRIP] ; iOp1=%s cbEffOp=%s\n'
c744a417746b736ef91efc38f5e4ee099293f141vboxsync % ( iScale, self.sInstr, oGen.gregNameBytes(iOp1, cbEffOp), cbEffOp * 8, iOp1, cbEffOp));
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync return True;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync def writeInstrGregSibScaledReg(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen):
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync """ Writes the instruction taking a register and disp+scaled register (no base reg), SIB form. """
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync assert iBaseReg in [5, 13]; assert iIndexReg != 4; assert cAddrBits != 16;
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync # Note! Using altsibxN to force scaled encoding. This is only really a
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync # necessity for iScale=1, but doesn't hurt for the rest.
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync oGen.write(' altsibx%u %s %s, [%s * %#x'
c744a417746b736ef91efc38f5e4ee099293f141vboxsync % (iScale, self.sInstr, oGen.gregNameBytes(iOp1, cbEffOp), oGen.gregNameBits(iIndexReg, cAddrBits), iScale,));
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync if offDisp is not None:
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.write(' + %#x' % (offDisp,));
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync oGen.write(']\n');
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync _ = iBaseReg;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync return True;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync def writeInstrGregSibBase(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen):
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync """ Writes the instruction taking a register and base only (with reg), SIB form. """
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync oGen.write(' altsibx%u %s %s, [%s'
c744a417746b736ef91efc38f5e4ee099293f141vboxsync % (iScale, self.sInstr, oGen.gregNameBytes(iOp1, cbEffOp), oGen.gregNameBits(iBaseReg, cAddrBits),));
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync if offDisp is not None:
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.write(' + %#x' % (offDisp,));
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync oGen.write(']\n');
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync _ = iIndexReg;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync return True;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync def writeInstrGregSibBaseAndScaledReg(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen):
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync """ Writes tinstruction taking a register and full featured SIB form address. """
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync # Note! From the looks of things, yasm will encode the following instructions the same way:
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync # mov eax, [rsi*1 + rbx]
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync # mov eax, [rbx + rsi*1]
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync # So, when there are two registers involved, the '*1' selects
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync # which is index and which is base.
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync oGen.write(' %s %s, [%s + %s * %u'
c744a417746b736ef91efc38f5e4ee099293f141vboxsync % ( self.sInstr, oGen.gregNameBytes(iOp1, cbEffOp),
c744a417746b736ef91efc38f5e4ee099293f141vboxsync oGen.gregNameBits(iBaseReg, cAddrBits), oGen.gregNameBits(iIndexReg, cAddrBits), iScale,));
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync if offDisp is not None:
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync oGen.write(' + %#x' % (offDisp,));
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync oGen.write(']\n');
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync return True;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync ## @}
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync ## @name Memory setups
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync ## @{
2fd6ecdd81cabe2dae6f05dd8b5c3c584f03231bvboxsync
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync def generateMemSetupReadByLabel(self, oGen, cbEffOp, uInput):
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync """ Sets up memory for a memory read. """
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.pushConst(uInput);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.write(' call VBINSTST_NAME(Common_SetupMemReadU%u)\n' % (cbEffOp*8,));
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync return True;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync def generateMemSetupReadByReg(self, oGen, cAddrBits, cbEffOp, iReg1, uInput, offDisp = None):
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync """ Sets up memory for a memory read indirectly addressed thru one register and optional displacement. """
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.pushConst(uInput);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.write(' call VBINSTST_NAME(%s)\n'
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, iBaseReg = iReg1, offDisp = offDisp),));
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iReg1],));
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync return True;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync def generateMemSetupReadByScaledReg(self, oGen, cAddrBits, cbEffOp, iIndexReg, iScale, uInput, offDisp = None):
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync """ Sets up memory for a memory read indirectly addressed thru one register and optional displacement. """
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.pushConst(uInput);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.write(' call VBINSTST_NAME(%s)\n'
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, offDisp = offDisp, iIndexReg = iIndexReg, iScale = iScale),));
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iIndexReg],));
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync return True;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync def generateMemSetupReadByBaseAndScaledReg(self, oGen, cAddrBits, cbEffOp, iBaseReg, iIndexReg, iScale, uInput, offDisp):
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync """ Sets up memory for a memory read indirectly addressed thru two registers with optional displacement. """
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.pushConst(uInput);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.write(' call VBINSTST_NAME(%s)\n'
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, iBaseReg = iBaseReg, offDisp = offDisp,
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync iIndexReg = iIndexReg, iScale = iScale),));
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iIndexReg],));
8541678784dbe432feebe6d9c1528525e1771397vboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iBaseReg],));
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync return True;
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync def generateMemSetupPureRM(self, oGen, cAddrBits, cbEffOp, iOp2, iMod, uInput, offDisp = None):
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync """ Sets up memory for a pure R/M addressed read, iOp2 being the R/M value. """
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync oGen.pushConst(uInput);
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync assert offDisp is None or iMod != 0;
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync if (iOp2 != 5 and iOp2 != 13) or iMod != 0:
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync oGen.write(' call VBINSTST_NAME(%s)\n'
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, iOp2, offDisp),));
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync else:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync oGen.write(' call VBINSTST_NAME(Common_SetupMemReadU%u)\n' % (cbEffOp*8,));
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iOp2],));
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync return True;
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync ## @}
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync def generateOneStdTestGregGreg(self, oGen, cbEffOp, cbMaxOp, iOp1, iOp1X, iOp2, iOp2X, uInput, uResult):
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync """ Generate one standard instr greg,greg test. """
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2X], uInput,));
8541678784dbe432feebe6d9c1528525e1771397vboxsync if iOp1X != iOp2X:
8541678784dbe432feebe6d9c1528525e1771397vboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iOp2X],));
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync self.writeInstrGregGreg(cbEffOp, iOp1, iOp2, oGen);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.pushConst(uResult);
8541678784dbe432feebe6d9c1528525e1771397vboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(iOp1X, iOp2X if iOp1X != iOp2X else None),));
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync _ = cbMaxOp;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync return True;
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync def generateOneStdTestGregGreg8BitHighPain(self, oGen, cbEffOp, cbMaxOp, iOp1, iOp2, uInput):
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync """ High 8-bit registers are a real pain! """
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync assert oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1) or oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2);
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync # Figure out the register indexes of the max op sized regs involved.
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync iOp1X = iOp1 & 3;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync iOp2X = iOp2 & 3;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync oGen.write(' ; iOp1=%u iOp1X=%u iOp2=%u iOp2X=%u\n' % (iOp1, iOp1X, iOp2, iOp2X,));
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync # Calculate unshifted result.
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if iOp1X != iOp2X:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uCur = oGen.auRegValues[iOp1X];
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1):
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uCur = rotateRightUxx(cbMaxOp * 8, uCur, 8);
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync else:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uCur = uInput;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1) != oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2):
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1):
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uCur = rotateRightUxx(cbMaxOp * 8, uCur, 8);
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync else:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uCur = rotateLeftUxx(cbMaxOp * 8, uCur, 8);
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uResult = self.fnCalcResult(cbEffOp, uInput, uCur, oGen);
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync # Rotate the input and/or result to match their max-op-sized registers.
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2):
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uInput = rotateLeftUxx(cbMaxOp * 8, uInput, 8);
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1):
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uResult = rotateLeftUxx(cbMaxOp * 8, uResult, 8);
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync # Hand it over to an overridable worker method.
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync return self.generateOneStdTestGregGreg(oGen, cbEffOp, cbMaxOp, iOp1, iOp1X, iOp2, iOp2X, uInput, uResult);
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync def generateOneStdTestGregMemNoSib(self, oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, iOp2, uInput, uResult):
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync """ Generate mode 0, 1 and 2 test for the R/M=iOp2. """
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync if cAddrBits == 16:
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync _ = cbMaxOp;
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync else:
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync iMod = 0; # No disp, except for i=5.
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync self.generateMemSetupPureRM(oGen, cAddrBits, cbEffOp, iOp2, iMod, uInput);
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync self.writeInstrGregPureRM(cbEffOp, iOp1, cAddrBits, iOp2, iMod, None, oGen);
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync oGen.pushConst(uResult);
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(iOp1, iOp2),));
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync if iOp2 != 5 and iOp2 != 13:
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync iMod = 1;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync for offDisp in oGen.getDispForMod(iMod):
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync self.generateMemSetupPureRM(oGen, cAddrBits, cbEffOp, iOp2, iMod, uInput, offDisp);
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync self.writeInstrGregPureRM(cbEffOp, iOp1, cAddrBits, iOp2, iMod, offDisp, oGen);
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync oGen.pushConst(uResult);
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(iOp1, iOp2),));
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync iMod = 2;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync for offDisp in oGen.getDispForMod(iMod):
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync self.generateMemSetupPureRM(oGen, cAddrBits, cbEffOp, iOp2, iMod, uInput, offDisp);
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync self.writeInstrGregPureRM(cbEffOp, iOp1, cAddrBits, iOp2, iMod, offDisp, oGen);
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync oGen.pushConst(uResult);
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(iOp1, iOp2),));
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync return True;
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync def generateOneStdTestGregMemSib(self, oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, iMod, # pylint: disable=R0913
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync iBaseReg, iIndexReg, iScale, uInput, uResult):
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync """ Generate one SIB variations. """
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync for offDisp in oGen.getDispForMod(iMod, cbEffOp):
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync if ((iBaseReg == 5 or iBaseReg == 13) and iMod == 0):
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync if iIndexReg == 4:
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync if cAddrBits == 64:
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync continue; # skipping.
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync self.generateMemSetupReadByLabel(oGen, cbEffOp, uInput);
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync self.writeInstrGregSibLabel(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync sChecker = oGen.needGRegChecker(iOp1);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync else:
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync self.generateMemSetupReadByScaledReg(oGen, cAddrBits, cbEffOp, iIndexReg, iScale, uInput, offDisp);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync self.writeInstrGregSibScaledReg(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync sChecker = oGen.needGRegChecker(iOp1, iIndexReg);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync else:
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync if iIndexReg == 4:
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync self.generateMemSetupReadByReg(oGen, cAddrBits, cbEffOp, iBaseReg, uInput, offDisp);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync self.writeInstrGregSibBase(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync sChecker = oGen.needGRegChecker(iOp1, iBaseReg);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync else:
8541678784dbe432feebe6d9c1528525e1771397vboxsync if iIndexReg == iBaseReg and iScale == 1 and offDisp is not None and (offDisp & 1):
8541678784dbe432feebe6d9c1528525e1771397vboxsync if offDisp < 0: offDisp += 1;
8541678784dbe432feebe6d9c1528525e1771397vboxsync else: offDisp -= 1;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync self.generateMemSetupReadByBaseAndScaledReg(oGen, cAddrBits, cbEffOp, iBaseReg,
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync iIndexReg, iScale, uInput, offDisp);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync self.writeInstrGregSibBaseAndScaledReg(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync sChecker = oGen.needGRegChecker(iOp1, iBaseReg, iIndexReg);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.pushConst(uResult);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (sChecker,));
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync _ = cbMaxOp;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync return True;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync def generateStdTestGregMemSib(self, oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, auInputs):
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync """ Generate all SIB variations for the given iOp1 (reg) value. """
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync assert cAddrBits in [32, 64];
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync i = oGen.cSibBasePerRun;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync while i > 0:
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync oGen.iSibBaseReg = (oGen.iSibBaseReg + 1) % oGen.oTarget.getGRegCount(cAddrBits / 8);
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync if oGen.iSibBaseReg == X86_GREG_xSP: # no RSP testing atm.
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync continue;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync j = oGen.getSibIndexPerRun();
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync while j > 0:
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync oGen.iSibIndexReg = (oGen.iSibIndexReg + 1) % oGen.oTarget.getGRegCount(cAddrBits / 8);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync if oGen.iSibIndexReg == iOp1 and oGen.iSibIndexReg != 4 and cAddrBits != cbMaxOp:
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync continue; # Don't know the high bit of the address ending up the result - skip it for now.
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync for iMod in [0, 1, 2]:
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync if oGen.iSibBaseReg == iOp1 \
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync and ((oGen.iSibBaseReg != 5 and oGen.iSibBaseReg != 13) or iMod != 0) \
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync and cAddrBits != cbMaxOp:
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync continue; # Don't know the high bit of the address ending up the result - skip it for now.
72e9ef1022a910facbd4a232500026befd944d95vboxsync
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync for _ in oGen.oSibScaleRange:
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync oGen.iSibScale *= 2;
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync if oGen.iSibScale > 8:
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync oGen.iSibScale = 1;
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync for uInput in auInputs:
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync oGen.newSubTest();
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync uResult = self.fnCalcResult(cbEffOp, uInput, oGen.auRegValues[iOp1], oGen);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync self.generateOneStdTestGregMemSib(oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, iMod,
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync oGen.iSibBaseReg, oGen.iSibIndexReg, oGen.iSibScale,
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync uInput, uResult);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync j -= 1;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync i -= 1;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync return True;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync def generateStandardTests(self, oGen):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ Generate standard tests. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync # Parameters.
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync cbDefOp = oGen.oTarget.getDefOpBytes();
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync cbMaxOp = oGen.oTarget.getMaxOpBytes();
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync auShortInputs = self.generateInputs(cbDefOp, cbMaxOp, oGen);
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync auLongInputs = self.generateInputs(cbDefOp, cbMaxOp, oGen, fLong = True);
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync iLongOp1 = oGen.oTarget.randGRegNoSp();
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync iLongOp2 = oGen.oTarget.randGRegNoSp();
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync
270236340676d2385b27ea992e07fcb643bb78b6vboxsync # Register tests
2fd6ecdd81cabe2dae6f05dd8b5c3c584f03231bvboxsync if self.fTestRegForm:
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync for cbEffOp in self.acbOpVars:
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync if cbEffOp > cbMaxOp:
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync continue;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync oOp2Range = range(oGen.oTarget.getGRegCount(cbEffOp));
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if oGen.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync oOp2Range = [iLongOp2,];
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync oGen.write('; cbEffOp=%u\n' % (cbEffOp,));
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync for iOp1 in range(oGen.oTarget.getGRegCount(cbEffOp)):
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if iOp1 == X86_GREG_xSP:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync continue; # Cannot test xSP atm.
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync for iOp2 in oOp2Range:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if (iOp2 >= 16 and iOp1 in range(4, 16)) \
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync or (iOp1 >= 16 and iOp2 in range(4, 16)):
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync continue; # Any REX encoding turns AH,CH,DH,BH regs into SPL,BPL,SIL,DIL.
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if iOp2 == X86_GREG_xSP:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync continue; # Cannot test xSP atm.
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync oGen.write('; iOp2=%u cbEffOp=%u\n' % (iOp2, cbEffOp));
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync for uInput in (auLongInputs if iOp1 == iLongOp1 and iOp2 == iLongOp2 else auShortInputs):
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync oGen.newSubTest();
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync if not oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1) and not oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2):
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uCur = oGen.auRegValues[iOp1 & 15] if iOp1 != iOp2 else uInput;
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uResult = self.fnCalcResult(cbEffOp, uInput, uCur, oGen);
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync self.generateOneStdTestGregGreg(oGen, cbEffOp, cbMaxOp, iOp1, iOp1 & 15, iOp2, iOp2 & 15,
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync uInput, uResult);
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync else:
c4b8dd273d2becff4145cf4c634b566e2dd633e6vboxsync self.generateOneStdTestGregGreg8BitHighPain(oGen, cbEffOp, cbMaxOp, iOp1, iOp2, uInput);
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync # Memory test.
2fd6ecdd81cabe2dae6f05dd8b5c3c584f03231bvboxsync if self.fTestMemForm:
72e9ef1022a910facbd4a232500026befd944d95vboxsync for cAddrBits in oGen.oTarget.getAddrModes():
72e9ef1022a910facbd4a232500026befd944d95vboxsync for cbEffOp in self.acbOpVars:
72e9ef1022a910facbd4a232500026befd944d95vboxsync if cbEffOp > cbMaxOp:
72e9ef1022a910facbd4a232500026befd944d95vboxsync continue;
72e9ef1022a910facbd4a232500026befd944d95vboxsync
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync for _ in oGen.getModRegRange(cbEffOp):
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync oGen.iModReg = (oGen.iModReg + 1) % oGen.oTarget.getGRegCount(cbEffOp);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync if oGen.iModReg == X86_GREG_xSP:
72e9ef1022a910facbd4a232500026befd944d95vboxsync continue; # Cannot test xSP atm.
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync if oGen.iModReg > 15:
72e9ef1022a910facbd4a232500026befd944d95vboxsync continue; ## TODO AH,CH,DH,BH
72e9ef1022a910facbd4a232500026befd944d95vboxsync
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync auInputs = auLongInputs if oGen.iModReg == iLongOp1 else auShortInputs;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync for _ in oGen.oModRmRange:
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync oGen.iModRm = (oGen.iModRm + 1) % oGen.oTarget.getGRegCount(cAddrBits * 8);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync if oGen.iModRm != 4 or cAddrBits == 16:
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync for uInput in auInputs:
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync oGen.newSubTest();
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if oGen.iModReg == oGen.iModRm and oGen.iModRm != 5 \
54ed927d658674ced4387afbd1877a27cb975a76vboxsync and oGen.iModRm != 13 and cbEffOp != cbMaxOp:
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync continue; # Don't know the high bit of the address ending up the result - skip it for now.
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync uResult = self.fnCalcResult(cbEffOp, uInput, oGen.auRegValues[oGen.iModReg & 15], oGen);
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync self.generateOneStdTestGregMemNoSib(oGen, cAddrBits, cbEffOp, cbMaxOp,
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync oGen.iModReg, oGen.iModRm, uInput, uResult);
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync else:
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync # SIB - currently only short list of inputs or things may get seriously out of hand.
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.generateStdTestGregMemSib(oGen, cAddrBits, cbEffOp, cbMaxOp, oGen.iModReg, auShortInputs);
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync return True;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def generateTest(self, oGen, sTestFnName):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync oGen.write('VBINSTST_BEGINPROC %s\n' % (sTestFnName,));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.generateStandardTests(oGen);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync oGen.write(' ret\n');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync oGen.write('VBINSTST_ENDPROC %s\n' % (sTestFnName,));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return True;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsyncclass InstrTest_Mov_Gv_Ev(InstrTest_MemOrGreg_2_Greg):
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync """
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync Tests MOV Gv,Ev.
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync """
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync def __init__(self):
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync InstrTest_MemOrGreg_2_Greg.__init__(self, 'mov Gv,Ev', self.calc_mov);
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync @staticmethod
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync def calc_mov(cbEffOp, uInput, uCur, oGen):
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync """ Calculates the result of a mov instruction."""
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync if cbEffOp == 8:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync return uInput & UINT64_MAX;
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync if cbEffOp == 4:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync return uInput & UINT32_MAX;
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync if cbEffOp == 2:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync return (uCur & 0xffffffffffff0000) | (uInput & UINT16_MAX);
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync assert cbEffOp == 1; _ = oGen;
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync return (uCur & 0xffffffffffffff00) | (uInput & UINT8_MAX);
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncclass InstrTest_MovSxD_Gv_Ev(InstrTest_MemOrGreg_2_Greg):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Tests MOVSXD Gv,Ev.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def __init__(self):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync InstrTest_MemOrGreg_2_Greg.__init__(self, 'movsxd Gv,Ev', self.calc_movsxd, acbOpVars = [ 8, 4, 2, ]);
2fd6ecdd81cabe2dae6f05dd8b5c3c584f03231bvboxsync self.fTestMemForm = False; # drop this...
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def writeInstrGregGreg(self, cbEffOp, iOp1, iOp2, oGen):
2fd6ecdd81cabe2dae6f05dd8b5c3c584f03231bvboxsync """ Writes the instruction with two general registers as operands. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if cbEffOp == 8:
2fd6ecdd81cabe2dae6f05dd8b5c3c584f03231bvboxsync oGen.write(' movsxd %s, %s\n'
2fd6ecdd81cabe2dae6f05dd8b5c3c584f03231bvboxsync % ( oGen.gregNameBytes(iOp1, cbEffOp), oGen.gregNameBytes(iOp2, cbEffOp / 2),));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync else:
2fd6ecdd81cabe2dae6f05dd8b5c3c584f03231bvboxsync oGen.write(' oddmovsxd %s, %s\n'
2fd6ecdd81cabe2dae6f05dd8b5c3c584f03231bvboxsync % ( oGen.gregNameBytes(iOp1, cbEffOp), oGen.gregNameBytes(iOp2, cbEffOp),));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return True;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync def isApplicable(self, oGen):
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync return oGen.oTarget.is64Bit();
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync @staticmethod
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def calc_movsxd(cbEffOp, uInput, uCur, oGen):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Calculates the result of a movxsd instruction.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Returns the result value (cbMaxOp sized).
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync _ = oGen;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if cbEffOp == 8 and (uInput & RT_BIT_32(31)):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return (UINT32_MAX << 32) | (uInput & UINT32_MAX);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if cbEffOp == 2:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return (uCur & 0xffffffffffff0000) | (uInput & 0xffff);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return uInput & UINT32_MAX;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsyncclass InstrTest_DivIDiv(InstrTestBase):
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync """
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync Tests IDIV and DIV instructions.
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync """
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync def __init__(self, fIsIDiv):
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync if not fIsIDiv:
54ed927d658674ced4387afbd1877a27cb975a76vboxsync InstrTestBase.__init__(self, 'div Gv,Ev', 'div');
54ed927d658674ced4387afbd1877a27cb975a76vboxsync else:
54ed927d658674ced4387afbd1877a27cb975a76vboxsync InstrTestBase.__init__(self, 'idiv Gv,Ev', 'idiv');
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync self.fIsIDiv = fIsIDiv;
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync def generateInputEdgeCases(self, cbEffOp, fLong, fXcpt):
7528d4a15800321b4013826ce35ad184898dba21vboxsync """ Generate edge case inputs for cbEffOp. Returns a list of pairs, dividen + divisor. """
54ed927d658674ced4387afbd1877a27cb975a76vboxsync # Test params.
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uStep = 1 << (cbEffOp * 8);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if self.fIsIDiv:
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uStep /= 2;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync # edge tests
54ed927d658674ced4387afbd1877a27cb975a76vboxsync auRet = [];
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uDivisor = 1 if fLong else 3;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uDividend = uStep * uDivisor - 1;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync for i in range(5 if fLong else 3):
7528d4a15800321b4013826ce35ad184898dba21vboxsync auRet.append([uDividend + fXcpt, uDivisor]);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if self.fIsIDiv:
7528d4a15800321b4013826ce35ad184898dba21vboxsync auRet.append([-uDividend - fXcpt, -uDivisor]);
7528d4a15800321b4013826ce35ad184898dba21vboxsync auRet.append([-(uDividend + uDivisor + fXcpt), uDivisor]);
7528d4a15800321b4013826ce35ad184898dba21vboxsync auRet.append([ (uDividend + uDivisor + fXcpt), -uDivisor]);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if i <= 3 and fLong:
7528d4a15800321b4013826ce35ad184898dba21vboxsync auRet.append([uDividend - 1 + fXcpt*3, uDivisor]);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if self.fIsIDiv:
7528d4a15800321b4013826ce35ad184898dba21vboxsync auRet.append([-(uDividend - 1 + fXcpt*3), -uDivisor]);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uDivisor += 1;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uDividend += uStep;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uDivisor = uStep - 1;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uDividend = uStep * uDivisor - 1;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync for _ in range(3 if fLong else 1):
7528d4a15800321b4013826ce35ad184898dba21vboxsync auRet.append([uDividend + fXcpt, uDivisor]);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if self.fIsIDiv:
7528d4a15800321b4013826ce35ad184898dba21vboxsync auRet.append([-uDividend - fXcpt, -uDivisor]);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uDivisor -= 1;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uDividend -= uStep;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if self.fIsIDiv:
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uDivisor = -uStep;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync for _ in range(3 if fLong else 1):
7528d4a15800321b4013826ce35ad184898dba21vboxsync auRet.append([uDivisor * (-uStep - 1) - (not fXcpt), uDivisor]);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uDivisor += 1
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uDivisor = uStep - 1;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync for _ in range(3 if fLong else 1):
7528d4a15800321b4013826ce35ad184898dba21vboxsync auRet.append([-(uDivisor * (uStep + 1) - (not fXcpt)), uDivisor]);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uDivisor -= 1
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync return auRet;
7528d4a15800321b4013826ce35ad184898dba21vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync def generateInputsNoXcpt(self, cbEffOp, fLong = False):
7528d4a15800321b4013826ce35ad184898dba21vboxsync """ Generate inputs for cbEffOp. Returns a list of pairs, dividen + divisor. """
7528d4a15800321b4013826ce35ad184898dba21vboxsync # Test params.
7528d4a15800321b4013826ce35ad184898dba21vboxsync uStep = 1 << (cbEffOp * 8);
7528d4a15800321b4013826ce35ad184898dba21vboxsync if self.fIsIDiv:
7528d4a15800321b4013826ce35ad184898dba21vboxsync uStep /= 2;
7528d4a15800321b4013826ce35ad184898dba21vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync # edge tests
7528d4a15800321b4013826ce35ad184898dba21vboxsync auRet = self.generateInputEdgeCases(cbEffOp, fLong, False)
7528d4a15800321b4013826ce35ad184898dba21vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync # random tests.
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if self.fIsIDiv:
54ed927d658674ced4387afbd1877a27cb975a76vboxsync for _ in range(6 if fLong else 2):
54ed927d658674ced4387afbd1877a27cb975a76vboxsync while True:
7528d4a15800321b4013826ce35ad184898dba21vboxsync uDivisor = randSxx(cbEffOp * 8);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if uDivisor == 0 or uDivisor >= uStep or uDivisor < -uStep:
54ed927d658674ced4387afbd1877a27cb975a76vboxsync continue;
7528d4a15800321b4013826ce35ad184898dba21vboxsync uDividend = randSxx(cbEffOp * 16);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uResult = uDividend / uDivisor;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if uResult >= uStep or uResult <= -uStep: # exclude difficulties
54ed927d658674ced4387afbd1877a27cb975a76vboxsync continue;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync break;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync auRet.append([uDividend, uDivisor]);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync else:
54ed927d658674ced4387afbd1877a27cb975a76vboxsync for _ in range(6 if fLong else 2):
54ed927d658674ced4387afbd1877a27cb975a76vboxsync while True:
7528d4a15800321b4013826ce35ad184898dba21vboxsync uDivisor = randUxx(cbEffOp * 8);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if uDivisor == 0 or uDivisor >= uStep:
54ed927d658674ced4387afbd1877a27cb975a76vboxsync continue;
7528d4a15800321b4013826ce35ad184898dba21vboxsync uDividend = randUxx(cbEffOp * 16);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uResult = uDividend / uDivisor;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if uResult >= uStep:
54ed927d658674ced4387afbd1877a27cb975a76vboxsync continue;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync break;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync auRet.append([uDividend, uDivisor]);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync return auRet;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync def generateOneStdTestGreg(self, oGen, cbEffOp, iOp2, iDividend, iDivisor):
54ed927d658674ced4387afbd1877a27cb975a76vboxsync """ Generate code of one '[I]DIV rDX:rAX,<GREG>' test. """
54ed927d658674ced4387afbd1877a27cb975a76vboxsync cbMaxOp = oGen.oTarget.getMaxOpBytes();
54ed927d658674ced4387afbd1877a27cb975a76vboxsync fEffOp = ((1 << (cbEffOp *8) ) - 1);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync fMaxOp = UINT64_MAX if cbMaxOp == 8 else UINT32_MAX; assert cbMaxOp in [8, 4];
54ed927d658674ced4387afbd1877a27cb975a76vboxsync fTopOp = fMaxOp - fEffOp;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync fFullOp1 = ((1 << (cbEffOp*16)) - 1);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uAX = iDividend & fFullOp1; # full with unsigned
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uDX = uAX >> (cbEffOp*8);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uAX &= fEffOp;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uOp2Val = iDivisor & fEffOp;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync iQuotient = iDividend / iDivisor;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync iReminder = iDividend % iDivisor;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if iReminder != 0 and iQuotient < 0: # python has different rounding rules for negative division.
54ed927d658674ced4387afbd1877a27cb975a76vboxsync iQuotient += 1;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync iReminder -= iDivisor;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uAXResult = iQuotient & fEffOp;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uDXResult = iReminder & fEffOp;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if cbEffOp < cbMaxOp:
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uAX |= randUxx(cbMaxOp * 8) & fTopOp;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uDX |= randUxx(cbMaxOp * 8) & fTopOp;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uOp2Val |= randUxx(cbMaxOp * 8) & fTopOp;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if cbEffOp < 4:
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uAXResult |= uAX & fTopOp;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uDXResult |= uDX & fTopOp;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.write(' ; iDividend=%#x (%d) iDivisor=%#x (%d)\n'
54ed927d658674ced4387afbd1877a27cb975a76vboxsync ' ; iQuotient=%#x (%d) iReminder=%#x (%d)\n'
54ed927d658674ced4387afbd1877a27cb975a76vboxsync % ( iDividend & fFullOp1, iDividend, iDivisor & fEffOp, iDivisor,
54ed927d658674ced4387afbd1877a27cb975a76vboxsync iQuotient & fEffOp, iQuotient, iReminder & fEffOp, iReminder, ));
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[X86_GREG_xDX], uDX,));
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[X86_GREG_xAX], uAX,));
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2], uOp2Val,));
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iOp2],));
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.pushConst(uDXResult);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.pushConst(uAXResult);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
6adbde734d9d0bd2d870a3efa022b7f3fcc8b6f7vboxsync oGen.write(' %-4s %s\n' % (self.sInstr, oGen.gregNameBytes(iOp2, cbEffOp),));
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(X86_GREG_xAX, X86_GREG_xDX, iOp2),));
54ed927d658674ced4387afbd1877a27cb975a76vboxsync return True;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync def generateOneStdTestGreg8Bit(self, oGen, cbEffOp, iOp2, iDividend, iDivisor):
54ed927d658674ced4387afbd1877a27cb975a76vboxsync """ Generate code of one '[I]DIV AX,<GREG>' test (8-bit). """
54ed927d658674ced4387afbd1877a27cb975a76vboxsync cbMaxOp = oGen.oTarget.getMaxOpBytes();
54ed927d658674ced4387afbd1877a27cb975a76vboxsync fMaxOp = UINT64_MAX if cbMaxOp == 8 else UINT32_MAX; assert cbMaxOp in [8, 4];
54ed927d658674ced4387afbd1877a27cb975a76vboxsync iOp2X = (iOp2 & 3) if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2) else iOp2;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync assert iOp2X != X86_GREG_xAX;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uAX = iDividend & UINT16_MAX; # full with unsigned
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uOp2Val = iDivisor & UINT8_MAX;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync iQuotient = iDividend / iDivisor;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync iReminder = iDividend % iDivisor;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if iReminder != 0 and iQuotient < 0: # python has different rounding rules for negative division.
54ed927d658674ced4387afbd1877a27cb975a76vboxsync iQuotient += 1;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync iReminder -= iDivisor;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uAXResult = (iQuotient & UINT8_MAX) | ((iReminder & UINT8_MAX) << 8);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uAX |= randUxx(cbMaxOp * 8) & (fMaxOp - UINT16_MAX);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uAXResult |= uAX & (fMaxOp - UINT16_MAX);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uOp2Val |= randUxx(cbMaxOp * 8) & (fMaxOp - UINT8_MAX);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if iOp2X != iOp2:
54ed927d658674ced4387afbd1877a27cb975a76vboxsync uOp2Val = rotateLeftUxx(cbMaxOp * 8, uOp2Val, 8);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.write(' ; iDividend=%#x (%d) iDivisor=%#x (%d)\n'
54ed927d658674ced4387afbd1877a27cb975a76vboxsync ' ; iQuotient=%#x (%d) iReminder=%#x (%d)\n'
54ed927d658674ced4387afbd1877a27cb975a76vboxsync % ( iDividend & UINT16_MAX, iDividend, iDivisor & UINT8_MAX, iDivisor,
54ed927d658674ced4387afbd1877a27cb975a76vboxsync iQuotient & UINT8_MAX, iQuotient, iReminder & UINT8_MAX, iReminder, ));
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[X86_GREG_xAX], uAX,));
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2X], uOp2Val,));
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iOp2X],));
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.pushConst(uAXResult);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
6adbde734d9d0bd2d870a3efa022b7f3fcc8b6f7vboxsync oGen.write(' %-4s %s\n' % (self.sInstr, oGen.gregNameBytes(iOp2, cbEffOp),));
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(X86_GREG_xAX, iOp2X),));
54ed927d658674ced4387afbd1877a27cb975a76vboxsync return;
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync def generateStandardTests(self, oGen):
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync """ Generates test that causes no exceptions. """
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # Parameters.
54ed927d658674ced4387afbd1877a27cb975a76vboxsync iLongOp2 = oGen.oTarget.randGRegNoSp();
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # Register tests
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync if True:
54ed927d658674ced4387afbd1877a27cb975a76vboxsync for cbEffOp in ( 8, 4, 2, 1 ):
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if cbEffOp > oGen.oTarget.getMaxOpBytes():
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync continue;
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync oGen.write('; cbEffOp=%u\n' % (cbEffOp,));
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync oOp2Range = range(oGen.oTarget.getGRegCount(cbEffOp));
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync if oGen.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny:
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync oOp2Range = [iLongOp2,];
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync for iOp2 in oOp2Range:
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync if iOp2 == X86_GREG_xSP:
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync continue; # Cannot test xSP atm.
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if iOp2 == X86_GREG_xAX or (cbEffOp > 1 and iOp2 == X86_GREG_xDX):
54ed927d658674ced4387afbd1877a27cb975a76vboxsync continue; # Will overflow or be too complicated to get right.
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if cbEffOp == 1 and iOp2 == (16 if oGen.oTarget.is64Bit() else 4):
54ed927d658674ced4387afbd1877a27cb975a76vboxsync continue; # Avoid dividing by AH, same reasons as above.
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync for iDividend, iDivisor in self.generateInputsNoXcpt(cbEffOp, iOp2 == iLongOp2):
54ed927d658674ced4387afbd1877a27cb975a76vboxsync oGen.newSubTest();
54ed927d658674ced4387afbd1877a27cb975a76vboxsync if cbEffOp > 1:
54ed927d658674ced4387afbd1877a27cb975a76vboxsync self.generateOneStdTestGreg(oGen, cbEffOp, iOp2, iDividend, iDivisor);
54ed927d658674ced4387afbd1877a27cb975a76vboxsync else:
54ed927d658674ced4387afbd1877a27cb975a76vboxsync self.generateOneStdTestGreg8Bit(oGen, cbEffOp, iOp2, iDividend, iDivisor);
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync ## Memory test.
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync #if False:
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # for cAddrBits in oGen.oTarget.getAddrModes():
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # for cbEffOp in self.acbOpVars:
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # if cbEffOp > cbMaxOp:
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # continue;
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync #
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # auInputs = auLongInputs if oGen.iModReg == iLongOp1 else auShortInputs;
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # for _ in oGen.oModRmRange:
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # oGen.iModRm = (oGen.iModRm + 1) % oGen.oTarget.getGRegCount(cAddrBits * 8);
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # if oGen.iModRm != 4 or cAddrBits == 16:
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # for uInput in auInputs:
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # oGen.newSubTest();
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # if oGen.iModReg == oGen.iModRm and oGen.iModRm != 5 and oGen.iModRm != 13 and cbEffOp != cbMaxOp:
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # continue; # Don't know the high bit of the address ending up the result - skip it for now.
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # uResult = self.fnCalcResult(cbEffOp, uInput, oGen.auRegValues[oGen.iModReg & 15], oGen);
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # self.generateOneStdTestGregMemNoSib(oGen, cAddrBits, cbEffOp, cbMaxOp,
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # oGen.iModReg, oGen.iModRm, uInput, uResult);
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # else:
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # # SIB - currently only short list of inputs or things may get seriously out of hand.
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync # self.generateStdTestGregMemSib(oGen, cAddrBits, cbEffOp, cbMaxOp, oGen.iModReg, auShortInputs);
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync #
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync return True;
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync def generateInputsXcpt(self, cbEffOp, fLong = False):
7528d4a15800321b4013826ce35ad184898dba21vboxsync """
7528d4a15800321b4013826ce35ad184898dba21vboxsync Generate inputs for cbEffOp that will overflow or underflow.
7528d4a15800321b4013826ce35ad184898dba21vboxsync Returns a list of pairs, dividen + divisor.
7528d4a15800321b4013826ce35ad184898dba21vboxsync """
7528d4a15800321b4013826ce35ad184898dba21vboxsync # Test params.
7528d4a15800321b4013826ce35ad184898dba21vboxsync uStep = 1 << (cbEffOp * 8);
7528d4a15800321b4013826ce35ad184898dba21vboxsync if self.fIsIDiv:
7528d4a15800321b4013826ce35ad184898dba21vboxsync uStep /= 2;
7528d4a15800321b4013826ce35ad184898dba21vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync # edge tests
7528d4a15800321b4013826ce35ad184898dba21vboxsync auRet = self.generateInputEdgeCases(cbEffOp, fLong, True);
7528d4a15800321b4013826ce35ad184898dba21vboxsync auRet.extend([[0, 0], [1, 0], [ uStep * uStep / 2 - 1, 0]]);
7528d4a15800321b4013826ce35ad184898dba21vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync # random tests.
7528d4a15800321b4013826ce35ad184898dba21vboxsync if self.fIsIDiv:
7528d4a15800321b4013826ce35ad184898dba21vboxsync for _ in range(6 if fLong else 2):
7528d4a15800321b4013826ce35ad184898dba21vboxsync while True:
7528d4a15800321b4013826ce35ad184898dba21vboxsync uDivisor = randSxx(cbEffOp * 8);
7528d4a15800321b4013826ce35ad184898dba21vboxsync uDividend = randSxx(cbEffOp * 16);
7528d4a15800321b4013826ce35ad184898dba21vboxsync if uDivisor >= uStep or uDivisor < -uStep:
7528d4a15800321b4013826ce35ad184898dba21vboxsync continue;
7528d4a15800321b4013826ce35ad184898dba21vboxsync if uDivisor != 0:
7528d4a15800321b4013826ce35ad184898dba21vboxsync uResult = uDividend / uDivisor;
7528d4a15800321b4013826ce35ad184898dba21vboxsync if (uResult <= uStep and uResult >= 0) or (uResult >= -uStep and uResult < 0):
7528d4a15800321b4013826ce35ad184898dba21vboxsync continue; # exclude difficulties
7528d4a15800321b4013826ce35ad184898dba21vboxsync break;
7528d4a15800321b4013826ce35ad184898dba21vboxsync auRet.append([uDividend, uDivisor]);
7528d4a15800321b4013826ce35ad184898dba21vboxsync else:
7528d4a15800321b4013826ce35ad184898dba21vboxsync for _ in range(6 if fLong else 2):
7528d4a15800321b4013826ce35ad184898dba21vboxsync while True:
7528d4a15800321b4013826ce35ad184898dba21vboxsync uDivisor = randUxx(cbEffOp * 8);
7528d4a15800321b4013826ce35ad184898dba21vboxsync uDividend = randUxx(cbEffOp * 16);
7528d4a15800321b4013826ce35ad184898dba21vboxsync if uDivisor >= uStep:
7528d4a15800321b4013826ce35ad184898dba21vboxsync continue;
7528d4a15800321b4013826ce35ad184898dba21vboxsync if uDivisor != 0:
7528d4a15800321b4013826ce35ad184898dba21vboxsync uResult = uDividend / uDivisor;
7528d4a15800321b4013826ce35ad184898dba21vboxsync if uResult < uStep:
7528d4a15800321b4013826ce35ad184898dba21vboxsync continue;
7528d4a15800321b4013826ce35ad184898dba21vboxsync break;
7528d4a15800321b4013826ce35ad184898dba21vboxsync auRet.append([uDividend, uDivisor]);
7528d4a15800321b4013826ce35ad184898dba21vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync return auRet;
7528d4a15800321b4013826ce35ad184898dba21vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync def generateOneDivideErrorTestGreg(self, oGen, cbEffOp, iOp2, iDividend, iDivisor):
7528d4a15800321b4013826ce35ad184898dba21vboxsync """ Generate code of one '[I]DIV rDX:rAX,<GREG>' test that causes #DE. """
7528d4a15800321b4013826ce35ad184898dba21vboxsync cbMaxOp = oGen.oTarget.getMaxOpBytes();
7528d4a15800321b4013826ce35ad184898dba21vboxsync fEffOp = ((1 << (cbEffOp *8) ) - 1);
7528d4a15800321b4013826ce35ad184898dba21vboxsync fMaxOp = UINT64_MAX if cbMaxOp == 8 else UINT32_MAX; assert cbMaxOp in [8, 4];
7528d4a15800321b4013826ce35ad184898dba21vboxsync fTopOp = fMaxOp - fEffOp;
7528d4a15800321b4013826ce35ad184898dba21vboxsync fFullOp1 = ((1 << (cbEffOp*16)) - 1);
7528d4a15800321b4013826ce35ad184898dba21vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync uAX = iDividend & fFullOp1; # full with unsigned
7528d4a15800321b4013826ce35ad184898dba21vboxsync uDX = uAX >> (cbEffOp*8);
7528d4a15800321b4013826ce35ad184898dba21vboxsync uAX &= fEffOp;
7528d4a15800321b4013826ce35ad184898dba21vboxsync uOp2Val = iDivisor & fEffOp;
7528d4a15800321b4013826ce35ad184898dba21vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync if cbEffOp < cbMaxOp:
7528d4a15800321b4013826ce35ad184898dba21vboxsync uAX |= randUxx(cbMaxOp * 8) & fTopOp;
7528d4a15800321b4013826ce35ad184898dba21vboxsync uDX |= randUxx(cbMaxOp * 8) & fTopOp;
7528d4a15800321b4013826ce35ad184898dba21vboxsync uOp2Val |= randUxx(cbMaxOp * 8) & fTopOp;
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' ; iDividend=%#x (%d) iDivisor=%#x (%d)\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync % ( iDividend & fFullOp1, iDividend, iDivisor & fEffOp, iDivisor,));
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[X86_GREG_xDX], uDX,));
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[X86_GREG_xAX], uAX,));
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2], uOp2Val,));
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iOp2],));
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[X86_GREG_xDX],));
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[X86_GREG_xAX],));
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' VBINSTST_TRAP_INSTR X86_XCPT_DE, 0, %-4s %s\n'
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync % (self.sInstr, oGen.gregNameBytes(iOp2, cbEffOp),));
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(X86_GREG_xAX, X86_GREG_xDX, iOp2),));
7528d4a15800321b4013826ce35ad184898dba21vboxsync return True;
7528d4a15800321b4013826ce35ad184898dba21vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync def generateOneDivideErrorTestGreg8Bit(self, oGen, cbEffOp, iOp2, iDividend, iDivisor):
7528d4a15800321b4013826ce35ad184898dba21vboxsync """ Generate code of one '[I]DIV AX,<GREG>' test that causes #DE (8-bit). """
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync if not oGen.oTarget.is64Bit() and iOp2 == 4: # Avoid AH.
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync iOp2 = 5;
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync cbMaxOp = oGen.oTarget.getMaxOpBytes();
7528d4a15800321b4013826ce35ad184898dba21vboxsync fMaxOp = UINT64_MAX if cbMaxOp == 8 else UINT32_MAX; assert cbMaxOp in [8, 4];
7528d4a15800321b4013826ce35ad184898dba21vboxsync iOp2X = (iOp2 & 3) if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2) else iOp2;
7528d4a15800321b4013826ce35ad184898dba21vboxsync assert iOp2X != X86_GREG_xAX;
7528d4a15800321b4013826ce35ad184898dba21vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync uAX = iDividend & UINT16_MAX; # full with unsigned
7528d4a15800321b4013826ce35ad184898dba21vboxsync uOp2Val = iDivisor & UINT8_MAX;
7528d4a15800321b4013826ce35ad184898dba21vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync uAX |= randUxx(cbMaxOp * 8) & (fMaxOp - UINT16_MAX);
7528d4a15800321b4013826ce35ad184898dba21vboxsync uOp2Val |= randUxx(cbMaxOp * 8) & (fMaxOp - UINT8_MAX);
7528d4a15800321b4013826ce35ad184898dba21vboxsync if iOp2X != iOp2:
7528d4a15800321b4013826ce35ad184898dba21vboxsync uOp2Val = rotateLeftUxx(cbMaxOp * 8, uOp2Val, 8);
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' ; iDividend=%#x (%d) iDivisor=%#x (%d)\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync % ( iDividend & UINT16_MAX, iDividend, iDivisor & UINT8_MAX, iDivisor,));
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[X86_GREG_xAX], uAX,));
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2X], uOp2Val,));
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iOp2X],));
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' push sAX\n');
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' VBINSTST_TRAP_INSTR X86_XCPT_DE, 0, %-4s %s\n'
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync % (self.sInstr, oGen.gregNameBytes(iOp2, cbEffOp),));
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(X86_GREG_xAX, iOp2X),));
7528d4a15800321b4013826ce35ad184898dba21vboxsync return;
7528d4a15800321b4013826ce35ad184898dba21vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync def generateDivideErrorTests(self, oGen):
7528d4a15800321b4013826ce35ad184898dba21vboxsync """ Generate divide error tests (raises X86_XCPT_DE). """
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write('%ifdef VBINSTST_CAN_DO_TRAPS\n');
7528d4a15800321b4013826ce35ad184898dba21vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync # We do one register variation here, assuming the standard test has got them covered.
7528d4a15800321b4013826ce35ad184898dba21vboxsync # Register tests
7528d4a15800321b4013826ce35ad184898dba21vboxsync if True:
7528d4a15800321b4013826ce35ad184898dba21vboxsync iOp2 = oGen.oTarget.randGRegNoSp();
7528d4a15800321b4013826ce35ad184898dba21vboxsync while iOp2 == X86_GREG_xAX or iOp2 == X86_GREG_xDX:
7528d4a15800321b4013826ce35ad184898dba21vboxsync iOp2 = oGen.oTarget.randGRegNoSp();
7528d4a15800321b4013826ce35ad184898dba21vboxsync
d9e8d25a9d654b882b82e4e33ca8b6f294a770f7vboxsync for cbEffOp in ( 8, 4, 2, 1 ):
7528d4a15800321b4013826ce35ad184898dba21vboxsync if cbEffOp > oGen.oTarget.getMaxOpBytes():
7528d4a15800321b4013826ce35ad184898dba21vboxsync continue;
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write('; cbEffOp=%u iOp2=%u\n' % (cbEffOp, iOp2,));
7528d4a15800321b4013826ce35ad184898dba21vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync for iDividend, iDivisor in self.generateInputsXcpt(cbEffOp, fLong = not oGen.isTiny()):
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.newSubTest();
7528d4a15800321b4013826ce35ad184898dba21vboxsync if cbEffOp > 1:
7528d4a15800321b4013826ce35ad184898dba21vboxsync self.generateOneDivideErrorTestGreg(oGen, cbEffOp, iOp2, iDividend, iDivisor);
7528d4a15800321b4013826ce35ad184898dba21vboxsync else:
7528d4a15800321b4013826ce35ad184898dba21vboxsync self.generateOneDivideErrorTestGreg8Bit(oGen, cbEffOp, iOp2, iDividend, iDivisor);
7528d4a15800321b4013826ce35ad184898dba21vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync oGen.write('%endif ; VBINSTST_CAN_DO_TRAPS\n');
7528d4a15800321b4013826ce35ad184898dba21vboxsync return True;
7528d4a15800321b4013826ce35ad184898dba21vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync def generateTest(self, oGen, sTestFnName):
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync oGen.write('VBINSTST_BEGINPROC %s\n' % (sTestFnName,));
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync #oGen.write(' int3\n');
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync
6adbde734d9d0bd2d870a3efa022b7f3fcc8b6f7vboxsync self.generateStandardTests(oGen);
7528d4a15800321b4013826ce35ad184898dba21vboxsync self.generateDivideErrorTests(oGen);
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync #oGen.write(' int3\n');
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync oGen.write(' ret\n');
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync oGen.write('VBINSTST_ENDPROC %s\n' % (sTestFnName,));
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync return True;
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsyncclass InstrTest_DaaDas(InstrTestBase):
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync """ Tests the DAA and DAS instructions. """
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync def __init__(self, fIsDas):
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync InstrTestBase.__init__(self, 'das' if fIsDas else 'daa');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync self.fIsDas = fIsDas;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync def isApplicable(self, oGen):
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync return not oGen.oTarget.is64Bit();
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync def generateTest(self, oGen, sTestFnName):
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync if self.fIsDas: from itgTableDas import g_aItgDasResults as aItgResults;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync else: from itgTableDaa import g_aItgDaaResults as aItgResults;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync cMax = len(aItgResults);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync if oGen.isTiny():
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync cMax = 64;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write('VBINSTST_BEGINPROC %s\n' % (sTestFnName,));
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' xor ebx, ebx\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write('.das_loop:\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync # Save the loop variable so we can load known values.
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' push ebx\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.newSubTestEx('ebx');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync # Push the results.
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' movzx eax, byte [.abAlResults + ebx]\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' or eax, %#x\n' % (oGen.au32Regs[X86_GREG_xAX] & ~0xff,));
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' push eax\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' movzx eax, byte [.aFlagsResults + ebx]\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' push eax\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync # Calc and push the inputs.
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' mov eax, ebx\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' shr eax, 2\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' and eax, 0ffh\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' or eax, %#x\n' % (oGen.au32Regs[X86_GREG_xAX] & ~0xff,));
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' push eax\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' pushfd\n')
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' and dword [xSP], ~(X86_EFL_CF | X86_EFL_AF)\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' mov al, bl\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' and al, 2\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' shl al, X86_EFL_AF_BIT - 1\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' or [xSP], al\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' mov al, bl\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' and al, X86_EFL_CF\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' or [xSP], al\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync # Load register values and do the test.
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' popfd\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' pop eax\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync if self.fIsDas:
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' das\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync else:
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' daa\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync # Verify the results.
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync fFlagsToCheck = X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_ZF;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needFlagsGRegChecker(fFlagsToCheck, X86_GREG_xAX),));
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync # Restore the loop variable and advance.
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' pop ebx\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' inc ebx\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' cmp ebx, %#x\n' % (cMax,));
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' jb .das_loop\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' ret\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write('.abAlResults:\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync for i in range(cMax):
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' db %#x\n' % (aItgResults[i][0],));
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write('.aFlagsResults:\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync for i in range(cMax):
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write(' db %#x\n' % (aItgResults[i][1],));
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oGen.write('VBINSTST_ENDPROC %s\n' % (sTestFnName,));
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync return True;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
0cd5b157d7c4708b8ad79e3acd474ac781dfbcf1vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync##
54ed927d658674ced4387afbd1877a27cb975a76vboxsync# Instruction Tests.
54ed927d658674ced4387afbd1877a27cb975a76vboxsync#
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncg_aoInstructionTests = [
c744a417746b736ef91efc38f5e4ee099293f141vboxsync InstrTest_Mov_Gv_Ev(),
2fd6ecdd81cabe2dae6f05dd8b5c3c584f03231bvboxsync InstrTest_MovSxD_Gv_Ev(),
54ed927d658674ced4387afbd1877a27cb975a76vboxsync InstrTest_DivIDiv(fIsIDiv = False),
d9e8d25a9d654b882b82e4e33ca8b6f294a770f7vboxsync InstrTest_DivIDiv(fIsIDiv = True),
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync InstrTest_DaaDas(fIsDas = False),
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync InstrTest_DaaDas(fIsDas = True),
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync];
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsyncclass InstructionTestGen(object): # pylint: disable=R0902
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Instruction Test Generator.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync ## @name Test size
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync ## @{
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync ksTestSize_Large = 'large';
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync ksTestSize_Medium = 'medium';
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync ksTestSize_Tiny = 'tiny';
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync ## @}
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync kasTestSizes = ( ksTestSize_Large, ksTestSize_Medium, ksTestSize_Tiny );
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ## The prefix for the checker functions.
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ksCheckerPrefix = 'Common_Check_'
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def __init__(self, oOptions):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.oOptions = oOptions;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.oTarget = g_dTargetEnvs[oOptions.sTargetEnv];
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync # Calculate the number of output files.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.cFiles = 1;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if len(g_aoInstructionTests) > self.oOptions.cInstrPerFile:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.cFiles = len(g_aoInstructionTests) / self.oOptions.cInstrPerFile;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if self.cFiles * self.oOptions.cInstrPerFile < len(g_aoInstructionTests):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.cFiles += 1;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync # Fix the known register values.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.au64Regs = randUxxList(64, 16);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.au32Regs = [(self.au64Regs[i] & UINT32_MAX) for i in range(8)];
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.au16Regs = [(self.au64Regs[i] & UINT16_MAX) for i in range(8)];
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync self.auRegValues = self.au64Regs if self.oTarget.is64Bit() else self.au32Regs;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync # Declare state variables used while generating.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.oFile = sys.stderr;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.iFile = -1;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.sFile = '';
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._dCheckFns = dict();
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._dMemSetupFns = dict();
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._d64BitConsts = dict();
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync # State variables used while generating test convenientely placed here (lazy bird)...
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.iModReg = 0;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.iModRm = 0;
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync self.iSibBaseReg = 0;
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync self.iSibIndexReg = 0;
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync self.iSibScale = 1;
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync if self.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny:
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._oModRegRange = range(2);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._oModRegRange8 = range(2);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.oModRmRange = range(2);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.cSibBasePerRun = 1;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._cSibIndexPerRun = 2;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.oSibScaleRange = range(1);
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync elif self.oOptions.sTestSize == InstructionTestGen.ksTestSize_Medium:
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._oModRegRange = range( 5 if self.oTarget.is64Bit() else 4);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._oModRegRange8 = range( 6 if self.oTarget.is64Bit() else 4);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.oModRmRange = range(5);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.cSibBasePerRun = 5;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._cSibIndexPerRun = 4
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.oSibScaleRange = range(2);
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync else:
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._oModRegRange = range(16 if self.oTarget.is64Bit() else 8);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._oModRegRange8 = range(20 if self.oTarget.is64Bit() else 8);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.oModRmRange = range(16 if self.oTarget.is64Bit() else 8);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.cSibBasePerRun = 8;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._cSibIndexPerRun = 9;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.oSibScaleRange = range(4);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.iSibIndexRange = 0;
be177d2edf33024ee98bf5a84a32615473ac9568vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync #
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync # Methods used by instruction tests.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync #
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def write(self, sText):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ Writes to the current output file. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return self.oFile.write(unicode(sText));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def writeln(self, sText):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """ Writes a line to the current output file. """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write(sText);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return self.write('\n');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def writeInstrBytes(self, abInstr):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Emits an instruction given as a sequence of bytes values.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write(' db %#04x' % (abInstr[0],));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync for i in range(1, len(abInstr)):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write(', %#04x' % (abInstr[i],));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return self.write('\n');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def newSubTest(self):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Indicates that a new subtest has started.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write(' mov dword [VBINSTST_NAME(g_uVBInsTstSubTestIndicator) xWrtRIP], __LINE__\n');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return True;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync def newSubTestEx(self, sIndicator):
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync """
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync Indicates that a new subtest has started.
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync """
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync self.write(' mov dword [VBINSTST_NAME(g_uVBInsTstSubTestIndicator) xWrtRIP], %s\n' % (sIndicator, ));
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync return True;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync def needGRegChecker(self, iReg1, iReg2 = None, iReg3 = None):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Records the need for a given register checker function, returning its label.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync if iReg2 is not None:
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync if iReg3 is not None:
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync sName = '%s_%s_%s' % (self.oTarget.asGRegs[iReg1], self.oTarget.asGRegs[iReg2], self.oTarget.asGRegs[iReg3],);
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync else:
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync sName = '%s_%s' % (self.oTarget.asGRegs[iReg1], self.oTarget.asGRegs[iReg2],);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync else:
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync sName = '%s' % (self.oTarget.asGRegs[iReg1],);
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync assert iReg3 is None;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync if sName in self._dCheckFns:
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._dCheckFns[sName] += 1;
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync else:
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._dCheckFns[sName] = 1;
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync return self.ksCheckerPrefix + sName;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync def needFlagsGRegChecker(self, fFlagsToCheck, iReg1, iReg2 = None, iReg3 = None):
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync """
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync Records the need for a given rFLAGS + register checker function, returning its label.
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync """
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync sWorkerName = self.needGRegChecker(iReg1, iReg2, iReg3);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync sName = 'eflags_%#x_%s' % (fFlagsToCheck, sWorkerName[len(self.ksCheckerPrefix):]);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync if sName in self._dCheckFns:
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync self._dCheckFns[sName] += 1;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync else:
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync self._dCheckFns[sName] = 1;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync return self.ksCheckerPrefix + sName;
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync def needGRegMemSetup(self, cAddrBits, cbEffOp, iBaseReg = None, offDisp = None, iIndexReg = None, iScale = 1):
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync """
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync Records the need for a given register checker function, returning its label.
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync """
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync assert cAddrBits in [64, 32, 16];
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync assert cbEffOp in [8, 4, 2, 1];
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync assert iScale in [1, 2, 4, 8];
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync sName = '%ubit_U%u' % (cAddrBits, cbEffOp * 8,);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync if iBaseReg is not None:
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync sName += '_%s' % (gregName(iBaseReg, cAddrBits),);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync sName += '_x%u' % (iScale,);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync if iIndexReg is not None:
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync sName += '_%s' % (gregName(iIndexReg, cAddrBits),);
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync if offDisp is not None:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync sName += '_%#010x' % (offDisp & UINT32_MAX, );
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync if sName in self._dMemSetupFns:
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._dMemSetupFns[sName] += 1;
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync else:
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._dMemSetupFns[sName] = 1;
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync return 'Common_MemSetup_' + sName;
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def need64BitConstant(self, uVal):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Records the need for a 64-bit constant, returning its label.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync These constants are pooled to attempt reduce the size of the whole thing.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync assert uVal >= 0 and uVal <= UINT64_MAX;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync if uVal in self._d64BitConsts:
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._d64BitConsts[uVal] += 1;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync else:
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self._d64BitConsts[uVal] = 1;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return 'g_u64Const_0x%016x' % (uVal, );
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync def pushConst(self, uResult):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Emits a push constant value, taking care of high values on 64-bit hosts.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync if self.oTarget.is64Bit() and uResult >= 0x80000000:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write(' push qword [%s wrt rip]\n' % (self.need64BitConstant(uResult),));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync else:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write(' push dword 0x%x\n' % (uResult,));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return True;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync def getDispForMod(self, iMod, cbAlignment = 1):
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync """
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync Get a set of address dispositions for a given addressing mode.
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync The alignment restriction is for SIB scaling.
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync """
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync assert cbAlignment in [1, 2, 4, 8];
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync if iMod == 0:
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync aoffDisp = [ None, ];
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync elif iMod == 1:
8541678784dbe432feebe6d9c1528525e1771397vboxsync aoffDisp = [ 127 & ~(cbAlignment - 1), -128 ];
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync elif iMod == 2:
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync aoffDisp = [ 2147483647 & ~(cbAlignment - 1), -2147483648 ];
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync else: assert False;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync return aoffDisp;
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync def getModRegRange(self, cbEffOp):
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync """
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync The Mod R/M register range varies with the effective operand size, for
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync 8-bit registers we have 4 more.
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync """
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync if cbEffOp == 1:
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync return self._oModRegRange8;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync return self._oModRegRange;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync def getSibIndexPerRun(self):
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync """
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync We vary the SIB index test range a little to try cover more operand
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync combinations and avoid repeating the same ones.
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync """
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.iSibIndexRange += 1;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.iSibIndexRange %= 3;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync if self.iSibIndexRange == 0:
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync return self._cSibIndexPerRun - 1;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync return self._cSibIndexPerRun;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync def isTiny(self):
7528d4a15800321b4013826ce35ad184898dba21vboxsync """ Checks if we're in tiny mode."""
7528d4a15800321b4013826ce35ad184898dba21vboxsync return self.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny;
7528d4a15800321b4013826ce35ad184898dba21vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync def isMedium(self):
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync """ Checks if we're in medium mode."""
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync return self.oOptions.sTestSize == InstructionTestGen.ksTestSize_Medium;
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync #
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync # Forwarding calls for oTarget to shorted typing and lessen the attacks
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync # on the right margin.
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync #
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync def gregNameBits(self, iReg, cBitsWide):
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync """ Target: Get the name of a general register for the given size (in bits). """
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync return self.oTarget.gregNameBits(iReg, cBitsWide);
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync def gregNameBytes(self, iReg, cbWide):
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync """ Target: Get the name of a general register for the given size (in bytes). """
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync return self.oTarget.gregNameBytes(iReg, cbWide);
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync def is64Bit(self):
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync """ Target: Is the target 64-bit? """
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync return self.oTarget.is64Bit();
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync
44f548822e604beb589f687f22c21b2b5f1ee7c6vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync #
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync # Internal machinery.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync #
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync def _randInitIndexes(self):
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync """
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync Initializes the Mod R/M and SIB state index with random numbers prior
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync to generating a test.
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync Note! As with all other randomness and variations we do, we cannot
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync test all combinations for each and every instruction so we try
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync get coverage over time.
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync """
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.iModReg = randU8();
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.iModRm = randU8();
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.iSibBaseReg = randU8();
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.iSibIndexReg = randU8();
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.iSibScale = 1 << (randU8() & 3);
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.iSibIndexRange = randU8();
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync return True;
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def _calcTestFunctionName(self, oInstrTest, iInstrTest):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Calc a test function name for the given instruction test.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync sName = 'TestInstr%03u_%s' % (iInstrTest, oInstrTest.sName);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return sName.replace(',', '_').replace(' ', '_').replace('%', '_');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def _generateFileHeader(self, ):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Writes the file header.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Raises exception on trouble.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('; $Id$\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ';; @file %s\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync '; Autogenerate by %s %s. DO NOT EDIT\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ';\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync '\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ';\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync '; Headers\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ';\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync '%%include "env-%s.mac"\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync % ( os.path.basename(self.sFile),
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync os.path.basename(__file__), __version__[11:-1],
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.oTarget.sName,
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ) );
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync # Target environment specific init stuff.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync #
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync # Global variables.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync #
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('\n\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ';\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync '; Globals\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ';\n');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('VBINSTST_BEGINDATA\n'
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync 'VBINSTST_GLOBALNAME_EX g_pvLow16Mem4K, data hidden\n'
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync ' dq 0\n'
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync 'VBINSTST_GLOBALNAME_EX g_pvLow32Mem4K, data hidden\n'
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync ' dq 0\n'
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync 'VBINSTST_GLOBALNAME_EX g_pvMem4K, data hidden\n'
270236340676d2385b27ea992e07fcb643bb78b6vboxsync ' dq 0\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync 'VBINSTST_GLOBALNAME_EX g_uVBInsTstSubTestIndicator, data hidden\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' dd 0\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync '%ifdef VBINSTST_CAN_DO_TRAPS\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync 'VBINSTST_TRAP_RECS_BEGIN\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync '%endif\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync 'VBINSTST_BEGINCODE\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync );
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('%ifdef RT_ARCH_AMD64\n');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync for i in range(len(g_asGRegs64)):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('g_u64KnownValue_%s: dq 0x%x\n' % (g_asGRegs64[i], self.au64Regs[i]));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('%endif\n\n')
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync #
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync # Common functions.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync #
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync # Loading common values.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('\n\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync 'VBINSTST_BEGINPROC Common_LoadKnownValues\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync '%ifdef RT_ARCH_AMD64\n');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync for i in range(len(g_asGRegs64NoSp)):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if g_asGRegs64NoSp[i]:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write(' mov %s, 0x%x\n' % (g_asGRegs64NoSp[i], self.au64Regs[i],));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('%else\n');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync for i in range(8):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if g_asGRegs32NoSp[i]:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write(' mov %s, 0x%x\n' % (g_asGRegs32NoSp[i], self.au32Regs[i],));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('%endif\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' ret\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync 'VBINSTST_ENDPROC Common_LoadKnownValues\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync '\n');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('VBINSTST_BEGINPROC Common_CheckKnownValues\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync '%ifdef RT_ARCH_AMD64\n');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync for i in range(len(g_asGRegs64NoSp)):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if g_asGRegs64NoSp[i]:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write(' cmp %s, [g_u64KnownValue_%s wrt rip]\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' je .ok_%u\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' push %u ; register number\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' push %s ; actual\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' push qword [g_u64KnownValue_%s wrt rip] ; expected\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' call VBINSTST_NAME(Common_BadValue)\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync '.ok_%u:\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync % ( g_asGRegs64NoSp[i], g_asGRegs64NoSp[i], i, i, g_asGRegs64NoSp[i], g_asGRegs64NoSp[i], i,));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('%else\n');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync for i in range(8):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if g_asGRegs32NoSp[i]:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write(' cmp %s, 0x%x\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' je .ok_%u\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' push %u ; register number\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' push %s ; actual\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' push dword 0x%x ; expected\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' call VBINSTST_NAME(Common_BadValue)\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync '.ok_%u:\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync % ( g_asGRegs32NoSp[i], self.au32Regs[i], i, i, g_asGRegs32NoSp[i], self.au32Regs[i], i,));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('%endif\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' ret\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync 'VBINSTST_ENDPROC Common_CheckKnownValues\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync '\n');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return True;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
54ed927d658674ced4387afbd1877a27cb975a76vboxsync def _generateMemSetupFunctions(self): # pylint: disable=R0915
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync """
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync Generates the memory setup functions.
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync """
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync cDefAddrBits = self.oTarget.getDefAddrBits();
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync for sName in self._dMemSetupFns:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync # Unpack it.
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync asParams = sName.split('_');
8541678784dbe432feebe6d9c1528525e1771397vboxsync cAddrBits = int(asParams[0][:-3]); assert asParams[0][-3:] == 'bit';
8541678784dbe432feebe6d9c1528525e1771397vboxsync cEffOpBits = int(asParams[1][1:]); assert asParams[1][0] == 'U';
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync if cAddrBits == 64: asAddrGRegs = g_asGRegs64;
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync elif cAddrBits == 32: asAddrGRegs = g_asGRegs32;
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync else: asAddrGRegs = g_asGRegs16;
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync i = 2;
8541678784dbe432feebe6d9c1528525e1771397vboxsync iBaseReg = None;
8541678784dbe432feebe6d9c1528525e1771397vboxsync sBaseReg = None;
8541678784dbe432feebe6d9c1528525e1771397vboxsync if i < len(asParams) and asParams[i] in asAddrGRegs:
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync sBaseReg = asParams[i];
8541678784dbe432feebe6d9c1528525e1771397vboxsync iBaseReg = asAddrGRegs.index(sBaseReg);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync i += 1
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync
8541678784dbe432feebe6d9c1528525e1771397vboxsync assert i < len(asParams); assert asParams[i][0] == 'x';
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync iScale = iScale = int(asParams[i][1:]); assert iScale in [1, 2, 4, 8], '%u %s' % (iScale, sName);
8541678784dbe432feebe6d9c1528525e1771397vboxsync i += 1;
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync sIndexReg = None;
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync iIndexReg = None;
8541678784dbe432feebe6d9c1528525e1771397vboxsync if i < len(asParams) and asParams[i] in asAddrGRegs:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync sIndexReg = asParams[i];
8541678784dbe432feebe6d9c1528525e1771397vboxsync iIndexReg = asAddrGRegs.index(sIndexReg);
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync i += 1;
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
8541678784dbe432feebe6d9c1528525e1771397vboxsync u32Disp = None;
8541678784dbe432feebe6d9c1528525e1771397vboxsync if i < len(asParams) and len(asParams[i]) == 10:
8541678784dbe432feebe6d9c1528525e1771397vboxsync u32Disp = long(asParams[i], 16);
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync i += 1;
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync assert i == len(asParams), 'i=%d len=%d len[i]=%d (%s)' % (i, len(asParams), len(asParams[i]), asParams[i],);
8541678784dbe432feebe6d9c1528525e1771397vboxsync assert iScale == 1 or iIndexReg is not None;
8541678784dbe432feebe6d9c1528525e1771397vboxsync
8541678784dbe432feebe6d9c1528525e1771397vboxsync # Find a temporary register.
8541678784dbe432feebe6d9c1528525e1771397vboxsync iTmpReg1 = X86_GREG_xCX;
8541678784dbe432feebe6d9c1528525e1771397vboxsync while iTmpReg1 in [iBaseReg, iIndexReg]:
8541678784dbe432feebe6d9c1528525e1771397vboxsync iTmpReg1 += 1;
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync # Prologue.
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync self.write('\n\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync '; cAddrBits=%s cEffOpBits=%s iBaseReg=%s u32Disp=%s iIndexReg=%s iScale=%s\n'
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync 'VBINSTST_BEGINPROC Common_MemSetup_%s\n'
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync ' MY_PUSH_FLAGS\n'
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync ' push %s\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync % ( cAddrBits, cEffOpBits, iBaseReg, u32Disp, iIndexReg, iScale,
8541678784dbe432feebe6d9c1528525e1771397vboxsync sName, self.oTarget.asGRegs[iTmpReg1], ));
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync # Figure out what to use.
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync if cEffOpBits == 64:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync sTmpReg1 = g_asGRegs64[iTmpReg1];
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync sDataVar = 'VBINSTST_NAME(g_u64Data)';
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync elif cEffOpBits == 32:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync sTmpReg1 = g_asGRegs32[iTmpReg1];
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync sDataVar = 'VBINSTST_NAME(g_u32Data)';
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync elif cEffOpBits == 16:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync sTmpReg1 = g_asGRegs16[iTmpReg1];
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync sDataVar = 'VBINSTST_NAME(g_u16Data)';
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync else:
8541678784dbe432feebe6d9c1528525e1771397vboxsync assert cEffOpBits == 8; assert iTmpReg1 < 4;
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync sTmpReg1 = g_asGRegs8Rex[iTmpReg1];
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync sDataVar = 'VBINSTST_NAME(g_u8Data)';
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
8541678784dbe432feebe6d9c1528525e1771397vboxsync # Special case: reg + reg * [2,4,8]
8541678784dbe432feebe6d9c1528525e1771397vboxsync if iBaseReg == iIndexReg and iBaseReg is not None and iScale != 1:
8541678784dbe432feebe6d9c1528525e1771397vboxsync iTmpReg2 = X86_GREG_xBP;
8541678784dbe432feebe6d9c1528525e1771397vboxsync while iTmpReg2 in [iBaseReg, iIndexReg, iTmpReg1]:
8541678784dbe432feebe6d9c1528525e1771397vboxsync iTmpReg2 += 1;
c744a417746b736ef91efc38f5e4ee099293f141vboxsync sTmpReg2 = self.gregNameBits(iTmpReg2, cAddrBits);
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' push sAX\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync ' push %s\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync ' push sDX\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync % (self.oTarget.asGRegs[iTmpReg2],));
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync if cAddrBits == 16:
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' mov %s, [VBINSTST_NAME(g_pvLow16Mem4K) xWrtRIP]\n' % (sTmpReg2,));
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync else:
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' mov %s, [VBINSTST_NAME(g_pvLow32Mem4K) xWrtRIP]\n' % (sTmpReg2,));
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' add %s, 0x200\n' % (sTmpReg2,));
c744a417746b736ef91efc38f5e4ee099293f141vboxsync self.write(' mov %s, %s\n' % (self.gregNameBits(X86_GREG_xAX, cAddrBits), sTmpReg2,));
8541678784dbe432feebe6d9c1528525e1771397vboxsync if u32Disp is not None:
c744a417746b736ef91efc38f5e4ee099293f141vboxsync self.write(' sub %s, %d\n'
c744a417746b736ef91efc38f5e4ee099293f141vboxsync % ( self.gregNameBits(X86_GREG_xAX, cAddrBits), convU32ToSigned(u32Disp), ));
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' xor edx, edx\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync '%if xCB == 2\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync ' push 0\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync '%endif\n');
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' push %u\n' % (iScale + 1,));
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' div %s [xSP]\n' % ('qword' if cAddrBits == 64 else 'dword',));
c744a417746b736ef91efc38f5e4ee099293f141vboxsync self.write(' sub %s, %s\n' % (sTmpReg2, self.gregNameBits(X86_GREG_xDX, cAddrBits),));
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' pop sDX\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync ' pop sDX\n'); # sTmpReg2 is eff address; sAX is sIndexReg value.
8541678784dbe432feebe6d9c1528525e1771397vboxsync # Note! sTmpReg1 can be xDX and that's no problem now.
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' mov %s, [xSP + sCB*3 + MY_PUSH_FLAGS_SIZE + xCB]\n' % (sTmpReg1,));
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' mov [%s], %s\n' % (sTmpReg2, sTmpReg1,)); # Value in place.
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' pop %s\n' % (self.oTarget.asGRegs[iTmpReg2],));
8541678784dbe432feebe6d9c1528525e1771397vboxsync if iBaseReg == X86_GREG_xAX:
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' pop %s\n' % (self.oTarget.asGRegs[iTmpReg1],));
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync else:
c744a417746b736ef91efc38f5e4ee099293f141vboxsync self.write(' mov %s, %s\n' % (sBaseReg, self.gregNameBits(X86_GREG_xAX, cAddrBits),));
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' pop sAX\n');
8541678784dbe432feebe6d9c1528525e1771397vboxsync
8541678784dbe432feebe6d9c1528525e1771397vboxsync else:
8541678784dbe432feebe6d9c1528525e1771397vboxsync # Load the value and mem address, storing the value there.
8541678784dbe432feebe6d9c1528525e1771397vboxsync # Note! ASSUMES that the scale and disposition works fine together.
8541678784dbe432feebe6d9c1528525e1771397vboxsync sAddrReg = sBaseReg if sBaseReg is not None else sIndexReg;
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' mov %s, [xSP + sCB + MY_PUSH_FLAGS_SIZE + xCB]\n' % (sTmpReg1,));
8541678784dbe432feebe6d9c1528525e1771397vboxsync if cAddrBits >= cDefAddrBits:
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' mov [%s xWrtRIP], %s\n' % (sDataVar, sTmpReg1,));
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' lea %s, [%s xWrtRIP]\n' % (sAddrReg, sDataVar,));
8541678784dbe432feebe6d9c1528525e1771397vboxsync else:
8541678784dbe432feebe6d9c1528525e1771397vboxsync if cAddrBits == 16:
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' mov %s, [VBINSTST_NAME(g_pvLow16Mem4K) xWrtRIP]\n' % (sAddrReg,));
8541678784dbe432feebe6d9c1528525e1771397vboxsync else:
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' mov %s, [VBINSTST_NAME(g_pvLow32Mem4K) xWrtRIP]\n' % (sAddrReg,));
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' add %s, %s\n' % (sAddrReg, (randU16() << cEffOpBits) & 0xfff, ));
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' mov [%s], %s\n' % (sAddrReg, sTmpReg1, ));
8541678784dbe432feebe6d9c1528525e1771397vboxsync
8541678784dbe432feebe6d9c1528525e1771397vboxsync # Adjust for disposition and scaling.
8541678784dbe432feebe6d9c1528525e1771397vboxsync if u32Disp is not None:
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' sub %s, %d\n' % ( sAddrReg, convU32ToSigned(u32Disp), ));
8541678784dbe432feebe6d9c1528525e1771397vboxsync if iIndexReg is not None:
8541678784dbe432feebe6d9c1528525e1771397vboxsync if iBaseReg == iIndexReg:
8541678784dbe432feebe6d9c1528525e1771397vboxsync assert iScale == 1;
8541678784dbe432feebe6d9c1528525e1771397vboxsync assert u32Disp is None or (u32Disp & 1) == 0;
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' shr %s, 1\n' % (sIndexReg,));
8541678784dbe432feebe6d9c1528525e1771397vboxsync elif sBaseReg is not None:
8541678784dbe432feebe6d9c1528525e1771397vboxsync uIdxRegVal = randUxx(cAddrBits);
8541678784dbe432feebe6d9c1528525e1771397vboxsync if cAddrBits == 64:
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' mov %s, %u\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync ' sub %s, %s\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync ' mov %s, %u\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync % ( sIndexReg, (uIdxRegVal * iScale) & UINT64_MAX,
8541678784dbe432feebe6d9c1528525e1771397vboxsync sBaseReg, sIndexReg,
8541678784dbe432feebe6d9c1528525e1771397vboxsync sIndexReg, uIdxRegVal, ));
8541678784dbe432feebe6d9c1528525e1771397vboxsync else:
8541678784dbe432feebe6d9c1528525e1771397vboxsync assert cAddrBits == 32;
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' mov %s, %u\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync ' sub %s, %#06x\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync % ( sIndexReg, uIdxRegVal, sBaseReg, (uIdxRegVal * iScale) & UINT32_MAX, ));
8541678784dbe432feebe6d9c1528525e1771397vboxsync elif iScale == 2:
8541678784dbe432feebe6d9c1528525e1771397vboxsync assert u32Disp is None or (u32Disp & 1) == 0;
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' shr %s, 1\n' % (sIndexReg,));
8541678784dbe432feebe6d9c1528525e1771397vboxsync elif iScale == 4:
8541678784dbe432feebe6d9c1528525e1771397vboxsync assert u32Disp is None or (u32Disp & 3) == 0;
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' shr %s, 2\n' % (sIndexReg,));
8541678784dbe432feebe6d9c1528525e1771397vboxsync elif iScale == 8:
8541678784dbe432feebe6d9c1528525e1771397vboxsync assert u32Disp is None or (u32Disp & 7) == 0;
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' shr %s, 3\n' % (sIndexReg,));
8541678784dbe432feebe6d9c1528525e1771397vboxsync else:
8541678784dbe432feebe6d9c1528525e1771397vboxsync assert iScale == 1;
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync # Set upper bits that's supposed to be unused.
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync if cDefAddrBits > cAddrBits or cAddrBits == 16:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync if cDefAddrBits == 64:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync assert cAddrBits == 32;
8541678784dbe432feebe6d9c1528525e1771397vboxsync if iBaseReg is not None:
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.write(' mov %s, %#018x\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync ' or %s, %s\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync % ( g_asGRegs64[iTmpReg1], randU64() & 0xffffffff00000000,
8541678784dbe432feebe6d9c1528525e1771397vboxsync g_asGRegs64[iBaseReg], g_asGRegs64[iTmpReg1],));
8541678784dbe432feebe6d9c1528525e1771397vboxsync if iIndexReg is not None and iIndexReg != iBaseReg:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync self.write(' mov %s, %#018x\n'
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync ' or %s, %s\n'
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync % ( g_asGRegs64[iTmpReg1], randU64() & 0xffffffff00000000,
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync g_asGRegs64[iIndexReg], g_asGRegs64[iTmpReg1],));
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync else:
8541678784dbe432feebe6d9c1528525e1771397vboxsync assert cDefAddrBits == 32; assert cAddrBits == 16; assert iIndexReg is None;
8541678784dbe432feebe6d9c1528525e1771397vboxsync if iBaseReg is not None:
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync self.write(' or %s, %#010x\n'
8541678784dbe432feebe6d9c1528525e1771397vboxsync % ( g_asGRegs32[iBaseReg], randU32() & 0xffff0000, ));
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync # Epilogue.
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync self.write(' pop %s\n'
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync ' MY_POP_FLAGS\n'
bec4d1c0274e4712fe01426313aab120b5ad1c17vboxsync ' ret sCB\n'
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync 'VBINSTST_ENDPROC Common_MemSetup_%s\n'
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync % ( self.oTarget.asGRegs[iTmpReg1], sName,));
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def _generateFileFooter(self):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Generates file footer.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
7528d4a15800321b4013826ce35ad184898dba21vboxsync # Terminate the trap records.
7528d4a15800321b4013826ce35ad184898dba21vboxsync self.write('\n\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync ';\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync '; Terminate the trap records\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync ';\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync 'VBINSTST_BEGINDATA\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync '%ifdef VBINSTST_CAN_DO_TRAPS\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync 'VBINSTST_TRAP_RECS_END\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync '%endif\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync 'VBINSTST_BEGINCODE\n');
7528d4a15800321b4013826ce35ad184898dba21vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync # Register checking functions.
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync for sName in self._dCheckFns:
d17bffd306255c509aa98e8118e9a5456ee2138evboxsync asRegs = sName.split('_');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync sPushSize = 'dword';
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync # Do we check eflags first.
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync if asRegs[0] == 'eflags':
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync asRegs.pop(0);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync sFlagsToCheck = asRegs.pop(0);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync self.write('\n\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync '; Check flags and then defers to the register-only checker\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync '; To save space, the callee cleans up the stack.'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync '; Ref count: %u\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync 'VBINSTST_BEGINPROC %s%s\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' MY_PUSH_FLAGS\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' push sAX\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' mov sAX, [xSP + sCB]\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' and sAX, %s\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' cmp sAX, [xSP + xCB + sCB*2]\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' je .equal\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync % ( self._dCheckFns[sName], self.ksCheckerPrefix, sName,
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync sFlagsToCheck,));
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync self.write(' push dword 0xef ; register number\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' push sAX ; actual\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' mov sAX, [xSP + xCB + sCB*4]\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' push sAX ; expected\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' call VBINSTST_NAME(Common_BadValue)\n');
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync self.write('.equal:\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' mov xAX, [xSP + sCB*2]\n' # Remove the expected eflags value from the stack frame.
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' mov [xSP + sCB*2 + xCB + sCB - xCB], xAX\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' pop sAX\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' MY_POP_FLAGS\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' lea xSP, [xSP + sCB]\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' jmp VBINSTST_NAME(Common_Check_%s)\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync 'VBINSTST_ENDPROC %s%s\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync % ( '_'.join(asRegs),
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync self.ksCheckerPrefix, sName,) );
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync else:
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync # Prologue
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync self.write('\n\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync '; Checks 1 or more register values, expected values pushed on the stack.\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync '; To save space, the callee cleans up the stack.'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync '; Ref count: %u\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync 'VBINSTST_BEGINPROC %s%s\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' MY_PUSH_FLAGS\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync % ( self._dCheckFns[sName], self.ksCheckerPrefix, sName, ) );
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync # Register checks.
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync for i in range(len(asRegs)):
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync sReg = asRegs[i];
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync iReg = self.oTarget.asGRegs.index(sReg);
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync if i == asRegs.index(sReg): # Only check once, i.e. input = output reg.
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync self.write(' cmp %s, [xSP + MY_PUSH_FLAGS_SIZE + xCB + sCB * %u]\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' je .equal%u\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' push %s %u ; register number\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' push %s ; actual\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' mov %s, [xSP + sCB*2 + MY_PUSH_FLAGS_SIZE + xCB + sCB * %u]\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' push %s ; expected\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' call VBINSTST_NAME(Common_BadValue)\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync '.equal%u:\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync % ( sReg, i, i, sPushSize, iReg, sReg, sReg, i, sReg, i, ) );
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync # Restore known register values and check the other registers.
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync for sReg in asRegs:
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync if self.oTarget.is64Bit():
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync self.write(' mov %s, [g_u64KnownValue_%s wrt rip]\n' % (sReg, sReg,));
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync else:
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync iReg = self.oTarget.asGRegs.index(sReg)
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync self.write(' mov %s, 0x%x\n' % (sReg, self.au32Regs[iReg],));
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync self.write(' MY_POP_FLAGS\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' call VBINSTST_NAME(Common_CheckKnownValues)\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ' ret sCB*%u\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync 'VBINSTST_ENDPROC %s%s\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync % (len(asRegs), self.ksCheckerPrefix, sName,));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync # memory setup functions
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync self._generateMemSetupFunctions();
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync # 64-bit constants.
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync if len(self._d64BitConsts) > 0:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('\n\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ';\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync '; 64-bit constants\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ';\n');
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync for uVal in self._d64BitConsts:
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync self.write('g_u64Const_0x%016x: dq 0x%016x ; Ref count: %d\n' % (uVal, uVal, self._d64BitConsts[uVal], ) );
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return True;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def _generateTests(self):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Generate the test cases.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync for self.iFile in range(self.cFiles):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if self.cFiles == 1:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.sFile = '%s.asm' % (self.oOptions.sOutputBase,)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync else:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.sFile = '%s-%u.asm' % (self.oOptions.sOutputBase, self.iFile)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.oFile = sys.stdout;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if self.oOptions.sOutputBase != '-':
8541678784dbe432feebe6d9c1528525e1771397vboxsync self.oFile = io.open(self.sFile, 'w', buffering = 65536, encoding = 'utf-8');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self._generateFileHeader();
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync # Calc the range.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync iInstrTestStart = self.iFile * self.oOptions.cInstrPerFile;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync iInstrTestEnd = iInstrTestStart + self.oOptions.cInstrPerFile;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if iInstrTestEnd > len(g_aoInstructionTests):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync iInstrTestEnd = len(g_aoInstructionTests);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync # Generate the instruction tests.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync for iInstrTest in range(iInstrTestStart, iInstrTestEnd):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync oInstrTest = g_aoInstructionTests[iInstrTest];
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync if oInstrTest.isApplicable(self):
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync self.write('\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync '\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ';\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync '; %s\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync ';\n'
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync % (oInstrTest.sName,));
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync self._randInitIndexes();
2532c528b686eb371278fc8d8b26b1fdba7960b0vboxsync oInstrTest.generateTest(self, self._calcTestFunctionName(oInstrTest, iInstrTest));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync # Generate the main function.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('\n\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync 'VBINSTST_BEGINPROC TestInstrMain\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' MY_PUSH_ALL\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' sub xSP, 40h\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync '%ifdef VBINSTST_CAN_DO_TRAPS\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync ' VBINSTST_TRAP_RECS_INSTALL\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync '%endif\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync '\n');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync for iInstrTest in range(iInstrTestStart, iInstrTestEnd):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync oInstrTest = g_aoInstructionTests[iInstrTest];
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync if oInstrTest.isApplicable(self):
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync self.write('%%ifdef ASM_CALL64_GCC\n'
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync ' lea rdi, [.szInstr%03u wrt rip]\n'
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync '%%elifdef ASM_CALL64_MSC\n'
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync ' lea rcx, [.szInstr%03u wrt rip]\n'
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync '%%else\n'
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync ' mov xAX, .szInstr%03u\n'
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync ' mov [xSP], xAX\n'
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync '%%endif\n'
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync ' VBINSTST_CALL_FN_SUB_TEST\n'
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync ' call VBINSTST_NAME(%s)\n'
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync % ( iInstrTest, iInstrTest, iInstrTest, self._calcTestFunctionName(oInstrTest, iInstrTest)));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync '%ifdef VBINSTST_CAN_DO_TRAPS\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync ' VBINSTST_TRAP_RECS_UNINSTALL\n'
7528d4a15800321b4013826ce35ad184898dba21vboxsync '%endif\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' add xSP, 40h\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' MY_POP_ALL\n'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ' ret\n\n');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync for iInstrTest in range(iInstrTestStart, iInstrTestEnd):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('.szInstr%03u: db \'%s\', 0\n' % (iInstrTest, g_aoInstructionTests[iInstrTest].sName,));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.write('VBINSTST_ENDPROC TestInstrMain\n\n');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self._generateFileFooter();
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if self.oOptions.sOutputBase != '-':
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.oFile.close();
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.oFile = None;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync self.sFile = '';
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return RTEXITCODE_SUCCESS;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def _runMakefileMode(self):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Generate a list of output files on standard output.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if self.cFiles == 1:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync print('%s.asm' % (self.oOptions.sOutputBase,));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync else:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync print(' '.join('%s-%s.asm' % (self.oOptions.sOutputBase, i) for i in range(self.cFiles)));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return RTEXITCODE_SUCCESS;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def run(self):
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Generates the tests or whatever is required.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if self.oOptions.fMakefileMode:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return self._runMakefileMode();
ca935c7716bd7361d80c27c870d108a8fec80b79vboxsync sys.stderr.write('InstructionTestGen.py: Seed = %s\n' % (g_iMyRandSeed,));
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return self._generateTests();
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync @staticmethod
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync def main():
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Main function a la C/C++. Returns exit code.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync """
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync #
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync # Parse the command line.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync #
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync oParser = OptionParser(version = __version__[11:-1].strip());
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync oParser.add_option('--makefile-mode', dest = 'fMakefileMode', action = 'store_true', default = False,
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync help = 'Special mode for use to output a list of output files for the benefit of '
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync 'the make program (kmk).');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync oParser.add_option('--split', dest = 'cInstrPerFile', metavar = '<instr-per-file>', type = 'int', default = 9999999,
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync help = 'Number of instruction to test per output file.');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync oParser.add_option('--output-base', dest = 'sOutputBase', metavar = '<file>', default = None,
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync help = 'The output file base name, no suffix please. Required.');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync oParser.add_option('--target', dest = 'sTargetEnv', metavar = '<target>',
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync default = 'iprt-r3-32',
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync choices = g_dTargetEnvs.keys(),
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync help = 'The target environment. Choices: %s'
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync % (', '.join(sorted(g_dTargetEnvs.keys())),));
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync oParser.add_option('--test-size', dest = 'sTestSize', default = InstructionTestGen.ksTestSize_Medium,
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync choices = InstructionTestGen.kasTestSizes,
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync help = 'Selects the test size.');
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync (oOptions, asArgs) = oParser.parse_args();
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if len(asArgs) > 0:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync oParser.print_help();
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return RTEXITCODE_SYNTAX
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if oOptions.sOutputBase is None:
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync print('syntax error: Missing required option --output-base.', file = sys.stderr);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return RTEXITCODE_SYNTAX
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync #
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync # Instantiate the program class and run it.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync #
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync oProgram = InstructionTestGen(oOptions);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return oProgram.run();
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncif __name__ == '__main__':
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync sys.exit(InstructionTestGen.main());
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync