584 lines
11 KiB
C
584 lines
11 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"
|
|
|
|
#ifndef HAS_LIBC
|
|
void *memcpy(void *dest, const void *src, size_t n)
|
|
{
|
|
unsigned i;
|
|
for (i = 0; i < n; i++)
|
|
((unsigned char *) dest)[i] = ((unsigned char *) src)[i];
|
|
return dest;
|
|
}
|
|
#endif // !HAS_LIBC
|
|
|
|
#ifndef HAS_LIBC
|
|
void *memset(void *s, int c, size_t n)
|
|
{
|
|
unsigned char *dst = s;
|
|
for (; n > 0; n--, dst++)
|
|
*dst = (unsigned char) c;
|
|
return s;
|
|
}
|
|
#endif // !HAS_LIBC
|
|
|
|
#ifndef HAS_LIBC
|
|
int memcmp(void *s1, void *s2, size_t n)
|
|
{
|
|
unsigned i;
|
|
for (i = 0; i < n; i++, s1++, s2++) {
|
|
if (* (unsigned char *) s1 < * (unsigned char *) s2) return -1;
|
|
else if (* (unsigned char *) s1 > * (unsigned char *) s2) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif // !HAS_LIBC
|
|
|
|
#if defined(BUILD_EXE)
|
|
|
|
#pragma GCC push_options
|
|
#pragma GCC optimize("O0")
|
|
|
|
#ifndef HAS_LIBC
|
|
void write(int fd, char *buf, int count)
|
|
{
|
|
#if defined(__AARCH64EL__) || defined(__AARCH64EB__)
|
|
asm( "mov x0,%[fd]\n\t"
|
|
"mov x1,%[msgstr]\n\t"
|
|
"mov x2,%[msglen]\n\t"
|
|
"mov x8,#64\n\t"
|
|
"svc #0\n\t"
|
|
:
|
|
: [fd] "r" (fd),
|
|
[msgstr] "r" (buf),
|
|
[msglen] "r" (count)
|
|
: "x0", "x1", "x2", "x8"
|
|
);
|
|
|
|
#elif defined(__ARM_ARCH_ISA_THUMB)
|
|
asm( "push {r7}\n\t"
|
|
"mov r0,%[fd]\n\t"
|
|
"mov r1,%[msgstr]\n\t"
|
|
"mov r2,%[msglen]\n\t"
|
|
"mov r7,#4\n\t"
|
|
"swi #0\n\t"
|
|
"pop {r7}\n\t"
|
|
:
|
|
: [fd] "r" (fd),
|
|
[msgstr] "r" (buf),
|
|
[msglen] "r" (count)
|
|
: "r0", "r1", "r2"
|
|
);
|
|
|
|
|
|
#elif defined(__ARMEL__) || defined(__ARMEB__)
|
|
asm( "mov %%r0,%[fd]\n\t"
|
|
"mov %%r1,%[msgstr]\n\t"
|
|
"mov %%r2,%[msglen]\n\t"
|
|
"mov %%r7,#4\n\t"
|
|
"swi $0\n\t"
|
|
:
|
|
: [fd] "r" (fd),
|
|
[msgstr] "r" (buf),
|
|
[msglen] "r" (count)
|
|
: "r0", "%r1", "r2", "r7"
|
|
);
|
|
|
|
#elif defined(__m68k__)
|
|
asm( "moveq #4,%%d0\n\t"
|
|
"move %[fd],%%d1\n\t"
|
|
"move %[msgstr],%%d2\n\t"
|
|
"move %[msglen],%%d3\n\t"
|
|
"trap #0\n\t"
|
|
:
|
|
: [fd] "r" (fd),
|
|
[msgstr] "r" (buf),
|
|
[msglen] "r" (count)
|
|
: "d0", "d1", "d2", "d3"
|
|
);
|
|
|
|
#elif defined(__MIPSEB__)
|
|
asm( "move $a0, %[fd]\n\t"
|
|
"move $a1, %[msgstr]\n\t"
|
|
"move $a2, %[msglen]\n\t"
|
|
"li $v0, 4004\n\t"
|
|
"syscall\n\t"
|
|
:
|
|
: [fd] "r" (fd),
|
|
[msgstr] "r" (buf),
|
|
[msglen] "r" (count)
|
|
: "v0", "a0", "a1", "a2"
|
|
);
|
|
|
|
#elif defined(__PPC__)
|
|
asm( "li 0,4\n\t"
|
|
"lwz 3,%[fd]\n\t"
|
|
#ifdef __PPC64__
|
|
"ld 4,%[msgstr]\n\t"
|
|
#else
|
|
"lwz 4,%[msgstr]\n\t"
|
|
#endif
|
|
"lwz 5,%[msglen]\n\t"
|
|
"sc\n\t"
|
|
:
|
|
: [fd] "" (fd),
|
|
[msgstr] "" (buf),
|
|
[msglen] "" (count)
|
|
: "r0", "r3", "r4", "r5"
|
|
);
|
|
|
|
#elif defined(__pentium__)
|
|
asm( "mov %[msglen],%%edx\n\t"
|
|
"mov %[msgstr],%%ecx\n\t"
|
|
"mov %[fd],%%ebx\n\t"
|
|
"mov $4,%%eax\n\t"
|
|
"int $0x80\n\t"
|
|
:
|
|
: [fd] "" (fd),
|
|
[msgstr] "" (buf),
|
|
[msglen] "" (count)
|
|
: "eax", "ebx", "ecx", "edx"
|
|
);
|
|
|
|
#elif defined(__SH4__)
|
|
asm( "mov #4,r3\n\t"
|
|
"mov %[fd],r4\n\t"
|
|
"mov %[msgstr],r5\n\t"
|
|
"mov %[msglen],r6\n\t"
|
|
"trapa #17\n\t"
|
|
:
|
|
: [fd] "r" (fd),
|
|
[msgstr] "r" (buf),
|
|
[msglen] "r" (count)
|
|
: "r3", "r4", "r5", "r6"
|
|
);
|
|
|
|
#elif defined(__sparc__)
|
|
asm( "mov 1,%%o0\n\t"
|
|
// "sethi %%hi(%[msgstr]), %%g1\n\t"
|
|
// "or %%g1, %%lo(%[msgstr]), %%o1\n\t"
|
|
"ld %[msgstr], %%o1\n\t"
|
|
"mov 4,%%g1\n\t"
|
|
"ld %[msglen],%%o2\n\t"
|
|
"t 0x6d\n\t"
|
|
:
|
|
: [fd] "" (fd),
|
|
[msgstr] "" (buf),
|
|
[msglen] "" (count)
|
|
: "o0", "g1", "o1", "o2"
|
|
);
|
|
|
|
#elif defined(__x86_64__)
|
|
asm( "mov %[msglen],%%edx\n\t"
|
|
"movq %[msgstr],%%rsi\n\t"
|
|
"movq %[fd],%%rdi\n\t"
|
|
"movq $1,%%rax\n\t"
|
|
"syscall\n\t"
|
|
:
|
|
: [fd] "" (fd),
|
|
[msgstr] "" (buf),
|
|
[msglen] "" (count)
|
|
: "rax", "rdi", "rsi", "rdx"
|
|
);
|
|
#endif
|
|
}
|
|
#endif // !HAS_LIBC
|
|
|
|
#ifndef HAS_LIBC
|
|
void exit(int stat)
|
|
{
|
|
#if defined(__AARCH64EL__) || defined(__AARCH64EB__)
|
|
asm( "mov x0,%[status]\n\t"
|
|
"mov x8,#93\n\t"
|
|
"svc #0\n\t"
|
|
:
|
|
: [status] "r" (stat)
|
|
: "x0", "x8"
|
|
);
|
|
|
|
#elif defined(__ARM_ARCH_ISA_THUMB)
|
|
asm( "push {r7}\n\t"
|
|
"mov r0,%[status]\n\t"
|
|
"mov r7,#1\n\t"
|
|
"swi #0\n\t"
|
|
"pop {r7}\n\t"
|
|
:
|
|
: [status] "r" (stat)
|
|
: "r0"
|
|
);
|
|
|
|
#elif defined(__ARMEL__) || defined(__ARMEB__)
|
|
asm( "mov %%r0,%[status]\n\t"
|
|
"mov %%r7,#1\n\t"
|
|
"swi $0\n\t"
|
|
:
|
|
: [status] "r" (stat)
|
|
: "r0", "r7"
|
|
);
|
|
|
|
#elif defined(__m68k__)
|
|
asm( "moveq #1,%%d0\n\t"
|
|
"move %[status],%%d1\n\t"
|
|
"trap #0\n\t"
|
|
:
|
|
: [status] "" (stat)
|
|
: "d0", "d1"
|
|
);
|
|
|
|
#elif defined(__MIPSEB__)
|
|
asm( "move $a0,%[status]\n\t"
|
|
"li $v0, 4001\n\t"
|
|
"syscall\n\t"
|
|
:
|
|
: [status] "r" (stat)
|
|
: "v0", "a0"
|
|
);
|
|
|
|
#elif defined(__PPC__)
|
|
asm( " li 0,1 \n"
|
|
" lwz 3,%[status] \n"
|
|
" sc \n"
|
|
:
|
|
: [status] "" (stat)
|
|
: "r0", "r3"
|
|
);
|
|
|
|
#elif defined(__pentium__)
|
|
asm( "mov %[status],%%ebx\n\t"
|
|
"mov $1,%%eax\n\t"
|
|
"int $0x80\n\t"
|
|
:
|
|
: [status] "" (stat)
|
|
: "eax", "ebx"
|
|
);
|
|
|
|
#elif defined(__SH4__)
|
|
asm( "mov #1,r3\n\t"
|
|
"mov %[status],r4\n\t"
|
|
"trapa #17\n\t"
|
|
:
|
|
: [status] "r" (stat)
|
|
: "r3", "r4"
|
|
);
|
|
|
|
#elif defined(__sparc__)
|
|
asm( "mov 1,%%g1\n\t"
|
|
"mov %[status],%%o0\n\t"
|
|
"t 0x6d\n\t"
|
|
"nop\n\t"
|
|
:
|
|
: [status] "r" (stat)
|
|
: "g1", "o0"
|
|
);
|
|
|
|
#elif defined(__x86_64__)
|
|
asm( "mov %[status],%%rdi\n\t"
|
|
"mov $60,%%rax\n\t"
|
|
"syscall\n\t"
|
|
:
|
|
: [status] "" (stat)
|
|
: "rax", "rdi"
|
|
);
|
|
#endif
|
|
}
|
|
#endif // !HAS_LIBC
|
|
|
|
#ifndef HAS_LIBC
|
|
static int strlen(char *str)
|
|
{
|
|
int len;
|
|
for (len = 0; str[len]; len++) ;
|
|
return len;
|
|
}
|
|
#endif // !HAS_LIBC
|
|
|
|
#ifndef HAS_LIBC
|
|
static void strcpy(char *dst, char *src)
|
|
{
|
|
while (*src) *dst++ = *src++;
|
|
*dst = *src;
|
|
}
|
|
#endif // !HAS_LIBC
|
|
|
|
#ifndef HAS_LIBC
|
|
static void put(char *str)
|
|
{
|
|
write(1, str, strlen(str));
|
|
}
|
|
#endif // !HAS_LIBC
|
|
|
|
// utoa, itoa and ftoa
|
|
|
|
// Convert unsigned u to decimal.
|
|
// if dflag is set, insert a decimal point after the first nonzero
|
|
// digit, and return the number of decimal places
|
|
|
|
static int utoa(unsigned long u, char *buff, int len, int dflag)
|
|
{
|
|
int i = len - 1;
|
|
int ret = 0;
|
|
int j;
|
|
|
|
if (dflag) dflag = 1;
|
|
|
|
if (u == 0) {
|
|
if (dflag) {
|
|
strcpy(buff, "0.0");
|
|
return 1;
|
|
} else {
|
|
strcpy(buff, "0");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// Put in ascii at the end of the buffer
|
|
|
|
buff[i] = '\0';
|
|
i = i - 1;
|
|
while (u > 0 && i >= 0) {
|
|
buff[i] = '0' + (u % 10);
|
|
u = u / 10;
|
|
i = i - 1;
|
|
}
|
|
|
|
// Now move the string to the front of the buffer, optionally
|
|
// inserting a decimal point
|
|
|
|
j = 0;
|
|
i = i + 1;
|
|
while (i < len && j < i) {
|
|
if (j == 1 && dflag) {
|
|
buff[j] = '.';
|
|
j = j + 1;
|
|
}
|
|
buff[j] = buff[i];
|
|
if (dflag && j > 1 && buff[j]) ret = ret + 1;
|
|
j = j + 1;
|
|
i = i + 1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int itoa(long u, char *buff, int len, int dflag)
|
|
{
|
|
if (u < 0) {
|
|
*buff = '-';
|
|
len = len - 1;
|
|
buff = buff + 1;
|
|
u = - u;
|
|
}
|
|
utoa(u, buff, len, dflag);
|
|
}
|
|
|
|
static void ftoa(float f, char *buff, int len)
|
|
{
|
|
unsigned int fi;
|
|
int sig;
|
|
unsigned int f2, fa;
|
|
int e2, ea;
|
|
int ra;
|
|
|
|
*buff = '\0';
|
|
|
|
// find fa and ea such that
|
|
// f = f2 2^(e2-23) = fa 10^ea
|
|
|
|
if (sizeof(f) == 4) {
|
|
fi = * (int *) &f;
|
|
sig = (fi & 0x80000000) ? 1 : 0;
|
|
e2 = ((fi >> 23) & 0xff);
|
|
f2 = (fi & 0x7fffff);
|
|
|
|
// Handle normalized numbers
|
|
|
|
if (e2 != 0) {
|
|
f2 = f2 | 0x800000;
|
|
e2 = e2 - 127;
|
|
e2 = e2 - 23;
|
|
}
|
|
|
|
if (e2 == 0 && f2 == 0) {
|
|
strcpy(buff, "0.0");
|
|
return;
|
|
}
|
|
|
|
// determine ea, fa iteratively
|
|
// by reducing e2 to 0
|
|
|
|
ea = 0;
|
|
fa = f2;
|
|
// printf("%f = %u 2^%d 10^%d?\n", f, fa, e2, ea);
|
|
while (e2 > 0) {
|
|
// If the the high bit is set
|
|
// then we can't multiply by 2
|
|
// without losing it, so divide by 10
|
|
// and round off
|
|
if (fa & (1 << 31)) {
|
|
ra = ((fa % 5) > 2) ? 1 : 0;
|
|
fa = (fa / 5) + ra;
|
|
ea = ea + 1;
|
|
} else {
|
|
fa = fa * 2;
|
|
}
|
|
e2 = e2 - 1;
|
|
// printf("%f = %u 2^%d 10^%d?\n", f, fa, e2, ea);
|
|
}
|
|
while (e2 < 0) {
|
|
// If the top 3 bits are zero
|
|
// then we can multiply by 10
|
|
// and preserve the precision
|
|
if ((fa & (7 << 29)) == 0) {
|
|
fa = fa * 5;
|
|
ea = ea - 1;
|
|
} else {
|
|
ra = (fa % 2) ? 1 : 0;
|
|
fa = (fa / 2) + ra;
|
|
}
|
|
e2 = e2 + 1;
|
|
// printf("%f = %u 2^%d 10^%d?\n", f, fa, e2, ea);
|
|
}
|
|
|
|
// Now we have what we want, f = fa 10^ea
|
|
// it remains to convert this to ascii
|
|
// and move the decimal point
|
|
|
|
if (sig) {
|
|
*buff = '-';
|
|
len = len - 1;
|
|
buff = buff + 1;
|
|
}
|
|
ea = ea + utoa(fa, buff, len, 1);
|
|
len = len - strlen(buff);
|
|
buff = buff + strlen(buff);
|
|
if (ea == 0) return;
|
|
|
|
*buff = 'e';
|
|
len = len - 1;
|
|
buff = buff + 1;
|
|
|
|
if (ea < 0) {
|
|
*buff = '-';
|
|
len = len - 1;
|
|
buff = buff + 1;
|
|
ea = -ea;
|
|
} else {
|
|
*buff = '+';
|
|
len = len - 1;
|
|
buff = buff + 1;
|
|
}
|
|
utoa(ea, buff, len, 0);
|
|
}
|
|
}
|
|
|
|
static void print_info(char *file, int line, char *func, char *type, char *expected, char *val, char *ok)
|
|
{
|
|
#ifndef HAS_LIBC
|
|
char lbuff[100];
|
|
utoa(line, lbuff, 100, 0);
|
|
|
|
put("File "); put(file);
|
|
put(" line "); put(lbuff);
|
|
put(" function "); put(func);
|
|
put(" expected "); put(type);
|
|
put(" "); put(expected);
|
|
put(" got "); put(val);
|
|
put(" "); put(ok);
|
|
put("\n");
|
|
#else
|
|
printf("File %s line %d function %s expected %s %s got %s %s\n", file, line, func, type, expected, val, ok);
|
|
#endif // HAS_LIBC
|
|
}
|
|
|
|
void print_int(char *file, int line, char *func, int expected, int val, char *ok)
|
|
{
|
|
#ifdef HAS_PRINTF
|
|
printf("File %s line %d function %s expected %s %d got %d %s\n", file, line, func, "int", expected, val, ok);
|
|
#else
|
|
char ebuff[100];
|
|
itoa(expected, ebuff, 100, 0);
|
|
char vbuff[100];
|
|
itoa(val, vbuff, 100, 0);
|
|
print_info(file, line, func, "int", ebuff, vbuff, ok);
|
|
#endif
|
|
}
|
|
|
|
void print_long(char *file, int line, char *func, long expected, long val, char *ok)
|
|
{
|
|
#ifdef HAS_PRINTF
|
|
printf("File %s line %d function %s expected %s %ld got %ld %s\n", file, line, func, "long", expected, val, ok);
|
|
#else
|
|
char ebuff[100];
|
|
itoa(expected, ebuff, 100, 0);
|
|
char vbuff[100];
|
|
itoa(val, vbuff, 100, 0);
|
|
print_info(file, line, func, "long", ebuff, vbuff, ok);
|
|
#endif
|
|
}
|
|
|
|
void print_uint(char *file, int line, char *func, unsigned int expected, unsigned int val, char *ok)
|
|
{
|
|
#ifdef HAS_PRINTF
|
|
printf("File %s line %d function %s expected %s %u got %u %s\n", file, line, func, "uint", expected, val, ok);
|
|
#else
|
|
char ebuff[100];
|
|
utoa(expected, ebuff, 100, 0);
|
|
char vbuff[100];
|
|
utoa(val, vbuff, 100, 0);
|
|
print_info(file, line, func, "uint", ebuff, vbuff, ok);
|
|
#endif
|
|
}
|
|
|
|
void print_ulong(char *file, int line, char *func, unsigned long expected, unsigned long val, char *ok)
|
|
{
|
|
#ifdef HAS_PRINTF
|
|
printf("File %s line %d function %s expected %s %lu got %lu %s\n", file, line, func, "ulong", expected, val, ok);
|
|
#else
|
|
char ebuff[100];
|
|
utoa(expected, ebuff, 100, 0);
|
|
char vbuff[100];
|
|
utoa(val, vbuff, 100, 0);
|
|
print_info(file, line, func, "ulong", ebuff, vbuff, ok);
|
|
#endif
|
|
}
|
|
|
|
void print_float(char *file, int line, char *func, float expected, float val, char *ok)
|
|
{
|
|
#ifdef HAS_PRINTF
|
|
printf("File %s line %d function %s expected %s %.9e got %.9e %s\n", file, line, func, "float", expected, val, ok);
|
|
#else
|
|
char ebuff[100];
|
|
char vbuff[100];
|
|
ftoa(expected, ebuff, 100);
|
|
ftoa(val, vbuff, 100);
|
|
print_info(file, line, func, "float", ebuff, vbuff, ok);
|
|
#endif
|
|
}
|
|
|
|
void print_val(char *name, int val)
|
|
{
|
|
#ifdef HAS_PRINTF
|
|
printf("%s %d\n", name, val);
|
|
#else
|
|
char vbuff[100];
|
|
itoa(val, vbuff, 100, 0);
|
|
put(name); put(" "); put(vbuff); put("\n");
|
|
#endif
|
|
}
|
|
|
|
#pragma GCC pop_options
|
|
#endif // BUILD_EXE
|