-/*
- * emit_load_volatile_arguments:
- *
- * Load volatile arguments from the stack to the original input registers.
- * Required before a tail call.
- */
-static guint8*
-emit_load_volatile_arguments (MonoCompile *cfg, guint8 *code)
-{
- MonoMethod *method = cfg->method;
- MonoMethodSignature *sig;
- MonoInst *inst;
- CallInfo *cinfo;
- guint32 i, pos;
- int struct_index = 0;
-
- sig = mono_method_signature (method);
-
- /* This is the opposite of the code in emit_prolog */
-
- pos = 0;
-
- cinfo = calculate_sizes (sig, sig->pinvoke);
-
- if (MONO_TYPE_ISSTRUCT (sig->ret)) {
- ArgInfo *ainfo = &cinfo->ret;
- inst = cfg->vret_addr;
- g_assert (ppc_is_imm16 (inst->inst_offset));
- ppc_ldptr (code, ainfo->reg, inst->inst_offset, inst->inst_basereg);
- }
- for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
- ArgInfo *ainfo = cinfo->args + i;
- inst = cfg->args [pos];
-
- g_assert (inst->opcode != OP_REGVAR);
- g_assert (ppc_is_imm16 (inst->inst_offset));
-
- switch (ainfo->regtype) {
- case RegTypeGeneral:
- switch (ainfo->size) {
- case 1:
- ppc_lbz (code, ainfo->reg, inst->inst_offset, inst->inst_basereg);
- break;
- case 2:
- ppc_lhz (code, ainfo->reg, inst->inst_offset, inst->inst_basereg);
- break;
-#ifdef __mono_ppc64__
- case 4:
- ppc_lwz (code, ainfo->reg, inst->inst_offset, inst->inst_basereg);
- break;
-#endif
- default:
- ppc_ldptr (code, ainfo->reg, inst->inst_offset, inst->inst_basereg);
- break;
- }
- break;
-
- case RegTypeFP:
- switch (ainfo->size) {
- case 4:
- ppc_lfs (code, ainfo->reg, inst->inst_offset, inst->inst_basereg);
- break;
- case 8:
- ppc_lfd (code, ainfo->reg, inst->inst_offset, inst->inst_basereg);
- break;
- default:
- g_assert_not_reached ();
- }
- break;
-
- case RegTypeBase: {
- MonoType *type = mini_type_get_underlying_type (cfg->generic_sharing_context,
- &inst->klass->byval_arg);
-
-#ifndef __mono_ppc64__
- if (type->type == MONO_TYPE_I8)
- NOT_IMPLEMENTED;
-#endif
-
- if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_I8) {
- ppc_ldptr (code, ppc_r0, inst->inst_offset, inst->inst_basereg);
- ppc_stptr (code, ppc_r0, ainfo->offset, ainfo->reg);
- } else if (type->type == MONO_TYPE_I4) {
- ppc_lwz (code, ppc_r0, inst->inst_offset, inst->inst_basereg);
- ppc_stw (code, ppc_r0, ainfo->offset, ainfo->reg);
- } else {
- NOT_IMPLEMENTED;
- }
-
- break;
- }
-
- case RegTypeStructByVal: {
-#ifdef __APPLE__
- guint32 size = 0;
-#endif
- int j;
-
- /* FIXME: */
- if (ainfo->vtsize)
- NOT_IMPLEMENTED;
-#ifdef __APPLE__
- /*
- * Darwin pinvokes needs some special handling
- * for 1 and 2 byte arguments
- */
- if (method->signature->pinvoke)
- size = mono_class_native_size (inst->klass, NULL);
- if (size == 1 || size == 2) {
- /* FIXME: */
- NOT_IMPLEMENTED;
- } else
-#endif
- for (j = 0; j < ainfo->vtregs; ++j) {
- ppc_ldptr (code, ainfo->reg + j,
- inst->inst_offset + j * sizeof (gpointer),
- inst->inst_basereg);
- /* FIXME: shift to the right */
- if (ainfo->bytes)
- NOT_IMPLEMENTED;
- }
- break;
- }
-
- case RegTypeStructByAddr: {
- MonoInst *addr = cfg->tailcall_valuetype_addrs [struct_index];
-
- g_assert (ppc_is_imm16 (addr->inst_offset));
- g_assert (!ainfo->offset);
- ppc_ldptr (code, ainfo->reg, addr->inst_offset, addr->inst_basereg);
-
- struct_index++;
- break;
- }
-
- default:
- g_assert_not_reached ();
- }
-
- pos ++;
- }
-
- g_free (cinfo);
-
- return code;
-}
-
-/* This must be kept in sync with emit_load_volatile_arguments(). */