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 13/24] target-sparc: Use QT0 to return results from ldda
Date: Tue, 12 Jul 2016 12:02:07 -0700	[thread overview]
Message-ID: <1468350138-9736-14-git-send-email-rth@twiddle.net> (raw)
In-Reply-To: <1468350138-9736-1-git-send-email-rth@twiddle.net>

Also implement a few more twinx asis.

Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/helper.h      |   2 +-
 target-sparc/ldst_helper.c | 156 ++++++++++++++++++++++++++++++++-------------
 target-sparc/translate.c   |  12 +++-
 3 files changed, 120 insertions(+), 50 deletions(-)

diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 14712cc..66abf83 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -17,7 +17,7 @@ DEF_HELPER_1(rdcwp, tl, env)
 DEF_HELPER_2(wrcwp, void, env, tl)
 DEF_HELPER_FLAGS_2(array8, TCG_CALL_NO_RWG_SE, tl, tl, tl)
 DEF_HELPER_FLAGS_1(popc, TCG_CALL_NO_RWG_SE, tl, tl)
-DEF_HELPER_4(ldda_asi, void, env, tl, int, int)
+DEF_HELPER_FLAGS_3(ldda_asi, TCG_CALL_NO_WG, void, env, tl, int)
 DEF_HELPER_5(ldf_asi, void, env, tl, int, int, int)
 DEF_HELPER_FLAGS_5(stf_asi, TCG_CALL_NO_WG, void, env, tl, int, int, int)
 DEF_HELPER_FLAGS_5(casx_asi, TCG_CALL_NO_WG, tl, env, tl, tl, tl, i32)
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 77323a3..ba48687 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -1329,8 +1329,6 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
     case ASI_S:  /* Secondary */
     case ASI_PL: /* Primary LE */
     case ASI_SL: /* Secondary LE */
-    case ASI_BLK_INIT_QUAD_LDD_P: /* UA2007 Primary block init */
-    case ASI_BLK_INIT_QUAD_LDD_S: /* UA2007 Secondary block init */
         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
             if (cpu_hypervisor_mode(env)) {
                 switch (size) {
@@ -1443,11 +1441,6 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
             }
             break;
         }
-    case ASI_NUCLEUS_QUAD_LDD:   /* Nucleus quad LDD 128 bit atomic */
-    case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */
-        /* Only ldda allowed */
-        helper_raise_exception(env, TT_ILL_INSN);
-        return 0;
     case ASI_N:  /* Nucleus */
     case ASI_NL: /* Nucleus Little Endian (LE) */
         {
@@ -1595,6 +1588,25 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
         cpu_unassigned_access(cs, addr, false, false, 1, size);
         ret = 0;
         break;
+
+    case ASI_NUCLEUS_QUAD_LDD:   /* Nucleus quad LDD 128 bit atomic */
+    case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */
+    case ASI_TWINX_AIUP:   /* As if user primary, twinx */
+    case ASI_TWINX_AIUS:   /* As if user secondary, twinx */
+    case ASI_TWINX_REAL:   /* Real address, twinx */
+    case ASI_TWINX_AIUP_L: /* As if user primary, twinx, LE */
+    case ASI_TWINX_AIUS_L: /* As if user secondary, twinx, LE */
+    case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
+    case ASI_TWINX_N:  /* Nucleus, twinx */
+    case ASI_TWINX_NL: /* Nucleus, twinx, LE */
+    /* ??? From the UA2011 document; overlaps BLK_INIT_QUAD_LDD_* */
+    case ASI_TWINX_P:  /* Primary, twinx */
+    case ASI_TWINX_PL: /* Primary, twinx, LE */
+    case ASI_TWINX_S:  /* Secondary, twinx */
+    case ASI_TWINX_SL: /* Secondary, twinx, LE */
+        /* These are all 128-bit atomic; only ldda (now ldtxa) allowed */
+        helper_raise_exception(env, TT_ILL_INSN);
+        return 0;
     }
 
     /* Convert from little endian */
@@ -1702,8 +1714,6 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
     case ASI_S:  /* Secondary */
     case ASI_PL: /* Primary LE */
     case ASI_SL: /* Secondary LE */
-    case ASI_BLK_INIT_QUAD_LDD_P: /* UA2007 Primary block init */
-    case ASI_BLK_INIT_QUAD_LDD_S: /* UA2007 Secondary block init */
         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
             if (cpu_hypervisor_mode(env)) {
                 switch (size) {
@@ -1816,11 +1826,6 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
             }
         }
         return;
