The A32 and T32 load-acquire instructions LDA, LDAB and LDAH must be
ordered before the memory accesses that follow them, so their
translator has to emit a trailing barrier.  op_lda() emits that barrier
with TCG_BAR_STRL instead of TCG_BAR_LDAQ, inverting the polarity:
TCG_BAR_STRL annotates a leading barrier ("previous ops will not be
delayed") and TCG_BAR_LDAQ a trailing one ("following ops will not come
forward"), as documented in include/tcg/tcg-mo.h.

The x86 and aarch64 backends only look at the TCG_MO_* bits, which the
wrong annotation does not affect, so the generated host code is
unchanged on those hosts.  The annotation is still wrong: it violates
the TCG barrier contract, it lets the optimizer's barrier merging in
fold_mb() combine the barriers of an "LDA; STL" pair into a weaker one
than the correctly annotated form (STRL|STRL stays STRL instead of
LDAQ|STRL = SC), and it diverges from every other load-acquire
translation in the target, which all use TCG_BAR_LDAQ.

Fix the polarity.

Signed-off-by: LIU Zhiwei <[email protected]>
---
 target/arm/tcg/translate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index bddac41bf9..a81b8d3852 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -4421,7 +4421,7 @@ static bool op_lda(DisasContext *s, arg_LDA *a, MemOp mop)
     disas_set_da_iss(s, mop, a->rt | ISSIsAcqRel);
 
     store_reg(s, a->rt, tmp);
-    tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
+    tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
     return true;
 }
 
-- 
2.43.0


Reply via email to