qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Leon Alrae <leon.alrae@imgtec.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 27/29] target-mips: add MTHC0 and MFHC0 instructions
Date: Fri, 12 Jun 2015 10:35:34 +0100	[thread overview]
Message-ID: <1434101736-11558-28-git-send-email-leon.alrae@imgtec.com> (raw)
In-Reply-To: <1434101736-11558-1-git-send-email-leon.alrae@imgtec.com>

Implement MTHC0 and MFHC0 instructions. In MIPS32 they are used to access
upper word of extended to 64-bits CP0 registers.

In MIPS64, when CP0 destination register specified is the EntryLo0 or
EntryLo1, bits 1:0 of the GPR appear at bits 31:30 of EntryLo0 or
EntryLo1. This is to compensate for RI and XI, which were shifted to bits
63:62 by MTC0 to EntryLo0 or EntryLo1. Therefore creating separate
functions for EntryLo0 and EntryLo1.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
---
 disas/mips.c            |   2 +
 target-mips/cpu.h       |   1 +
 target-mips/translate.c | 226 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 229 insertions(+)

diff --git a/disas/mips.c b/disas/mips.c
index 832468c..32940fe 100644
--- a/disas/mips.c
+++ b/disas/mips.c
@@ -2238,6 +2238,8 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"ceil.l.s", "D,S",	0x4600000a, 0xffff003f, WR_D|RD_S|FP_S|FP_D,	0,		I3|I33	},
 {"ceil.w.d", "D,S",	0x4620000e, 0xffff003f, WR_D|RD_S|FP_S|FP_D,	0,		I2	},
 {"ceil.w.s", "D,S",	0x4600000e, 0xffff003f, WR_D|RD_S|FP_S,		0,		I2	},
