/* src/vm/jit/s390/codegen.c - machine code generator for s390
- 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 <stdint.h>
#include <stdio.h>
-#include "native/jni.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "vm/jit/s390/arch.h"
+#include "vm/jit/s390/codegen.h"
+#include "vm/jit/s390/emit.h"
+#include "vm/jit/s390/md-abi.h"
+
+#include "native/localref.hpp"
+#include "native/native.hpp"
#include "mm/memory.h"
-#if defined(ENABLE_THREADS)
-# include "threads/lock-common.h"
-# include "threads/native/lock.h"
-#endif
+#include "threads/lock.hpp"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/loader.hpp"
+#include "vm/options.h"
+#include "vm/statistics.h"
+#include "vm/types.h"
+#include "vm/vm.hpp"
+
#include "vm/jit/abi.h"
#if defined(ENABLE_LSRA)
# include "vm/jit/allocator/lsra.h"
#endif
#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/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/s390/arch.h"
-#include "vm/jit/s390/codegen.h"
-#include "vm/jit/s390/emit.h"
-#include "vm/jit/s390/md-abi.h"
-#include "vm/jit/stacktrace.h"
-#include "vm/types.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/jit/replace.hpp"
+#include "vm/jit/stacktrace.hpp"
+#include "vm/jit/trap.h"
+
/* DO__LOG generates a call to do__log. No registers are destroyed,
* so you may use it anywhere. regs is an array containing all general
* purpose registers.
*/
+/*
static void do__log(u4 *regs) {
- /* insert stuff here */
}
+*/
#define DO__LOG \
N_AHI(REG_SP, -200); \
N_LM(R0, R15, 96, REG_SP); \
N_AHI(REG_SP, 200);
-#define SUPPORT_HERCULES 1
+/* If the following macro is defined, workaround code for hercules quirks
+ * is generated
+ */
+
+/* #define SUPPORT_HERCULES 1 */
/* codegen *********************************************************************
registerdata *rd;
s4 len, s1, s2, s3, d, dd, disp;
u2 currentline;
- ptrint a;
- varinfo *var, *var1, *var2, *dst;
+ varinfo *var;
basicblock *bptr;
instruction *iptr;
- exception_entry *ex;
constant_classref *cr;
unresolved_class *uc;
methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
(void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
(void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
- (void) dseg_addlinenumbertablesize(cd);
-
- (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
-
- /* create exception table */
-
- for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
- dseg_add_target(cd, ex->start);
- dseg_add_target(cd, ex->end);
- dseg_add_target(cd, ex->handler);
- (void) dseg_add_unique_address(cd, ex->catchtype.any);
- }
-
/* Offset PV */
M_AADD_IMM(N_PV_OFFSET, REG_PV);
/* decide which monitor enter function to call */
if (m->flags & ACC_STATIC) {
- disp = dseg_add_address(cd, &m->class->object.header);
+ disp = dseg_add_address(cd, &m->clazz->object.header);
M_ALD_DSEG(REG_A0, disp);
}
else {
M_TEST(REG_A0);
M_BNE(SZ_BRC + SZ_ILL);
- M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ILL(TRAP_NullPointerException);
}
disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
if (iptr->line != currentline) {
- dseg_addlinenumber(cd, iptr->line);
+ linenumbertable_list_entry_add(cd, iptr->line);
currentline = iptr->line;
}
case ICMD_INLINE_BODY:
REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
- dseg_addlinenumber_inline_start(cd, iptr);
- dseg_addlinenumber(cd, iptr->line);
+ linenumbertable_list_entry_add_inline_start(cd, iptr);
+ linenumbertable_list_entry_add(cd, iptr->line);
break;
case ICMD_INLINE_END:
- dseg_addlinenumber_inline_end(cd, iptr);
- dseg_addlinenumber(cd, iptr->line);
+ linenumbertable_list_entry_add_inline_end(cd, iptr);
+ linenumbertable_list_entry_add(cd, iptr->line);
break;
case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
case ICMD_F2D: /* ..., value ==> ..., (double) value */
{
+#ifdef SUPPORT_HERCULES
u1 *ref;
+#endif
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
#ifdef SUPPORT_HERCULES
N_L(
GET_LOW_REG(d) /* maybe itmp3 */,
- OFFSET(java_intarray_t, data[0]) + 4,
+ OFFSET(java_longarray_t, data[0]) + 4,
REG_ITMP2, s1 /* maybe itmp1 */
);
N_L(
GET_HIGH_REG(d) /* maybe itmp1 */,
- OFFSET(java_intarray_t, data[0]),
+ OFFSET(java_longarray_t, data[0]),
REG_ITMP2, s1 /* maybe itmp1 */
);
M_INTMOVE(s2, REG_ITMP2);
M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
- N_LD(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
+ N_LD(d, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
emit_store_dst(jd, iptr, d);
break;
M_SLL_IMM(3, REG_ITMP2);
s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
- N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
+ N_ST(s3, OFFSET(java_longarray_t, data[0]), REG_ITMP2, s1);
s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
- N_ST(s3, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1);
+ N_ST(s3, OFFSET(java_longarray_t, data[0]) + 4, REG_ITMP2, s1);
break;
case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
PROFILE_CYCLE_STOP;
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, 0);
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
PROFILE_CYCLE_START;
}
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
PROFILE_CYCLE_STOP;
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, disp);
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, disp);
PROFILE_CYCLE_START;
}
}
}
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref);
+ ((patchref_t *)list_first(jd->code->patchers))->disp = (cd->mcodeptr - ref);
}
switch (fieldtype) {
}
else {
s1 = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * lm->class->index;
+ sizeof(methodptr*) * lm->clazz->index;
- s2 = sizeof(methodptr) * (lm - lm->class->methods);
+ s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
}
/* Implicit null-pointer check */
supervftbl = super->vftbl;
}
- if ((super == NULL) || !(super->flags & ACC_INTERFACE))
- CODEGEN_CRITICAL_SECTION_NEW;
-
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
/* if class is not resolved, check which code to call */
}
#if 1
- CODEGEN_CRITICAL_SECTION_START;
-
/* REG_ITMP3 := baseval(s1) */
M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ALD_DSEG(REG_ITMP2, disp);
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
/* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
M_ALD_DSEG(REG_ITMP3, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
M_ISUB(REG_ITMP3, REG_ITMP2);
M_ALD_DSEG(REG_ITMP3, disp);
M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
/* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
/* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
# define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
# define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
- 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_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
M_ALD_DSEG(REG_ITMP2, 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_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
} /* if (bptr -> flags >= BBREACHED) */
} /* for basic block */
- dseg_createlinenumbertable(cd);
-
/* generate stubs */
emit_patcher_traps(jd);
return true;
}
-
-/* codegen_emit_stub_compiler **************************************************
-
- Emits a stub routine which calls the compiler.
-
-*******************************************************************************/
-
-void codegen_emit_stub_compiler(jitdata *jd)
-{
- methodinfo *m;
- codegendata *cd;
-
- /* get required compiler data */
-
- m = jd->m;
- cd = jd->cd;
-
- /* code for the stub */
-
- /* don't touch ITMP2 as it cointains the return address */
-
- M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
-
- /* REG_METHODPTR (REG_ITMP1) already used */
- M_ILD_DSEG(REG_ITMP3, -2 * SIZEOF_VOID_P); /* methodinfo */
- M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
- N_BR(REG_PV);
-}
-
-
/* codegen_emit_stub_native ****************************************************
Emits a stub routine which calls a native method.
codeinfo *code;
codegendata *cd;
methoddesc *md;
- s4 i, j; /* count variables */
- s4 t;
- s4 s1, s2, disp;
- s4 funcdisp;
+ int i, j;
+ int t;
+ int s1, s2;
+ int disp;
/* get required compiler data */
(void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
(void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
- (void) dseg_add_unique_s4(cd, 0); /* IsSync */
(void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
(void) dseg_add_unique_s4(cd, 0); /* IntSave */
(void) dseg_add_unique_s4(cd, 0); /* FltSave */
- (void) dseg_addlinenumbertablesize(cd);
- (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
/* generate code */
M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
- /* get function address (this must happen before the stackframeinfo) */
-
- funcdisp = dseg_add_functionptr(cd, f);
-
- if (f == NULL)
- patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp);
-
#if defined(ENABLE_GC_CACAO)
/* Save callee saved integer registers in stackframeinfo (GC may
need to recover them during a collection). */
/* put env into first argument register */
- disp = dseg_add_address(cd, _Jv_env);
+ disp = dseg_add_address(cd, VM_get_jnienv());
M_ALD_DSEG(REG_A0, disp);
}
- /* generate the actual native call */
+ /* Call native function. */
- M_ALD_DSEG(REG_ITMP2, funcdisp);
+ disp = dseg_add_functionptr(cd, f);
+ M_ALD_DSEG(REG_ITMP2, disp);
M_CALL(REG_ITMP2);
/* save return value */
/* handle exception */
M_MOV(REG_RA, REG_ITMP1_XPC);
+ M_ASUB_IMM(2, REG_ITMP1_XPC);
disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
M_ALD_DSEG(REG_ITMP2, disp);
M_JMP(RN, REG_ITMP2);
-
- /* generate patcher traps */
-
- emit_patcher_traps(jd);
}
/*