#include <sys/sysctl.h>
#endif
+#define FORCE_INDIR_CALL 1
+
enum {
TLS_MODE_DETECT,
TLS_MODE_FAILED,
typedef struct {
gint32 offset;
- guint16 vtsize; /* in param area */
+ guint32 vtsize; /* in param area */
guint8 reg;
guint8 regtype : 4; /* 0 general, 1 basereg, 2 floating point register, see RegType* */
guint8 size : 4; /* 1, 2, 4, 8, or regs used by RegTypeStructByVal */
#else
add_general (&gr, &stack_size, cinfo->args + n, TRUE);
cinfo->args [n].regtype = RegTypeStructByAddr;
+ cinfo->args [n].vtsize = size;
#endif
n++;
break;
#else
add_general (&gr, &stack_size, cinfo->args + n, TRUE);
cinfo->args [n].regtype = RegTypeStructByAddr;
+ cinfo->args [n].vtsize = size;
#endif
n++;
break;
if (arg->type == STACK_I8)
call->used_iregs |= 1 << (ainfo->reg + 1);
} else if (ainfo->regtype == RegTypeStructByAddr) {
- /* FIXME: where si the data allocated? */
- arg->backend.reg3 = ainfo->reg;
- call->used_iregs |= 1 << ainfo->reg;
+ if (ainfo->offset) {
+ MonoPPCArgInfo *ai = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoPPCArgInfo));
+ arg->opcode = OP_OUTARG_MEMBASE;
+ ai->reg = ainfo->reg;
+ ai->size = sizeof (gpointer);
+ ai->offset = ainfo->offset;
+ arg->backend.data = ai;
+ } else {
+ arg->backend.reg3 = ainfo->reg;
+ call->used_iregs |= 1 << ainfo->reg;
+ }
} else if (ainfo->regtype == RegTypeStructByVal) {
int cur_reg;
MonoPPCArgInfo *ai = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoPPCArgInfo));
if (last_ins && (last_ins->opcode == OP_STOREI1_MEMBASE_REG) &&
ins->inst_basereg == last_ins->inst_destbasereg &&
ins->inst_offset == last_ins->inst_offset) {
- if (ins->dreg == last_ins->sreg1) {
- last_ins->next = ins->next;
- ins = ins->next;
- continue;
- } else {
- //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
- ins->opcode = OP_MOVE;
- ins->sreg1 = last_ins->sreg1;
- }
+ ins->opcode = (ins->opcode == OP_LOADI1_MEMBASE) ? CEE_CONV_I1 : CEE_CONV_U1;
+ ins->sreg1 = last_ins->sreg1;
}
break;
case OP_LOADU2_MEMBASE:
if (last_ins && (last_ins->opcode == OP_STOREI2_MEMBASE_REG) &&
ins->inst_basereg == last_ins->inst_destbasereg &&
ins->inst_offset == last_ins->inst_offset) {
- if (ins->dreg == last_ins->sreg1) {
- last_ins->next = ins->next;
- ins = ins->next;
- continue;
- } else {
- //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
- ins->opcode = OP_MOVE;
- ins->sreg1 = last_ins->sreg1;
- }
+ ins->opcode = (ins->opcode == OP_LOADI2_MEMBASE) ? CEE_CONV_I2 : CEE_CONV_U2;
+ ins->sreg1 = last_ins->sreg1;
}
break;
case CEE_CONV_I4:
PPC_BR_LT
};
-static const char*const * ins_spec = ppcg4;
-
static void
insert_after_ins (MonoBasicBlock *bb, MonoInst *ins, MonoInst *to_insert)
{
int imm;
/* setup the virtual reg allocator */
- if (bb->max_ireg > cfg->rs->next_vireg)
- cfg->rs->next_vireg = bb->max_ireg;
+ if (bb->max_vreg > cfg->rs->next_vreg)
+ cfg->rs->next_vreg = bb->max_vreg;
ins = bb->code;
while (ins) {
ins = ins->next;
}
bb->last_ins = last_ins;
- bb->max_ireg = cfg->rs->next_vireg;
+ bb->max_vreg = cfg->rs->next_vreg;
}
return;
}
- if (prim == 15 || ins == 0x4e800021) {
+ if (prim == 15 || ins == 0x4e800021 || ins == 0x4e800020 || ins == 0x4e800420) {
guint32 *seq;
- /* the trampoline code will try to patch the blrl */
- if (ins == 0x4e800021) {
+ /* the trampoline code will try to patch the blrl, blr, bcctr */
+ if (ins == 0x4e800021 || ins == 0x4e800020 || ins == 0x4e800420) {
code -= 12;
}
/* this is the lis/ori/mtlr/blrl sequence */
g_assert ((seq [0] >> 26) == 15);
g_assert ((seq [1] >> 26) == 24);
g_assert ((seq [2] >> 26) == 31);
- g_assert (seq [3] == 0x4e800021);
+ g_assert (seq [3] == 0x4e800021 || seq [3] == 0x4e800020 || seq [3] == 0x4e800420);
/* FIXME: make this thread safe */
ppc_lis (code, ppc_r0, (guint32)(target) >> 16);
ppc_ori (code, ppc_r0, ppc_r0, (guint32)(target) & 0xffff);
while (ins) {
offset = code - cfg->native_code;
- max_len = ((guint8 *)ins_spec [ins->opcode])[MONO_INST_LEN];
+ max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
if (offset > (cfg->code_size - max_len - 16)) {
cfg->code_size *= 2;
if (!(ins->inst_imm & 0xffff0000)) {
ppc_ori (code, ins->sreg1, ins->dreg, ins->inst_imm);
} else if (!(ins->inst_imm & 0xffff)) {
- ppc_oris (code, ins->sreg1, ins->dreg, ((guint32)(ins->inst_imm) >> 16));
+ ppc_oris (code, ins->dreg, ins->sreg1, ((guint32)(ins->inst_imm) >> 16));
} else {
g_assert_not_reached ();
}
mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_METHOD, call->method);
else
mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_ABS, call->fptr);
- if (cfg->method->dynamic) {
+ if (FORCE_INDIR_CALL || cfg->method->dynamic) {
ppc_lis (code, ppc_r0, 0);
ppc_ori (code, ppc_r0, ppc_r0, 0);
ppc_mtlr (code, ppc_r0);
ppc_mr (code, ppc_r3, ins->sreg1);
mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
(gpointer)"mono_arch_throw_exception");
- if (cfg->method->dynamic) {
+ if (FORCE_INDIR_CALL || cfg->method->dynamic) {
ppc_lis (code, ppc_r0, 0);
ppc_ori (code, ppc_r0, ppc_r0, 0);
ppc_mtlr (code, ppc_r0);
ppc_mr (code, ppc_r3, ins->sreg1);
mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
(gpointer)"mono_arch_rethrow_exception");
- if (cfg->method->dynamic) {
+ if (FORCE_INDIR_CALL || cfg->method->dynamic) {
ppc_lis (code, ppc_r0, 0);
ppc_ori (code, ppc_r0, ppc_r0, 0);
ppc_mtlr (code, ppc_r0);
g_assert_not_reached ();
break;
case OP_FCOMPARE:
- ppc_fcmpo (code, 0, ins->sreg1, ins->sreg2);
+ ppc_fcmpu (code, 0, ins->sreg1, ins->sreg2);
break;
case OP_FCEQ:
ppc_fcmpo (code, 0, ins->sreg1, ins->sreg2);
EMIT_COND_BRANCH (ins, CEE_BNE_UN - CEE_BEQ);
break;
case OP_FBLT:
+ ppc_bc (code, PPC_BR_TRUE, PPC_BR_SO, 2);
EMIT_COND_BRANCH (ins, CEE_BLT - CEE_BEQ);
break;
case OP_FBLT_UN:
EMIT_COND_BRANCH (ins, CEE_BLT_UN - CEE_BEQ);
break;
case OP_FBGT:
+ ppc_bc (code, PPC_BR_TRUE, PPC_BR_SO, 2);
EMIT_COND_BRANCH (ins, CEE_BGT - CEE_BEQ);
break;
case OP_FBGT_UN:
EMIT_COND_BRANCH (ins, CEE_BGT_UN - CEE_BEQ);
break;
case OP_FBGE:
+ ppc_bc (code, PPC_BR_TRUE, PPC_BR_SO, 2);
EMIT_COND_BRANCH (ins, CEE_BGE - CEE_BEQ);
break;
case OP_FBGE_UN:
EMIT_COND_BRANCH (ins, CEE_BGE_UN - CEE_BEQ);
break;
case OP_FBLE:
+ ppc_bc (code, PPC_BR_TRUE, PPC_BR_SO, 2);
EMIT_COND_BRANCH (ins, CEE_BLE - CEE_BEQ);
break;
case OP_FBLE_UN:
max_offset += 6;
while (ins) {
- max_offset += ((guint8 *)ins_spec [ins->opcode])[MONO_INST_LEN];
+ max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
ins = ins->next;
}
}
code = emit_memcpy (code, ainfo->vtsize * sizeof (gpointer), inst->inst_basereg, doffset, ppc_r11, ainfo->offset + soffset);
}
} else if (ainfo->regtype == RegTypeStructByAddr) {
+ /* if it was originally a RegTypeBase */
+ if (ainfo->offset) {
+ /* load the previous stack pointer in r11 */
+ ppc_lwz (code, ppc_r11, 0, ppc_sp);
+ ppc_lwz (code, ppc_r11, ainfo->offset, ppc_r11);
+ } else {
+ ppc_mr (code, ppc_r11, ainfo->reg);
+ }
g_assert (ppc_is_imm16 (inst->inst_offset));
- /* FIXME: handle overrun! with struct sizes not multiple of 4 */
- code = emit_memcpy (code, ainfo->vtsize * sizeof (gpointer), inst->inst_basereg, inst->inst_offset, ainfo->reg, 0);
+ code = emit_memcpy (code, ainfo->vtsize, inst->inst_basereg, inst->inst_offset, ppc_r11, 0);
+ /*g_print ("copy in %s: %d bytes from %d to offset: %d\n", method->name, ainfo->vtsize, ainfo->reg, inst->inst_offset);*/
} else
g_assert_not_reached ();
}
if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
ppc_load (code, ppc_r3, cfg->domain);
mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_jit_thread_attach");
- ppc_bl (code, 0);
+ if (FORCE_INDIR_CALL || cfg->method->dynamic) {
+ ppc_lis (code, ppc_r0, 0);
+ ppc_ori (code, ppc_r0, ppc_r0, 0);
+ ppc_mtlr (code, ppc_r0);
+ ppc_blrl (code);
+ } else {
+ ppc_bl (code, 0);
+ }
}
if (method->save_lmf) {
} else {
mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
(gpointer)"mono_get_lmf_addr");
- if (cfg->method->dynamic) {
+ if (FORCE_INDIR_CALL || cfg->method->dynamic) {
ppc_lis (code, ppc_r0, 0);
ppc_ori (code, ppc_r0, ppc_r0, 0);
ppc_mtlr (code, ppc_r0);
if (patch_info->type == MONO_PATCH_INFO_EXC) {
i = exception_id_by_name (patch_info->data.target);
if (!exc_throw_found [i]) {
- max_epilog_size += 12;
+ max_epilog_size += 24;
exc_throw_found [i] = TRUE;
}
} else if (patch_info->type == MONO_PATCH_INFO_BB_OVF)
MonoOvfJump *ovfj = patch_info->data.target;
i = exception_id_by_name (ovfj->data.exception);
if (!exc_throw_found [i]) {
- max_epilog_size += 12;
+ max_epilog_size += 24;
exc_throw_found [i] = TRUE;
}
max_epilog_size += 8;
patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
patch_info->data.name = "mono_arch_throw_exception_by_name";
patch_info->ip.i = code - cfg->native_code;
- ppc_b (code, 0);
+ if (FORCE_INDIR_CALL || cfg->method->dynamic) {
+ ppc_lis (code, ppc_r0, 0);
+ ppc_ori (code, ppc_r0, ppc_r0, 0);
+ ppc_mtctr (code, ppc_r0);
+ ppc_bcctr (code, PPC_BR_ALWAYS, 0);
+ } else {
+ ppc_b (code, 0);
+ }
break;
}
default: