target/mips: reimplement SC instruction emulation and use cmpxchg

Completely rewrite conditional stores handling. Use cmpxchg.

This eliminates need for separate implementations of SC instruction
emulation for user and system emulation.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
Signed-off-by: Miodrag Dinic <miodrag.dinic@imgtec.com>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Acked-by: Alex Bennée <alex.bennee@linaro.org>
Tested-by: Emilio G. Cota <cota@braap.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Leon Alrae 2019-02-11 16:09:23 +01:00 committed by Aleksandar Markovic
parent c7c7e1e9a5
commit 33a07fa2db
6 changed files with 44 additions and 191 deletions

View file

@ -392,70 +392,6 @@ static const uint8_t mips_syscall_args[] = {
# undef MIPS_SYS
# endif /* O32 */
static int do_store_exclusive(CPUMIPSState *env)
{
target_ulong addr;
target_ulong page_addr;
target_ulong val;
uint32_t val_wp = 0;
uint32_t llnewval_wp = 0;
int flags;
int segv = 0;
int reg;
int d;
int wp;
addr = env->lladdr;
page_addr = addr & TARGET_PAGE_MASK;
start_exclusive();
mmap_lock();
flags = page_get_flags(page_addr);
if ((flags & PAGE_READ) == 0) {
segv = 1;
} else {
reg = env->llreg & 0x1f;
d = (env->llreg & 0x20) != 0;
wp = (env->llreg & 0x40) != 0;
if (!wp) {
if (d) {
segv = get_user_s64(val, addr);
} else {
segv = get_user_s32(val, addr);
}
} else {
segv = get_user_s32(val, addr);
segv |= get_user_s32(val_wp, addr);
llnewval_wp = env->llnewval_wp;
}
if (!segv) {
if (val != env->llval && val_wp == llnewval_wp) {
env->active_tc.gpr[reg] = 0;
} else {
if (!wp) {
if (d) {
segv = put_user_u64(env->llnewval, addr);
} else {
segv = put_user_u32(env->llnewval, addr);
}
} else {
segv = put_user_u32(env->llnewval, addr);
segv |= put_user_u32(env->llnewval_wp, addr + 4);
}
if (!segv) {
env->active_tc.gpr[reg] = 1;
}
}
}
}
env->lladdr = -1;
if (!segv) {
env->active_tc.PC += 4;
}
mmap_unlock();
end_exclusive();
return segv;
}
/* Break codes */
enum {
BRK_OVERFLOW = 6,
@ -597,15 +533,6 @@ done_syscall:
info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
case EXCP_SC:
if (do_store_exclusive(env)) {
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = env->active_tc.PC;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
}
break;
case EXCP_DSPDIS:
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;