aboutsummaryrefslogtreecommitdiff
path: root/target/hppa/op_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/hppa/op_helper.c')
-rw-r--r--target/hppa/op_helper.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index f36ce74163..0aa5fb99d4 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -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;