microblaze: Correct prio between MMU and unaligned exceptions.
The microblaze gives MMU faults priority. For stores we still have a flaw that the value leaks to memory in the case of an unaligned exception. Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
This commit is contained in:
parent
97f90cbfe8
commit
a12f650781
@ -819,14 +819,28 @@ static void dec_load(DisasContext *dc)
|
||||
|
||||
/* Verify alignment if needed. */
|
||||
if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
|
||||
TCGv v = tcg_temp_new();
|
||||
|
||||
/*
|
||||
* Microblaze gives MMU faults priority over faults due to
|
||||
* unaligned addresses. That's why we speculatively do the load
|
||||
* into v. If the load succeeds, we verify alignment of the
|
||||
* address and if that succeeds we write into the destination reg.
|
||||
*/
|
||||
gen_load(dc, v, *addr, size);
|
||||
|
||||
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
|
||||
gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
|
||||
tcg_const_tl(0), tcg_const_tl(size - 1));
|
||||
}
|
||||
|
||||
if (dc->rd) {
|
||||
gen_load(dc, cpu_R[dc->rd], *addr, size);
|
||||
if (dc->rd)
|
||||
tcg_gen_mov_tl(cpu_R[dc->rd], v);
|
||||
tcg_temp_free(v);
|
||||
} else {
|
||||
gen_load(dc, env_imm, *addr, size);
|
||||
if (dc->rd) {
|
||||
gen_load(dc, cpu_R[dc->rd], *addr, size);
|
||||
} else {
|
||||
gen_load(dc, env_imm, *addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
if (addr == &t)
|
||||
@ -868,13 +882,18 @@ static void dec_store(DisasContext *dc)
|
||||
sync_jmpstate(dc);
|
||||
addr = compute_ldst_addr(dc, &t);
|
||||
|
||||
gen_store(dc, *addr, cpu_R[dc->rd], size);
|
||||
|
||||
/* Verify alignment if needed. */
|
||||
if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
|
||||
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
|
||||
/* FIXME: if the alignment is wrong, we should restore the value
|
||||
* in memory.
|
||||
*/
|
||||
gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
|
||||
tcg_const_tl(1), tcg_const_tl(size - 1));
|
||||
}
|
||||
|
||||
gen_store(dc, *addr, cpu_R[dc->rd], size);
|
||||
if (addr == &t)
|
||||
tcg_temp_free(t);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user