/* This file is part of JOP, the Java Optimized Processor see <http://www.jopdesign.com/> Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * Created on 24.05.2004 * * To change the template for this generated file go to * Window>Preferences>Java>Code Generation>Code and Comments */ package com.jopdesign.sys; /** * @author Martin martin@jopdesign.com * * Starup code and very simple JVM interpreter for large <clinit> * methods. */ public class Startup { // use static vars, don't waste stack space static int var; /** Size of main memory in 32-bit words */ static int mem_size; /** Size of scratchpad memory in 32-bit words */ static int spm_size; // a stack for the interpreter mode static int[] stack; final static int MAX_STACK = 100; static int sp, pc, cp; /** * How needs this field, and why? */ static boolean started; /** * The start method for CPU 1 to n-1. * * Public just for a quick test. */ static Runnable[] cpuStart = new Runnable[Native.rdMem(Const.IO_CPUCNT)-1]; /** * called from jvm.asm as first method. * Do all initialization here and call main method. */ static void boot() { // use local variable - statics are not CMP save! int val; // disable all interrupts locally // global enable and disable on monitorenter/exit don't hurt Native.wr(0, Const.IO_INTMASK); // only CPU 0 does the initialization stuff if (Native.rdMem(Const.IO_CPU_ID) == 0) { started = false; msg(); spm_size = getRamSize(Const.SCRATCHPAD_ADDRESS); mem_size = getRamSize(0); // mem(0) is the length of the application // or in other words the heap start val = Native.rdMem(1); // pointer to 'special' pointers // first initialize the GC with the address of static ref. fields GC.init(mem_size, val+4); // place for some initialization: // could be placed in <clinit> in the future // System.init(); version(); started = true; clazzinit(); // not in <clinit> as first methods are special and palcement // of <clinit> depends on compiler JVMHelp.init(); } // clear all pending interrupts (e.g. timer after reset) Native.wr(1, Const.IO_INTCLEARALL); // set global enable Native.wr(1, Const.IO_INT_ENA); // reset any performance counter Native.wr(-1, Const.IO_PERFCNT); // request CPU id val = Native.rdMem(Const.IO_CPU_ID); if (val==0) { // only CPU 0 invokes main() val = Native.rdMem(1); // pointer to 'special' pointers val = Native.rdMem(val+3); // pointer to main method structure Native.invoke(0, val); // call main (with null pointer on TOS exit(); } else { // other CPUs invoke a Runnable if (cpuStart[val-1]!=null) { cpuStart[val-1].run(); } for (;;) { ; // busy loop for other CPUs exit } } } static void msg() { JVMHelp.wr("JOP start"); } /** * Add a Runnable for the other CPUs * @param r * @param index */ public static void setRunnable(Runnable r, int index) { cpuStart[index] = r; } /** * @return RAM size in 32 bit words */ static int getRamSize(int offset) { // change for DE2-70 VGA board // int size = 0x0078500; // adresses for JOP - after this memory for vga int size = 0; int firstWord = Native.rd(offset+0); int val; // increment in 512 Bytes for (size=0; ; size+=128) { val = Native.rd(offset+size); Native.wr(0xaaaa5555, offset+size); if (Native.rd(offset+size)!=0xaaaa5555) break; Native.wr(0x12345678, offset+size); if (Native.rd(offset+size)!=0x12345678) break; if (size!=0) { // invalidate cache Native.invalidate(); if (Native.rd(offset+0)!=firstWord) break; } // restore current word Native.wr(val, offset+size); } // restore the first word Native.wr(firstWord, offset+0); return size; } /** * @return Processor speed in MHz */ static int getSpeed() { int start=0, end=0; int val = Native.rd(Const.IO_US_CNT) + 5; while (Native.rd(Const.IO_US_CNT)-val<0) { ; } start = Native.rd(Const.IO_CNT); val += 32; // wait 32 us while (Native.rd(Const.IO_US_CNT)-val<0) { ; } end = Native.rd(Const.IO_CNT); // round and divide by 32 return (end-start+16)>>5; } static void version() { // BTW: why not using System.out.println()? int version = Native.rdIntMem(64-2); if (version==0x12345678) { // not in the new location, try the old one version = Native.rdIntMem(64); } JVMHelp.wr(" V "); // take care with future GC - JVMHelp.intVal allocates // a buffer! if (version==0x12345678) { JVMHelp.wr("pre2005"); } else { JVMHelp.intVal(version); } JVMHelp.wr("\r\n"); int speed = getSpeed(); JVMHelp.intVal(speed); JVMHelp.wr("MHz, "); JVMHelp.intVal(mem_size/1024*4); JVMHelp.wr("KB RAM"); if (spm_size!=0) { JVMHelp.wr(", "); JVMHelp.intVal(spm_size*4); JVMHelp.wr("Byte on-chip RAM"); } JVMHelp.wr(", "); JVMHelp.intVal(Native.rdMem(Const.IO_CPUCNT)); JVMHelp.wr("CPUs"); JVMHelp.wr("\r\n"); } public static void exit() { for (;RtThreadImpl.mission;) { RtThreadImpl.sleepMs(1000); } JVMHelp.wr("\r\nJVM exit!\r\n"); synchronized (stack) { for (;;) ; } } public static int getSPMSize() { return spm_size*4; } static void clazzinit() { stack = new int[MAX_STACK]; int table = Native.rdMem(1)+6; // start of clinit table int cnt = Native.rdMem(table); // number of methods ++table; for (int i=0; i<cnt; ++i) { int addr = Native.rdMem(table+i); // System.out.print("<clinit> "); // System.out.println(addr); // reuse static var for var = Native.rdMem(addr); int len = var & 0x03ff; var >>>= 10; cp = Native.rdMem(addr+1); // int locals = (cp>>>5) & 0x01f; // int args = cp & 0x01f; cp >>>= 10; // System.out.print("start="); // System.out.println(var); // System.out.println("len="); // System.out.println(len); if (len<256 && len!=0) { // see JOPizer constant on max. method length Native.invoke(addr); // len=0 means interpret it } else { interpret(); } } } // start address is in var static void interpret() { pc = 0; sp = 0; int instr, val, idx; for (;;) { // System.out.print(pc); instr = readBC8u(); // System.out.print(" "); // System.out.println(instr); switch (instr) { case 0 : // nop break; case 1 : // aconst_null stack[++sp] = 0; break; case 2 : // iconst_m1 stack[++sp] = -1; break; case 3 : // iconst_0 stack[++sp] = 0; break; case 4 : // iconst_1 stack[++sp] = 1; break; case 5 : // iconst_2 stack[++sp] = 2; break; case 6 : // iconst_3 stack[++sp] = 3; break; case 7 : // iconst_4 stack[++sp] = 4; break; case 8 : // iconst_5 stack[++sp] = 5; break; case 9 : // lconst_0 stack[++sp] = 0; stack[++sp] = 0; break; case 10 : // lconst_1 stack[++sp] = 0; stack[++sp] = 1; break; case 11 : // fconst_0 stack[++sp] = 0; break; case 12 : // fconst_1 stack[++sp] = 0x3f800000; break; case 13 : // fconst_2 stack[++sp] = 0x40000000; break; case 14 : // dconst_0 stack[++sp] = 0; stack[++sp] = 0; break; case 15 : // dconst_1 stack[++sp] = 0x3ff00000; stack[++sp] = 0x00000000; break; case 16 : // bipush stack[++sp] = readBC8s(); break; case 17 : // sipush stack[++sp] = readBC16s(); break; case 18 : // ldc stack[++sp] = Native.rdMem(cp+readBC8u()); break; case 19 : // ldc_w stack[++sp] = Native.rdMem(cp+readBC16u()); break; case 20 : // ldc2_w idx = readBC16u(); stack[++sp] = Native.rdMem(cp+idx); stack[++sp] = Native.rdMem(cp+idx+1); break; case 83 : // aastore case 84 : // bastore case 85 : // castore case 81 : // fastore case 79 : // iastore case 86 : // sastore xastore(); break; case 80 : // lastore case 82 : // dastore x2astore(); break; case 89 : // dup val = stack[sp]; stack[++sp] = val; break; case 177 : // return return; case 178 : // getstatic case 224 : // getstatic_ref getstatic(); break; case 179 : // putstatic case 225 : // putstatic_ref, no concurrent GC during <clinit>! putstatic(); break; // GETFIELD/PUTFIELD does not make sense without NEW // case 180 : // getfield // getfield(); // break; // case 181 : // putfield // case 227 : // putfield_ref, no concurrent GC during <clinit>! // putfield(); // break; // NEW does not make sense without INVOKESPECIAL // case 187 : // new // newobj(); // break; case 188 : // newarray newarray(); break; case 189 : // anewarray anewarray(); break; case 190 : // arraylength arraylength(); break; case 221 : // jopsys_nop break; default: System.out.print("JVM interpreter: bytecode "); System.out.print(instr); System.out.println(" not implemented"); for (;;); } } } static int readBC8u() { int val = Native.rdMem(var + (pc>>2)); val >>= (3-(pc&0x03))<<3; val &= 0xff; ++pc; return val; } static byte readBC8s() { int val = Native.rdMem(var + (pc>>2)); val >>= (3-(pc&0x03))<<3; ++pc; return (byte) val; } static short readBC16s() { short val = readBC8s(); val <<= 8; val |= readBC8s() & 0x0ff; return val; } static int readBC16u() { int idx = readBC16s(); return idx & 0xffff; } static void xastore() { int val = stack[sp--]; // value int idx = stack[sp--]; // index int ref = stack[sp--]; // ref // handle: ref = Native.rdMem(ref); Native.wrMem(val, ref+idx); } static void x2astore() { int val = stack[sp--]; // value int val2 = stack[sp--]; // value2 int idx = stack[sp--] << 1; // index int ref = stack[sp--]; // ref // handle: ref = Native.rdMem(ref); Native.wrMem(val2, ref+idx); Native.wrMem(val, ref+idx+1); } static void putstatic() { int addr = readBC16u(); Native.putStatic(stack[sp--], addr); } static void getstatic() { int addr = readBC16u(); stack[++sp] = Native.getStatic(addr); } static void putfield() { int off = readBC16u(); int val = stack[sp--]; int ref = stack[sp--]; Native.putField(ref, off, val); } static void getfield() { int off = readBC16u(); int ref = stack[sp]; stack[sp] = Native.getField(ref, off); } static void newobj() { int type = readBC16u(); // use typ stack[++sp] = JVM.f_new(type); } static void newarray() { int type = readBC8u(); // use typ int val = stack[sp]; // count from stack stack[sp] = JVM.f_newarray(val, type); } static void anewarray() { int cons = readBC16u(); int val = stack[sp]; // count from stack stack[sp] = JVM.f_anewarray(val, cons); } static void arraylength() { int ref = stack[sp]; stack[sp] = Native.arrayLength(ref); } }