mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
target-hppa: Implement loads and stores
Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
@@ -2,4 +2,7 @@ DEF_HELPER_2(excp, noreturn, env, int)
|
||||
DEF_HELPER_FLAGS_2(tsv, TCG_CALL_NO_WG, void, env, tl)
|
||||
DEF_HELPER_FLAGS_2(tcond, TCG_CALL_NO_WG, void, env, tl)
|
||||
|
||||
DEF_HELPER_FLAGS_3(stby_b, TCG_CALL_NO_WG, void, env, tl, tl)
|
||||
DEF_HELPER_FLAGS_3(stby_e, TCG_CALL_NO_WG, void, env, tl, tl)
|
||||
|
||||
DEF_HELPER_FLAGS_1(loaded_fr0, TCG_CALL_NO_RWG, void, env)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
|
||||
void QEMU_NORETURN HELPER(excp)(CPUHPPAState *env, int excp)
|
||||
{
|
||||
@@ -54,6 +55,83 @@ void HELPER(tcond)(CPUHPPAState *env, target_ulong cond)
|
||||
}
|
||||
}
|
||||
|
||||
static void atomic_store_3(CPUHPPAState *env, target_ulong addr, uint32_t val,
|
||||
uint32_t mask, uintptr_t ra)
|
||||
{
|
||||
uint32_t old, new, cmp;
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
uint32_t *haddr = g2h(addr - 1);
|
||||
old = *haddr;
|
||||
while (1) {
|
||||
new = (old & ~mask) | (val & mask);
|
||||
cmp = atomic_cmpxchg(haddr, old, new);
|
||||
if (cmp == old) {
|
||||
return;
|
||||
}
|
||||
old = cmp;
|
||||
}
|
||||
#else
|
||||
#error "Not implemented."
|
||||
#endif
|
||||
}
|
||||
|
||||
void HELPER(stby_b)(CPUHPPAState *env, target_ulong addr, target_ulong val)
|
||||
{
|
||||
uintptr_t ra = GETPC();
|
||||
|
||||
switch (addr & 3) {
|
||||
case 3:
|
||||
cpu_stb_data_ra(env, addr, val, ra);
|
||||
break;
|
||||
case 2:
|
||||
cpu_stw_data_ra(env, addr, val, ra);
|
||||
break;
|
||||
case 1:
|
||||
/* The 3 byte store must appear atomic. */
|
||||
if (parallel_cpus) {
|
||||
atomic_store_3(env, addr, val, 0x00ffffffu, ra);
|
||||
} else {
|
||||
cpu_stb_data_ra(env, addr, val >> 16, ra);
|
||||
cpu_stw_data_ra(env, addr + 1, val, ra);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cpu_stl_data_ra(env, addr, val, ra);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HELPER(stby_e)(CPUHPPAState *env, target_ulong addr, target_ulong val)
|
||||
{
|
||||
uintptr_t ra = GETPC();
|
||||
|
||||
switch (addr & 3) {
|
||||
case 3:
|
||||
/* The 3 byte store must appear atomic. */
|
||||
if (parallel_cpus) {
|
||||
atomic_store_3(env, addr - 3, val, 0xffffff00u, ra);
|
||||
} else {
|
||||
cpu_stw_data_ra(env, addr - 3, val >> 16, ra);
|
||||
cpu_stb_data_ra(env, addr - 1, val >> 8, ra);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
cpu_stw_data_ra(env, addr - 2, val >> 16, ra);
|
||||
break;
|
||||
case 1:
|
||||
cpu_stb_data_ra(env, addr - 1, val >> 24, ra);
|
||||
break;
|
||||
default:
|
||||
/* Nothing is stored, but protection is checked and the
|
||||
cacheline is marked dirty. */
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
probe_write(env, addr, cpu_mmu_index(env, 0), ra);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HELPER(loaded_fr0)(CPUHPPAState *env)
|
||||
{
|
||||
uint32_t shadow = env->fr[0] >> 32;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user