-    case ASI_NUCLEUS_QUAD_LDD:   /* Nucleus quad LDD 128 bit atomic */
-    case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */
-        /* Only ldda allowed */
-        helper_raise_exception(env, TT_ILL_INSN);
-        return;
     case ASI_N:  /* Nucleus */
     case ASI_NL: /* Nucleus Little Endian (LE) */
         {
@@ -2001,6 +2006,24 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
     case ASI_INTR_RECEIVE: /* Interrupt data receive */
         env->ivec_status = val & 0x20;
         return;
+    case ASI_NUCLEUS_QUAD_LDD:   /* Nucleus quad LDD 128 bit atomic */
+    case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */
+    case ASI_TWINX_AIUP:   /* As if user primary, twinx */
+    case ASI_TWINX_AIUS:   /* As if user secondary, twinx */
+    case ASI_TWINX_REAL:   /* Real address, twinx */
+    case ASI_TWINX_AIUP_L: /* As if user primary, twinx, LE */
+    case ASI_TWINX_AIUS_L: /* As if user secondary, twinx, LE */
+    case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
+    case ASI_TWINX_N:  /* Nucleus, twinx */
+    case ASI_TWINX_NL: /* Nucleus, twinx, LE */
+    /* ??? From the UA2011 document; overlaps BLK_INIT_QUAD_LDD_* */
+    case ASI_TWINX_P:  /* Primary, twinx */
+    case ASI_TWINX_PL: /* Primary, twinx, LE */
+    case ASI_TWINX_S:  /* Secondary, twinx */
+    case ASI_TWINX_SL: /* Secondary, twinx, LE */
+        /* Only stda allowed */
+        helper_raise_exception(env, TT_ILL_INSN);
+        return;
     case ASI_DCACHE_DATA: /* D-cache data */
     case ASI_DCACHE_TAG: /* D-cache tag access */
     case ASI_ESTATE_ERROR_EN: /* E-cache error enable */
@@ -2034,8 +2057,11 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
 }
 #endif /* CONFIG_USER_ONLY */
 
