target-arm: A64: Implement store-exclusive for system mode
System mode store-exclusive use a different code path to usermode ones; implement this missing code, in a similar way to the 32 bit version. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
7900e9f1f9
commit
d324b36ad9
@ -1487,12 +1487,68 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
|
static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
|
||||||
TCGv_i64 addr, int size, int is_pair)
|
TCGv_i64 inaddr, int size, int is_pair)
|
||||||
{
|
{
|
||||||
qemu_log_mask(LOG_UNIMP,
|
/* if (env->exclusive_addr == addr && env->exclusive_val == [addr]
|
||||||
"%s:%d: system mode store_exclusive unsupported "
|
* && (!is_pair || env->exclusive_high == [addr + datasize])) {
|
||||||
"at pc=%016" PRIx64 "\n",
|
* [addr] = {Rt};
|
||||||
__FILE__, __LINE__, s->pc - 4);
|
* if (is_pair) {
|
||||||
|
* [addr + datasize] = {Rt2};
|
||||||
|
* }
|
||||||
|
* {Rd} = 0;
|
||||||
|
* } else {
|
||||||
|
* {Rd} = 1;
|
||||||
|
* }
|
||||||
|
* env->exclusive_addr = -1;
|
||||||
|
*/
|
||||||
|
int fail_label = gen_new_label();
|
||||||
|
int done_label = gen_new_label();
|
||||||
|
TCGv_i64 addr = tcg_temp_local_new_i64();
|
||||||
|
TCGv_i64 tmp;
|
||||||
|
|
||||||
|
/* Copy input into a local temp so it is not trashed when the
|
||||||
|
* basic block ends at the branch insn.
|
||||||
|
*/
|
||||||
|
tcg_gen_mov_i64(addr, inaddr);
|
||||||
|
tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
|
||||||
|
|
||||||
|
tmp = tcg_temp_new_i64();
|
||||||
|
tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), MO_TE + size);
|
||||||
|
tcg_gen_brcond_i64(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
|
||||||
|
tcg_temp_free_i64(tmp);
|
||||||
|
|
||||||
|
if (is_pair) {
|
||||||
|
TCGv_i64 addrhi = tcg_temp_new_i64();
|
||||||
|
TCGv_i64 tmphi = tcg_temp_new_i64();
|
||||||
|
|
||||||
|
tcg_gen_addi_i64(addrhi, addr, 1 << size);
|
||||||
|
tcg_gen_qemu_ld_i64(tmphi, addrhi, get_mem_index(s), MO_TE + size);
|
||||||
|
tcg_gen_brcond_i64(TCG_COND_NE, tmphi, cpu_exclusive_high, fail_label);
|
||||||
|
|
||||||
|
tcg_temp_free_i64(tmphi);
|
||||||
|
tcg_temp_free_i64(addrhi);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We seem to still have the exclusive monitor, so do the store */
|
||||||
|
tcg_gen_qemu_st_i64(cpu_reg(s, rt), addr, get_mem_index(s), MO_TE + size);
|
||||||
|
if (is_pair) {
|
||||||
|
TCGv_i64 addrhi = tcg_temp_new_i64();
|
||||||
|
|
||||||
|
tcg_gen_addi_i64(addrhi, addr, 1 << size);
|
||||||
|
tcg_gen_qemu_st_i64(cpu_reg(s, rt2), addrhi,
|
||||||
|
get_mem_index(s), MO_TE + size);
|
||||||
|
tcg_temp_free_i64(addrhi);
|
||||||
|
}
|
||||||
|
|
||||||
|
tcg_temp_free_i64(addr);
|
||||||
|
|
||||||
|
tcg_gen_movi_i64(cpu_reg(s, rd), 0);
|
||||||
|
tcg_gen_br(done_label);
|
||||||
|
gen_set_label(fail_label);
|
||||||
|
tcg_gen_movi_i64(cpu_reg(s, rd), 1);
|
||||||
|
gen_set_label(done_label);
|
||||||
|
tcg_gen_movi_i64(cpu_exclusive_addr, -1);
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user