/* src/vm/jit/x86_64/codegen.c - machine code generator for x86_64
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "mm/memory.h"
-#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/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/loader.hpp"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/statistics.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/code.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/code.hpp"
+#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/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
#include "vm/jit/methodheader.h"
-#include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#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_LSRA)
# include "vm/jit/allocator/lsra.h"
#endif
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-
/* codegen_emit ****************************************************************
if (IS_IMM32(iptr->sx.s23.s2.constval))
M_LST_IMM32(iptr->sx.s23.s2.constval, REG_ITMP1, 0);
else {
- M_IST_IMM(iptr->sx.s23.s2.constval, REG_ITMP1, 0);
- M_IST_IMM(iptr->sx.s23.s2.constval >> 32, REG_ITMP1, 4);
+ M_MOV_IMM(iptr->sx.s23.s2.constval, REG_ITMP2);
+ M_LST(REG_ITMP2, REG_ITMP1, 0);
}
break;
}
case TYPE_LNG:
case TYPE_ADR:
case TYPE_DBL:
- /* XXX why no check for IS_IMM32? */
- M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
- M_IST32_IMM(iptr->sx.s23.s2.constval >> 32, s1, disp + 4);
+ /* XXX why no check for IS_IMM32? -- probably because of the patcher */
+ M_MOV_IMM(iptr->sx.s23.s2.constval, REG_ITMP2);
+ if (disp) /* resolved, disp can never be 0 */
+ M_LST(REG_ITMP2, s1, disp);
+ else /* unresolved */
+ M_LST32(REG_ITMP2, s1, disp);
break;
}
break;
classinfo *super;
s4 superindex;
- s4 looptarget;
-
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
super = NULL;
superindex = 0;
disp = dseg_add_address(cd, super->vftbl);
}
- if (s1 == REG_ITMP1)
- M_AST(REG_ITMP1, REG_SP, -8); /* store in red zone */
-
- M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
- M_ALD(REG_ITMP2, RIP, disp);
+ 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_ALD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, subtype_offset));
-
- *(cd->mcodeptr++) = 0x4e;
- *(cd->mcodeptr++) = 0x3b;
- *(cd->mcodeptr++) = 0x14;
- *(cd->mcodeptr++) = 0x18;
- /* cmp (ITMP1, ITMP3, 1), ITMP2 */
-
- emit_label_beq(cd, BRANCH_LABEL_6); /* good */
-
- M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP3);
- emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
-
- /* use red zone */
- M_AST(REG_ITMP2, REG_SP, -16);
- M_AST_IMM32(0, REG_SP, -24);
- M_ALD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, subtype_overflow));
- looptarget = cd->mcodeptr - cd->mcodebase;
-
- M_ALD(REG_ITMP2, REG_SP, -24);
- M_ICMP_MEMBASE(REG_ITMP1, OFFSET(vftbl_t, subtype_overflow_length), REG_ITMP2);
-
- emit_classcast_check(cd, iptr, BRANCH_GE, REG_ITMP3, s1);
-
- *(cd->mcodeptr++) = 0x4f;
- *(cd->mcodeptr++) = 0x8b;
- *(cd->mcodeptr++) = 0x14;
- *(cd->mcodeptr++) = 0xd3;
- /* movq (ITMP3, ITMP2, 8), ITMP2 */
-
- M_LCMP_MEMBASE(REG_SP, -16, REG_ITMP2);
- emit_label_beq(cd, BRANCH_LABEL_7); /* good, pop */
-
- M_LINC_MEMBASE(REG_SP, -24);
- M_JMP_IMM2(looptarget - (cd->mcodeptr - cd->mcodebase) - 2); /* 1 byte displacement */
-
- emit_label(cd, BRANCH_LABEL_7);
-
- emit_label(cd, BRANCH_LABEL_6);
+ M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+ M_LCMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3);
+ emit_label_beq(cd, BRANCH_LABEL_6); /* good */
+
+ if (super == NULL) {
+ M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
+ emit_label_bne(cd, BRANCH_LABEL_10); /* throw */
+ }
+
+ M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
+ M_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1);
+ emit_label_bgt(cd, BRANCH_LABEL_9); /* throw */
+
+ M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+ M_LCMP_MEMINDEX(REG_ITMP2, -8*DISPLAY_SIZE, REG_ITMP1, 3, REG_ITMP3);
+ emit_label_beq(cd, BRANCH_LABEL_7); /* 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_MEM(s1, 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 {
- assert(super->vftbl->subtype_offset < 0x80);
- *(cd->mcodeptr++) = 0x4c;
- *(cd->mcodeptr++) = 0x3b;
- *(cd->mcodeptr++) = 0x50;
- *(cd->mcodeptr++) = super->vftbl->subtype_offset;
- /* cmp off(ITMP1), ITMP2 */
-
+ M_LCMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3);
emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
}
- if (s1 == REG_ITMP1)
- M_ALD(REG_ITMP1, REG_SP, -8);
-
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_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_ALD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, subtype_offset));
+ M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+ M_LCMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3);
+ emit_label_bne(cd, BRANCH_LABEL_8); /* jump over INC/SETE */
+ if (d == REG_ITMP2) {
+ M_SETE(d);
+ M_BSEXT(d, d);
+ } else
+ M_LINC(d);
+ emit_label_br(cd, BRANCH_LABEL_6); /* true */
+ emit_label(cd, BRANCH_LABEL_8);
+
+ if (super == NULL) {
+ M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
+ emit_label_bne(cd, BRANCH_LABEL_10); /* false */
+ }
- *(cd->mcodeptr++) = 0x4e;
- *(cd->mcodeptr++) = 0x3b;
- *(cd->mcodeptr++) = 0x14;
- *(cd->mcodeptr++) = 0x18;
- /* cmp (ITMP1, ITMP3, 1), ITMP2 */
+ M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
+ M_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1);
+ emit_label_bgt(cd, BRANCH_LABEL_9); /* false */
- 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_ITMP3);
- emit_label_bne(cd, BRANCH_LABEL_6); /* ende false */
-
- /* use the red zone */
- M_AST(REG_ITMP2, REG_SP, -16);
- M_AST_IMM32(0, REG_SP, -24);
- M_ALD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, subtype_overflow));
- looptarget = cd->mcodeptr - cd->mcodebase;
-
- M_ALD(REG_ITMP2, REG_SP, -24);
- M_ICMP_MEMBASE(REG_ITMP1, OFFSET(vftbl_t, subtype_overflow_length), REG_ITMP2);
- emit_label_bge(cd, BRANCH_LABEL_8); /* ende false */
-
- *(cd->mcodeptr++) = 0x4f;
- *(cd->mcodeptr++) = 0x8b;
- *(cd->mcodeptr++) = 0x14;
- *(cd->mcodeptr++) = 0xd3;
- /* movq (ITMP3, ITMP2, 8), ITMP2 */
-
- M_LCMP_MEMBASE(REG_SP, -16, REG_ITMP2);
- emit_label_bne(cd, BRANCH_LABEL_9);
- if (d == REG_ITMP2) {
+ M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+ M_LCMP_MEMINDEX(REG_ITMP2, -8*DISPLAY_SIZE, REG_ITMP1, 3, REG_ITMP3);
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);
- M_JMP_IMM2(looptarget - (cd->mcodeptr - cd->mcodebase) - 2); /* 1 byte displacement */
+ if (d == REG_ITMP2) {
+ M_BSEXT(d, d);
- emit_label(cd, BRANCH_LABEL_8);
- emit_label(cd, BRANCH_LABEL_6);
+ emit_label_br(cd, BRANCH_LABEL_7); /* jump over M_CLR */
+ }
- if (d == REG_ITMP2)
- M_CLR(d);
+ 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_10);
- emit_label(cd, BRANCH_LABEL_7);
+ emit_label(cd, BRANCH_LABEL_7);
+ }
+ emit_label(cd, BRANCH_LABEL_6);
}
else {
- assert(super->vftbl->subtype_offset < 0x80);
- *(cd->mcodeptr++) = 0x4c;
- *(cd->mcodeptr++) = 0x3b;
- *(cd->mcodeptr++) = 0x50;
- *(cd->mcodeptr++) = super->vftbl->subtype_offset;
- /* cmp off(ITMP1), ITMP2 */
-
+ M_LCMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3);
M_SETE(d);
if (d == REG_ITMP2)
M_BSEXT(d, d);
/* put env into first argument register */
- M_MOV_IMM(_Jv_env, REG_A0);
+ M_MOV_IMM(VM_get_jnienv(), REG_A0);
}
/* Call the native function. */
case TYPE_INT:
case TYPE_LNG:
case TYPE_ADR:
+ switch (md->returntype.primitivetype) {
+ case PRIMITIVETYPE_BOOLEAN:
+ M_BZEXT(REG_RESULT, REG_RESULT);
+ break;
+ case PRIMITIVETYPE_BYTE:
+ M_BSEXT(REG_RESULT, REG_RESULT);
+ break;
+ case PRIMITIVETYPE_CHAR:
+ M_CZEXT(REG_RESULT, REG_RESULT);
+ break;
+ case PRIMITIVETYPE_SHORT:
+ M_SSEXT(REG_RESULT, REG_RESULT);
+ break;
+ }
M_LST(REG_RESULT, REG_SP, 0 * 8);
break;
case TYPE_FLT: