tstDisasm-1.cpp revision 520c825ff8270d50597dc471316acb6ee63275e2
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync/* $Id$ */
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync/** @file
b736c553dbde2c3b2533c93c57d9b7f07714371cvboxsync * VBox disassembler - Test application
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync */
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2006-2012 Oracle Corporation
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync *
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync * available from http://www.virtualbox.org. This file is free software;
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync * you can redistribute it and/or modify it under the terms of the GNU
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync * General Public License (GPL) as published by the Free Software
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync */
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync/*******************************************************************************
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync* Header Files *
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync*******************************************************************************/
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync#include <VBox/dis.h>
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync#include <iprt/test.h>
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync#include <iprt/ctype.h>
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync#include <iprt/string.h>
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync#include <iprt/err.h>
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync#include <iprt/time.h>
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsyncDECLASM(int) TestProc32(void);
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsyncDECLASM(int) TestProc32_EndProc(void);
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync#ifndef RT_OS_OS2
d544fe535c163a24bf8cd831b39264da292b8adfvboxsyncDECLASM(int) TestProc64(void);
d544fe535c163a24bf8cd831b39264da292b8adfvboxsyncDECLASM(int) TestProc64_EndProc(void);
d544fe535c163a24bf8cd831b39264da292b8adfvboxsync#endif
d544fe535c163a24bf8cd831b39264da292b8adfvboxsync//uint8_t aCode16[] = { 0x66, 0x67, 0x89, 0x07 };
d544fe535c163a24bf8cd831b39264da292b8adfvboxsync
97566036db1dc1dba46ed21be4e147c728fd1027vboxsyncstatic void testDisas(const char *pszSub, uint8_t const *pabInstrs, uintptr_t uEndPtr, DISCPUMODE enmDisCpuMode)
174e1d5b2d6b6d7c92271d7fcc070c6d0cc92312vboxsync{
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync RTTestISub(pszSub);
d544fe535c163a24bf8cd831b39264da292b8adfvboxsync size_t const cbInstrs = uEndPtr - (uintptr_t)pabInstrs;
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync for (size_t off = 0; off < cbInstrs;)
97566036db1dc1dba46ed21be4e147c728fd1027vboxsync {
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync uint32_t const cErrBefore = RTTestIErrorCount();
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync uint32_t cb = 1;
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync DISSTATE Dis;
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync char szOutput[256] = {0};
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync int rc = DISInstrToStr(&pabInstrs[off], enmDisCpuMode, &Dis, &cb, szOutput, sizeof(szOutput));
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync RTTESTI_CHECK(cb == Dis.cbInstr);
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync RTTESTI_CHECK(cb > 0);
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync RTTESTI_CHECK(cb <= 16);
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync RTStrStripR(szOutput);
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync RTTESTI_CHECK(szOutput[0]);
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync if (szOutput[0])
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync {
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync char *pszBytes = strchr(szOutput, '[');
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync RTTESTI_CHECK(pszBytes);
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync if (pszBytes)
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync {
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync RTTESTI_CHECK(pszBytes[-1] == ' ');
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync RTTESTI_CHECK(RT_C_IS_XDIGIT(pszBytes[1]));
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync RTTESTI_CHECK(pszBytes[cb * 3] == ']');
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync RTTESTI_CHECK(pszBytes[cb * 3 + 1] == ' ');
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync size_t cch = strlen(szOutput);
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync RTTESTI_CHECK(szOutput[cch - 1] != ',');
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync }
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync }
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync if (cErrBefore != RTTestIErrorCount())
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync RTTestIFailureDetails("rc=%Rrc, off=%#x (%u) cbInstr=%u enmDisCpuMode=%d\n",
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync rc, off, Dis.cbInstr, enmDisCpuMode);
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync RTTestIPrintf(RTTESTLVL_ALWAYS, "%s\n", szOutput);
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync off += cb;
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync }
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync}
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsyncstatic DECLCALLBACK(int) testReadBytes(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync{
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync memcpy(&pDis->abInstr[offInstr], (void *)((uintptr_t)pDis->uInstrAddr + offInstr), cbMaxRead);
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync pDis->cbCachedInstr = offInstr + cbMaxRead;
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync return VINF_SUCCESS;
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync}
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsyncstatic void testPerformance(const char *pszSub, uint8_t const *pabInstrs, uintptr_t uEndPtr, DISCPUMODE enmDisCpuMode)
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync{
9474d83dcac691984017f8255821b95ec7642804vboxsync RTTestISubF("Performance - %s", pszSub);
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync size_t const cbInstrs = uEndPtr - (uintptr_t)pabInstrs;
9474d83dcac691984017f8255821b95ec7642804vboxsync uint64_t cInstrs = 0;
9474d83dcac691984017f8255821b95ec7642804vboxsync uint64_t nsStart = RTTimeNanoTS();
b379286f0d2c8d82f5a575eb907c7476aa6ae84bvboxsync for (uint32_t i = 0; i < _512K; i++) /* the samples are way to small. :-) */
b379286f0d2c8d82f5a575eb907c7476aa6ae84bvboxsync {
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync for (size_t off = 0; off < cbInstrs; cInstrs++)
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync {
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync uint32_t cb = 1;
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync DISSTATE Dis;
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync DISInstrWithReader((uintptr_t)&pabInstrs[off], enmDisCpuMode, testReadBytes, NULL, &Dis, &cb);
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync off += cb;
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync }
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync }
9cabb72c6d6feb65e839ce50765643b98bb9a301vboxsync uint64_t cNsElapsed = RTTimeNanoTS() - nsStart;
9474d83dcac691984017f8255821b95ec7642804vboxsync
97566036db1dc1dba46ed21be4e147c728fd1027vboxsync RTTestIValueF(cNsElapsed, RTTESTUNIT_NS, "%s-Total", pszSub);
9474d83dcac691984017f8255821b95ec7642804vboxsync RTTestIValueF(cNsElapsed / cInstrs, RTTESTUNIT_NS_PER_CALL, "%s-per-instruction", pszSub);
9474d83dcac691984017f8255821b95ec7642804vboxsync}
9474d83dcac691984017f8255821b95ec7642804vboxsync
9474d83dcac691984017f8255821b95ec7642804vboxsync
9474d83dcac691984017f8255821b95ec7642804vboxsyncint main(int argc, char **argv)
9474d83dcac691984017f8255821b95ec7642804vboxsync{
9474d83dcac691984017f8255821b95ec7642804vboxsync RTTEST hTest;
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync RTEXITCODE rcExit = RTTestInitAndCreate("tstDisasm", &hTest);
9474d83dcac691984017f8255821b95ec7642804vboxsync if (rcExit)
b379286f0d2c8d82f5a575eb907c7476aa6ae84bvboxsync return rcExit;
b379286f0d2c8d82f5a575eb907c7476aa6ae84bvboxsync RTTestBanner(hTest);
9474d83dcac691984017f8255821b95ec7642804vboxsync
9474d83dcac691984017f8255821b95ec7642804vboxsync static const struct
9474d83dcac691984017f8255821b95ec7642804vboxsync {
9474d83dcac691984017f8255821b95ec7642804vboxsync const char *pszDesc;
9474d83dcac691984017f8255821b95ec7642804vboxsync uint8_t const *pbStart;
9474d83dcac691984017f8255821b95ec7642804vboxsync uintptr_t uEndPtr;
9474d83dcac691984017f8255821b95ec7642804vboxsync DISCPUMODE enmCpuMode;
9474d83dcac691984017f8255821b95ec7642804vboxsync } aSnippets[] =
9474d83dcac691984017f8255821b95ec7642804vboxsync {
9474d83dcac691984017f8255821b95ec7642804vboxsync { "32-bit", (uint8_t const *)(uintptr_t)TestProc32, (uintptr_t)&TestProc32_EndProc, DISCPUMODE_32BIT },
97566036db1dc1dba46ed21be4e147c728fd1027vboxsync { "64-bit", (uint8_t const *)(uintptr_t)TestProc64, (uintptr_t)&TestProc64_EndProc, DISCPUMODE_64BIT },
97566036db1dc1dba46ed21be4e147c728fd1027vboxsync };
666e2c9af6a34f7a05d8069a11194756312f5be6vboxsync
666e2c9af6a34f7a05d8069a11194756312f5be6vboxsync for (unsigned i = 0; i < RT_ELEMENTS(aSnippets); i++)
b379286f0d2c8d82f5a575eb907c7476aa6ae84bvboxsync testDisas(aSnippets[i].pszDesc, aSnippets[i].pbStart, aSnippets[i].uEndPtr, aSnippets[i].enmCpuMode);
b379286f0d2c8d82f5a575eb907c7476aa6ae84bvboxsync
97566036db1dc1dba46ed21be4e147c728fd1027vboxsync if (RTTestIErrorCount() == 0)
97566036db1dc1dba46ed21be4e147c728fd1027vboxsync {
97566036db1dc1dba46ed21be4e147c728fd1027vboxsync for (unsigned i = 0; i < RT_ELEMENTS(aSnippets); i++)
97566036db1dc1dba46ed21be4e147c728fd1027vboxsync testPerformance(aSnippets[i].pszDesc, aSnippets[i].pbStart, aSnippets[i].uEndPtr, aSnippets[i].enmCpuMode);
97566036db1dc1dba46ed21be4e147c728fd1027vboxsync }
97566036db1dc1dba46ed21be4e147c728fd1027vboxsync
97566036db1dc1dba46ed21be4e147c728fd1027vboxsync return RTTestSummaryAndDestroy(hTest);
97566036db1dc1dba46ed21be4e147c728fd1027vboxsync}
97566036db1dc1dba46ed21be4e147c728fd1027vboxsync
97566036db1dc1dba46ed21be4e147c728fd1027vboxsync