mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-12-17 21:26:13 -07:00
MIPS atomic instructions
Implement MIPS ll/sc instructions using atomic compare+exchange. Signed-off-by: Paul Brook <paul@codesourcery.com>
This commit is contained in:
parent
ff867ddcbd
commit
590bc601d8
3 changed files with 124 additions and 24 deletions
|
|
@ -1826,6 +1826,55 @@ static const uint8_t mips_syscall_args[] = {
|
|||
|
||||
#undef MIPS_SYS
|
||||
|
||||
static int do_store_exclusive(CPUMIPSState *env)
|
||||
{
|
||||
target_ulong addr;
|
||||
target_ulong page_addr;
|
||||
target_ulong val;
|
||||
int flags;
|
||||
int segv = 0;
|
||||
int reg;
|
||||
int d;
|
||||
|
||||
addr = env->CP0_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;
|
||||
if (d) {
|
||||
segv = get_user_s64(val, addr);
|
||||
} else {
|
||||
segv = get_user_s32(val, addr);
|
||||
}
|
||||
if (!segv) {
|
||||
if (val != env->llval) {
|
||||
env->active_tc.gpr[reg] = 0;
|
||||
} else {
|
||||
if (d) {
|
||||
segv = put_user_u64(env->llnewval, addr);
|
||||
} else {
|
||||
segv = put_user_u32(env->llnewval, addr);
|
||||
}
|
||||
if (!segv) {
|
||||
env->active_tc.gpr[reg] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
env->CP0_LLAddr = -1;
|
||||
if (!segv) {
|
||||
env->active_tc.PC += 4;
|
||||
}
|
||||
mmap_unlock();
|
||||
end_exclusive();
|
||||
return segv;
|
||||
}
|
||||
|
||||
void cpu_loop(CPUMIPSState *env)
|
||||
{
|
||||
target_siginfo_t info;
|
||||
|
|
@ -1833,7 +1882,9 @@ void cpu_loop(CPUMIPSState *env)
|
|||
unsigned int syscall_num;
|
||||
|
||||
for(;;) {
|
||||
cpu_exec_start(env);
|
||||
trapnr = cpu_mips_exec(env);
|
||||
cpu_exec_end(env);
|
||||
switch(trapnr) {
|
||||
case EXCP_SYSCALL:
|
||||
syscall_num = env->active_tc.gpr[2] - 4000;
|
||||
|
|
@ -1910,6 +1961,15 @@ void cpu_loop(CPUMIPSState *env)
|
|||
}
|
||||
}
|
||||
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, &info);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// error:
|
||||
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue