#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>

typedef long long jlong;
typedef char jbyte;
typedef unsigned short jchar;
typedef signed short jshort;
typedef int jint;
typedef float jfloat;
typedef double jdouble;

typedef struct {
    char* name;
    int address;
} MethodEntry;

MethodEntry method[256];
int method_counter = 0;
int baseAddress;
int codeLength;

jint (*s3_services_simplejit_test_TestJIT_testIreturn)();
jlong (*s3_services_simplejit_test_TestJIT_testLreturn)();
jfloat (*s3_services_simplejit_test_TestJIT_testFreturn)();
jdouble (*s3_services_simplejit_test_TestJIT_testDreturn)();
jint (*s3_services_simplejit_test_TestJIT_testIadd)();
jlong (*s3_services_simplejit_test_TestJIT_testLadd)();
jfloat (*s3_services_simplejit_test_TestJIT_testFadd)();
jdouble (*s3_services_simplejit_test_TestJIT_testDadd)();
jint (*s3_services_simplejit_test_TestJIT_testIsub)();
jlong (*s3_services_simplejit_test_TestJIT_testLsub)();
jfloat (*s3_services_simplejit_test_TestJIT_testFsub)();
jdouble (*s3_services_simplejit_test_TestJIT_testDsub)();
jint (*s3_services_simplejit_test_TestJIT_testImul)();
jlong (*s3_services_simplejit_test_TestJIT_testLmul)();
jfloat (*s3_services_simplejit_test_TestJIT_testFmul)();
jdouble (*s3_services_simplejit_test_TestJIT_testDmul)();
jint (*s3_services_simplejit_test_TestJIT_testIdiv)();
jfloat (*s3_services_simplejit_test_TestJIT_testFdiv)();
jdouble (*s3_services_simplejit_test_TestJIT_testDdiv)();
jint (*s3_services_simplejit_test_TestJIT_testIrem)();
jint (*s3_services_simplejit_test_TestJIT_testIneg)();
jlong (*s3_services_simplejit_test_TestJIT_testLneg)();
jfloat (*s3_services_simplejit_test_TestJIT_testFneg)();
jdouble (*s3_services_simplejit_test_TestJIT_testDneg)();
jint (*s3_services_simplejit_test_TestJIT_testIshl)();
jlong (*s3_services_simplejit_test_TestJIT_testLshl)();
jint (*s3_services_simplejit_test_TestJIT_testIshr)();
jlong (*s3_services_simplejit_test_TestJIT_testLshr)();
jint (*s3_services_simplejit_test_TestJIT_testIushr)();
jlong (*s3_services_simplejit_test_TestJIT_testLushr)();
jint (*s3_services_simplejit_test_TestJIT_testIand)();
jlong (*s3_services_simplejit_test_TestJIT_testLand)();
jint (*s3_services_simplejit_test_TestJIT_testIor)();
jlong (*s3_services_simplejit_test_TestJIT_testLor)();
jint (*s3_services_simplejit_test_TestJIT_testIxor)();
jlong (*s3_services_simplejit_test_TestJIT_testLxor)();
jint (*s3_services_simplejit_test_TestJIT_testIinc)();
jlong (*s3_services_simplejit_test_TestJIT_testI2l)();
jfloat (*s3_services_simplejit_test_TestJIT_testI2f)();
jdouble (*s3_services_simplejit_test_TestJIT_testI2d)();
jint (*s3_services_simplejit_test_TestJIT_testL2i)();
jfloat (*s3_services_simplejit_test_TestJIT_testL2f)();
jdouble (*s3_services_simplejit_test_TestJIT_testL2d)();
jint (*s3_services_simplejit_test_TestJIT_testF2i)();
jlong (*s3_services_simplejit_test_TestJIT_testF2l)();
jdouble (*s3_services_simplejit_test_TestJIT_testF2d)();
jint (*s3_services_simplejit_test_TestJIT_testD2i)();
jlong (*s3_services_simplejit_test_TestJIT_testD2l)();
jfloat (*s3_services_simplejit_test_TestJIT_testD2f)();
jbyte (*s3_services_simplejit_test_TestJIT_testI2b)();
jchar (*s3_services_simplejit_test_TestJIT_testI2c)();
jshort (*s3_services_simplejit_test_TestJIT_testI2s)();
jint (*s3_services_simplejit_test_TestJIT_testIfxx)();
jint (*s3_services_simplejit_test_TestJIT_testIf_icmpxx)();
jint (*s3_services_simplejit_test_TestJIT_testLcmp)();
jint (*s3_services_simplejit_test_TestJIT_testFcmp)();
jint (*s3_services_simplejit_test_TestJIT_testDcmp)();
jint (*s3_services_simplejit_test_TestJIT_testJsr)();
jint (*s3_services_simplejit_test_TestJIT_testTableswitch)();
jint (*s3_services_simplejit_test_TestJIT_testLookupswitch)();
jint (*s3_services_simplejit_test_TestJIT_testIfnull)();
jint (*s3_services_simplejit_test_TestJIT_testIfnonnull)();
jdouble (*s3_services_simplejit_test_TestJIT_testWide)();
jint (*s3_services_simplejit_test_TestJIT_testGoto_wAndJsr_w)();
jint (*s3_services_simplejit_test_TestJIT_testLdc)();
jlong (*s3_services_simplejit_test_TestJIT_testLdc2_w)();

