RegTypeBase,
RegTypeFP,
RegTypeStructByVal,
- RegTypeStructByAddr,
- RegTypeFPStructByVal, // For the v2 ABI, floats should be passed in FRs instead of GRs. Only valid for ABI v2!
+ RegTypeStructByAddr
};
typedef struct {
gint32 offset;
guint32 vtsize; /* in param area */
guint8 reg;
- guint8 vtregs; /* number of registers used to pass a RegTypeStructByVal/RegTypeFPStructByVal */
+ guint8 vtregs; /* number of registers used to pass a RegTypeStructByVal */
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/RegTypeFPStructByVal */
+ guint8 size : 4; /* 1, 2, 4, 8, or regs used by RegTypeStructByVal */
guint8 bytes : 4; /* size in bytes - only valid for
- RegTypeStructByVal/RegTypeFPStructByVal if the struct fits
+ RegTypeStructByVal if the struct fits
in one word, otherwise it's 0*/
} ArgInfo;
#define DEBUG(a)
-
-//
-// Test if a structure completely composed of fields that are all floats XOR doubles and that there are fewer than
-// 8 () members.
-// Note: If this is true the structure can be returned directly via registers fr1 through fr8 instead of by a hidden parameter
-// pointing to where the return value should be stored.
-// This is as per the ELF ABI v2.
-//
-#if PPC_RETURN_SMALL_FLOAT_STRUCTS_IN_FR_REGS
-gboolean
-is_float_struct_returnable_via_regs (MonoClass *klass)
-{
- gboolean has_a_field = FALSE;
- int member_cnt = 0;
- if (klass) {
- gpointer iter = NULL;
- MonoClassField *f = 0;
- MonoClassField *firstMember = &klass->fields [0];
- if (!firstMember) {
- mono_class_setup_fields_locking (klass);
- firstMember = &klass->fields [0];
- if (!firstMember) {
- return FALSE;
- }
- }
- while ((f = mono_class_get_fields (klass, &iter)) && (member_cnt <= PPC_MOST_FLOAT_STRUCT_MEMBERS_TO_RETURN_VIA_REGISTERS)) {
- if (!(f->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
- if (!f->type->byref && mono_metadata_type_equal(firstMember->type, f->type) && (f->type->type == MONO_TYPE_R4 || f->type->type == MONO_TYPE_R8)) {
- has_a_field = TRUE;
- ++member_cnt;
- } else
- return FALSE;
- }
- }
- }
- return has_a_field && (member_cnt <= PPC_MOST_FLOAT_STRUCT_MEMBERS_TO_RETURN_VIA_REGISTERS);
-}
-#endif
-
-
-//
-// Test if a structure is smaller in size than 2 doublewords (PPC_LARGEST_STRUCT_SIZE_TO_RETURN_VIA_REGISTERS) and is
-// completely composed of fields all of basic types.
-// Note: If this is true the structure can be returned directly via registers r3/r4 instead of by a hidden parameter
-// pointing to where the return value should be stored.
-// This is as per the ELF ABI v2.
-//
-#if PPC_RETURN_SMALL_STRUCTS_IN_REGS
-gboolean
-is_struct_returnable_via_regs (MonoClass *klass, gboolean is_pinvoke)
-{
- gboolean has_a_field = FALSE;
- int size = 0;
- if (klass) {
- gpointer iter = NULL;
- MonoClassField *f;
- MonoClassField *firstMember = &klass->fields [0];
- if (!firstMember) {
- mono_class_setup_fields_locking (klass);
- firstMember = &klass->fields [0];
- if (!firstMember) {
- return FALSE;
- }
- }
- if (is_pinvoke)
- size = mono_type_native_stack_size (&klass->byval_arg, 0);
- else
- size = mini_type_stack_size (NULL, &klass->byval_arg, 0);
- if ((size == 0) || (size > PPC_LARGEST_STRUCT_SIZE_TO_RETURN_VIA_REGISTERS))
- return FALSE;
- while ((f = mono_class_get_fields (klass, &iter))) {
- if (!(f->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
- // TBD: Is there a better way to check for the basic types?
- if (!f->type->byref && (f->type->type >= MONO_TYPE_BOOLEAN) && (f->type->type <= MONO_TYPE_R8)) {
- has_a_field = TRUE;
- } else
- return FALSE;
- }
- }
- }
- return has_a_field;
-}
-#endif
-
-gint
-member_count (MonoClass *klass)
-{
- gint field_cnt = 0;
- if (klass) {
- gpointer iter = NULL;
- MonoClassField *f;
- while ((f = mono_class_get_fields (klass, &iter))) {
- if (!(f->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
- ++field_cnt;
- }
- }
- }
- return field_cnt;
-}
-
-gint
-float_member_size (MonoClass *klass)
-{
- if (klass) {
- MonoClassField *firstMember = &klass->fields [0];
- g_assert (firstMember);
- // The class is homogenous so the first member will be the same as all the members
- if (firstMember->type->type == MONO_TYPE_R4)
- return 4;
- else if (firstMember->type->type == MONO_TYPE_R8)
- return 8;
- else
- // Floats should always be 4 or 8 bytes
- g_assert_not_reached ();
- }
-
- return 0;
-}
-
-
-#if PPC_RETURN_SMALL_STRUCTS_IN_REGS
-// If the value is being returned via registers we don't need to allocate a temporary variable for it.
-// Note that this can have effects elsewhere (like with the unbox code) that expects there to be a
-// variable.
-gboolean
-function_return_value_requires_temporary (MonoMethodSignature *sig) {
- MonoType *sig_ret = mini_replace_type (sig->ret);
- gboolean is_all_floats = is_float_struct_returnable_via_regs(mono_class_from_mono_type (sig_ret));
- gboolean is_returnable_via_regs = is_struct_returnable_via_regs(mono_class_from_mono_type (sig_ret), sig->pinvoke);
- DEBUG_ELFABIV2_printf("return_value_requires_temporary: sig_ret: FL? %d non-FL? %d ", (int)is_all_floats, (int)is_returnable_via_regs); DEBUG_ELFABIV2_mono_print_klass(mono_class_from_mono_type (sig_ret));
-
- return (!is_all_floats && !is_returnable_via_regs);
-}
-#endif
-
-
-#ifdef MONO_ARCH_RETURN_CAN_USE_MULTIPLE_REGISTERS
-void
-mono_arch_handle_multiple_dregs(MonoBasicBlock *bb, MonoCompile *cfg, MonoInst *ins, MonoInst *var) {
- if (ins->opcode == OP_LOAD_MEMBASE &&
- var->backend.additional_regs) {
- MonoInst *tmp = 0;
- DEBUG_ELFABIV2_printf("mono_spill_global_vars Existing non-float load: "); DEBUG_ELFABIV2_mono_print_ins(ins);
- DEBUG_ELFABIV2_printf(" klass: "); DEBUG_ELFABIV2_mono_print_klass(var->klass);
- MONO_INST_NEW (cfg, tmp, OP_LOAD_MEMBASE);
- *tmp = *ins;
- tmp->dreg += 1;
- tmp->inst_offset += 8; // FIXME: use a proper constant here
- mono_bblock_insert_after_ins (bb, ins, tmp);
- DEBUG_ELFABIV2_printf(" Adding new load: "); DEBUG_ELFABIV2_mono_print_ins(tmp);
- } else if (((ins->opcode == OP_LOADR4_MEMBASE) || (ins->opcode == OP_LOADR8_MEMBASE)) &&
- var->backend.additional_regs) {
- // Return small (<= 8 member) structures entirely made up of either float or double members
- // in FR registers.
- MonoInst *tmp = 0;
- int cnt = 0;
- int mbr_cnt = member_count(var->klass);
- int mbr_size = float_member_size(var->klass);
- DEBUG_ELFABIV2_printf("mono_spill_global_vars Existing float/double load: "); DEBUG_ELFABIV2_mono_print_ins(ins);
- DEBUG_ELFABIV2_printf(" klass: "); DEBUG_ELFABIV2_mono_print_klass(var->klass);
- for (cnt=0; cnt < mbr_cnt; ++cnt) {
- MONO_INST_NEW (cfg, tmp, OP_LOAD_MEMBASE);
- *tmp = *ins;
- tmp->dreg += 1;
- tmp->inst_offset += mbr_size;
- mono_bblock_insert_after_ins (bb, ins, tmp);
- DEBUG_ELFABIV2_printf(" Adding new load: "); DEBUG_ELFABIV2_mono_print_ins(tmp);
- } // for
- } // else if
-}
-#endif
-
-
static void inline
add_general (guint *gr, guint *stack_size, ArgInfo *ainfo, gboolean simple)
{
(*gr) ++;
}
-#if defined(__APPLE__) || (defined(__mono_ppc64__) && !PPC_PASS_SMALL_FLOAT_STRUCTS_IN_FR_REGS)
+#if defined(__APPLE__) || defined(__mono_ppc64__)
static gboolean
has_only_a_r48_field (MonoClass *klass)
{
guint32 stack_size = 0;
CallInfo *cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * n);
gboolean is_pinvoke = sig->pinvoke;
- gboolean is_struct = MONO_TYPE_ISSTRUCT (sig->ret);
- MonoClass *klass = mono_class_from_mono_type (sig->ret);
- gboolean is_all_floats = FALSE;
- gboolean is_returnable_via_regs = FALSE;
fr = PPC_FIRST_FPARG_REG;
gr = PPC_FIRST_ARG_REG;
- // Handle returning small structs via registers
- // This is active for two cases:
- // 1) All-float (or double) member structs with 8 or fewer members
- // 2) Other structures smaller than 16 bytes
- if (is_struct) {
- is_all_floats = is_float_struct_returnable_via_regs(klass);
- is_returnable_via_regs = is_struct_returnable_via_regs(klass, sig->pinvoke);
- if (!is_all_floats && !is_returnable_via_regs) {
+ /* FIXME: handle returning a struct */
+ if (MONO_TYPE_ISSTRUCT (sig->ret)) {
cinfo->vtype_retaddr = TRUE;
}
- }
pstart = 0;
n = 0;
* are sometimes made using calli without sig->hasthis set, like in the delegate
* invoke wrappers.
*/
- if (is_struct && !is_pinvoke && (sig->hasthis || (sig->param_count > 0 && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (gsctx, sig->params [0]))))) {
+ 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 ++;
pstart = 1;
n ++;
}
- if (!is_all_floats && !is_returnable_via_regs) {
add_general (&gr, &stack_size, &cinfo->ret, TRUE);
cinfo->struct_ret = cinfo->ret.reg;
cinfo->vret_arg_index = 1;
- } else {
- cinfo->struct_ret = -1; // Just a flag for later
- }
} else {
/* this */
if (sig->hasthis) {
n ++;
}
- if (is_struct) {
- if (!is_all_floats && !is_returnable_via_regs) {
+ if (cinfo->vtype_retaddr) {
add_general (&gr, &stack_size, &cinfo->ret, TRUE);
cinfo->struct_ret = cinfo->ret.reg;
- } else {
- cinfo->struct_ret = -1; // Just a flag for later
- }
}
}
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_TYPEDBYREF: {
gint size;
- MonoClass *klass = mono_class_from_mono_type (sig->params [i]);
+ MonoClass *klass;
+
+ klass = mono_class_from_mono_type (sig->params [i]);
if (simpletype->type == MONO_TYPE_TYPEDBYREF)
size = sizeof (MonoTypedRef);
else if (is_pinvoke)
else
size = mono_class_value_size (klass, NULL);
-#if defined(__APPLE__) || (defined(__mono_ppc64__) && !PPC_PASS_SMALL_FLOAT_STRUCTS_IN_FR_REGS)
+#if defined(__APPLE__) || defined(__mono_ppc64__)
if ((size == 4 || size == 8) && has_only_a_r48_field (klass)) {
cinfo->args [n].size = size;
{
int align_size = size;
int nregs = 0;
- int rest = 0;
- int n_in_regs = 0;
- int mbr_cnt = member_count (klass);
- gboolean is_all_floats = is_float_struct_returnable_via_regs(klass);
-
- if (!is_all_floats) {
- rest = PPC_LAST_ARG_REG - gr + 1;
- } else {
- rest = PPC_LAST_FPARG_REG - fr + 1;
- }
+ int rest = PPC_LAST_ARG_REG - gr + 1;
+ int n_in_regs;
-#if PPC_PASS_SMALL_FLOAT_STRUCTS_IN_FR_REGS
- // Pass small (<= 8 member) structures entirely made up of either float or double members
- // in FR registers. There have to be at least mbr_cnt registers left.
- if (is_all_floats &&
- (rest >= mbr_cnt) &&
- (mbr_cnt <= 8)) {
- int mbr_size = float_member_size(klass);
- nregs = mbr_cnt; // size / memberSize;
- n_in_regs = MIN (rest, nregs);
- cinfo->args [n].regtype = RegTypeFPStructByVal;
- cinfo->args [n].vtregs = n_in_regs;
- cinfo->args [n].size = mbr_size;
- cinfo->args [n].vtsize = nregs - n_in_regs;
- cinfo->args [n].reg = fr;
- fr += n_in_regs;
- if (mbr_size == 4) {
- // floats
- FP_ALSO_IN_REG (gr += (n_in_regs+1)/2);
- } else {
- // doubles
- FP_ALSO_IN_REG (gr += (n_in_regs));
- }
- } else
-#endif
- {
align_size += (sizeof (gpointer) - 1);
align_size &= ~(sizeof (gpointer) - 1);
nregs = (align_size + sizeof (gpointer) -1 ) / sizeof (gpointer);
cinfo->args [n].size = n_in_regs;
cinfo->args [n].vtsize = nregs - n_in_regs;
cinfo->args [n].reg = gr;
- gr += n_in_regs;
- }
#ifdef __mono_ppc64__
if (nregs == 1 && is_pinvoke)
else
#endif
cinfo->args [n].bytes = 0;
+ gr += n_in_regs;
cinfo->args [n].offset = PPC_STACK_PARAM_OFFSET + stack_size;
/*g_print ("offset for arg %d at %d\n", n, PPC_STACK_PARAM_OFFSET + stack_size);*/
stack_size += nregs * sizeof (gpointer);
cinfo->args [n].size = 4;
/* It was 7, now it is 8 in LinuxPPC */
- if (fr <= PPC_LAST_FPARG_REG
-#if (_CALL_ELF == 2)
- // For non-native vararg calls the parms must go in storage
- && !(!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG))
-#endif
- ) {
+ if (fr <= PPC_LAST_FPARG_REG) {
cinfo->args [n].regtype = RegTypeFP;
cinfo->args [n].reg = fr;
fr ++;
case MONO_TYPE_R8:
cinfo->args [n].size = 8;
/* It was 7, now it is 8 in LinuxPPC */
- if (fr <= PPC_LAST_FPARG_REG
-#if (_CALL_ELF == 2)
- // For non-native vararg calls the parms must go in storage
- && !(!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG))
-#endif
- ) {
+ if (fr <= PPC_LAST_FPARG_REG) {
cinfo->args [n].regtype = RegTypeFP;
cinfo->args [n].reg = fr;
fr ++;
offset = 0;
curinst = 0;
if (MONO_TYPE_ISSTRUCT (sig->ret)) {
- int size=0;
- MonoClass *klass = mono_class_from_mono_type (sig->ret);
- gboolean is_all_floats = is_float_struct_returnable_via_regs(klass);
- gboolean is_returnable_via_regs = is_struct_returnable_via_regs(klass, sig->pinvoke);
-
- m->ret->backend.additional_regs = 0;
m->ret->opcode = OP_REGVAR;
- if (!is_all_floats) {
m->ret->inst_c0 = m->ret->dreg = ppc_r3;
- DEBUG_ELFABIV2_printf("Changed m->ret->dreg to ppc_r3: "); DEBUG_ELFABIV2_mono_print_ins(m->ret);
- if (is_returnable_via_regs) {
- if (sig->pinvoke)
- size = mono_type_native_stack_size (sig->ret, 0);
- else
- size = mini_type_stack_size (NULL, sig->ret, 0);
- if (size > 8) { // FIXME: replace "8" with proper constant
- m->ret->backend.additional_regs = 1;
- DEBUG_ELFABIV2_printf(" and added ppc_r4 for non-floats (later): "); DEBUG_ELFABIV2_mono_print_ins(m->ret);
- }
- }
- } else { // is_all_floats
- int mbr_cnt = member_count(klass);
- m->ret->inst_c0 = m->ret->dreg = ppc_f1;
- DEBUG_ELFABIV2_printf("Changed m->ret->dreg to ppc_f1: "); DEBUG_ELFABIV2_mono_print_ins(m->ret);
- if (mbr_cnt > 1) {
- m->ret->backend.additional_regs = 1;
- }
- }
} else {
/* FIXME: handle long values? */
switch (mini_type_get_underlying_type (m->generic_sharing_context, sig->ret)->type) {
#endif
if (MONO_TYPE_ISSTRUCT (sig->ret)) {
- // The return value for a structure may either be returned via address or via registers depending on its size
- MonoClass *klass = mono_class_from_mono_type (sig->ret);
- gboolean is_all_floats = is_float_struct_returnable_via_regs(klass);
- gboolean is_returnable_via_regs = is_struct_returnable_via_regs(klass, sig->pinvoke);
-
- if (!is_all_floats && !is_returnable_via_regs) {
- // function value will be returned indirectly
offset += sizeof(gpointer) - 1;
offset &= ~(sizeof(gpointer) - 1);
offset += sizeof(gpointer);
}
- else {
- // function return value will be returned via registers
- // Anything to do here?
- }
- }
offsets = mono_allocate_stack_slots (m, FALSE, &locals_stack_size, &locals_stack_align);
if (locals_stack_align) {
{
MonoMethodSignature *sig = mono_method_signature (cfg->method);
- // The return value for a structure may either be returned via address or via registers depending on its size
if (MONO_TYPE_ISSTRUCT (sig->ret)) {
- MonoClass *klass = mono_class_from_mono_type (sig->ret);
- gboolean is_all_floats = is_float_struct_returnable_via_regs(klass);
- gboolean is_returnable_via_regs = is_struct_returnable_via_regs(klass, sig->pinvoke);
-
- if (!is_all_floats && !is_returnable_via_regs) {
cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
}
}
-}
/* Fixme: we need an alignment solution for enter_method and mono_arch_call_opcode,
* currently alignment in mono_arch_call_opcode is computed without arch_get_argument_info
ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
MONO_ADD_INS (cfg->cbb, ins);
- } else if (ainfo->regtype == RegTypeFPStructByVal) {
- /* this is further handled in mono_arch_emit_outarg_vt () */
- MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
- ins->opcode = OP_OUTARG_VT;
- ins->sreg1 = in->dreg;
- ins->klass = in->klass;
- ins->inst_p0 = call;
- ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
- memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
- MONO_ADD_INS (cfg->cbb, ins);
- cfg->flags |= MONO_CFG_HAS_FPOUT;
} else if (ainfo->regtype == RegTypeBase) {
if (!t->byref && ((t->type == MONO_TYPE_I8) || (t->type == MONO_TYPE_U8))) {
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, ppc_r1, ainfo->offset, in->dreg);
emit_sig_cookie (cfg, call, cinfo);
if (cinfo->struct_ret) {
- // Handle returning small structs via registers
- // This is active for two cases:
- // 1) All-float (or double) member structs with 8 or fewer members
- // 2) Other non-float structures 16 bytes or smaller
- gboolean is_all_floats = is_float_struct_returnable_via_regs(((MonoInst*)call)->klass); // Also verifies <= 8 members
- gboolean is_returnable_via_regs = is_struct_returnable_via_regs(((MonoInst*)call)->klass, sig->pinvoke); // Also verifies <= 8 members
-
- if (!is_all_floats && !is_returnable_via_regs) {
MonoInst *vtarg;
MONO_INST_NEW (cfg, vtarg, OP_MOVE);
MONO_ADD_INS (cfg->cbb, vtarg);
mono_call_inst_add_outarg_reg (cfg, call, vtarg->dreg, cinfo->struct_ret, FALSE);
- } else {
- // structure will be returned via registers
- DEBUG_ELFABIV2_printf("mono_arch_emit_call call->vret_in_reg = TRUE! for "); DEBUG_ELFABIV2_mono_print_ins((MonoInst*)call);
- call->vret_in_reg = TRUE;
- }
}
call->stack_usage = cinfo->stack_usage;
} else
#endif
for (i = 0; i < ainfo->vtregs; ++i) {
+ int antipadding = 0;
+ if (ainfo->bytes) {
+ g_assert (i == 0);
+ antipadding = sizeof (gpointer) - ainfo->bytes;
+ }
dreg = mono_alloc_ireg (cfg);
- if (ainfo->bytes && mono_class_native_size (ins->klass, NULL) == 1) {
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, dreg, src->dreg, soffset);
- } else if (ainfo->bytes && mono_class_native_size (ins->klass, NULL) == 2) {
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU2_MEMBASE, dreg, src->dreg, soffset);
- } else if (ainfo->bytes && mono_class_native_size (ins->klass, NULL) == 4) { // FIXME -- Maybe <= 4?
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU4_MEMBASE, dreg, src->dreg, soffset);
- } else {
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, src->dreg, soffset);
- }
+ if (antipadding)
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_UN_IMM, dreg, dreg, antipadding * 8);
mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg + i, FALSE);
soffset += sizeof (gpointer);
}
if (ovf_size != 0)
mini_emit_memcpy (cfg, ppc_r1, doffset + soffset, src->dreg, soffset, ovf_size * sizeof (gpointer), 0);
- } else if (ainfo->regtype == RegTypeFPStructByVal) {
- soffset = 0;
- for (i = 0; i < ainfo->vtregs; ++i) {
- int tmpr = mono_alloc_freg (cfg);
- if (ainfo->size == 4)
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, tmpr, src->dreg, soffset);
- else // ==8
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, tmpr, src->dreg, soffset);
- dreg = mono_alloc_freg (cfg);
- MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, dreg, tmpr);
- mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg+i, TRUE);
- soffset += ainfo->size;
- }
- if (ovf_size != 0)
- mini_emit_memcpy (cfg, ppc_r1, doffset + soffset, src->dreg, soffset, ovf_size * sizeof (gpointer), 0);
} else if (ainfo->regtype == RegTypeFP) {
int tmpr = mono_alloc_freg (cfg);
if (ainfo->size == 4)
if (enable_arguments) {
/* FIXME: get the actual address */
ppc_mr (code, ppc_r4, ppc_r3);
- // FIXME: Support the new v2 ABI!
}
break;
case SAVE_NONE:
bb->last_ins = last_ins;
}
-
-#ifdef MONO_ARCH_HAVE_DECOMPOSE_VTYPE_OPTS
-gboolean
-mono_arch_decompose_vtype_opts (MonoCompile *cfg, MonoInst *ins, MonoBasicBlock *bb)
-{
- MonoInst *dest_var=0, *src=0, *dest=0;
- gboolean is_all_floats = FALSE;
- gboolean is_returnable_via_regs = FALSE;
- int mbr_size = 0;
- int mbr_cnt = 0;
- int return_value_size = 0;
-
- switch (ins->opcode) {
- case OP_VMOVE: {
- MonoInst *src_var=0;
- // For now this code only handles small structures returned from functions. Everything else is handled by the "generic" code.
- MonoMethodSignature *sig = mono_method_signature (cfg->method);
- if (!MONO_TYPE_ISSTRUCT (sig->ret)) {
- return FALSE;
- }
-
- is_all_floats = is_float_struct_returnable_via_regs(ins->klass);
- is_returnable_via_regs = is_struct_returnable_via_regs(ins->klass, sig->pinvoke);
-
- if (!is_all_floats && !is_returnable_via_regs) {
- return FALSE;
- }
-
- DEBUG_ELFABIV2_printf("mono_arch_decompose_vtype_opts OP_VMOVE, ins->dreg: %d, ins->klass: ", (int)ins->dreg); DEBUG_ELFABIV2_mono_print_klass(ins->klass);
-
- src_var = get_vreg_to_inst (cfg, ins->sreg1);
- if (!src_var) {
- src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
- }
-
- dest_var = get_vreg_to_inst (cfg, ins->dreg);
- if (!dest_var) {
- dest_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
- }
- DEBUG_ELFABIV2_printf(" src_var: "); DEBUG_ELFABIV2_mono_print_ins(src_var);
- DEBUG_ELFABIV2_printf(" dest_var: "); DEBUG_ELFABIV2_mono_print_ins(dest_var);
- DEBUG_ELFABIV2_printf(" cfg->ret: "); if (is_all_floats) DEBUG_ELFABIV2_printf("all_floats ");DEBUG_ELFABIV2_mono_print_ins(cfg->ret);
- DEBUG_ELFABIV2_printf(" ins: "); DEBUG_ELFABIV2_mono_print_ins(ins);
- if (!src_var || !dest_var || (dest_var != cfg->ret)) {
- return FALSE;
- }
-
- g_assert (ins->klass);
- DEBUG_ELFABIV2_printf("Converting OP_VMOVE for returning value via registers\n");
-
- // FIXME:
- if (src_var->backend.is_pinvoke)
- dest_var->backend.is_pinvoke = 1;
-
- // return of structure via registers
- g_assert(src_var->klass);
- if (is_all_floats) {
- // Pass small (<= 8 member) structures entirely made up of either float or double members
- // in FR registers. There have to be at least 8 registers left.
- mbr_cnt = member_count(ins->klass);
- mbr_size = float_member_size(ins->klass);
- DEBUG_ELFABIV2_printf("is_float_struct_returnable_via_regs with length %d, %d members, member size %d\n", return_value_size, mbr_cnt, mbr_size);
- if (mbr_size == 4) {
- EMIT_NEW_VARLOADA ((cfg), (src), src_var, src_var->inst_vtype);
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, ins->dreg, src->dreg, 0);
- } else {
- EMIT_NEW_VARLOADA ((cfg), (src), src_var, src_var->inst_vtype);
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, ins->dreg, src->dreg, 0);
- } // else
- } else {
- // Not a homogenous float structure
- if (sig->pinvoke)
- return_value_size = mono_type_native_stack_size (sig->ret, 0);
- else
- return_value_size = mini_type_stack_size (NULL, sig->ret, 0);
- DEBUG_ELFABIV2_printf("is_struct_returnable_via_regs with length %d\n", return_value_size);
- g_assert(is_returnable_via_regs);
- EMIT_NEW_VARLOADA ((cfg), (src), src_var, src_var->inst_vtype);
- MONO_EMIT_NEW_LOAD_MEMBASE (cfg, ins->dreg, src->dreg, 0);
- } // else
- return TRUE;
- break;
- } // case OP_VMOVE
- case OP_VZERO: {
- int return_value_size = 0;
-
- // For now this code only handles small structures returned from functions. Everything else is handled by the "generic" code.
- MonoMethodSignature *sig = mono_method_signature (cfg->method);
- if (!MONO_TYPE_ISSTRUCT (sig->ret)) {
- return FALSE;
- }
- if (sig->pinvoke)
- return_value_size = mono_type_native_stack_size (sig->ret, 0);
- else
- return_value_size = mini_type_stack_size (NULL, sig->ret, 0);
- is_all_floats = is_float_struct_returnable_via_regs(ins->klass);
- is_returnable_via_regs = is_struct_returnable_via_regs(ins->klass, sig->pinvoke);
-
- if (!is_all_floats && !is_returnable_via_regs) {
- return FALSE;
- }
- if (is_all_floats) {
- mbr_cnt = member_count(ins->klass);
- mbr_size = float_member_size(ins->klass);
- }
- DEBUG_ELFABIV2_printf("mono_arch_decompose_vtype_opts OP_VZERO\n");
-
- dest_var = get_vreg_to_inst (cfg, ins->dreg);
- if (!dest_var) {
- dest_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
- DEBUG_ELFABIV2_printf("TMP creating dest_var\n");
- }
- if (!dest_var || (dest_var != cfg->ret)) {
- return FALSE;
- }
- DEBUG_ELFABIV2_printf("OP_VZERO of return value!\n");
- DEBUG_ELFABIV2_printf("ins "); DEBUG_ELFABIV2_mono_print_ins(ins);
- DEBUG_ELFABIV2_printf("cfg->ret "); DEBUG_ELFABIV2_mono_print_ins(cfg->ret);
- DEBUG_ELFABIV2_printf("dest_var "); DEBUG_ELFABIV2_mono_print_ins(dest_var);
- // The destination will become a REGVAR
- if (SIZEOF_REGISTER == 8)
- MONO_EMIT_NEW_I8CONST (cfg, dest_var->dreg, 0);
- else
- MONO_EMIT_NEW_ICONST (cfg, dest_var->dreg, 0);
- if (return_value_size == 16) {
- // FIXME: Potential problem here?
- if (SIZEOF_REGISTER == 8)
- MONO_EMIT_NEW_I8CONST (cfg, dest_var->dreg+1, 0);
- else
- MONO_EMIT_NEW_ICONST (cfg, dest_var->dreg+1, 0);
- } // if
-
- if (cfg->compute_gc_maps) {
- MonoInst *tmp;
-
- /*
- * Tell the GC map code that the vtype is considered live after
- * the initialization.
- */
- MONO_INST_NEW (cfg, tmp, OP_GC_LIVENESS_DEF);
- tmp->inst_c1 = ins->dreg;
- MONO_ADD_INS (cfg->cbb, tmp);
- }
- return TRUE;
- break;
- }
- case OP_LOADV_MEMBASE: {
- int return_value_size = 0;
- MonoInst *temp;
- int dreg;
-
- // For now this code only handles small structures returned from functions. Everything else is handled by the "generic" code.
- MonoMethodSignature *sig = mono_method_signature (cfg->method);
- if (!MONO_TYPE_ISSTRUCT (sig->ret)) {
- return FALSE;
- }
-
- dest_var = get_vreg_to_inst (cfg, ins->dreg);
- if (!dest_var) {
- dest_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
- }
- if (! dest_var || (dest_var != cfg->ret)) {
- return FALSE;
- }
- if (sig->pinvoke)
- return_value_size = mono_type_native_stack_size (sig->ret, 0);
- else
- return_value_size = mini_type_stack_size (NULL, sig->ret, 0);
- is_all_floats = is_float_struct_returnable_via_regs(ins->klass);
- is_returnable_via_regs = is_struct_returnable_via_regs(ins->klass, sig->pinvoke);
-
- if (!is_all_floats && !is_returnable_via_regs) {
- return FALSE;
- }
- DEBUG_ELFABIV2_printf("mono_arch_decompose_vtype_opts DS OP_LOADV_MEMBASE ins: "); DEBUG_ELFABIV2_mono_print_ins(ins);
-
- // Allocate a temp to hold the value we will be returning
- temp = mono_compile_create_var (cfg, &dest_var->klass->byval_arg, OP_LOCAL);
- dreg = alloc_preg (cfg);
- temp->backend.is_pinvoke = dest_var->backend.is_pinvoke;
- DEBUG_ELFABIV2_printf(" temp: "); DEBUG_ELFABIV2_mono_print_ins(temp);
- dest_var = get_vreg_to_inst (cfg, temp->dreg);
- if (!dest_var) {
- dest_var = mono_compile_create_var_for_vreg (cfg, &temp->klass->byval_arg, OP_LOCAL, temp->dreg);
- }
-
- // This is a very clumsy way of handling this. See if this can be done in a better way.
-
- // Store the value being returned in the temp
- EMIT_NEW_BIALU_IMM (cfg, src, OP_ADD_IMM, dreg, ins->inst_basereg, ins->inst_offset);
- EMIT_NEW_VARLOADA (cfg, dest, dest_var, dest_var->inst_vtype);
- mini_emit_stobj (cfg, dest, src, dest_var->klass, dest_var->backend.is_pinvoke);
-
- if (is_all_floats) {
- mbr_cnt = member_count(ins->klass);
- mbr_size = float_member_size(ins->klass);
- if (mbr_size == 4) {
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, ins->dreg, dest->dreg, 0);
- } else {
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, ins->dreg, dest->dreg, 0);
- }
- } else {
- // Load the temp for the return via register(s)
- MONO_EMIT_NEW_LOAD_MEMBASE (cfg, ins->dreg, dest->dreg, 0);
- } // else
- return TRUE;
- break;
- }
- case OP_VCALL:
- case OP_VCALL_REG:
- case OP_VCALL_MEMBASE: {
- MonoCallInst *call = (MonoCallInst*)ins;
- MonoCallInst *call2 = 0;
- int return_value_size = 0;
- DEBUG_ELFABIV2_printf("mono_arch_decompose_vtype_opts OP_VCALL vret_in_reg: %d, ins: ", call->vret_in_reg); DEBUG_ELFABIV2_mono_print_ins(ins);
- DEBUG_ELFABIV2_printf(" ins->klass: "); DEBUG_ELFABIV2_mono_print_klass(ins->klass);
-
- if (!call->vret_in_reg) {
- DEBUG_ELFABIV2_printf(" !call->vret_in_reg\n");
- return FALSE;
- }
-
- /* Compute the vtype location */
- dest_var = get_vreg_to_inst (cfg, call->inst.dreg);
- if (!dest_var)
- dest_var = mono_compile_create_var_for_vreg (cfg, call->signature->ret, OP_LOCAL, call->inst.dreg);
- if (!dest_var || (!MONO_TYPE_ISSTRUCT(dest_var->inst_vtype))) {
- DEBUG_ELFABIV2_printf(" !dest_var || (!MONO_TYPE_ISSTRUCT(dest_var->inst_vtype))\n");
- return FALSE;
- }
-
- if (dest_var->backend.is_pinvoke)
- return_value_size = mono_class_native_size (mono_class_from_mono_type (dest_var->inst_vtype), NULL);
- else
- return_value_size = mono_type_size (dest_var->inst_vtype, NULL);
- is_all_floats = is_float_struct_returnable_via_regs(dest_var->klass);
- is_returnable_via_regs = is_struct_returnable_via_regs(dest_var->klass, dest_var->backend.is_pinvoke);
-
- if (!is_all_floats && !is_returnable_via_regs) {
- DEBUG_ELFABIV2_printf(" (!is_all_floats && !is_returnable_via_regs)\n");
- return FALSE;
- }
-
- DEBUG_ELFABIV2_printf(" dest_var: "); DEBUG_ELFABIV2_mono_print_ins(dest_var);
- /* Replace the vcall with an integer call */
- MONO_INST_NEW_CALL (cfg, call2, OP_NOP);
- memcpy (call2, call, sizeof (MonoCallInst));
- switch (ins->opcode) {
- case OP_VCALL:
- call2->inst.opcode = OP_CALL;
- break;
- case OP_VCALL_REG:
- call2->inst.opcode = OP_CALL_REG;
- break;
- case OP_VCALL_MEMBASE:
- call2->inst.opcode = OP_CALL_MEMBASE;
- break;
- }
- // Note: mono_arch_allocate_vars in ppc-mini.c will set this to ppc_r3
- call2->inst.dreg = alloc_preg (cfg); //ppc_r3; //-1; //alloc_preg (cfg);
- MONO_ADD_INS (cfg->cbb, ((MonoInst*)call2));
-
- DEBUG_ELFABIV2_printf(" call: "); DEBUG_ELFABIV2_mono_print_ins((MonoInst*)call);
- DEBUG_ELFABIV2_printf(" call2: "); DEBUG_ELFABIV2_mono_print_ins((MonoInst*)call2);
- DEBUG_ELFABIV2_printf(" cfg->ret: "); DEBUG_ELFABIV2_mono_print_ins(cfg->ret);
- // If the dest_var of this call is the return var of this (the calling) function we do not need to store
- // the returned value because it will be returned via the same registers.
- if (dest_var == cfg->ret) {
- DEBUG_ELFABIV2_printf("returning function value directly (already in the right registers from call on return)\n");
- } else {
- if ((ins->next) && (ins->next->opcode == OP_DUMMY_USE)) {
- // If a call is followed by a DUMMY_USE it can cause ppc_r3 to be erroneously reloaded with an earlier saved value. Just remove the DUMMY_USE.
- // TBD: A better solution would be to not insert the DUMMY_USE but that might not be possible. The test case
- // appdomain1 demonstrates this problem.
- ins->next->opcode = OP_NOP;
- }
- EMIT_NEW_VARLOADA (cfg, dest, dest_var, dest_var->inst_vtype);
-
- g_assert(ins->klass);
- /* Save the result */
- if (is_all_floats) {
- // Small structures entirely made up of either float or double members
- // are returned in FR registers.
- int mbr_size = float_member_size(ins->klass);
- int mbr_cnt = member_count(ins->klass);
- int cnt;
- DEBUG_ELFABIV2_printf("storing function result, is_float_struct_returnable_via_regs(ins->klass) with length %d, %d members, member size %d\n", return_value_size, mbr_cnt, mbr_size);
-
- for (cnt=0; cnt < mbr_cnt; ++cnt) {
- if (mbr_size == 4) {
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, dest->dreg, cnt*mbr_size, ppc_f1+cnt);
- } else {
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, dest->dreg, cnt*mbr_size, ppc_f1+cnt);
- } // else
- } // for
- } else {
- MonoInst *dummy_use3=0;
- //MonoInst *dummy_use4=0;
- DEBUG_ELFABIV2_printf("storing function result, is_struct_returnable_via_regs(ins->klass) with length %d\n", return_value_size);
- DEBUG_ELFABIV2_printf(" ins->next: "); DEBUG_ELFABIV2_mono_print_ins(ins->next);
- g_assert(is_returnable_via_regs);
- // TBD: Improve the following code...
- // Emit a store (or stores) of the values that are in ppc_r3/ppc_r4. Also emit a DUMMY_USE to
- // prevent the register spilling code from overwriting ppc_r3.
- // TBD: See if this can happen for ppc_r4 as well.
- switch (return_value_size) {
- case 1:
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
- EMIT_NEW_DUMMY_USE (cfg, dummy_use3, &call2->inst);
- break;
- case 2:
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
- EMIT_NEW_DUMMY_USE (cfg, dummy_use3, &call2->inst);
- break;
- case 3:
- case 4:
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
- EMIT_NEW_DUMMY_USE (cfg, dummy_use3, &call2->inst);
- break;
- case 5:
- case 6:
- case 7:
- case 8:
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
- EMIT_NEW_DUMMY_USE (cfg, dummy_use3, &call2->inst);
- break;
- case 9: {
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, dest->dreg, 8, ppc_r4);
- EMIT_NEW_DUMMY_USE (cfg, dummy_use3, &call2->inst);
- // What about ppc_r4?
- break;
- }
- case 10: {
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, dest->dreg, 8, ppc_r4);
- EMIT_NEW_DUMMY_USE (cfg, dummy_use3, &call2->inst);
- // What about ppc_r4?
- break;
- }
- case 11:
- case 12: {
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 8, ppc_r4);
- EMIT_NEW_DUMMY_USE (cfg, dummy_use3, &call2->inst);
- // What about ppc_r4?
- break;
- }
- case 13:
- case 14:
- case 15:
- case 16: {
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, dest->dreg, 8, ppc_r4);
- EMIT_NEW_DUMMY_USE (cfg, dummy_use3, &call2->inst);
- // What about ppc_r4?
- break;
- }
- default:
- DEBUG_ELFABIV2_printf("Bad size? %d\n", return_value_size);
- g_assert_not_reached ();
- break;
- } // switch
- } // else
- } // if
- return TRUE;
- break;
- } // CALL case
- default:
- return FALSE;
- break;
- } // switch ins->opcode
- return TRUE;
-}
-#endif
-
-
void
mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
{
switch (ins->opcode) {
case OP_ICONV_TO_R_UN: {
- // This value is OK as-is for both big and little endian because of how it is stored
+#if G_BYTE_ORDER == G_BIG_ENDIAN
static const guint64 adjust_val = 0x4330000000000000ULL;
+#else
+ static const guint64 adjust_val = 0x0000000000003043ULL;
+#endif
int msw_reg = mono_alloc_ireg (cfg);
int adj_reg = mono_alloc_freg (cfg);
int tmp_reg = mono_alloc_freg (cfg);
basereg = mono_alloc_ireg (cfg);
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IADD_IMM, basereg, cfg->frame_reg, offset);
}
-#if G_BYTE_ORDER == G_BIG_ENDIAN
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, basereg, offset, msw_reg);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, basereg, offset + 4, ins->sreg1);
-#else
- // For little endian the words are reversed
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, basereg, offset + 4, msw_reg);
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, basereg, offset, ins->sreg1);
-#endif
MONO_EMIT_NEW_LOAD_R8 (cfg, adj_reg, &adjust_val);
MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, tmp_reg, basereg, offset);
MONO_EMIT_NEW_BIALU (cfg, OP_FSUB, ins->dreg, tmp_reg, adj_reg);
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IADD_IMM, basereg, cfg->frame_reg, offset);
}
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, basereg, offset, ins->sreg1);
-#if G_BYTE_ORDER == G_BIG_ENDIAN
MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, msw_reg, basereg, offset);
-#else
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, msw_reg, basereg, offset+4);
-#endif
MONO_EMIT_NEW_UNALU (cfg, OP_CHECK_FINITE, -1, msw_reg);
MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, ins->dreg, ins->sreg1);
ins->opcode = OP_NOP;
else
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, ins->dreg, result_shifted_reg, 32);
ins->opcode = OP_NOP;
- break;
}
#endif
- default:
- break;
}
}
ppc_ldptr_indexed (code, ins->dreg, ins->inst_basereg, ppc_r0);
}
}
- g_assert(ins->dreg > 0);
break;
case OP_LOADI4_MEMBASE:
#ifdef __mono_ppc64__
ppc_ldptr (code, ppc_r2, 8, ins->sreg1);
ppc_mtlr (code, ppc_r0);
#else
-#if (_CALL_ELF == 2)
- if (ins->flags & MONO_INST_HAS_METHOD) {
- // Not a global entry point
- } else {
- // Need to set up r12 with function entry address for global entry point
- if (ppc_r12 != ins->sreg1) {
- ppc_mr(code,ppc_r12,ins->sreg1);
- }
- }
-#endif
ppc_mtlr (code, ins->sreg1);
#endif
ppc_blrl (code);
cinfo = get_call_info (cfg->generic_sharing_context, sig);
if (MONO_TYPE_ISSTRUCT (sig->ret)) {
- // The return value for a structure may either be returned via address or via registers depending on its size
- MonoClass *klass = mono_class_from_mono_type (sig->ret);
- gboolean is_all_floats = is_float_struct_returnable_via_regs(klass);
- gboolean is_returnable_via_regs = is_struct_returnable_via_regs(klass, sig->pinvoke);
-
- DEBUG_ELFABIV2_printf("mono_arch_emit_prolog for struct "); DEBUG_ELFABIV2_mono_print_klass(klass);
- if (!is_all_floats && !is_returnable_via_regs) {
ArgInfo *ainfo = &cinfo->ret;
inst = cfg->vret_addr;
ppc_load (code, ppc_r12, inst->inst_offset);
ppc_stptr_indexed (code, ainfo->reg, ppc_r12, inst->inst_basereg);
}
-
- DEBUG_ELFABIV2_printf("mono_arch_emit_prolog extra parm for return value\n");
-
- } else {
- DEBUG_ELFABIV2_printf("mono_arch_emit_prolog NO extra parm for return value\n");
- }
}
tailcall_struct_index = 0;
ppc_stfs (code, ainfo->reg, inst->inst_offset, inst->inst_basereg);
else
g_assert_not_reached ();
- } else if (ainfo->regtype == RegTypeFPStructByVal) {
- int doffset = inst->inst_offset;
- int soffset = 0;
- int cur_reg;
- int size = 0;
- g_assert (ppc_is_imm16 (inst->inst_offset));
- g_assert (ppc_is_imm16 (inst->inst_offset + ainfo->vtregs * sizeof (gpointer)));
- /* FIXME: what if there is no class? */
- if (sig->pinvoke && mono_class_from_mono_type (inst->inst_vtype))
- size = mono_class_native_size (mono_class_from_mono_type (inst->inst_vtype), NULL);
- for (cur_reg = 0; cur_reg < ainfo->vtregs; ++cur_reg) {
- if (ainfo->size == 4) {
- ppc_stfs (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg);
- } else {
- ppc_stfd (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg);
- }
- soffset += ainfo->size;
- doffset += ainfo->size;
- }
} else if (ainfo->regtype == RegTypeStructByVal) {
int doffset = inst->inst_offset;
int soffset = 0;
#ifdef __mono_ppc64__
if (ainfo->bytes) {
g_assert (cur_reg == 0);
- if (mono_class_native_size (inst->klass, NULL) == 1) {
- ppc_stb (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg);
- } else if (mono_class_native_size (inst->klass, NULL) == 2) {
- ppc_sth (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg);
- } else if (mono_class_native_size (inst->klass, NULL) == 4) { // FIXME -- maybe <=4?
- ppc_stw (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg);
- } else {
- ppc_stptr (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg); // FIXME -- Better way?
- }
+ ppc_sldi (code, ppc_r0, ainfo->reg,
+ (sizeof (gpointer) - ainfo->bytes) * 8);
+ ppc_stptr (code, ppc_r0, doffset, inst->inst_basereg);
} else
#endif
{
ext->lmf.ebp = (gssize)ext;
}
-
-#if 0
-// FIXME: To get the test case finally_block_ending_in_dead_bb to work properly we need to define the following
-// (in mini-ppc.h) and then implement the fuction mono_arch_create_handler_block_trampoline.
-// #define MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD 1
-
-gpointer
-mono_arch_create_handler_block_trampoline (void)
-{
- . . .
-}
-#endif
-
-
#endif
gboolean