Patchwork [RFC,V1,2/2] target-microblaze: lwx/swx: first implementation

login
register
mail settings
Submitter Peter A. G. Crosthwaite
Date May 17, 2012, 5:37 a.m.
Message ID <f180718497cc2db2144b26a0b8e9245bf7474075.1337232850.git.peter.crosthwaite@petalogix.com>
Download mbox | patch
Permalink /patch/159813/
State New
Headers show

Comments

Peter A. G. Crosthwaite - May 17, 2012, 5:37 a.m.
Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
---
 target-microblaze/cpu.h       |    1 +
 target-microblaze/helper.c    |    2 +
 target-microblaze/translate.c |   51 ++++++++++++++++++++++++++++++++++++++--
 3 files changed, 51 insertions(+), 3 deletions(-)
Edgar Iglesias - May 18, 2012, 10:36 a.m.
On Thu, May 17, 2012 at 03:37:50PM +1000, Peter A. G. Crosthwaite wrote:
> Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
> ---
>  target-microblaze/cpu.h       |    1 +
>  target-microblaze/helper.c    |    2 +
>  target-microblaze/translate.c |   51 ++++++++++++++++++++++++++++++++++++++--
>  3 files changed, 51 insertions(+), 3 deletions(-)
> 
> diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
> index 718d5bb..775a16d 100644
> --- a/target-microblaze/cpu.h
> +++ b/target-microblaze/cpu.h
> @@ -250,6 +250,7 @@ struct CPUMBState {
>  #define DRTE_FLAG	(1 << 17)
>  #define DRTB_FLAG	(1 << 18)
>  #define D_FLAG		(1 << 19)  /* Bit in ESR.  */
> +#define R_FLAG      (1 << 24) /* Reservation Bit */
>  /* TB dependent CPUMBState.  */
>  #define IFLAGS_TB_MASK  (D_FLAG | IMM_FLAG | DRTI_FLAG | DRTE_FLAG | DRTB_FLAG)
>      uint32_t iflags;
> diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c
> index 2412a58..235f1be 100644
> --- a/target-microblaze/helper.c
> +++ b/target-microblaze/helper.c
> @@ -29,6 +29,7 @@
>  void do_interrupt (CPUMBState *env)
>  {
>      env->exception_index = -1;
> +    env->iflags &= ~R_FLAG;
>      env->regs[14] = env->sregs[SR_PC];
>  }
>  
> @@ -116,6 +117,7 @@ void do_interrupt(CPUMBState *env)
>      assert(!((env->iflags & D_FLAG) && (env->iflags & IMM_FLAG)));
>      assert(!(env->iflags & (DRTI_FLAG | DRTE_FLAG | DRTB_FLAG)));
>  /*    assert(env->sregs[SR_MSR] & (MSR_EE)); Only for HW exceptions.  */
> +    env->iflags &= ~R_FLAG;
>      switch (env->exception_index) {
>          case EXCP_HW_EXCP:
>              if (!(env->pvr.regs[0] & PVR0_USE_EXC_MASK)) {
> diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
> index a362938..9c1a0b5 100644
> --- a/target-microblaze/translate.c
> +++ b/target-microblaze/translate.c
> @@ -948,12 +948,13 @@ static inline void dec_byteswap(DisasContext *dc, TCGv dst, TCGv src, int size)
>  static void dec_load(DisasContext *dc)
>  {
>      TCGv t, *addr;
> -    unsigned int size, rev = 0;
> +    unsigned int size, rev = 0, ex = 0;
>  
>      size = 1 << (dc->opcode & 3);
>  
>      if (!dc->type_b) {
>          rev = (dc->ir >> 9) & 1;
> +        ex = (dc->ir >> 10) & 1;
>      }
>  
>      if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
> @@ -1019,6 +1020,17 @@ static void dec_load(DisasContext *dc)
>          }
>      }
>  
> +    /* lwx does not throw unaligned access errors, so force alignment */
> +    if (ex) {
> +        /* Force addr into the temp.  */
> +        if (addr != &t) {
> +            t = tcg_temp_new();
> +            tcg_gen_mov_tl(t, *addr);
> +            addr = &t;
> +        }
> +        tcg_gen_andi_tl(t, t, ~3);
> +    }
> +
>      /* If we get a fault on a dslot, the jmpstate better be in sync.  */
>      sync_jmpstate(dc);
>  
> @@ -1057,6 +1069,13 @@ static void dec_load(DisasContext *dc)
>          }
>      }
>  
> +    if (ex) { /* lwx */
> +        /* no support for for AXI exlusive so always clear C */
> +        TCGv_i32 zero = tcg_const_i32(0);
> +        write_carry(dc, zero);
> +        dc->tb_flags |= R_FLAG;


Here, instead of touching tb_flags you need to emit code that sets the flag
at execution time.




> +    }
> +
>      if (addr == &t)
>          tcg_temp_free(t);
>  }
> @@ -1078,12 +1097,14 @@ static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
>  
>  static void dec_store(DisasContext *dc)
>  {
> -    TCGv t, *addr;
> -    unsigned int size, rev = 0;
> +    TCGv t, *addr, swx_carry = 0;
> +    int swx_skip;
> +    unsigned int size, rev = 0, ex = 0;
>  
>      size = 1 << (dc->opcode & 3);
>      if (!dc->type_b) {
>          rev = (dc->ir >> 9) & 1;
> +        ex = (dc->ir >> 10) & 1;
>      }
>  
>      if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
> @@ -1099,6 +1120,26 @@ static void dec_store(DisasContext *dc)
>      sync_jmpstate(dc);
>      addr = compute_ldst_addr(dc, &t);
>  
> +    if (ex) { /* swx */
> +        TCGv r_check = tcg_temp_new();
> +        swx_carry = tcg_temp_new();
> +        swx_skip = gen_new_label();
> +
> +        tcg_gen_andi_tl(r_check, env_iflags, R_FLAG);
> +        tcg_gen_movi_tl(swx_carry, 1);
> +        tcg_gen_brcondi_tl(TCG_COND_NE, r_check, R_FLAG, swx_skip);
> +        tcg_gen_movi_tl(swx_carry, 0);
> +
> +        /* Force addr into the temp.  */
> +        if (addr != &t) {
> +            t = tcg_temp_new();
> +            tcg_gen_mov_tl(t, *addr);
> +            addr = &t;
> +        }
> +        /* swx does not throw unaligned access errors, so force alignment */
> +        tcg_gen_andi_tl(t, t, ~3);
> +    }
> +
>      if (rev && size != 4) {
>          /* Endian reverse the address. t is addr.  */
>          switch (size) {
> @@ -1174,6 +1215,10 @@ static void dec_store(DisasContext *dc)
>          gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
>                              tcg_const_tl(1), tcg_const_tl(size - 1));
>      }
> +    if (ex) {
> +        gen_set_label(swx_skip);
> +        write_carry(dc, swx_carry);
> +    }
>  
>      if (addr == &t)
>          tcg_temp_free(t);
> -- 
> 1.7.3.2
>

Patch

diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 718d5bb..775a16d 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -250,6 +250,7 @@  struct CPUMBState {
 #define DRTE_FLAG	(1 << 17)
 #define DRTB_FLAG	(1 << 18)
 #define D_FLAG		(1 << 19)  /* Bit in ESR.  */
+#define R_FLAG      (1 << 24) /* Reservation Bit */
 /* TB dependent CPUMBState.  */
 #define IFLAGS_TB_MASK  (D_FLAG | IMM_FLAG | DRTI_FLAG | DRTE_FLAG | DRTB_FLAG)
     uint32_t iflags;
diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c
index 2412a58..235f1be 100644
--- a/target-microblaze/helper.c
+++ b/target-microblaze/helper.c
@@ -29,6 +29,7 @@ 
 void do_interrupt (CPUMBState *env)
 {
     env->exception_index = -1;
+    env->iflags &= ~R_FLAG;
     env->regs[14] = env->sregs[SR_PC];
 }
 
@@ -116,6 +117,7 @@  void do_interrupt(CPUMBState *env)
     assert(!((env->iflags & D_FLAG) && (env->iflags & IMM_FLAG)));
     assert(!(env->iflags & (DRTI_FLAG | DRTE_FLAG | DRTB_FLAG)));
 /*    assert(env->sregs[SR_MSR] & (MSR_EE)); Only for HW exceptions.  */
+    env->iflags &= ~R_FLAG;
     switch (env->exception_index) {
         case EXCP_HW_EXCP:
             if (!(env->pvr.regs[0] & PVR0_USE_EXC_MASK)) {
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index a362938..9c1a0b5 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -948,12 +948,13 @@  static inline void dec_byteswap(DisasContext *dc, TCGv dst, TCGv src, int size)
 static void dec_load(DisasContext *dc)
 {
     TCGv t, *addr;
-    unsigned int size, rev = 0;
+    unsigned int size, rev = 0, ex = 0;
 
     size = 1 << (dc->opcode & 3);
 
     if (!dc->type_b) {
         rev = (dc->ir >> 9) & 1;
+        ex = (dc->ir >> 10) & 1;
     }
 
     if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
@@ -1019,6 +1020,17 @@  static void dec_load(DisasContext *dc)
         }
     }
 
+    /* lwx does not throw unaligned access errors, so force alignment */
+    if (ex) {
+        /* Force addr into the temp.  */
+        if (addr != &t) {
+            t = tcg_temp_new();
+            tcg_gen_mov_tl(t, *addr);
+            addr = &t;
+        }
+        tcg_gen_andi_tl(t, t, ~3);
+    }
+
     /* If we get a fault on a dslot, the jmpstate better be in sync.  */
     sync_jmpstate(dc);
 
@@ -1057,6 +1069,13 @@  static void dec_load(DisasContext *dc)
         }
     }
 
+    if (ex) { /* lwx */
+        /* no support for for AXI exlusive so always clear C */
+        TCGv_i32 zero = tcg_const_i32(0);
+        write_carry(dc, zero);
+        dc->tb_flags |= R_FLAG;
+    }
+
     if (addr == &t)
         tcg_temp_free(t);
 }