void assert(int b, char* msg) {
    if (! b) {
	char message[256];
	message[0] = 0;
	strcat(message, "assertion failure : ");
	strcat(message, msg);
	fprintf(stderr, message);
    }
}

void printInteger(int i) {
    printf("0x%x\n", i);
}

void printLong(jlong l) {
    printf("0x%x,%x\n", (int)(l >> 32), (int)(l & 0xFFFFFFFF));
}

void printFloat(float f) {
    printf("%f\n", f);
}

void printDouble(double d) {
    printf("%lf\n", d);
}

typedef struct {
    char* token;
    int position;
} Token;

static void getNextToken(char* stream,
			 Token* token,
			 int end) {
    int begin = 0;
    int i;
    int start = -1;
    if (token->token != NULL) {
	begin = token->position + strlen(token->token) + 1;
    } else {
	begin = 0;
    }
    if (begin >= end) {
	token->position = -1;
	return;
    }
    i = begin;
    while ((stream[i] == ' ' ||
	    stream[i] == '\n' ||
	    stream[i] == '\t' ||
	    stream[i] == 0) &&
	   i < end)
	i++;
    start = i;
    while (stream[i] != ' ' &&
	   stream[i] != '\n' &&
	   stream[i] != '\t' &&
	   stream[i] != 0 &&
	   i < end)
	i++;
    stream[i] = 0;
    token->token = (char*)(stream + start);
    token->position = start;
}

void readSymbols(char* symbolfilename) {
    int read_size;
    FILE* symbolfile = fopen(symbolfilename, "r");
    const int buf_size = 1024 * 1024;
    char buffer[buf_size];
    Token token;

    token.token = NULL;
    token.position = 0;

    read_size = fread(buffer, sizeof(char), buf_size, symbolfile);

    getNextToken(buffer, &token, read_size);
    assert(strcmp(token.token, "<start>") == 0, "invalid start\n");

    getNextToken(buffer, &token, read_size);
    sscanf(token.token, "%d", &baseAddress);

    getNextToken(buffer, &token, read_size);
    assert(strcmp(token.token, "<length>") == 0, "invalid length\n");

    getNextToken(buffer, &token, read_size);
    sscanf(token.token, "%d", &codeLength);

    getNextToken(buffer, &token, read_size);

    while (token.position != -1) {
	int code_offset;
	method[method_counter].name 
	    = (char*)malloc((strlen(token.token) + 1) * sizeof(char));
	strcpy(method[method_counter].name, token.token);
	
	getNextToken(buffer, &token, read_size);
	sscanf(token.token, "%d", &code_offset);
	method[method_counter].address = baseAddress + code_offset;

	method_counter++;
	getNextToken(buffer, &token, read_size);
    }

}
void mapCompiledCode(char* codefilename) {
    int fd;
    void* mapped;
    //mmap
    fd = open(codefilename, O_NDELAY|O_RDWR);
    mapped = mmap((void*)baseAddress, 
		  codeLength, 
		  PROT_EXEC|PROT_READ|PROT_WRITE, 
		  MAP_PRIVATE|MAP_FIXED,
		  fd,
		  0);
    close(fd);
}

