classinfo *super;
s4 superindex;
+ s4 looptarget;
+
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
super = NULL;
superindex = 0;
M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
M_ALD(REG_ITMP3, RIP, disp);
- M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
+ if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+ M_AADD_IMM(-32, REG_SP); /* need some stack */
+ if (s1 == REG_ITMP1)
+ M_AST(REG_ITMP1, REG_SP, -8 + 32);
- /* if (s1 != REG_ITMP1) { */
- /* emit_movl_membase_reg(cd, REG_ITMP3, */
- /* OFFSET(vftbl_t, baseval), */
- /* REG_ITMP1); */
- /* emit_movl_membase_reg(cd, REG_ITMP3, */
- /* OFFSET(vftbl_t, diffval), */
- /* REG_ITMP3); */
- /* #if defined(ENABLE_THREADS) */
- /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
- /* #endif */
- /* emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
+ M_ALD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
- /* } else { */
+ *(cd->mcodeptr++) = 0x4d;
+ *(cd->mcodeptr++) = 0x3b;
+ *(cd->mcodeptr++) = 0x1c;
+ *(cd->mcodeptr++) = 0x02;
+ /* cmp (ITMP2, ITMP1, 1), ITMP3 */
- M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
- M_ISUB(REG_ITMP3, REG_ITMP2);
- M_ALD(REG_ITMP3, RIP, disp);
- M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
- /* } */
+ emit_label_beq(cd, BRANCH_LABEL_6); /* good */
+
+ M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
+ emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
+
+ M_AST(REG_ITMP3, REG_SP, -16 + 32);
+ M_AST_IMM32(0, REG_SP, -24 + 32);
+ M_ALD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+ looptarget = cd->mcodeptr - cd->mcodebase;
+
+ M_ALD(REG_ITMP3, REG_SP, -24 + 32);
+ M_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_overflow_length), REG_ITMP3);
+ emit_label_bge(cd, BRANCH_LABEL_9); /* throw */
+
+ *(cd->mcodeptr++) = 0x4e;
+ *(cd->mcodeptr++) = 0x8b;
+ *(cd->mcodeptr++) = 0x1c;
+ *(cd->mcodeptr++) = 0xd8;
+ /* movq (ITMP1, ITMP3, 8), ITMP3 */
+
+ M_LCMP_MEMBASE(REG_SP, -16 + 32, REG_ITMP3);
+ emit_label_beq(cd, BRANCH_LABEL_7); /* good, pop */
+
+ M_LINC_MEMBASE(REG_SP, -24 + 32);
+ M_JMP_IMM2(looptarget - (cd->mcodeptr - cd->mcodebase) - 2); /* 1 byte displacement */
+
+ emit_label(cd, BRANCH_LABEL_9);
+ M_AADD_IMM(32, REG_SP); /* restore stack frame */
+ M_ALD_MEM(REG_ITMP3, TRAP_ClassCastException);
+
+ emit_label(cd, BRANCH_LABEL_7);
+
+ emit_label(cd, BRANCH_LABEL_6);
- M_ICMP(REG_ITMP3, REG_ITMP2);
- emit_classcast_check(cd, iptr, BRANCH_UGT, REG_ITMP3, s1);
+ if (s1 == REG_ITMP1)
+ M_ALD(REG_ITMP1, REG_SP, -8 + 32);
+ M_AADD_IMM(32, REG_SP);
+ }
+ else {
+ assert(super->vftbl->subtype_offset < 0x80);
+ *(cd->mcodeptr++) = 0x4d;
+ *(cd->mcodeptr++) = 0x3b;
+ *(cd->mcodeptr++) = 0x5a;
+ *(cd->mcodeptr++) = super->vftbl->subtype_offset;
+ /* cmp off(ITMP1), ITMP2 */
+
+ emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
+ }
if (super != NULL)
emit_label(cd, BRANCH_LABEL_5);
classinfo *super;
s4 superindex;
+ s4 looptarget;
+
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
super = NULL;
superindex = 0;
disp = dseg_add_address(cd, super->vftbl);
}
- M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
- M_ALD(REG_ITMP2, RIP, disp);
-
- M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
- M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, diffval));
- M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
+ M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
+ M_ALD(REG_ITMP3, RIP, disp);
+
+ if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+ M_AADD_IMM(-32, REG_SP); /* need some stack */
+ M_ALD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+
+ *(cd->mcodeptr++) = 0x4d;
+ *(cd->mcodeptr++) = 0x3b;
+ *(cd->mcodeptr++) = 0x1c;
+ *(cd->mcodeptr++) = 0x02;
+ /* cmp (ITMP2, ITMP1, 1), ITMP3 */
+
+ emit_label_bne(cd, BRANCH_LABEL_6);
+ if (d == REG_ITMP2) {
+ M_SETE(d);
+ M_BSEXT(d, d);
+ } else
+ M_LINC(d);
+ emit_label_br(cd, BRANCH_LABEL_7); /* ende true */
+
+ emit_label(cd, BRANCH_LABEL_6);
+
+ M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
+ emit_label_bne(cd, BRANCH_LABEL_6); /* ende false */
+
+ M_AST(REG_ITMP3, REG_SP, -16 + 32);
+ M_AST_IMM32(0, REG_SP, -24 + 32);
+ M_ALD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+ looptarget = cd->mcodeptr - cd->mcodebase;
+
+ M_ALD(REG_ITMP3, REG_SP, -24 + 32);
+ M_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_overflow_length), REG_ITMP3);
+ emit_label_bge(cd, BRANCH_LABEL_8); /* ende false */
+
+ *(cd->mcodeptr++) = 0x4e;
+ *(cd->mcodeptr++) = 0x8b;
+ *(cd->mcodeptr++) = 0x1c;
+ *(cd->mcodeptr++) = 0xd8;
+ /* movq (ITMP1, ITMP3, 8), ITMP3 */
+
+ M_LCMP_MEMBASE(REG_SP, -16 + 32, REG_ITMP3);
+ emit_label_bne(cd, BRANCH_LABEL_9);
+ if (d == REG_ITMP2) {
+ M_SETE(d);
+ M_BSEXT(d, d);
+ } else
+ M_LINC(d);
+ emit_label_br(cd, BRANCH_LABEL_10); /* ende true */
+ emit_label(cd, BRANCH_LABEL_9);
+
+ M_LINC_MEMBASE(REG_SP, -24 + 32);
+ M_JMP_IMM2(looptarget - (cd->mcodeptr - cd->mcodebase) - 2); /* 1 byte displacement */
+
+ emit_label(cd, BRANCH_LABEL_8);
+ emit_label(cd, BRANCH_LABEL_6);
+
+ if (d == REG_ITMP2)
+ M_CLR(d);
- M_ISUB(REG_ITMP2, REG_ITMP1);
- M_CLR(d); /* may be REG_ITMP2 */
- M_ICMP(REG_ITMP3, REG_ITMP1);
- M_SETULE(d);
+ emit_label(cd, BRANCH_LABEL_10);
+ emit_label(cd, BRANCH_LABEL_7);
+ M_AADD_IMM(32, REG_SP);
+ }
+ else {
+ assert(super->vftbl->subtype_offset < 0x80);
+ *(cd->mcodeptr++) = 0x4d;
+ *(cd->mcodeptr++) = 0x3b;
+ *(cd->mcodeptr++) = 0x5a;
+ *(cd->mcodeptr++) = super->vftbl->subtype_offset;
+ /* cmp off(ITMP1), ITMP2 */
+
+ M_SETE(d);
+ if (d == REG_ITMP2)
+ M_BSEXT(d, d);
+ }
if (super != NULL)
emit_label(cd, BRANCH_LABEL_5);