ghidra/Ghidra/Extensions/SleighDevTools/pcodetest/c_src/pcode_test.c

300 lines
8.0 KiB
C

/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pcode_test.h"
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
NOINLINE i4 breakOnPass(void);
NOINLINE i4 breakOnError(void);
void nosprintf5() { } /* sprintf5 function was removed, but java is still looking for it. */
FunctionInfo mainFunctionInfoTable[] = {
#ifdef HAS_FLOAT
{"assertF4", (testFuncPtr) assertF4, 0},
#endif
#ifdef HAS_DOUBLE
{"assertF8", (testFuncPtr) assertF8, 0},
#endif
{"assertI1", (testFuncPtr) assertI1, 0},
{"assertI2", (testFuncPtr) assertI2, 0},
{"assertI4", (testFuncPtr) assertI4, 0},
#ifdef HAS_LONGLONG
{"assertI8", (testFuncPtr) assertI8, 0},
#endif
{"assertU1", (testFuncPtr) assertU1, 0},
{"assertU2", (testFuncPtr) assertU2, 0},
{"assertU4", (testFuncPtr) assertU4, 0},
#ifdef HAS_LONGLONG
{"assertU8", (testFuncPtr) assertU8, 0},
#endif
{"breakOnDone", (testFuncPtr) breakOnDone, 0},
{"breakOnError", (testFuncPtr) breakOnError, 0},
{"breakOnPass", (testFuncPtr) breakOnPass, 0},
{"breakOnSubDone", (testFuncPtr) breakOnSubDone, 0},
{"noteTestMain", (testFuncPtr) noteTestMain, 0},
{0, 0, 0},
};
static TestInfo MainInfo = {
{'A', 'b', 'C', 'd', 'E', 'F', 'g', 'H'},
sizeof(i1 *), /* ptrSz */
0x01020304, /* byteOrder */
breakOnPass, /* onPass function ptr */
breakOnError, /* onError function ptr */
breakOnDone, /* onDone function ptr */
0, /* numpass */
0, /* numfail */
0, /* lastTestPos */
0, /* lastErrorLine */
"none", /* lastErrorFile */
"none", /* lasFunc */
nosprintf5, /* sprintf5 function ptr */
0, /* sprintf5 buffer */
0, /* sprintf5 enabled flag */
__VERSION__, /* compiler version */
TOSTRING(NAME), /* value of name symbol */
TOSTRING(THECCFLAGS), /* value of THECCFLAGS symbol */
"BUILDDATE: " __DATE__, /* build date */
mainFunctionInfoTable, /* function table */
};
NOINLINE void TestInfo_reset(void)
{
MainInfo.numpass = 0;
MainInfo.numfail = 0;
MainInfo.lastTestPos = 0;
MainInfo.lastErrorFile = "none";
MainInfo.lastFunc = "none";
}
/* Injected call when a test is done */
NOINLINE i4 breakOnDone(const char *file, int line, const char *func)
{
return 0;
}
/* Called from assert when a test passes */
NOINLINE i4 breakOnPass(void)
{
MainInfo.numpass++;
return 0;
}
/* Called from assert when a test fails */
NOINLINE i4 breakOnError(void)
{
MainInfo.numfail++;
return 0;
}
/* Injected call when a subtest is done */
NOINLINE i4 breakOnSubDone(const char *file, int line, const char *func)
{
return 0;
}
/* Injected at start of a test to record file position */
void noteTestMain(const char *file, int line, const char *func)
{
MainInfo.lastFunc = (char *) func;
MainInfo.lastTestPos = line;
}
#if defined(BUILD_EXE)
#define DO_PRINT_INT(ok) print_int(file, line, MainInfo.lastFunc, expected, val, (ok) ? "OK" : "ERROR");
#define DO_PRINT_LONG(ok) print_long(file, line, MainInfo.lastFunc, expected, val, (ok) ? "OK" : "ERROR");
/* for ARM platform, and possibly others, printf does not properly handle long long args */
#define DO_PRINT_LONGLONG(ok) print_long(file, line, MainInfo.lastFunc, (long) expected, (long) val, (ok) ? "OK" : "ERROR");
#define DO_PRINT_UINT(ok) print_uint(file, line, MainInfo.lastFunc, expected, val, (ok) ? "OK" : "ERROR");
#define DO_PRINT_ULONG(ok) print_ulong(file, line, MainInfo.lastFunc, expected, val, (ok) ? "OK" : "ERROR");
#define DO_PRINT_ULONGLONG(ok) print_ulong(file, line, MainInfo.lastFunc, (long) expected, (long) val, (ok) ? "OK" : "ERROR");
#define DO_PRINT_FLOAT(ok) print_float(file, line, MainInfo.lastFunc, expected, val, (ok) ? "OK" : "ERROR");
#else
#define DO_PRINT_INT(ok)
#define DO_PRINT_LONG(ok)
#define DO_PRINT_LONGLONG(ok)
#define DO_PRINT_UINT(ok)
#define DO_PRINT_ULONG(ok)
#define DO_PRINT_ULONGLONG(ok)
#define DO_PRINT_FLOAT(ok)
#endif
/* The remaining functions are asserts. Assert functions perform
* comparison of expected and actual values, record location of
* errors, and call breakOnPass or breakOnError.
*/
void assertI1(const char *file, int line, const char *func, i1 val, i1 expected)
{
if (val == expected) {
breakOnPass();
} else {
MainInfo.lastErrorLine = line;
MainInfo.lastErrorFile = (char *) file;
breakOnError();
}
MainInfo.lastTestPos = line;
DO_PRINT_INT(val == expected);
}
void assertI2(const char *file, int line, const char *func, i2 val, i2 expected)
{
if (val == expected) {
breakOnPass();
} else {
MainInfo.lastErrorLine = line;
MainInfo.lastErrorFile = (char *) file;
breakOnError();
}
MainInfo.lastTestPos = line;
DO_PRINT_INT(val == expected);
}
void assertI4(const char *file, int line, const char *func, i4 val, i4 expected)
{
if (val == expected) {
breakOnPass();
} else {
MainInfo.lastErrorLine = line;
MainInfo.lastErrorFile = (char *) file;
breakOnError();
}
MainInfo.lastTestPos = line;
DO_PRINT_INT(val == expected);
}
#ifdef HAS_LONGLONG
void assertI8(const char *file, int line, const char *func, i8 val, i8 expected)
{
if (val == expected) {
breakOnPass();
} else {
MainInfo.lastErrorLine = line;
MainInfo.lastErrorFile = (char *) file;
breakOnError();
}
MainInfo.lastTestPos = line;
DO_PRINT_LONGLONG(val == expected);
}
#endif
void assertU1(const char *file, int line, const char *func, u1 val, u1 expected)
{
if (val == expected) {
breakOnPass();
} else {
MainInfo.lastErrorLine = line;
MainInfo.lastErrorFile = (char *) file;
breakOnError();
}
MainInfo.lastTestPos = line;
DO_PRINT_UINT(val == expected);
}
void assertU2(const char *file, int line, const char *func, u2 val, u2 expected)
{
if (val == expected) {
breakOnPass();
} else {
MainInfo.lastErrorLine = line;
MainInfo.lastErrorFile = (char *) file;
breakOnError();
}
MainInfo.lastTestPos = line;
DO_PRINT_UINT(val == expected);
}
void assertU4(const char *file, int line, const char *func, u4 val, u4 expected)
{
if (val == expected) {
breakOnPass();
} else {
MainInfo.lastErrorLine = line;
MainInfo.lastErrorFile = (char *) file;
breakOnError();
}
MainInfo.lastTestPos = line;
DO_PRINT_UINT(val == expected);
}
#ifdef HAS_LONGLONG
void assertU8(const char *file, int line, const char *func, u8 val, u8 expected)
{
if (val == expected) {
breakOnPass();
} else {
MainInfo.lastErrorLine = line;
MainInfo.lastErrorFile = (char *) file;
breakOnError();
}
MainInfo.lastTestPos = line;
DO_PRINT_ULONGLONG(val == expected);
}
#endif
#ifdef HAS_FLOAT
void assertF4(const char *file, int line, const char *func, f4 val, f4 expected)
{
u4 u4Val = *(u4 *) & val;
u4 u4Expected = *(u4 *) & expected;
/* Mask off last byte from value and expected */
u4Val &= 0xFFFFFF00;
u4Expected &= 0xFFFFFF00;
/* Should fail if diff in sign/exponent/or more than (0xFF * eplison) */
if (u4Val == u4Expected) {
breakOnPass();
} else {
MainInfo.lastErrorLine = line;
MainInfo.lastErrorFile = (char *) file;
breakOnError();
}
MainInfo.lastTestPos = line;
DO_PRINT_FLOAT(u4Val == u4Expected);
}
#endif
#ifdef HAS_DOUBLE
void assertF8(const char *file, int line, const char *func, f8 val, f8 expected)
{
u8 u8Val = *(u8 *) & val;
u8 u8Expected = *(u8 *) & expected;
/* Mask off last 2 bytes from value and expected */
u8Val &= 0xFFFFFFFFFFFF0000ULL;
u8Expected &= 0xFFFFFFFFFFFF0000ULL;
/* Should fail if diff in sign/exponent/or more than (0xFFFF * eplison) */
if (u8Val == u8Expected) {
breakOnPass();
} else {
MainInfo.lastErrorLine = line;
MainInfo.lastErrorFile = (char *) file;
breakOnError();
}
MainInfo.lastTestPos = line;
DO_PRINT_FLOAT(u8Val == u8Expected);
}
#endif