+{"mfhc0",   "t,G,H",    0x40400000, 0xffe007f8, LCD|WR_t|RD_C0,       0, I33},
+{"mthc0",   "t,G,H",    0x40c00000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC, 0, I33},
 {"cfc0",    "t,G",	0x40400000, 0xffe007ff,	LCD|WR_t|RD_C0,		0,		I1	},
 {"cfc1",    "t,G",	0x44400000, 0xffe007ff,	LCD|WR_t|RD_C1|FP_S,	0,		I1	},
 {"cfc1",    "t,S",	0x44400000, 0xffe007ff,	LCD|WR_t|RD_C1|FP_S,	0,		I1	},
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index c266e9f..474a0e3 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -473,6 +473,7 @@ struct CPUMIPSState {
 #define CP0C5_UFE        9
 #define CP0C5_FRE        8
 #define CP0C5_SBRI       6
+#define CP0C5_MVH        5
 #define CP0C5_LLB        4
 #define CP0C5_UFR        2
 #define CP0C5_NFExists   0
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 6a39ef0..1d128ee 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -868,8 +868,10 @@ enum {
 enum {
     OPC_MFC0     = (0x00 << 21) | OPC_CP0,
     OPC_DMFC0    = (0x01 << 21) | OPC_CP0,
+    OPC_MFHC0    = (0x02 << 21) | OPC_CP0,
     OPC_MTC0     = (0x04 << 21) | OPC_CP0,
     OPC_DMTC0    = (0x05 << 21) | OPC_CP0,
+    OPC_MTHC0    = (0x06 << 21) | OPC_CP0,
     OPC_MFTR     = (0x08 << 21) | OPC_CP0,
     OPC_RDPGPR   = (0x0A << 21) | OPC_CP0,
     OPC_MFMC0    = (0x0B << 21) | OPC_CP0,
@@ -1424,6 +1426,9 @@ typedef struct DisasContext {
     int ie;
     bool bi;
     bool bp;
+    uint64_t PAMask;
+    bool mvh;
+    int CP0_LLAddr_shift;
 } DisasContext;
 
 enum {
@@ -1821,6 +1826,15 @@ static inline void check_mips_64(DisasContext *ctx)
 }
 #endif
 
+#ifndef CONFIG_USER_ONLY
+static inline void check_mvh(DisasContext *ctx)
+{
+    if (unlikely(!ctx->mvh)) {
+        generate_exception(ctx, EXCP_RI);
+    }
+}
+#endif
+
 /* Define small wrappers for gen_load_fpr* so that we have a uniform
    calling interface for 32 and 64-bit FPRs.  No sense in changing
    all callers for gen_load_fpr32 when we need the CTX parameter for
@@ -4842,6 +4856,60 @@ static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
 #endif
 }
 
+static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
+{
+    TCGv_i64 t0 = tcg_temp_new_i64();
+    TCGv_i64 t1 = tcg_temp_new_i64();
+
+    tcg_gen_ext_tl_i64(t0, arg);
+    tcg_gen_ld_i64(t1, cpu_env, off);
+#if defined(TARGET_MIPS64)
+    tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
+#else
+    tcg_gen_concat32_i64(t1, t1, t0);
+#endif
+    tcg_gen_st_i64(t1, cpu_env, off);
+    tcg_temp_free_i64(t1);
+    tcg_temp_free_i64(t0);
+}
+
+static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
+{
+    TCGv_i64 t0 = tcg_temp_new_i64();
+    TCGv_i64 t1 = tcg_temp_new_i64();
+
+    tcg_gen_ext_tl_i64(t0, arg);
+    tcg_gen_ld_i64(t1, cpu_env, off);
+    tcg_gen_concat32_i64(t1, t1, t0);
+    tcg_gen_st_i64(t1, cpu_env, off);
+    tcg_temp_free_i64(t1);
+    tcg_temp_free_i64(t0);
+}
+
+static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
+{
+    TCGv_i64 t0 = tcg_temp_new_i64();
+
+    tcg_gen_ld_i64(t0, cpu_env, off);
+#if defined(TARGET_MIPS64)
+    tcg_gen_shri_i64(t0, t0, 30);
+#else
+    tcg_gen_shri_i64(t0, t0, 32);
+#endif
+    gen_move_low32(arg, t0);
+    tcg_temp_free_i64(t0);
+}
+
+static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
+{
+    TCGv_i64 t0 = tcg_temp_new_i64();
+
+    tcg_gen_ld_i64(t0, cpu_env, off);
+    tcg_gen_shri_i64(t0, t0, 32 + shift);
+    gen_move_low32(arg, t0);
+    tcg_temp_free_i64(t0);
+}
+
 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
 {
     TCGv_i32 t0 = tcg_temp_new_i32();
@@ -4872,6 +4940,140 @@ static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
     tcg_gen_st_tl(arg, cpu_env, off);
 }
 
+static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
+{
+    const char *rn = "invalid";
+
+    if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
+        goto mfhc0_read_zero;
+    }
+
+    switch (reg) {
+    case 2:
+        switch (sel) {
+        case 0:
+            gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
+            rn = "EntryLo0";
+            break;
+        default:
+            goto mfhc0_read_zero;
+        }
+        break;
+    case 3:
+        switch (sel) {
+        case 0:
+            gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
+            rn = "EntryLo1";
+            break;
+        default:
+            goto mfhc0_read_zero;
+        }
+        break;
+    case 17:
+        switch (sel) {
+        case 0:
+            gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
+                             ctx->CP0_LLAddr_shift);
+            rn = "LLAddr";
+            break;
+        default:
+            goto mfhc0_read_zero;
+        }
+        break;
+    case 28:
+        switch (sel) {
+        case 0:
+        case 2:
+        case 4:
+        case 6:
+            gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
+            rn = "TagLo";
+            break;
+        default:
+            goto mfhc0_read_zero;
+        }
+        break;
+    default:
+        goto mfhc0_read_zero;
+    }
+
+    (void)rn; /* avoid a compiler warning */
+    LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
+    return;
+
+mfhc0_read_zero:
+    LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
+    tcg_gen_movi_tl(arg, 0);
+}
+
+static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
+{
+    const char *rn = "invalid";
+    uint64_t mask = ctx->PAMask >> 36;
+
+    if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
+        goto mthc0_nop;
+    }
+
+    switch (reg) {
+    case 2:
+        switch (sel) {
+        case 0:
+            tcg_gen_andi_tl(arg, arg, mask);
+            gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
+            rn = "EntryLo0";
+            break;
+        default:
+            goto mthc0_nop;
+        }
+        break;
+    case 3:
+        switch (sel) {
+        case 0:
+            tcg_gen_andi_tl(arg, arg, mask);
+            gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
+            rn = "EntryLo1";
+            break;
+        default:
+            goto mthc0_nop;
+        }
+        break;
+    case 17:
+        switch (sel) {
+        case 0:
+            /* LLAddr is read-only (the only exception is bit 0 if LLB is
+               supported); the CP0_LLAddr_rw_bitmask does not seem to be
+               relevant for modern MIPS cores supporting MTHC0, therefore
+               treating MTHC0 to LLAddr as NOP. */
+            rn = "LLAddr";
+            break;
+        default:
+            goto mthc0_nop;
+        }
+        break;
+    case 28:
+        switch (sel) {
+        case 0:
+        case 2:
+        case 4:
+        case 6:
+            tcg_gen_andi_tl(arg, arg, mask);
+            gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
+            rn = "TagLo";
+            break;
+        default:
+            goto mthc0_nop;
+        }
+        break;
+    default:
+        goto mthc0_nop;
+    }
+
+    (void)rn; /* avoid a compiler warning */
+mthc0_nop:
+    LOG_DISAS("mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
+}
+
 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
 {
     if (ctx->insn_flags & ISA_MIPS32R6) {
@@ -7880,6 +8082,25 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
         opn = "dmtc0";
         break;
 #endif
+    case OPC_MFHC0:
+        check_mvh(ctx);
+        if (rt == 0) {
+            /* Treat as NOP. */
+            return;
+        }
+        gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
+        opn = "mfhc0";
+        break;
+    case OPC_MTHC0:
+        check_mvh(ctx);
+        {
+            TCGv t0 = tcg_temp_new();
+            gen_load_gpr(t0, rt);
+            gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
+            tcg_temp_free(t0);
+        }
+        opn = "mthc0";
+        break;
     case OPC_MFTR:
         check_insn(ctx, ASE_MT);
         if (rd == 0) {
@@ -18621,6 +18842,8 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
         case OPC_MTC0:
         case OPC_MFTR:
         case OPC_MTTR:
+        case OPC_MFHC0:
+        case OPC_MTHC0:
 #if defined(TARGET_MIPS64)
         case OPC_DMFC0:
         case OPC_DMTC0:
@@ -19191,6 +19414,9 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
     ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
     ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
     ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
+    ctx.PAMask = env->PAMask;
+    ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
+    ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift;
     /* Restore delay slot state from the tb context.  */
     ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
     ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
-- 
2.1.0

  parent reply	other threads:[~2015-06-12  9:37 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-12  9:35 [Qemu-devel] [PULL 00/29] target-mips queue Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 01/29] target-mips: move group of functions above gen_load_fpr32() Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 02/29] target-mips: add Config5.FRE support allowing Status.FR=0 emulation Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 03/29] mips_malta: provide ememsize env variable to kernels Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 04/29] target-mips: Misaligned memory accesses for R6 Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 05/29] softmmu: Add probe_write() Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 06/29] target-mips: Misaligned memory accesses for MSA Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 07/29] target-mips: add ERETNC instruction and Config5.LLB bit Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 08/29] mips jazz: compile only in 64 bit Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 09/29] dma/rc4030: create custom DMA address space Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 10/29] dma/rc4030: use AddressSpace and address_space_rw in users Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 11/29] dma/rc4030: do not use old_mmio accesses Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 12/29] dma/rc4030: document register at offset 0x210 Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 13/29] dma/rc4030: use trace events instead of custom logging Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 14/29] dma/rc4030: convert to QOM Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 15/29] net/dp8393x: always calculate proper checksums Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 16/29] net/dp8393x: do not use old_mmio accesses Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 17/29] net/dp8393x: use dp8393x_ prefix for all functions Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 18/29] net/dp8393x: QOM'ify Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 19/29] net/dp8393x: add PROM to store MAC address Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 20/29] net/dp8393x: add load/save support Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 21/29] net/dp8393x: correctly reset in_use field Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 22/29] net/dp8393x: fix hardware reset Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 23/29] target-mips: correct MFC0 for CP0.EntryLo in MIPS64 Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 24/29] target-mips: extend selected CP0 registers to 64-bits in MIPS32 Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 25/29] target-mips: support Page Frame Number Extension field Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 26/29] target-mips: add CP0.PageGrain.ELPA support Leon Alrae
2015-06-12  9:35 ` Leon Alrae [this message]
2015-06-12  9:35 ` [Qemu-devel] [PULL 28/29] target-mips: remove misleading comments in translate_init.c Leon Alrae
2015-06-12  9:35 ` [Qemu-devel] [PULL 29/29] target-mips: enable XPA and LPA features Leon Alrae
2015-06-12 13:30 ` [Qemu-devel] [PULL 00/29] target-mips queue Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1434101736-11558-28-git-send-email-leon.alrae@imgtec.com \
    --to=leon.alrae@imgtec.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).