From patchwork Tue May 26 16:49:21 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yongbok Kim X-Patchwork-Id: 476640 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 91B7F14016A for ; Wed, 27 May 2015 02:50:13 +1000 (AEST) Received: from localhost ([::1]:49184 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxI3P-0005oT-Qt for incoming@patchwork.ozlabs.org; Tue, 26 May 2015 12:50:11 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44552) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxI2u-0004pk-IL for qemu-devel@nongnu.org; Tue, 26 May 2015 12:49:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YxI2r-0002Be-2x for qemu-devel@nongnu.org; Tue, 26 May 2015 12:49:40 -0400 Received: from mailapp01.imgtec.com ([195.59.15.196]:64211) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxI2q-0002BY-Rn for qemu-devel@nongnu.org; Tue, 26 May 2015 12:49:37 -0400 Received: from KLMAIL01.kl.imgtec.org (unknown [192.168.5.35]) by Websense Email Security Gateway with ESMTPS id 60B77F034BE6; Tue, 26 May 2015 17:49:31 +0100 (IST) Received: from hhmail02.hh.imgtec.org (10.100.10.20) by KLMAIL01.kl.imgtec.org (192.168.5.35) with Microsoft SMTP Server (TLS) id 14.3.195.1; Tue, 26 May 2015 17:49:34 +0100 Received: from localhost.localdomain (192.168.14.192) by hhmail02.hh.imgtec.org (10.100.10.20) with Microsoft SMTP Server (TLS) id 14.3.224.2; Tue, 26 May 2015 17:49:34 +0100 From: Yongbok Kim To: Date: Tue, 26 May 2015 17:49:21 +0100 Message-ID: <1432658961-48553-4-git-send-email-yongbok.kim@imgtec.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1432658961-48553-1-git-send-email-yongbok.kim@imgtec.com> References: <1432658961-48553-1-git-send-email-yongbok.kim@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [192.168.14.192] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 195.59.15.196 Cc: peter.maydell@linaro.org, leon.alrae@imgtec.com, afaerber@suse.de, rth@twiddle.net Subject: [Qemu-devel] [PATCH v5 3/3] target-mips: Misaligned memory accesses for MSA X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org MIPS SIMD Architecture vector loads and stores require misalignment support. MSA Memory access should work as an atomic operation. Therefore, it has to check validity of all addresses for a vector store access if it is spanning into two pages. Separating helper functions for each data format as format is known in translation. To use mmu_idx from cpu_mmu_index() instead of calculating it from hflag. Removing save_cpu_state() call in translation because it is able to use cpu_restore_state() on fault as GETRA() is passed. Signed-off-by: Yongbok Kim --- target-mips/helper.h | 10 +++- target-mips/op_helper.c | 135 +++++++++++++++++++++++++--------------------- target-mips/translate.c | 27 ++++++---- 3 files changed, 98 insertions(+), 74 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index 3bd0b02..bdd5ba5 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -931,5 +931,11 @@ DEF_HELPER_4(msa_ftint_u_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_ffint_s_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_ffint_u_df, void, env, i32, i32, i32) -DEF_HELPER_5(msa_ld_df, void, env, i32, i32, i32, s32) -DEF_HELPER_5(msa_st_df, void, env, i32, i32, i32, s32) +#define MSALDST_PROTO(type) \ +DEF_HELPER_3(msa_ld_ ## type, void, env, i32, tl) \ +DEF_HELPER_3(msa_st_ ## type, void, env, i32, tl) +MSALDST_PROTO(b) +MSALDST_PROTO(h) +MSALDST_PROTO(w) +MSALDST_PROTO(d) +#undef MSALDST_PROTO diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 73a8e45..f44b9bb 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -3558,72 +3558,83 @@ FOP_CONDN_S(sne, (float32_lt(fst1, fst0, &env->active_fpu.fp_status) /* Element-by-element access macros */ #define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df)) -void helper_msa_ld_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t rs, - int32_t s10) -{ - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - target_ulong addr = env->active_tc.gpr[rs] + (s10 << df); - int i; +#if !defined(CONFIG_USER_ONLY) +#define MEMOP_IDX(DF) \ + TCGMemOpIdx oi = make_memop_idx(MO_TE | DF | MO_UNALN, \ + cpu_mmu_index(env)); +#else +#define MEMOP_IDX(DF) +#endif - switch (df) { - case DF_BYTE: - for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { - pwd->b[i] = do_lbu(env, addr + (i << DF_BYTE), - env->hflags & MIPS_HFLAG_KSU); - } - break; - case DF_HALF: - for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { - pwd->h[i] = do_lhu(env, addr + (i << DF_HALF), - env->hflags & MIPS_HFLAG_KSU); - } - break; - case DF_WORD: - for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { - pwd->w[i] = do_lw(env, addr + (i << DF_WORD), - env->hflags & MIPS_HFLAG_KSU); - } - break; - case DF_DOUBLE: - for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { - pwd->d[i] = do_ld(env, addr + (i << DF_DOUBLE), - env->hflags & MIPS_HFLAG_KSU); - } - break; - } +#define MSA_LD_DF(DF, TYPE, LD_INSN, ...) \ +void helper_msa_ld_ ## TYPE(CPUMIPSState *env, uint32_t wd, \ + target_ulong addr) \ +{ \ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ + wr_t wx; \ + int i; \ + MEMOP_IDX(DF) \ + for (i = 0; i < DF_ELEMENTS(DF); i++) { \ + wx.TYPE[i] = LD_INSN(env, addr + (i << DF), ##__VA_ARGS__); \ + } \ + memcpy(pwd, &wx, sizeof(wr_t)); \ } -void helper_msa_st_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t rs, - int32_t s10) +#if !defined(CONFIG_USER_ONLY) +MSA_LD_DF(DF_BYTE, b, helper_ret_ldub_mmu, oi, GETRA()) +MSA_LD_DF(DF_HALF, h, helper_ret_lduw_mmu, oi, GETRA()) +MSA_LD_DF(DF_WORD, w, helper_ret_ldul_mmu, oi, GETRA()) +MSA_LD_DF(DF_DOUBLE, d, helper_ret_ldq_mmu, oi, GETRA()) +#else +MSA_LD_DF(DF_BYTE, b, cpu_ldub_data) +MSA_LD_DF(DF_HALF, h, cpu_lduw_data) +MSA_LD_DF(DF_WORD, w, cpu_ldl_data) +MSA_LD_DF(DF_DOUBLE, d, cpu_ldq_data) +#endif + +static inline void ensure_writable_pages(CPUMIPSState *env, + target_ulong addr, + int mmu_idx, + uintptr_t retaddr) { - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - target_ulong addr = env->active_tc.gpr[rs] + (s10 << df); - int i; +#if !defined(CONFIG_USER_ONLY) +#define MSA_PAGESPAN(x) (unlikely((((x) & ~TARGET_PAGE_MASK) \ + + MSA_WRLEN/8 - 1) >= TARGET_PAGE_SIZE)) + target_ulong page_addr; - switch (df) { - case DF_BYTE: - for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { - do_sb(env, addr + (i << DF_BYTE), pwd->b[i], - env->hflags & MIPS_HFLAG_KSU); - } - break; - case DF_HALF: - for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { - do_sh(env, addr + (i << DF_HALF), pwd->h[i], - env->hflags & MIPS_HFLAG_KSU); - } - break; - case DF_WORD: - for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { - do_sw(env, addr + (i << DF_WORD), pwd->w[i], - env->hflags & MIPS_HFLAG_KSU); - } - break; - case DF_DOUBLE: - for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { - do_sd(env, addr + (i << DF_DOUBLE), pwd->d[i], - env->hflags & MIPS_HFLAG_KSU); - } - break; + if (MSA_PAGESPAN(addr)) { + /* first page */ + probe_write(env, addr, mmu_idx, retaddr); + /* second page */ + page_addr = (addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; + probe_write(env, page_addr, mmu_idx, retaddr); } +#endif +} + +#define MSA_ST_DF(DF, TYPE, ST_INSN, ...) \ +void helper_msa_st_ ## TYPE(CPUMIPSState *env, uint32_t wd, \ + target_ulong addr) \ +{ \ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ + int mmu_idx = cpu_mmu_index(env); \ + int i; \ + MEMOP_IDX(DF) \ + ensure_writable_pages(env, addr, mmu_idx, GETRA()); \ + for (i = 0; i < DF_ELEMENTS(DF); i++) { \ + ST_INSN(env, addr + (i << DF), pwd->TYPE[i], ##__VA_ARGS__); \ + } \ } + +#if !defined(CONFIG_USER_ONLY) +MSA_ST_DF(DF_BYTE, b, helper_ret_stb_mmu, oi, GETRA()) +MSA_ST_DF(DF_HALF, h, helper_ret_stw_mmu, oi, GETRA()) +MSA_ST_DF(DF_WORD, w, helper_ret_stl_mmu, oi, GETRA()) +MSA_ST_DF(DF_DOUBLE, d, helper_ret_stq_mmu, oi, GETRA()) +#else +MSA_ST_DF(DF_BYTE, b, cpu_stb_data) +MSA_ST_DF(DF_HALF, h, cpu_stw_data) +MSA_ST_DF(DF_WORD, w, cpu_stl_data) +MSA_ST_DF(DF_DOUBLE, d, cpu_stq_data) +#endif + diff --git a/target-mips/translate.c b/target-mips/translate.c index a5ea04e..a30b0f8 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -18419,32 +18419,39 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx) uint8_t wd = (ctx->opcode >> 6) & 0x1f; uint8_t df = (ctx->opcode >> 0) & 0x3; - TCGv_i32 tdf = tcg_const_i32(df); TCGv_i32 twd = tcg_const_i32(wd); - TCGv_i32 trs = tcg_const_i32(rs); - TCGv_i32 ts10 = tcg_const_i32(s10); + TCGv taddr = tcg_temp_new(); + gen_base_offset_addr(ctx, taddr, rs, s10 << df); switch (MASK_MSA_MINOR(opcode)) { case OPC_LD_B: + gen_helper_msa_ld_b(cpu_env, twd, taddr); + break; case OPC_LD_H: + gen_helper_msa_ld_h(cpu_env, twd, taddr); + break; case OPC_LD_W: + gen_helper_msa_ld_w(cpu_env, twd, taddr); + break; case OPC_LD_D: - save_cpu_state(ctx, 1); - gen_helper_msa_ld_df(cpu_env, tdf, twd, trs, ts10); + gen_helper_msa_ld_d(cpu_env, twd, taddr); break; case OPC_ST_B: + gen_helper_msa_st_b(cpu_env, twd, taddr); + break; case OPC_ST_H: + gen_helper_msa_st_h(cpu_env, twd, taddr); + break; case OPC_ST_W: + gen_helper_msa_st_w(cpu_env, twd, taddr); + break; case OPC_ST_D: - save_cpu_state(ctx, 1); - gen_helper_msa_st_df(cpu_env, tdf, twd, trs, ts10); + gen_helper_msa_st_d(cpu_env, twd, taddr); break; } tcg_temp_free_i32(twd); - tcg_temp_free_i32(tdf); - tcg_temp_free_i32(trs); - tcg_temp_free_i32(ts10); + tcg_temp_free(taddr); } break; default: