diff mbox

[01/12] target-mips: add KScratch registers

Message ID 1403189143-54609-2-git-send-email-leon.alrae@imgtec.com
State New
Headers show

Commit Message

Leon Alrae June 19, 2014, 2:45 p.m. UTC
KScratch<n> Registers (CP0 Register 31, Selects 2 to 7)

The KScratch registers are read/write registers available for scratch pad
storage by kernel mode software. They are 32-bits in width for 32-bit
processors and 64-bits for 64-bit processors.

CP0Config4.KScrExist[2:7] bits indicate presence of CP0_KScratch1-6 registers.
For Release 6, all KScratch registers are required.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/cpu.h       |    3 +++
 target-mips/translate.c |   27 +++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 0 deletions(-)

Comments

Aurelien Jarno June 20, 2014, 10:02 p.m. UTC | #1
On Thu, Jun 19, 2014 at 03:45:32PM +0100, Leon Alrae wrote:
> KScratch<n> Registers (CP0 Register 31, Selects 2 to 7)
> 
> The KScratch registers are read/write registers available for scratch pad
> storage by kernel mode software. They are 32-bits in width for 32-bit
> processors and 64-bits for 64-bit processors.
> 
> CP0Config4.KScrExist[2:7] bits indicate presence of CP0_KScratch1-6 registers.
> For Release 6, all KScratch registers are required.
> 
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>  target-mips/cpu.h       |    3 +++
>  target-mips/translate.c |   27 +++++++++++++++++++++++++++
>  2 files changed, 30 insertions(+), 0 deletions(-)
> 
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 217c09b..fae94ed 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -136,6 +136,7 @@ typedef struct mips_def_t mips_def_t;
>  #define MIPS_TC_MAX 5
>  #define MIPS_FPU_MAX 1
>  #define MIPS_DSP_ACC 4
> +#define MIPS_KSCRATCH_NUM 6
>  
>  typedef struct TCState TCState;
>  struct TCState {
> @@ -229,6 +230,7 @@ struct CPUMIPSState {
>      target_ulong CP0_EntryLo0;
>      target_ulong CP0_EntryLo1;
>      target_ulong CP0_Context;
> +    target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
>      int32_t CP0_PageMask;
>      int32_t CP0_PageGrain;
>      int32_t CP0_Wired;
> @@ -374,6 +376,7 @@ struct CPUMIPSState {
>  #define CP0C3_TL   0
>      uint32_t CP0_Config4;
>      uint32_t CP0_Config4_rw_bitmask;
> +#define CP0C4_KScrExist 16
>  #define CP0C4_M    31
>      uint32_t CP0_Config5;
>      uint32_t CP0_Config5_rw_bitmask;
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index a8dc529..4e90c08 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -1174,6 +1174,7 @@ typedef struct DisasContext {
>      int bstate;
>      target_ulong btarget;
>      bool ulri;
> +    int32_t kscrexist;
>  } DisasContext;
>  
>  enum {
> @@ -5198,6 +5199,12 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>              gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
>              rn = "DESAVE";
>              break;
> +        case 2 ... 7:
> +            tcg_gen_ld_tl(arg, cpu_env,
> +                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> +            tcg_gen_ext32s_tl(arg, arg);
> +            rn = "KScratch";
> +            break;

This change the behaviour of existing CPU which don't implement scratch
registers. Before it would generate an RI exception, and after the
patch, it would simply leave the register unchanged.

The architecture manuals says in that case the result is UNDEFINED, so
that might be fine, that said it also says this instruction could
generate an RI exception, and I wouldn't be surprised real silicon
actually generate such an exception.

The best would be to try on a real silicon to decide.

>          default:
>              goto die;
>          }
> @@ -5806,6 +5813,13 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>              gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
>              rn = "DESAVE";
>              break;
> +        case 2 ... 7:
> +            if (ctx->kscrexist & (1 << sel)) {
> +                tcg_gen_st_tl(arg, cpu_env,
> +                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> +                rn = "KScratch";
> +            }
> +            break;
>          default:
>              goto die;
>          }
> @@ -6393,6 +6407,11 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>              gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
>              rn = "DESAVE";
>              break;
> +        case 2 ... 7:
> +            tcg_gen_ld_tl(arg, cpu_env,
> +                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> +            rn = "KScratch";
> +            break;
>          default:
>              goto die;
>          }
> @@ -6992,6 +7011,13 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>              gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
>              rn = "DESAVE";
>              break;
> +        case 2 ... 7:
> +            if (ctx->kscrexist & (1 << sel)) {
> +                tcg_gen_st_tl(arg, cpu_env,
> +                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> +                rn = "KScratch";
> +            }
> +            break;
>          default:
>              goto die;
>          }
> @@ -17499,6 +17525,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
>      ctx.insn_flags = env->insn_flags;
>      ctx.tb = tb;
>      ctx.bstate = BS_NONE;
> +    ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
>      /* 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 & (1 << CP0C3_ULRI);
> -- 
> 1.7.5.4
> 
>
Leon Alrae July 8, 2014, 8:18 a.m. UTC | #2
On 20/06/2014 23:02, Aurelien Jarno wrote:
>> @@ -5198,6 +5199,12 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>>              gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
>>              rn = "DESAVE";
>>              break;
>> +        case 2 ... 7:
>> +            tcg_gen_ld_tl(arg, cpu_env,
>> +                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
>> +            tcg_gen_ext32s_tl(arg, arg);
>> +            rn = "KScratch";
>> +            break;
> 
> This change the behaviour of existing CPU which don't implement scratch
> registers. Before it would generate an RI exception, and after the
> patch, it would simply leave the register unchanged.
> 
> The architecture manuals says in that case the result is UNDEFINED, so
> that might be fine, that said it also says this instruction could
> generate an RI exception, and I wouldn't be surprised real silicon
> actually generate such an exception.

On the real HW - reads from an unimplemented cp0 register return
0xffffffff (in R6 it will be 0) and writes are just ignored, there is no
RI exception. In v2 I updated the behaviour for the new registers only.
I think the same changes will be needed for the existing registers, but
this is out of the current patch series scope - I plan to do this later.

Thanks,
Leon
diff mbox

Patch

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 217c09b..fae94ed 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -136,6 +136,7 @@  typedef struct mips_def_t mips_def_t;
 #define MIPS_TC_MAX 5
 #define MIPS_FPU_MAX 1
 #define MIPS_DSP_ACC 4
+#define MIPS_KSCRATCH_NUM 6
 
 typedef struct TCState TCState;
 struct TCState {
@@ -229,6 +230,7 @@  struct CPUMIPSState {
     target_ulong CP0_EntryLo0;
     target_ulong CP0_EntryLo1;
     target_ulong CP0_Context;
+    target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
     int32_t CP0_PageMask;
     int32_t CP0_PageGrain;
     int32_t CP0_Wired;
@@ -374,6 +376,7 @@  struct CPUMIPSState {
 #define CP0C3_TL   0
     uint32_t CP0_Config4;
     uint32_t CP0_Config4_rw_bitmask;
+#define CP0C4_KScrExist 16
 #define CP0C4_M    31
     uint32_t CP0_Config5;
     uint32_t CP0_Config5_rw_bitmask;
diff --git a/target-mips/translate.c b/target-mips/translate.c
index a8dc529..4e90c08 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1174,6 +1174,7 @@  typedef struct DisasContext {
     int bstate;
     target_ulong btarget;
     bool ulri;
+    int32_t kscrexist;
 } DisasContext;
 
 enum {
@@ -5198,6 +5199,12 @@  static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
             rn = "DESAVE";
             break;
+        case 2 ... 7:
+            tcg_gen_ld_tl(arg, cpu_env,
+                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
+            tcg_gen_ext32s_tl(arg, arg);
+            rn = "KScratch";
+            break;
         default:
             goto die;
         }
@@ -5806,6 +5813,13 @@  static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
             rn = "DESAVE";
             break;
+        case 2 ... 7:
+            if (ctx->kscrexist & (1 << sel)) {
+                tcg_gen_st_tl(arg, cpu_env,
+                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
+                rn = "KScratch";
+            }
+            break;
         default:
             goto die;
         }
@@ -6393,6 +6407,11 @@  static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
             rn = "DESAVE";
             break;
+        case 2 ... 7:
+            tcg_gen_ld_tl(arg, cpu_env,
+                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
+            rn = "KScratch";
+            break;
         default:
             goto die;
         }
@@ -6992,6 +7011,13 @@  static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
             rn = "DESAVE";
             break;
+        case 2 ... 7:
+            if (ctx->kscrexist & (1 << sel)) {
+                tcg_gen_st_tl(arg, cpu_env,
+                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
+                rn = "KScratch";
+            }
+            break;
         default:
             goto die;
         }
@@ -17499,6 +17525,7 @@  gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
     ctx.insn_flags = env->insn_flags;
     ctx.tb = tb;
     ctx.bstate = BS_NONE;
+    ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
     /* 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 & (1 << CP0C3_ULRI);