#endif
}
-gpointer
-mono_arch_get_vcall_slot (guint8 *code_ptr, mgreg_t *regs, int *displacement)
-{
- char *o = NULL;
- int reg, offset = 0;
- guint32* code = (guint32*)code_ptr;
- mgreg_t *r = (mgreg_t*)regs;
-
- *displacement = 0;
-
- /* This is the 'blrl' instruction */
- --code;
-
- /* Sanity check: instruction must be 'blrl' */
- if (*code != 0x4e800021)
- return NULL;
-
- if (mono_ppc_is_direct_call_sequence (code))
- return NULL;
-
- /* FIXME: more sanity checks here */
- /* OK, we're now at the 'blrl' instruction. Now walk backwards
- till we get to a 'mtlr rA' */
- for (; --code;) {
- if((*code & 0x7c0803a6) == 0x7c0803a6) {
- gint16 soff;
- /* Here we are: we reached the 'mtlr rA'.
- Extract the register from the instruction */
- reg = (*code & 0x03e00000) >> 21;
- --code;
- /* ok, this is a lwz reg, offset (vtreg)
- * it is emitted with:
- * ppc_emit32 (c, (32 << 26) | ((D) << 21) | ((a) << 16) | (guint16)(d))
- */
- soff = (*code & 0xffff);
- offset = soff;
- reg = (*code >> 16) & 0x1f;
- g_assert (reg != ppc_r1);
- /*g_print ("patching reg is %d\n", reg);*/
- o = (gpointer)(gsize)r [reg];
- break;
- }
- }
- *displacement = offset;
- return o;
-}
-
#define MAX_ARCH_DELEGATE_PARAMS 7
static gpointer
}
gpointer
-mono_arch_get_this_arg_from_call (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, mgreg_t *regs, guint8 *code)
+mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
{
mgreg_t *r = (mgreg_t*)regs;
- /* FIXME: handle returning a struct */
- if (MONO_TYPE_ISSTRUCT (sig->ret))
- return (gpointer)(gsize)r [ppc_r4];
return (gpointer)(gsize)r [ppc_r3];
}
void
mono_arch_cpu_init (void)
{
-#ifdef __APPLE__
+}
+
+/*
+ * Initialize architecture specific code.
+ */
+void
+mono_arch_init (void)
+{
+#if defined(MONO_CROSS_COMPILE)
+#elif defined(__APPLE__)
int mib [3];
size_t len;
mib [0] = CTL_HW;
#elif defined(G_COMPILER_CODEWARRIOR)
cachelinesize = 32;
cachelineinc = 32;
-#elif defined(MONO_CROSS_COMPILE)
#else
//#error Need a way to get cache line size
#endif
if (mono_cpu_count () > 1)
cpu_hw_caps |= PPC_SMP_CAPABLE;
-}
-
-/*
- * Initialize architecture specific code.
- */
-void
-mono_arch_init (void)
-{
InitializeCriticalSection (&mini_arch_mutex);
ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
guint32 struct_ret;
ArgInfo ret;
ArgInfo sig_cookie;
+ gboolean vtype_retaddr;
+ int vret_arg_index;
ArgInfo args [1];
} CallInfo;
#endif
static CallInfo*
-calculate_sizes (MonoMethodSignature *sig, gboolean is_pinvoke)
+calculate_sizes (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, gboolean is_pinvoke)
{
- guint i, fr, gr;
+ guint i, fr, gr, pstart;
int n = sig->hasthis + sig->param_count;
MonoType *simpletype;
guint32 stack_size = 0;
/* FIXME: handle returning a struct */
if (MONO_TYPE_ISSTRUCT (sig->ret)) {
- add_general (&gr, &stack_size, &cinfo->ret, TRUE);
- cinfo->struct_ret = PPC_FIRST_ARG_REG;
+ cinfo->vtype_retaddr = TRUE;
}
+ pstart = 0;
n = 0;
- if (sig->hasthis) {
- add_general (&gr, &stack_size, cinfo->args + n, TRUE);
- n++;
+ /*
+ * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
+ * the first argument, allowing 'this' to be always passed in the first arg reg.
+ * Also do this if the first argument is a reference type, since virtual calls
+ * are sometimes made using calli without sig->hasthis set, like in the delegate
+ * invoke wrappers.
+ */
+ if (cinfo->vtype_retaddr && !is_pinvoke && (sig->hasthis || (sig->param_count > 0 && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (gsctx, sig->params [0]))))) {
+ if (sig->hasthis) {
+ add_general (&gr, &stack_size, cinfo->args + 0, TRUE);
+ n ++;
+ } else {
+ add_general (&gr, &stack_size, &cinfo->args [sig->hasthis + 0], TRUE);
+ pstart = 1;
+ n ++;
+ }
+ add_general (&gr, &stack_size, &cinfo->ret, TRUE);
+ cinfo->struct_ret = cinfo->ret.reg;
+ cinfo->vret_arg_index = 1;
+ } else {
+ /* this */
+ if (sig->hasthis) {
+ add_general (&gr, &stack_size, cinfo->args + 0, TRUE);
+ n ++;
+ }
+
+ if (cinfo->vtype_retaddr) {
+ add_general (&gr, &stack_size, &cinfo->ret, TRUE);
+ cinfo->struct_ret = cinfo->ret.reg;
+ }
}
+
DEBUG(printf("params: %d\n", sig->param_count));
- for (i = 0; i < sig->param_count; ++i) {
+ for (i = pstart; i < sig->param_count; ++i) {
if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (i == sig->sentinelpos)) {
/* Prevent implicit arguments and sig_cookie from
being passed in registers */
}
if (MONO_TYPE_ISSTRUCT (sig->params [i]) && size < sizeof (gpointer))
size = align = sizeof (gpointer);
+ /*
+ * Use at least 4/8 byte alignment, since these might be passed in registers, and
+ * they are saved using std in the prolog.
+ */
+ align = sizeof (gpointer);
offset += align - 1;
offset &= ~(align - 1);
inst->inst_offset = offset;
m->stack_offset = offset;
if (sig->call_convention == MONO_CALL_VARARG) {
- CallInfo *cinfo = calculate_sizes (m->method->signature, m->method->signature->pinvoke);
+ CallInfo *cinfo = calculate_sizes (m->generic_sharing_context, m->method->signature, m->method->signature->pinvoke);
m->sig_cookie = cinfo->sig_cookie.offset;
sig = call->signature;
n = sig->param_count + sig->hasthis;
- cinfo = calculate_sizes (sig, sig->pinvoke);
+ cinfo = calculate_sizes (cfg->generic_sharing_context, sig, sig->pinvoke);
for (i = 0; i < n; ++i) {
ArgInfo *ainfo = cinfo->args + i;
g_free (cinfo);
}
+#ifndef DISABLE_JIT
+
void
mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
{
return TRUE;
}
+#endif /* DISABLE_JIT */
+
/*
* Allow tracing to work with this interface (with an optional argument)
*/
pos = 0;
- cinfo = calculate_sizes (sig, sig->pinvoke);
+ cinfo = calculate_sizes (cfg->generic_sharing_context, sig, sig->pinvoke);
if (MONO_TYPE_ISSTRUCT (sig->ret)) {
ArgInfo *ainfo = &cinfo->ret;
call = (MonoCallInst*)ins;
sig = mono_method_signature (cfg->method);
- cinfo = calculate_sizes (sig, sig->pinvoke);
+ cinfo = calculate_sizes (cfg->generic_sharing_context, sig, sig->pinvoke);
if (MONO_TYPE_ISSTRUCT (sig->ret))
len += 4;
}
break;
case OP_BREAK:
- ppc_break (code);
+ /*
+ * gdb does not like encountering a trap in the debugged code. So
+ * instead of emitting a trap, we emit a call a C function and place a
+ * breakpoint there.
+ */
+ //ppc_break (code);
+ ppc_mr (code, ppc_r3, ins->sreg1);
+ mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
+ (gpointer)"mono_break");
+ if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) {
+ ppc_load_func (code, ppc_r0, 0);
+ ppc_mtlr (code, ppc_r0);
+ ppc_blrl (code);
+ } else {
+ ppc_bl (code, 0);
+ }
break;
case OP_ADDCC:
case OP_IADDCC:
ppc_sldi (code, ppc_r0, ppc_r0, 32);
#endif
ppc_compare (code, 0, ins->sreg1, ppc_r0);
- EMIT_COND_SYSTEM_EXCEPTION_FLAGS (PPC_BR_TRUE, PPC_BR_EQ, "ArithmeticException");
+ EMIT_COND_SYSTEM_EXCEPTION_FLAGS (PPC_BR_TRUE, PPC_BR_EQ, "OverflowException");
ppc_patch (divisor_is_m1, code);
/* XER format: SO, OV, CA, reserved [21 bits], count [8 bits]
*/
EMIT_COND_SYSTEM_EXCEPTION (CEE_BEQ - CEE_BEQ, "ArithmeticException");
break;
case OP_JUMP_TABLE:
- mono_add_patch_info (cfg, offset, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
+ mono_add_patch_info (cfg, offset, (MonoJumpInfoType)ins->inst_c1, ins->inst_p0);
#ifdef __mono_ppc64__
ppc_load_sequence (code, ins->dreg, (guint64)0x0f0f0f0f0f0f0f0fLL);
#else
#ifndef DISABLE_JIT
void
-mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, gboolean run_cctors)
+mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, MonoCodeManager *dyn_code_mp, gboolean run_cctors)
{
MonoJumpInfo *patch_info;
gboolean compile_aot = !run_cctors;
tracing = 1;
sig = mono_method_signature (method);
- cfg->code_size = MONO_PPC_32_64_CASE (260, 384) + sig->param_count * 20;
+ cfg->code_size = 512 + sig->param_count * 32;
code = cfg->native_code = g_malloc (cfg->code_size);
cfa_offset = 0;
/* load arguments allocated to register from the stack */
pos = 0;
- cinfo = calculate_sizes (sig, sig->pinvoke);
+ cinfo = calculate_sizes (cfg->generic_sharing_context, sig, sig->pinvoke);
if (MONO_TYPE_ISSTRUCT (sig->ret)) {
ArgInfo *ainfo = &cinfo->ret;
} else {
if (ppc_is_imm32 (inst->inst_offset)) {
ppc_addis (code, ppc_r11, inst->inst_basereg, ppc_ha(inst->inst_offset));
- ppc_stb (code, ainfo->reg, ppc_r11, inst->inst_offset);
+ ppc_stb (code, ainfo->reg, inst->inst_offset, ppc_r11);
} else {
ppc_load (code, ppc_r11, inst->inst_offset);
ppc_stbx (code, ainfo->reg, inst->inst_basereg, ppc_r11);
} else {
if (ppc_is_imm32 (inst->inst_offset)) {
ppc_addis (code, ppc_r11, inst->inst_basereg, ppc_ha(inst->inst_offset));
- ppc_sth (code, ainfo->reg, ppc_r11, inst->inst_offset);
+ ppc_sth (code, ainfo->reg, inst->inst_offset, ppc_r11);
} else {
ppc_load (code, ppc_r11, inst->inst_offset);
ppc_sthx (code, ainfo->reg, inst->inst_basereg, ppc_r11);
} else {
if (ppc_is_imm32 (inst->inst_offset)) {
ppc_addis (code, ppc_r11, inst->inst_basereg, ppc_ha(inst->inst_offset));
- ppc_stw (code, ainfo->reg, ppc_r11, inst->inst_offset);
+ ppc_stw (code, ainfo->reg, inst->inst_offset, ppc_r11);
} else {
ppc_load (code, ppc_r11, inst->inst_offset);
ppc_stwx (code, ainfo->reg, inst->inst_basereg, ppc_r11);
} else {
if (ppc_is_imm32 (inst->inst_offset)) {
ppc_addis (code, ppc_r11, inst->inst_basereg, ppc_ha(inst->inst_offset));
- ppc_stptr (code, ainfo->reg, ppc_r11, inst->inst_offset);
+ ppc_stptr (code, ainfo->reg, inst->inst_offset, ppc_r11);
} else {
ppc_load (code, ppc_r11, inst->inst_offset);
ppc_stptr_indexed (code, ainfo->reg, inst->inst_basereg, ppc_r11);
} else {
if (ppc_is_imm32 (inst->inst_offset)) {
ppc_addis (code, ppc_r11, inst->inst_basereg, ppc_ha(inst->inst_offset));
- ppc_stb (code, ppc_r0, ppc_r11, inst->inst_offset);
+ ppc_stb (code, ppc_r0, inst->inst_offset, ppc_r11);
} else {
ppc_load (code, ppc_r11, inst->inst_offset);
ppc_stbx (code, ppc_r0, inst->inst_basereg, ppc_r11);
} else {
if (ppc_is_imm32 (inst->inst_offset)) {
ppc_addis (code, ppc_r11, inst->inst_basereg, ppc_ha(inst->inst_offset));
- ppc_sth (code, ppc_r0, ppc_r11, inst->inst_offset);
+ ppc_sth (code, ppc_r0, inst->inst_offset, ppc_r11);
} else {
ppc_load (code, ppc_r11, inst->inst_offset);
ppc_sthx (code, ppc_r0, inst->inst_basereg, ppc_r11);
} else {
if (ppc_is_imm32 (inst->inst_offset)) {
ppc_addis (code, ppc_r11, inst->inst_basereg, ppc_ha(inst->inst_offset));
- ppc_stw (code, ppc_r0, ppc_r11, inst->inst_offset);
+ ppc_stw (code, ppc_r0, inst->inst_offset, ppc_r11);
} else {
ppc_load (code, ppc_r11, inst->inst_offset);
ppc_stwx (code, ppc_r0, inst->inst_basereg, ppc_r11);
} else {
if (ppc_is_imm32 (inst->inst_offset)) {
ppc_addis (code, ppc_r11, inst->inst_basereg, ppc_ha(inst->inst_offset));
- ppc_stptr (code, ppc_r0, ppc_r11, inst->inst_offset);
+ ppc_stptr (code, ppc_r0, inst->inst_offset, ppc_r11);
} else {
ppc_load (code, ppc_r11, inst->inst_offset);
ppc_stptr_indexed (code, ppc_r0, inst->inst_basereg, ppc_r11);
return MONO_EXC_NULL_REF;
if (strcmp (name, "ArrayTypeMismatchException") == 0)
return MONO_EXC_ARRAY_TYPE_MISMATCH;
+ if (strcmp (name, "ArgumentException") == 0)
+ return MONO_EXC_ARGUMENT;
g_error ("Unknown intrinsic exception %s\n", name);
return 0;
}
return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
}
+GSList*
+mono_arch_get_cie_program (void)
+{
+ GSList *l = NULL;
+
+ mono_add_unwind_op_def_cfa (l, (guint8*)NULL, (guint8*)NULL, ppc_r1, 0);
+
+ return l;
+}
+
MonoInst*
mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
{