/*
#define exit EXIT
#define printf PRINTF
#define main MAIN
#define O_RDONLY 0
#define STDOUT_FILENO 1
#define PROT_READ 1
#define MAP_PRIVATE 2
#define SYS_CALL(r,a,a1,a2,a3) \
int res; __asm__ __volatile__ ( "int $0x80" : "=a"(res) \
: "0"(a),"b"((long)(a1)),"c"((long)(a2)),"d"((long)(a3)) ); \
return (((unsigned)(res) >= (unsigned)(-125)) ? (r)-1 : (r)res);
#define SYS_CALL3(r,n,x,t1,t2,t3) r n(t1 a1, t2 a2, t3 a3) { SYS_CALL(r,x,a1,a2,a3); }
#define SYS_CALL2(r,n,x,t1,t2) r n(t1 a1, t2 a2) { SYS_CALL(r,x,a1,a2, 0); }
#define SYS_CALL1(r,n,x,t1) r n(t1 a1) { SYS_CALL(r,x,a1, 0, 0); }
SYS_CALL1(void,exit,0x01,int)
SYS_CALL1(int,close,0x06,int)
SYS_CALL2(int,open,0x05,const char*,int)
SYS_CALL3(int,read,0x03,int,void*,int)
SYS_CALL3(int,write,0x04,int,const void*,int)
void *mmap(void *a, int b, int c, int d, int e, int f)
{
unsigned buf[6] = { (unsigned)a, (unsigned)b, (unsigned)c, (unsigned)d, (unsigned)e, (unsigned)f };
SYS_CALL(void*, 0x5A, buf, 0, 0);
}
void printf(const char *str, ...);
char **environ;
extern int main(int argc, char *argv[]);
void _start(int a, int b, int c, int d, int argc, char *argv0) {
environ = (char**)&argv0 + argc + 1;
printf("argc = %i\n", argc);
exit(main(argc, &argv0));
}
// GCC code
unsigned __udivmodsi4(unsigned num, unsigned den, unsigned *rem_p)
{
unsigned quot = 0, qbit = 1;
if ( den == 0 ) {
printf("Divide by 0\n");
//__divide_error();
return 0;
}
while ( (int)den >= 0 ) {
den <<= 1;
qbit <<= 1;
}
while ( qbit ) {
if ( den <= num ) {
num -= den;
quot += qbit;
}
den >>= 1;
qbit >>= 1;
}
if ( rem_p )
*rem_p = num;
return quot;
}
// GCC code
unsigned __udivsi3(unsigned num, unsigned den)
{
return __udivmodsi4(num, den, 0);
}
// GCC code
unsigned __umodsi3(unsigned num, unsigned den)
{
unsigned v;
(void) __udivmodsi4(num, den, &v);
return v;
}
char strTmpBuf[64];
char *strInteger(unsigned num, unsigned base)
{
const char *lookup = "0123456789ABCDEF";
int i = 1;
strTmpBuf[63] = 0;
do {
strTmpBuf[63-i] = lookup[num % base];
num /= base;
i++;
} while (num);
return &(strTmpBuf[63-i+1]);
}
#define PRINTF_BUF_SIZE 2048
void printf(const char *str, ...)
{
int ap = (int)&str + sizeof(str);
char outputBuffer[PRINTF_BUF_SIZE];
int i = 0, x = 0;
while (str[i]) {
if (str[i] == '%') {
i++;
if (str[i] == '%') {
outputBuffer[x] = str[i];
x++;
} else if (str[i] == 'i' || str[i] == 'd' || str[i] == 'u' || str[i] == 'o' ||
str[i] == 'x' || str[i] == 'X' || str[i] == 'p' || str[i] == 'n' ||
str[i] == 's') {
int num, base = 10, t = 0;
char *tmp;
if (str[i] != 's') {
if (str[i] == 'n')
num = x;
else {
num = *(int*)ap;
ap += sizeof(int);
}
if (str[i] == 'o') {
outputBuffer[x] = '0'; x++;
base = 8;
}
if (str[i] == 'x' || str[i] == 'X') {
outputBuffer[x] = '0'; x++;
outputBuffer[x] = str[i]; x++;
base = 16;
}
if (str[i] == 'p') {
outputBuffer[x] = '('; x++;
outputBuffer[x] = '0'; x++;
outputBuffer[x] = 'X'; x++;
base = 16;
}
tmp = strInteger(num, base);
} else {
tmp = *(char**)ap;
ap += sizeof(char*);
}
while (tmp[t]) {
outputBuffer[x] = tmp[t];
t++;
x++;
}
if (str[i] == 'p') {
outputBuffer[x] = ')'; x++;
}
} else if (str[i] == 'c') {
int ch = *(int*)ap;
ap += sizeof(int);
outputBuffer[x] = (char)ch;
x++;
} else {
// unrecognized / unsupported format identifier
}
} else {
outputBuffer[x] = str[i];
x++;
}
if ( x >= (PRINTF_BUF_SIZE / 2) ) {
write(STDOUT_FILENO, outputBuffer, x);
x = 0;
}
i++;
}
write(STDOUT_FILENO, outputBuffer, x);
}
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
int verbose = 0;
unsigned char *sectionData[4];
unsigned int sectionSize[4];
int init(char *file)
{
int fd = open(file, O_RDONLY);
read(fd, sectionSize, 16);
int total = 0;
int i;
for (i = 0; i < 4; i++) {
total += sectionSize[i];
// debug
if (verbose)
printf("size[%i] = %i\n", i, sectionSize[i]);
}
unsigned char *data = (unsigned char *)mmap(0, total+16, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
int runningTotal = 0;
for (i = 0; i < 4; i++) {
sectionData[i] = data + runningTotal + 16;
runningTotal += sectionSize[i];
}
// debug
int j;
if (verbose)
for (i = 0; i < 4; i++)
for (j = 0; j < sectionSize[i]; j++)
printf("data[%i][%i] = %i\n", i, j, sectionData[i][j]);
return 1;
}
void done()
{
printf("got nop, will exit now\n");
exit(0);
}
void call()
{
printf("got call inst\n");
}
void pnum(int i)
{
printf("debug %i\n", i);
}
void lineByte(int i, int b)
{
printf("debug: line %i byte: %i\n", i, b);
}
unsigned char *code;
unsigned char *data;
unsigned codeSize;
unsigned char *codeEnd;
int run(char *file)
{
if (!init(file))
return -1;
code = sectionData[0];
data = sectionData[1];
codeSize = sectionSize[0];
codeEnd = &code[codeSize];
// codeEnd[0] = -1;
// codeEnd[1] = -1;
__asm__ __volatile__ (
" movl code,%esi\n"
" movl data,%edi\n"
"again:\n"
" xorl %ecx,%ecx\n"
" mov (%esi),%cl\n"
// Debugging
" movl %esi,%eax\n"
" sub code,%eax\n"
" push %ecx\n"
" push %eax\n"
" push %ecx\n"
" push %eax\n"
" call lineByte\n"
" pop %eax\n"
" pop %ecx\n"
" addl $1,%esi\n"
// " cmpl codeEnd,%esi\n" // Can avoid if can cause
// " jle over1\n" // the end of the mapped
// " call exit\n" // code to call 'done' or nop etc.
// "over1:\n"
" movl %ecx,%ebx\n"
" andl $15,%ebx\n"
" jmpl *tab1(,%ebx,4)\n"
"next_nibble:\n"
" shrl $4,%ecx\n"
" andl $15,%ecx\n"
" jmpl *tab2(,%ecx,4)\n"
"tab1:\n"
" .long PUSH1a,ADDa,SUBa,MULa,DIVa,ANDa,ORa,XORa,RETa\n"
" .long SHIFT,CALL,JMP,POP,PUSHval,PUSHref,NOP1\n"
"tab2:\n"
" .long PUSH1b,ADDb,SUBb,MULb,DIVb,ANDb,ORb,XORb,RETb\n"
" .long SHIFT,CALL,JMP,POP,PUSHval,PUSHref,NOP1\n"
"PUSH1a:\n" " pushl $1\n" "\tjmp next_nibble\n"
"ADDa:\n" " popl %eax\n" "\taddl %eax,(%esp)\n" "\tjmp next_nibble\n"
"SUBa:\n" " popl %eax\n" "\tsubl %eax,(%esp)\n" "\tjmp next_nibble\n"
"MULa:\n" " popl %eax\n" "\timull (%esp)\n"
"\tmovl %eax,(%esp)\n" "\tjmp next_nibble\n"
"DIVa:\n" " popl %eax\n" "\tidivl (%esp)\n"
"\tmovl %eax,(%esp)\n" "\tjmp next_nibble\n"
"ANDa:\n" " popl %eax\n" "\tandl %eax,(%esp)\n" "\tjmp next_nibble\n"
"ORa:\n" " popl %eax\n" "\torl %eax,(%esp)\n" "\tjmp next_nibble\n"
"XORa:\n" " popl %eax\n" "\txorl %eax,(%esp)\n" "\tjmp next_nibble\n"
"RETa:\n" " popl %esi\n" "\tjmp next_nibble\n"
"PUSH1b:\n" " pushl $1\n" "\tjmp again\n"
"ADDb:\n" " popl %eax\n" "\taddl %eax,(%esp)\n" "\tjmp again\n"
"SUBb:\n" " popl %eax\n" "\tsubl %eax,(%esp)\n" "\tjmp again\n"
"MULb:\n" " popl %eax\n" "\timull (%esp)\n"
"\tmovl %eax,(%esp)\n" "\tjmp again\n"
"DIVb:\n" " popl %eax\n" "\tidivl (%esp)\n"
"\tmovl %eax,(%esp)\n" "\tjmp again\n"
"ANDb:\n" " popl %eax\n" "\tandl %eax,(%esp)\n" "\tjmp again\n"
"ORb:\n" " popl %eax\n" "\torl %eax,(%esp)\n" "\tjmp again\n"
"XORb:\n" " popl %eax\n" "\txorl %eax,(%esp)\n" "\tjmp again\n"
"RETb:\n" " popl %esi\n" "\tjmp again\n"
"JMP:\n" // TODO - seems to work
// "\taddl $4,%esi\n"
"\tmovl (%esi),%eax\n"
"\tmovl code,%esi\n"
"\taddl %eax,%esi\n"
// "\taddl $4,%esi\n"
"\tjmp again\n"
"SHIFT:\n" // TODO
"\taddl $4,%esi\n"
"\tjmp again\n"
"CALL:\n" // TODO
"\tcall call\n"
// "\tcall printf\n"
"\taddl $4,%esi\n"
"\tjmp again\n"
"POP:\n"
"\tmovl (%esi),%eax\n"
"\tpopl (%edi,%eax,)\n"
"\taddl $4,%esi\n"
"\tjmp again\n"
"PUSHval:\n"
"\tmovl (%esi),%eax\n"
"\tpushl (%edi,%eax,)\n"
"\taddl $4,%esi\n"
"\tjmp again\n"
"PUSHref:\n"
"\tmovl (%esi),%eax\n"
"\tleal (%edi,%eax,),%eax\n"
"\tpushl %eax\n"
"\taddl $4,%esi\n"
"\tjmp again\n"
"NOP1:\n"
"\tcall done\n"
"\tjmp again\n"
);
}
int main(int argc, char *argv[])
{
int i;
char *input = 0;
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-' && argv[i][1] == 'v')
verbose = 1;
else
input = argv[i];
}
if (input)
return run(input);
printf("No input files.\n");
return -1;
}