-/* jit/i386/codegen.c - machine code generator for i386
+/* vm/jit/i386/codegen.c - machine code generator for i386
- 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 1506 2004-11-14 14:48:49Z jowenn $
+ Changes: Joseph Wenninger
+
+ $Id: codegen.c 1735 2004-12-07 14:33:27Z twisti $
*/
+
#define _GNU_SOURCE
-#include "config.h"
-#include "global.h"
#include <stdio.h>
-#include <signal.h>
-#include <sys/ucontext.h>
-#include "types.h"
-#include "main.h"
-#include "builtin.h"
-#include "asmpart.h"
-#include "exceptions.h"
-#include "jni.h"
-#include "loader.h"
-#include "tables.h"
-#include "native.h"
-#include "jit/jit.h"
-#include "jit/parse.h"
-#include "jit/reg.h"
-#include "jit/i386/codegen.h"
-#include "jit/i386/emitfuncs.h"
+#include <ucontext.h>
+#ifdef __FreeBSD__
+#include <machine/signal.h>
+#endif
+
+#include "config.h"
+#include "native/jni.h"
+#include "native/native.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/tables.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/parse.h"
+#include "vm/jit/reg.h"
+#include "vm/jit/i386/codegen.h"
+#include "vm/jit/i386/emitfuncs.h"
+#include "vm/jit/i386/types.h"
+#include "vm/jit/i386/asmoffsets.h"
/* register descripton - array ************************************************/
/* #define REG_END -1 last entry in tables */
-int nregdescint[] = {
+static int nregdescint[] = {
REG_RET, REG_RES, REG_RES, REG_TMP, REG_RES, REG_SAV, REG_SAV, REG_SAV,
REG_END
};
-int nregdescfloat[] = {
+static int nregdescfloat[] = {
/* rounding problems with callee saved registers */
/* REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_RES, REG_RES, */
/* REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, */
*******************************************************************************/
-#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
void codegen_stubcalled() {
log_text("Stub has been called");
void thread_restartcriticalsection(ucontext_t *uc)
{
void *critical;
+#ifdef __FreeBSD__
+ if ((critical = thread_checkcritical((void*) uc->uc_mcontext.mc_eip)) != NULL)
+ uc->uc_mcontext.mc_eip = (u4) critical;
+#else
if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[REG_EIP])) != NULL)
uc->uc_mcontext.gregs[REG_EIP] = (u4) critical;
+
+#endif
}
#endif
-#define PREPARE_NATIVE_STACKINFO \
- i386_push_reg(cd, REG_ITMP1); /*save itmp1, needed by some stubs */ \
- i386_alu_imm_reg(cd, I386_SUB, 2*4, REG_SP); /* build stack frame (2 * 4 bytes), together with previous =3*4 */ \
- i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1); \
- i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/ \
- i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1); \
- i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/ \
- i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/ \
- i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */ \
- i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */ \
- i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */ \
- i386_mov_membase_reg(cd, REG_SP,2*4,REG_ITMP1); /* restore ITMP1, need for some stubs*/ \
- i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */
-
-
-#define REMOVE_NATIVE_STACKINFO \
- i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2); \
- i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3); \
- i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0); \
- i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
-
/* NullPointerException signal handler for hardware null pointer check */
sigset_t nsig;
/* long faultaddr; */
- struct ucontext *_uc = (struct ucontext *) _p;
- struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
+#ifdef __FreeBSD__
+ ucontext_t *_uc = (ucontext_t *) _p;
+ mcontext_t *sigctx = (mcontext_t *) &_uc->uc_mcontext;
+#else
+ struct ucontext *_uc = (struct ucontext *) _p;
+ struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
+#endif
struct sigaction act;
/* Reset signal handler - necessary for SysV, does no harm for BSD */
/* if (faultaddr == 0) { */
/* signal(sig, (void *) catch_NullPointerException); */
- act.sa_sigaction = (void *) catch_NullPointerException;
+ act.sa_sigaction = (functionptr) catch_NullPointerException;
act.sa_flags = SA_SIGINFO;
sigaction(sig, &act, NULL); /* reinstall handler */
- sigemptyset(&nsig);
- sigaddset(&nsig, sig);
- sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
+ sigemptyset(&nsig);
+ sigaddset(&nsig, sig);
+ sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
- sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
- sigctx->eax = (u4) string_java_lang_NullPointerException;
- sigctx->eip = (u4) asm_throw_and_handle_exception;
-
- return;
+#ifdef __FreeBSD__
+ sigctx->mc_ecx = sigctx->mc_eip; /* REG_ITMP2_XPC*/
+ sigctx->mc_eax = (u4) string_java_lang_NullPointerException;
+ sigctx->mc_eip = (u4) asm_throw_and_handle_exception;
+#else
+ sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
+ sigctx->eax = (u4) string_java_lang_NullPointerException;
+ sigctx->eip = (u4) asm_throw_and_handle_exception;
+#endif
+ return;
/* } else { */
/* faultaddr += (long) ((instr << 16) >> 16); */
/* void **_p = (void **) &sig; */
/* struct sigcontext *sigctx = (struct sigcontext *) ++_p; */
- struct ucontext *_uc = (struct ucontext *) _p;
- struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
+
+#ifdef __FreeBSD__
+ ucontext_t *_uc = (ucontext_t *) _p;
+ mcontext_t *sigctx = (mcontext_t *) &_uc->uc_mcontext;
+#else
+ struct ucontext *_uc = (struct ucontext *) _p;
+ struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
+#endif
+
struct sigaction act;
/* Reset signal handler - necessary for SysV, does no harm for BSD */
/* signal(sig, (void *) catch_ArithmeticException); */
- act.sa_sigaction = (void *) catch_ArithmeticException;
+ act.sa_sigaction = (functionptr) catch_ArithmeticException;
act.sa_flags = SA_SIGINFO;
sigaction(sig, &act, NULL); /* reinstall handler */
sigaddset(&nsig, sig);
sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
- sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
+#ifdef __FreeBSD__
+ sigctx->mc_ecx = sigctx->mc_eip; /* REG_ITMP2_XPC */
+ sigctx->mc_eip = (u4) asm_throw_and_handle_hardware_arithmetic_exception;
+#else
+ sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
sigctx->eip = (u4) asm_throw_and_handle_hardware_arithmetic_exception;
-
+#endif
return;
}
if (!checknull) {
#if defined(SIGSEGV)
/* signal(SIGSEGV, (void *) catch_NullPointerException); */
- act.sa_sigaction = (void *) catch_NullPointerException;
+ act.sa_sigaction = (functionptr) catch_NullPointerException;
act.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &act, NULL);
#endif
#if defined(SIGBUS)
/* signal(SIGBUS, (void *) catch_NullPointerException); */
- act.sa_sigaction = (void *) catch_NullPointerException;
+ act.sa_sigaction = (functionptr) catch_NullPointerException;
act.sa_flags = SA_SIGINFO;
sigaction(SIGBUS, &act, NULL);
#endif
}
/* signal(SIGFPE, (void *) catch_ArithmeticException); */
- act.sa_sigaction = (void *) catch_ArithmeticException;
+ act.sa_sigaction = (functionptr) catch_ArithmeticException;
act.sa_flags = SA_SIGINFO;
sigaction(SIGFPE, &act, NULL);
}
parentargs_base = rd->maxmemuse + savedregs_num;
+
#if defined(USE_THREADS) /* space to save argument of monitor_enter */
if (checksync && (m->flags & ACC_SYNCHRONIZED))
/* save monitorenter argument */
#if defined(USE_THREADS)
- s4 func_enter = (m->flags & ACC_STATIC) ?
- (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
-
if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+ s4 func_enter = (m->flags & ACC_STATIC) ?
+ (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
+
if (m->flags & ACC_STATIC) {
i386_mov_imm_reg(cd, (s4) m->class, REG_ITMP1);
i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, rd->maxmemuse * 8);
src = bptr->instack;
len = bptr->indepth;
MCODECHECK(64+len);
+
+#ifdef LSRA
+ if (opt_lsra) {
while (src != NULL) {
len--;
if ((len == 0) && (bptr->type != BBTYPE_STD)) {
if (!IS_2_WORD_TYPE(src->type)) {
if (bptr->type == BBTYPE_SBR) {
- d = reg_of_var(rd, src, REG_ITMP1);
+ /* d = reg_of_var(m, src, REG_ITMP1); */
+ if (!(src->flags & INMEMORY))
+ d= src->regoff;
+ else
+ d=REG_ITMP1;
i386_pop_reg(cd, d);
store_reg_to_var_int(src, d);
+ } else if (bptr->type == BBTYPE_EXH) {
+ /* d = reg_of_var(m, src, REG_ITMP1); */
+ if (!(src->flags & INMEMORY))
+ d= src->regoff;
+ else
+ d=REG_ITMP1;
+ M_INTMOVE(REG_ITMP1, d);
+ store_reg_to_var_int(src, d);
+ }
+ } else {
+ panic("copy interface registers(EXH, SBR): longs have to me in memory (begin 1)");
+ }
+ }
+ src = src->prev;
+ }
+ } else {
+#endif
+ while (src != NULL) {
+ len--;
+ if ((len == 0) && (bptr->type != BBTYPE_STD)) {
+ if (!IS_2_WORD_TYPE(src->type)) {
+ if (bptr->type == BBTYPE_SBR) {
+ d = reg_of_var(rd, src, REG_ITMP1);
+ i386_pop_reg(cd, d);
+ store_reg_to_var_int(src, d);
} else if (bptr->type == BBTYPE_EXH) {
d = reg_of_var(rd, src, REG_ITMP1);
M_INTMOVE(REG_ITMP1, d);
}
src = src->prev;
}
+#ifdef LSRA
+ }
+#endif
/* walk through all instructions */
/* val.i = constant */
d = reg_of_var(rd, iptr->dst, REG_NULL);
- /* should we use a inc optimization for smaller code size? */
i386_emit_ialuconst(cd, I386_ADD, src, iptr);
break;
i386_alu_imm_membase(cd, I386_ADD, iptr->val.i, REG_SP, var->regoff * 8);
} else {
+ /* `inc reg' is slower on p4's (regarding to ia32 */
+ /* optimization reference manual and benchmarks) and as fast */
+ /* on athlon's. */
i386_alu_imm_reg(cd, I386_ADD, iptr->val.i, var->regoff);
}
break;
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 */
- i386_mov_imm_reg(cd, (s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
- i386_mov_imm_reg(cd, (s4) asm_check_clinit, REG_ITMP2);
- i386_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) {
+ i386_nop(cd);
+ i386_nop(cd);
+ i386_nop(cd);
+ i386_nop(cd);
+ i386_nop(cd);
+ }
}
- a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
- /* here it's slightly slower */
- i386_mov_imm_reg(cd, 0, REG_ITMP2);
- dseg_adddata(cd, cd->mcodeptr);
- i386_mov_membase_reg(cd, REG_ITMP2, a, REG_ITMP2);
+ a = (u4) &(((fieldinfo *) iptr->val.a)->value);
switch (iptr->op1) {
case TYPE_INT:
case TYPE_ADR:
var_to_reg_int(s2, src, REG_ITMP1);
- i386_mov_reg_membase(cd, s2, REG_ITMP2, 0);
+ i386_mov_reg_mem(cd, s2, a);
break;
case TYPE_LNG:
if (src->flags & INMEMORY) {
- i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
- i386_mov_reg_membase(cd, REG_ITMP1, REG_ITMP2, 0);
- i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
- i386_mov_reg_membase(cd, REG_ITMP1, REG_ITMP2, 0 + 4);
+ /* Using both REG_ITMP1 and REG_ITMP2 is faster than only */
+ /* using REG_ITMP1 alternating. */
+ s2 = src->regoff;
+ i386_mov_membase_reg(cd, REG_SP, s2 * 8, REG_ITMP1);
+ i386_mov_membase_reg(cd, REG_SP, s2 * 8 + 4, REG_ITMP2);
+ i386_mov_reg_mem(cd, REG_ITMP1, a);
+ i386_mov_reg_mem(cd, REG_ITMP2, a + 4);
} else {
panic("PUTSTATIC: longs have to be in memory");
}
break;
case TYPE_FLT:
var_to_reg_flt(s2, src, REG_FTMP1);
- i386_fstps_membase(cd, REG_ITMP2, 0);
+ i386_fstps_mem(cd, a);
fpu_st_offset--;
break;
case TYPE_DBL:
var_to_reg_flt(s2, src, REG_FTMP1);
- i386_fstpl_membase(cd, REG_ITMP2, 0);
+ i386_fstpl_mem(cd, a);
fpu_st_offset--;
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 */
- i386_mov_imm_reg(cd, (s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
- i386_mov_imm_reg(cd, (s4) asm_check_clinit, REG_ITMP2);
- i386_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) {
+ i386_nop(cd);
+ i386_nop(cd);
+ i386_nop(cd);
+ i386_nop(cd);
+ i386_nop(cd);
+ }
+ }
- a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
- i386_mov_imm_reg(cd, 0, REG_ITMP2);
- dseg_adddata(cd, cd->mcodeptr);
- i386_mov_membase_reg(cd, REG_ITMP2, a, REG_ITMP2);
+ a = (u4) &(((fieldinfo *) iptr->val.a)->value);
switch (iptr->op1) {
case TYPE_INT:
case TYPE_ADR:
d = reg_of_var(rd, iptr->dst, REG_ITMP1);
- i386_mov_membase_reg(cd, REG_ITMP2, 0, d);
+ i386_mov_mem_reg(cd, a, d);
store_reg_to_var_int(iptr->dst, d);
break;
case TYPE_LNG:
d = reg_of_var(rd, iptr->dst, REG_NULL);
if (iptr->dst->flags & INMEMORY) {
- i386_mov_membase_reg(cd, REG_ITMP2, 0, REG_ITMP1);
+ /* Using both REG_ITMP1 and REG_ITMP2 is faster than only */
+ /* using REG_ITMP1 alternating. */
+ i386_mov_mem_reg(cd, a, REG_ITMP1);
+ i386_mov_mem_reg(cd, a + 4, REG_ITMP2);
i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
- i386_mov_membase_reg(cd, REG_ITMP2, 0 + 4, REG_ITMP1);
- i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
+ i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
} else {
panic("GETSTATIC: longs have to be in memory");
}
break;
case TYPE_FLT:
d = reg_of_var(rd, iptr->dst, REG_FTMP1);
- i386_flds_membase(cd, REG_ITMP2, 0);
+ i386_flds_mem(cd, a);
fpu_st_offset++;
store_reg_to_var_flt(iptr->dst, d);
break;
case TYPE_DBL:
d = reg_of_var(rd, iptr->dst, REG_FTMP1);
- i386_fldl_membase(cd, REG_ITMP2, 0);
+ i386_fldl_mem(cd, a);
fpu_st_offset++;
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 */
- a = ((fieldinfo *)(iptr->val.a))->offset;
+ a = ((fieldinfo *) (iptr->val.a))->offset;
switch (iptr->op1) {
- case TYPE_INT:
- case TYPE_ADR:
- var_to_reg_int(s1, src->prev, REG_ITMP1);
- var_to_reg_int(s2, src, REG_ITMP2);
- gen_nullptr_check(s1);
- i386_mov_reg_membase(cd, s2, s1, a);
- break;
- case TYPE_LNG:
- var_to_reg_int(s1, src->prev, REG_ITMP1);
- gen_nullptr_check(s1);
- if (src->flags & INMEMORY) {
- i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2);
- i386_mov_reg_membase(cd, REG_ITMP2, s1, a);
- i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
- i386_mov_reg_membase(cd, REG_ITMP2, s1, a + 4);
- } else {
- panic("PUTFIELD: longs have to be in memory");
- }
- break;
- case TYPE_FLT:
- var_to_reg_int(s1, src->prev, REG_ITMP1);
- var_to_reg_flt(s2, src, REG_FTMP1);
- gen_nullptr_check(s1);
- i386_fstps_membase(cd, s1, a);
- fpu_st_offset--;
- break;
- case TYPE_DBL:
- var_to_reg_int(s1, src->prev, REG_ITMP1);
- var_to_reg_flt(s2, src, REG_FTMP1);
- gen_nullptr_check(s1);
- i386_fstpl_membase(cd, s1, a);
- fpu_st_offset--;
- break;
- default: panic ("internal error");
+ case TYPE_INT:
+ case TYPE_ADR:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ gen_nullptr_check(s1);
+ i386_mov_reg_membase(cd, s2, s1, a);
+ break;
+ case TYPE_LNG:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ gen_nullptr_check(s1);
+ if (src->flags & INMEMORY) {
+ i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2);
+ i386_mov_reg_membase(cd, REG_ITMP2, s1, a);
+ i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
+ i386_mov_reg_membase(cd, REG_ITMP2, s1, a + 4);
+ } else {
+ panic("PUTFIELD: longs have to be in memory");
}
+ break;
+ case TYPE_FLT:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_flt(s2, src, REG_FTMP1);
+ gen_nullptr_check(s1);
+ i386_fstps_membase(cd, s1, a);
+ fpu_st_offset--;
+ break;
+ case TYPE_DBL:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_flt(s2, src, REG_FTMP1);
+ gen_nullptr_check(s1);
+ i386_fstpl_membase(cd, s1, a);
+ fpu_st_offset--;
+ break;
+ default:
+ throw_cacao_exception_exit(string_java_lang_InternalError,
+ "Unknown PUTFIELD operand type %d",
+ iptr->op1);
+ }
break;
case ICMD_GETFIELD: /* ... ==> ..., value */
/* op1 = type, val.i = field offset */
- a = ((fieldinfo *)(iptr->val.a))->offset;
+ a = ((fieldinfo *) (iptr->val.a))->offset;
switch (iptr->op1) {
- case TYPE_INT:
- case TYPE_ADR:
- var_to_reg_int(s1, src, REG_ITMP1);
- d = reg_of_var(rd, iptr->dst, REG_ITMP2);
- gen_nullptr_check(s1);
- i386_mov_membase_reg(cd, s1, a, d);
- store_reg_to_var_int(iptr->dst, d);
- break;
- case TYPE_LNG:
- var_to_reg_int(s1, src, REG_ITMP1);
- d = reg_of_var(rd, iptr->dst, REG_NULL);
- gen_nullptr_check(s1);
- i386_mov_membase_reg(cd, s1, a, REG_ITMP2);
- i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8);
- i386_mov_membase_reg(cd, s1, a + 4, REG_ITMP2);
- i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
- break;
- case TYPE_FLT:
- var_to_reg_int(s1, src, REG_ITMP1);
- d = reg_of_var(rd, iptr->dst, REG_FTMP1);
- gen_nullptr_check(s1);
- i386_flds_membase(cd, s1, a);
- fpu_st_offset++;
- store_reg_to_var_flt(iptr->dst, d);
- break;
- case TYPE_DBL:
- var_to_reg_int(s1, src, REG_ITMP1);
- d = reg_of_var(rd, iptr->dst, REG_FTMP1);
- gen_nullptr_check(s1);
- i386_fldl_membase(cd, s1, a);
- fpu_st_offset++;
- store_reg_to_var_flt(iptr->dst, d);
- break;
- default: panic ("internal error");
- }
+ case TYPE_INT:
+ case TYPE_ADR:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(rd, iptr->dst, REG_ITMP2);
+ gen_nullptr_check(s1);
+ i386_mov_membase_reg(cd, s1, a, d);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case TYPE_LNG:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(rd, iptr->dst, REG_NULL);
+ gen_nullptr_check(s1);
+ i386_mov_membase_reg(cd, s1, a, REG_ITMP2);
+ i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8);
+ i386_mov_membase_reg(cd, s1, a + 4, REG_ITMP2);
+ i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
+ break;
+ case TYPE_FLT:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(rd, iptr->dst, REG_FTMP1);
+ gen_nullptr_check(s1);
+ i386_flds_membase(cd, s1, a);
+ fpu_st_offset++;
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+ case TYPE_DBL:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(rd, iptr->dst, REG_FTMP1);
+ gen_nullptr_check(s1);
+ i386_fldl_membase(cd, s1, a);
+ fpu_st_offset++;
+ 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;
/* branch operations **************************************************/
- /* TWISTI */
-/* #define ALIGNCODENOP {if((int)((long)cd->mcodeptr&7)){M_NOP;}} */
-#define ALIGNCODENOP do {} while (0)
-
case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
var_to_reg_int(s1, src, REG_ITMP1);
M_INTMOVE(s1, REG_ITMP1_XPTR);
- i386_call_imm(cd, 0); /* passing exception pointer */
+ i386_call_imm(cd, 0); /* passing exception pointer */
i386_pop_reg(cd, REG_ITMP2_XPC);
i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
src = bptr->outstack;
len = bptr->outdepth;
MCODECHECK(64+len);
+#ifdef LSRA
+ if (!opt_lsra)
+#endif
while (src) {
len--;
if ((src->varkind != STACKVAR)) {
i386_push_reg(cd, REG_ITMP2_XPC);
- PREPARE_NATIVE_STACKINFO;
+ /*PREPARE_NATIVE_STACKINFO;*/
+ i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
+ i386_push_imm(cd,0);
+ i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
+ i386_call_reg(cd,REG_ITMP3);
i386_alu_imm_reg(cd, I386_SUB, 1 * 4, REG_SP);
i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0 * 4);
i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);
- REMOVE_NATIVE_STACKINFO;
+ /*REMOVE_NATIVE_STACKINFO;*/
+ i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
+ i386_call_reg(cd,REG_ITMP3);
i386_pop_reg(cd, REG_ITMP2_XPC);
i386_push_reg(cd, REG_ITMP2_XPC);
- PREPARE_NATIVE_STACKINFO;
+ /*PREPARE_NATIVE_STACKINFO;*/
+ i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
+ i386_push_imm(cd,0);
+ i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
+ i386_call_reg(cd,REG_ITMP3);
+
+
i386_mov_imm_reg(cd, (u4) new_negativearraysizeexception, REG_ITMP1);
i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
/*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/
- REMOVE_NATIVE_STACKINFO;
+ /*REMOVE_NATIVE_STACKINFO;*/
+ i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
+ i386_call_reg(cd,REG_ITMP3);
+
i386_pop_reg(cd, REG_ITMP2_XPC);
i386_push_reg(cd, REG_ITMP2_XPC);
- PREPARE_NATIVE_STACKINFO;
+ /*PREPARE_NATIVE_STACKINFO;*/
+ i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
+ i386_push_imm(cd,0);
+ i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
+ i386_call_reg(cd,REG_ITMP3);
+
i386_mov_imm_reg(cd, (u4) new_classcastexception, REG_ITMP1);
i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
/*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/
- REMOVE_NATIVE_STACKINFO;
+ /*REMOVE_NATIVE_STACKINFO;*/
+ i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
+ i386_call_reg(cd,REG_ITMP3);
+
i386_pop_reg(cd, REG_ITMP2_XPC);
i386_push_reg(cd, REG_ITMP2_XPC);
- PREPARE_NATIVE_STACKINFO;
+ /*PREPARE_NATIVE_STACKINFO;*/
+ i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
+ i386_push_imm(cd,0);
+ i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
+ i386_call_reg(cd,REG_ITMP3);
+
+
i386_mov_imm_reg(cd, (u4) new_arithmeticexception, REG_ITMP1);
i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
- REMOVE_NATIVE_STACKINFO;
+ /*REMOVE_NATIVE_STACKINFO;*/
+ i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
+ i386_call_reg(cd,REG_ITMP3);
+
i386_pop_reg(cd, REG_ITMP2_XPC);
i386_push_reg(cd, REG_ITMP2_XPC);
- PREPARE_NATIVE_STACKINFO;
+ /*PREPARE_NATIVE_STACKINFO;*/
+ i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
+ i386_push_imm(cd,0);
+ i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
+ i386_call_reg(cd,REG_ITMP3);
+
i386_mov_imm_reg(cd, (s4) codegen_general_stubcalled, REG_ITMP1);
i386_call_reg(cd, REG_ITMP1);
i386_pop_reg(cd, REG_ITMP1_XPTR);
i386_pop_reg(cd, REG_ITMP3); /* just remove the no longer needed 0 from the stack*/
- REMOVE_NATIVE_STACKINFO;
+ /*REMOVE_NATIVE_STACKINFO;*/
+ i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
+ i386_call_reg(cd,REG_ITMP3);
+
i386_pop_reg(cd, REG_ITMP2_XPC);
i386_push_reg(cd, REG_ITMP2_XPC);
- PREPARE_NATIVE_STACKINFO;
+ /*PREPARE_NATIVE_STACKINFO;*/
+ i386_push_imm(cd,0); /* the pushed XPC is directly below the java frame*/
+ i386_push_imm(cd,0);
+ i386_mov_imm_reg(cd,(s4)asm_prepare_native_stackinfo,REG_ITMP3);
+ i386_call_reg(cd,REG_ITMP3);
+
+
#if 0
/* create native call block*/
i386_mov_imm_reg(cd, (u4) new_nullpointerexception, REG_ITMP1);
i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
- REMOVE_NATIVE_STACKINFO;
+ /*REMOVE_NATIVE_STACKINFO;*/
+ i386_mov_imm_reg(cd,(s4)asm_remove_native_stackinfo,REG_ITMP3);
+ i386_call_reg(cd,REG_ITMP3);
+
#if 0
/* restore native call stack */
i386_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 */
+ i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
+
+ /* Save current stack pointer into a temporary register. */
+ i386_mov_reg_reg(cd, REG_SP, REG_ITMP1);
+
+ /* Push machine code bytes to patch onto the stack. */
+ i386_push_imm(cd, (u4) xmcode);
+ i386_push_imm(cd, (u4) mcode);
+
+ i386_push_imm(cd, (u4) cref->class);
+
+ /* Push previously saved stack pointer onto stack. */
+ i386_push_reg(cd, REG_ITMP1);
+
+ i386_mov_imm_reg(cd, (u4) asm_check_clinit, REG_ITMP1);
+ i386_jmp_reg(cd, REG_ITMP1);
+ }
+ }
}
codegen_finish(m, cd, (u4) (cd->mcodeptr - cd->mcodebase));
u1 *createcompilerstub(methodinfo *m)
{
u1 *s = CNEW(u1, COMPSTUBSIZE); /* memory to hold the stub */
- codegendata *cd = NEW(codegendata);
+ codegendata *cd;
+ s4 dumpsize;
+ /* mark start of dump memory area */
+
+ dumpsize = dump_size();
+
+ cd = DNEW(codegendata);
cd->mcodeptr = s;
/* code for the stub */
i386_mov_imm_reg(cd, (u4) asm_call_jit_compiler, REG_ITMP3);
i386_jmp_reg(cd, REG_ITMP3); /* jump to compiler */
- /* free codegendata memory */
- codegen_close(m);
-
#if defined(STATISTICS)
if (opt_stat)
count_cstub_len += COMPSTUBSIZE;
#endif
- FREE(cd, codegendata);
+ /* release dump area */
+ dump_release(dumpsize);
+
return s;
}
*******************************************************************************/
-#define NATIVESTUBSIZE 350
+#define NATIVESTUBSIZE 370 + 36
+
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
}
+
u1 *createnativestub(functionptr f, methodinfo *m)
{
u1 *s = CNEW(u1, NATIVESTUBSIZE); /* memory to hold the stub */
+ codegendata *cd;
+ registerdata *rd;
+ t_inlining_globals *id;
+ s4 dumpsize;
+
int addmethod=0;
u1 *tptr;
int i;
- int stackframesize = 4+12; /* initial 4 bytes is space for jni env,
- + 4 byte thread pointer + 4 byte previous pointer + method info*/
+ int stackframesize = 4+16; /* initial 4 bytes is space for jni env,
+ + 4 byte thread pointer + 4 byte previous pointer + method info + 4 offset native*/
int stackframeoffset = 4;
int p, t;
u1* jmpInstrPos=0;
void** jmpInstrPatchPos=0;
- codegendata *cd = NEW(codegendata);
- registerdata *rd = NEW(registerdata);
- t_inlining_globals *id = NEW(t_inlining_globals);
+ /* mark start of dump memory area */
+
+ dumpsize = dump_size();
+
+ /* allocate required dump memory */
+
+ cd = DNEW(codegendata);
+ rd = DNEW(registerdata);
+ id = DNEW(t_inlining_globals);
/* setup registers before using it */
+
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;
if (m->flags & ACC_STATIC) {
stackframesize += 4;
stackframeoffset += 4;
}
- reg_init(m);
descriptor2types(m); /* set paramcount and paramtypes */
/*DEBUG*/
/* if function is static, check for initialized */
if (m->flags & ACC_STATIC) {
- /* if class isn't yet initialized, do it */
+ /* if class isn't yet initialized, do it */
if (!m->class->initialized) {
s4 *header = (s4 *) s;
*header = 0;/*extablesize*/
- header;
+ header++;
*header = 0;/*line number table start*/
header++;
*header = 0;/*line number table size*/
*header = 0;/*framesize*/
header++;
*header = (u4) m;/*methodpointer*/
- *header++;
- cd->mcodeptr = s = (u1 *) header;
+ header++;
+
+ s = (u1 *) header;
+
+ cd->mcodebase = s;
+ cd->mcodeptr = s;
addmethod = 1;
- /* call helper function which patches this code */
- i386_mov_imm_reg(cd, (u4) m->class, REG_ITMP1);
- i386_mov_imm_reg(cd, (u4) asm_check_clinit, REG_ITMP2);
- i386_call_reg(cd, REG_ITMP2);
+ codegen_addclinitref(cd, cd->mcodeptr, m->class);
}
}
i386_alu_imm_reg(cd, I386_SUB, stackframesize, REG_SP);
/* CREATE DYNAMIC STACK INFO -- BEGIN*/
- i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
+ i386_mov_imm_membase(cd,0,REG_SP,stackframesize-4);
+ i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-8);
i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo, REG_ITMP1);
i386_call_reg(cd, REG_ITMP1);
- i386_mov_reg_membase(cd, REG_RESULT,REG_SP,stackframesize-8); /*save thread specific pointer*/
+ i386_mov_reg_membase(cd, REG_RESULT,REG_SP,stackframesize-12); /*save thread specific pointer*/
i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2);
- i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,stackframesize-12); /*save previous value of memory adress pointed to by thread specific pointer*/
+ i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,stackframesize-16); /*save previous value of memory adress pointed to by thread specific pointer*/
i386_mov_reg_reg(cd, REG_SP,REG_ITMP2);
- i386_alu_imm_reg(cd, I386_ADD,stackframesize-12,REG_ITMP2);
+ i386_alu_imm_reg(cd, I386_ADD,stackframesize-16,REG_ITMP2);
i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT,0);
/*TESTING ONLY */
/* RESOLVE NATIVE METHOD -- BEGIN*/
#ifndef STATIC_CLASSPATH
if (f==0) {
- log_text("Dynamic classpath: preparing for delayed native function resolving");
+ /*log_text("Dynamic classpath: preparing for delayed native function resolving");*/
i386_jmp_imm(cd,0);
jmpInstrPos=cd->mcodeptr-4;
/*patchposition*/
i386_pop_reg(cd,REG_ITMP1);
/*fix jmp offset replacement*/
(*jmpInstrPatchPos)=cd->mcodeptr-jmpInstrPos-4;
- } else log_text("Dynamic classpath: immediate native function resolution possible");
+ } /*else log_text("Dynamic classpath: immediate native function resolution possible");*/
#endif
/* RESOLVE NATIVE METHOD -- END*/
/*REMOVE DYNAMIC STACK INFO -BEGIN */
i386_push_reg(cd, REG_RESULT2);
- i386_mov_membase_reg(cd, REG_SP,stackframesize-8,REG_ITMP2); /*old value*/
- i386_mov_membase_reg(cd, REG_SP,stackframesize-4,REG_RESULT2); /*pointer*/
+ i386_mov_membase_reg(cd, REG_SP,stackframesize-12,REG_ITMP2); /*old value*/
+ i386_mov_membase_reg(cd, REG_SP,stackframesize-8,REG_RESULT2); /*pointer*/
i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT2,0);
i386_pop_reg(cd, REG_RESULT2);
/*REMOVE DYNAMIC STACK INFO -END */
i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
}
-
/* we can't use REG_ITMP3 == REG_RESULT2 */
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
i386_push_reg(cd, REG_RESULT);
codegen_insertmethod(s, cd->mcodeptr);
}
+ {
+ 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 */
+ i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
+
+ /* Save current stack pointer into a temporary register. */
+ i386_mov_reg_reg(cd, REG_SP, REG_ITMP1);
+
+ /* Push machine code bytes to patch onto the stack. */
+ i386_push_imm(cd, (u4) xmcode);
+ i386_push_imm(cd, (u4) mcode);
+
+ i386_push_imm(cd, (u4) cref->class);
+
+ /* Push previously saved stack pointer onto stack. */
+ i386_push_reg(cd, REG_ITMP1);
+
+ i386_mov_imm_reg(cd, (u4) asm_check_clinit, REG_ITMP1);
+ i386_jmp_reg(cd, REG_ITMP1);
+ }
+ }
+
#if 0
- dolog_plain("native stubentry: %p, stubsize: %x (for %d params) --", (s4)s,(s4) (cd->mcodeptr - s), m->paramcount);
+ dolog_plain("native stubentry: %p, stubsize: %d (for %d params) --", (s4)s,(s4) (cd->mcodeptr - s), m->paramcount);
utf_display(m->name);
dolog_plain("\n");
#endif
- /* free codegendata memory */
- codegen_close(m);
-
#if defined(STATISTICS)
if (opt_stat)
count_nstub_len += NATIVESTUBSIZE;
#endif
- FREE(cd, codegendata);
- FREE(rd, registerdata);
- FREE(id, t_inlining_globals);
+ /* release dump area */
+
+ dump_release(dumpsize);
return s;
}