Merged branch subtype-trunk into default.
[cacao.git] / src / vm / jit / alpha / codegen.c
index aa899028330e1475bdf04ad1a8b48368977af8e1..a49b1a0af59426899539c7e7a9ec37272353f68e 100644 (file)
 #include "vm/jit/alpha/arch.h"
 #include "vm/jit/alpha/codegen.h"
 
-#include "mm/memory.h"
+#include "mm/memory.hpp"
 
-#include "native/jni.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/vm.h"
+#include "vm/loader.hpp"
+#include "vm/options.h"
+#include "vm/vm.hpp"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
-#include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
+#include "vm/jit/parse.hpp"
+#include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/replace.hpp"
+#include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.h"
 
 #if defined(ENABLE_SSA)
@@ -70,9 +71,6 @@
 # include "vm/jit/allocator/lsra.h"
 #endif
 
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
 
 /* codegen_emit ****************************************************************
 
@@ -1117,17 +1115,13 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_FADD(s1, s2, d);
+                       if (d == s1 || d == s2) {
+                               M_FADDS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FMOV(REG_FTMP3, d);
                        } else {
-                               if (d == s1 || d == s2) {
-                                       M_FADDS(s1, s2, REG_FTMP3);
-                                       M_TRAPB;
-                                       M_FMOV(REG_FTMP3, d);
-                               } else {
-                                       M_FADDS(s1, s2, d);
-                                       M_TRAPB;
-                               }
+                               M_FADDS(s1, s2, d);
+                               M_TRAPB;
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1137,17 +1131,13 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_DADD(s1, s2, d);
+                       if (d == s1 || d == s2) {
+                               M_DADDS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FMOV(REG_FTMP3, d);
                        } else {
-                               if (d == s1 || d == s2) {
-                                       M_DADDS(s1, s2, REG_FTMP3);
-                                       M_TRAPB;
-                                       M_FMOV(REG_FTMP3, d);
-                               } else {
-                                       M_DADDS(s1, s2, d);
-                                       M_TRAPB;
-                               }
+                               M_DADDS(s1, s2, d);
+                               M_TRAPB;
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1157,17 +1147,13 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_FSUB(s1, s2, d);
+                       if (d == s1 || d == s2) {
+                               M_FSUBS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FMOV(REG_FTMP3, d);
                        } else {
-                               if (d == s1 || d == s2) {
-                                       M_FSUBS(s1, s2, REG_FTMP3);
-                                       M_TRAPB;
-                                       M_FMOV(REG_FTMP3, d);
-                               } else {
-                                       M_FSUBS(s1, s2, d);
-                                       M_TRAPB;
-                               }
+                               M_FSUBS(s1, s2, d);
+                               M_TRAPB;
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1177,17 +1163,13 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_DSUB(s1, s2, d);
+                       if (d == s1 || d == s2) {
+                               M_DSUBS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FMOV(REG_FTMP3, d);
                        } else {
-                               if (d == s1 || d == s2) {
-                                       M_DSUBS(s1, s2, REG_FTMP3);
-                                       M_TRAPB;
-                                       M_FMOV(REG_FTMP3, d);
-                               } else {
-                                       M_DSUBS(s1, s2, d);
-                                       M_TRAPB;
-                               }
+                               M_DSUBS(s1, s2, d);
+                               M_TRAPB;
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1197,17 +1179,13 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_FMUL(s1, s2, d);
+                       if (d == s1 || d == s2) {
+                               M_FMULS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FMOV(REG_FTMP3, d);
                        } else {
-                               if (d == s1 || d == s2) {
-                                       M_FMULS(s1, s2, REG_FTMP3);
-                                       M_TRAPB;
-                                       M_FMOV(REG_FTMP3, d);
-                               } else {
-                                       M_FMULS(s1, s2, d);
-                                       M_TRAPB;
-                               }
+                               M_FMULS(s1, s2, d);
+                               M_TRAPB;
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1217,17 +1195,13 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_DMUL(s1, s2, d);
+                       if (d == s1 || d == s2) {
+                               M_DMULS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FMOV(REG_FTMP3, d);
                        } else {
-                               if (d == s1 || d == s2) {
-                                       M_DMULS(s1, s2, REG_FTMP3);
-                                       M_TRAPB;
-                                       M_FMOV(REG_FTMP3, d);
-                               } else {
-                                       M_DMULS(s1, s2, d);
-                                       M_TRAPB;
-                               }
+                               M_DMULS(s1, s2, d);
+                               M_TRAPB;
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1237,17 +1211,13 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_FDIV(s1, s2, d);
+                       if (d == s1 || d == s2) {
+                               M_FDIVS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FMOV(REG_FTMP3, d);
                        } else {
-                               if (d == s1 || d == s2) {
-                                       M_FDIVS(s1, s2, REG_FTMP3);
-                                       M_TRAPB;
-                                       M_FMOV(REG_FTMP3, d);
-                               } else {
-                                       M_FDIVS(s1, s2, d);
-                                       M_TRAPB;
-                               }
+                               M_FDIVS(s1, s2, d);
+                               M_TRAPB;
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1257,17 +1227,13 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_DDIV(s1, s2, d);
+                       if (d == s1 || d == s2) {
+                               M_DDIVS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FMOV(REG_FTMP3, d);
                        } else {
-                               if (d == s1 || d == s2) {
-                                       M_DDIVS(s1, s2, REG_FTMP3);
-                                       M_TRAPB;
-                                       M_FMOV(REG_FTMP3, d);
-                               } else {
-                                       M_DDIVS(s1, s2, d);
-                                       M_TRAPB;
-                               }
+                               M_DDIVS(s1, s2, d);
+                               M_TRAPB;
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1330,12 +1296,8 @@ bool codegen_emit(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       if (opt_noieee) {
-                               M_CVTDF(s1, d);
-                       } else {
-                               M_CVTDFS(s1, d);
-                               M_TRAPB;
-                       }
+                       M_CVTDFS(s1, d);
+                       M_TRAPB;
                        emit_store_dst(jd, iptr, d);
                        break;
                
@@ -1344,25 +1306,15 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       if (opt_noieee) {
-                               M_LSUB_IMM(REG_ZERO, 1, d);
-                               M_FCMPEQ(s1, s2, REG_FTMP3);
-                               M_FBEQZ (REG_FTMP3, 1);        /* jump over next instructions */
-                               M_CLR   (d);
-                               M_FCMPLT(s2, s1, REG_FTMP3);
-                               M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
-                               M_LADD_IMM(REG_ZERO, 1, d);
-                       } else {
-                               M_LSUB_IMM(REG_ZERO, 1, d);
-                               M_FCMPEQS(s1, s2, REG_FTMP3);
-                               M_TRAPB;
-                               M_FBEQZ (REG_FTMP3, 1);        /* jump over next instructions */
-                               M_CLR   (d);
-                               M_FCMPLTS(s2, s1, REG_FTMP3);
-                               M_TRAPB;
-                               M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
-                               M_LADD_IMM(REG_ZERO, 1, d);
-                       }
+                       M_LSUB_IMM(REG_ZERO, 1, d);
+                       M_FCMPEQS(s1, s2, REG_FTMP3);
+                       M_TRAPB;
+                       M_FBEQZ (REG_FTMP3, 1);        /* jump over next instructions */
+                       M_CLR   (d);
+                       M_FCMPLTS(s2, s1, REG_FTMP3);
+                       M_TRAPB;
+                       M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
+                       M_LADD_IMM(REG_ZERO, 1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
                        
@@ -1371,25 +1323,15 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       if (opt_noieee) {
-                               M_LADD_IMM(REG_ZERO, 1, d);
-                               M_FCMPEQ(s1, s2, REG_FTMP3);
-                               M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
-                               M_CLR   (d);
-                               M_FCMPLT(s1, s2, REG_FTMP3);
-                               M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
-                               M_LSUB_IMM(REG_ZERO, 1, d);
-                       } else {
-                               M_LADD_IMM(REG_ZERO, 1, d);
-                               M_FCMPEQS(s1, s2, REG_FTMP3);
-                               M_TRAPB;
-                               M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
-                               M_CLR   (d);
-                               M_FCMPLTS(s1, s2, REG_FTMP3);
-                               M_TRAPB;
-                               M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
-                               M_LSUB_IMM(REG_ZERO, 1, d);
-                       }
+                       M_LADD_IMM(REG_ZERO, 1, d);
+                       M_FCMPEQS(s1, s2, REG_FTMP3);
+                       M_TRAPB;
+                       M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
+                       M_CLR   (d);
+                       M_FCMPLTS(s1, s2, REG_FTMP3);
+                       M_TRAPB;
+                       M_FBEQZ (REG_FTMP3, 1);        /* jump over next instruction  */
+                       M_LSUB_IMM(REG_ZERO, 1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -2780,24 +2722,49 @@ gen_method:
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
                                        M_ALD(REG_ITMP3, REG_PV, disp);
 
-                                       M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
-                                       /*                              if (s1 != REG_ITMP1) { */
-                                       /*                                      M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
-                                       /*                                      M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
-                                       /*  #if defined(ENABLE_THREADS) */
-                                       /*                                      codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
-                                       /*  #endif */
-                                       /*                                      M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
-
-                                       /*                              } else { */
-                                       M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
-                                       M_ISUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
-                                       M_ALD(REG_ITMP3, REG_PV, disp);
-                                       M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
-
-                                       /*                              } */
-                                       M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3);
-                                       emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
+                                       if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+                                               M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                               M_LADD(REG_ITMP1, REG_ITMP2, REG_ITMP1);
+                                               M_ALD(REG_ITMP1, REG_ITMP1, 0);
+                                               M_CMPEQ(REG_ITMP1, REG_ITMP3, REG_ITMP1);
+                                               emit_label_bnez(cd, BRANCH_LABEL_6, REG_ITMP1);  /* good */
+
+                                               if (super == NULL) {
+                                                       M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                                       M_CMPEQ_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
+                                                       emit_label_beqz(cd, BRANCH_LABEL_10, REG_ITMP1);  /* throw */
+                                               }
+
+                                               M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
+                                               M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
+                                               M_CMPLE(REG_ITMP1, REG_ITMP3, REG_ITMP3);
+                                               emit_label_beqz(cd, BRANCH_LABEL_9, REG_ITMP3);  /* throw */
+                                               /* reload */
+                                               M_ALD(REG_ITMP3, REG_PV, disp);
+                                               M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+                                               M_S8ADDQ(REG_ITMP1, REG_ITMP2, REG_ITMP2);
+                                               M_ALD(REG_ITMP1, REG_ITMP2, -DISPLAY_SIZE*8);
+                                               M_CMPEQ(REG_ITMP1, REG_ITMP3, REG_ITMP1);
+                                               emit_label_bnez(cd, BRANCH_LABEL_7, REG_ITMP1);  /* good */
+
+                                               emit_label(cd, BRANCH_LABEL_9);
+                                               if (super == NULL)
+                                                       emit_label(cd, BRANCH_LABEL_10);
+
+                                               /* reload s1, might have been destroyed */
+                                               emit_load_s1(jd, iptr, REG_ITMP1);
+                                               M_ALD_INTERN(s1, REG_ZERO, TRAP_ClassCastException);
+
+                                               emit_label(cd, BRANCH_LABEL_7);
+                                               emit_label(cd, BRANCH_LABEL_6);
+                                               /* reload s1, might have been destroyed */
+                                               emit_load_s1(jd, iptr, REG_ITMP1);
+                                       }
+                                       else {
+                                               M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
+                                               M_CMPEQ(REG_ITMP2, REG_ITMP3, REG_ITMP2);
+                                               emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
+                                       }
 
                                        if (super != NULL)
                                                emit_label(cd, BRANCH_LABEL_5);
