target-hppa: Implement loads and stores

Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Richard Henderson
2017-01-23 09:52:40 -08:00
parent 0b1347d259
commit 96d6407f36
3 changed files with 699 additions and 0 deletions
+3
View File
@@ -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)
+78
View File
@@ -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