+ case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
+ /* val.a: (classinfo*) superclass */
+
+ /* superclass is an interface:
+ *
+ * return (sub != NULL) &&
+ * (sub->vftbl->interfacetablelength > super->index) &&
+ * (sub->vftbl->interfacetable[-super->index] != NULL);
+ *
+ * superclass is a class:
+ *
+ * return ((sub != NULL) && (0
+ * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
+ * super->vftbl->diffvall));
+ */
+
+ {
+ classinfo *super;
+ vftbl_t *supervftbl;
+ s4 superindex;
+
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ super = NULL;
+ superindex = 0;
+ supervftbl = NULL;
+
+ } else {
+ super = iptr->sx.s23.s3.c.cls;
+ superindex = super->index;
+ supervftbl = super->vftbl;
+ }
+
+ if ((super == NULL) || !(super->flags & ACC_INTERFACE))
+ CODEGEN_CRITICAL_SECTION_NEW;
+
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+ if (s1 == d) {
+ M_MOV(s1, REG_ITMP1);
+ s1 = REG_ITMP1;
+ }
+
+ M_CLR(d);
+
+ /* if class is not resolved, check which code to call */
+
+ if (super == NULL) {
+ emit_label_beqz(cd, BRANCH_LABEL_1, s1);
+
+ cr = iptr->sx.s23.s3.c.ref;
+ disp = dseg_add_unique_s4(cd, 0); /* super->flags */
+
+ codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
+ cr, disp);
+
+ M_ILD(REG_ITMP3, REG_PV, disp);
+ M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
+ emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
+ }
+
+ /* interface instanceof code */
+
+ if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
+ if (super == NULL) {
+ cr = iptr->sx.s23.s3.c.ref;
+
+ codegen_add_patch_ref(cd, PATCHER_instanceof_interface,
+ cr, 0);
+ }
+ else {
+ emit_label_beqz(cd, BRANCH_LABEL_3, s1);
+ }
+
+ M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
+ M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
+ M_CMP_IMM(REG_ITMP3, superindex);
+ M_BLE(4);
+ M_NOP;
+ M_ALD(REG_ITMP1, REG_ITMP1,
+ (s4) (OFFSET(vftbl_t, interfacetable[0]) -
+ superindex * sizeof(methodptr*)));
+ M_CMOVRNE_IMM(REG_ITMP1, 1, d); /* REG_ITMP1 != 0 */
+
+ 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);
+
+ codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_class,
+ cr, disp);
+ }
+ else {
+ disp = dseg_add_address(cd, supervftbl);
+
+ 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);
+
+ CODEGEN_CRITICAL_SECTION_START;
+
+ 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));
+
+ CODEGEN_CRITICAL_SECTION_END;
+
+ 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;
+
+ case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
+
+ /* check for negative sizes and copy sizes to stack if necessary */
+
+ MCODECHECK((iptr->s1.argcount << 1) + 64);
+
+ for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
+
+ var = VAR(iptr->sx.s23.s2.args[s1]);
+
+ /* copy SAVEDVAR sizes to stack */
+
+ /* Already Preallocated? */
+
+ if (!(var->flags & PREALLOC)) {
+ s2 = emit_load(jd, iptr, var, REG_ITMP1);
+ M_STX(s2, REG_SP, CSTACK + (s1 * 8));
+ }
+ }
+
+ /* arg 0 = dimension count */
+
+ ICONST(REG_OUT0, iptr->s1.argcount);
+
+ /* is patcher function set? */
+
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ disp = dseg_add_unique_address(cd, 0);
+
+ codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
+ iptr->sx.s23.s3.c.ref,
+ disp);
+ }
+ else
+ disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
+
+ /* arg 1 = arraydescriptor */
+
+ M_ALD(REG_OUT1, REG_PV, disp);