/* 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/>. */ package com.jopdesign.sys; class JVM { private static void f_nop() { JVMHelp.noim(); /* jvm.asm */ } private static void f_aconst_null() { JVMHelp.noim(); /* jvm.asm */ } private static void f_iconst_m1() { JVMHelp.noim(); /* jvm.asm */ } private static void f_iconst_0() { JVMHelp.noim(); /* jvm.asm */ } private static void f_iconst_1() { JVMHelp.noim(); /* jvm.asm */ } private static void f_iconst_2() { JVMHelp.noim(); /* jvm.asm */ } private static void f_iconst_3() { JVMHelp.noim(); /* jvm.asm */ } private static void f_iconst_4() { JVMHelp.noim(); /* jvm.asm */ } private static void f_iconst_5() { JVMHelp.noim(); /* jvm.asm */ } private static void f_lconst_0() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_lconst_1() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_fconst_0() { JVMHelp.noim(); /* jvm.asm */ } private static int f_fconst_1() { return 0x3f800000; } private static int f_fconst_2() { return 0x40000000; } private static void f_dconst_0() { JVMHelp.noim(); /* jvm_long.inc */ } private static long f_dconst_1() { return 0x3ff0000000000000L; } private static void f_bipush() { JVMHelp.noim(); /* jvm.asm */ } private static void f_sipush() { JVMHelp.noim(); /* jvm.asm */ } private static void f_ldc() { JVMHelp.noim(); /* jvm.asm */ } private static void f_ldc_w() { JVMHelp.noim();} private static void f_ldc2_w() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_iload() { JVMHelp.noim(); /* jvm.asm */ } private static void f_lload() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_fload() { JVMHelp.noim();} private static void f_dload() { JVMHelp.noim();} private static void f_aload() { JVMHelp.noim(); /* jvm.asm */ } private static void f_iload_0() { JVMHelp.noim(); /* jvm.asm */ } private static void f_iload_1() { JVMHelp.noim(); /* jvm.asm */ } private static void f_iload_2() { JVMHelp.noim(); /* jvm.asm */ } private static void f_iload_3() { JVMHelp.noim(); /* jvm.asm */ } private static void f_lload_0() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_lload_1() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_lload_2() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_lload_3() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_fload_0() { JVMHelp.noim();} private static void f_fload_1() { JVMHelp.noim();} private static void f_fload_2() { JVMHelp.noim();} private static void f_fload_3() { JVMHelp.noim();} private static void f_dload_0() { JVMHelp.noim();} private static void f_dload_1() { JVMHelp.noim();} private static void f_dload_2() { JVMHelp.noim();} private static void f_dload_3() { JVMHelp.noim();} private static void f_aload_0() { JVMHelp.noim(); /* jvm.asm */ } private static void f_aload_1() { JVMHelp.noim(); /* jvm.asm */ } private static void f_aload_2() { JVMHelp.noim(); /* jvm.asm */ } private static void f_aload_3() { JVMHelp.noim(); /* jvm.asm */ } private static void f_iaload() { JVMHelp.noim(); /* jvm.asm */ } private static void f_laload() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_faload() { JVMHelp.noim(); /* jvm.asm */ } private static void f_daload() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_aaload() { JVMHelp.noim(); /* jvm.asm */ } private static void f_baload() { JVMHelp.noim(); /* jvm.asm */ } private static void f_caload() { JVMHelp.noim(); /* jvm.asm */ } private static void f_saload() { JVMHelp.noim(); /* jvm.asm */ } private static void f_istore() { JVMHelp.noim(); /* jvm.asm */ } private static void f_lstore() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_fstore() { JVMHelp.noim();} private static void f_dstore() { JVMHelp.noim();} private static void f_astore() { JVMHelp.noim(); /* jvm.asm */ } private static void f_istore_0() { JVMHelp.noim(); /* jvm.asm */ } private static void f_istore_1() { JVMHelp.noim(); /* jvm.asm */ } private static void f_istore_2() { JVMHelp.noim(); /* jvm.asm */ } private static void f_istore_3() { JVMHelp.noim(); /* jvm.asm */ } private static void f_lstore_0() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_lstore_1() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_lstore_2() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_lstore_3() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_fstore_0() { JVMHelp.noim();} private static void f_fstore_1() { JVMHelp.noim();} private static void f_fstore_2() { JVMHelp.noim();} private static void f_fstore_3() { JVMHelp.noim();} private static void f_dstore_0() { JVMHelp.noim();} private static void f_dstore_1() { JVMHelp.noim();} private static void f_dstore_2() { JVMHelp.noim();} private static void f_dstore_3() { JVMHelp.noim();} private static void f_astore_0() { JVMHelp.noim(); /* jvm.asm */ } private static void f_astore_1() { JVMHelp.noim(); /* jvm.asm */ } private static void f_astore_2() { JVMHelp.noim(); /* jvm.asm */ } private static void f_astore_3() { JVMHelp.noim(); /* jvm.asm */ } private static void f_iastore() { JVMHelp.noim(); /* jvm.asm */ } private static void f_lastore() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_fastore() { JVMHelp.noim(); /* jvm.asm */ } private static void f_dastore() { JVMHelp.noim(); /* jvm_long.inc */ } private static void f_aastore(int ref, int index, int value) { synchronized (GC.mutex) { if (Config.USE_SCOPES) { if (Config.USE_SCOPECHECKS){ // Pointer version // if ((value >>> 25) > (ref >>> 25)){ // GC.log("Illegal array reference"); // } // Handler version (default) int ref_level; int val_level; ref_level = Native.rdMem(ref + GC.OFF_SPACE); val_level = Native.rdMem(value + GC.OFF_SPACE); if (val_level > ref_level){ GC.log("Illegal array reference"); }; } } else { // snapshot-at-beginning barrier int oldVal = Native.arrayLoad(ref, index); // Is it white? if (oldVal != 0 && Native.rdMem(oldVal+GC.OFF_SPACE) != GC.toSpace && Native.rdMem(oldVal+GC.OFF_GREY)==0) { // Mark grey Native.wrMem(GC.grayList, oldVal+GC.OFF_GREY); GC.grayList = oldVal; } } Native.arrayStore(ref, index, value); } } private static void f_bastore() { JVMHelp.noim();} private static void f_castore() { JVMHelp.noim();} private static void f_sastore() { JVMHelp.noim();} private static void f_pop() { JVMHelp.noim(); /* jvm.asm */ } private static void f_pop2() { JVMHelp.noim();} private static void f_dup() { JVMHelp.noim(); /* jvm.asm */ } private static void f_dup_x1() { JVMHelp.noim();} private static void f_dup_x2() { JVMHelp.noim();} private static void f_dup2() { JVMHelp.noim(); /* jvm.asm */ } private static void f_dup2_x1() { JVMHelp.noim();} private static void f_dup2_x2() { JVMHelp.noim();} private static void f_swap() { JVMHelp.noim();} private static void f_iadd() { JVMHelp.noim(); /* jvm.asm */ } private static long f_ladd(int ah, int al, int bh, int bl) { int carry = ((al>>>1) + (bl>>>1) + (al & bl & 1)) >>> 31; return Native.makeLong(ah+bh+carry, al+bl); } private static int f_fadd(int a, int b) { if (Const.SUPPORT_FLOAT) { return SoftFloat32.float_add(a, b); } else { JVMHelp.noim(); return 0; } } private static long f_dadd(long a, long b) { if (Const.SUPPORT_DOUBLE) { return SoftFloat64.double_add(a, b); } else { JVMHelp.noim(); return 0; } } private static void f_isub() { JVMHelp.noim(); /* jvm.asm */ } private static long f_lsub(long a, long b) { return a + (~b) + 1; } private static int f_fsub(int a, int b) { if (Const.SUPPORT_FLOAT) { return SoftFloat32.float_sub(a, b); } else { JVMHelp.noim(); return 0; } } private static long f_dsub( long a, long b) { if (Const.SUPPORT_DOUBLE) { return SoftFloat64.double_sub(a, b); } else { JVMHelp.noim(); return 0; } } private static void f_imul() { JVMHelp.noim(); /* jvm.asm */ } private static long f_lmul(long a, long b) { boolean positive = true; if(a<0) { a = -a; positive = false; } if(b<0) { b = -b; positive = !positive; } long aa = a; long res = 0; for(int i=0;i<64;i=i+8) // @WCA loop=8 { long bb = b; int am = ((int)aa) & 0x000000FF; for(int j=0;j<64;j=j+8) // @WCA loop=8 { int bm = ((int)bb) & 0x000000FF; long sres = 0; if (i+j < 64) sres = Native.makeLong(0,am*bm) << (i+j); res += sres; bb = bb>>>8; } aa = aa>>>8; } if(!positive) res = -res; return res; } private static int f_fmul(int a, int b) { if (Const.SUPPORT_FLOAT) { return SoftFloat32.float_mul(a, b); } else { JVMHelp.noim(); return 0; } } private static long f_dmul(long a, long b) { if (Const.SUPPORT_DOUBLE) { return SoftFloat64.double_mul(a, b); } else { JVMHelp.noim(); return 0; } } private static int f_idiv(int a, int b) { if (b==0) { // division by zero exception Native.wrMem(Const.EXC_DIVZ, Const.IO_EXCPT); return 0; } if(b==0x80000000) { if(a==0x80000000) return 1; else return 0; } boolean neg = false; if (a<0) { neg = true; a = -a; } if (b<0) { neg = !neg; b = -b; } int c = 0; int r = 0; for (int i=0; i<32; ++i) { // @WCA loop=32 c <<= 1; r <<= 1; if (a < 0) { r |= 1; } a <<= 1; if (r>=b) { r -= b; c |= 1; } } if (neg) { c = -c; } return c; } private static long f_ldiv(long a, long b) { if (b==0) { // division by zero exception Native.wrMem(Const.EXC_DIVZ, Const.IO_EXCPT); return 0; } if(b==0x8000000000000000L) { if(a==0x8000000000000000L) return 1; else return 0; } boolean neg = false; if (a<0) { neg = true; a = -a; } if (b<0) { neg = !neg; b = -b; } long c = 0; long r = 0; for (int i=0; i<64; ++i) { // @WCA loop=64 c <<= 1; r <<= 1; if (a < 0) { r |= 1; } a <<= 1; if ((r-1)>=(b-1)) //over/underflow problem - other testcases?? { r -= b; c |= 1; } // System.out.println("c="+((int)(c>>32))+" "+((int)c)); // System.out.println("r="+((int)(r>>32))+" "+((int)r)); } if (neg) { c = -c; } return c; } private static int f_fdiv(int a, int b) { if (Const.SUPPORT_FLOAT) { return SoftFloat32.float_div(a, b); } else { JVMHelp.noim(); return 0; } } private static long f_ddiv(long a, long b) { if (Const.SUPPORT_DOUBLE) { return SoftFloat64.double_div(a, b); } else { JVMHelp.noim(); return 0; } } private static int f_irem(int a, int b) { if (b==0) { // division by zero exception Native.wrMem(Const.EXC_DIVZ, Const.IO_EXCPT); return 0; } if(b==0x80000000) { if(a==0x80000000) return 0; else return a; } boolean neg = false; if (a<0) { neg = true; a = -a; } if (b<0) { b = -b; } int r = 0; for (int i=0; i<32; ++i) { // @WCA loop=32 r <<= 1; if (a < 0) { r |= 1; } a <<= 1; if (r>=b) { r -= b; } } if (neg) { r = -r; } return r; } private static long f_lrem(long a, long b) { if (b==0) { // division by zero exception Native.wrMem(Const.EXC_DIVZ, Const.IO_EXCPT); return 0; } if(b==0x8000000000000000L) { if(a==0x8000000000000000L) return 0; else return a; } boolean neg = false; if (a<0) { neg = true; a = -a; } if (b<0) { b = -b; } long r = 0; for (int i=0; i<64; ++i) { // @WCA loop=64 r <<= 1; if (a < 0) { r |= 1; } a <<= 1; if (r>=b) { r -= b; } // System.out.println("r="+((int)(r>>32))+" "+((int)r)); } if (neg) { r = -r; } return r; } private static int f_frem(int a, int b) { if (Const.SUPPORT_FLOAT) { return SoftFloat32.float_rem(a, b); } else { JVMHelp.noim(); return 0; } } private static long f_drem(long a, long b) { if (Const.SUPPORT_DOUBLE) { return SoftFloat64.double_rem(a, b); } else { JVMHelp.noim(); return 0; } } private static void f_ineg() { JVMHelp.noim(); /* jvm.asm */ } private static long f_lneg(long a) { return ~a+1; } private static int f_fneg(int a) { return a ^ 0x80000000; } private static long f_dneg(long a) { return a ^ 0x8000000000000000L; } private static void f_ishl() { JVMHelp.noim(); /* jvm.asm */ } private static long f_lshl(int ah, int al, int cnt) { cnt &= 0x3F; if ((cnt==0)) return Native.makeLong(ah, al); if (cnt>31) { ah = al << (cnt-32); al = 0; } else { ah = ah << cnt; ah += al >>> (32-cnt); al = al << cnt; } return Native.makeLong(ah, al); } private static void f_ishr() { JVMHelp.noim(); /* jvm.asm */ } private static long f_lshr(int ah, int al, int cnt) { cnt &= 0x3F; if (cnt==0) return Native.makeLong(ah, al); if (cnt>31) { al = ah >> (cnt-32); if(ah<0) ah = -1; else ah = 0; } else { al = al >>> cnt; al += ah << (32-cnt); ah = ah >> cnt; } return Native.makeLong(ah, al); } private static void f_iushr() { JVMHelp.noim(); /* jvm.asm */ } private static long f_lushr(int ah, int al, int cnt) { cnt &= 0x3F; if ((cnt==0)) return Native.makeLong(ah, al); if (cnt>31) { al = ah >>> (cnt-32); ah = 0; } else { al = al >>> cnt; al += ah << (32-cnt); ah = ah >>> cnt; } return Native.makeLong(ah, al); } private static void f_iand() { JVMHelp.noim(); /* jvm.asm */ } private static long f_land(int ah, int al, int bh, int bl) { ah &= bh; al &= bl; return Native.makeLong(ah, al); } private static void f_ior() { JVMHelp.noim(); /* jvm.asm */ } private static long f_lor(int ah, int al, int bh, int bl) { ah |= bh; al |= bl; return Native.makeLong(ah, al); } private static void f_ixor() { JVMHelp.noim(); /* jvm.asm */ } private static long f_lxor(int ah, int al, int bh, int bl) { ah ^= bh; al ^= bl; return Native.makeLong(ah, al); } private static void f_iinc() { JVMHelp.noim(); /* jvm.asm */ } private static long f_i2l(int a) { return Native.makeLong(a>>31, a); } private static int f_i2f(int a) { if (Const.SUPPORT_FLOAT) { return SoftFloat32.intToFloat(a); } else { JVMHelp.noim(); return 0; } } private static long f_i2d(int a) { if (Const.SUPPORT_DOUBLE) { return SoftFloat64.intToDouble(a); } else { JVMHelp.noim(); return 0; } } private static void f_l2i() { JVMHelp.noim(); /* jvm_long.inc */} private static int f_l2f(long a) { if (Const.SUPPORT_FLOAT) { return SoftFloat32.longToFloat(a); } else { JVMHelp.noim(); return 0; } } private static long f_l2d(long a) { if (Const.SUPPORT_DOUBLE) { return SoftFloat64.longToDouble(a); } else { JVMHelp.noim(); return 0; } } private static int f_f2i(int a) { if (Const.SUPPORT_FLOAT) { return SoftFloat32.intValue(a); } else { JVMHelp.noim(); return 0; } } private static long f_f2l(int a) { if (Const.SUPPORT_FLOAT) { return SoftFloat32.longValue(a); } else { JVMHelp.noim(); return 0; } } private static long f_f2d(int f) { if (Const.SUPPORT_DOUBLE) { return SoftFloat64.floatToDouble(f); } else { JVMHelp.noim(); return 0; } } private static int f_d2i(long d) { if (Const.SUPPORT_DOUBLE) { return SoftFloat64.intValue(d); } else { JVMHelp.noim(); return 0; } } private static long f_d2l(long d) { if (Const.SUPPORT_DOUBLE) { return SoftFloat64.longValue(d); } else { JVMHelp.noim(); return 0; } } private static int f_d2f(long d) { if (Const.SUPPORT_FLOAT) { return SoftFloat32.doubleToFloat(d); } else { JVMHelp.noim(); return 0; } } // i2x should be done in jvm.asm!!! // just to lazy and stay compatible with OEBB project private static int f_i2b(int a) { a &= 0xff; if ((a & 0x80)!=0) { a |= 0xffffff00; } return a; } private static void f_i2c() { JVMHelp.noim(); /* jvm.asm */ } private static int f_i2s(int a) { a &= 0xffff; if ((a&0x8000) != 0) { a |= 0xffff0000; } return a; } private static int f_lcmp(int ah, int al, int bh, int bl) { //overflow, underflow, if a and b have different signs if((ah >= 0)&&(bh < 0)) return 1; if((ah < 0)&&(bh >= 0)) return -1; // I didn't have it in my first implementation long a = Native.makeLong(ah, al) - Native.makeLong(bh, bl); al = (int) a; ah = (int) (a>>>32); if ((ah | al)==0) return 0; if (ah >= 0) { return 1; } else { return -1; } } private static int f_fcmpl(int a, int b) { if (Const.SUPPORT_FLOAT) { return SoftFloat32.float_cmpl(a, b); } else { JVMHelp.noim(); return 0; } } private static int f_fcmpg(int a, int b) { if (Const.SUPPORT_FLOAT) { return SoftFloat32.float_cmpg(a, b); } else { JVMHelp.noim(); return 0; } } private static int f_dcmpl(long a, long b) { if (Const.SUPPORT_DOUBLE) { return SoftFloat64.double_cmpl(a, b); } else { JVMHelp.noim(); return 0; } } private static int f_dcmpg(long a, long b) { if (Const.SUPPORT_DOUBLE) { return SoftFloat64.double_cmpg(a, b); } else { JVMHelp.noim(); return 0; } } private static void f_ifeq() { JVMHelp.noim(); /* jvm.asm */ } private static void f_ifne() { JVMHelp.noim(); /* jvm.asm */ } private static void f_iflt() { JVMHelp.noim(); /* jvm.asm */ } private static void f_ifge() { JVMHelp.noim(); /* jvm.asm */ } private static void f_ifgt() { JVMHelp.noim(); /* jvm.asm */ } private static void f_ifle() { JVMHelp.noim(); /* jvm.asm */ } private static void f_if_icmpeq() { JVMHelp.noim(); /* jvm.asm */ } private static void f_if_icmpne() { JVMHelp.noim(); /* jvm.asm */ } private static void f_if_icmplt() { JVMHelp.noim(); /* jvm.asm */ } private static void f_if_icmpge() { JVMHelp.noim(); /* jvm.asm */ } private static void f_if_icmpgt() { JVMHelp.noim(); /* jvm.asm */ } private static void f_if_icmple() { JVMHelp.noim(); /* jvm.asm */ } private static void f_if_acmpeq() { JVMHelp.noim(); /* jvm.asm */ } private static void f_if_acmpne() { JVMHelp.noim(); /* jvm.asm */ } private static void f_goto() { JVMHelp.noim(); /* jvm.asm */ } private static void f_jsr() { JVMHelp.noim();} private static void f_ret() { JVMHelp.noim();} private static void f_tableswitch(int idx) { int i; int sp = Native.getSP(); // sp of (); int pc = Native.rdIntMem(sp-3)-1; // one to high i = Native.rdIntMem(sp); // mp int start = Native.rdMem(i)>>>10; // address of method // memory is addressed in 32 bit words! i = (pc>>>2)+1+start; // points to default word int low = Native.rdMem(i+1); // if (idx<low || idx>high) { if (idx<low || idx>Native.rdMem(i+2)) { pc += Native.rdMem(i); // default case } else { pc += Native.rdMem(i+3+idx-low); } Native.wrIntMem(pc, sp-3); } private static void f_lookupswitch(int key) { int i, j; int sp = Native.getSP(); // sp of (); int pc = Native.rdIntMem(sp-3)-1; // one to high i = Native.rdIntMem(sp); // mp int start = Native.rdMem(i)>>>10; // address of method // memory is addressed in 32 bit words! i = (pc>>>2)+1+start; // points to default word int off = Native.rdMem(i); // default offset int cnt = Native.rdMem(i+1); i += 2; // point to pairs for (j=0; j<cnt; ++j) { if (Native.rdMem(i+(j<<1)) == key) { off = Native.rdMem(i+(j<<1)+1); // found match break; } } Native.wrIntMem(pc+off, sp-3); } private static void f_ireturn() { JVMHelp.noim(); /* jvm.asm */ } private static void f_lreturn() { JVMHelp.noim();} private static void f_freturn() { JVMHelp.noim();} private static void f_dreturn() { JVMHelp.noim();} private static void f_areturn() { JVMHelp.noim(); /* jvm.asm */ } private static void f_return() { JVMHelp.noim(); /* jvm.asm */ } private static void f_getstatic() { JVMHelp.noim(); /* jvm.asm */ } private static void f_putstatic() { JVMHelp.noim(); /* jvm.asm */ } private static void f_getfield() { JVMHelp.noim(); /* jvm.asm */ } private static void f_putfield() { JVMHelp.noim(); /* jvm.asm */ } private static void f_invokevirtual() { JVMHelp.noim(); /* jvm.asm */ } private static void f_invokespecial() { JVMHelp.noim(); /* jvm.asm */ } private static void f_invokestatic() { JVMHelp.noim(); /* jvm.asm */ } private static void f_invokeinterface() { JVMHelp.noim();} private static void f_unused_ba() { JVMHelp.noim();} static int f_new(int cons) { return GC.newObject(cons); } static int f_newarray(int count, int type) { return GC.newArray(count, type); } static int f_anewarray(int count, int cons) { // ignore cons (type info) // should be different for the GC!!! return GC.newArray(count, 1); //1..type not available=reference } private static void f_arraylength() { JVMHelp.noim(); /* jvm.asm */ } private static Throwable f_athrow(Throwable t) { Native.lock(0); // Just lock on address 0 as a form of Global lock if (Const.USE_RTTM) { // abort transaction on any exception Native.wrMem(Const.TM_ABORTED, Const.MEM_TM_MAGIC); } int i, j; // get frame pointer int fp = Native.getSP()-4; while (fp > Const.STACK_OFF+5) { // save frame information int pc = Native.rdIntMem(fp+1)-1; // correct one-off int vp = Native.rdIntMem(fp+2); int cp = Native.rdIntMem(fp+3); int mp = Native.rdIntMem(fp+4); // locate exception table i = Native.rdMem(mp); int tabstart = (i >>> 10) + (i & 0x3ff); i = Native.rdMem(tabstart); int tablen = i & 0xffff; int isSync = i & 0x10000; int isStat = i & 0x20000; // search exception table for (j = tabstart+1; j < tabstart+1+(tablen<<1); j+=2) { // extract table entry i = Native.rdMem(j); int begin = i >> 16; int end = i & 0xffff; i = Native.rdMem(j+1); int target = i >> 16; int type = i & 0xffff; // check if applicable if (pc >= begin && pc < end) { if (type == 0 || f_instanceof(Native.toInt(t), Native.rdMem(cp+type)) != 0) { // compute correct stack pointer i = Native.rdMem(mp+1); int sp = vp + (i & 0x1f) + ((i >>> 5) & 0x1f) + 4; // fake return frame Native.wrIntMem(sp, fp+0); Native.wrIntMem(target, fp+1); // return with faked frame Native.setSP(fp+4); Native.unlock(0); return t; } } } // do monitorexit if necessary if (isSync != 0) { // TODO: object to lock is found somewhere else for static methods, pass null for now i = Native.rdIntMem(vp); // reference is first argument of caller if (isStat != 0) i = 0; Native.unlock(i); } // go up one frame i = Native.rdMem(mp+1); fp = vp + (i & 0x1f) + ((i >>> 5) & 0x1f); } JVMHelp.wr("Uncaught exception: "); String s = t.getMessage(); if (s!=null) { JVMHelp.wr(s); } JVMHelp.wr("\n"); JVMHelp.trace(Native.getSP()); // Native.unlock(); // No need to unlock if we're about to crash anyway System.exit(1); return t; } private static int f_checkcast(int objref, int cons) { if (objref==0) { return objref; } int p = Native.rdMem(objref+GC.OFF_MTAB_ALEN); // ptr to MTAB p -= Const.CLASS_HEADR; // start of class info // check against interface int ifidx = Native.rdMem(cons+Const.CLASS_SUPER); if (ifidx < 0) { int iftab = Native.rdMem(p+Const.CLASS_IFTAB); if (iftab == 0) { // the class does not implement any interface throw JVMHelp.CCExc; } else { // check if the appropriate bit is set int i = Native.rdMem(iftab-((-ifidx+31)>>>5)); if (((i >>> (~ifidx & 0x1f)) & 1) != 0) { return objref; } else { throw JVMHelp.CCExc; } } } // search for superclass for (;;) { // always check this bound with TypeGraphTool! if (p==cons) { // @WCA loop <= 5 return objref; } else { p = Native.rdMem(p+Const.CLASS_SUPER); // super class ptr if (p==0) throw JVMHelp.CCExc; } } } private static int f_instanceof(int objref, int cons) { if (objref==0) { return 0; } int p = Native.rdMem(objref+GC.OFF_MTAB_ALEN); // handle indirection p -= Const.CLASS_HEADR; // start of class info // check against interface int ifidx = Native.rdMem(cons+Const.CLASS_SUPER); if (ifidx < 0) { int iftab = Native.rdMem(p+Const.CLASS_IFTAB); if (iftab == 0) { // the class does not implement any interface return 0; } else { // check if the appropriate bit is set int i = Native.rdMem(iftab-((-ifidx+31)>>>5)); return (i >>> (~ifidx & 0x1f)) & 1; } } // search for superclass for (;;) { // always check this bound with TypeGraphTool! if (p==cons) { // @WCA loop <= 5 return 1; } else { p = Native.rdMem(p+Const.CLASS_SUPER); if (p==0) return 0; } } } private static void f_monitorenter(int objAddr) {JVMHelp.noim(); /* jvm.asm */ } private static void f_monitorexit(int objAddr) {JVMHelp.noim(); /* jvm.asm */ } private static void f_wide() { JVMHelp.noim();} private static int f_multianewarray() { // JVMHelp.wr("multianewarray - GC issue?"); // JVMHelp.wr("\r\n"); // // be careful! We have to manipulate the stack frame. // If the layout changes we have to change this method. // int ret = 0; int i, j; int sp = Native.getSP(); // sp after call of f_multi(); int fp = sp-4; // first frame point is easy, since last sp points to the end of the frame // pc points to the next byte - the first index byte int pc = Native.rdIntMem(fp+1); int cp = Native.rdIntMem(fp+3); int mp = Native.rdIntMem(fp+4); int start = Native.rdMem(mp)>>>10; // address of method // memory is addressed in 32 bit words! // get index into cpool and array type j = Native.rdMem(start+(pc>>2)); for (i=(pc&0x03); i<3; ++i) j >>= 8; j &= 0xff; j <<= 8; ++pc; int type = Native.rdMem(start+(pc>>2)); for (i=(pc&0x03); i<3; ++i) type >>= 8; type &= 0xff; type += j; type += cp; type = Native.rdMem(type); ++pc; // now to dimensions int dim = Native.rdMem(start+(pc>>2)); for (i=(pc&0x03); i<3; ++i) dim >>= 8; dim &= 0xff; // correct pc to point to the next instruction Native.wrIntMem(pc+1, fp+1); // int vp = Native.rdIntMem(fp+2); // sp is now the previous sp sp = Native.rdIntMem(fp); sp -= dim; // correct the sp Native.wrIntMem(sp, fp); if (dim!=2) { // System.out.print("multanewarray: "); System.out.print(dim); System.out.println("dimensions not supported"); JVMHelp.noim(); } /* System.out.print("multianewarray: "); System.out.println(dim); for (i=1; i<=dim; ++i) { System.out.println(Native.rdIntMem(sp+i)); } */ // first dimension int cnt = Native.rdIntMem(sp+1); int cnt2 = Native.rdIntMem(sp+2); // we ignore type on anewarray ret = f_anewarray(cnt, 0); // handle for (i=0; i<cnt; ++i) { int arr = f_newarray(cnt2, type); synchronized(GC.mutex) { Native.wrMem(arr, Native.rdMem(ret)+i); } } return ret; } private static void f_ifnull() { JVMHelp.noim();} private static void f_ifnonnull() { JVMHelp.noim();} private static void f_goto_w() { JVMHelp.noim();} private static void f_jsr_w() { JVMHelp.noim();} private static void f_breakpoint() { JVMHelp.noim();} private static void f_resCB() { JVMHelp.noim();} private static void f_resCC() { JVMHelp.noim();} private static void f_resCD() { JVMHelp.noim();} private static void f_resCE() { JVMHelp.noim();} private static void f_resCF() { JVMHelp.noim();} private static void f_jopsys_null() { JVMHelp.noim();} private static void f_jopsys_rd() { JVMHelp.noim(); /* jvm.asm */ } private static void f_jopsys_wr() { JVMHelp.noim(); /* jvm.asm */ } private static void f_jopsys_rdmem() { JVMHelp.noim(); /* jvm.asm */ } private static void f_jopsys_wrmem() { JVMHelp.noim(); /* jvm.asm */ } private static void f_jopsys_rdint() { JVMHelp.noim(); /* jvm.asm */ } private static void f_jopsys_wrint() { JVMHelp.noim(); /* jvm.asm */ } private static void f_jopsys_getsp() { JVMHelp.noim(); /* jvm.asm */ } private static void f_jopsys_setsp() { JVMHelp.noim(); /* jvm.asm */ } private static void f_jopsys_getvp() { JVMHelp.noim(); /* jvm.asm */ } private static void f_jopsys_setvp() { JVMHelp.noim(); /* jvm.asm */ } private static void f_resDB() { JVMHelp.noim();} private static void f_resDC() { JVMHelp.noim();} private static void f_resDD() { JVMHelp.noim();} private static void f_resDE() { JVMHelp.noim();} private static void f_resDF() { JVMHelp.noim();} private static void f_resE0() { JVMHelp.noim();} private static void f_putstatic_ref(int val, int addr) { synchronized (GC.mutex) { if (Config.USE_SCOPES) { if (Config.USE_SCOPECHECKS) { // Pointer version // if ((val >>> 25) != 0){ // GC.log("Illegal static reference"); //} // Handler version (Default) int val_level; val_level = Native.rdMem(val + GC.OFF_SPACE); if (val_level != 0){ GC.log("Illegal static reference"); } } } else { // snapshot-at-beginning barrier int oldVal = Native.getStatic(addr); // Is it white? if (oldVal != 0 && Native.rdMem(oldVal+GC.OFF_SPACE) != GC.toSpace && Native.rdMem(oldVal+GC.OFF_GREY)==0) { // Mark grey Native.wrMem(GC.grayList, oldVal+GC.OFF_GREY); GC.grayList = oldVal; } } Native.putStatic(val, addr); } } private static void f_resE2() { JVMHelp.noim();} private static void f_putfield_ref(int ref, int value, int index) { synchronized (GC.mutex) { if (Config.USE_SCOPES) { if (Config.USE_SCOPECHECKS) { // Pointer version // if ((value >>> 25) > (ref >>> 25)){ // GC.log("Illegal field reference"); // } // Handler version (default) int ref_level; int val_level; ref_level = Native.rdMem(ref + GC.OFF_SPACE); val_level = Native.rdMem(value + GC.OFF_SPACE); if (val_level > ref_level){ //GC.log("Illegal field reference"); } } } else { // snapshot-at-beginning barrier int oldVal = Native.getField(ref, index); // Is it white? if (oldVal != 0 && Native.rdMem(oldVal+GC.OFF_SPACE) != GC.toSpace && Native.rdMem(oldVal+GC.OFF_GREY)==0) { // Mark grey Native.wrMem(GC.grayList, oldVal+GC.OFF_GREY); GC.grayList = oldVal; } } Native.putField(ref, index, value); } } private static void f_resE4() { JVMHelp.noim();} private static void f_resE5() { JVMHelp.noim();} private static void f_resE6() { JVMHelp.noim();} private static void f_resE7() { JVMHelp.noim();} private static void f_jopsys_memcpy() { JVMHelp.noim();} private static void f_jopsys_getfield() { JVMHelp.noim();} private static void f_jopsys_putfield() { JVMHelp.noim();} private static void f_resEB() { JVMHelp.noim();} private static void f_invokesuper() { JVMHelp.noim(); /* jvm.asm */ } private static void f_resED() { JVMHelp.noim();} private static void f_resEE() { JVMHelp.noim();} private static void f_resEF() { JVMHelp.noim();} private static void f_resF0() { JVMHelp.noim();} private static void f_resF1() { JVMHelp.noim();} private static void f_resF2() { JVMHelp.noim();} private static void f_resF3() { JVMHelp.noim();} private static void f_resF4() { JVMHelp.noim();} private static void f_resF5() { JVMHelp.noim();} private static void f_resF6() { JVMHelp.noim();} private static void f_resF7() { JVMHelp.noim();} private static void f_resF8() { JVMHelp.noim();} private static void f_resF9() { JVMHelp.noim();} private static void f_resFA() { JVMHelp.noim();} private static void f_resFB() { JVMHelp.noim();} private static void f_resFC() { JVMHelp.noim();} private static void f_resFD() { JVMHelp.noim();} private static void f_sys_noim() { JVMHelp.noim(); /* jvm.asm */ } private static void f_sys_init() { JVMHelp.noim(); /* jvm.asm */ } }