/* jit/x86_64/codegen.c - machine code generator for x86_64
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- Institut f. Computersprachen, TU Wien
- R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
- S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
- J. Wenninger
+ Copyright (C) 1996-2005 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
This file is part of CACAO.
Authors: Andreas Krall
Christian Thalinger
- $Id: codegen.c 1494 2004-11-12 13:34:26Z twisti $
+ $Id: codegen.c 1735 2004-12-07 14:33:27Z twisti $
*/
+
#define _GNU_SOURCE
-#include "global.h"
#include <stdio.h>
-#include <signal.h>
-#include <sys/ucontext.h>
-#include "builtin.h"
-#include "asmpart.h"
-#include "jni.h"
-#include "loader.h"
-#include "tables.h"
-#include "native.h"
-#include "jit/jit.h"
-#include "jit/reg.h"
-#include "jit/parse.h"
-#include "jit/x86_64/codegen.h"
-#include "jit/x86_64/emitfuncs.h"
-#include "jit/x86_64/types.h"
+#include <ucontext.h>
+
+#include "native/native.h"
+/* #include "native/jni.h" */
+#include "vm/global.h"
+#include "vm/builtin.h"
+#include "vm/loader.h"
+#include "vm/tables.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/reg.h"
+#include "vm/jit/parse.h"
+#include "vm/jit/x86_64/arch.h"
+#include "vm/jit/x86_64/codegen.h"
+#include "vm/jit/x86_64/emitfuncs.h"
+#include "vm/jit/x86_64/types.h"
+#include "vm/jit/x86_64/asmoffsets.h"
/* register descripton - array ************************************************/
/* #define REG_END -1 last entry in tables */
-int nregdescint[] = {
+static int nregdescint[] = {
REG_RET, REG_ARG, REG_ARG, REG_TMP, REG_RES, REG_SAV, REG_ARG, REG_ARG,
REG_ARG, REG_ARG, REG_RES, REG_RES, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
REG_END
};
-int nregdescfloat[] = {
- /* REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP, */
- /* REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, */
+static int nregdescfloat[] = {
+/* REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP, */
+/* REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, */
REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
REG_END
};
-/*******************************************************************************
-
- include independent code generation stuff -- include after register
- descriptions to avoid extern definitions
-
-*******************************************************************************/
+/* Include independent code generation stuff -- include after register */
+/* descriptions to avoid extern definitions. */
-#include "jit/codegen.inc"
-#include "jit/reg.inc"
+#include "vm/jit/codegen.inc"
+#include "vm/jit/reg.inc"
+#ifdef LSRA
+#include "vm/jit/lsra.inc"
+#endif
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
case ICMD_PUTSTATIC: /* ..., value ==> ... */
/* op1 = type, val.a = field address */
- /* if class isn't yet initialized, do it */
+ /* If the static fields' class is not yet initialized, we do it */
+ /* now. The call code is generated later. */
if (!((fieldinfo *) iptr->val.a)->class->initialized) {
- /* call helper function which patches this code */
- x86_64_mov_imm_reg(cd, (s8) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
- x86_64_mov_imm_reg(cd, (s8) asm_check_clinit, REG_ITMP2);
- x86_64_call_reg(cd, REG_ITMP2);
+ codegen_addclinitref(cd, cd->mcodeptr, ((fieldinfo *) iptr->val.a)->class);
+
+ /* This is just for debugging purposes. Is very difficult to */
+ /* read patched code. Here we patch the following 5 nop's */
+ /* so that the real code keeps untouched. */
+ if (showdisassemble) {
+ x86_64_nop(cd);
+ x86_64_nop(cd);
+ x86_64_nop(cd);
+ x86_64_nop(cd);
+ x86_64_nop(cd);
+ }
}
+ /* This approach is much faster than moving the field address */
+ /* inline into a register. */
a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
x86_64_mov_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 7) - (s8) cd->mcodebase) + a, REG_ITMP2);
switch (iptr->op1) {
var_to_reg_flt(s2, src, REG_FTMP1);
x86_64_movsd_reg_membase(cd, s2, REG_ITMP2, 0);
break;
- default: panic("internal error");
+ default:
+ throw_cacao_exception_exit(string_java_lang_InternalError,
+ "Unknown PUTSTATIC operand type %d",
+ iptr->op1);
}
break;
case ICMD_GETSTATIC: /* ... ==> ..., value */
/* op1 = type, val.a = field address */
- /* if class isn't yet initialized, do it */
+ /* If the static fields' class is not yet initialized, we do it */
+ /* now. The call code is generated later. */
if (!((fieldinfo *) iptr->val.a)->class->initialized) {
- /* call helper function which patches this code */
- x86_64_mov_imm_reg(cd, (s8) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
- x86_64_mov_imm_reg(cd, (s8) asm_check_clinit, REG_ITMP2);
- x86_64_call_reg(cd, REG_ITMP2);
+ codegen_addclinitref(cd, cd->mcodeptr, ((fieldinfo *) iptr->val.a)->class);
+
+ /* This is just for debugging purposes. Is very difficult to */
+ /* read patched code. Here we patch the following 5 nop's */
+ /* so that the real code keeps untouched. */
+ if (showdisassemble) {
+ x86_64_nop(cd);
+ x86_64_nop(cd);
+ x86_64_nop(cd);
+ x86_64_nop(cd);
+ x86_64_nop(cd);
+ }
}
+ /* This approach is much faster than moving the field address */
+ /* inline into a register. */
a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
x86_64_mov_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 7) - (s8) cd->mcodebase) + a, REG_ITMP2);
switch (iptr->op1) {
x86_64_movsd_membase_reg(cd, REG_ITMP2, 0, d);
store_reg_to_var_flt(iptr->dst, d);
break;
- default: panic("internal error");
+ default:
+ throw_cacao_exception_exit(string_java_lang_InternalError,
+ "Unknown GETSTATIC operand type %d",
+ iptr->op1);
}
break;
case ICMD_PUTFIELD: /* ..., value ==> ... */
/* op1 = type, val.i = field offset */
- /* if class isn't yet initialized, do it */
- if (!((fieldinfo *) iptr->val.a)->class->initialized) {
- /* call helper function which patches this code */
- x86_64_mov_imm_reg(cd, (s8) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
- x86_64_mov_imm_reg(cd, (s8) asm_check_clinit, REG_ITMP2);
- x86_64_call_reg(cd, REG_ITMP2);
- }
-
a = ((fieldinfo *)(iptr->val.a))->offset;
var_to_reg_int(s1, src->prev, REG_ITMP1);
switch (iptr->op1) {
- case TYPE_INT:
- var_to_reg_int(s2, src, REG_ITMP2);
- gen_nullptr_check(s1);
- x86_64_movl_reg_membase(cd, s2, s1, a);
- break;
- case TYPE_LNG:
- case TYPE_ADR:
- var_to_reg_int(s2, src, REG_ITMP2);
- gen_nullptr_check(s1);
- x86_64_mov_reg_membase(cd, s2, s1, a);
- break;
- case TYPE_FLT:
- var_to_reg_flt(s2, src, REG_FTMP2);
- gen_nullptr_check(s1);
- x86_64_movss_reg_membase(cd, s2, s1, a);
- break;
- case TYPE_DBL:
- var_to_reg_flt(s2, src, REG_FTMP2);
- gen_nullptr_check(s1);
- x86_64_movsd_reg_membase(cd, s2, s1, a);
- break;
- default: panic ("internal error");
- }
+ case TYPE_INT:
+ var_to_reg_int(s2, src, REG_ITMP2);
+ gen_nullptr_check(s1);
+ x86_64_movl_reg_membase(cd, s2, s1, a);
+ break;
+ case TYPE_LNG:
+ case TYPE_ADR:
+ var_to_reg_int(s2, src, REG_ITMP2);
+ gen_nullptr_check(s1);
+ x86_64_mov_reg_membase(cd, s2, s1, a);
+ break;
+ case TYPE_FLT:
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ gen_nullptr_check(s1);
+ x86_64_movss_reg_membase(cd, s2, s1, a);
+ break;
+ case TYPE_DBL:
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ gen_nullptr_check(s1);
+ x86_64_movsd_reg_membase(cd, s2, s1, a);
+ break;
+ default:
+ throw_cacao_exception_exit(string_java_lang_InternalError,
+ "Unknown PUTFIELD operand type %d",
+ iptr->op1);
+ }
break;
case ICMD_GETFIELD: /* ... ==> ..., value */
a = ((fieldinfo *)(iptr->val.a))->offset;
var_to_reg_int(s1, src, REG_ITMP1);
switch (iptr->op1) {
- case TYPE_INT:
- d = reg_of_var(rd, iptr->dst, REG_ITMP1);
- gen_nullptr_check(s1);
- x86_64_movl_membase_reg(cd, s1, a, d);
- store_reg_to_var_int(iptr->dst, d);
- break;
- case TYPE_LNG:
- case TYPE_ADR:
- d = reg_of_var(rd, iptr->dst, REG_ITMP1);
- gen_nullptr_check(s1);
- x86_64_mov_membase_reg(cd, s1, a, d);
- store_reg_to_var_int(iptr->dst, d);
- break;
- case TYPE_FLT:
- d = reg_of_var(rd, iptr->dst, REG_FTMP1);
- gen_nullptr_check(s1);
- x86_64_movss_membase_reg(cd, s1, a, d);
- store_reg_to_var_flt(iptr->dst, d);
- break;
- case TYPE_DBL:
- d = reg_of_var(rd, iptr->dst, REG_FTMP1);
- gen_nullptr_check(s1);
- x86_64_movsd_membase_reg(cd, s1, a, d);
- store_reg_to_var_flt(iptr->dst, d);
- break;
- default: panic ("internal error");
- }
+ case TYPE_INT:
+ d = reg_of_var(rd, iptr->dst, REG_ITMP1);
+ gen_nullptr_check(s1);
+ x86_64_movl_membase_reg(cd, s1, a, d);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case TYPE_LNG:
+ case TYPE_ADR:
+ d = reg_of_var(rd, iptr->dst, REG_ITMP1);
+ gen_nullptr_check(s1);
+ x86_64_mov_membase_reg(cd, s1, a, d);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case TYPE_FLT:
+ d = reg_of_var(rd, iptr->dst, REG_FTMP1);
+ gen_nullptr_check(s1);
+ x86_64_movss_membase_reg(cd, s1, a, d);
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+ case TYPE_DBL:
+ d = reg_of_var(rd, iptr->dst, REG_FTMP1);
+ gen_nullptr_check(s1);
+ x86_64_movsd_membase_reg(cd, s1, a, d);
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+ default:
+ throw_cacao_exception_exit(string_java_lang_InternalError,
+ "Unknown GETFIELD operand type %d",
+ iptr->op1);
+ }
break;
var_to_reg_int(s1, src, REG_ITMP1);
M_INTMOVE(s1, REG_ITMP1_XPTR);
- x86_64_call_imm(cd, 0); /* passing exception pointer */
+ x86_64_call_imm(cd, 0); /* passing exception pointer */
x86_64_pop_reg(cd, REG_ITMP2_XPC);
x86_64_mov_imm_reg(cd, (s8) asm_handle_exception, REG_ITMP3);
store_reg_to_var_int(iptr->dst, s1);
break;
- default: error("Unknown pseudo command: %d", iptr->opc);
+ default:
+ throw_cacao_exception_exit(string_java_lang_InternalError,
+ "Unknown ICMD %d", iptr->opc);
} /* switch */
} /* for instruction */
x86_64_jmp_reg(cd, REG_ITMP3);
}
}
+
+ /* generate put/getstatic stub call code */
+
+ {
+ clinitref *cref;
+ codegendata *tmpcd;
+ u1 xmcode;
+ u4 mcode;
+
+ tmpcd = DNEW(codegendata);
+
+ for (cref = cd->clinitrefs; cref != NULL; cref = cref->next) {
+ /* Get machine code which is patched back in later. A */
+ /* `call rel32' is 5 bytes long. */
+ xcodeptr = cd->mcodebase + cref->branchpos;
+ xmcode = *xcodeptr;
+ mcode = *((u4 *) (xcodeptr + 1));
+
+ MCODECHECK(50);
+
+ /* patch in `call rel32' to call the following code */
+ tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
+ x86_64_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
+
+ /* Save current stack pointer into a temporary register. */
+ x86_64_mov_reg_reg(cd, REG_SP, REG_ITMP1);
+
+ /* Push machine code bytes to patch onto the stack. */
+ x86_64_push_imm(cd, (u1) xmcode);
+ x86_64_push_imm(cd, (u4) mcode);
+
+ x86_64_push_imm(cd, (u8) cref->class);
+
+ /* Push previously saved stack pointer onto stack. */
+ x86_64_push_reg(cd, REG_ITMP1);
+
+ x86_64_mov_imm_reg(cd, (u8) asm_check_clinit, REG_ITMP1);
+ x86_64_jmp_reg(cd, REG_ITMP1);
+ }
+ }
}
codegen_finish(m, cd, (s4) ((u1 *) cd->mcodeptr - cd->mcodebase));
cd->mcodeptr = s;
/* code for the stub */
- x86_64_mov_imm_reg(cd, (s8) m, REG_ITMP1); /* pass method to compiler */
- x86_64_mov_imm_reg(cd, (s8) asm_call_jit_compiler, REG_ITMP3);/* load address */
+ x86_64_mov_imm_reg(cd, (u8) m, REG_ITMP1); /* pass method to compiler */
+ x86_64_mov_imm_reg(cd, (u8) asm_call_jit_compiler, REG_ITMP3);/* load address */
x86_64_jmp_reg(cd, REG_ITMP3); /* jump to compiler */
#if defined(STATISTICS)
t_inlining_globals *id;
s4 dumpsize;
+ void **callAddrPatchPos=0;
+ u1 *jmpInstrPos=0;
+ void **jmpInstrPatchPos=0;
+
/* mark start of dump memory area */
dumpsize = dump_size();
inlining_setup(m, id);
reg_setup(m, rd, id);
+ /* set some required varibles which are normally set by codegen_setup */
+ cd->mcodebase = s;
cd->mcodeptr = s;
+ cd->clinitrefs = NULL;
descriptor2types(m); /* set paramcount and paramtypes */
if (m->flags & ACC_STATIC) {
/* if class isn't yet initialized, do it */
if (!m->class->initialized) {
- /* call helper function which patches this code */
- x86_64_mov_imm_reg(cd, (u8) m->class, REG_ITMP1);
- x86_64_mov_imm_reg(cd, (u8) asm_check_clinit, REG_ITMP2);
- x86_64_call_reg(cd, REG_ITMP2);
+ codegen_addclinitref(cd, cd->mcodeptr, m->class);
}
}
- if (runverbose) {
- s4 p, l, s1;
- x86_64_alu_imm_reg(cd, X86_64_SUB, (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8, REG_SP);
+ x86_64_alu_imm_reg(cd, X86_64_SUB, (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8, REG_SP);
- x86_64_mov_reg_membase(cd, rd->argintregs[0], REG_SP, 1 * 8);
- x86_64_mov_reg_membase(cd, rd->argintregs[1], REG_SP, 2 * 8);
- x86_64_mov_reg_membase(cd, rd->argintregs[2], REG_SP, 3 * 8);
- x86_64_mov_reg_membase(cd, rd->argintregs[3], REG_SP, 4 * 8);
- x86_64_mov_reg_membase(cd, rd->argintregs[4], REG_SP, 5 * 8);
- x86_64_mov_reg_membase(cd, rd->argintregs[5], REG_SP, 6 * 8);
+ x86_64_mov_reg_membase(cd, rd->argintregs[0], REG_SP, 1 * 8);
+ x86_64_mov_reg_membase(cd, rd->argintregs[1], REG_SP, 2 * 8);
+ x86_64_mov_reg_membase(cd, rd->argintregs[2], REG_SP, 3 * 8);
+ x86_64_mov_reg_membase(cd, rd->argintregs[3], REG_SP, 4 * 8);
+ x86_64_mov_reg_membase(cd, rd->argintregs[4], REG_SP, 5 * 8);
+ x86_64_mov_reg_membase(cd, rd->argintregs[5], REG_SP, 6 * 8);
- x86_64_movq_reg_membase(cd, rd->argfltregs[0], REG_SP, 7 * 8);
- x86_64_movq_reg_membase(cd, rd->argfltregs[1], REG_SP, 8 * 8);
- x86_64_movq_reg_membase(cd, rd->argfltregs[2], REG_SP, 9 * 8);
- x86_64_movq_reg_membase(cd, rd->argfltregs[3], REG_SP, 10 * 8);
+ x86_64_movq_reg_membase(cd, rd->argfltregs[0], REG_SP, 7 * 8);
+ x86_64_movq_reg_membase(cd, rd->argfltregs[1], REG_SP, 8 * 8);
+ x86_64_movq_reg_membase(cd, rd->argfltregs[2], REG_SP, 9 * 8);
+ x86_64_movq_reg_membase(cd, rd->argfltregs[3], REG_SP, 10 * 8);
/* x86_64_movq_reg_membase(cd, rd->argfltregs[4], REG_SP, 11 * 8); */
/* x86_64_movq_reg_membase(cd, rd->argfltregs[5], REG_SP, 12 * 8); */
/* x86_64_movq_reg_membase(cd, rd->argfltregs[6], REG_SP, 13 * 8); */
/* x86_64_movq_reg_membase(cd, rd->argfltregs[7], REG_SP, 14 * 8); */
+ if (runverbose) {
+ s4 p, l, s1;
+
/* show integer hex code for float arguments */
for (p = 0, l = 0; p < m->paramcount; p++) {
if (IS_FLT_DBL_TYPE(m->paramtypes[p])) {
x86_64_mov_imm_reg(cd, (s8) m, REG_ITMP1);
x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0 * 8);
- x86_64_mov_imm_reg(cd, (s8) builtin_trace_args, REG_ITMP1);
+ x86_64_mov_imm_reg(cd, (s8) builtin_trace_args, REG_ITMP1);
x86_64_call_reg(cd, REG_ITMP1);
+ }
+/* call method to resolve native function if needed */
+#ifndef STATIC_CLASSPATH
+ if (f==0) { /* only if not already resolved */
+ x86_64_jmp_imm(cd,0);
+ jmpInstrPos=cd->mcodeptr-4; /*needed to patch a jump over this block*/
+ x86_64_mov_imm_reg(cd,(u8)m,rd->argintregs[0]);
+ x86_64_mov_imm_reg(cd,0,rd->argintregs[1]);
+ callAddrPatchPos=cd->mcodeptr-8; /* at this position the place is specified where the native function adress should be patched into*/
+ x86_64_mov_imm_reg(cd,0,rd->argintregs[2]);
+ jmpInstrPatchPos=cd->mcodeptr-8;
+ x86_64_mov_imm_reg(cd,jmpInstrPos,rd->argintregs[3]);
+ x86_64_mov_imm_reg(cd,(s8)codegen_resolve_native,REG_ITMP1);
+ x86_64_call_reg(cd,REG_ITMP1);
+ *(jmpInstrPatchPos)=cd->mcodeptr-jmpInstrPos-1; /*=opcode jmp_imm size*/
+ }
+#endif
- x86_64_mov_membase_reg(cd, REG_SP, 1 * 8, rd->argintregs[0]);
- x86_64_mov_membase_reg(cd, REG_SP, 2 * 8, rd->argintregs[1]);
- x86_64_mov_membase_reg(cd, REG_SP, 3 * 8, rd->argintregs[2]);
- x86_64_mov_membase_reg(cd, REG_SP, 4 * 8, rd->argintregs[3]);
- x86_64_mov_membase_reg(cd, REG_SP, 5 * 8, rd->argintregs[4]);
- x86_64_mov_membase_reg(cd, REG_SP, 6 * 8, rd->argintregs[5]);
-
- x86_64_movq_membase_reg(cd, REG_SP, 7 * 8, rd->argfltregs[0]);
- x86_64_movq_membase_reg(cd, REG_SP, 8 * 8, rd->argfltregs[1]);
- x86_64_movq_membase_reg(cd, REG_SP, 9 * 8, rd->argfltregs[2]);
- x86_64_movq_membase_reg(cd, REG_SP, 10 * 8, rd->argfltregs[3]);
+ x86_64_mov_membase_reg(cd, REG_SP, 1 * 8, rd->argintregs[0]);
+ x86_64_mov_membase_reg(cd, REG_SP, 2 * 8, rd->argintregs[1]);
+ x86_64_mov_membase_reg(cd, REG_SP, 3 * 8, rd->argintregs[2]);
+ x86_64_mov_membase_reg(cd, REG_SP, 4 * 8, rd->argintregs[3]);
+ x86_64_mov_membase_reg(cd, REG_SP, 5 * 8, rd->argintregs[4]);
+ x86_64_mov_membase_reg(cd, REG_SP, 6 * 8, rd->argintregs[5]);
+
+ x86_64_movq_membase_reg(cd, REG_SP, 7 * 8, rd->argfltregs[0]);
+ x86_64_movq_membase_reg(cd, REG_SP, 8 * 8, rd->argfltregs[1]);
+ x86_64_movq_membase_reg(cd, REG_SP, 9 * 8, rd->argfltregs[2]);
+ x86_64_movq_membase_reg(cd, REG_SP, 10 * 8, rd->argfltregs[3]);
/* x86_64_movq_membase_reg(cd, REG_SP, 11 * 8, rd->argfltregs[4]); */
/* x86_64_movq_membase_reg(cd, REG_SP, 12 * 8, rd->argfltregs[5]); */
/* x86_64_movq_membase_reg(cd, REG_SP, 13 * 8, rd->argfltregs[6]); */
/* x86_64_movq_membase_reg(cd, REG_SP, 14 * 8, rd->argfltregs[7]); */
- x86_64_alu_imm_reg(cd, X86_64_ADD, (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8, REG_SP);
- }
+ x86_64_alu_imm_reg(cd, X86_64_ADD, (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8, REG_SP);
+
#if 0
x86_64_alu_imm_reg(cd, X86_64_SUB, 7 * 8, REG_SP); /* keep stack 16-byte aligned */
x86_64_mov_imm_reg(cd, (u8) &env, rd->argintregs[0]);
x86_64_mov_imm_reg(cd, (u8) f, REG_ITMP1);
+#ifndef STATIC_CLASSPATH
+ if (f==0)
+ (*callAddrPatchPos)=cd->mcodeptr-8;
+#endif
x86_64_call_reg(cd, REG_ITMP1);
/* remove stackframe if there is one */
x86_64_mov_imm_reg(cd, (s8) asm_handle_nat_exception, REG_ITMP3);
x86_64_jmp_reg(cd, REG_ITMP3);
+ {
+ u1 *xcodeptr;
+ clinitref *cref;
+ codegendata *tmpcd;
+ u1 xmcode;
+ u4 mcode;
+
+ tmpcd = DNEW(codegendata);
+
+ /* there can only be one clinit ref entry */
+ cref = cd->clinitrefs;
+
+ if (cref) {
+ /* Get machine code which is patched back in later. A */
+ /* `call rel32' is 5 bytes long. */
+ xcodeptr = cd->mcodebase + cref->branchpos;
+ xmcode = *xcodeptr;
+ mcode = *((u4 *) (xcodeptr + 1));
+
+ /* patch in `call rel32' to call the following code */
+ tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
+ x86_64_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
+
+ /* Save current stack pointer into a temporary register. */
+ x86_64_mov_reg_reg(cd, REG_SP, REG_ITMP1);
+
+ /* Push machine code bytes to patch onto the stack. */
+ x86_64_push_imm(cd, (u1) xmcode);
+ x86_64_push_imm(cd, (u4) mcode);
+
+ x86_64_push_imm(cd, (u8) cref->class);
+
+ /* Push previously saved stack pointer onto stack. */
+ x86_64_push_reg(cd, REG_ITMP1);
+
+ x86_64_mov_imm_reg(cd, (u8) asm_check_clinit, REG_ITMP1);
+ x86_64_jmp_reg(cd, REG_ITMP1);
+ }
+ }
+
#if 0
{
static int stubprinted;