qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 2/2] target-mips: implement UserLocal Register


From: Petar Jovanovic
Subject: [Qemu-devel] [PATCH 2/2] target-mips: implement UserLocal Register
Date: Fri, 16 May 2014 20:13:34 +0200

From: Petar Jovanovic <address@hidden>

>From MIPS documentation (Volume III):

UserLocal Register (CP0 Register 4, Select 2)
Compliance Level: Recommended.

The UserLocal register is a read-write register that is not interpreted by
the hardware and conditionally readable via the RDHWR instruction.

This register only exists if the Config3-ULRI register field is set.

Privileged software may write this register with arbitrary information and
make it accessable to unprivileged software via register 29 (ULR) of the
RDHWR instruction. To do so, bit 29 of the HWREna register must be set to a
1 to enable unprivileged access to the register.

Signed-off-by: Petar Jovanovic <address@hidden>
---
 target-mips/cpu.h       |    2 ++
 target-mips/helper.h    |    1 +
 target-mips/op_helper.c |   20 +++++++++++++++++++-
 target-mips/translate.c |   43 +++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 6c2014e..bb18fb8 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -227,6 +227,7 @@ struct CPUMIPSState {
     target_ulong CP0_EntryLo0;
     target_ulong CP0_EntryLo1;
     target_ulong CP0_Context;
+    target_ulong CP0_UserLocal;
     int32_t CP0_PageMask;
     int32_t CP0_PageGrain;
     int32_t CP0_Wired;
@@ -361,6 +362,7 @@ struct CPUMIPSState {
     int32_t CP0_Config3;
 #define CP0C3_M    31
 #define CP0C3_ISA_ON_EXC 16
+#define CP0C3_ULRI 13
 #define CP0C3_DSPP 10
 #define CP0C3_LPA  7
 #define CP0C3_VEIC 6
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 8c7921a..ec56199 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -296,6 +296,7 @@ DEF_HELPER_1(rdhwr_cpunum, tl, env)
 DEF_HELPER_1(rdhwr_synci_step, tl, env)
 DEF_HELPER_1(rdhwr_cc, tl, env)
 DEF_HELPER_1(rdhwr_ccres, tl, env)
+DEF_HELPER_1(rdhwr_ul, tl, env)
 DEF_HELPER_2(pmon, void, env, int)
 DEF_HELPER_1(wait, void, env)
 
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 4edec6c..72c0a25 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1301,7 +1301,13 @@ void helper_mtc0_srsconf4(CPUMIPSState *env, 
target_ulong arg1)
 
 void helper_mtc0_hwrena(CPUMIPSState *env, target_ulong arg1)
 {
-    env->CP0_HWREna = arg1 & 0x0000000F;
+    uint32_t mask = 0x0000000F;
+
+    if (env->CP0_Config3 & (1 << CP0C3_ULRI)) {
+        mask |= 0x20000000;
+    }
+
+    env->CP0_HWREna = arg1 & mask;
 }
 
 void helper_mtc0_count(CPUMIPSState *env, target_ulong arg1)
@@ -2091,6 +2097,18 @@ target_ulong helper_rdhwr_ccres(CPUMIPSState *env)
     return 0;
 }
 
+target_ulong helper_rdhwr_ul(CPUMIPSState *env)
+{
+    if ((env->hflags & MIPS_HFLAG_CP0) ||
+        (env->CP0_HWREna & (1 << 29))) {
+        return env->CP0_UserLocal;
+    } else {
+        helper_raise_exception(env, EXCP_RI);
+    }
+
+    return 0;
+}
+
 void helper_pmon(CPUMIPSState *env, int function)
 {
     function /= 2;
diff --git a/target-mips/translate.c b/target-mips/translate.c
index d629b73..792da07 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -4216,7 +4216,17 @@ static void gen_mfc0(CPUMIPSState *env, DisasContext 
*ctx,
         case 1:
 //            gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
             rn = "ContextConfig";
+            goto die;
 //            break;
+        case 2:
+            if (env->CP0_Config3 & (1 << CP0C3_ULRI)) {
+                tcg_gen_ld_tl(arg, cpu_env,
+                              offsetof(CPUMIPSState, CP0_UserLocal));
+                tcg_gen_ext32s_tl(arg, arg);
+                rn = "UserLocal";
+            } else {
+                tcg_gen_movi_tl(arg, 0);
+            }
         default:
             goto die;
         }
@@ -4804,7 +4814,15 @@ static void gen_mtc0(CPUMIPSState *env, DisasContext 
*ctx,
         case 1:
 //            gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
             rn = "ContextConfig";
+            goto die;
 //            break;
+        case 2:
+            if (env->CP0_Config3 & (1 << CP0C3_ULRI)) {
+                tcg_gen_st_tl(arg, cpu_env,
+                              offsetof(CPUMIPSState, CP0_UserLocal));
+                rn = "UserLocal";
+            }
+            break;
         default:
             goto die;
         }
@@ -5409,7 +5427,17 @@ static void gen_dmfc0(CPUMIPSState *env, DisasContext 
*ctx,
         case 1:
 //            gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
             rn = "ContextConfig";
+            goto die;
 //            break;
+        case 2:
+            if (env->CP0_Config3 & (1 << CP0C3_ULRI)) {
+                tcg_gen_ld_tl(arg, cpu_env,
+                              offsetof(CPUMIPSState, CP0_UserLocal));
+                rn = "UserLocal";
+            } else {
+                tcg_gen_movi_tl(arg, 0);
+            }
+            break;
         default:
             goto die;
         }
@@ -5982,7 +6010,15 @@ static void gen_dmtc0(CPUMIPSState *env, DisasContext 
*ctx,
         case 1:
 //           gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
             rn = "ContextConfig";
+            goto die;
 //           break;
+        case 2:
+            if (env->CP0_Config3 & (1 << CP0C3_ULRI)) {
+                tcg_gen_st_tl(arg, cpu_env,
+                              offsetof(CPUMIPSState, CP0_UserLocal));
+                rn = "UserLocal";
+            }
+            break;
         default:
             goto die;
         }
@@ -9068,8 +9104,10 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
         gen_store_gpr(t0, rt);
         break;
 #else
-        /* XXX: Some CPUs implement this in hardware.
-           Not supported yet. */
+        save_cpu_state(ctx, 1);
+        gen_helper_rdhwr_ul(t0, cpu_env);
+        gen_store_gpr(t0, rt);
+        break;
 #endif
     default:            /* Invalid */
         MIPS_INVAL("rdhwr");
@@ -16034,6 +16072,7 @@ void cpu_state_reset(CPUMIPSState *env)
     /* vectored interrupts not implemented, timer on int 7,
        no performance counters. */
     env->CP0_IntCtl = 0xe0000000;
+    env->CP0_UserLocal = 0;
     {
         int i;
 
-- 
1.7.9.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]