aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2020-01-16 15:46:38 -1000
committerRichard Henderson <richard.henderson@linaro.org>2020-01-27 10:49:51 -0800
commitb1af755c33bf0d690553a5ccd93689dfd15a98e8 (patch)
tree80c91a18bf947821d1d6dbeb04fab63942a45ce2
parent4debfdac03babcf858fb45204157a05236635a21 (diff)
downloadqemu-b1af755c33bf0d690553a5ccd93689dfd15a98e8.zip
qemu-b1af755c33bf0d690553a5ccd93689dfd15a98e8.tar.gz
qemu-b1af755c33bf0d690553a5ccd93689dfd15a98e8.tar.bz2
target/hppa: Allow, but diagnose, LDCW aligned only mod 4
The PA-RISC 1.1 specification says that LDCW must be aligned mod 16 or the operation is undefined. However, real hardware only generates an unaligned access trap for unaligned mod 4. Match real hardware, but diagnose with GUEST_ERROR a violation of the specification. At the same time fix a bug in the initialization of mop, where the size was specified twice, and another to free the zero temporary. Tested-by: Helge Deller <deller@gmx.de> Reported-by: Helge Deller <deller@gmx.de> Suggested-by: John David Anglin <dave.anglin@bell.net> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r--target/hppa/helper.h2
-rw-r--r--target/hppa/op_helper.c9
-rw-r--r--target/hppa/translate.c15
3 files changed, 25 insertions, 1 deletions
diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index 38d834e..2d483aa 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -17,6 +17,8 @@ DEF_HELPER_FLAGS_3(stby_b_parallel, TCG_CALL_NO_WG, void, env, tl, tr)
DEF_HELPER_FLAGS_3(stby_e, TCG_CALL_NO_WG, void, env, tl, tr)
DEF_HELPER_FLAGS_3(stby_e_parallel, TCG_CALL_NO_WG, void, env, tl, tr)
+DEF_HELPER_FLAGS_1(ldc_check, TCG_CALL_NO_RWG, void, tl)
+
DEF_HELPER_FLAGS_4(probe, TCG_CALL_NO_WG, tr, env, tl, i32, i32)
DEF_HELPER_FLAGS_1(loaded_fr0, TCG_CALL_NO_RWG, void, env)
diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index f0516e8..7823706 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -153,6 +153,15 @@ void HELPER(stby_e_parallel)(CPUHPPAState *env, target_ulong addr,
do_stby_e(env, addr, val, true, GETPC());
}
+void HELPER(ldc_check)(target_ulong addr)
+{
+ if (unlikely(addr & 0xf)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "Undefined ldc to unaligned address mod 16: "
+ TARGET_FMT_lx "\n", addr);
+ }
+}
+
target_ureg HELPER(probe)(CPUHPPAState *env, target_ulong addr,
uint32_t level, uint32_t want)
{
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index f25927a..52d7bea 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2942,7 +2942,7 @@ static bool trans_st(DisasContext *ctx, arg_ldst *a)
static bool trans_ldc(DisasContext *ctx, arg_ldst *a)
{
- MemOp mop = MO_TEUL | MO_ALIGN_16 | a->size;
+ MemOp mop = MO_TE | MO_ALIGN | a->size;
TCGv_reg zero, dest, ofs;
TCGv_tl addr;
@@ -2958,8 +2958,21 @@ static bool trans_ldc(DisasContext *ctx, arg_ldst *a)
form_gva(ctx, &addr, &ofs, a->b, a->x, a->scale ? a->size : 0,
a->disp, a->sp, a->m, ctx->mmu_idx == MMU_PHYS_IDX);
+
+ /*
+ * For hppa1.1, LDCW is undefined unless aligned mod 16.
+ * However actual hardware succeeds with aligned mod 4.
+ * Detect this case and log a GUEST_ERROR.
+ *
+ * TODO: HPPA64 relaxes the over-alignment requirement
+ * with the ,co completer.
+ */
+ gen_helper_ldc_check(addr);
+
zero = tcg_const_reg(0);
tcg_gen_atomic_xchg_reg(dest, addr, zero, ctx->mmu_idx, mop);
+ tcg_temp_free(zero);
+
if (a->m) {
save_gpr(ctx, a->b, ofs);
}