Authors: Andreas Krall
Christian Thalinger
- $Id: codegen.c 1526 2004-11-17 15:50:27Z twisti $
+ $Id: codegen.c 1581 2004-11-24 13:57:02Z twisti $
*/
/* #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[] = {
+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,
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;
+
+ 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;
+ cref->xmcode = *xcodeptr;
+ cref->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) cref->xmcode);
+ x86_64_push_imm(cd, (u4) cref->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)
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);
}
}
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;
+
+ 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;
+ cref->xmcode = *xcodeptr;
+ cref->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) cref->xmcode);
+ x86_64_push_imm(cd, (u4) cref->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;