Re: [Qemu-devel] [RFC v3 06/13] target-i386: translate: implement qemu_ldlink and qemu_stcond ops
Alvise Rigo a.r...@virtualopensystems.com writes: Implement strex and ldrex instruction relying on TCG's qemu_ldlink and qemu_stcond. For the time being only 32bit configurations are supported. Suggested-by: Jani Kokkonen jani.kokko...@huawei.com Suggested-by: Claudio Fontana claudio.font...@huawei.com Signed-off-by: Alvise Rigo a.r...@virtualopensystems.com --- tcg/i386/tcg-target.c | 136 ++ 1 file changed, 114 insertions(+), 22 deletions(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 0d7c99c..d8250a9 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -1141,6 +1141,17 @@ static void * const qemu_ld_helpers[16] = { [MO_BEQ] = helper_be_ldq_mmu, }; +/* LoadLink helpers, only unsigned. Use the macro below to access them. */ +static void * const qemu_ldex_helpers[16] = { +[MO_LEUL] = helper_le_ldlinkul_mmu, +}; + +#define LDEX_HELPER(mem_op) \ +({ \ +assert(mem_op MO_EXCL); \ +qemu_ldex_helpers[((int)mem_op - MO_EXCL)]; \ +}) + /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr, * uintxx_t val, int mmu_idx, uintptr_t ra) */ @@ -1154,6 +1165,17 @@ static void * const qemu_st_helpers[16] = { [MO_BEQ] = helper_be_stq_mmu, }; +/* StoreConditional helpers. Use the macro below to access them. */ +static void * const qemu_stex_helpers[16] = { +[MO_LEUL] = helper_le_stcondl_mmu, +}; + +#define STEX_HELPER(mem_op) \ +({ \ +assert(mem_op MO_EXCL); \ +qemu_stex_helpers[(int)mem_op - MO_EXCL]; \ +}) + Same comments as for target-arm. Do we need to be protecting backends with HAS_LDST_EXCL defines or some such macro hackery? What currently happens if you use the new TCG ops when the backend doesn't support them? Is supporting all backends a prerequisite for the series? /* Perform the TLB load and compare. Inputs: @@ -1249,6 +1271,7 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi, * for a load or store, so that we can later generate the correct helper code */ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi, +TCGReg llsc_success, TCGReg datalo, TCGReg datahi, TCGReg addrlo, TCGReg addrhi, tcg_insn_unit *raddr, @@ -1257,6 +1280,7 @@ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi, TCGLabelQemuLdst *label = new_ldst_label(s); label-is_ld = is_ld; +label-llsc_success = llsc_success; label-oi = oi; label-datalo_reg = datalo; label-datahi_reg = datahi; @@ -1311,7 +1335,11 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) (uintptr_t)l-raddr); } -tcg_out_call(s, qemu_ld_helpers[opc (MO_BSWAP | MO_SIZE)]); +if (opc MO_EXCL) { +tcg_out_call(s, LDEX_HELPER(opc)); +} else { +tcg_out_call(s, qemu_ld_helpers[opc ~MO_SIGN]); +} data_reg = l-datalo_reg; switch (opc MO_SSIZE) { @@ -1415,9 +1443,16 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) } } -/* Tail call to the helper, with the return address back inline. */ -tcg_out_push(s, retaddr); -tcg_out_jmp(s, qemu_st_helpers[opc (MO_BSWAP | MO_SIZE)]); +if (opc MO_EXCL) { +tcg_out_call(s, STEX_HELPER(opc)); +/* Save the output of the StoreConditional */ +tcg_out_mov(s, TCG_TYPE_I32, l-llsc_success, TCG_REG_EAX); +tcg_out_jmp(s, l-raddr); +} else { +/* Tail call to the helper, with the return address back inline. */ +tcg_out_push(s, retaddr); +tcg_out_jmp(s, qemu_st_helpers[opc]); +} } #elif defined(__x86_64__) defined(__linux__) # include asm/prctl.h @@ -1530,7 +1565,8 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, /* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and EAX. It will be useful once fixed registers globals are less common. */ -static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64) +static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64, +bool isLoadLink) { TCGReg datalo, datahi, addrlo; TCGReg addrhi __attribute__((unused)); @@ -1553,14 +1589,34 @@ static void
Re: [Qemu-devel] [RFC v3 06/13] target-i386: translate: implement qemu_ldlink and qemu_stcond ops
On Fri, Jul 17, 2015 at 2:56 PM, Alex Bennée alex.ben...@linaro.org wrote: Alvise Rigo a.r...@virtualopensystems.com writes: Implement strex and ldrex instruction relying on TCG's qemu_ldlink and qemu_stcond. For the time being only 32bit configurations are supported. Suggested-by: Jani Kokkonen jani.kokko...@huawei.com Suggested-by: Claudio Fontana claudio.font...@huawei.com Signed-off-by: Alvise Rigo a.r...@virtualopensystems.com --- tcg/i386/tcg-target.c | 136 ++ 1 file changed, 114 insertions(+), 22 deletions(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 0d7c99c..d8250a9 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -1141,6 +1141,17 @@ static void * const qemu_ld_helpers[16] = { [MO_BEQ] = helper_be_ldq_mmu, }; +/* LoadLink helpers, only unsigned. Use the macro below to access them. */ +static void * const qemu_ldex_helpers[16] = { +[MO_LEUL] = helper_le_ldlinkul_mmu, +}; + +#define LDEX_HELPER(mem_op) \ +({ \ +assert(mem_op MO_EXCL); \ +qemu_ldex_helpers[((int)mem_op - MO_EXCL)]; \ +}) + /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr, * uintxx_t val, int mmu_idx, uintptr_t ra) */ @@ -1154,6 +1165,17 @@ static void * const qemu_st_helpers[16] = { [MO_BEQ] = helper_be_stq_mmu, }; +/* StoreConditional helpers. Use the macro below to access them. */ +static void * const qemu_stex_helpers[16] = { +[MO_LEUL] = helper_le_stcondl_mmu, +}; + +#define STEX_HELPER(mem_op) \ +({ \ +assert(mem_op MO_EXCL); \ +qemu_stex_helpers[(int)mem_op - MO_EXCL]; \ +}) + Same comments as for target-arm. Do we need to be protecting backends with HAS_LDST_EXCL defines or some such macro hackery? What currently happens if you use the new TCG ops when the backend doesn't support them? Is supporting all backends a prerequisite for the series? I think that the ideal approach would be to have all the backends implementing the slowpath for atomic instructions so that the HAS_LDST_EXCL macro will not be needed. Then a frontend can rely on the slowpath or not. So, ideally, it's a prerequisite. Regards, alvise /* Perform the TLB load and compare. Inputs: @@ -1249,6 +1271,7 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi, * for a load or store, so that we can later generate the correct helper code */ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi, +TCGReg llsc_success, TCGReg datalo, TCGReg datahi, TCGReg addrlo, TCGReg addrhi, tcg_insn_unit *raddr, @@ -1257,6 +1280,7 @@ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi, TCGLabelQemuLdst *label = new_ldst_label(s); label-is_ld = is_ld; +label-llsc_success = llsc_success; label-oi = oi; label-datalo_reg = datalo; label-datahi_reg = datahi; @@ -1311,7 +1335,11 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) (uintptr_t)l-raddr); } -tcg_out_call(s, qemu_ld_helpers[opc (MO_BSWAP | MO_SIZE)]); +if (opc MO_EXCL) { +tcg_out_call(s, LDEX_HELPER(opc)); +} else { +tcg_out_call(s, qemu_ld_helpers[opc ~MO_SIGN]); +} data_reg = l-datalo_reg; switch (opc MO_SSIZE) { @@ -1415,9 +1443,16 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) } } -/* Tail call to the helper, with the return address back inline. */ -tcg_out_push(s, retaddr); -tcg_out_jmp(s, qemu_st_helpers[opc (MO_BSWAP | MO_SIZE)]); +if (opc MO_EXCL) { +tcg_out_call(s, STEX_HELPER(opc)); +/* Save the output of the StoreConditional */ +tcg_out_mov(s, TCG_TYPE_I32, l-llsc_success, TCG_REG_EAX); +tcg_out_jmp(s, l-raddr); +} else { +/* Tail call to the helper, with the return address back inline. */ +tcg_out_push(s, retaddr); +tcg_out_jmp(s, qemu_st_helpers[opc]); +} } #elif defined(__x86_64__) defined(__linux__) # include asm/prctl.h @@ -1530,7 +1565,8 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, /* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and EAX. It will be useful once fixed registers globals are less common. */
[Qemu-devel] [RFC v3 06/13] target-i386: translate: implement qemu_ldlink and qemu_stcond ops
Implement strex and ldrex instruction relying on TCG's qemu_ldlink and qemu_stcond. For the time being only 32bit configurations are supported. Suggested-by: Jani Kokkonen jani.kokko...@huawei.com Suggested-by: Claudio Fontana claudio.font...@huawei.com Signed-off-by: Alvise Rigo a.r...@virtualopensystems.com --- tcg/i386/tcg-target.c | 136 ++ 1 file changed, 114 insertions(+), 22 deletions(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 0d7c99c..d8250a9 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -1141,6 +1141,17 @@ static void * const qemu_ld_helpers[16] = { [MO_BEQ] = helper_be_ldq_mmu, }; +/* LoadLink helpers, only unsigned. Use the macro below to access them. */ +static void * const qemu_ldex_helpers[16] = { +[MO_LEUL] = helper_le_ldlinkul_mmu, +}; + +#define LDEX_HELPER(mem_op) \ +({ \ +assert(mem_op MO_EXCL); \ +qemu_ldex_helpers[((int)mem_op - MO_EXCL)]; \ +}) + /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr, * uintxx_t val, int mmu_idx, uintptr_t ra) */ @@ -1154,6 +1165,17 @@ static void * const qemu_st_helpers[16] = { [MO_BEQ] = helper_be_stq_mmu, }; +/* StoreConditional helpers. Use the macro below to access them. */ +static void * const qemu_stex_helpers[16] = { +[MO_LEUL] = helper_le_stcondl_mmu, +}; + +#define STEX_HELPER(mem_op) \ +({ \ +assert(mem_op MO_EXCL); \ +qemu_stex_helpers[(int)mem_op - MO_EXCL]; \ +}) + /* Perform the TLB load and compare. Inputs: @@ -1249,6 +1271,7 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi, * for a load or store, so that we can later generate the correct helper code */ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi, +TCGReg llsc_success, TCGReg datalo, TCGReg datahi, TCGReg addrlo, TCGReg addrhi, tcg_insn_unit *raddr, @@ -1257,6 +1280,7 @@ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi, TCGLabelQemuLdst *label = new_ldst_label(s); label-is_ld = is_ld; +label-llsc_success = llsc_success; label-oi = oi; label-datalo_reg = datalo; label-datahi_reg = datahi; @@ -1311,7 +1335,11 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) (uintptr_t)l-raddr); } -tcg_out_call(s, qemu_ld_helpers[opc (MO_BSWAP | MO_SIZE)]); +if (opc MO_EXCL) { +tcg_out_call(s, LDEX_HELPER(opc)); +} else { +tcg_out_call(s, qemu_ld_helpers[opc ~MO_SIGN]); +} data_reg = l-datalo_reg; switch (opc MO_SSIZE) { @@ -1415,9 +1443,16 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) } } -/* Tail call to the helper, with the return address back inline. */ -tcg_out_push(s, retaddr); -tcg_out_jmp(s, qemu_st_helpers[opc (MO_BSWAP | MO_SIZE)]); +if (opc MO_EXCL) { +tcg_out_call(s, STEX_HELPER(opc)); +/* Save the output of the StoreConditional */ +tcg_out_mov(s, TCG_TYPE_I32, l-llsc_success, TCG_REG_EAX); +tcg_out_jmp(s, l-raddr); +} else { +/* Tail call to the helper, with the return address back inline. */ +tcg_out_push(s, retaddr); +tcg_out_jmp(s, qemu_st_helpers[opc]); +} } #elif defined(__x86_64__) defined(__linux__) # include asm/prctl.h @@ -1530,7 +1565,8 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, /* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and EAX. It will be useful once fixed registers globals are less common. */ -static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64) +static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64, +bool isLoadLink) { TCGReg datalo, datahi, addrlo; TCGReg addrhi __attribute__((unused)); @@ -1553,14 +1589,34 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64) mem_index = get_mmuidx(oi); s_bits = opc MO_SIZE; -tcg_out_tlb_load(s, addrlo, addrhi, mem_index, s_bits, - label_ptr, offsetof(CPUTLBEntry, addr_read)); +if (isLoadLink) { +TCGType t = ((TCG_TARGET_REG_BITS == 64) (TARGET_LONG_BITS == 64)) ? + TCG_TYPE_I64 : TCG_TYPE_I32; +/* The JMP address will