Message ID | 1390335150-13470-7-git-send-email-peter.maydell@linaro.org |
---|---|
State | New |
Headers | show |
On Tue, Jan 21, 2014 at 08:12:12PM +0000, Peter Maydell wrote: > 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> > --- > target-arm/translate-a64.c | 68 ++++++++++++++++++++++++++++++++++++++++++---- > 1 file changed, 62 insertions(+), 6 deletions(-) > > diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c > index e0f6765..5aa1f17 100644 > --- a/target-arm/translate-a64.c > +++ b/target-arm/translate-a64.c > @@ -1422,12 +1422,68 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, > } > #else > static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, > - TCGv_i64 addr, int size, int is_pair) > -{ > - qemu_log_mask(LOG_UNIMP, > - "%s:%d: system mode store_exclusive unsupported " > - "at pc=%016" PRIx64 "\n", > - __FILE__, __LINE__, s->pc - 4); > + TCGv_i64 inaddr, int size, int is_pair) > +{ > + /* if (env->exclusive_addr == addr && env->exclusive_val == [addr] > + * && (!is_pair || env->exclusive_high == [addr + datasize])) { > + * [addr] = {Rt}; > + * 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, tmp, cpu_exclusive_high, fail_label); s/tmp/tmphi/ > + > + tcg_temp_free_i64(tmphi); > + tcg_temp_free_i64(addrhi); Can addrhi be saved and free after doing store? > + } > + > + /* 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 > > -- > 1.8.5 > > _______________________________________________ > kvmarm mailing list > kvmarm@lists.cs.columbia.edu > https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
On 22 January 2014 02:19, Hu Tao <hutao@cn.fujitsu.com> wrote: > On Tue, Jan 21, 2014 at 08:12:12PM +0000, Peter Maydell wrote: >> + 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, tmp, cpu_exclusive_high, fail_label); > > s/tmp/tmphi/ Thanks, nice catch. >> + >> + tcg_temp_free_i64(tmphi); >> + tcg_temp_free_i64(addrhi); > > Can addrhi be saved and free after doing store? It would have to be made a local-temp to avoid the branch trashing it. I preferred to make it a local and recalculate for the store on the basis that the TCG backend really ought to be capable of turning "add tmp, addr, 4; load from tmp" into a single "load from addr+4" instruction, and having the constant go into a local-temp would probably defeat that. thanks -- PMM
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index e0f6765..5aa1f17 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -1422,12 +1422,68 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, } #else static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, - TCGv_i64 addr, int size, int is_pair) -{ - qemu_log_mask(LOG_UNIMP, - "%s:%d: system mode store_exclusive unsupported " - "at pc=%016" PRIx64 "\n", - __FILE__, __LINE__, s->pc - 4); + TCGv_i64 inaddr, int size, int is_pair) +{ + /* if (env->exclusive_addr == addr && env->exclusive_val == [addr] + * && (!is_pair || env->exclusive_high == [addr + datasize])) { + * [addr] = {Rt}; + * 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, tmp, 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
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> --- target-arm/translate-a64.c | 68 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 6 deletions(-)