📄 jopvm.c
字号:
/**
* jopvm.c
*
* nach Vorlage von Martin Schoeberls com.jopdesign.tools.JopSim
*
* Nils Hagge
*
*
* 2003-10-11 nh Erstelldatum
* 2003-12-05 ms ...
*/
#include <stdio.h>
#include <string.h>
#ifdef __nios__
#include "nios.h"
#else
#include <time.h>
#endif
#define STATISTICS(op) /* nichts */
#define DEBUG(op) /* op oder nichts */
#define MAX_MEM 200000
#define MAX_JAVA 16384
#define MAX_BC 1024
#define MAX_STACK 256
#define SYS_INT 0xf0
#ifdef INCJAVA
int prog[] = {
#include "java.bin"
};
#endif
int mem[MAX_MEM];
char bc[MAX_BC];
int stack[MAX_STACK];
int maxInstr, instrCnt;
int pc, cp, vp, sp, mp;
int heap, jjp, jjhp, moncnt;
//
// simulate timer interrupt
//
static int nextTimerInt;
static int intPend;
static int interrupt;
static int intEna;
struct
{
char *name;
int len;
enum { IMP_ASM, IMP_JAVA, IMP_NO } imp;
int cnt;
} jopInstruction[] =
{
{"nop", 1, IMP_ASM, 1}, /* 0x00 */
{"aconst_null", 1, IMP_JAVA, 1}, /* 0x01 */
{"iconst_m1", 1, IMP_ASM, 1}, // 0x02
{"iconst_0", 1, IMP_ASM, 1}, // 0x03
{"iconst_1", 1, IMP_ASM, 1}, // 0x04
{"iconst_2", 1, IMP_ASM, 1}, // 0x05
{"iconst_3", 1, IMP_ASM, 1}, // 0x06
{"iconst_4", 1, IMP_ASM, 1}, // 0x07
{"iconst_5", 1, IMP_ASM, 1}, // 0x08
{"lconst_0", 1, IMP_NO, 1}, // 0x09
{"lconst_1", 1, IMP_NO, 1}, // 0x0A
{"fconst_0", 1, IMP_NO, 1}, // 0x0B
{"fconst_1", 1, IMP_NO, 1}, // 0x0C
{"fconst_2", 1, IMP_NO, 1}, // 0x0D
{"dconst_0", 1, IMP_NO, 1}, // 0x0E
{"dconst_1", 1, IMP_NO, 1}, // 0x0F
{"bipush", 2, IMP_ASM, 2}, // 0x10
{"sipush", 3, IMP_ASM, 3}, // 0x11
{"ldc", 2, IMP_ASM, 2}, // 0x12
{"ldc_w", 3, IMP_NO, 1}, // 0x13
{"ldc2_w", 3, IMP_ASM, 1}, // 0x14
{"iload", 2, IMP_ASM, 2}, // 0x15
{"lload", 2, IMP_NO, 1}, // 0x16
{"fload", 2, IMP_NO, 1}, // 0x17
{"dload", 2, IMP_NO, 1}, // 0x18
{"aload", 2, IMP_ASM, 2}, // 0x19
{"iload_0", 1, IMP_ASM, 1}, // 0x1A
{"iload_1", 1, IMP_ASM, 1}, // 0x1B
{"iload_2", 1, IMP_ASM, 1}, // 0x1C
{"iload_3", 1, IMP_ASM, 1}, // 0x1D
{"lload_0", 1, IMP_NO, 1}, // 0x1E
{"lload_1", 1, IMP_NO, 1}, // 0x1F
{"lload_2", 1, IMP_NO, 1}, // 0x20
{"lload_3", 1, IMP_NO, 1}, // 0x21
{"fload_0", 1, IMP_NO, 1}, // 0x22
{"fload_1", 1, IMP_NO, 1}, // 0x23
{"fload_2", 1, IMP_NO, 1}, // 0x24
{"fload_3", 1, IMP_NO, 1}, // 0x25
{"dload_0", 1, IMP_NO, 1}, // 0x26
{"dload_1", 1, IMP_NO, 1}, // 0x27
{"dload_2", 1, IMP_NO, 1}, // 0x28
{"dload_3", 1, IMP_NO, 1}, // 0x29
{"aload_0", 1, IMP_ASM, 1}, // 0x2A
{"aload_1", 1, IMP_ASM, 1}, // 0x2B
{"aload_2", 1, IMP_ASM, 1}, // 0x2C
{"aload_3", 1, IMP_ASM, 1}, // 0x2D
{"iaload", 1, IMP_ASM, 17}, // 0x2E
{"laload", 1, IMP_NO, 1}, // 0x2F
{"faload", 1, IMP_NO, 1}, // 0x30
{"daload", 1, IMP_NO, 1}, // 0x31
{"aaload", 1, IMP_NO, 1}, // 0x32
{"baload", 1, IMP_NO, 1}, // 0x33
{"caload", 1, IMP_NO, 1}, // 0x34
{"saload", 1, IMP_NO, 1}, // 0x35
{"istore", 2, IMP_ASM, 2}, // 0x36
{"lstore", 2, IMP_NO, 1}, // 0x37
{"fstore", 2, IMP_NO, 1}, // 0x38
{"dstore", 2, IMP_NO, 1}, // 0x39
{"astore", 2, IMP_ASM, 2}, // 0x3A
{"istore_0", 1, IMP_ASM, 1}, // 0x3B
{"istore_1", 1, IMP_ASM, 1}, // 0x3C
{"istore_2", 1, IMP_ASM, 1}, // 0x3D
{"istore_3", 1, IMP_ASM, 1}, // 0x3E
{"lstore_0", 1, IMP_NO, 1}, // 0x3F
{"lstore_1", 1, IMP_NO, 1}, // 0x40
{"lstore_2", 1, IMP_NO, 1}, // 0x41
{"lstore_3", 1, IMP_NO, 1}, // 0x42
{"fstore_0", 1, IMP_NO, 1}, // 0x43
{"fstore_1", 1, IMP_NO, 1}, // 0x44
{"fstore_2", 1, IMP_NO, 1}, // 0x45
{"fstore_3", 1, IMP_NO, 1}, // 0x46
{"dstore_0", 1, IMP_NO, 1}, // 0x47
{"dstore_1", 1, IMP_NO, 1}, // 0x48
{"dstore_2", 1, IMP_NO, 1}, // 0x49
{"dstore_3", 1, IMP_NO, 1}, // 0x4A
{"astore_0", 1, IMP_ASM, 1}, // 0x4B
{"astore_1", 1, IMP_ASM, 1}, // 0x4C
{"astore_2", 1, IMP_ASM, 1}, // 0x4D
{"astore_3", 1, IMP_ASM, 1}, // 0x4E
{"iastore", 1, IMP_ASM, 18}, // 0x4F
{"lastore", 1, IMP_NO, 1}, // 0x50
{"fastore", 1, IMP_NO, 1}, // 0x51
{"dastore", 1, IMP_NO, 1}, // 0x52
{"aastore", 1, IMP_NO, 1}, // 0x53
{"bastore", 1, IMP_NO, 1}, // 0x54
{"castore", 1, IMP_NO, 1}, // 0x55
{"sastore", 1, IMP_NO, 1}, // 0x56
{"pop", 1, IMP_ASM, 1}, // 0x57
{"pop2", 1, IMP_NO, 1}, // 0x58
{"dup", 1, IMP_ASM, 1}, // 0x59
{"dup_x1", 1, IMP_NO, 1}, // 0x5A
{"dup_x2", 1, IMP_NO, 1}, // 0x5B
{"dup2", 1, IMP_ASM, 1}, // 0x5C
{"dup2_x1", 1, IMP_NO, 1}, // 0x5D
{"dup2_x2", 1, IMP_NO, 1}, // 0x5E
{"swap", 1, IMP_NO, 1}, // 0x5F
{"iadd", 1, IMP_ASM, 1}, // 0x60
{"ladd", 1, IMP_NO, 1}, // 0x61
{"fadd", 1, IMP_NO, 1}, // 0x62
{"dadd", 1, IMP_NO, 1}, // 0x63
{"isub", 1, IMP_ASM, 1}, // 0x64
{"lsub", 1, IMP_NO, 1}, // 0x65
{"fsub", 1, IMP_NO, 1}, // 0x66
{"dsub", 1, IMP_NO, 1}, // 0x67
{"imul", 1, IMP_ASM, 800}, // 0x68
{"lmul", 1, IMP_NO, 1}, // 0x69
{"fmul", 1, IMP_NO, 1}, // 0x6A
{"dmul", 1, IMP_NO, 1}, // 0x6B
{"idiv", 1, IMP_ASM, 1300}, // 0x6C
{"ldiv", 1, IMP_NO, 1}, // 0x6D
{"fdiv", 1, IMP_NO, 1}, // 0x6E
{"ddiv", 1, IMP_NO, 1}, // 0x6F
{"irem", 1, IMP_ASM, 1300}, // 0x70
{"lrem", 1, IMP_NO, 1}, // 0x71
{"frem", 1, IMP_NO, 1}, // 0x72
{"drem", 1, IMP_NO, 1}, // 0x73
{"ineg", 1, IMP_ASM, 4}, // 0x74
{"lneg", 1, IMP_NO, 1}, // 0x75
{"fneg", 1, IMP_NO, 1}, // 0x76
{"dneg", 1, IMP_NO, 1}, // 0x77
{"ishl", 1, IMP_ASM, 1}, // 0x78
{"lshl", 1, IMP_NO, 1}, // 0x79
{"ishr", 1, IMP_ASM, 1}, // 0x7A
{"lshr", 1, IMP_NO, 1}, // 0x7B
{"iushr", 1, IMP_ASM, 1}, // 0x7C
{"lushr", 1, IMP_NO, 1}, // 0x7D
{"iand", 1, IMP_ASM, 1}, // 0x7E
{"land", 1, IMP_NO, 1}, // 0x7F
{"ior", 1, IMP_ASM, 1}, // 0x80
{"lor", 1, IMP_NO, 1}, // 0x81
{"ixor", 1, IMP_ASM, 1}, // 0x82
{"lxor", 1, IMP_NO, 1}, // 0x83
{"iinc", 3, IMP_ASM, 11}, // 0x84
{"i2l", 1, IMP_NO, 1}, // 0x85
{"i2f", 1, IMP_NO, 1}, // 0x86
{"i2d", 1, IMP_NO, 1}, // 0x87
{"l2i", 1, IMP_NO, 1}, // 0x88
{"l2f", 1, IMP_NO, 1}, // 0x89
{"l2d", 1, IMP_NO, 1}, // 0x8A
{"f2i", 1, IMP_NO, 1}, // 0x8B
{"f2l", 1, IMP_NO, 1}, // 0x8C
{"f2d", 1, IMP_NO, 1}, // 0x8D
{"d2i", 1, IMP_NO, 1}, // 0x8E
{"d2l", 1, IMP_NO, 1}, // 0x8F
{"d2f", 1, IMP_NO, 1}, // 0x90
{"i2b", 1, IMP_NO, 1}, // 0x91
{"i2c", 1, IMP_ASM, 2}, // 0x92
{"i2s", 1, IMP_NO, 1}, // 0x93
{"lcmp", 1, IMP_NO, 1}, // 0x94
{"fcmpl", 1, IMP_NO, 1}, // 0x95
{"fcmpg", 1, IMP_NO, 1}, // 0x96
{"dcmpl", 1, IMP_NO, 1}, // 0x97
{"dcmpg", 1, IMP_NO, 1}, // 0x98
{"ifeq", 3, IMP_ASM, 4}, // 0x99
{"ifne", 3, IMP_ASM, 4}, // 0x9A
{"iflt", 3, IMP_ASM, 4}, // 0x9B
{"ifge", 3, IMP_ASM, 4}, // 0x9C
{"ifgt", 3, IMP_ASM, 4}, // 0x9D
{"ifle", 3, IMP_ASM, 4}, // 0x9E
{"if_icmpeq", 3, IMP_ASM, 4}, // 0x9F
{"if_icmpne", 3, IMP_ASM, 4}, // 0xA0
{"if_icmplt", 3, IMP_ASM, 4}, // 0xA1
{"if_icmpge", 3, IMP_ASM, 4}, // 0xA2
{"if_icmpgt", 3, IMP_ASM, 4}, // 0xA3
{"if_icmple", 3, IMP_ASM, 4}, // 0xA4
{"if_acmpeq", 3, IMP_ASM, 4}, // 0xA5
{"if_acmpne", 3, IMP_ASM, 4}, // 0xA6
{"goto", 3, IMP_ASM, 4}, // 0xA7
{"jsr", 3, IMP_NO, 1}, // 0xA8
{"ret", 2, IMP_NO, 1}, // 0xA9
{"tableswitch", 0, IMP_NO, 1}, // 0xAA
{"lookupswitch", 0, IMP_NO, 1}, // 0xAB
{"ireturn", 1, IMP_ASM, 12}, // 0xAC
{"lreturn", 1, IMP_NO, 1}, // 0xAD
{"freturn", 1, IMP_NO, 1}, // 0xAE
{"dreturn", 1, IMP_NO, 1}, // 0xAF
{"areturn", 1, IMP_ASM, 1}, // 0xB0
{"return", 1, IMP_ASM, 10}, // 0xB1
{"getstatic", 3, IMP_ASM, 11}, // 0xB2 // derzeit!!!
{"putstatic", 3, IMP_ASM, 11}, // 0xB3
{"getfield", 3, IMP_ASM, 30}, // 0xB4
{"putfield", 3, IMP_ASM, 30}, // 0xB5
{"invokevirtual", 3, IMP_ASM, 30}, // 0xB6
{"invokespecial", 3, IMP_ASM, 30}, // 0xB7
{"invokestatic", 3, IMP_ASM, 30}, // 0xB8 cnt ????
{"invokeinterface", 5, IMP_NO, 1}, // 0xB9
{"unused_ba", 1, IMP_NO, 1}, // 0xBA
{"new", 3, IMP_NO, 30}, // 0xBB
{"newarray", 2, IMP_ASM, 26}, // 0xBC // mit mem!!
{"anewarray", 3, IMP_NO, 1}, // 0xBD
{"arraylength", 1, IMP_ASM, 18}, // 0xBE // mit mem!!
{"athrow", 1, IMP_NO, 1}, // 0xBF
{"checkcast", 3, IMP_NO, 1}, // 0xC0
{"instanceof", 3, IMP_NO, 1}, // 0xC1
{"monitorenter", 1, IMP_NO, 1}, // 0xC2
{"monitorexit", 1, IMP_NO, 1}, // 0xC3
{"wide", 0, IMP_NO, 1}, // 0xC4
{"multianewarray", 4, IMP_NO, 1}, // 0xC5
{"ifnull", 3, IMP_NO, 1}, // 0xC6
{"ifnonnull", 3, IMP_NO, 1}, // 0xC7
{"goto_w", 5, IMP_NO, 1}, // 0xC8
{"jsr_w", 5, IMP_NO, 1}, // 0xC9
{"breakpoint", 1, IMP_NO, 1}, // 0xCA
/**
* reserved instructions
*/
{"resCB", 1, IMP_NO, 1}, // 0xCB
{"resCC", 1, IMP_NO, 1}, // 0xCC
{"resCD", 1, IMP_NO, 1}, // 0xCD
{"resCE", 1, IMP_NO, 1}, // 0xCE
{"resCF", 1, IMP_NO, 1}, // 0xCF
{"jopsys_null", 1, IMP_NO, 1}, // 0xD0
{"jopsys_rd", 1, IMP_ASM, 3}, // 0xD1
{"jopsys_wr", 1, IMP_ASM, 3}, // 0xD2
{"jopsys_rdmem", 1, IMP_ASM, 15}, // 0xD3
{"jopsys_wrmem", 1, IMP_ASM, 15}, // 0xD4
{"jopsys_rdint", 1, IMP_ASM, 8}, // 0xD5
{"jopsys_wrint", 1, IMP_ASM, 8}, // 0xD6
{"jopsys_getsp", 1, IMP_ASM, 3}, // 0xD7
{"jopsys_setsp", 1, IMP_ASM, 4}, // 0xD8
{"jopsys_getvp", 1, IMP_ASM, 1}, // 0xD9
{"jopsys_setvp", 1, IMP_ASM, 2}, // 0xDA
{"jopsys_int2ext", 1, IMP_ASM, 100}, // 0xDB
{"jopsys_ext2int", 1, IMP_ASM, 100}, // 0xDC
{"resDD", 1, IMP_NO, 1}, // 0xDD
{"resDE", 1, IMP_NO, 1}, // 0xDE
{"resDF", 1, IMP_NO, 1}, // 0xDF
{"resE0", 1, IMP_NO, 1}, // 0xE0
{"resE1", 1, IMP_NO, 1}, // 0xE1
{"resE2", 1, IMP_NO, 1}, // 0xE2
{"resE3", 1, IMP_NO, 1}, // 0xE3
{"resE4", 1, IMP_NO, 1}, // 0xE4
{"resE5", 1, IMP_NO, 1}, // 0xE5
{"resE6", 1, IMP_NO, 1}, // 0xE6
{"resE7", 1, IMP_NO, 1}, // 0xE7
{"resE8", 1, IMP_NO, 1}, // 0xE8
{"resE9", 1, IMP_NO, 1}, // 0xE9
{"resEA", 1, IMP_NO, 1}, // 0xEA
{"resEB", 1, IMP_NO, 1}, // 0xEB
{"resEC", 1, IMP_NO, 1}, // 0xEC
{"resED", 1, IMP_NO, 1}, // 0xED
{"resEE", 1, IMP_NO, 1}, // 0xEE
{"resEF", 1, IMP_NO, 1}, // 0xEF
{"sys_int", 1, IMP_ASM, 1}, // 0xF0
{"resF1", 1, IMP_NO, 1}, // 0xF1
{"resF2", 1, IMP_NO, 1}, // 0xF2
{"resF3", 1, IMP_NO, 1}, // 0xF3
{"resF4", 1, IMP_NO, 1}, // 0xF4
{"resF5", 1, IMP_NO, 1}, // 0xF5
{"resF6", 1, IMP_NO, 1}, // 0xF6
{"resF7", 1, IMP_NO, 1}, // 0xF7
{"resF8", 1, IMP_NO, 1}, // 0xF8
{"resF9", 1, IMP_NO, 1}, // 0xF9
{"resFA", 1, IMP_NO, 1}, // 0xFA
{"resFB", 1, IMP_NO, 1}, // 0xFB
{"resFC", 1, IMP_NO, 1}, // 0xFC
{"resFD", 1, IMP_NO, 1}, // 0xFD
{"sys_noim", 1, IMP_ASM, 1}, /* 0xFE */
{"sys_init", 1, IMP_ASM, 1} /* 0xFF */
};
int readMem(int addr)
{
STATISTICS(rdMemCnt++;)
STATISTICS(ioCnt += 12;)
if(!(0 <= addr && addr <= heap)) /* <= nicht < aber warum? */
printf("wrong read address %d (max %d).\n", addr, heap), exit(1);
return mem[addr];
}
void writeMem(int addr, int data)
{
STATISTICS(wrMemCnt++;)
STATISTICS(ioCnt += 12;)
if(!(0 <= addr && addr <= heap))
printf("wrong write address %d (max %d).\n", addr, heap), exit(1);
mem[addr] = data;
}
void invokestaticAddr(int);
void init(char *filename)
{
int ptr;
int i;
long l;
#ifndef INCJAVA
FILE *fp;
#endif
char buf[10000];
char *tok;
heap = 0;
moncnt = 1;
#ifdef INCJAVA
for (heap=0; heap<(sizeof(prog)/sizeof(int)); ++heap) {
mem[heap] = prog[heap];
}
#else
if ((fp=fopen(filename,"r"))==NULL) {
printf("Error opening %s\n", filename);
exit(-1);
}
while (fgets(buf, sizeof(buf), fp)!=NULL) {
for (i=0; i<strlen(buf); ++i) {
if (buf[i]=='/') {
buf[i]=0;
break;
}
}
tok = strtok(buf, " ,\t");
while (tok!=NULL) {
if (sscanf(tok, "%ld", &l)==1) {
mem[heap++] = l;
}
tok = strtok(NULL, " ,\t");
if (heap>=MAX_JAVA) {
printf("too many words (%d/%d)\n", heap, MAX_JAVA);
exit(-1);
}
}
}
fclose(fp);
#endif
printf("%d words of byte code (%d KB)\n", mem[0], mem[0]/256);
printf("%d words extern ram (%d KB)\n", heap, heap/256);
#ifndef __nios__
printf("This machine runns at %d MHz\n", getMHz());
#endif
printf("\n");
nextTimerInt = 0;
intPend = 0;
interrupt = 0;
intEna = 0;
pc = vp = 0;
sp = 128;
maxInstr = instrCnt = 0;
ptr = readMem(0);
jjp = readMem(ptr + 1);
jjhp = readMem(ptr + 2);
invokestaticAddr(ptr);
}
void loadBc(int start, int len)
{
/* high byte of word is first bc */
int i;
for(i = 0; i < len; ++i)
{
unsigned int val = readMem(start+i);
int j;
for(j = 0; j < 4; ++j)
{
bc[i * 4 + (3 - j)] = val;
val >>= 8;
}
}
STATISTICS(rdBcCnt += len;)
STATISTICS(simCach(start, len);)
}
void invoke(int new_mp)
{
int old_vp = vp;
int old_cp = cp;
int old_mp = mp;
int start, len, locals, args, old_sp;
mp = new_mp;
start = readMem(mp);
len = start & 0x03ff;
start = (unsigned int) start >> 10;
cp = readMem(mp + 1);
locals = ((unsigned int) cp >> 5) & 0x01f;
args = cp & 0x01f;
cp = (unsigned int) cp >> 10;
old_sp = sp - args;
vp = old_sp+1;
sp += locals;
// System.out.println("inv: start: "+start+" len: "+len+" locals: "+locals+" args: "+args+" cp: "+cp);
stack[++sp] = old_sp;
stack[++sp] = pc;
stack[++sp] = old_vp;
stack[++sp] = old_cp;
stack[++sp] = old_mp;
loadBc(start, len);
pc = 0;
}
void noim(int instr)
{
/*
printf("Bytecode %s nicht implementiert (mp = %d, pc = %d)\n",
jopInstruction[instr].name, mp, pc);
*/
invoke(jjp + (instr << 1));
}
/**
* call function in JVM.java with constant on stack
*/
int readOpd16u();
void jjvmConst(int instr)
{
int idx = readOpd16u();
int val = readMem(cp+idx); /* read constant */
stack[++sp] = val; /* push on stack */
invoke(jjp+(instr<<1));
}
void dump()
{
printf("vp = %d, sp = %d, pc = %d, Stack=[..., %d, %d, %d]\n",
vp, sp, pc, stack[sp-2], stack[sp-1], stack[sp]);
}
int readOpd16u()
{
int idx;
STATISTICS(instrBytesCnt += 2;)
idx = ((bc[pc] << 8) | (bc[pc + 1] & 255)) & 0xFFFF;
pc += 2;
return idx;
}
int readOpd16s()
{
int i = readOpd16u();
if(i & 0x8000)
i |= 0xFFFF0000;
return i;
}
int readOpd8s()
{
STATISTICS(instrBytes++;)
return bc[pc++];
}
int readOpd8u()
{
STATISTICS(instrBytes++;)
return bc[pc++];
}
/*
public static final int IO_CNT = 0;
public static final int IO_INT_ENA = 0;
public static final int IO_US_CNT = 1;
public static final int IO_TIMER = 1;
public static final int IO_SWINT = 2;
public static final int IO_WD = 3;
public static final int IO_STATUS = 4;
public static final int IO_UART = 5;
*/
#define Native_IO_CNT 0
#define Native_IO_INT_ENA 0
#define Native_IO_US_CNT 1
#define Native_IO_TIMER 1
#define Native_IO_SWINT 2
#define Native_IO_WD 3
#define Native_IO_STATUS 4
#define Native_IO_UART 5
#ifdef __nios__
int usCnt() {
return na_mhz_counter->np_cnt_val;
}
#else
#ifdef _MSC_VER
_int64 readTSC (void)
{
_int64 t;
unsigned int a,b;
unsigned int *c = (unsigned int *)&t;
_asm {
_emit 0x0f;
_emit 0x31;
mov a,eax;
mov b,edx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -