From d5d11a39a8f761c99276f20974de2f25928830c1 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 31 Jan 2012 03:19:23 +0100 Subject: [PATCH] PPC: E500: Implement msgsnd This patch implements the msgsnd instruction. It is part of the Embedded.Processor Control specification and allows one CPU to IPI another CPU without going through an interrupt controller. Signed-off-by: Alexander Graf --- target-ppc/helper.h | 1 + target-ppc/op_helper.c | 18 ++++++++++++++++++ target-ppc/translate.c | 16 ++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 48ceb61462..148543a8a1 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -358,6 +358,7 @@ DEF_HELPER_FLAGS_1(load_sr, TCG_CALL_CONST, tl, tl); DEF_HELPER_FLAGS_2(store_sr, TCG_CALL_CONST, void, tl, tl) DEF_HELPER_FLAGS_1(602_mfrom, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) +DEF_HELPER_1(msgsnd, void, tl) DEF_HELPER_1(msgclr, void, tl) #endif diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index e2f7614c27..3f4e06789f 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -4549,4 +4549,22 @@ void helper_msgclr(target_ulong rb) env->pending_interrupts &= ~(1 << irq); } +void helper_msgsnd(target_ulong rb) +{ + int irq = dbell2irq(rb); + int pir = rb & DBELL_PIRTAG_MASK; + CPUState *cenv; + + if (irq < 0) { + return; + } + + for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) { + if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) { + cenv->pending_interrupts |= 1 << irq; + cpu_interrupt(cenv, CPU_INTERRUPT_HARD); + } + } +} + #endif /* !CONFIG_USER_ONLY */ diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 01bfe0a1de..b2780dbe55 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -6236,6 +6236,20 @@ static void gen_msgclr(DisasContext *ctx) #endif } +static void gen_msgsnd(DisasContext *ctx) +{ +#if defined(CONFIG_USER_ONLY) + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); +#else + if (unlikely(ctx->mem_idx == 0)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); + return; + } + + gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]); +#endif +} + /*** Altivec vector extension ***/ /* Altivec registers moves */ @@ -8626,6 +8640,8 @@ GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001, PPC_NONE, PPC2_BOOKE206), GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001, PPC_NONE, PPC2_BOOKE206), +GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001, + PPC_NONE, PPC2_PRCNTL), GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001, PPC_NONE, PPC2_PRCNTL), GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),