From patchwork Fri Jun 12 09:35:13 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Alrae X-Patchwork-Id: 483445 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 0130C140280 for ; Fri, 12 Jun 2015 19:45:40 +1000 (AEST) Received: from localhost ([::1]:50272 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z3LWs-0003dZ-0B for incoming@patchwork.ozlabs.org; Fri, 12 Jun 2015 05:45:38 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47578) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z3LO5-0005Hf-1j for qemu-devel@nongnu.org; Fri, 12 Jun 2015 05:36:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z3LNw-0006aw-4r for qemu-devel@nongnu.org; Fri, 12 Jun 2015 05:36:32 -0400 Received: from mailapp01.imgtec.com ([195.59.15.196]:46762) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z3LNv-0006aG-JI for qemu-devel@nongnu.org; Fri, 12 Jun 2015 05:36:23 -0400 Received: from KLMAIL01.kl.imgtec.org (unknown [192.168.5.35]) by Websense Email Security Gateway with ESMTPS id D3DD8CB687312 for ; Fri, 12 Jun 2015 10:36:19 +0100 (IST) Received: from lalrae-linux.kl.imgtec.org (192.168.14.163) by KLMAIL01.kl.imgtec.org (192.168.5.35) with Microsoft SMTP Server (TLS) id 14.3.195.1; Fri, 12 Jun 2015 10:36:21 +0100 From: Leon Alrae To: Date: Fri, 12 Jun 2015 10:35:13 +0100 Message-ID: <1434101736-11558-7-git-send-email-leon.alrae@imgtec.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1434101736-11558-1-git-send-email-leon.alrae@imgtec.com> References: <1434101736-11558-1-git-send-email-leon.alrae@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [192.168.14.163] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 195.59.15.196 Cc: Yongbok Kim Subject: [Qemu-devel] [PULL 06/29] 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 From: Yongbok Kim 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 Reviewed-by: Leon Alrae [leon.alrae@imgtec.com: remove unused do_* functions] Signed-off-by: Leon Alrae --- target-mips/helper.h | 10 +++- target-mips/op_helper.c | 143 ++++++++++++++++++++++++++---------------------- target-mips/translate.c | 27 +++++---- 3 files changed, 102 insertions(+), 78 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 dd89068..2fe862a 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -90,10 +90,10 @@ static inline type do_##name(CPUMIPSState *env, target_ulong addr, \ } \ } #endif -HELPER_LD(lbu, ldub, uint8_t) -HELPER_LD(lhu, lduw, uint16_t) HELPER_LD(lw, ldl, int32_t) +#if defined(TARGET_MIPS64) HELPER_LD(ld, ldq, int64_t) +#endif #undef HELPER_LD #if defined(CONFIG_USER_ONLY) @@ -118,9 +118,10 @@ static inline void do_##name(CPUMIPSState *env, target_ulong addr, \ } #endif HELPER_ST(sb, stb, uint8_t) -HELPER_ST(sh, stw, uint16_t) HELPER_ST(sw, stl, uint32_t) +#if defined(TARGET_MIPS64) HELPER_ST(sd, stq, uint64_t) +#endif #undef HELPER_ST target_ulong helper_clo (target_ulong arg1) @@ -3592,72 +3593,82 @@ 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) -{ - 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) +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 - 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; +#define MSA_PAGESPAN(x) \ + ((((x) & ~TARGET_PAGE_MASK) + MSA_WRLEN/8 - 1) >= TARGET_PAGE_SIZE) + +static inline void ensure_writable_pages(CPUMIPSState *env, + target_ulong addr, + int mmu_idx, + uintptr_t retaddr) +{ +#if !defined(CONFIG_USER_ONLY) + target_ulong page_addr; + if (unlikely(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 966996f..fe6bc16 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -18423,32 +18423,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: