From d2a40a5f6938f30f44b536e997e1e89bb62b971c Mon Sep 17 00:00:00 2001 From: Mateja Marjanovic Date: Tue, 2 Apr 2019 14:11:49 +0200 Subject: target/mips: Make the results of DIV_. the same as on hardware MSA instructions DIV_. when dividing by zero, didn't return the same value when executed on a referent hardware (FPGA MIPS 64 r6, little endian) and when executed on QEMU, which is not a real bug, because the result when dividing by zero is UNPREDICTABLE [1] (page 141, 142). [1] MIPS Architecture for Programmers Volume IV-j: The MIPS64 SIMD Architecture Module, Revision 1.12 Signed-off-by: Mateja Marjanovic Signed-off-by: Aleksandar Markovic Reviewed-by: Aleksandar Markovic Message-Id: <1554207110-9113-2-git-send-email-mateja.marjanovic@rt-rk.com> --- target/mips/msa_helper.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c index c74e3cd..596190b 100644 --- a/target/mips/msa_helper.c +++ b/target/mips/msa_helper.c @@ -641,14 +641,15 @@ static inline int64_t msa_div_s_df(uint32_t df, int64_t arg1, int64_t arg2) if (arg1 == DF_MIN_INT(df) && arg2 == -1) { return DF_MIN_INT(df); } - return arg2 ? arg1 / arg2 : 0; + return arg2 ? arg1 / arg2 + : arg1 >= 0 ? -1 : 1; } static inline int64_t msa_div_u_df(uint32_t df, int64_t arg1, int64_t arg2) { uint64_t u_arg1 = UNSIGNED(arg1, df); uint64_t u_arg2 = UNSIGNED(arg2, df); - return u_arg2 ? u_arg1 / u_arg2 : 0; + return arg2 ? u_arg1 / u_arg2 : -1; } static inline int64_t msa_mod_s_df(uint32_t df, int64_t arg1, int64_t arg2) -- cgit v1.1 From cf122bf8d2732d5d8647901ebaea596668aaaa3a Mon Sep 17 00:00:00 2001 From: Mateja Marjanovic Date: Tue, 2 Apr 2019 14:11:50 +0200 Subject: target/mips: Make the results of MOD_. the same as on hardware MSA instructions MOD_. when dividing by zero, didn't return the same value when executed on a referent hardware (FPGA MIPS 64 r6, little endian) and when executed on QEMU, which is not a real bug, because the result when dividing by zero is UNPREDICTABLE [1] (page 255, 256). [1] MIPS Architecture for Programmers Volume IV-j: The MIPS64 SIMD Architecture Module, Revision 1.12 Signed-off-by: Mateja Marjanovic Signed-off-by: Aleksandar Markovic Reviewed-by: Aleksandar Markovic Message-Id: <1554207110-9113-3-git-send-email-mateja.marjanovic@rt-rk.com> --- target/mips/msa_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c index 596190b..274c6ca 100644 --- a/target/mips/msa_helper.c +++ b/target/mips/msa_helper.c @@ -657,14 +657,14 @@ static inline int64_t msa_mod_s_df(uint32_t df, int64_t arg1, int64_t arg2) if (arg1 == DF_MIN_INT(df) && arg2 == -1) { return 0; } - return arg2 ? arg1 % arg2 : 0; + return arg2 ? arg1 % arg2 : arg1; } static inline int64_t msa_mod_u_df(uint32_t df, int64_t arg1, int64_t arg2) { uint64_t u_arg1 = UNSIGNED(arg1, df); uint64_t u_arg2 = UNSIGNED(arg2, df); - return u_arg2 ? u_arg1 % u_arg2 : 0; + return u_arg2 ? u_arg1 % u_arg2 : u_arg1; } #define SIGNED_EVEN(a, df) \ -- cgit v1.1 From 83be6b54123a8f3c529554139f1d1e43356edf8d Mon Sep 17 00:00:00 2001 From: Mateja Marjanovic Date: Tue, 2 Apr 2019 15:43:21 +0200 Subject: target/mips: Fix MSA instructions LD. on big endian host Fix the case when the host is a big endian machine, and change the approach toward LD. instruction helpers. Signed-off-by: Mateja Marjanovic Signed-off-by: Aleksandar Markovic Reviewed-by: Aleksandar Markovic Message-Id: <1554212605-16457-2-git-send-email-mateja.marjanovic@rt-rk.com> --- target/mips/op_helper.c | 188 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 168 insertions(+), 20 deletions(-) diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index 6d86912..a8ae438 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -4356,31 +4356,179 @@ FOP_CONDN_S(sne, (float32_lt(fst1, fst0, &env->active_fpu.fp_status) #define MEMOP_IDX(DF) #endif -#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_ld_b(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + MEMOP_IDX(DF_BYTE) +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->b[0] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC()); + pwd->b[1] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC()); + pwd->b[2] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC()); + pwd->b[3] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC()); + pwd->b[4] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC()); + pwd->b[5] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC()); + pwd->b[6] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC()); + pwd->b[7] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC()); + pwd->b[8] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC()); + pwd->b[9] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC()); + pwd->b[10] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC()); + pwd->b[11] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC()); + pwd->b[12] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC()); + pwd->b[13] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC()); + pwd->b[14] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC()); + pwd->b[15] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC()); +#else + pwd->b[0] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC()); + pwd->b[1] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC()); + pwd->b[2] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC()); + pwd->b[3] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC()); + pwd->b[4] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC()); + pwd->b[5] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC()); + pwd->b[6] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC()); + pwd->b[7] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC()); + pwd->b[8] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC()); + pwd->b[9] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC()); + pwd->b[10] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC()); + pwd->b[11] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC()); + pwd->b[12] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC()); + pwd->b[13] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC()); + pwd->b[14] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC()); + pwd->b[15] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC()); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->b[0] = cpu_ldub_data(env, addr + (0 << DF_BYTE)); + pwd->b[1] = cpu_ldub_data(env, addr + (1 << DF_BYTE)); + pwd->b[2] = cpu_ldub_data(env, addr + (2 << DF_BYTE)); + pwd->b[3] = cpu_ldub_data(env, addr + (3 << DF_BYTE)); + pwd->b[4] = cpu_ldub_data(env, addr + (4 << DF_BYTE)); + pwd->b[5] = cpu_ldub_data(env, addr + (5 << DF_BYTE)); + pwd->b[6] = cpu_ldub_data(env, addr + (6 << DF_BYTE)); + pwd->b[7] = cpu_ldub_data(env, addr + (7 << DF_BYTE)); + pwd->b[8] = cpu_ldub_data(env, addr + (8 << DF_BYTE)); + pwd->b[9] = cpu_ldub_data(env, addr + (9 << DF_BYTE)); + pwd->b[10] = cpu_ldub_data(env, addr + (10 << DF_BYTE)); + pwd->b[11] = cpu_ldub_data(env, addr + (11 << DF_BYTE)); + pwd->b[12] = cpu_ldub_data(env, addr + (12 << DF_BYTE)); + pwd->b[13] = cpu_ldub_data(env, addr + (13 << DF_BYTE)); + pwd->b[14] = cpu_ldub_data(env, addr + (14 << DF_BYTE)); + pwd->b[15] = cpu_ldub_data(env, addr + (15 << DF_BYTE)); +#else + pwd->b[0] = cpu_ldub_data(env, addr + (7 << DF_BYTE)); + pwd->b[1] = cpu_ldub_data(env, addr + (6 << DF_BYTE)); + pwd->b[2] = cpu_ldub_data(env, addr + (5 << DF_BYTE)); + pwd->b[3] = cpu_ldub_data(env, addr + (4 << DF_BYTE)); + pwd->b[4] = cpu_ldub_data(env, addr + (3 << DF_BYTE)); + pwd->b[5] = cpu_ldub_data(env, addr + (2 << DF_BYTE)); + pwd->b[6] = cpu_ldub_data(env, addr + (1 << DF_BYTE)); + pwd->b[7] = cpu_ldub_data(env, addr + (0 << DF_BYTE)); + pwd->b[8] = cpu_ldub_data(env, addr + (15 << DF_BYTE)); + pwd->b[9] = cpu_ldub_data(env, addr + (14 << DF_BYTE)); + pwd->b[10] = cpu_ldub_data(env, addr + (13 << DF_BYTE)); + pwd->b[11] = cpu_ldub_data(env, addr + (12 << DF_BYTE)); + pwd->b[12] = cpu_ldub_data(env, addr + (11 << DF_BYTE)); + pwd->b[13] = cpu_ldub_data(env, addr + (10 << DF_BYTE)); + pwd->b[14] = cpu_ldub_data(env, addr + (9 << DF_BYTE)); + pwd->b[15] = cpu_ldub_data(env, addr + (8 << DF_BYTE)); +#endif +#endif } +void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + MEMOP_IDX(DF_HALF) #if !defined(CONFIG_USER_ONLY) -MSA_LD_DF(DF_BYTE, b, helper_ret_ldub_mmu, oi, GETPC()) -MSA_LD_DF(DF_HALF, h, helper_ret_lduw_mmu, oi, GETPC()) -MSA_LD_DF(DF_WORD, w, helper_ret_ldul_mmu, oi, GETPC()) -MSA_LD_DF(DF_DOUBLE, d, helper_ret_ldq_mmu, oi, GETPC()) +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->h[0] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC()); + pwd->h[1] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC()); + pwd->h[2] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC()); + pwd->h[3] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC()); + pwd->h[4] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC()); + pwd->h[5] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC()); + pwd->h[6] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC()); + pwd->h[7] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC()); +#else + pwd->h[0] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC()); + pwd->h[1] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC()); + pwd->h[2] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC()); + pwd->h[3] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC()); + pwd->h[4] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC()); + pwd->h[5] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC()); + pwd->h[6] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC()); + pwd->h[7] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC()); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->h[0] = cpu_lduw_data(env, addr + (0 << DF_HALF)); + pwd->h[1] = cpu_lduw_data(env, addr + (1 << DF_HALF)); + pwd->h[2] = cpu_lduw_data(env, addr + (2 << DF_HALF)); + pwd->h[3] = cpu_lduw_data(env, addr + (3 << DF_HALF)); + pwd->h[4] = cpu_lduw_data(env, addr + (4 << DF_HALF)); + pwd->h[5] = cpu_lduw_data(env, addr + (5 << DF_HALF)); + pwd->h[6] = cpu_lduw_data(env, addr + (6 << DF_HALF)); + pwd->h[7] = cpu_lduw_data(env, addr + (7 << DF_HALF)); #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) + pwd->h[0] = cpu_lduw_data(env, addr + (3 << DF_HALF)); + pwd->h[1] = cpu_lduw_data(env, addr + (2 << DF_HALF)); + pwd->h[2] = cpu_lduw_data(env, addr + (1 << DF_HALF)); + pwd->h[3] = cpu_lduw_data(env, addr + (0 << DF_HALF)); + pwd->h[4] = cpu_lduw_data(env, addr + (7 << DF_HALF)); + pwd->h[5] = cpu_lduw_data(env, addr + (6 << DF_HALF)); + pwd->h[6] = cpu_lduw_data(env, addr + (5 << DF_HALF)); + pwd->h[7] = cpu_lduw_data(env, addr + (4 << DF_HALF)); #endif +#endif +} + +void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + MEMOP_IDX(DF_WORD) +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->w[0] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC()); + pwd->w[1] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC()); + pwd->w[2] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC()); + pwd->w[3] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC()); +#else + pwd->w[0] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC()); + pwd->w[1] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC()); + pwd->w[2] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC()); + pwd->w[3] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC()); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->w[0] = cpu_ldl_data(env, addr + (0 << DF_WORD)); + pwd->w[1] = cpu_ldl_data(env, addr + (1 << DF_WORD)); + pwd->w[2] = cpu_ldl_data(env, addr + (2 << DF_WORD)); + pwd->w[3] = cpu_ldl_data(env, addr + (3 << DF_WORD)); +#else + pwd->w[0] = cpu_ldl_data(env, addr + (1 << DF_WORD)); + pwd->w[1] = cpu_ldl_data(env, addr + (0 << DF_WORD)); + pwd->w[2] = cpu_ldl_data(env, addr + (3 << DF_WORD)); + pwd->w[3] = cpu_ldl_data(env, addr + (2 << DF_WORD)); +#endif +#endif +} + +void helper_msa_ld_d(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + MEMOP_IDX(DF_DOUBLE) +#if !defined(CONFIG_USER_ONLY) + pwd->d[0] = helper_ret_ldq_mmu(env, addr + (0 << DF_DOUBLE), oi, GETPC()); + pwd->d[1] = helper_ret_ldq_mmu(env, addr + (1 << DF_DOUBLE), oi, GETPC()); +#else + pwd->d[0] = cpu_ldq_data(env, addr + (0 << DF_DOUBLE)); + pwd->d[1] = cpu_ldq_data(env, addr + (1 << DF_DOUBLE)); +#endif +} #define MSA_PAGESPAN(x) \ ((((x) & ~TARGET_PAGE_MASK) + MSA_WRLEN/8 - 1) >= TARGET_PAGE_SIZE) -- cgit v1.1 From 6decc572dcedbf298ae30f8213b39c8b842a595a Mon Sep 17 00:00:00 2001 From: Mateja Marjanovic Date: Tue, 2 Apr 2019 15:43:22 +0200 Subject: target/mips: Fix MSA instructions ST. on big endian host Fix the case when the host is a big endian machine, and change the approach toward ST. instruction helpers. Signed-off-by: Mateja Marjanovic Signed-off-by: Aleksandar Markovic Reviewed-by: Aleksandar Markovic Message-Id: <1554212605-16457-3-git-send-email-mateja.marjanovic@rt-rk.com> --- target/mips/op_helper.c | 200 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 180 insertions(+), 20 deletions(-) diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index a8ae438..3918027 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -4550,31 +4550,191 @@ static inline void ensure_writable_pages(CPUMIPSState *env, #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, false); \ - int i; \ - MEMOP_IDX(DF) \ - ensure_writable_pages(env, addr, mmu_idx, GETPC()); \ - for (i = 0; i < DF_ELEMENTS(DF); i++) { \ - ST_INSN(env, addr + (i << DF), pwd->TYPE[i], ##__VA_ARGS__); \ - } \ +void helper_msa_st_b(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + int mmu_idx = cpu_mmu_index(env, false); + + MEMOP_IDX(DF_BYTE) + ensure_writable_pages(env, addr, mmu_idx, GETPC()); +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) + helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[0], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[1], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[2], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[3], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[4], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[5], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[6], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[7], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[8], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[9], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[10], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[11], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[12], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[13], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[14], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[15], oi, GETPC()); +#else + helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[0], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[1], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[2], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[3], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[4], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[5], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[6], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[7], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[8], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[9], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[10], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[11], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[12], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[13], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[14], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[15], oi, GETPC()); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[0]); + cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[1]); + cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[2]); + cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[3]); + cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[4]); + cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[5]); + cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[6]); + cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[7]); + cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[8]); + cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[9]); + cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[10]); + cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[11]); + cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[12]); + cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[13]); + cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[14]); + cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[15]); +#else + cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[0]); + cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[1]); + cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[2]); + cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[3]); + cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[4]); + cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[5]); + cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[6]); + cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[7]); + cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[8]); + cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[9]); + cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[10]); + cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[11]); + cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[12]); + cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[13]); + cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[14]); + cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[15]); +#endif +#endif +} + +void helper_msa_st_h(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + int mmu_idx = cpu_mmu_index(env, false); + + MEMOP_IDX(DF_HALF) + ensure_writable_pages(env, addr, mmu_idx, GETPC()); +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) + helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[0], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[1], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[2], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[3], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[4], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[5], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[6], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[7], oi, GETPC()); +#else + helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[0], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[1], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[2], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[3], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[4], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[5], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[6], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[7], oi, GETPC()); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[0]); + cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[1]); + cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[2]); + cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[3]); + cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[4]); + cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[5]); + cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[6]); + cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[7]); +#else + cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[0]); + cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[1]); + cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[2]); + cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[3]); + cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[4]); + cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[5]); + cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[6]); + cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[7]); +#endif +#endif } +void helper_msa_st_w(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + int mmu_idx = cpu_mmu_index(env, false); + + MEMOP_IDX(DF_WORD) + ensure_writable_pages(env, addr, mmu_idx, GETPC()); #if !defined(CONFIG_USER_ONLY) -MSA_ST_DF(DF_BYTE, b, helper_ret_stb_mmu, oi, GETPC()) -MSA_ST_DF(DF_HALF, h, helper_ret_stw_mmu, oi, GETPC()) -MSA_ST_DF(DF_WORD, w, helper_ret_stl_mmu, oi, GETPC()) -MSA_ST_DF(DF_DOUBLE, d, helper_ret_stq_mmu, oi, GETPC()) +#if !defined(HOST_WORDS_BIGENDIAN) + helper_ret_stl_mmu(env, addr + (0 << DF_WORD), oi, GETPC(), pwd->w[0]); + helper_ret_stl_mmu(env, addr + (1 << DF_WORD), oi, GETPC(), pwd->w[1]); + helper_ret_stl_mmu(env, addr + (2 << DF_WORD), oi, GETPC(), pwd->w[2]); + helper_ret_stl_mmu(env, addr + (3 << DF_WORD), oi, GETPC(), pwd->w[3]); #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) + helper_ret_stl_mmu(env, addr + (1 << DF_WORD), oi, GETPC(), pwd->w[0]); + helper_ret_stl_mmu(env, addr + (0 << DF_WORD), oi, GETPC(), pwd->w[1]); + helper_ret_stl_mmu(env, addr + (3 << DF_WORD), oi, GETPC(), pwd->w[2]); + helper_ret_stl_mmu(env, addr + (2 << DF_WORD), oi, GETPC(), pwd->w[3]); #endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[0]); + cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[1]); + cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[2]); + cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[3]); +#else + cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[0]); + cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[1]); + cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[2]); + cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[3]); +#endif +#endif +} + +void helper_msa_st_d(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + int mmu_idx = cpu_mmu_index(env, false); + + MEMOP_IDX(DF_DOUBLE) + ensure_writable_pages(env, addr, mmu_idx, GETPC()); +#if !defined(CONFIG_USER_ONLY) + helper_ret_stq_mmu(env, addr + (0 << DF_DOUBLE), pwd->d[0], oi, GETPC()); + helper_ret_stq_mmu(env, addr + (1 << DF_DOUBLE), pwd->d[1], oi, GETPC()); +#else + cpu_stq_data(env, addr + (0 << DF_DOUBLE), pwd->d[0]); + cpu_stq_data(env, addr + (1 << DF_DOUBLE), pwd->d[1]); +#endif +} void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op) { -- cgit v1.1 From 631c467461496dcf6d6a3e4c3d27a1433e96868e Mon Sep 17 00:00:00 2001 From: Mateja Marjanovic Date: Tue, 2 Apr 2019 15:43:23 +0200 Subject: target/mips: Refactor and fix COPY_S. instructions The old version of the helper for the COPY_S. MSA instructions has been replaced with four helpers that don't use switch, and change the endianness of the given index, when executed on a big endian host. Signed-off-by: Mateja Marjanovic Signed-off-by: Aleksandar Markovic Reviewed-by: Aleksandar Markovic Message-Id: <1554212605-16457-4-git-send-email-mateja.marjanovic@rt-rk.com> --- target/mips/helper.h | 7 +++++- target/mips/msa_helper.c | 62 +++++++++++++++++++++++++++++++++--------------- target/mips/translate.c | 19 ++++++++++++++- 3 files changed, 67 insertions(+), 21 deletions(-) diff --git a/target/mips/helper.h b/target/mips/helper.h index a6d687e..de3a9e0 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -876,7 +876,7 @@ DEF_HELPER_5(msa_hsub_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_copy_s_df, void, env, i32, i32, i32, i32) + DEF_HELPER_5(msa_copy_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_insert_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32) @@ -938,6 +938,11 @@ DEF_HELPER_4(msa_pcnt_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_nloc_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_nlzc_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_s_d, void, env, i32, i32, i32) + DEF_HELPER_4(msa_fclass_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_ftrunc_s_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_ftrunc_u_df, void, env, i32, i32, i32) diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c index 274c6ca..89b3be9 100644 --- a/target/mips/msa_helper.c +++ b/target/mips/msa_helper.c @@ -1249,29 +1249,53 @@ void helper_msa_splati_df(CPUMIPSState *env, uint32_t df, uint32_t wd, msa_splat_df(df, pwd, pws, n); } -void helper_msa_copy_s_df(CPUMIPSState *env, uint32_t df, uint32_t rd, - uint32_t ws, uint32_t n) +void helper_msa_copy_s_b(CPUMIPSState *env, uint32_t rd, + uint32_t ws, uint32_t n) { - n %= DF_ELEMENTS(df); + n %= 16; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 8) { + n = 8 - n - 1; + } else { + n = 24 - n - 1; + } +#endif + env->active_tc.gpr[rd] = (int8_t)env->active_fpu.fpr[ws].wr.b[n]; +} - switch (df) { - case DF_BYTE: - env->active_tc.gpr[rd] = (int8_t)env->active_fpu.fpr[ws].wr.b[n]; - break; - case DF_HALF: - env->active_tc.gpr[rd] = (int16_t)env->active_fpu.fpr[ws].wr.h[n]; - break; - case DF_WORD: - env->active_tc.gpr[rd] = (int32_t)env->active_fpu.fpr[ws].wr.w[n]; - break; -#ifdef TARGET_MIPS64 - case DF_DOUBLE: - env->active_tc.gpr[rd] = (int64_t)env->active_fpu.fpr[ws].wr.d[n]; - break; +void helper_msa_copy_s_h(CPUMIPSState *env, uint32_t rd, + uint32_t ws, uint32_t n) +{ + n %= 8; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 4) { + n = 4 - n - 1; + } else { + n = 12 - n - 1; + } #endif - default: - assert(0); + env->active_tc.gpr[rd] = (int16_t)env->active_fpu.fpr[ws].wr.h[n]; +} + +void helper_msa_copy_s_w(CPUMIPSState *env, uint32_t rd, + uint32_t ws, uint32_t n) +{ + n %= 4; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 2) { + n = 2 - n - 1; + } else { + n = 6 - n - 1; } +#endif + env->active_tc.gpr[rd] = (int32_t)env->active_fpu.fpr[ws].wr.w[n]; +} + +void helper_msa_copy_s_d(CPUMIPSState *env, uint32_t rd, + uint32_t ws, uint32_t n) +{ + n %= 2; + env->active_tc.gpr[rd] = (int64_t)env->active_fpu.fpr[ws].wr.d[n]; } void helper_msa_copy_u_df(CPUMIPSState *env, uint32_t df, uint32_t rd, diff --git a/target/mips/translate.c b/target/mips/translate.c index f96c0d0..c65d19e 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -28301,7 +28301,24 @@ static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df, switch (MASK_MSA_ELM(ctx->opcode)) { case OPC_COPY_S_df: if (likely(wd != 0)) { - gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn); + switch (df) { + case DF_BYTE: + gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn); + break; + case DF_HALF: + gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn); + break; + case DF_WORD: + gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn); + break; +#if defined(TARGET_MIPS64) + case DF_DOUBLE: + gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn); + break; +#endif + default: + assert(0); + } } break; case OPC_COPY_U_df: -- cgit v1.1 From 41d288582782cf8d63241ecb6efa1e4160fe78f7 Mon Sep 17 00:00:00 2001 From: Mateja Marjanovic Date: Tue, 2 Apr 2019 15:43:24 +0200 Subject: target/mips: Refactor and fix COPY_U. instructions The old version of the helper for the COPY_U. MSA instructions has been replaced with four helpers that don't use switch, and change the endianness of the given index, when executed on a big endian host. Signed-off-by: Mateja Marjanovic Signed-off-by: Aleksandar Markovic Reviewed-by: Aleksandar Markovic Message-Id: <1554212605-16457-5-git-send-email-mateja.marjanovic@rt-rk.com> --- target/mips/helper.h | 4 +++- target/mips/msa_helper.c | 55 +++++++++++++++++++++++++++++++----------------- target/mips/translate.c | 21 +++++++++++++++++- 3 files changed, 59 insertions(+), 21 deletions(-) diff --git a/target/mips/helper.h b/target/mips/helper.h index de3a9e0..c4a77e2 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -877,7 +877,6 @@ DEF_HELPER_5(msa_hsub_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_copy_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_insert_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32) DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32) @@ -942,6 +941,9 @@ DEF_HELPER_4(msa_copy_s_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_copy_s_h, void, env, i32, i32, i32) DEF_HELPER_4(msa_copy_s_w, void, env, i32, i32, i32) DEF_HELPER_4(msa_copy_s_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_u_w, void, env, i32, i32, i32) DEF_HELPER_4(msa_fclass_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_ftrunc_s_df, void, env, i32, i32, i32) diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c index 89b3be9..52680fe 100644 --- a/target/mips/msa_helper.c +++ b/target/mips/msa_helper.c @@ -1298,29 +1298,46 @@ void helper_msa_copy_s_d(CPUMIPSState *env, uint32_t rd, env->active_tc.gpr[rd] = (int64_t)env->active_fpu.fpr[ws].wr.d[n]; } -void helper_msa_copy_u_df(CPUMIPSState *env, uint32_t df, uint32_t rd, - uint32_t ws, uint32_t n) +void helper_msa_copy_u_b(CPUMIPSState *env, uint32_t rd, + uint32_t ws, uint32_t n) { - n %= DF_ELEMENTS(df); + n %= 16; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 8) { + n = 8 - n - 1; + } else { + n = 24 - n - 1; + } +#endif + env->active_tc.gpr[rd] = (uint8_t)env->active_fpu.fpr[ws].wr.b[n]; +} - switch (df) { - case DF_BYTE: - env->active_tc.gpr[rd] = (uint8_t)env->active_fpu.fpr[ws].wr.b[n]; - break; - case DF_HALF: - env->active_tc.gpr[rd] = (uint16_t)env->active_fpu.fpr[ws].wr.h[n]; - break; - case DF_WORD: - env->active_tc.gpr[rd] = (uint32_t)env->active_fpu.fpr[ws].wr.w[n]; - break; -#ifdef TARGET_MIPS64 - case DF_DOUBLE: - env->active_tc.gpr[rd] = (uint64_t)env->active_fpu.fpr[ws].wr.d[n]; - break; +void helper_msa_copy_u_h(CPUMIPSState *env, uint32_t rd, + uint32_t ws, uint32_t n) +{ + n %= 8; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 4) { + n = 4 - n - 1; + } else { + n = 12 - n - 1; + } #endif - default: - assert(0); + env->active_tc.gpr[rd] = (uint16_t)env->active_fpu.fpr[ws].wr.h[n]; +} + +void helper_msa_copy_u_w(CPUMIPSState *env, uint32_t rd, + uint32_t ws, uint32_t n) +{ + n %= 4; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 2) { + n = 2 - n - 1; + } else { + n = 6 - n - 1; } +#endif + env->active_tc.gpr[rd] = (uint32_t)env->active_fpu.fpr[ws].wr.w[n]; } void helper_msa_insert_df(CPUMIPSState *env, uint32_t df, uint32_t wd, diff --git a/target/mips/translate.c b/target/mips/translate.c index c65d19e..68ea6ee 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -28297,6 +28297,11 @@ static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df, generate_exception_end(ctx, EXCP_RI); break; } + if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) && + (df == DF_WORD)) { + generate_exception_end(ctx, EXCP_RI); + break; + } #endif switch (MASK_MSA_ELM(ctx->opcode)) { case OPC_COPY_S_df: @@ -28323,7 +28328,21 @@ static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df, break; case OPC_COPY_U_df: if (likely(wd != 0)) { - gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn); + switch (df) { + case DF_BYTE: + gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn); + break; + case DF_HALF: + gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn); + break; +#if defined(TARGET_MIPS64) + case DF_WORD: + gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn); + break; +#endif + default: + assert(0); + } } break; case OPC_INSERT_df: -- cgit v1.1 From c1c9a10fb1f7a6782711817c167a2c20b000fc12 Mon Sep 17 00:00:00 2001 From: Mateja Marjanovic Date: Tue, 2 Apr 2019 15:43:25 +0200 Subject: target/mips: Refactor and fix INSERT. instructions The old version of the helper for the INSERT. MSA instructions has been replaced with four helpers that don't use switch, and change the endianness of the given index, when executed on a big endian host. Signed-off-by: Mateja Marjanovic Signed-off-by: Aleksandar Markovic Reviewed-by: Aleksandar Markovic Message-Id: <1554212605-16457-6-git-send-email-mateja.marjanovic@rt-rk.com> --- target/mips/helper.h | 5 +++- target/mips/msa_helper.c | 65 ++++++++++++++++++++++++++++++++++++------------ target/mips/translate.c | 19 +++++++++++++- 3 files changed, 71 insertions(+), 18 deletions(-) diff --git a/target/mips/helper.h b/target/mips/helper.h index c4a77e2..2863f60 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -877,7 +877,6 @@ DEF_HELPER_5(msa_hsub_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_insert_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32) DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32) DEF_HELPER_2(msa_cfcmsa, tl, env, i32) @@ -944,6 +943,10 @@ DEF_HELPER_4(msa_copy_s_d, void, env, i32, i32, i32) DEF_HELPER_4(msa_copy_u_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_copy_u_h, void, env, i32, i32, i32) DEF_HELPER_4(msa_copy_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_insert_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_insert_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_insert_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_insert_d, void, env, i32, i32, i32) DEF_HELPER_4(msa_fclass_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_ftrunc_s_df, void, env, i32, i32, i32) diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c index 52680fe..ee1b1fa 100644 --- a/target/mips/msa_helper.c +++ b/target/mips/msa_helper.c @@ -1340,28 +1340,61 @@ void helper_msa_copy_u_w(CPUMIPSState *env, uint32_t rd, env->active_tc.gpr[rd] = (uint32_t)env->active_fpu.fpr[ws].wr.w[n]; } -void helper_msa_insert_df(CPUMIPSState *env, uint32_t df, uint32_t wd, +void helper_msa_insert_b(CPUMIPSState *env, uint32_t wd, uint32_t rs_num, uint32_t n) { wr_t *pwd = &(env->active_fpu.fpr[wd].wr); target_ulong rs = env->active_tc.gpr[rs_num]; + n %= 16; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 8) { + n = 8 - n - 1; + } else { + n = 24 - n - 1; + } +#endif + pwd->b[n] = (int8_t)rs; +} - switch (df) { - case DF_BYTE: - pwd->b[n] = (int8_t)rs; - break; - case DF_HALF: - pwd->h[n] = (int16_t)rs; - break; - case DF_WORD: - pwd->w[n] = (int32_t)rs; - break; - case DF_DOUBLE: - pwd->d[n] = (int64_t)rs; - break; - default: - assert(0); +void helper_msa_insert_h(CPUMIPSState *env, uint32_t wd, + uint32_t rs_num, uint32_t n) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + target_ulong rs = env->active_tc.gpr[rs_num]; + n %= 8; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 4) { + n = 4 - n - 1; + } else { + n = 12 - n - 1; + } +#endif + pwd->h[n] = (int16_t)rs; +} + +void helper_msa_insert_w(CPUMIPSState *env, uint32_t wd, + uint32_t rs_num, uint32_t n) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + target_ulong rs = env->active_tc.gpr[rs_num]; + n %= 4; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 2) { + n = 2 - n - 1; + } else { + n = 6 - n - 1; } +#endif + pwd->w[n] = (int32_t)rs; +} + +void helper_msa_insert_d(CPUMIPSState *env, uint32_t wd, + uint32_t rs_num, uint32_t n) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + target_ulong rs = env->active_tc.gpr[rs_num]; + n %= 2; + pwd->d[n] = (int64_t)rs; } void helper_msa_insve_df(CPUMIPSState *env, uint32_t df, uint32_t wd, diff --git a/target/mips/translate.c b/target/mips/translate.c index 68ea6ee..dd706ad 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -28346,7 +28346,24 @@ static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df, } break; case OPC_INSERT_df: - gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn); + switch (df) { + case DF_BYTE: + gen_helper_msa_insert_b(cpu_env, twd, tws, tn); + break; + case DF_HALF: + gen_helper_msa_insert_h(cpu_env, twd, tws, tn); + break; + case DF_WORD: + gen_helper_msa_insert_w(cpu_env, twd, tws, tn); + break; +#if defined(TARGET_MIPS64) + case DF_DOUBLE: + gen_helper_msa_insert_d(cpu_env, twd, tws, tn); + break; +#endif + default: + assert(0); + } break; } break; -- cgit v1.1 From 7353113fa482e697a77575086a41f429a01f8dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jerm=C3=A1=C5=99?= Date: Fri, 17 May 2019 14:35:33 +0200 Subject: mips: Decide to map PAGE_EXEC in map_address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit addresses QEMU Bug #1825311: mips_cpu_handle_mmu_fault renders all accessed pages executable It allows finer-grained control over whether the accessed page should be executable by moving the decision to the underlying map_address function, which has more information for this. As a result, pages that have the XI bit set in the TLB and are accessed for read/write, don't suddenly end up being executable. Fixes: https://bugs.launchpad.net/qemu/+bug/1825311 Fixes: 2fb58b73746e ('target-mips: add RI and XI fields to TLB entry') Signed-off-by: Jakub Jermář Signed-off-by: Aleksandar Markovic Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20190517123533.868479-1-jakub.jermar@kernkonzept.com> --- target/mips/helper.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/target/mips/helper.c b/target/mips/helper.c index 9799f2e..68e44df 100644 --- a/target/mips/helper.c +++ b/target/mips/helper.c @@ -43,7 +43,7 @@ int no_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong address, int rw, int access_type) { *physical = address; - *prot = PAGE_READ | PAGE_WRITE; + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; return TLBRET_MATCH; } @@ -61,7 +61,7 @@ int fixed_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, else *physical = address; - *prot = PAGE_READ | PAGE_WRITE; + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; return TLBRET_MATCH; } @@ -101,6 +101,9 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, *prot = PAGE_READ; if (n ? tlb->D1 : tlb->D0) *prot |= PAGE_WRITE; + if (!(n ? tlb->XI1 : tlb->XI0)) { + *prot |= PAGE_EXEC; + } return TLBRET_MATCH; } return TLBRET_DIRTY; @@ -182,7 +185,7 @@ static int get_seg_physical_address(CPUMIPSState *env, hwaddr *physical, } else { /* The segment is unmapped */ *physical = physical_base | (real_address & segmask); - *prot = PAGE_READ | PAGE_WRITE; + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; return TLBRET_MATCH; } } @@ -907,7 +910,7 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, } if (ret == TLBRET_MATCH) { tlb_set_page(cs, address & TARGET_PAGE_MASK, - physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, + physical & TARGET_PAGE_MASK, prot, mmu_idx, TARGET_PAGE_SIZE); return true; } @@ -927,7 +930,7 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, access_type, mips_access_type, mmu_idx); if (ret == TLBRET_MATCH) { tlb_set_page(cs, address & TARGET_PAGE_MASK, - physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, + physical & TARGET_PAGE_MASK, prot, mmu_idx, TARGET_PAGE_SIZE); return true; } -- cgit v1.1 From 86e636951ddce2bb3a82fcaad5abc3779ba4f7ab Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Thu, 23 May 2019 19:54:13 +0200 Subject: linux-user: fix __NR_semtimedop undeclared error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In current code, __NR_msgrcv and__NR_semtimedop are supposed to be defined if __NR_msgsnd is defined. But linux headers 5.2-rc1 for MIPS define __NR_msgsnd without defining __NR_semtimedop and it breaks the QEMU build. __NR_semtimedop is defined in asm-mips/unistd_n64.h and asm-mips/unistd_n32.h but not in asm-mips/unistd_o32.h. Commit d9cb4336159a ("linux headers: update against Linux 5.2-rc1") has updated asm-mips/unistd_o32.h and added __NR_msgsnd but not __NR_semtimedop. It introduces __NR_semtimedop_time64 instead. This patch fixes the problem by checking for each __NR_XXX symbol before defining the corresponding syscall. Fixes: d9cb4336159a ("linux headers: update against Linux 5.2-rc1") Reported-by: Philippe Mathieu-Daudé Signed-off-by: Laurent Vivier Signed-off-by: Aleksandar Markovic Tested-by: Philippe Mathieu-Daudé Reviewed-by: Cornelia Huck Reviewed-by: Alex Bennée Tested-by: Alex Bennée Message-Id: <20190523175413.14448-1-laurent@vivier.eu> --- linux-user/syscall.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 5521258..5e29e67 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -763,14 +763,7 @@ safe_syscall2(int, nanosleep, const struct timespec *, req, safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags, const struct timespec *, req, struct timespec *, rem) #endif -#ifdef __NR_msgsnd -safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz, - int, flags) -safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz, - long, msgtype, int, flags) -safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops, - unsigned, nsops, const struct timespec *, timeout) -#else +#if !defined(__NR_msgsnd) || !defined(__NR_msgrcv) || !defined(__NR_semtimedop) /* This host kernel architecture uses a single ipc syscall; fake up * wrappers for the sub-operations to hide this implementation detail. * Annoyingly we can't include linux/ipc.h to get the constant definitions @@ -785,14 +778,29 @@ safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops, safe_syscall6(int, ipc, int, call, long, first, long, second, long, third, void *, ptr, long, fifth) +#endif +#ifdef __NR_msgsnd +safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz, + int, flags) +#else static int safe_msgsnd(int msgid, const void *msgp, size_t sz, int flags) { return safe_ipc(Q_IPCCALL(0, Q_MSGSND), msgid, sz, flags, (void *)msgp, 0); } +#endif +#ifdef __NR_msgrcv +safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz, + long, msgtype, int, flags) +#else static int safe_msgrcv(int msgid, void *msgp, size_t sz, long type, int flags) { return safe_ipc(Q_IPCCALL(1, Q_MSGRCV), msgid, sz, flags, msgp, type); } +#endif +#ifdef __NR_semtimedop +safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops, + unsigned, nsops, const struct timespec *, timeout) +#else static int safe_semtimedop(int semid, struct sembuf *tsops, unsigned nsops, const struct timespec *timeout) { -- cgit v1.1 From 8ebf2e1a68408068c0bcd0d02a783fd12f6a9cb5 Mon Sep 17 00:00:00 2001 From: Jules Irenge Date: Sat, 13 Apr 2019 21:28:17 +0100 Subject: target/mips: add or remove space to fix checkpatch errors Add or remove space to fix errors issued by checkpatch.pl tool "ERROR: spaces required around that..." "ERROR: space required after that..." "ERROR: space required before the open parenthesis" "ERROR: space required after that..." "ERROR: space prohibited between function name and open parenthesis" "ERROR: code indent should never use tabs" "ERROR: line over 90 characters" within "target/mips/cpu.h" file. Signed-off-by: Jules Irenge Signed-off-by: Aleksandar Markovic Reviewed-by: Aleksandar Markovic Message-Id: <20190413202818.13622-2-jbi.octave@gmail.com> --- target/mips/cpu.h | 175 +++++++++++++++++++++++++++++------------------------- 1 file changed, 94 insertions(+), 81 deletions(-) diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 1f41cf6..71dd403 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -22,10 +22,10 @@ typedef struct CPUMIPSTLBContext CPUMIPSTLBContext; typedef union wr_t wr_t; union wr_t { - int8_t b[MSA_WRLEN/8]; - int16_t h[MSA_WRLEN/16]; - int32_t w[MSA_WRLEN/32]; - int64_t d[MSA_WRLEN/64]; + int8_t b[MSA_WRLEN / 8]; + int16_t h[MSA_WRLEN / 16]; + int32_t w[MSA_WRLEN / 32]; + int64_t d[MSA_WRLEN / 64]; }; typedef union fpr_t fpr_t; @@ -71,16 +71,29 @@ struct CPUMIPSFPUContext { #define FCR31_FS 24 #define FCR31_ABS2008 19 #define FCR31_NAN2008 18 -#define SET_FP_COND(num,env) do { ((env).fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0) -#define CLEAR_FP_COND(num,env) do { ((env).fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0) -#define GET_FP_COND(env) ((((env).fcr31 >> 24) & 0xfe) | (((env).fcr31 >> 23) & 0x1)) +#define SET_FP_COND(num, env) do { ((env).fcr31) |= \ + ((num) ? (1 << ((num) + 24)) : \ + (1 << 23)); \ + } while (0) +#define CLEAR_FP_COND(num, env) do { ((env).fcr31) &= \ + ~((num) ? (1 << ((num) + 24)) : \ + (1 << 23)); \ + } while (0) +#define GET_FP_COND(env) ((((env).fcr31 >> 24) & 0xfe) | \ + (((env).fcr31 >> 23) & 0x1)) #define GET_FP_CAUSE(reg) (((reg) >> 12) & 0x3f) #define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f) #define GET_FP_FLAGS(reg) (((reg) >> 2) & 0x1f) -#define SET_FP_CAUSE(reg,v) do { (reg) = ((reg) & ~(0x3f << 12)) | ((v & 0x3f) << 12); } while(0) -#define SET_FP_ENABLE(reg,v) do { (reg) = ((reg) & ~(0x1f << 7)) | ((v & 0x1f) << 7); } while(0) -#define SET_FP_FLAGS(reg,v) do { (reg) = ((reg) & ~(0x1f << 2)) | ((v & 0x1f) << 2); } while(0) -#define UPDATE_FP_FLAGS(reg,v) do { (reg) |= ((v & 0x1f) << 2); } while(0) +#define SET_FP_CAUSE(reg, v) do { (reg) = ((reg) & ~(0x3f << 12)) | \ + ((v & 0x3f) << 12); \ + } while (0) +#define SET_FP_ENABLE(reg, v) do { (reg) = ((reg) & ~(0x1f << 7)) | \ + ((v & 0x1f) << 7); \ + } while (0) +#define SET_FP_FLAGS(reg, v) do { (reg) = ((reg) & ~(0x1f << 2)) | \ + ((v & 0x1f) << 2); \ + } while (0) +#define UPDATE_FP_FLAGS(reg, v) do { (reg) |= ((v & 0x1f) << 2); } while (0) #define FP_INEXACT 1 #define FP_UNDERFLOW 2 #define FP_OVERFLOW 4 @@ -95,25 +108,25 @@ struct CPUMIPSFPUContext { typedef struct CPUMIPSMVPContext CPUMIPSMVPContext; struct CPUMIPSMVPContext { int32_t CP0_MVPControl; -#define CP0MVPCo_CPA 3 -#define CP0MVPCo_STLB 2 -#define CP0MVPCo_VPC 1 -#define CP0MVPCo_EVP 0 +#define CP0MVPCo_CPA 3 +#define CP0MVPCo_STLB 2 +#define CP0MVPCo_VPC 1 +#define CP0MVPCo_EVP 0 int32_t CP0_MVPConf0; -#define CP0MVPC0_M 31 -#define CP0MVPC0_TLBS 29 -#define CP0MVPC0_GS 28 -#define CP0MVPC0_PCP 27 -#define CP0MVPC0_PTLBE 16 -#define CP0MVPC0_TCA 15 -#define CP0MVPC0_PVPE 10 -#define CP0MVPC0_PTC 0 +#define CP0MVPC0_M 31 +#define CP0MVPC0_TLBS 29 +#define CP0MVPC0_GS 28 +#define CP0MVPC0_PCP 27 +#define CP0MVPC0_PTLBE 16 +#define CP0MVPC0_TCA 15 +#define CP0MVPC0_PVPE 10 +#define CP0MVPC0_PTC 0 int32_t CP0_MVPConf1; -#define CP0MVPC1_CIM 31 -#define CP0MVPC1_CIF 30 -#define CP0MVPC1_PCX 20 -#define CP0MVPC1_PCP2 10 -#define CP0MVPC1_PCP1 0 +#define CP0MVPC1_CIM 31 +#define CP0MVPC1_CIF 30 +#define CP0MVPC1_PCX 20 +#define CP0MVPC1_PCP2 10 +#define CP0MVPC1_PCP1 0 }; typedef struct mips_def_t mips_def_t; @@ -481,44 +494,44 @@ struct CPUMIPSState { */ int32_t CP0_Random; int32_t CP0_VPEControl; -#define CP0VPECo_YSI 21 -#define CP0VPECo_GSI 20 -#define CP0VPECo_EXCPT 16 -#define CP0VPECo_TE 15 -#define CP0VPECo_TargTC 0 +#define CP0VPECo_YSI 21 +#define CP0VPECo_GSI 20 +#define CP0VPECo_EXCPT 16 +#define CP0VPECo_TE 15 +#define CP0VPECo_TargTC 0 int32_t CP0_VPEConf0; -#define CP0VPEC0_M 31 -#define CP0VPEC0_XTC 21 -#define CP0VPEC0_TCS 19 -#define CP0VPEC0_SCS 18 -#define CP0VPEC0_DSC 17 -#define CP0VPEC0_ICS 16 -#define CP0VPEC0_MVP 1 -#define CP0VPEC0_VPA 0 +#define CP0VPEC0_M 31 +#define CP0VPEC0_XTC 21 +#define CP0VPEC0_TCS 19 +#define CP0VPEC0_SCS 18 +#define CP0VPEC0_DSC 17 +#define CP0VPEC0_ICS 16 +#define CP0VPEC0_MVP 1 +#define CP0VPEC0_VPA 0 int32_t CP0_VPEConf1; -#define CP0VPEC1_NCX 20 -#define CP0VPEC1_NCP2 10 -#define CP0VPEC1_NCP1 0 +#define CP0VPEC1_NCX 20 +#define CP0VPEC1_NCP2 10 +#define CP0VPEC1_NCP1 0 target_ulong CP0_YQMask; target_ulong CP0_VPESchedule; target_ulong CP0_VPEScheFBack; int32_t CP0_VPEOpt; -#define CP0VPEOpt_IWX7 15 -#define CP0VPEOpt_IWX6 14 -#define CP0VPEOpt_IWX5 13 -#define CP0VPEOpt_IWX4 12 -#define CP0VPEOpt_IWX3 11 -#define CP0VPEOpt_IWX2 10 -#define CP0VPEOpt_IWX1 9 -#define CP0VPEOpt_IWX0 8 -#define CP0VPEOpt_DWX7 7 -#define CP0VPEOpt_DWX6 6 -#define CP0VPEOpt_DWX5 5 -#define CP0VPEOpt_DWX4 4 -#define CP0VPEOpt_DWX3 3 -#define CP0VPEOpt_DWX2 2 -#define CP0VPEOpt_DWX1 1 -#define CP0VPEOpt_DWX0 0 +#define CP0VPEOpt_IWX7 15 +#define CP0VPEOpt_IWX6 14 +#define CP0VPEOpt_IWX5 13 +#define CP0VPEOpt_IWX4 12 +#define CP0VPEOpt_IWX3 11 +#define CP0VPEOpt_IWX2 10 +#define CP0VPEOpt_IWX1 9 +#define CP0VPEOpt_IWX0 8 +#define CP0VPEOpt_DWX7 7 +#define CP0VPEOpt_DWX6 6 +#define CP0VPEOpt_DWX5 5 +#define CP0VPEOpt_DWX4 4 +#define CP0VPEOpt_DWX3 3 +#define CP0VPEOpt_DWX2 2 +#define CP0VPEOpt_DWX1 1 +#define CP0VPEOpt_DWX0 0 /* * CP0 Register 2 */ @@ -625,33 +638,33 @@ struct CPUMIPSState { #define CP0PC_PSN 0 /* 5..0 */ int32_t CP0_SRSConf0_rw_bitmask; int32_t CP0_SRSConf0; -#define CP0SRSC0_M 31 -#define CP0SRSC0_SRS3 20 -#define CP0SRSC0_SRS2 10 -#define CP0SRSC0_SRS1 0 +#define CP0SRSC0_M 31 +#define CP0SRSC0_SRS3 20 +#define CP0SRSC0_SRS2 10 +#define CP0SRSC0_SRS1 0 int32_t CP0_SRSConf1_rw_bitmask; int32_t CP0_SRSConf1; -#define CP0SRSC1_M 31 -#define CP0SRSC1_SRS6 20 -#define CP0SRSC1_SRS5 10 -#define CP0SRSC1_SRS4 0 +#define CP0SRSC1_M 31 +#define CP0SRSC1_SRS6 20 +#define CP0SRSC1_SRS5 10 +#define CP0SRSC1_SRS4 0 int32_t CP0_SRSConf2_rw_bitmask; int32_t CP0_SRSConf2; -#define CP0SRSC2_M 31 -#define CP0SRSC2_SRS9 20 -#define CP0SRSC2_SRS8 10 -#define CP0SRSC2_SRS7 0 +#define CP0SRSC2_M 31 +#define CP0SRSC2_SRS9 20 +#define CP0SRSC2_SRS8 10 +#define CP0SRSC2_SRS7 0 int32_t CP0_SRSConf3_rw_bitmask; int32_t CP0_SRSConf3; -#define CP0SRSC3_M 31 -#define CP0SRSC3_SRS12 20 -#define CP0SRSC3_SRS11 10 -#define CP0SRSC3_SRS10 0 +#define CP0SRSC3_M 31 +#define CP0SRSC3_SRS12 20 +#define CP0SRSC3_SRS11 10 +#define CP0SRSC3_SRS10 0 int32_t CP0_SRSConf4_rw_bitmask; int32_t CP0_SRSConf4; -#define CP0SRSC4_SRS15 20 -#define CP0SRSC4_SRS14 10 -#define CP0SRSC4_SRS13 0 +#define CP0SRSC4_SRS15 20 +#define CP0SRSC4_SRS14 10 +#define CP0SRSC4_SRS13 0 /* * CP0 Register 7 */ @@ -1090,7 +1103,7 @@ static inline int hflags_mmu_index(uint32_t hflags) } } -static inline int cpu_mmu_index (CPUMIPSState *env, bool ifetch) +static inline int cpu_mmu_index(CPUMIPSState *env, bool ifetch) { return hflags_mmu_index(env->hflags); } @@ -1182,7 +1195,7 @@ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level); void itc_reconfigure(struct MIPSITUState *tag); /* helper.c */ -target_ulong exception_resume_pc (CPUMIPSState *env); +target_ulong exception_resume_pc(CPUMIPSState *env); static inline void restore_snan_bit_mode(CPUMIPSState *env) { -- cgit v1.1 From 9e72f33d854b0a817c0d2fe4bca693b76f0fe776 Mon Sep 17 00:00:00 2001 From: Jules Irenge Date: Sat, 13 Apr 2019 21:28:18 +0100 Subject: target/mips: realign comments to fix checkpatch warnings Realign comments to fix warnings issued by checkpatc.pl tool "WARNING: Block comments use a leading /* on a separate line" within "target/mips/cpu.h" file. Signed-off-by: Jules Irenge Signed-off-by: Aleksandar Markovic Reviewed-by: Aleksandar Markovic Message-Id: <20190413202818.13622-3-jbi.octave@gmail.com> --- target/mips/cpu.h | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 71dd403..06a8ed4 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -37,7 +37,8 @@ union fpr_t { /* FPU/MSA register mapping is not tested on big-endian hosts. */ wr_t wr; /* vector data */ }; -/* define FP_ENDIAN_IDX to access the same location +/* + *define FP_ENDIAN_IDX to access the same location * in the fpr_t union regardless of the host endianness */ #if defined(HOST_WORDS_BIGENDIAN) @@ -976,9 +977,11 @@ struct CPUMIPSState { /* TMASK defines different execution modes */ #define MIPS_HFLAG_TMASK 0x1F5807FF #define MIPS_HFLAG_MODE 0x00007 /* execution modes */ - /* The KSU flags must be the lowest bits in hflags. The flag order - must be the same as defined for CP0 Status. This allows to use - the bits as the value of mmu_idx. */ + /* + * The KSU flags must be the lowest bits in hflags. The flag order + * must be the same as defined for CP0 Status. This allows to use + * the bits as the value of mmu_idx. + */ #define MIPS_HFLAG_KSU 0x00003 /* kernel/supervisor/user mode mask */ #define MIPS_HFLAG_UM 0x00002 /* user mode flag */ #define MIPS_HFLAG_SM 0x00001 /* supervisor mode flag */ @@ -988,18 +991,22 @@ struct CPUMIPSState { #define MIPS_HFLAG_CP0 0x00010 /* CP0 enabled */ #define MIPS_HFLAG_FPU 0x00020 /* FPU enabled */ #define MIPS_HFLAG_F64 0x00040 /* 64-bit FPU enabled */ - /* True if the MIPS IV COP1X instructions can be used. This also - controls the non-COP1X instructions RECIP.S, RECIP.D, RSQRT.S - and RSQRT.D. */ + /* + * True if the MIPS IV COP1X instructions can be used. This also + * controls the non-COP1X instructions RECIP.S, RECIP.D, RSQRT.S + * and RSQRT.D. + */ #define MIPS_HFLAG_COP1X 0x00080 /* COP1X instructions enabled */ #define MIPS_HFLAG_RE 0x00100 /* Reversed endianness */ #define MIPS_HFLAG_AWRAP 0x00200 /* 32-bit compatibility address wrapping */ #define MIPS_HFLAG_M16 0x00400 /* MIPS16 mode flag */ #define MIPS_HFLAG_M16_SHIFT 10 - /* If translation is interrupted between the branch instruction and + /* + * If translation is interrupted between the branch instruction and * the delay slot, record what type of branch it is so that we can * resume translation properly. It might be possible to reduce - * this from three bits to two. */ + * this from three bits to two. + */ #define MIPS_HFLAG_BMASK_BASE 0x803800 #define MIPS_HFLAG_B 0x00800 /* Unconditional branch */ #define MIPS_HFLAG_BC 0x01000 /* Conditional branch */ @@ -1086,8 +1093,10 @@ void mips_cpu_list(void); extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env); extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env); -/* MMU modes definitions. We carefully match the indices with our - hflags layout. */ +/* + * MMU modes definitions. We carefully match the indices with our + * hflags layout. + */ #define MMU_MODE0_SUFFIX _kernel #define MMU_MODE1_SUFFIX _super #define MMU_MODE2_SUFFIX _user @@ -1110,7 +1119,8 @@ static inline int cpu_mmu_index(CPUMIPSState *env, bool ifetch) #include "exec/cpu-all.h" -/* Memory access type : +/* + * Memory access type : * may be needed for precise access rights control and precise exceptions. */ enum { -- cgit v1.1 From c47c336e870585307f1e2371ea85a6256a05022e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 23 May 2019 18:18:32 +0200 Subject: BootLinuxSshTest: Test some userspace commands on Malta MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This tests boot a full VM and check the serial console until the SSH daemon is running, then start a SSH session and run some commands. This test can be run using: $ avocado --show=ssh run -t arch:mips tests/acceptance/linux_ssh_mips_malta.py ssh: Entering interactive session. ssh: # uname -a ssh: Linux debian-mips 3.2.0-4-4kc-malta #1 Debian 3.2.51-1 mips GNU/Linux ssh: # lspci -d 11ab:4620 ssh: 00:00.0 Host bridge: Marvell Technology Group Ltd. GT-64120/64120A/64121A System Controller (rev 10) ssh: # cat /sys/bus/i2c/devices/i2c-0/name ssh: SMBus PIIX4 adapter at 1100 ssh: # cat /proc/mtd ssh: dev: size erasesize name ssh: mtd0: 00100000 00010000 "YAMON" ssh: mtd1: 002e0000 00010000 "User FS" ssh: mtd2: 00020000 00010000 "Board Config" ssh: # md5sum /dev/mtd2ro ssh: 0dfbe8aa4c20b52e1b8bf3cb6cbdf193 /dev/mtd2ro ssh: # poweroff Acked-by: Aleksandar Markovic Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Aleksandar Markovic Reviewed-by: Eduardo Habkost Message-Id: <20190523161832.22490-5-f4bug@amsat.org> --- MAINTAINERS | 1 + tests/acceptance/linux_ssh_mips_malta.py | 230 +++++++++++++++++++++++++++++++ tests/requirements.txt | 1 + 3 files changed, 232 insertions(+) create mode 100644 tests/acceptance/linux_ssh_mips_malta.py diff --git a/MAINTAINERS b/MAINTAINERS index 3cacd75..8c34d5c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -934,6 +934,7 @@ M: Aurelien Jarno R: Aleksandar Rikalo S: Maintained F: hw/mips/mips_malta.c +F: tests/acceptance/linux_ssh_mips_malta.py Mipssim M: Aleksandar Markovic diff --git a/tests/acceptance/linux_ssh_mips_malta.py b/tests/acceptance/linux_ssh_mips_malta.py new file mode 100644 index 0000000..aafb0c3 --- /dev/null +++ b/tests/acceptance/linux_ssh_mips_malta.py @@ -0,0 +1,230 @@ +# Functional test that boots a VM and run commands via a SSH session +# +# Copyright (c) Philippe Mathieu-Daudé +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os +import re +import base64 +import logging +import paramiko +import time + +from avocado import skipIf +from avocado_qemu import Test +from avocado.utils import process +from avocado.utils import archive + + +class LinuxSSH(Test): + + timeout = 150 # Not for 'configure --enable-debug --enable-debug-tcg' + + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + VM_IP = '127.0.0.1' + + IMAGE_INFO = { + 'be': { + 'image_url': 'https://people.debian.org/~aurel32/qemu/mips/' + 'debian_wheezy_mips_standard.qcow2', + 'image_hash': '8987a63270df67345b2135a6b7a4885a35e392d5', + 'rsa_hostkey': b'AAAAB3NzaC1yc2EAAAADAQABAAABAQCca1VitiyLAdQOld' + b'zT43IOEVJZ0wHD78GJi8wDAjMiYWUzNSSn0rXGQsINHuH5' + b'IlF+kBZsHinb/FtKCAyS9a8uCHhQI4SuB4QhAb0+39MlUw' + b'Mm0CLkctgM2eUUZ6MQMQvDlqnue6CCkxN62EZYbaxmby7j' + b'CQa1125o1HRKBvdGm2zrJWxXAfA+f1v6jHLyE8Jnu83eQ+' + b'BFY25G+Vzx1PVc3zQBwJ8r0NGTRqy2//oWQP0h+bMsgeFe' + b'KH/J3RJM22vg6+I4JAdBFcxnK+l781h1FuRxOn4O/Xslbg' + b'go6WtB4V4TOsw2E/KfxI5IZ/icxF+swVcnvF46Hf3uQc/0' + b'BBqb', + }, + 'le': { + 'image_url': 'https://people.debian.org/~aurel32/qemu/mipsel/' + 'debian_wheezy_mipsel_standard.qcow2', + 'image_hash': '7866764d9de3ef536ffca24c9fb9f04ffdb45802', + 'rsa_hostkey': b'AAAAB3NzaC1yc2EAAAADAQABAAABAQClXJlBT71HL5yKvv' + b'gfC7jmxSWx5zSBCzET6CLZczwAafSIs7YKfNOy/dQTxhuk' + b'yIGFUugZFoF3E9PzdhunuyvyTd56MPoNIqFbb5rGokwU5I' + b'TOx3dBHZR0mClypL6MVrwe0bsiIb8GhF1zioNwcsaAZnAi' + b'KfXStVDtXvn/kLLq+xLABYt48CC5KYWoFaCoICskLAY+qo' + b'L+LWyAnQisj4jAH8VSaSKIImFpfkHWEXPhHcC4ZBlDKtnH' + b'po9vhfCHgnfW3Pzrqmk8BI4HysqPFVmJWkJGlGUL+sGeg3' + b'ZZolAYuDXGuBrw8ooPJq2v2dOH+z6dyD2q/ypmAbyPqj5C' + b'rc8H', + }, + } + + def wait_for_console_pattern(self, success_message, + failure_message='Oops'): + console = self.vm.console_socket.makefile() + console_logger = logging.getLogger('console') + while True: + msg = console.readline() + console_logger.debug(msg.strip()) + if success_message in msg: + break + if failure_message in msg: + fail = 'Failure message found in console: %s' % failure_message + self.fail(fail) + + def get_portfwd(self): + res = self.vm.command('human-monitor-command', + command_line='info usernet') + line = res.split('\r\n')[2] + port = re.split(r'.*TCP.HOST_FORWARD.*127\.0\.0\.1 (\d+)\s+10\..*', + line)[1] + self.log.debug("sshd listening on port:" + port) + return port + + def ssh_connect(self, username, password, rsa_hostkey_b64=None): + self.ssh_logger = logging.getLogger('ssh') + self.ssh_username = username + self.ssh_ps1 = '# ' if username is 'root' else '$ ' + self.ssh_client = paramiko.SSHClient() + port = self.get_portfwd() + if rsa_hostkey_b64: + rsa_hostkey_bin = base64.b64decode(rsa_hostkey_b64) + rsa_hostkey = paramiko.RSAKey(data = rsa_hostkey_bin) + ipport = '[%s]:%s' % (self.VM_IP, port) + self.ssh_logger.debug('ipport ' + ipport) + self.ssh_client.get_host_keys().add(ipport, 'ssh-rsa', rsa_hostkey) + for i in range(10): + try: + self.ssh_client.connect(self.VM_IP, int(port), + username, password, banner_timeout=90) + self.ssh_logger.info("Entering interactive session.") + return + except: + time.sleep(4) + pass + self.fail("sshd timeout") + + def ssh_disconnect_vm(self): + self.ssh_client.close() + + def ssh_command(self, command, is_root=True): + self.ssh_logger.info(self.ssh_ps1 + command) + stdin, stdout, stderr = self.ssh_client.exec_command(command) + stdout_lines = [line.strip('\n') for line in stdout] + for line in stdout_lines: + self.ssh_logger.info(line) + stderr_lines = [line.strip('\n') for line in stderr] + for line in stderr_lines: + self.ssh_logger.warning(line) + return stdout_lines, stderr_lines + + def boot_debian_wheezy_image_and_ssh_login(self, endianess, kernel_path): + image_url = self.IMAGE_INFO[endianess]['image_url'] + image_hash = self.IMAGE_INFO[endianess]['image_hash'] + image_path = self.fetch_asset(image_url, asset_hash=image_hash) + rsa_hostkey_b64 = self.IMAGE_INFO[endianess]['rsa_hostkey'] + + self.vm.set_machine('malta') + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 root=/dev/sda1') + self.vm.add_args('-no-reboot', + '-kernel', kernel_path, + '-append', kernel_command_line, + '-hda', image_path, + '-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22', + '-device', 'pcnet,netdev=vnet') + self.vm.launch() + + self.log.info('VM launched, waiting for sshd') + console_pattern = 'Starting OpenBSD Secure Shell server: sshd' + self.wait_for_console_pattern(console_pattern) + self.log.info('sshd ready') + + self.ssh_connect('root', 'root', rsa_hostkey_b64=rsa_hostkey_b64) + + def shutdown_via_ssh(self): + self.ssh_command('poweroff') + self.ssh_disconnect_vm() + self.wait_for_console_pattern('Power down') + + def run_common_commands(self): + stdout, stderr = self.ssh_command('lspci -d 11ab:4620') + self.assertIn(True, ["GT-64120" in line for line in stdout]) + + stdout, stderr = self.ssh_command('cat /sys/bus/i2c/devices/i2c-0/name') + self.assertIn(True, ["SMBus PIIX4 adapter" in line + for line in stdout]) + + stdout, stderr = self.ssh_command('cat /proc/mtd') + self.assertIn(True, ["YAMON" in line + for line in stdout]) + + # Empty 'Board Config' + stdout, stderr = self.ssh_command('md5sum /dev/mtd2ro') + self.assertIn(True, ["0dfbe8aa4c20b52e1b8bf3cb6cbdf193" in line + for line in stdout]) + + def do_test_mips_malta(self, endianess, kernel_path, uname_m): + self.boot_debian_wheezy_image_and_ssh_login(endianess, kernel_path) + + stdout, stderr = self.ssh_command('uname -a') + self.assertIn(True, [uname_m + " GNU/Linux" in line for line in stdout]) + + self.run_common_commands() + self.shutdown_via_ssh() + + @skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI') + def test_mips_malta32eb_kernel3_2_0(self): + """ + :avocado: tags=arch:mips + :avocado: tags=machine:malta + :avocado: tags=endian:big + :avocado: tags=device:pcnet32 + """ + kernel_url = ('https://people.debian.org/~aurel32/qemu/mips/' + 'vmlinux-3.2.0-4-4kc-malta') + kernel_hash = '592e384a4edc16dade52a6cd5c785c637bcbc9ad' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.do_test_mips_malta('be', kernel_path, 'mips') + + @skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI') + def test_mips_malta32el_kernel3_2_0(self): + """ + :avocado: tags=arch:mipsel + :avocado: tags=machine:malta + :avocado: tags=endian:little + :avocado: tags=device:pcnet32 + """ + kernel_url = ('https://people.debian.org/~aurel32/qemu/mipsel/' + 'vmlinux-3.2.0-4-4kc-malta') + kernel_hash = 'a66bea5a8adaa2cb3d36a1d4e0ccdb01be8f6c2a' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.do_test_mips_malta('le', kernel_path, 'mips') + + @skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI') + def test_mips_malta64eb_kernel3_2_0(self): + """ + :avocado: tags=arch:mips64 + :avocado: tags=machine:malta + :avocado: tags=endian:big + :avocado: tags=device:pcnet32 + """ + kernel_url = ('https://people.debian.org/~aurel32/qemu/mips/' + 'vmlinux-3.2.0-4-5kc-malta') + kernel_hash = 'db6eea7de35d36c77d8c165b6bcb222e16eb91db' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.do_test_mips_malta('be', kernel_path, 'mips64') + + @skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI') + def test_mips_malta64el_kernel3_2_0(self): + """ + :avocado: tags=arch:mips64el + :avocado: tags=machine:malta + :avocado: tags=endian:little + :avocado: tags=device:pcnet32 + """ + kernel_url = ('https://people.debian.org/~aurel32/qemu/mipsel/' + 'vmlinux-3.2.0-4-5kc-malta') + kernel_hash = '6a7f77245acf231415a0e8b725d91ed2f3487794' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.do_test_mips_malta('le', kernel_path, 'mips64') diff --git a/tests/requirements.txt b/tests/requirements.txt index 002ded6..3ae0e29 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -2,3 +2,4 @@ # in the tests/venv Python virtual environment. For more info, # refer to: https://pip.pypa.io/en/stable/user_guide/#id1 avocado-framework==68.0 +paramiko -- cgit v1.1