summaryrefslogtreecommitdiff
path: root/target-ppc/translate.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-ppc/translate.c')
-rw-r--r--target-ppc/translate.c142
1 files changed, 140 insertions, 2 deletions
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 198fbf6815..7d382d6cab 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -1584,6 +1584,14 @@ GEN_FLOAT_B(ctiw, 0x0E, 0x00);
GEN_FLOAT_B(ctiwz, 0x0F, 0x00);
/* frsp */
GEN_FLOAT_B(rsp, 0x0C, 0x00);
+#if defined(TARGET_PPC64)
+/* fcfid */
+GEN_FLOAT_B(cfid, 0x0E, 0x1A);
+/* fctid */
+GEN_FLOAT_B(ctid, 0x0E, 0x19);
+/* fctidz */
+GEN_FLOAT_B(ctidz, 0x0F, 0x19);
+#endif
/*** Floating-Point compare ***/
/* fcmpo */
@@ -1996,8 +2004,8 @@ GEN_STS(h, 0x0C, PPC_INTEGER);
GEN_STS(w, 0x04, PPC_INTEGER);
#if defined(TARGET_PPC64)
OP_ST_TABLE(d);
-GEN_STUX(d, 0x15, 0x01, PPC_64B);
-GEN_STX(d, 0x15, 0x00, PPC_64B);
+GEN_STUX(d, 0x15, 0x05, PPC_64B);
+GEN_STX(d, 0x15, 0x04, PPC_64B);
GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000002, PPC_64B)
{
if (Rc(ctx->opcode)) {
@@ -2358,6 +2366,62 @@ GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
op_stwcx();
}
+#if defined(TARGET_PPC64)
+#define op_ldarx() (*gen_op_ldarx[ctx->mem_idx])()
+#define op_stdcx() (*gen_op_stdcx[ctx->mem_idx])()
+#if defined(CONFIG_USER_ONLY)
+static GenOpFunc *gen_op_ldarx[] = {
+ &gen_op_ldarx_raw,
+ &gen_op_ldarx_le_raw,
+ &gen_op_ldarx_64_raw,
+ &gen_op_ldarx_le_64_raw,
+};
+static GenOpFunc *gen_op_stdcx[] = {
+ &gen_op_stdcx_raw,
+ &gen_op_stdcx_le_raw,
+ &gen_op_stdcx_64_raw,
+ &gen_op_stdcx_le_64_raw,
+};
+#else
+static GenOpFunc *gen_op_ldarx[] = {
+ &gen_op_ldarx_user,
+ &gen_op_ldarx_le_user,
+ &gen_op_ldarx_kernel,
+ &gen_op_ldarx_le_kernel,
+ &gen_op_ldarx_64_user,
+ &gen_op_ldarx_le_64_user,
+ &gen_op_ldarx_64_kernel,
+ &gen_op_ldarx_le_64_kernel,
+};
+static GenOpFunc *gen_op_stdcx[] = {
+ &gen_op_stdcx_user,
+ &gen_op_stdcx_le_user,
+ &gen_op_stdcx_kernel,
+ &gen_op_stdcx_le_kernel,
+ &gen_op_stdcx_64_user,
+ &gen_op_stdcx_le_64_user,
+ &gen_op_stdcx_64_kernel,
+ &gen_op_stdcx_le_64_kernel,
+};
+#endif
+
+/* ldarx */
+GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_RES)
+{
+ gen_addr_reg_index(ctx);
+ op_ldarx();
+ gen_op_store_T1_gpr(rD(ctx->opcode));
+}
+
+/* stdcx. */
+GEN_HANDLER(stdcx_, 0x1F, 0x16, 0x06, 0x00000000, PPC_RES)
+{
+ gen_addr_reg_index(ctx);
+ gen_op_load_gpr_T1(rS(ctx->opcode));
+ op_stdcx();
+}
+#endif /* defined(TARGET_PPC64) */
+
/* sync */
GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM_SYNC)
{
@@ -2807,6 +2871,26 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
#endif
}
+#if defined(TARGET_PPC64)
+GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_FLOW)
+{
+#if defined(CONFIG_USER_ONLY)
+ RET_PRIVOPC(ctx);
+#else
+ /* Restore CPU state */
+ if (unlikely(!ctx->supervisor)) {
+ RET_PRIVOPC(ctx);
+ return;
+ }
+ if (!ctx->sf_mode)
+ gen_op_rfid_32();
+ else
+ gen_op_rfid();
+ RET_CHG_FLOW(ctx);
+#endif
+}
+#endif
+
/* sc */
GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW)
{
@@ -2978,6 +3062,25 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
}
/* mtmsr */
+#if defined(TARGET_PPC64)
+GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001FF801, PPC_MISC)
+{
+#if defined(CONFIG_USER_ONLY)
+ RET_PRIVREG(ctx);
+#else
+ if (unlikely(!ctx->supervisor)) {
+ RET_PRIVREG(ctx);
+ return;
+ }
+ gen_update_nip(ctx, ctx->nip);
+ gen_op_load_gpr_T0(rS(ctx->opcode));
+ gen_op_store_msr();
+ /* Must stop the translation as machine state (may have) changed */
+ RET_CHG_FLOW(ctx);
+#endif
+}
+#endif
+
GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
{
#if defined(CONFIG_USER_ONLY)
@@ -3313,6 +3416,41 @@ GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
#endif
}
+#if defined(TARGET_PPC64)
+/* slbia */
+GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
+{
+#if defined(CONFIG_USER_ONLY)
+ RET_PRIVOPC(ctx);
+#else
+ if (unlikely(!ctx->supervisor)) {
+ if (loglevel)
+ fprintf(logfile, "%s: ! supervisor\n", __func__);
+ RET_PRIVOPC(ctx);
+ return;
+ }
+ gen_op_slbia();
+ RET_STOP(ctx);
+#endif
+}
+
+/* slbie */
+GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
+{
+#if defined(CONFIG_USER_ONLY)
+ RET_PRIVOPC(ctx);
+#else
+ if (unlikely(!ctx->supervisor)) {
+ RET_PRIVOPC(ctx);
+ return;
+ }
+ gen_op_load_gpr_T0(rB(ctx->opcode));
+ gen_op_slbie();
+ RET_STOP(ctx);
+#endif
+}
+#endif
+
/*** External control ***/
/* Optional: */
#define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()