mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-22 05:41:04 +00:00
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:
parent
e9442a5ca9
commit
06e5835cc7
|
@ -5039,6 +5039,7 @@ mips_symbols = (
|
|||
'helper_rdhwr_performance',
|
||||
'helper_rdhwr_synci_step',
|
||||
'helper_rdhwr_xnp',
|
||||
'helper_rotx',
|
||||
'helper_sc',
|
||||
'helper_scd',
|
||||
'helper_sdl',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) |
|
||||
|
|
Loading…
Reference in a new issue