void* resolveAddress(char* name) {
    int i;
    for(i = 0; i < method_counter; i++) {
	if (strcmp(method[i].name, name) == 0) {
	    return (void*)method[i].address;
	}
    }
    printf("%s not found\n", name);
    return 0;
}

void resolveCompiledMethods() {
    s3_services_simplejit_test_TestJIT_testIreturn = resolveAddress("s3_services_simplejit_test_TestJIT_testIreturn");
    s3_services_simplejit_test_TestJIT_testLreturn = resolveAddress("s3_services_simplejit_test_TestJIT_testLreturn");
    s3_services_simplejit_test_TestJIT_testFreturn = resolveAddress("s3_services_simplejit_test_TestJIT_testFreturn");
    s3_services_simplejit_test_TestJIT_testDreturn = resolveAddress("s3_services_simplejit_test_TestJIT_testDreturn");
    s3_services_simplejit_test_TestJIT_testIadd = resolveAddress("s3_services_simplejit_test_TestJIT_testIadd");
    s3_services_simplejit_test_TestJIT_testLadd = resolveAddress("s3_services_simplejit_test_TestJIT_testLadd");
    s3_services_simplejit_test_TestJIT_testFadd = resolveAddress("s3_services_simplejit_test_TestJIT_testFadd");
    s3_services_simplejit_test_TestJIT_testDadd = resolveAddress("s3_services_simplejit_test_TestJIT_testDadd");
    s3_services_simplejit_test_TestJIT_testIsub = resolveAddress("s3_services_simplejit_test_TestJIT_testIsub");
    s3_services_simplejit_test_TestJIT_testLsub = resolveAddress("s3_services_simplejit_test_TestJIT_testLsub");
    s3_services_simplejit_test_TestJIT_testFsub = resolveAddress("s3_services_simplejit_test_TestJIT_testFsub");
    s3_services_simplejit_test_TestJIT_testDsub = resolveAddress("s3_services_simplejit_test_TestJIT_testDsub");
    s3_services_simplejit_test_TestJIT_testImul = resolveAddress("s3_services_simplejit_test_TestJIT_testImul");
    s3_services_simplejit_test_TestJIT_testLmul = resolveAddress("s3_services_simplejit_test_TestJIT_testLmul");
    s3_services_simplejit_test_TestJIT_testFmul = resolveAddress("s3_services_simplejit_test_TestJIT_testFmul");
    s3_services_simplejit_test_TestJIT_testDmul = resolveAddress("s3_services_simplejit_test_TestJIT_testDmul");
    s3_services_simplejit_test_TestJIT_testIdiv = resolveAddress("s3_services_simplejit_test_TestJIT_testIdiv");
    s3_services_simplejit_test_TestJIT_testFdiv = resolveAddress("s3_services_simplejit_test_TestJIT_testFdiv");
    s3_services_simplejit_test_TestJIT_testDdiv = resolveAddress("s3_services_simplejit_test_TestJIT_testDdiv");
    s3_services_simplejit_test_TestJIT_testIrem = resolveAddress("s3_services_simplejit_test_TestJIT_testIrem");
    s3_services_simplejit_test_TestJIT_testIneg = resolveAddress("s3_services_simplejit_test_TestJIT_testIneg");
    s3_services_simplejit_test_TestJIT_testLneg = resolveAddress("s3_services_simplejit_test_TestJIT_testLneg");
    s3_services_simplejit_test_TestJIT_testFneg = resolveAddress("s3_services_simplejit_test_TestJIT_testFneg");
    s3_services_simplejit_test_TestJIT_testDneg = resolveAddress("s3_services_simplejit_test_TestJIT_testDneg");
    s3_services_simplejit_test_TestJIT_testIshl = resolveAddress("s3_services_simplejit_test_TestJIT_testIshl");
    s3_services_simplejit_test_TestJIT_testLshl = resolveAddress("s3_services_simplejit_test_TestJIT_testLshl");
    s3_services_simplejit_test_TestJIT_testIshr = resolveAddress("s3_services_simplejit_test_TestJIT_testIshr");
    s3_services_simplejit_test_TestJIT_testLshr = resolveAddress("s3_services_simplejit_test_TestJIT_testLshr");
    s3_services_simplejit_test_TestJIT_testIushr = resolveAddress("s3_services_simplejit_test_TestJIT_testIushr");
    s3_services_simplejit_test_TestJIT_testLushr = resolveAddress("s3_services_simplejit_test_TestJIT_testLushr");
    s3_services_simplejit_test_TestJIT_testIand = resolveAddress("s3_services_simplejit_test_TestJIT_testIand");
    s3_services_simplejit_test_TestJIT_testLand = resolveAddress("s3_services_simplejit_test_TestJIT_testLand");
    s3_services_simplejit_test_TestJIT_testIor = resolveAddress("s3_services_simplejit_test_TestJIT_testIor");
    s3_services_simplejit_test_TestJIT_testLor = resolveAddress("s3_services_simplejit_test_TestJIT_testLor");
    s3_services_simplejit_test_TestJIT_testIxor = resolveAddress("s3_services_simplejit_test_TestJIT_testIxor");
    s3_services_simplejit_test_TestJIT_testLxor = resolveAddress("s3_services_simplejit_test_TestJIT_testLxor");
    s3_services_simplejit_test_TestJIT_testIinc = resolveAddress("s3_services_simplejit_test_TestJIT_testIinc");
    s3_services_simplejit_test_TestJIT_testI2l = resolveAddress("s3_services_simplejit_test_TestJIT_testI2l");
    s3_services_simplejit_test_TestJIT_testI2f = resolveAddress("s3_services_simplejit_test_TestJIT_testI2f");
    s3_services_simplejit_test_TestJIT_testI2d = resolveAddress("s3_services_simplejit_test_TestJIT_testI2d");
    s3_services_simplejit_test_TestJIT_testL2i = resolveAddress("s3_services_simplejit_test_TestJIT_testL2i");
    s3_services_simplejit_test_TestJIT_testL2f = resolveAddress("s3_services_simplejit_test_TestJIT_testL2f");
    s3_services_simplejit_test_TestJIT_testL2d = resolveAddress("s3_services_simplejit_test_TestJIT_testL2d");
    s3_services_simplejit_test_TestJIT_testF2i = resolveAddress("s3_services_simplejit_test_TestJIT_testF2i");
    s3_services_simplejit_test_TestJIT_testF2l = resolveAddress("s3_services_simplejit_test_TestJIT_testF2l");
    s3_services_simplejit_test_TestJIT_testF2d = resolveAddress("s3_services_simplejit_test_TestJIT_testF2d");
    s3_services_simplejit_test_TestJIT_testD2i = resolveAddress("s3_services_simplejit_test_TestJIT_testD2i");
    s3_services_simplejit_test_TestJIT_testD2l = resolveAddress("s3_services_simplejit_test_TestJIT_testD2l");
    s3_services_simplejit_test_TestJIT_testD2f = resolveAddress("s3_services_simplejit_test_TestJIT_testD2f");
    s3_services_simplejit_test_TestJIT_testI2b = resolveAddress("s3_services_simplejit_test_TestJIT_testI2b");
    s3_services_simplejit_test_TestJIT_testI2c = resolveAddress("s3_services_simplejit_test_TestJIT_testI2c");
    s3_services_simplejit_test_TestJIT_testI2s = resolveAddress("s3_services_simplejit_test_TestJIT_testI2s");
    s3_services_simplejit_test_TestJIT_testIfxx = resolveAddress("s3_services_simplejit_test_TestJIT_testIfxx");
    s3_services_simplejit_test_TestJIT_testIf_icmpxx = resolveAddress("s3_services_simplejit_test_TestJIT_testIf_icmpxx");
    s3_services_simplejit_test_TestJIT_testLcmp = resolveAddress("s3_services_simplejit_test_TestJIT_testLcmp");
    s3_services_simplejit_test_TestJIT_testFcmp = resolveAddress("s3_services_simplejit_test_TestJIT_testFcmp");
    s3_services_simplejit_test_TestJIT_testDcmp = resolveAddress("s3_services_simplejit_test_TestJIT_testDcmp");
    s3_services_simplejit_test_TestJIT_testJsr = resolveAddress("s3_services_simplejit_test_TestJIT_testJsr");
    s3_services_simplejit_test_TestJIT_testTableswitch = resolveAddress("s3_services_simplejit_test_TestJIT_testTableswitch");
    s3_services_simplejit_test_TestJIT_testLookupswitch = resolveAddress("s3_services_simplejit_test_TestJIT_testLookupswitch");
    s3_services_simplejit_test_TestJIT_testIfnull = resolveAddress("s3_services_simplejit_test_TestJIT_testIfnull");
    s3_services_simplejit_test_TestJIT_testIfnonnull = resolveAddress("s3_services_simplejit_test_TestJIT_testIfnonnull");
    s3_services_simplejit_test_TestJIT_testWide = resolveAddress("s3_services_simplejit_test_TestJIT_testWide");
    s3_services_simplejit_test_TestJIT_testGoto_wAndJsr_w = resolveAddress("s3_services_simplejit_test_TestJIT_testGoto_wAndJsr_w");
    s3_services_simplejit_test_TestJIT_testLdc = resolveAddress("s3_services_simplejit_test_TestJIT_testLdc");
    s3_services_simplejit_test_TestJIT_testLdc2_w = resolveAddress("s3_services_simplejit_test_TestJIT_testLdc2_w");
}

