X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fsparc64%2Fcodegen.c;h=5504b550c0a6759d2586fc91bd041bdfe20f0995;hb=c2773616396e371383015b60aa59feb1f6d665b0;hp=7920828491ec03910cf6cfa29199addcd8e2e1d7;hpb=de93f9d16a5f057981019744d93dbdb1ce71aa81;p=cacao.git diff --git a/src/vm/jit/sparc64/codegen.c b/src/vm/jit/sparc64/codegen.c index 792082849..5504b550c 100644 --- a/src/vm/jit/sparc64/codegen.c +++ b/src/vm/jit/sparc64/codegen.c @@ -29,9 +29,8 @@ #include "config.h" -#include #include - +#include #include "vm/types.h" @@ -48,10 +47,12 @@ #include "vm/exceptions.h" #include "vm/global.h" +#include "vm/jit/abi.h" #include "vm/jit/asmpart.h" #include "vm/jit/codegen-common.h" #include "vm/jit/dseg.h" #include "vm/jit/emit-common.h" +#include "vm/jit/sparc64/emit.h" #include "vm/jit/jit.h" #include "vm/jit/parse.h" #include "vm/jit/patcher.h" @@ -61,6 +62,9 @@ #include "vmcore/loader.h" #include "vmcore/options.h" + +#define BUILTIN_FLOAT_ARGS 1 + /* XXX use something like this for window control ? * #define REG_PV (own_window?REG_PV_CALLEE:REG_PV_CALLER) */ @@ -68,18 +72,38 @@ bool fits_13(s4 disp) { - /* printf("fits disp %d?\n", disp); */ + /* + if ((disp < -4096) || (disp > 4095)) + printf("disp %d\n", disp); + */ return (disp >= -4096) && (disp <= 4095); } -/* codegen ********************************************************************* +s4 get_lopart_disp(disp) +{ + s4 lodisp; + + if (disp > 0) + lodisp = setlo_part(disp); + else { + if (setlo_part(disp) == 0) + lodisp = 0; + else + lodisp = setlo_part(disp) | 0x1c00; + } + + return lodisp; +} + + +/* codegen_emit **************************************************************** Generates machine code. *******************************************************************************/ -bool codegen(jitdata *jd) +bool codegen_emit(jitdata *jd) { methodinfo *m; codeinfo *code; @@ -214,7 +238,7 @@ bool codegen(jitdata *jd) /* XXX could use the param slots on the stack for this! */ for (p = 0; p < INT_ARG_CNT; p++) - M_STX(REG_WINDOW_TRANSPOSE(rd->argintregs[p]), REG_SP, JITSTACK + (p * 8)); + M_STX(REG_WINDOW_TRANSPOSE(abi_registers_integer_argument[p]), REG_SP, JITSTACK + (p * 8)); } @@ -231,20 +255,24 @@ bool codegen(jitdata *jd) continue; var = VAR(varindex); - - s1 = md->params[p].regoff; - if (IS_INT_LNG_TYPE(t)) { /* integer args */ + s1 = md->params[p].regoff; + + if (IS_INT_LNG_TYPE(t)) { /* integer args */ + if (!md->params[p].inmemory) { /* register arguments */ /*s2 = rd->argintregs[s1];*/ /*s2 = REG_WINDOW_TRANSPOSE(s2);*/ + + /* need the argument index (p) here, not the register number */ + if (!(var->flags & INMEMORY)) { /* reg arg -> register */ - /*M_INTMOVE(s2, var->vv.regoff);*/ - M_LDX(var->vv.regoff, REG_SP, JITSTACK + (s1 * 8)); + /*M_INTMOVE(s2, var->vv.regoff);*/ + M_LDX(var->vv.regoff, REG_SP, JITSTACK + (p * 8)); } else { /* reg arg -> spilled */ /*M_STX(s2, REG_SP, (WINSAVE_CNT + var->vv.regoff) * 8);*/ - M_LDX(REG_ITMP1, REG_SP, JITSTACK + (s1 * 8)); + M_LDX(REG_ITMP1, REG_SP, JITSTACK + (p * 8)); M_STX(REG_ITMP1, REG_SP, localbase + (var->vv.regoff * 8)); } @@ -254,18 +282,17 @@ bool codegen(jitdata *jd) } else { /* stack arg -> spilled */ /* add the callers window save registers */ - var->vv.regoff = cd->stackframesize + JITSTACK_CNT + s1; + var->vv.regoff = cd->stackframesize + s1; } } } else { /* floating args */ if (!md->params[p].inmemory) { /* register arguments */ - s2 = rd->argfltregs[s1]; if (!(var->flags & INMEMORY)) { /* reg arg -> register */ - M_FLTMOVE(s2, var->vv.regoff); + M_FLTMOVE(s1, var->vv.regoff); } else { /* reg arg -> spilled */ - M_DST(s2, REG_SP, localbase + (var->vv.regoff) * 8); + M_DST(s1, REG_SP, localbase + (var->vv.regoff) * 8); } } else { /* stack arguments */ @@ -273,7 +300,7 @@ bool codegen(jitdata *jd) M_DLD(var->vv.regoff, REG_FP, JITSTACK + (s1 * 8)); } else { /* stack-arg -> spilled */ - var->vv.regoff = cd->stackframesize + JITSTACK_CNT + s1; + var->vv.regoff = cd->stackframesize + s1; } } } @@ -446,23 +473,23 @@ bool codegen(jitdata *jd) /* load/store/copy/move operations ************************************/ case ICMD_ILOAD: /* ... ==> ..., content of local variable */ - case ICMD_LLOAD: /* ... ==> ..., content of local variable */ - case ICMD_ALOAD: /* ... ==> ..., content of local variable */ - case ICMD_FLOAD: /* ... ==> ..., content of local variable */ - case ICMD_DLOAD: /* ... ==> ..., content of local variable */ + case ICMD_LLOAD: + case ICMD_ALOAD: + case ICMD_FLOAD: + case ICMD_DLOAD: case ICMD_ISTORE: /* ..., value ==> ... */ - case ICMD_LSTORE: /* ..., value ==> ... */ - case ICMD_FSTORE: /* ..., value ==> ... */ - case ICMD_DSTORE: /* ..., value ==> ... */ + case ICMD_LSTORE: + case ICMD_FSTORE: + case ICMD_DSTORE: case ICMD_COPY: case ICMD_MOVE: - emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst)); + emit_copy(jd, iptr); break; case ICMD_ASTORE: if (!(iptr->flags.bits & INS_FLAG_RETADDR)) - emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst)); + emit_copy(jd, iptr); break; @@ -674,9 +701,9 @@ bool codegen(jitdata *jd) emit_arithmetic_check(cd, iptr, s2); M_ISEXT(s1, s1); /* XXX trim s2 like s1 ? */ - M_DIVX(s1, s2, d); - M_MULX(s2, d, d); - M_SUB(s1, d, d); + M_DIVX(s1, s2, REG_ITMP3); + M_MULX(s2, REG_ITMP3, REG_ITMP3); + M_SUB(s1, REG_ITMP3, d); emit_store_dst(jd, iptr, d); break; @@ -686,9 +713,9 @@ bool codegen(jitdata *jd) s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); emit_arithmetic_check(cd, iptr, s2); - M_DIVX(s1, s2, d); - M_MULX(s2, d, d); - M_SUB(s1, d, d); + M_DIVX(s1, s2, REG_ITMP3); + M_MULX(s2, REG_ITMP3, REG_ITMP3); + M_SUB(s1, REG_ITMP3, d); emit_store_dst(jd, iptr, d); break; @@ -705,7 +732,15 @@ bool codegen(jitdata *jd) break; case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */ - case ICMD_LSHL: + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + M_SLL(s1, s2, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); @@ -715,7 +750,16 @@ bool codegen(jitdata *jd) break; case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */ - case ICMD_LSHLCONST: /* val.i = constant */ + /* val.i = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + M_SLL_IMM(s1, iptr->sx.val.i, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */ + /* val.i = constant */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); @@ -819,26 +863,27 @@ bool codegen(jitdata *jd) emit_store_dst(jd, iptr, d); break; - case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */ + case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */ /* sx.val.i = constant */ + /* constant is actually constant - 1 */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */ if (s1 == d) { M_MOV(s1, REG_ITMP1); s1 = REG_ITMP1; } - if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 0xffff)) { + M_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */ + if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 4095)) { M_AND_IMM(s1, iptr->sx.val.i, d); - M_BGEZ(s1, 4); + M_BGEZ(s1, 5); M_NOP; M_SUB(REG_ZERO, s1, d); M_AND_IMM(d, iptr->sx.val.i, d); } else { ICONST(REG_ITMP2, iptr->sx.val.i); M_AND(s1, REG_ITMP2, d); - M_BGEZ(s1, 4); + M_BGEZ(s1, 5); M_NOP; M_SUB(REG_ZERO, s1, d); M_AND(d, REG_ITMP2, d); @@ -1071,7 +1116,7 @@ bool codegen(jitdata *jd) case ICMD_I2F: s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - disp = dseg_add_float(cd, 0.0); + disp = dseg_add_unique_float(cd, 0.0); M_IST (s1, REG_PV_CALLEE, disp); M_FLD (d, REG_PV_CALLEE, disp); M_CVTIF (d, d); /* rd gets translated to double target register */ @@ -1081,17 +1126,43 @@ bool codegen(jitdata *jd) case ICMD_I2D: s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - disp = dseg_add_float(cd, 0.0); - M_IST (s1, REG_PV_CALLEE, disp); - M_FLD (REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */ + disp = dseg_add_unique_float(cd, 0.0); + M_IST(s1, REG_PV_CALLEE, disp); + M_FLD(REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */ M_CVTID (REG_FTMP2, d); /* rd gets translated to double target register */ emit_store_dst(jd, iptr, d); break; + + case ICMD_L2F: + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + disp = dseg_add_unique_double(cd, 0.0); + M_STX(s1, REG_PV_CALLEE, disp); + M_DLD(REG_FTMP3, REG_PV_CALLEE, disp); + M_CVTLF(REG_FTMP3, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_L2D: + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + disp = dseg_add_unique_double(cd, 0.0); + M_STX(s1, REG_PV_CALLEE, disp); + M_DLD(d, REG_PV_CALLEE, disp); + M_CVTLD(d, d); + emit_store_dst(jd, iptr, d); + break; case ICMD_F2I: /* ..., value ==> ..., (int) value */ s1 = emit_load_s1(jd, iptr, REG_FTMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - disp = dseg_add_float(cd, 0.0); + disp = dseg_add_unique_float(cd, 0.0); + + /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */ + M_FCMP(s1, s1); + M_FBU(5); + M_MOV(REG_ZERO, d); /* delay slot */ + M_CVTFI(s1, REG_FTMP2); M_FST(REG_FTMP2, REG_PV_CALLEE, disp); M_ILD(d, REG_PV, disp); @@ -1102,7 +1173,13 @@ bool codegen(jitdata *jd) case ICMD_D2I: /* ..., value ==> ..., (int) value */ s1 = emit_load_s1(jd, iptr, REG_FTMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - disp = dseg_add_float(cd, 0.0); + disp = dseg_add_unique_float(cd, 0.0); + + /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */ + M_DCMP(s1, s1); + M_FBU(5); + M_MOV(REG_ZERO, d); /* delay slot */ + M_CVTDI(s1, REG_FTMP2); M_FST(REG_FTMP2, REG_PV, disp); M_ILD(d, REG_PV, disp); @@ -1112,7 +1189,13 @@ bool codegen(jitdata *jd) case ICMD_F2L: /* ..., value ==> ..., (long) value */ s1 = emit_load_s1(jd, iptr, REG_FTMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - disp = dseg_add_double(cd, 0.0); + disp = dseg_add_unique_double(cd, 0.0); + + /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */ + M_FCMP(s1, s1); + M_FBU(5); + M_MOV(REG_ZERO, d); /* delay slot */ + M_CVTFL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */ M_DST(REG_FTMP2, REG_PV, disp); M_LDX(d, REG_PV, disp); @@ -1122,7 +1205,13 @@ bool codegen(jitdata *jd) case ICMD_D2L: /* ..., value ==> ..., (long) value */ s1 = emit_load_s1(jd, iptr, REG_FTMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - disp = dseg_add_double(cd, 0.0); + disp = dseg_add_unique_double(cd, 0.0); + + /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */ + M_DCMP(s1, s1); + M_FBU(5); + M_MOV(REG_ZERO, d); /* delay slot */ + M_CVTDL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */ M_DST(REG_FTMP2, REG_PV, disp); M_LDX(d, REG_PV, disp); @@ -1211,7 +1300,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_AADD(s2, s1, REG_ITMP3); M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray, data[0])); emit_store_dst(jd, iptr, d); @@ -1222,7 +1312,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_AADD(s2, s1, REG_ITMP3); M_AADD(s2, REG_ITMP3, REG_ITMP3); M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0])); @@ -1234,7 +1325,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_AADD(s2, s1, REG_ITMP3); M_AADD(s2, REG_ITMP3, REG_ITMP3); M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray, data[0])); @@ -1246,7 +1338,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 2, REG_ITMP3); M_AADD(REG_ITMP3, s1, REG_ITMP3); M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0])); @@ -1258,7 +1351,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 3, REG_ITMP3); M_AADD(REG_ITMP3, s1, REG_ITMP3); M_LDX(d, REG_ITMP3, OFFSET(java_longarray, data[0])); @@ -1270,7 +1364,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 2, REG_ITMP3); M_AADD(REG_ITMP3, s1, REG_ITMP3); M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0])); @@ -1282,7 +1377,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 3, REG_ITMP3); M_AADD(REG_ITMP3, s1, REG_ITMP3); M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0])); @@ -1294,7 +1390,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3); M_AADD(REG_ITMP3, s1, REG_ITMP3); M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0])); @@ -1306,7 +1403,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_AADD(s2, s1, REG_ITMP1); s3 = emit_load_s3(jd, iptr, REG_ITMP3); M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0])); @@ -1317,7 +1415,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_AADD(s2, s1, REG_ITMP1); M_AADD(s2, REG_ITMP1, REG_ITMP1); s3 = emit_load_s3(jd, iptr, REG_ITMP3); @@ -1328,7 +1427,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 2, REG_ITMP2); M_AADD(REG_ITMP2, s1, REG_ITMP1); s3 = emit_load_s3(jd, iptr, REG_ITMP3); @@ -1339,7 +1439,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 3, REG_ITMP2); M_AADD(REG_ITMP2, s1, REG_ITMP1); s3 = emit_load_s3(jd, iptr, REG_ITMP3); @@ -1350,7 +1451,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 2, REG_ITMP2); M_AADD(REG_ITMP2, s1, REG_ITMP1); s3 = emit_load_s3(jd, iptr, REG_FTMP1); @@ -1361,7 +1463,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 3, REG_ITMP2); M_AADD(REG_ITMP2, s1, REG_ITMP1); s3 = emit_load_s3(jd, iptr, REG_FTMP1); @@ -1373,25 +1476,24 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); s3 = emit_load_s3(jd, iptr, REG_ITMP3); - M_MOV(s1, rd->argintregs[0]); - M_MOV(s3, rd->argintregs[1]); + M_MOV(s1, REG_OUT0); + M_MOV(s3, REG_OUT1); disp = dseg_add_functionptr(cd, BUILTIN_canstore); M_ALD(REG_ITMP3, REG_PV, disp); M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); M_NOP; - - M_BEQZ(REG_RESULT_CALLER, 0); - codegen_add_arraystoreexception_ref(cd); - M_NOP; + emit_exception_check(cd, iptr); s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2); M_AADD(REG_ITMP2, s1, REG_ITMP1); s3 = emit_load_s3(jd, iptr, REG_ITMP3); + /* implicit null-pointer check */ M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0])); break; @@ -1400,7 +1502,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_AADD(s2, s1, REG_ITMP1); M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0])); break; @@ -1410,7 +1513,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_AADD(s2, s1, REG_ITMP1); M_AADD(s2, REG_ITMP1, REG_ITMP1); M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0])); @@ -1420,7 +1524,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 2, REG_ITMP2); M_AADD(REG_ITMP2, s1, REG_ITMP1); M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0])); @@ -1430,7 +1535,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 3, REG_ITMP2); M_AADD(REG_ITMP2, s1, REG_ITMP1); M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0])); @@ -1440,7 +1546,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - emit_array_checks(cd, iptr, s1, s2); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2); M_AADD(REG_ITMP2, s1, REG_ITMP1); M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0])); @@ -1750,158 +1857,115 @@ bool codegen(jitdata *jd) case ICMD_GOTO: /* ... ==> ... */ case ICMD_RET: /* ... ==> ... */ - M_BR(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_br(cd, iptr->dst.block); ALIGNCODENOP; break; case ICMD_JSR: /* ... ==> ... */ - M_BR(0); - codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block); - M_NOP; + emit_br(cd, iptr->sx.s23.s3.jsrtarget.block); ALIGNCODENOP; break; case ICMD_IFNULL: /* ..., value ==> ... */ + case ICMD_IFNONNULL: s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_BEQZ(s1, 0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; - break; - - case ICMD_IFNONNULL: /* ..., value ==> ... */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_BNEZ(s1, 0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE); break; + + /* Note: int compares must not branch on the register directly. */ + /* Reason is, that register content is not 32-bit clean. */ case ICMD_IFEQ: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) { - M_BEQZ(s1, 0); - } else { - if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { - M_CMP_IMM(s1, iptr->sx.val.i); - } - else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMP(s1, REG_ITMP2); - } - M_BEQ(0); - } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + + if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { + M_CMP_IMM(s1, iptr->sx.val.i); + } + else { + ICONST(REG_ITMP2, iptr->sx.val.i); + M_CMP(s1, REG_ITMP2); + } + emit_beq(cd, iptr->dst.block); break; case ICMD_IFLT: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) { - M_BLTZ(s1, 0); - } else { - if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { - M_CMP_IMM(s1, iptr->sx.val.i); - } else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMP(s1, REG_ITMP2); - } - M_BLT(0); + + if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { + M_CMP_IMM(s1, iptr->sx.val.i); + } + else { + ICONST(REG_ITMP2, iptr->sx.val.i); + M_CMP(s1, REG_ITMP2); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_blt(cd, iptr->dst.block); break; case ICMD_IFLE: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) { - M_BLEZ(s1, 0); - } + + if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { + M_CMP_IMM(s1, iptr->sx.val.i); + } else { - if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { - M_CMP_IMM(s1, iptr->sx.val.i); - } - else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMP(s1, REG_ITMP2); - } - M_BLE(0); + ICONST(REG_ITMP2, iptr->sx.val.i); + M_CMP(s1, REG_ITMP2); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_ble(cd, iptr->dst.block); break; case ICMD_IFNE: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) { - M_BNEZ(s1, 0); - } + + if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { + M_CMP_IMM(s1, iptr->sx.val.i); + } else { - if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { - M_CMP_IMM(s1, iptr->sx.val.i); - } - else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMP(s1, REG_ITMP2); - } - M_BNE(0); + ICONST(REG_ITMP2, iptr->sx.val.i); + M_CMP(s1, REG_ITMP2); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bne(cd, iptr->dst.block); break; case ICMD_IFGT: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) { - M_BGTZ(s1, 0); + + if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { + M_CMP_IMM(s1, iptr->sx.val.i); } else { - if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { - M_CMP_IMM(s1, iptr->sx.val.i); - } else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMP(s1, REG_ITMP2); - } - M_BGT(0); + ICONST(REG_ITMP2, iptr->sx.val.i); + M_CMP(s1, REG_ITMP2); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bgt(cd, iptr->dst.block); break; case ICMD_IFGE: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) { - M_BGEZ(s1, 0); - } + + if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { + M_CMP_IMM(s1, iptr->sx.val.i); + } else { - if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { - M_CMP_IMM(s1, iptr->sx.val.i); - } - else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMP(s1, REG_ITMP2); - } - M_BGE(0); + ICONST(REG_ITMP2, iptr->sx.val.i); + M_CMP(s1, REG_ITMP2); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bge(cd, iptr->dst.block); break; case ICMD_IF_LEQ: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.l == 0) { - M_BEQZ(s1, 0); - } + if (iptr->sx.val.l == 0) + emit_beqz(cd, iptr->dst.block, s1); else { if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) { M_CMP_IMM(s1, iptr->sx.val.l); @@ -1910,108 +1974,93 @@ bool codegen(jitdata *jd) LCONST(REG_ITMP2, iptr->sx.val.l); M_CMP(s1, REG_ITMP2); } - M_XBEQ(0); + emit_beq_xcc(cd, iptr->dst.block); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; break; case ICMD_IF_LLT: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.l == 0) { - M_BLTZ(s1, 0); - } + if (iptr->sx.val.l == 0) + emit_bltz(cd, iptr->dst.block, s1); else { if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) { M_CMP_IMM(s1, iptr->sx.val.l); } else { - ICONST(REG_ITMP2, iptr->sx.val.l); + LCONST(REG_ITMP2, iptr->sx.val.l); M_CMP(s1, REG_ITMP2); } - M_XBLT(0); + emit_blt_xcc(cd, iptr->dst.block); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; break; case ICMD_IF_LLE: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.l == 0) { - M_BLEZ(s1, 0); - } + if (iptr->sx.val.l == 0) + emit_blez(cd, iptr->dst.block, s1); else { if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) { M_CMP_IMM(s1, iptr->sx.val.l); - } + } else { - ICONST(REG_ITMP2, iptr->sx.val.l); + LCONST(REG_ITMP2, iptr->sx.val.l); M_CMP(s1, REG_ITMP2); } - M_XBLE(0); + emit_ble_xcc(cd, iptr->dst.block); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; break; case ICMD_IF_LNE: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.l == 0) { - M_BNEZ(s1, 0); - } + if (iptr->sx.val.l == 0) + emit_bnez(cd, iptr->dst.block, s1); else { if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) { - M_CMP_IMM(s1, iptr->sx.val.i); + M_CMP_IMM(s1, iptr->sx.val.l); } else { - ICONST(REG_ITMP2, iptr->sx.val.l); + LCONST(REG_ITMP2, iptr->sx.val.l); M_CMP(s1, REG_ITMP2); } - M_XBNE(0); + emit_bne_xcc(cd, iptr->dst.block); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; break; case ICMD_IF_LGT: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.l == 0) { - M_BGTZ(s1, 0); - } else { + if (iptr->sx.val.l == 0) + emit_bgtz(cd, iptr->dst.block, s1); + else { if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) { M_CMP_IMM(s1, iptr->sx.val.l); - } else { - ICONST(REG_ITMP2, iptr->sx.val.l); + } + else { + LCONST(REG_ITMP2, iptr->sx.val.l); M_CMP(s1, REG_ITMP2); } - M_XBGT(0); + emit_bgt_xcc(cd, iptr->dst.block); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; break; case ICMD_IF_LGE: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.l == 0) { - M_BGEZ(s1, 0); - } + if (iptr->sx.val.l == 0) + emit_bgez(cd, iptr->dst.block, s1); else { if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) { M_CMP_IMM(s1, iptr->sx.val.l); } else { - ICONST(REG_ITMP2, iptr->sx.val.l); + LCONST(REG_ITMP2, iptr->sx.val.l); M_CMP(s1, REG_ITMP2); } - M_XBGE(0); + emit_bge_xcc(cd, iptr->dst.block); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; break; @@ -2021,9 +2070,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_XBEQ(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_beq_xcc(cd, iptr->dst.block); break; case ICMD_IF_ICMPEQ: /* 32-bit compare */ @@ -2031,9 +2078,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BEQ(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_beq(cd, iptr->dst.block); break; case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */ @@ -2042,9 +2087,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_XBNE(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bne_xcc(cd, iptr->dst.block); break; case ICMD_IF_ICMPNE: /* 32-bit compare */ @@ -2052,9 +2095,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BNE(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bne(cd, iptr->dst.block); break; case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */ @@ -2062,9 +2103,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_XBLT(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_blt_xcc(cd, iptr->dst.block); break; case ICMD_IF_ICMPLT: /* 32-bit compare */ @@ -2072,9 +2111,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BLT(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_blt(cd, iptr->dst.block); break; case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */ @@ -2082,9 +2119,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_XBGT(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bgt_xcc(cd, iptr->dst.block); break; case ICMD_IF_ICMPGT: /* 32-bit compare */ @@ -2092,9 +2127,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BGT(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bgt(cd, iptr->dst.block); break; case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */ @@ -2102,9 +2135,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BLE(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_ble_xcc(cd, iptr->dst.block); break; case ICMD_IF_ICMPLE: /* 32-bit compare */ @@ -2112,9 +2143,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BLE(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_ble(cd, iptr->dst.block); break; @@ -2123,9 +2152,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BGE(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bge_xcc(cd, iptr->dst.block); break; case ICMD_IF_ICMPGE: /* 32-bit compare */ @@ -2133,9 +2160,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BGE(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bge(cd, iptr->dst.block); break; @@ -2247,9 +2272,7 @@ nowperformreturn: ICONST(REG_ITMP2, i - 1); M_CMP(REG_ITMP1, REG_ITMP2); } - M_XBUGT(0); - codegen_add_branch_ref(cd, table[0].block); /* default target */ - M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/ + emit_bugt(cd, table[0].block); /* default target */ /* build jump table top down and use address of lowest entry */ @@ -2263,6 +2286,7 @@ nowperformreturn: /* length of dataseg after last dseg_addtarget is used by load */ + M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); M_AADD(REG_ITMP1, REG_PV, REG_ITMP2); M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen)); M_JMP(REG_ZERO, REG_ITMP2, REG_ZERO); @@ -2289,15 +2313,11 @@ nowperformreturn: ICONST(REG_ITMP2, lookup->value); M_CMP(s1, REG_ITMP2); } - M_BEQ(0); - codegen_add_branch_ref(cd, lookup->target.block); - M_NOP; + emit_beq(cd, lookup->target.block); ++lookup; } - M_BR(0); - codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block); - M_NOP; + emit_br(cd, iptr->sx.s23.s3.lookupdefault.block); ALIGNCODENOP; break; } @@ -2308,8 +2328,50 @@ nowperformreturn: bte = iptr->sx.s23.s3.bte; md = bte->md; - /* XXX: proper builtin calling and float args are so not implemented */ - assert(md->paramcount <= 5 && md->argfltreguse < 1); + /* XXX: builtin calling with stack arguments not implemented */ + assert(md->paramcount <= 5 && md->argfltreguse <= 16); + + s3 = md->paramcount; + + MCODECHECK((s3 << 1) + 64); + +#ifdef BUILTIN_FLOAT_ARGS /* float args for builtins disabled */ + + /* copy float arguments according to ABI convention */ + + int num_fltregargs = 0; + int fltregarg_inswap[16]; + + for (s3 = s3 - 1; s3 >= 0; s3--) { + var = VAR(iptr->sx.s23.s2.args[s3]); + + if (IS_FLT_DBL_TYPE(var->type)) { + if (!md->params[s3].inmemory) { + s1 = s3; /*native flt args use argument index directly*/ + d = emit_load(jd, iptr, var, REG_FTMP1); + + M_DMOV(d, s1 + 16); + fltregarg_inswap[num_fltregargs] = s1; + num_fltregargs++; + /*printf("builtin: flt arg swap to %d\n", s1 + 16);*/ + } + else { + assert(0); + } + } + } + + int i; + /* move swapped float args to target regs */ + for (i = 0; i < num_fltregargs; i++) { + s1 = fltregarg_inswap[i]; + M_DMOV(s1 + 16, s1); + /*printf("builtin float arg to target reg: %d ==> %d\n", s1+16, s1);*/ + } + +#else + assert(md->argfltreguse == 0); +#endif goto gen_method; @@ -2339,36 +2401,40 @@ gen_method: for (s3 = s3 - 1; s3 >= 0; s3--) { var = VAR(iptr->sx.s23.s2.args[s3]); + d = md->params[s3].regoff; if (var->flags & PREALLOC) continue; if (IS_INT_LNG_TYPE(var->type)) { if (!md->params[s3].inmemory) { - s1 = rd->argintregs[md->params[s3].regoff]; - d = emit_load(jd, iptr, var, s1); - M_INTMOVE(d, s1); + s1 = emit_load(jd, iptr, var, d); + M_INTMOVE(s1, d); } else { - d = emit_load(jd, iptr, var, REG_ITMP1); - M_STX(d, REG_SP, JITSTACK + md->params[s3].regoff * 8); + s1 = emit_load(jd, iptr, var, REG_ITMP1); + M_STX(s1, REG_SP, JITSTACK + d * 8); } } else { +#ifdef BUILTIN_FLOAT_ARGS + if (iptr->opc == ICMD_BUILTIN) + continue; +#endif + if (!md->params[s3].inmemory) { - s1 = rd->argfltregs[md->params[s3].regoff]; - d = emit_load(jd, iptr, var, s1); + s1 = emit_load(jd, iptr, var, d); if (IS_2_WORD_TYPE(var->type)) - M_DMOV(d, s1); + M_DMOV(s1, d); else - M_FMOV(d, s1); + M_FMOV(s1, d); } else { - d = emit_load(jd, iptr, var, REG_FTMP1); + s1 = emit_load(jd, iptr, var, REG_FTMP1); if (IS_2_WORD_TYPE(var->type)) - M_DST(d, REG_SP, JITSTACK + md->params[s3].regoff * 8); + M_DST(s1, REG_SP, JITSTACK + d * 8); else - M_FST(d, REG_SP, JITSTACK + md->params[s3].regoff * 8); + M_FST(s1, REG_SP, JITSTACK + d * 8); } } } @@ -2378,17 +2444,26 @@ gen_method: disp = dseg_add_functionptr(cd, bte->fp); M_ALD(REG_PV_CALLER, REG_PV, disp); /* built-in-function pointer */ - s1 = REG_PV_CALLER; /* XXX jit-c-call */ - + /* generate the actual call */ + + M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO); + M_NOP; + disp = (s4) (cd->mcodeptr - cd->mcodebase); + /* REG_RA holds the value of the jmp instruction, therefore +8 */ + M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); + + emit_exception_check(cd, iptr); + if (md->returntype.type == TYPE_FLT) { + /* special handling for float return value in %f0 */ + M_FMOV_INTERN(0,1); + } break; case ICMD_INVOKESPECIAL: - M_BEQZ(REG_OUT0, 0); - codegen_add_nullpointerexception_ref(cd); - M_NOP; - /* fall through */ + emit_nullpointer_check(cd, iptr, REG_OUT0); + /* fall-through */ case ICMD_INVOKESTATIC: if (lm == NULL) { @@ -2401,7 +2476,14 @@ gen_method: disp = dseg_add_address(cd, lm->stubroutine); M_ALD(REG_PV_CALLER, REG_PV, disp); /* method pointer in pv */ - s1 = REG_PV_CALLER; + + /* generate the actual call */ + + M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO); + M_NOP; + disp = (s4) (cd->mcodeptr - cd->mcodebase); + /* REG_RA holds the value of the jmp instruction, therefore +8 */ + M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); break; case ICMD_INVOKEVIRTUAL: @@ -2416,10 +2498,17 @@ gen_method: s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex; - M_ALD(REG_METHODPTR, REG_OUT0, - OFFSET(java_objectheader, vftbl)); + /* implicit null-pointer check */ + M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_objectheader, vftbl)); M_ALD(REG_PV_CALLER, REG_METHODPTR, s1); - s1 = REG_PV_CALLER; + + /* generate the actual call */ + + M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO); + M_NOP; + disp = (s4) (cd->mcodeptr - cd->mcodebase); + /* REG_RA holds the value of the jmp instruction, therefore +8 */ + M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); break; case ICMD_INVOKEINTERFACE: @@ -2438,29 +2527,19 @@ gen_method: s2 = sizeof(methodptr) * (lm - lm->class->methods); } - M_ALD(REG_METHODPTR, REG_OUT0, - OFFSET(java_objectheader, vftbl)); + /* implicit null-pointer check */ + M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_objectheader, vftbl)); M_ALD(REG_METHODPTR, REG_METHODPTR, s1); M_ALD(REG_PV_CALLER, REG_METHODPTR, s2); - s1 = REG_PV_CALLER; - break; - } - /* generate the actual call */ - - M_JMP(REG_RA_CALLER, s1, REG_ZERO); - M_NOP; - disp = (s4) (cd->mcodeptr - cd->mcodebase); - /* REG_RA holds the value of the jmp instruction, therefore +8 */ - M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); - - - /* actually only used for ICMD_BUILTIN */ - - if (INSTRUCTION_MUST_CHECK(iptr)) { - M_BEQZ(REG_RESULT_CALLER, 0); - codegen_add_fillinstacktrace_ref(cd); - M_NOP; + /* generate the actual call */ + + M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO); + M_NOP; + disp = (s4) (cd->mcodeptr - cd->mcodebase); + /* REG_RA holds the value of the jmp instruction, therefore +8 */ + M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); + break; } /* store return value */ @@ -2520,23 +2599,10 @@ gen_method: s1 = emit_load_s1(jd, iptr, REG_ITMP1); - /* calculate interface checkcast code size */ - - s2 = 8; - if (super == NULL) - s2 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0); - - /* calculate class checkcast code size */ - - s3 = 10; - if (super == NULL) - s3 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0); - /* if class is not resolved, check which code to call */ if (super == NULL) { - M_BEQZ(s1, 5 + (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0) + s2 + 2 + s3 + 1); - M_NOP; + emit_label_beqz(cd, BRANCH_LABEL_1, s1); cr = iptr->sx.s23.s3.c.ref; disp = dseg_add_unique_s4(cd, 0); /* super->flags */ @@ -2546,8 +2612,7 @@ gen_method: M_ILD(REG_ITMP2, REG_PV, disp); M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2); - M_BEQZ(REG_ITMP2, s2 + 2 + 2); - M_NOP; + emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2); } /* interface checkcast code */ @@ -2560,37 +2625,32 @@ gen_method: cr, 0); } else { - M_BEQZ(s1, s2 + 2); - M_NOP; + emit_label_beqz(cd, BRANCH_LABEL_3, s1); } M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl)); M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength)); M_ADD_IMM(REG_ITMP3, -superindex, REG_ITMP3); - M_BLEZ(REG_ITMP3, 0); - codegen_add_classcastexception_ref(cd, s1); - M_NOP; + emit_classcast_check(cd, iptr, ICMD_IFLE, REG_ITMP3, s1); + M_ALD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*)); - M_BEQZ(REG_ITMP3, 0); - codegen_add_classcastexception_ref(cd, s1); - M_NOP; + emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_ITMP3, s1); - if (super == NULL) { - /* on sparc we always add 2 to the size of the code we want */ - /* branch over. (1 for branch delay nop, 1 since the base is */ - /* the address of the branch instruction */ - M_BR(s3 + 2); - M_NOP; - } + if (super == NULL) + emit_label_br(cd, BRANCH_LABEL_4); + else + emit_label(cd, BRANCH_LABEL_3); } /* class checkcast code */ if ((super == NULL) || !(super->flags & ACC_INTERFACE)) { if (super == NULL) { + emit_label(cd, BRANCH_LABEL_2); + cr = iptr->sx.s23.s3.c.ref; disp = dseg_add_unique_address(cd, NULL); @@ -2601,8 +2661,7 @@ gen_method: else { disp = dseg_add_address(cd, super->vftbl); - M_BEQZ(s1, s3 + 2); - M_NOP; + emit_label_beqz(cd, BRANCH_LABEL_5, s1); } M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl)); @@ -2620,9 +2679,15 @@ gen_method: #endif /* } */ M_CMP(REG_ITMP3, REG_ITMP2); - M_BULT(0); /* branch if ITMP3 < ITMP2 */ - codegen_add_classcastexception_ref(cd, s1); - M_NOP; + emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1); + + if (super != NULL) + emit_label(cd, BRANCH_LABEL_5); + } + + if (super == NULL) { + emit_label(cd, BRANCH_LABEL_1); + emit_label(cd, BRANCH_LABEL_4); } d = codegen_reg_of_dst(jd, iptr, s1); @@ -2630,8 +2695,8 @@ gen_method: else { /* array type cast-check */ - s1 = emit_load_s1(jd, iptr, rd->argintregs[0]); - M_INTMOVE(s1, rd->argintregs[0]); + s1 = emit_load_s1(jd, iptr, REG_OUT0); + M_INTMOVE(s1, REG_OUT0); disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls); @@ -2645,7 +2710,7 @@ gen_method: else disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls); - M_ALD(rd->argintregs[1], REG_PV, disp); + M_ALD(REG_OUT1, REG_PV, disp); disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast); M_ALD(REG_ITMP3, REG_PV, disp); /* XXX jit-c-call */ @@ -2653,9 +2718,7 @@ gen_method: M_NOP; s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_BEQZ(REG_RESULT_CALLER, 0); - codegen_add_classcastexception_ref(cd, s1); - M_NOP; + emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_RESULT_CALLER, s1); d = codegen_reg_of_dst(jd, iptr, s1); } @@ -2665,6 +2728,7 @@ gen_method: break; case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */ + /* val.a: (classinfo*) superclass */ /* superclass is an interface: * @@ -2705,25 +2769,12 @@ gen_method: s1 = REG_ITMP1; } - /* calculate interface instanceof code size */ - - s2 = 7; - if (super == NULL) - s2 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0); - - /* calculate class instanceof code size */ - - s3 = 8; - if (super == NULL) - s3 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0); - M_CLR(d); /* if class is not resolved, check which code to call */ if (super == NULL) { - M_BEQZ(s1, 5 + (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0) + s2 + 2 + s3); - M_NOP; + emit_label_beqz(cd, BRANCH_LABEL_1, s1); cr = iptr->sx.s23.s3.c.ref; disp = dseg_add_unique_s4(cd, 0); /* super->flags */ @@ -2733,8 +2784,7 @@ gen_method: M_ILD(REG_ITMP3, REG_PV, disp); M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3); - M_BEQZ(REG_ITMP3, s2 + 2 + 2); - M_NOP; + emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3); } /* interface instanceof code */ @@ -2747,8 +2797,7 @@ gen_method: cr, 0); } else { - M_BEQZ(s1, s2 + 2); - M_NOP; + emit_label_beqz(cd, BRANCH_LABEL_3, s1); } M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl)); @@ -2761,16 +2810,18 @@ gen_method: superindex * sizeof(methodptr*))); M_CMOVRNE_IMM(REG_ITMP1, 1, d); /* REG_ITMP1 != 0 */ - if (super == NULL) { - M_BR(s3 + 2); - M_NOP; - } + if (super == NULL) + emit_label_br(cd, BRANCH_LABEL_4); + else + emit_label(cd, BRANCH_LABEL_3); } /* class instanceof code */ if ((super == NULL) || !(super->flags & ACC_INTERFACE)) { if (super == NULL) { + emit_label(cd, BRANCH_LABEL_2); + cr = iptr->sx.s23.s3.c.ref; disp = dseg_add_unique_address(cd, NULL); @@ -2780,8 +2831,7 @@ gen_method: else { disp = dseg_add_address(cd, supervftbl); - M_BEQZ(s1, s3 + 2); - M_NOP; + emit_label_beqz(cd, BRANCH_LABEL_5, s1); } M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl)); @@ -2798,7 +2848,16 @@ gen_method: M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1); M_CMP(REG_ITMP1, REG_ITMP2); M_XCMOVULE_IMM(1, d); + + if (super != NULL) + emit_label(cd, BRANCH_LABEL_5); + } + + if (super == NULL) { + emit_label(cd, BRANCH_LABEL_1); + emit_label(cd, BRANCH_LABEL_4); } + emit_store_dst(jd, iptr, d); } break; @@ -2855,9 +2914,7 @@ gen_method: /* check for exception before result assignment */ - M_BEQZ(REG_RESULT_CALLER, 0); - codegen_add_fillinstacktrace_ref(cd); - M_NOP; + emit_exception_check(cd, iptr); d = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER); M_INTMOVE(REG_RESULT_CALLER, d); @@ -2880,15 +2937,10 @@ gen_method: dseg_createlinenumbertable(cd); - /* generate exception and patcher stubs */ + /* generate stubs */ - emit_exception_stubs(jd); emit_patcher_stubs(jd); -#if defined(ENABLE_REPLACEMENT) - emit_replacement_stubs(jd); -#endif /* defined(ENABLE_REPLACEMENT) */ - - codegen_finish(jd); + REPLACEMENT_EMIT_STUBS(jd); /* everything's ok */ @@ -2896,85 +2948,43 @@ gen_method: } +/* codegen_emit_stub_compiler ************************************************** - - -/* createcompilerstub ********************************************************** - - Creates a stub routine which calls the compiler. + Emits a stub routine which calls the compiler. *******************************************************************************/ -#define COMPILERSTUB_DATASIZE 3 * SIZEOF_VOID_P -#define COMPILERSTUB_CODESIZE 4 * 4 - -#define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE - - -u1 *createcompilerstub(methodinfo *m) +void codegen_emit_stub_compiler(jitdata *jd) { - u1 *s; /* memory to hold the stub */ - ptrint *d; - codeinfo *code; + methodinfo *m; codegendata *cd; - s4 dumpsize; - - s = CNEW(u1, COMPILERSTUB_SIZE); - - /* set data pointer and code pointer */ - - d = (ptrint *) s; - s = s + COMPILERSTUB_DATASIZE; - /* mark start of dump memory area */ - - dumpsize = dump_size(); - - cd = DNEW(codegendata); - cd->mcodeptr = s; - - /* Store the codeinfo pointer in the same place as in the - methodheader for compiled methods. */ - - code = code_codeinfo_new(m); + /* get required compiler data */ - d[0] = (ptrint) asm_call_jit_compiler; - d[1] = (ptrint) m; - d[2] = (ptrint) code; + m = jd->m; + cd = jd->cd; /* code for the stub */ + /* no window save yet, user caller's PV */ M_ALD_INTERN(REG_ITMP1, REG_PV_CALLER, -2 * SIZEOF_VOID_P); /* codeinfo pointer */ M_ALD_INTERN(REG_PV_CALLER, REG_PV_CALLER, -3 * SIZEOF_VOID_P); /* pointer to compiler */ M_JMP(REG_ZERO, REG_PV_CALLER, REG_ZERO); /* jump to the compiler, RA is wasted */ M_NOP; - -#if defined(ENABLE_STATISTICS) - if (opt_stat) - count_cstub_len += COMPILERSTUB_SIZE; -#endif - - /* release dump area */ - - dump_release(dumpsize); - - return s; } +/* codegen_emit_stub_native **************************************************** -/* createnativestub ************************************************************ - - Creates a stub routine which calls a native method. + Emits a stub routine which calls a native method. *******************************************************************************/ -u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) +void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) { methodinfo *m; codeinfo *code; codegendata *cd; - registerdata *rd; methoddesc *md; s4 nativeparams; s4 i, j; /* count variables */ @@ -2987,10 +2997,6 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) m = jd->m; code = jd->code; cd = jd->cd; - rd = jd->rd; - - /* redo param allocation */ - md_native_param_alloc(nmd); /* initialize variables */ @@ -3040,7 +3046,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) { if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) { - M_DST(rd->argfltregs[i], REG_SP, CSTACK + (j * 8)); + M_DST(abi_registers_float_argument[i], REG_SP, CSTACK + (j * 8)); j++; } } @@ -3060,7 +3066,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) { if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) { - M_DLD(rd->argfltregs[i], REG_SP, CSTACK + (j * 8)); + M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + (j * 8)); j++; } } @@ -3073,7 +3079,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) if (IS_INT_LNG_TYPE(t)) { if (!md->params[i].inmemory) { - s1 = rd->argintregs[md->params[i].regoff]; + s1 = md->params[i].regoff; /* s1 refers to the old window, transpose */ s1 = REG_WINDOW_TRANSPOSE(s1); @@ -3086,6 +3092,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) } } else { + /*assert(false);*/ s1 = md->params[i].regoff + cd->stackframesize; s2 = nmd->params[j].regoff - 6; M_ALD(REG_ITMP1, REG_SP, CSTACK + s1 * 8); @@ -3094,7 +3101,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) } else { if (!md->params[i].inmemory) { - s1 = rd->argfltregs[md->params[i].regoff]; + s1 = md->params[i].regoff; if (!nmd->params[j].inmemory) { /* no mapping to regs needed, native flt args use regoff */ @@ -3104,7 +3111,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) M_DMOV(s1, s2 + 16); fltregarg_inswap[num_fltregargs] = s2; num_fltregargs++; - printf("flt arg swap to %d\n", s2 + 16); + /*printf("flt arg swap to %d\n", s2 + 16);*/ } else { s2 = nmd->params[j].regoff; @@ -3115,6 +3122,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) } } else { + /*assert(false);*/ s1 = md->params[i].regoff + cd->stackframesize; s2 = nmd->params[j].regoff - 6; if (IS_2_WORD_TYPE(t)) { @@ -3132,7 +3140,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) for (i = 0; i < num_fltregargs; i++) { s1 = fltregarg_inswap[i]; M_DMOV(s1 + 16, s1); - printf("float arg to target reg: %d ==> %d\n", s1+16, s1); + /*printf("float arg to target reg: %d ==> %d\n", s1+16, s1);*/ } @@ -3196,33 +3204,23 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) } /* check for exception */ - M_BNEZ(REG_ITMP2_XPTR, 4); /* if no exception then return */ M_NOP; M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */ M_NOP; -#if 0 - M_RESTORE(REG_ZERO, 0, REG_ZERO); /* restore callers window (DELAY) */ - - M_RET(REG_RA_CALLER, 8); /* return to caller */ - M_NOP; /* DELAY SLOT */ -#endif /* handle exception */ disp = dseg_add_functionptr(cd, asm_handle_nat_exception); - M_ALD(REG_ITMP3, REG_PV, disp); /* load asm exception handler address */ - M_JMP(REG_ZERO, REG_ITMP3, REG_ZERO);/* jump to asm exception handler */ - M_MOV(REG_RA_CALLEE, REG_ITMP3_XPC); /* get exception address (DELAY) */ - + M_ALD(REG_ITMP1, REG_PV, disp); /* load asm exception handler address */ + M_MOV(REG_RA_CALLEE, REG_ITMP3_XPC); /* get exception address */ + M_JMP(REG_ZERO, REG_ITMP1, REG_ZERO);/* jump to asm exception handler */ + M_RESTORE(REG_ZERO, 0, REG_ZERO); /* restore callers window (DELAY) */ + /* generate patcher stubs */ emit_patcher_stubs(jd); - - codegen_finish(jd); - - return code->entrypoint; } /*