/** pseudo instruction: load immediate: rt = imm */ void ppc_li(struct ppc_function *p, uint rt, int imm) { boolean print = p->print; p->print = FALSE; ppc_addi(p, rt, 0, imm); if (print) { indent(p); printf("addi\tr%u, r0, %d \t# r%u = %d\n", rt, imm, rt, imm); } p->print = print; }
/** * arch_get_throw_exception_generic: * * Returns a function pointer which can be used to raise * exceptions. The returned function has the following * signature: void (*func) (MonoException *exc); or * void (*func) (guint32 ex_token, gpointer ip) * */ static gpointer mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, int corlib, gboolean rethrow, gboolean aot) { guint8 *start, *code; int alloc_size, pos; MonoJumpInfo *ji = NULL; GSList *unwind_ops = NULL; code = start = mono_global_codeman_reserve (size); if (!aot) code = mono_ppc_create_pre_code_ftnptr (code); /* store ret addr */ if (corlib) ppc_mr (code, ppc_r0, ppc_r4); else ppc_mflr (code, ppc_r0); ppc_stptr (code, ppc_r0, PPC_RET_ADDR_OFFSET, ppc_sp); alloc_size = REG_SAVE_STACK_FRAME_SIZE; g_assert ((alloc_size & (MONO_ARCH_FRAME_ALIGNMENT-1)) == 0); ppc_stptr_update (code, ppc_sp, -alloc_size, ppc_sp); code = emit_save_saved_regs (code, alloc_size); //ppc_break (code); if (corlib) { ppc_mr (code, ppc_r4, ppc_r3); if (aot) { code = mono_arch_emit_load_aotconst (start, code, &ji, MONO_PATCH_INFO_IMAGE, mono_defaults.corlib); ppc_mr (code, ppc_r3, ppc_r12); code = mono_arch_emit_load_aotconst (start, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_exception_from_token"); #ifdef PPC_USES_FUNCTION_DESCRIPTOR ppc_ldptr (code, ppc_r2, sizeof (gpointer), ppc_r12); ppc_ldptr (code, ppc_r12, 0, ppc_r12); #endif ppc_mtctr (code, ppc_r12); ppc_bcctrl (code, PPC_BR_ALWAYS, 0); } else { ppc_load (code, ppc_r3, (gulong)mono_defaults.corlib); ppc_load_func (code, PPC_CALL_REG, mono_exception_from_token); ppc_mtctr (code, PPC_CALL_REG); ppc_bcctrl (code, PPC_BR_ALWAYS, 0); } } /* call throw_exception (exc, ip, sp, int_regs, fp_regs) */ /* caller sp */ ppc_ldptr (code, ppc_r5, 0, ppc_sp); /* exc is already in place in r3 */ if (corlib) ppc_ldptr (code, ppc_r4, PPC_RET_ADDR_OFFSET, ppc_r5); else ppc_mr (code, ppc_r4, ppc_r0); /* caller ip */ /* pointer to the saved fp regs */ pos = alloc_size - sizeof (gdouble) * MONO_MAX_FREGS; ppc_addi (code, ppc_r7, ppc_sp, pos); /* pointer to the saved int regs */ pos -= sizeof (gpointer) * MONO_MAX_IREGS; ppc_addi (code, ppc_r6, ppc_sp, pos); ppc_li (code, ppc_r8, rethrow); if (aot) { // This can be called from runtime code, which can't guarantee that // r30 contains the got address. // So emit the got address loading code too code = mono_arch_emit_load_got_addr (start, code, NULL, &ji); code = mono_arch_emit_load_aotconst (start, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_ppc_throw_exception"); #ifdef PPC_USES_FUNCTION_DESCRIPTOR ppc_ldptr (code, ppc_r2, sizeof (gpointer), ppc_r12); ppc_ldptr (code, ppc_r12, 0, ppc_r12); #endif ppc_mtctr (code, ppc_r12); ppc_bcctrl (code, PPC_BR_ALWAYS, 0); } else { ppc_load_func (code, PPC_CALL_REG, mono_ppc_throw_exception); ppc_mtctr (code, PPC_CALL_REG); ppc_bcctrl (code, PPC_BR_ALWAYS, 0); } /* we should never reach this breakpoint */ ppc_break (code); g_assert ((code - start) <= size); mono_arch_flush_icache (start, code - start); MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL)); if (info) *info = mono_tramp_info_create (corlib ? "throw_corlib_exception" : (rethrow ? "rethrow_exception" : "throw_exception"), start, code - start, ji, unwind_ops); return start; }