@@ -2941,15 +2908,53 @@ gen_method:
                                        emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                }
 
-                               M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
-                               M_ALD(REG_ITMP2, REG_PV, disp);
+                               M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
+                               M_ALD(REG_ITMP3, REG_PV, disp);
 
-                               M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
-                               M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
-                               M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
+                               if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+                                       M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                       M_LADD(REG_ITMP1, REG_ITMP2, REG_ITMP1);
+                                       M_ALD(REG_ITMP1, REG_ITMP1, 0);
+                                       M_CMPEQ(REG_ITMP1, REG_ITMP3, REG_ITMP1);
+                                       emit_label_beqz(cd, BRANCH_LABEL_8, REG_ITMP1);
+                                       ICONST(d, 1);
+                                       emit_label_br(cd, BRANCH_LABEL_6);  /* true */
+                                       emit_label(cd, BRANCH_LABEL_8);
+
+                                       if (super == NULL) {
+                                               M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                               M_CMPEQ_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
+                                               emit_label_beqz(cd, BRANCH_LABEL_10, REG_ITMP1);  /* false */
+                                       }
+
+                                       M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
+
+                                       M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
+                                       M_CMPLE(REG_ITMP1, REG_ITMP3, REG_ITMP3);
+                                       emit_label_beqz(cd, BRANCH_LABEL_9, REG_ITMP3);  /* false */
+                                       /* reload */
+                                       M_ALD(REG_ITMP3, REG_PV, disp);
+                                       M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+                                       M_S8ADDQ(REG_ITMP1, REG_ITMP2, REG_ITMP2);
+                                       M_ALD(REG_ITMP1, REG_ITMP2, -DISPLAY_SIZE*8);
+                                       M_CMPEQ(REG_ITMP1, REG_ITMP3, d);
 
-                               M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
-                               M_CMPULE(REG_ITMP1, REG_ITMP2, d);
+                                       if (d == REG_ITMP2)
+                                               emit_label_br(cd, BRANCH_LABEL_7);
+                                       emit_label(cd, BRANCH_LABEL_9);
+                                       if (super == NULL)
+                                               emit_label(cd, BRANCH_LABEL_10);
+                                       if (d == REG_ITMP2) {
+                                               M_CLR(d);
+
+                                               emit_label(cd, BRANCH_LABEL_7);
+                                       }
+                                       emit_label(cd, BRANCH_LABEL_6);
+                               }
+                               else {
+                                       M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
+                                       M_CMPEQ(REG_ITMP2, REG_ITMP3, d);
+                               }
 
                                if (super != NULL)
                                        emit_label(cd, BRANCH_LABEL_5);
@@ -3222,7 +3227,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s
 
                /* put env into first argument register */
 
-               disp = dseg_add_address(cd, _Jv_env);
+               disp = dseg_add_address(cd, VM_get_jnienv());
                M_ALD(REG_A0, REG_PV, disp);
        }