@@ -1078,12 +1097,14 @@  static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
 
 static void dec_store(DisasContext *dc)
 {
-    TCGv t, *addr;
-    unsigned int size, rev = 0;
+    TCGv t, *addr, swx_carry = 0;
+    int swx_skip;
+    unsigned int size, rev = 0, ex = 0;
 
     size = 1 << (dc->opcode & 3);
     if (!dc->type_b) {
         rev = (dc->ir >> 9) & 1;
+        ex = (dc->ir >> 10) & 1;
     }
 
     if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
@@ -1099,6 +1120,26 @@  static void dec_store(DisasContext *dc)
     sync_jmpstate(dc);
     addr = compute_ldst_addr(dc, &t);
 
+    if (ex) { /* swx */
+        TCGv r_check = tcg_temp_new();
+        swx_carry = tcg_temp_new();
+        swx_skip = gen_new_label();
+
+        tcg_gen_andi_tl(r_check, env_iflags, R_FLAG);
+        tcg_gen_movi_tl(swx_carry, 1);
+        tcg_gen_brcondi_tl(TCG_COND_NE, r_check, R_FLAG, swx_skip);
+        tcg_gen_movi_tl(swx_carry, 0);
+
+        /* Force addr into the temp.  */
+        if (addr != &t) {
+            t = tcg_temp_new();
+            tcg_gen_mov_tl(t, *addr);
+            addr = &t;
+        }
+        /* swx does not throw unaligned access errors, so force alignment */
+        tcg_gen_andi_tl(t, t, ~3);
+    }
+
     if (rev && size != 4) {
         /* Endian reverse the address. t is addr.  */
         switch (size) {
@@ -1174,6 +1215,10 @@  static void dec_store(DisasContext *dc)
         gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
                             tcg_const_tl(1), tcg_const_tl(size - 1));
     }
+    if (ex) {
+        gen_set_label(swx_skip);
+        write_carry(dc, swx_carry);
+    }
 
     if (addr == &t)
         tcg_temp_free(t);