mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-01 06:43:53 -06:00
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:
parent
c7c7e1e9a5
commit
33a07fa2db
6 changed files with 44 additions and 191 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue