qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Richard Henderson <rth@twiddle.net>
To: qemu-devel@nongnu.org
Cc: peter.maydell@linaro.org, mark.cave-ayland@ilande.co.uk
Subject: [Qemu-devel] [PULL 15/24] target-sparc: Directly implement easy ldd/std asis
Date: Tue, 12 Jul 2016 12:02:09 -0700	[thread overview]
Message-ID: <1468350138-9736-16-git-send-email-rth@twiddle.net> (raw)
In-Reply-To: <1468350138-9736-1-git-send-email-rth@twiddle.net>

Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/translate.c | 115 ++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 103 insertions(+), 12 deletions(-)

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index e7120f8..0d5149d 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1988,6 +1988,7 @@ typedef enum {
     GET_ASI_HELPER,
     GET_ASI_EXCP,
     GET_ASI_DIRECT,
+    GET_ASI_DTWINX,
 } ASIType;
 
 typedef struct {
@@ -2046,18 +2047,26 @@ static DisasASI get_asi(DisasContext *dc, int insn, TCGMemOp memop)
         switch (asi) {
         case ASI_N:  /* Nucleus */
         case ASI_NL: /* Nucleus LE */
+        case ASI_TWINX_N:
+        case ASI_TWINX_NL:
             mem_idx = MMU_NUCLEUS_IDX;
             break;
         case ASI_AIUP:  /* As if user primary */
         case ASI_AIUPL: /* As if user primary LE */
+        case ASI_TWINX_AIUP:
+        case ASI_TWINX_AIUP_L:
             mem_idx = MMU_USER_IDX;
             break;
         case ASI_AIUS:  /* As if user secondary */
         case ASI_AIUSL: /* As if user secondary LE */
+        case ASI_TWINX_AIUS:
+        case ASI_TWINX_AIUS_L:
             mem_idx = MMU_USER_SECONDARY_IDX;
             break;
         case ASI_S:  /* Secondary */
         case ASI_SL: /* Secondary LE */
+        case ASI_TWINX_S:
+        case ASI_TWINX_SL:
             if (mem_idx == MMU_USER_IDX) {
                 mem_idx = MMU_USER_SECONDARY_IDX;
             } else if (mem_idx == MMU_KERNEL_IDX) {
@@ -2066,6 +2075,8 @@ static DisasASI get_asi(DisasContext *dc, int insn, TCGMemOp memop)
             break;
         case ASI_P:  /* Primary */
         case ASI_PL: /* Primary LE */
+        case ASI_TWINX_P:
+        case ASI_TWINX_PL:
             break;
         }
         switch (asi) {
@@ -2081,6 +2092,18 @@ static DisasASI get_asi(DisasContext *dc, int insn, TCGMemOp memop)
         case ASI_PL:
             type = GET_ASI_DIRECT;
             break;
+        case ASI_TWINX_N:
+        case ASI_TWINX_NL:
+        case ASI_TWINX_AIUP:
+        case ASI_TWINX_AIUP_L:
+        case ASI_TWINX_AIUS:
+        case ASI_TWINX_AIUS_L:
+        case ASI_TWINX_P:
+        case ASI_TWINX_PL:
+        case ASI_TWINX_S:
+        case ASI_TWINX_SL:
+            type = GET_ASI_DTWINX;
+            break;
         }
         /* The little-endian asis all have bit 3 set.  */
         if (asi & 8) {
@@ -2100,6 +2123,9 @@ static void gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr,
     switch (da.type) {
     case GET_ASI_EXCP:
         break;
+    case GET_ASI_DTWINX: /* Reserved for ldda.  */
+        gen_exception(dc, TT_ILL_INSN);
+        break;
     case GET_ASI_DIRECT:
         gen_address_mask(dc, addr);
         tcg_gen_qemu_ld_tl(dst, addr, da.mem_idx, da.memop);
@@ -2137,6 +2163,9 @@ static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr,
     switch (da.type) {
     case GET_ASI_EXCP:
         break;
+    case GET_ASI_DTWINX: /* Reserved for stda.  */
+        gen_exception(dc, TT_ILL_INSN);
+        break;
     case GET_ASI_DIRECT:
         gen_address_mask(dc, addr);
         tcg_gen_qemu_st_tl(src, addr, da.mem_idx, da.memop);
@@ -2303,32 +2332,59 @@ static void gen_stf_asi(DisasContext *dc, TCGv addr,
     }
 }
 
-static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
-                         int insn, int rd)
+static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd)
 {
     DisasASI da = get_asi(dc, insn, MO_TEQ);
+    TCGv_i64 hi = gen_dest_gpr(dc, rd);
+    TCGv_i64 lo = gen_dest_gpr(dc, rd + 1);
 
     switch (da.type) {
     case GET_ASI_EXCP:
+        return;
+
+    case GET_ASI_DTWINX:
+        gen_check_align(addr, 15);
+        gen_address_mask(dc, addr);
+        tcg_gen_qemu_ld_i64(hi, addr, da.mem_idx, da.memop);
+        tcg_gen_addi_tl(addr, addr, 8);
+        tcg_gen_qemu_ld_i64(lo, addr, da.mem_idx, da.memop);
         break;
+
+    case GET_ASI_DIRECT:
+        {
+            TCGv_i64 tmp = tcg_temp_new_i64();
+
+            gen_address_mask(dc, addr);
+            tcg_gen_qemu_ld_i64(tmp, addr, da.mem_idx, da.memop);
+
+            /* Note that LE ldda acts as if each 32-bit register
+               result is byte swapped.  Having just performed one
+               64-bit bswap, we need now to swap the writebacks.  */
+            if ((da.memop & MO_BSWAP) == MO_TE) {
+                tcg_gen_extr32_i64(lo, hi, tmp);
+            } else {
+                tcg_gen_extr32_i64(hi, lo, tmp);
+            }
+            tcg_temp_free_i64(tmp);
+        }
+        break;
+
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
-            TCGv_i64 tmp;
 
             save_state(dc);
             gen_helper_ldda_asi(cpu_env, addr, r_asi);
             tcg_temp_free_i32(r_asi);
 
-            tmp = gen_dest_gpr(dc, rd);
-            tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUSPARCState, qt0.high));
-            gen_store_gpr(dc, rd, tmp);
-            tmp = gen_dest_gpr(dc, rd + 1);
-            tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUSPARCState, qt0.low));
-            gen_store_gpr(dc, rd + 1, tmp);
+            tcg_gen_ld_i64(hi, cpu_env, offsetof(CPUSPARCState, qt0.high));
+            tcg_gen_ld_i64(lo, cpu_env, offsetof(CPUSPARCState, qt0.low));
         }
         break;
     }
+
+    gen_store_gpr(dc, rd, hi);
+    gen_store_gpr(dc, rd + 1, lo);
 }
 
 static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
@@ -2340,6 +2396,33 @@ static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
     switch (da.type) {
     case GET_ASI_EXCP:
         break;
+
+    case GET_ASI_DTWINX:
+        gen_check_align(addr, 15);
+        gen_address_mask(dc, addr);
+        tcg_gen_qemu_st_i64(hi, addr, da.mem_idx, da.memop);
+        tcg_gen_addi_tl(addr, addr, 8);
+        tcg_gen_qemu_st_i64(lo, addr, da.mem_idx, da.memop);
+        break;
+
+    case GET_ASI_DIRECT:
+        {
+            TCGv_i64 t64 = tcg_temp_new_i64();
+
+            /* Note that LE stda acts as if each 32-bit register result is
+               byte swapped.  We will perform one 64-bit LE store, so now
+               we must swap the order of the construction.  */
+            if ((da.memop & MO_BSWAP) == MO_TE) {
+                tcg_gen_concat32_i64(t64, lo, hi);
+            } else {
+                tcg_gen_concat32_i64(t64, hi, lo);
+            }
+            gen_address_mask(dc, addr);
+            tcg_gen_qemu_st_i64(t64, addr, da.mem_idx, da.memop);
+            tcg_temp_free_i64(t64);
+        }
+        break;
+
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
@@ -2379,14 +2462,14 @@ static void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv val2,
 }
 
 #elif !defined(CONFIG_USER_ONLY)
-static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
-                         int insn, int rd)
+static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd)
 {
     /* ??? Work around an apparent bug in Ubuntu gcc 4.8.2-10ubuntu2+12,
        whereby "rd + 1" elicits "error: array subscript is above array".
        Since we have already asserted that rd is even, the semantics
        are unchanged.  */
     TCGv lo = gen_dest_gpr(dc, rd | 1);
+    TCGv hi = gen_dest_gpr(dc, rd);
     TCGv_i64 t64 = tcg_temp_new_i64();
     DisasASI da = get_asi(dc, insn, MO_TEQ);
 
@@ -2394,6 +2477,10 @@ static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
     case GET_ASI_EXCP:
         tcg_temp_free_i64(t64);
         return;
+    case GET_ASI_DIRECT:
+        gen_address_mask(dc, addr);
+        tcg_gen_qemu_ld_i64(t64, addr, da.mem_idx, da.memop);
+        break;
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
@@ -2427,6 +2514,10 @@ static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
     switch (da.type) {
     case GET_ASI_EXCP:
         break;
+    case GET_ASI_DIRECT:
+        gen_address_mask(dc, addr);
+        tcg_gen_qemu_st_i64(t64, addr, da.mem_idx, da.memop);
+        break;
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
@@ -4918,7 +5009,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     if (rd & 1) {
                         goto illegal_insn;
                     }
-                    gen_ldda_asi(dc, cpu_val, cpu_addr, insn, rd);
+                    gen_ldda_asi(dc, cpu_addr, insn, rd);
                     goto skip_move;
                 case 0x19:      /* ldsba, load signed byte alternate */
                     gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_SB);
-- 
2.7.4

  parent reply	other threads:[~2016-07-12 19:03 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-12 19:01 [Qemu-devel] [PULL 00/24] target-sparc improvements Richard Henderson
2016-07-12 19:01 ` [Qemu-devel] [PULL 01/24] target-sparc: Mark more flags for helpers Richard Henderson
2016-07-12 19:01 ` [Qemu-devel] [PULL 02/24] target-sparc: Remove softint as a TCG global Richard Henderson
2016-07-12 19:01 ` [Qemu-devel] [PULL 03/24] target-sparc: Store mmu index in TB flags Richard Henderson
2016-07-12 19:01 ` [Qemu-devel] [PULL 04/24] target-sparc: Create gen_exception Richard Henderson
2016-07-12 19:01 ` [Qemu-devel] [PULL 05/24] target-sparc: Unify asi handling between 32 and 64-bit Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 06/24] target-sparc: Store %asi in TB flags Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 07/24] target-sparc: Introduce get_asi Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 08/24] target-sparc: Pass TCGMemOp to gen_ld/st_asi Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 09/24] target-sparc: Import linux/arch/sparc/include/uapi/asm/asi.h Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 10/24] target-sparc: Add UA2005 defines to asi.h Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 11/24] target-sparc: Use defines from asi.h Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 12/24] target-sparc: Directly implement easy ld/st asis Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 13/24] target-sparc: Use QT0 to return results from ldda Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 14/24] target-sparc: Introduce gen_check_align Richard Henderson
2016-07-12 19:02 ` Richard Henderson [this message]
2016-07-12 19:02 ` [Qemu-devel] [PULL 16/24] target-sparc: Fix obvious error in ASI_M_BFILL Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 17/24] target-sparc: Pass TCGMemOp constants to helper_ld/st_asi Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 18/24] target-sparc: Directly implement easy ldf/stf asis Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 19/24] target-sparc: Directly implement block and short " Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 20/24] target-sparc: Remove helper_ldf_asi, helper_stf_asi Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 21/24] target-sparc: Use explicit writes to cpu_fsr Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 22/24] target-sparc: Use cpu_fsr in stfsr Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 23/24] target-sparc: Use cpu_loop_exit_restore from helper_check_ieee_exceptions Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 24/24] target-sparc: Elide duplicate updates to fprs Richard Henderson
2016-07-14 10:48 ` [Qemu-devel] [PULL 00/24] target-sparc improvements 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=1468350138-9736-16-git-send-email-rth@twiddle.net \
    --to=rth@twiddle.net \
    --cc=mark.cave-ayland@ilande.co.uk \
    --cc=peter.maydell@linaro.org \
    --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).