jint callI(jint (*method)() , int argSize);
jbyte callB(jbyte (*method)() , int argSize);
jshort callS(jshort (*method)() , int argSize);
jchar callC(jchar (*method)() , int argSize);
jfloat callF(jfloat (*method)() , int argSize);
jlong callJ(jlong (*method)() , int argSize);
jdouble callD(jdouble (*method)() , int argSize);

__asm__("
.text
    .align 4
    .type callI,@function
callI:
    push  %ebp
    mov   %esp, %ebp
    push  %edi
    push  %esi
    push  %ebx
    mov   0x8(%ebp), %eax
    push  $0
    push  $0
    call  *%eax
    popl  %eax
    pop   %ebx
    pop   %esi
    pop   %edi
    pop   %ebp
    ret

    .type callB,@function
callB:
    push  %ebp
    mov   %esp, %ebp
    push  %edi
    push  %esi
    push  %ebx
    mov   0x8(%ebp), %eax
    push  $0
    push  $0
    call  *%eax
    popl  %eax
    pop   %ebx
    pop   %esi
    pop   %edi
    pop   %ebp
    ret

    .type callS,@function
callS:
    push  %ebp
    mov   %esp, %ebp
    push  %edi
    push  %esi
    push  %ebx
    mov   0x8(%ebp), %eax
    push  $0
    push  $0
    call  *%eax
    popl  %eax
    pop   %ebx
    pop   %esi
    pop   %edi
    pop   %ebp
    ret

    .type callC,@function
callC:
    push  %ebp
    mov   %esp, %ebp
    push  %edi
    push  %esi
    push  %ebx
    mov   0x8(%ebp), %eax
    push  $0
    push  $0
    call  *%eax
    popl  %eax
    pop   %ebx
    pop   %esi
    pop   %edi
    pop   %ebp
    ret

    .type callF,@function
callF:
    push  %ebp
    mov   %esp, %ebp
    push  %edi
    push  %esi
    push  %ebx
    sub   $4, %esp
    mov   0x8(%ebp), %eax
    push  $0
    push  $0
    call  *%eax
    popl  -16(%ebp)
    flds  -16(%ebp)
    add   $4, %esp
    pop   %ebx
    pop   %esi
    pop   %edi
    pop   %ebp
    ret

    .type callD,@function
callD:
    push  %ebp
    mov   %esp, %ebp
    push  %edi
    push  %esi
    push  %ebx
    sub   $8, %esp
    mov   0x8(%ebp), %eax
    push  $0
    push  $0
    call  *%eax
    popl  -20(%ebp)
    popl  -16(%ebp)
    fldl  -20(%ebp)
    add   $8, %esp
    pop   %ebx
    pop   %esi
    pop   %edi
    pop   %ebp
    ret

    .type callJ,@function
callJ:
    push  %ebp
    mov   %esp, %ebp
    push  %edi
    push  %esi
    push  %ebx
    mov   0x8(%ebp), %eax
    push  $0
    push  $0
    call  *%eax
    popl  %eax
    popl  %edx
    pop   %ebx
    pop   %esi
    pop   %edi
    pop   %ebp
    ret

");


/*
jint callI(jint (*method)() , int argSize) {
    jint ret, dummy;
    __asm__ volatile ("push $0
                       push $0
                       push $0
                       call *%2
                       pop %0
                       pop %1" : 
		      "=m"(ret), "=m"(dummy) : 
		      "r"(method) :
		      "%ebx", "%esi", "%edi");
    return ret;
}    

jbyte callB(jbyte (*method)() , int argSize) {
    jint ret, dummy;
    __asm__ volatile ("push $0
                       push $0
                       call *%2
                       pop %0
                       pop %1" : 
		      "=m"(ret), "=m"(dummy) : 
		      "r"(method) :
		      "%ebx", "%esi", "%edi");
    return (jbyte)ret;
}    

jshort callS(jshort (*method)() , int argSize) {
    jint ret, dummy;
    __asm__ volatile ("push $0
                       push $0
                       call *%2
                       pop %0
                       pop %1" : 
		      "=m"(ret), "=m"(dummy) : 
		      "r"(method) :
		      "%ebx", "%esi", "%edi");
    return (jshort)ret;
}    

jchar callC(jchar (*method)() , int argSize) {
    jint ret, dummy;
    __asm__ volatile ("push $0
                       push $0
                       call *%2
                       pop %0
                       pop %1" : 
		      "=m"(ret), "=m"(dummy) : 
		      "r"(method) :
		      "%ebx", "%esi", "%edi");
    return (jchar)ret;
}    

jfloat callFxxx(jfloat (*method)(), int argSize) {
    jfloat ret, dummy;
    __asm__ volatile ("push $0
                       push $0
                       call *%2
                       pop %0
                       pop %1" : 
		      "=m"(ret), "=m"(dummy) : 
		      "r"(method) :
		      "%ebx", "%esi", "%edi");
    return ret;
}

jlong makeJLong(int h, int l) {
    int i;
    jlong bits = 0LL;
    for(i = 0; i < 32; i++) {
	if ((l & (1 << i)) != 0) {
	    bits |= (1LL << i);
	}
    }
    for(i = 0; i < 32; i++) {
	if ((h & (1 << i)) != 0) {
	    bits |= (1LL << (i + 32));
	}
    }
    return bits;
}

jdouble callDxxx(jdouble (*method)(), int argSize) {
    jdouble ret;
    int l, h;
    jlong bits;
    __asm__ volatile ("push $0
                       push $0
                       call *%2
                       pop %0
                       pop %1" : 
		      "=m"(l), "=m"(h) : 
		      "r"(method) :
		      "%ebx", "%esi", "%edi");
    bits = makeJLong(h, l);
    ret = *(jdouble*)&bits;
    return ret;
}

jlong callJxxx(jlong (*method)(), int argSize) {
    jlong ret;
    int l, h;
    __asm__ volatile ("push $0
                       push $0
                       call *%2
                       pop %0
                       pop %1" : 
		      "=m"(l), "=m"(h) : 
		      "r"(method):
		      "%ebx", "%esi", "%edi");
    ret = makeJLong(h, l);
    return ret;
}

*/

void testCompiledMethods() {
    assert(callI(s3_services_simplejit_test_TestJIT_testIreturn, 0) == 5, "testIreturn\n");
    assert(callJ(s3_services_simplejit_test_TestJIT_testLreturn, 0) == 1LL, "testLreturn\n");
    assert(callF(s3_services_simplejit_test_TestJIT_testFreturn, 0) == 1.0F, "testFreturn\n");
    assert(callD(s3_services_simplejit_test_TestJIT_testDreturn, 0) == 1.0, "testDreturn\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testIadd, 0) == 3, "testIadd\n");
    assert(callJ(s3_services_simplejit_test_TestJIT_testLadd, 0) == 2LL, "testLadd\n");
    assert(callF(s3_services_simplejit_test_TestJIT_testFadd, 0) == 3.0F, "testFadd\n");
    assert(callD(s3_services_simplejit_test_TestJIT_testDadd, 0) == 2.0, "testDadd\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testIsub, 0) == -3, "testIsub\n");
    assert(callJ(s3_services_simplejit_test_TestJIT_testLsub, 0) == 0LL, "testLsub\n");
    assert(callF(s3_services_simplejit_test_TestJIT_testFsub, 0) == 1.0F, "testFsub\n");
    assert(callD(s3_services_simplejit_test_TestJIT_testDsub, 0) == 1.0, "testDsub\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testImul, 0) == 150, "testImul\n");
    assert(callJ(s3_services_simplejit_test_TestJIT_testLmul, 0) == 1LL, "testLmul\n");
    assert(callF(s3_services_simplejit_test_TestJIT_testFmul, 0) == 2.0F, "testFmul\n");
    assert(callD(s3_services_simplejit_test_TestJIT_testDmul, 0) == 1.0, "testDmul\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testIdiv, 0) == 3, "testIdiv\n");
    assert(callF(s3_services_simplejit_test_TestJIT_testFdiv, 0) == 2.0F, "testFdiv\n");
    assert(callD(s3_services_simplejit_test_TestJIT_testDdiv, 0) == 1.0, "testDdiv\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testIrem, 0) == 3, "testIrem\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testIneg, 0) == -10, "testIneg\n");
    assert(callJ(s3_services_simplejit_test_TestJIT_testLneg, 0) == -1LL, "testLneg\n");
    assert(callF(s3_services_simplejit_test_TestJIT_testFneg, 0) == -2.0F, "testFneg\n");
    assert(callD(s3_services_simplejit_test_TestJIT_testDneg, 0) == -1.0, "testDneg\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testIshl, 0) == 1024, "testIshl\n");
    assert(callJ(s3_services_simplejit_test_TestJIT_testLshl, 0) == (1LL << 30), "testLshl\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testIshr, 0) == -1, "testIshr\n");
    assert(callJ(s3_services_simplejit_test_TestJIT_testLshr, 0) == -1LL, "testLshr\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testIushr, 0) == 1, "testIushr\n");
    assert(callJ(s3_services_simplejit_test_TestJIT_testLushr, 0) == 1LL, "testLushr\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testIand, 0) == 0x1230123, "testIand\n");
    assert(callJ(s3_services_simplejit_test_TestJIT_testLand, 0) == 0x8000000080000000LL, "testLand\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testIor, 0) == 0x9390939, "testIor\n");
    assert(callJ(s3_services_simplejit_test_TestJIT_testLor, 0) == 0x800c000080006000LL, "testLor\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testIxor, 0) == 0xEDC0EDC, "testIand\n");
    assert(callJ(s3_services_simplejit_test_TestJIT_testLxor, 0) == 0x000c000000006000LL, "testLand\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testIinc, 0) == 110, "testIinc\n");
    assert(callJ(s3_services_simplejit_test_TestJIT_testI2l, 0) == -1L, "testI2l\n");
    assert(callF(s3_services_simplejit_test_TestJIT_testI2f, 0) == 52.0F, "testI2f\n");
    assert(callD(s3_services_simplejit_test_TestJIT_testI2d, 0) == 14444.0, "testI2d\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testL2i, 0) == 1024, "testL2i\n");
    assert(callF(s3_services_simplejit_test_TestJIT_testL2f, 0) == 1024.0F, "testL2f\n");
    assert(callD(s3_services_simplejit_test_TestJIT_testL2d, 0) == 1024.0, "testL2d\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testF2i, 0) == 2, "testF2i\n");
    assert(callJ(s3_services_simplejit_test_TestJIT_testF2l, 0) == 2LL, "testF2l\n");
    assert(callD(s3_services_simplejit_test_TestJIT_testF2d, 0) == 2.0, "testF2d\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testD2i, 0) == 1, "testD2i\n");
    assert(callJ(s3_services_simplejit_test_TestJIT_testD2l, 0) == 1LL, "testD2l\n");
    assert(callF(s3_services_simplejit_test_TestJIT_testD2f, 0) == 1.0F, "testD2f\n");
    assert(callB(s3_services_simplejit_test_TestJIT_testI2b, 0) == (jbyte)0xFF, "testI2b\n");
    assert(callC(s3_services_simplejit_test_TestJIT_testI2c, 0) == (jchar)0xFFFF, "testI2c\n");
    assert(callS(s3_services_simplejit_test_TestJIT_testI2s, 0) == (jshort)0xFFFF, "testI2s\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testIfxx, 0) == 200, "testIfxx\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testIf_icmpxx, 0) == 200, "testIf_icmpxx\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testLcmp, 0) == 1, "testLcmp\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testFcmp, 0) == 1, "testLcmp\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testDcmp, 0) == 1, "testLcmp\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testJsr, 0) == 3, "testJsr\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testTableswitch, 0) == 2, "testTableswitch\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testLookupswitch, 0) == 100, "testLookupswitch\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testIfnull, 0) == 10, "testIfnull\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testIfnonnull, 0) == 10, "testIfnonnull\n");
    assert(callD(s3_services_simplejit_test_TestJIT_testWide, 0) == 8.0, "testWide\n");
    assert(s3_services_simplejit_test_TestJIT_testGoto_wAndJsr_w() == 2, "testGoto_wAndJsr_w\n");
    assert(callI(s3_services_simplejit_test_TestJIT_testLdc, 0) == 333333300/*333333333*/, "testLdc\n");
    assert(callJ(s3_services_simplejit_test_TestJIT_testLdc2_w, 0) == 333333300LL/*333333333LL*/, "testLdc2_w\n");
}

int main(int argc, char** argv) {
    if (argc != 3) {
	fprintf(stderr, "usage: testJIT [symbolfile] [codefile]\n");
	exit(1);
    }
    readSymbols(argv[1]);
    mapCompiledCode(argv[2]);
    resolveCompiledMethods();
    testCompiledMethods();

    return 0;
}
