300 lines
8.0 KiB
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
|
|
|