-void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi, int rd)
+/* 128-bit LDDA; result returned in QT0.  */
+void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi)
 {
+    uint64_t h, l;
+
     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
         || (cpu_has_hypervisor(env)
             && asi >= 0x30 && asi < 0x80
@@ -2047,44 +2073,82 @@ void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi, int rd)
 
     switch (asi) {
 #if !defined(CONFIG_USER_ONLY)
-    case ASI_NUCLEUS_QUAD_LDD: /* Nucleus quad LDD 128 bit atomic */
-    case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */
+    case ASI_TWINX_AIUP:   /* As if user primary, twinx */
+    case ASI_TWINX_AIUP_L: /* As if user primary, twinx, LE */
         helper_check_align(env, addr, 0xf);
-        if (rd == 0) {
-            env->gregs[1] = cpu_ldq_nucleus(env, addr + 8);
-            if (asi == ASI_NUCLEUS_QUAD_LDD_L) {
-                bswap64s(&env->gregs[1]);
-            }
-        } else if (rd < 8) {
-            env->gregs[rd] = cpu_ldq_nucleus(env, addr);
-            env->gregs[rd + 1] = cpu_ldq_nucleus(env, addr + 8);
-            if (asi == ASI_NUCLEUS_QUAD_LDD_L) {
-                bswap64s(&env->gregs[rd]);
-                bswap64s(&env->gregs[rd + 1]);
-            }
-        } else {
-            env->regwptr[rd - 8] = cpu_ldq_nucleus(env, addr);
-            env->regwptr[rd + 1 - 8] = cpu_ldq_nucleus(env, addr + 8);
-            if (asi == ASI_NUCLEUS_QUAD_LDD_L) {
-                bswap64s(&env->regwptr[rd - 8]);
-                bswap64s(&env->regwptr[rd + 1 - 8]);
+        h = cpu_ldq_user(env, addr);
+        l = cpu_ldq_user(env, addr + 8);
+        break;
+    case ASI_TWINX_AIUS:   /* As if user secondary, twinx */
+    case ASI_TWINX_AIUS_L: /* As if user secondary, twinx, LE */
+        helper_check_align(env, addr, 0xf);
+        h = cpu_ldq_user_secondary(env, addr);
+        l = cpu_ldq_user_secondary(env, addr + 8);
+        break;
+    case ASI_TWINX_REAL:   /* Real address, twinx */
+    case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
+        helper_check_align(env, addr, 0xf);
+        {
+            CPUState *cs = CPU(sparc_env_get_cpu(env));
+            h = ldq_phys(cs->as, addr);
+            l = ldq_phys(cs->as, addr + 8);
+        }
+        break;
+    case ASI_NUCLEUS_QUAD_LDD:
+    case ASI_NUCLEUS_QUAD_LDD_L:
+    case ASI_TWINX_N:  /* Nucleus, twinx */
+    case ASI_TWINX_NL: /* Nucleus, twinx, LE */
+        helper_check_align(env, addr, 0xf);
+        h = cpu_ldq_nucleus(env, addr);
+        l = cpu_ldq_nucleus(env, addr + 8);
+        break;
+    case ASI_TWINX_S: /* Secondary, twinx */
+    case ASI_TWINX_SL: /* Secondary, twinx, LE */
+        if (!cpu_hypervisor_mode(env)) {
+            helper_check_align(env, addr, 0xf);
+            if (env->pstate & PS_PRIV) {
+                h = cpu_ldq_kernel_secondary(env, addr);
+                l = cpu_ldq_kernel_secondary(env, addr + 8);
+            } else {
+                h = cpu_ldq_user_secondary(env, addr);
+                l = cpu_ldq_user_secondary(env, addr + 8);
             }
+            break;
         }
+        /* fallthru */
+    case ASI_TWINX_P:  /* Primary, twinx */
+    case ASI_TWINX_PL: /* Primary, twinx, LE */
+        helper_check_align(env, addr, 0xf);
+        h = cpu_ldq_data(env, addr);
+        l = cpu_ldq_data(env, addr + 8);
         break;
+#else
+    case ASI_TWINX_P:  /* Primary, twinx */
+    case ASI_TWINX_PL: /* Primary, twinx, LE */
+    case ASI_TWINX_S:  /* Primary, twinx */
+    case ASI_TWINX_SL: /* Primary, twinx, LE */
+        /* ??? Should be available, but we need to implement
+           an atomic 128-bit load.  */
+        helper_raise_exception(env, TT_PRIV_ACT);
 #endif
     default:
-        helper_check_align(env, addr, 0x3);
-        if (rd == 0) {
-            env->gregs[1] = helper_ld_asi(env, addr + 4, asi, 4, 0);
-        } else if (rd < 8) {
-            env->gregs[rd] = helper_ld_asi(env, addr, asi, 4, 0);
-            env->gregs[rd + 1] = helper_ld_asi(env, addr + 4, asi, 4, 0);
-        } else {
-            env->regwptr[rd - 8] = helper_ld_asi(env, addr, asi, 4, 0);
-            env->regwptr[rd + 1 - 8] = helper_ld_asi(env, addr + 4, asi, 4, 0);
-        }
-        break;
+        /* Non-twinx asi, so this is the legacy ldda insn, which
+           performs two word sized operations.  */
+        /* ??? The UA2011 manual recommends emulating this with
+           a single 64-bit load.  However, LE asis *are* treated
+           as two 32-bit loads individually byte swapped.  */
+        helper_check_align(env, addr, 0x7);
+        QT0.high = (uint32_t)helper_ld_asi(env, addr, asi, 4, 0);
+        QT0.low = (uint32_t)helper_ld_asi(env, addr + 4, asi, 4, 0);
+        return;
+    }
+
+    if (asi & 8) {
+        h = bswap64(h);
+        l = bswap64(l);
     }
+    QT0.high = h;
+    QT0.low = l;
 }
 
 void helper_ldf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 55364ad..885fa58 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2307,12 +2307,18 @@ static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
-            TCGv_i32 r_rd = tcg_const_i32(rd);
+            TCGv_i64 tmp;
 
             save_state(dc);
-            gen_helper_ldda_asi(cpu_env, addr, r_asi, r_rd);
-            tcg_temp_free_i32(r_rd);
+            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);
         }
         break;
     }
-- 
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 ` Richard Henderson [this message]
2016-07-12 19:02 ` [Qemu-devel] [PULL 14/24] target-sparc: Introduce gen_check_align Richard Henderson
2016-07-12 19:02 ` [Qemu-devel] [PULL 15/24] target-sparc: Directly implement easy ldd/std asis Richard Henderson
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-14-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).