From 06e5835cc7069611b30ecbb596ddf781165d5046 Mon Sep 17 00:00:00 2001 From: Matthew Fortune Date: Mon, 27 Aug 2018 05:11:05 -0400 Subject: [PATCH] target/mips: Implement emulation of nanoMIPS ROTX instruction Added a helper for ROTX based on the pseudocode from the architecture spec. This instraction was not present in previous MIPS instruction sets. Backports commit e222f5067269392af489731221750976d0cf3c05 from qemu --- qemu/header_gen.py | 1 + qemu/mips.h | 1 + qemu/mips64.h | 1 + qemu/mips64el.h | 1 + qemu/mipsel.h | 1 + qemu/target/mips/helper.h | 2 + qemu/target/mips/op_helper.c | 94 ++++++++++++++++++++++++++++++++++++ qemu/target/mips/translate.c | 15 ++++++ 8 files changed, 116 insertions(+) diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 97b8ba9d..967aba71 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -5039,6 +5039,7 @@ mips_symbols = ( 'helper_rdhwr_performance', 'helper_rdhwr_synci_step', 'helper_rdhwr_xnp', + 'helper_rotx', 'helper_sc', 'helper_scd', 'helper_sdl', diff --git a/qemu/mips.h b/qemu/mips.h index 4a4978bd..ef585968 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -4129,6 +4129,7 @@ #define helper_rdhwr_performance helper_rdhwr_performance_mips #define helper_rdhwr_synci_step helper_rdhwr_synci_step_mips #define helper_rdhwr_xnp helper_rdhwr_xnp_mips +#define helper_rotx helper_rotx_mips #define helper_sc helper_sc_mips #define helper_scd helper_scd_mips #define helper_sdl helper_sdl_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 7458c11a..db01ae46 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -4129,6 +4129,7 @@ #define helper_rdhwr_performance helper_rdhwr_performance_mips64 #define helper_rdhwr_synci_step helper_rdhwr_synci_step_mips64 #define helper_rdhwr_xnp helper_rdhwr_xnp_mips64 +#define helper_rotx helper_rotx_mips64 #define helper_sc helper_sc_mips64 #define helper_scd helper_scd_mips64 #define helper_sdl helper_sdl_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index dd2ab5c4..9fc86442 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -4129,6 +4129,7 @@ #define helper_rdhwr_performance helper_rdhwr_performance_mips64el #define helper_rdhwr_synci_step helper_rdhwr_synci_step_mips64el #define helper_rdhwr_xnp helper_rdhwr_xnp_mips64el +#define helper_rotx helper_rotx_mips64el #define helper_sc helper_sc_mips64el #define helper_scd helper_scd_mips64el #define helper_sdl helper_sdl_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index a04a749e..be407bcd 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -4129,6 +4129,7 @@ #define helper_rdhwr_performance helper_rdhwr_performance_mipsel #define helper_rdhwr_synci_step helper_rdhwr_synci_step_mipsel #define helper_rdhwr_xnp helper_rdhwr_xnp_mipsel +#define helper_rotx helper_rotx_mipsel #define helper_sc helper_sc_mipsel #define helper_scd helper_scd_mipsel #define helper_sdl helper_sdl_mipsel diff --git a/qemu/target/mips/helper.h b/qemu/target/mips/helper.h index 69274c4a..404444ee 100644 --- a/qemu/target/mips/helper.h +++ b/qemu/target/mips/helper.h @@ -40,6 +40,8 @@ DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl) #endif +DEF_HELPER_FLAGS_4(rotx, TCG_CALL_NO_RWG_SE, tl, tl, i32, i32, i32) + #ifndef CONFIG_USER_ONLY /* CP0 helpers */ DEF_HELPER_1(mfc0_mvpcontrol, tl, env) diff --git a/qemu/target/mips/op_helper.c b/qemu/target/mips/op_helper.c index 2f2ae753..2286f0c8 100644 --- a/qemu/target/mips/op_helper.c +++ b/qemu/target/mips/op_helper.c @@ -247,6 +247,100 @@ target_ulong helper_bitswap(target_ulong rt) return (int32_t)bitswap(rt); } +target_ulong helper_rotx(target_ulong rs, uint32_t shift, uint32_t shiftx, + uint32_t stripe) +{ + int i; + uint64_t tmp0 = ((uint64_t)rs) << 32 | ((uint64_t)rs & 0xffffffff); + uint64_t tmp1 = tmp0; + for (i = 0; i <= 46; i++) { + int s; + if (i & 0x8) { + s = shift; + } else { + s = shiftx; + } + + if (stripe != 0 && !(i & 0x4)) { + s = ~s; + } + if (s & 0x10) { + if (tmp0 & (1LL << (i + 16))) { + tmp1 |= 1LL << i; + } else { + tmp1 &= ~(1LL << i); + } + } + } + + uint64_t tmp2 = tmp1; + for (i = 0; i <= 38; i++) { + int s; + if (i & 0x4) { + s = shift; + } else { + s = shiftx; + } + + if (s & 0x8) { + if (tmp1 & (1LL << (i + 8))) { + tmp2 |= 1LL << i; + } else { + tmp2 &= ~(1LL << i); + } + } + } + + uint64_t tmp3 = tmp2; + for (i = 0; i <= 34; i++) { + int s; + if (i & 0x2) { + s = shift; + } else { + s = shiftx; + } + if (s & 0x4) { + if (tmp2 & (1LL << (i + 4))) { + tmp3 |= 1LL << i; + } else { + tmp3 &= ~(1LL << i); + } + } + } + + uint64_t tmp4 = tmp3; + for (i = 0; i <= 32; i++) { + int s; + if (i & 0x1) { + s = shift; + } else { + s = shiftx; + } + if (s & 0x2) { + if (tmp3 & (1LL << (i + 2))) { + tmp4 |= 1LL << i; + } else { + tmp4 &= ~(1LL << i); + } + } + } + + uint64_t tmp5 = tmp4; + for (i = 0; i <= 31; i++) { + int s; + s = shift; + if (s & 0x1) { + if (tmp4 & (1LL << (i + 1))) { + tmp5 |= 1LL << i; + } else { + tmp5 &= ~(1LL << i); + } + } + } + + return (int64_t)(int32_t)(uint32_t)tmp5; +} + #ifndef CONFIG_USER_ONLY static inline hwaddr do_translate_address(CPUMIPSState *env, diff --git a/qemu/target/mips/translate.c b/qemu/target/mips/translate.c index 6c89ef68..3314760c 100644 --- a/qemu/target/mips/translate.c +++ b/qemu/target/mips/translate.c @@ -17933,6 +17933,21 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) } break; case NM_P_ROTX: + if (rt != 0) { + TCGv t0 = tcg_temp_new(tcg_ctx); + TCGv_i32 shift = tcg_const_i32(tcg_ctx, extract32(ctx->opcode, 0, 5)); + TCGv_i32 shiftx = tcg_const_i32(tcg_ctx, extract32(ctx->opcode, 7, 4) + << 1); + TCGv_i32 stripe = tcg_const_i32(tcg_ctx, extract32(ctx->opcode, 6, 1)); + + gen_load_gpr(ctx, t0, rs); + gen_helper_rotx(tcg_ctx, tcg_ctx->cpu_gpr[rt], t0, shift, shiftx, stripe); + tcg_temp_free(tcg_ctx, t0); + + tcg_temp_free_i32(tcg_ctx, shift); + tcg_temp_free_i32(tcg_ctx, shiftx); + tcg_temp_free_i32(tcg_ctx, stripe); + } break; case NM_P_INS: switch (((ctx->opcode >> 10) & 2) |