Patchwork [20/26] target-xtensa: implement extended L32R

login
register
mail settings
Submitter Max Filippov
Date May 17, 2011, 10:32 p.m.
Message ID <1305671572-5899-21-git-send-email-jcmvbkbc@gmail.com>
Download mbox | patch
Permalink /patch/96070/
State New
Headers show

Comments

Max Filippov - May 17, 2011, 10:32 p.m.
See ISA, 4.3.3 for details.

TB flag XTENSA_TBFLAG_LITBASE is used to track enable bit of LITBASE SR.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
RFC -> PATCH changes:
- add XTENSA_TBFLAG_LITBASE, use it in L32R;
---
 target-xtensa/cpu.h       |    6 ++++++
 target-xtensa/helper.c    |    1 +
 target-xtensa/translate.c |   19 +++++++++++++++----
 3 files changed, 22 insertions(+), 4 deletions(-)
Richard Henderson - May 19, 2011, 10 p.m.
On 05/17/2011 03:32 PM, Max Filippov wrote:
> +static void gen_wsr_litbase(DisasContext *dc, uint32_t sr, TCGv_i32 s)
> +{
> +    tcg_gen_mov_i32(cpu_SR[sr], s);
> +    /* This can change tb->flags, so exit tb */
> +    gen_jumpi_check_loop_end(dc, -1);
> +}

Surely you have to flush all TB's when changing litbase?

> +                    ((dc->tb->flags & XTENSA_TBFLAG_LITBASE) ?
> +                     dc->litbase :
> +                     ((dc->pc + 3) & ~3)) +
> +                    (0xfffc0000 | (RI16_IMM16 << 2)));

Unless you actually read from env->sr[LITBASE] here, instead
of building the value into the TB.


r~
Max Filippov - May 20, 2011, 7:14 a.m.
> > +static void gen_wsr_litbase(DisasContext *dc, uint32_t sr, TCGv_i32 s)
> > +{
> > +    tcg_gen_mov_i32(cpu_SR[sr], s);
> > +    /* This can change tb->flags, so exit tb */
> > +    gen_jumpi_check_loop_end(dc, -1);
> > +}
> 
> Surely you have to flush all TB's when changing litbase?
> 
> > +                    ((dc->tb->flags & XTENSA_TBFLAG_LITBASE) ?
> > +                     dc->litbase :
> > +                     ((dc->pc + 3) & ~3)) +
> > +                    (0xfffc0000 | (RI16_IMM16 << 2)));
> 
> Unless you actually read from env->sr[LITBASE] here, instead
> of building the value into the TB.

You're right, I have to flush all TBs at gen_wsr_litbase for this code to always work correctly.
As far as I can see LITBASE usage pattern is that it is set up once in early initialization and is never changed after.

Thanks.
-- Max
Richard Henderson - May 20, 2011, 3:30 p.m.
On 05/20/2011 12:14 AM, Max Filippov wrote:
> As far as I can see LITBASE usage pattern is that it is set up once
> in early initialization and is never changed after.

That's probably true on a per-program basis.  I.e. for semi-hosting or userland
emulation, hard-coding litbase into the TB could make sense.

However, for full system emulation, with kernel and userland et al, I would 
expect that litbase would tend to be set per-application.  At which point it
would almost certainly be more efficient to read the value at runtime.


r~

Patch

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 026b854..793a6b5 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -110,6 +110,7 @@  enum {
     LEND = 1,
     LCOUNT = 2,
     SAR = 3,
+    LITBASE = 5,
     SCOMPARE1 = 12,
     WINDOW_BASE = 72,
     WINDOW_START = 73,
@@ -261,6 +262,7 @@  static inline int cpu_mmu_index(CPUState *env)
 }
 
 #define XTENSA_TBFLAG_EXCM 0x1
+#define XTENSA_TBFLAG_LITBASE 0x2
 
 static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
         target_ulong *cs_base, int *flags)
@@ -271,6 +273,10 @@  static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
     if (env->sregs[PS] & PS_EXCM) {
         *flags |= XTENSA_TBFLAG_EXCM;
     }
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_EXTENDED_L32R) &&
+            (env->sregs[LITBASE] & 1)) {
+        *flags |= XTENSA_TBFLAG_LITBASE;
+    }
 }
 
 #include "cpu-all.h"
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 0eb3b9a..ffa5590 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -38,6 +38,7 @@  void cpu_reset(CPUXtensaState *env)
 {
     env->exception_taken = 0;
     env->pc = env->config->exception_vector[EXC_RESET];
+    env->sregs[LITBASE] &= ~1;
     env->sregs[PS] = 0x1f;
 }
 
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index e5e4ce7..592072a 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -47,6 +47,7 @@  typedef struct DisasContext {
     uint32_t next_pc;
     int mem_idx;
     uint32_t lend;
+    uint32_t litbase;
     int is_jmp;
     int singlestep_enabled;
 
@@ -69,6 +70,7 @@  static const char * const sregnames[256] = {
     [LEND] = "LEND",
     [LCOUNT] = "LCOUNT",
     [SAR] = "SAR",
+    [LITBASE] = "LITBASE",
     [SCOMPARE1] = "SCOMPARE1",
     [WINDOW_BASE] = "WINDOW_BASE",
     [WINDOW_START] = "WINDOW_START",
@@ -314,6 +316,13 @@  static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)
     dc->sar_m32_5bit = false;
 }
 
+static void gen_wsr_litbase(DisasContext *dc, uint32_t sr, TCGv_i32 s)
+{
+    tcg_gen_mov_i32(cpu_SR[sr], s);
+    /* This can change tb->flags, so exit tb */
+    gen_jumpi_check_loop_end(dc, -1);
+}
+
 static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     gen_helper_wsr_windowbase(v);
@@ -325,6 +334,7 @@  static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
             uint32_t sr, TCGv_i32 v) = {
         [LEND] = gen_wsr_lend,
         [SAR] = gen_wsr_sar,
+        [LITBASE] = gen_wsr_litbase,
         [WINDOW_BASE] = gen_wsr_windowbase,
     };
 
@@ -1250,10 +1260,10 @@  static void disas_xtensa_insn(DisasContext *dc)
     case 1: /*L32R*/
         {
             TCGv_i32 tmp = tcg_const_i32(
-                    (0xfffc0000 | (RI16_IMM16 << 2)) +
-                    ((dc->pc + 3) & ~3));
-
-            /* no ext L32R */
+                    ((dc->tb->flags & XTENSA_TBFLAG_LITBASE) ?
+                     dc->litbase :
+                     ((dc->pc + 3) & ~3)) +
+                    (0xfffc0000 | (RI16_IMM16 << 2)));
 
             tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, 0);
             tcg_temp_free(tmp);
@@ -1780,6 +1790,7 @@  static void gen_intermediate_code_internal(
     dc.pc = env->pc;
     dc.mem_idx = cpu_mmu_index(env);
     dc.lend = env->sregs[LEND];
+    dc.litbase = env->sregs[LITBASE] & 0xfffff000;
     dc.is_jmp = DISAS_NEXT;
 
     reset_sar_tracker(&dc);