aboutsummaryrefslogtreecommitdiff
path: root/target-ppc
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2012-01-31 03:19:23 +0100
committerAlexander Graf <agraf@suse.de>2012-02-02 02:47:47 +0100
commitd5d11a39a8f761c99276f20974de2f25928830c1 (patch)
treef506222b8885da4ee448e477ce42240c6a1833c1 /target-ppc
parent9e0b5cb1ecf5543864fad0628a17be23bb617ed7 (diff)
downloadqemu-d5d11a39a8f761c99276f20974de2f25928830c1.zip
qemu-d5d11a39a8f761c99276f20974de2f25928830c1.tar.gz
qemu-d5d11a39a8f761c99276f20974de2f25928830c1.tar.bz2
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 <agraf@suse.de>
Diffstat (limited to 'target-ppc')
-rw-r--r--target-ppc/helper.h1
-rw-r--r--target-ppc/op_helper.c18
-rw-r--r--target-ppc/translate.c16
3 files changed, 35 insertions, 0 deletions
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 48ceb61..148543a 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 e2f7614..3f4e067 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 01bfe0a..b2780db 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),