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
This commit is contained in:
Matthew Fortune 2018-08-27 05:11:05 -04:00 committed by Lioncash
parent e9442a5ca9
commit 06e5835cc7
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
8 changed files with 116 additions and 0 deletions

View file

@ -5039,6 +5039,7 @@ mips_symbols = (
'helper_rdhwr_performance',
'helper_rdhwr_synci_step',
'helper_rdhwr_xnp',
'helper_rotx',
'helper_sc',
'helper_scd',
'helper_sdl',

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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,

View file

@ -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) |