mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
target-mips: implement unaligned loads using TCG
Load/store from helpers should be avoided as they are quite inefficient. Rewrite unaligned loads instructions using TCG and aligned loads. The number of actual loads operations to implement an unaligned load instruction is reduced from up to 8 to 1. Note: As we can't rely on shift by 32 or 64 undefined behaviour, the code loads already shift by one constants. Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
parent
18bba4dc78
commit
fc40787abc
3 changed files with 62 additions and 159 deletions
|
@ -350,56 +350,6 @@ HELPER_ST_ATOMIC(scd, ld, sd, 0x7)
|
|||
#define GET_OFFSET(addr, offset) (addr - (offset))
|
||||
#endif
|
||||
|
||||
target_ulong helper_lwl(CPUMIPSState *env, target_ulong arg1,
|
||||
target_ulong arg2, int mem_idx)
|
||||
{
|
||||
target_ulong tmp;
|
||||
|
||||
tmp = do_lbu(env, arg2, mem_idx);
|
||||
arg1 = (arg1 & 0x00FFFFFF) | (tmp << 24);
|
||||
|
||||
if (GET_LMASK(arg2) <= 2) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, 1), mem_idx);
|
||||
arg1 = (arg1 & 0xFF00FFFF) | (tmp << 16);
|
||||
}
|
||||
|
||||
if (GET_LMASK(arg2) <= 1) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, 2), mem_idx);
|
||||
arg1 = (arg1 & 0xFFFF00FF) | (tmp << 8);
|
||||
}
|
||||
|
||||
if (GET_LMASK(arg2) == 0) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, 3), mem_idx);
|
||||
arg1 = (arg1 & 0xFFFFFF00) | tmp;
|
||||
}
|
||||
return (int32_t)arg1;
|
||||
}
|
||||
|
||||
target_ulong helper_lwr(CPUMIPSState *env, target_ulong arg1,
|
||||
target_ulong arg2, int mem_idx)
|
||||
{
|
||||
target_ulong tmp;
|
||||
|
||||
tmp = do_lbu(env, arg2, mem_idx);
|
||||
arg1 = (arg1 & 0xFFFFFF00) | tmp;
|
||||
|
||||
if (GET_LMASK(arg2) >= 1) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, -1), mem_idx);
|
||||
arg1 = (arg1 & 0xFFFF00FF) | (tmp << 8);
|
||||
}
|
||||
|
||||
if (GET_LMASK(arg2) >= 2) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, -2), mem_idx);
|
||||
arg1 = (arg1 & 0xFF00FFFF) | (tmp << 16);
|
||||
}
|
||||
|
||||
if (GET_LMASK(arg2) == 3) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, -3), mem_idx);
|
||||
arg1 = (arg1 & 0x00FFFFFF) | (tmp << 24);
|
||||
}
|
||||
return (int32_t)arg1;
|
||||
}
|
||||
|
||||
void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
|
||||
int mem_idx)
|
||||
{
|
||||
|
@ -440,98 +390,6 @@ void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
|
|||
#define GET_LMASK64(v) (((v) & 7) ^ 7)
|
||||
#endif
|
||||
|
||||
target_ulong helper_ldl(CPUMIPSState *env, target_ulong arg1,
|
||||
target_ulong arg2, int mem_idx)
|
||||
{
|
||||
uint64_t tmp;
|
||||
|
||||
tmp = do_lbu(env, arg2, mem_idx);
|
||||
arg1 = (arg1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
|
||||
|
||||
if (GET_LMASK64(arg2) <= 6) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, 1), mem_idx);
|
||||
arg1 = (arg1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
|
||||
}
|
||||
|
||||
if (GET_LMASK64(arg2) <= 5) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, 2), mem_idx);
|
||||
arg1 = (arg1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
|
||||
}
|
||||
|
||||
if (GET_LMASK64(arg2) <= 4) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, 3), mem_idx);
|
||||
arg1 = (arg1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
|
||||
}
|
||||
|
||||
if (GET_LMASK64(arg2) <= 3) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, 4), mem_idx);
|
||||
arg1 = (arg1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
|
||||
}
|
||||
|
||||
if (GET_LMASK64(arg2) <= 2) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, 5), mem_idx);
|
||||
arg1 = (arg1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
|
||||
}
|
||||
|
||||
if (GET_LMASK64(arg2) <= 1) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, 6), mem_idx);
|
||||
arg1 = (arg1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
|
||||
}
|
||||
|
||||
if (GET_LMASK64(arg2) == 0) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, 7), mem_idx);
|
||||
arg1 = (arg1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
|
||||
}
|
||||
|
||||
return arg1;
|
||||
}
|
||||
|
||||
target_ulong helper_ldr(CPUMIPSState *env, target_ulong arg1,
|
||||
target_ulong arg2, int mem_idx)
|
||||
{
|
||||
uint64_t tmp;
|
||||
|
||||
tmp = do_lbu(env, arg2, mem_idx);
|
||||
arg1 = (arg1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
|
||||
|
||||
if (GET_LMASK64(arg2) >= 1) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, -1), mem_idx);
|
||||
arg1 = (arg1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
|
||||
}
|
||||
|
||||
if (GET_LMASK64(arg2) >= 2) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, -2), mem_idx);
|
||||
arg1 = (arg1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
|
||||
}
|
||||
|
||||
if (GET_LMASK64(arg2) >= 3) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, -3), mem_idx);
|
||||
arg1 = (arg1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
|
||||
}
|
||||
|
||||
if (GET_LMASK64(arg2) >= 4) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, -4), mem_idx);
|
||||
arg1 = (arg1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
|
||||
}
|
||||
|
||||
if (GET_LMASK64(arg2) >= 5) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, -5), mem_idx);
|
||||
arg1 = (arg1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
|
||||
}
|
||||
|
||||
if (GET_LMASK64(arg2) >= 6) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, -6), mem_idx);
|
||||
arg1 = (arg1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
|
||||
}
|
||||
|
||||
if (GET_LMASK64(arg2) == 7) {
|
||||
tmp = do_lbu(env, GET_OFFSET(arg2, -7), mem_idx);
|
||||
arg1 = (arg1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
|
||||
}
|
||||
|
||||
return arg1;
|
||||
}
|
||||
|
||||
void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
|
||||
int mem_idx)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue