From: Aboorva Devarajan <[email protected]>

Move below instructions to decodetree specification:

        lwat, stwat     : X-form (word atomic, ISA 3.0)
        ldat, stdat     : X-form (doubleword atomic, ISA 3.0)

The legacy gen_ld_atomic()/gen_st_atomic() functions that read register
fields and the function code from ctx->opcode are replaced by new
do_ld_atomic()/do_st_atomic() helpers in fixedpoint-impl.c.inc that
use the pre-extracted decodetree argument fields (a->rt, a->ra, a->rb)
directly.  The RB field carries the Function Code (FC) selecting the
atomic operation.

gen_fetch_inc_conditional() is similarly moved and refactored to accept
the destination register number as an explicit parameter instead of
extracting it from ctx->opcode.

Checked with '-d in_asm,op'.  The printed TCG ops may differ from the
pre-refactor log because EA now uses do_ea_calc(ctx, ra, 0), which lowers
as GPR[ra] + 0 (then narrow in 32-bit mode) instead of mov/ext32u from ra
alone.

Signed-off-by: Aboorva Devarajan <[email protected]>
Signed-off-by: Chinmay Rath <[email protected]>
---
 target/ppc/insn32.decode                   |   7 +
 target/ppc/translate.c                     | 212 --------------------
 target/ppc/translate/fixedpoint-impl.c.inc | 215 +++++++++++++++++++++
 3 files changed, 222 insertions(+), 212 deletions(-)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 4a28fad64b..f35f7113a0 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -343,6 +343,13 @@ LSKU            111010 ..... ..... ............. 0 11   @DD
 LCXU            111010 ..... ..... ............. 1 11   @DD
 
 
+### Fixed-Point Atomic Load/Store Instructions
+
+LWAT            011111 ..... ..... ..... 1001000110 -   @X
+STWAT           011111 ..... ..... ..... 1011000110 -   @X
+LDAT            011111 ..... ..... ..... 1001100110 -   @X
+STDAT           011111 ..... ..... ..... 1011100110 -   @X
+
 ### Fixed-Point Store Instructions
 
 STB             100110 ..... ..... ................     @D
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 7bfbba85d0..2345bf8867 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -2741,212 +2741,6 @@ static void gen_isync(DisasContext *ctx)
     ctx->base.is_jmp = DISAS_EXIT_UPDATE;
 }
 
-static void gen_fetch_inc_conditional(DisasContext *ctx, MemOp memop,
-                                      TCGv EA, TCGCond cond, int addend)
-{
-    TCGv t = tcg_temp_new();
-    TCGv t2 = tcg_temp_new();
-    TCGv u = tcg_temp_new();
-
-    tcg_gen_qemu_ld_tl(t, EA, ctx->mem_idx, memop);
-    tcg_gen_addi_tl(t2, EA, memop_size(memop));
-    tcg_gen_qemu_ld_tl(t2, t2, ctx->mem_idx, memop);
-    tcg_gen_addi_tl(u, t, addend);
-
-    /* E.g. for fetch and increment bounded... */
-    /* mem(EA,s) = (t != t2 ? u = t + 1 : t) */
-    tcg_gen_movcond_tl(cond, u, t, t2, u, t);
-    tcg_gen_qemu_st_tl(u, EA, ctx->mem_idx, memop);
-
-    /* RT = (t != t2 ? t : u = 1<<(s*8-1)) */
-    tcg_gen_movcond_tl(cond, cpu_gpr[rD(ctx->opcode)], t, t2, t,
-                       tcg_constant_tl(1 << (memop_size(memop) * 8 - 1)));
-}
-
-static void gen_ld_atomic(DisasContext *ctx, MemOp memop)
-{
-    uint32_t gpr_FC = FC(ctx->opcode);
-    TCGv EA = tcg_temp_new();
-    int rt = rD(ctx->opcode);
-    bool need_serial;
-    TCGv src, dst;
-
-    gen_addr_register(ctx, EA);
-    dst = cpu_gpr[rt];
-    src = cpu_gpr[(rt + 1) & 31];
-
-    need_serial = false;
-    memop |= MO_ALIGN;
-    switch (gpr_FC) {
-    case 0: /* Fetch and add */
-        tcg_gen_atomic_fetch_add_tl(dst, EA, src, ctx->mem_idx, memop);
-        break;
-    case 1: /* Fetch and xor */
-        tcg_gen_atomic_fetch_xor_tl(dst, EA, src, ctx->mem_idx, memop);
-        break;
-    case 2: /* Fetch and or */
-        tcg_gen_atomic_fetch_or_tl(dst, EA, src, ctx->mem_idx, memop);
-        break;
-    case 3: /* Fetch and 'and' */
-        tcg_gen_atomic_fetch_and_tl(dst, EA, src, ctx->mem_idx, memop);
-        break;
-    case 4:  /* Fetch and max unsigned */
-        tcg_gen_atomic_fetch_umax_tl(dst, EA, src, ctx->mem_idx, memop);
-        break;
-    case 5:  /* Fetch and max signed */
-        tcg_gen_atomic_fetch_smax_tl(dst, EA, src, ctx->mem_idx, memop);
-        break;
-    case 6:  /* Fetch and min unsigned */
-        tcg_gen_atomic_fetch_umin_tl(dst, EA, src, ctx->mem_idx, memop);
-        break;
-    case 7:  /* Fetch and min signed */
-        tcg_gen_atomic_fetch_smin_tl(dst, EA, src, ctx->mem_idx, memop);
-        break;
-    case 8: /* Swap */
-        tcg_gen_atomic_xchg_tl(dst, EA, src, ctx->mem_idx, memop);
-        break;
-
-    case 16: /* Compare and swap not equal */
-        if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
-            need_serial = true;
-        } else {
-            TCGv t0 = tcg_temp_new();
-            TCGv t1 = tcg_temp_new();
-
-            tcg_gen_qemu_ld_tl(t0, EA, ctx->mem_idx, memop);
-            if ((memop & MO_SIZE) == MO_64 || TARGET_LONG_BITS == 32) {
-                tcg_gen_mov_tl(t1, src);
-            } else {
-                tcg_gen_ext32u_tl(t1, src);
-            }
-            tcg_gen_movcond_tl(TCG_COND_NE, t1, t0, t1,
-                               cpu_gpr[(rt + 2) & 31], t0);
-            tcg_gen_qemu_st_tl(t1, EA, ctx->mem_idx, memop);
-            tcg_gen_mov_tl(dst, t0);
-        }
-        break;
-
-    case 24: /* Fetch and increment bounded */
-        if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
-            need_serial = true;
-        } else {
-            gen_fetch_inc_conditional(ctx, memop, EA, TCG_COND_NE, 1);
-        }
-        break;
-    case 25: /* Fetch and increment equal */
-        if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
-            need_serial = true;
-        } else {
-            gen_fetch_inc_conditional(ctx, memop, EA, TCG_COND_EQ, 1);
-        }
-        break;
-    case 28: /* Fetch and decrement bounded */
-        if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
-            need_serial = true;
-        } else {
-            gen_fetch_inc_conditional(ctx, memop, EA, TCG_COND_NE, -1);
-        }
-        break;
-
-    default:
-        /* invoke data storage error handler */
-        gen_exception_err(ctx, POWERPC_EXCP_DSI, POWERPC_EXCP_INVAL);
-    }
-
-    if (need_serial) {
-        /* Restart with exclusive lock.  */
-        gen_helper_exit_atomic(tcg_env);
-        ctx->base.is_jmp = DISAS_NORETURN;
-    }
-}
-
-static void gen_lwat(DisasContext *ctx)
-{
-    gen_ld_atomic(ctx, DEF_MEMOP(MO_UL));
-}
-
-#ifdef TARGET_PPC64
-static void gen_ldat(DisasContext *ctx)
-{
-    gen_ld_atomic(ctx, DEF_MEMOP(MO_UQ));
-}
-#endif
-
-static void gen_st_atomic(DisasContext *ctx, MemOp memop)
-{
-    uint32_t gpr_FC = FC(ctx->opcode);
-    TCGv EA = tcg_temp_new();
-    TCGv src, discard;
-
-    gen_addr_register(ctx, EA);
-    src = cpu_gpr[rD(ctx->opcode)];
-    discard = tcg_temp_new();
-
-    memop |= MO_ALIGN;
-    switch (gpr_FC) {
-    case 0: /* add and Store */
-        tcg_gen_atomic_add_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
-        break;
-    case 1: /* xor and Store */
-        tcg_gen_atomic_xor_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
-        break;
-    case 2: /* Or and Store */
-        tcg_gen_atomic_or_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
-        break;
-    case 3: /* 'and' and Store */
-        tcg_gen_atomic_and_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
-        break;
-    case 4:  /* Store max unsigned */
-        tcg_gen_atomic_umax_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
-        break;
-    case 5:  /* Store max signed */
-        tcg_gen_atomic_smax_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
-        break;
-    case 6:  /* Store min unsigned */
-        tcg_gen_atomic_umin_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
-        break;
-    case 7:  /* Store min signed */
-        tcg_gen_atomic_smin_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
-        break;
-    case 24: /* Store twin  */
-        if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
-            /* Restart with exclusive lock.  */
-            gen_helper_exit_atomic(tcg_env);
-            ctx->base.is_jmp = DISAS_NORETURN;
-        } else {
-            TCGv t = tcg_temp_new();
-            TCGv t2 = tcg_temp_new();
-            TCGv s = tcg_temp_new();
-            TCGv s2 = tcg_temp_new();
-            TCGv ea_plus_s = tcg_temp_new();
-
-            tcg_gen_qemu_ld_tl(t, EA, ctx->mem_idx, memop);
-            tcg_gen_addi_tl(ea_plus_s, EA, memop_size(memop));
-            tcg_gen_qemu_ld_tl(t2, ea_plus_s, ctx->mem_idx, memop);
-            tcg_gen_movcond_tl(TCG_COND_EQ, s, t, t2, src, t);
-            tcg_gen_movcond_tl(TCG_COND_EQ, s2, t, t2, src, t2);
-            tcg_gen_qemu_st_tl(s, EA, ctx->mem_idx, memop);
-            tcg_gen_qemu_st_tl(s2, ea_plus_s, ctx->mem_idx, memop);
-        }
-        break;
-    default:
-        /* invoke data storage error handler */
-        gen_exception_err(ctx, POWERPC_EXCP_DSI, POWERPC_EXCP_INVAL);
-    }
-}
-
-static void gen_stwat(DisasContext *ctx)
-{
-    gen_st_atomic(ctx, DEF_MEMOP(MO_UL));
-}
-
-#ifdef TARGET_PPC64
-static void gen_stdat(DisasContext *ctx)
-{
-    gen_st_atomic(ctx, DEF_MEMOP(MO_UQ));
-}
-#endif
-
 /* wait */
 static void gen_wait(DisasContext *ctx)
 {
@@ -5608,12 +5402,6 @@ GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, 
PPC_STRING),
 GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
 GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
 GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
-GEN_HANDLER_E(lwat, 0x1F, 0x06, 0x12, 0x00000001, PPC_NONE, PPC2_ISA300),
-GEN_HANDLER_E(stwat, 0x1F, 0x06, 0x16, 0x00000001, PPC_NONE, PPC2_ISA300),
-#if defined(TARGET_PPC64)
-GEN_HANDLER_E(ldat, 0x1F, 0x06, 0x13, 0x00000001, PPC_NONE, PPC2_ISA300),
-GEN_HANDLER_E(stdat, 0x1F, 0x06, 0x17, 0x00000001, PPC_NONE, PPC2_ISA300),
-#endif
 /* ISA v3.0 changed the extended opcode from 62 to 30 */
 GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x039FF801, PPC_WAIT),
 GEN_HANDLER_E(wait, 0x1F, 0x1E, 0x00, 0x039CF801, PPC_NONE, PPC2_ISA300),
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc 
b/target/ppc/translate/fixedpoint-impl.c.inc
index 25a60d3d3a..4d35133adc 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -1646,3 +1646,218 @@ static bool trans_SRAWI(DisasContext *ctx, arg_SRAWI *a)
     }
     return true;
 }
+
+static void do_fetch_inc_conditional(DisasContext *ctx, MemOp memop,
+                                     TCGv EA, int rt,
+                                     TCGCond cond, int addend)
+{
+    TCGv t = tcg_temp_new();
+    TCGv t2 = tcg_temp_new();
+    TCGv u = tcg_temp_new();
+
+    tcg_gen_qemu_ld_tl(t, EA, ctx->mem_idx, memop);
+    tcg_gen_addi_tl(t2, EA, memop_size(memop));
+    tcg_gen_qemu_ld_tl(t2, t2, ctx->mem_idx, memop);
+    tcg_gen_addi_tl(u, t, addend);
+
+    /* mem(EA,s) = (t cond t2 ? u = t + addend : t) */
+    tcg_gen_movcond_tl(cond, u, t, t2, u, t);
+    tcg_gen_qemu_st_tl(u, EA, ctx->mem_idx, memop);
+
+    /* RT = (t cond t2 ? t : 1<<(s*8-1)) */
+    tcg_gen_movcond_tl(cond, cpu_gpr[rt], t, t2, t,
+                       tcg_constant_tl(1 << (memop_size(memop) * 8 - 1)));
+}
+
+/*
+ * Fixed-Point Atomic Load/Store Instructions
+ *
+ * In the X-form encoding the RB field carries the Function Code (FC)
+ * that selects the atomic operation.  EA is computed from RA alone.
+ */
+static bool do_ld_atomic(DisasContext *ctx, arg_X *a, MemOp memop)
+{
+    TCGv EA, dst, src;
+    bool need_serial;
+
+    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+
+    EA = do_ea_calc(ctx, a->ra, tcg_constant_tl(0));
+    dst = cpu_gpr[a->rt];
+    src = cpu_gpr[(a->rt + 1) & 31];
+
+    need_serial = false;
+    memop |= MO_ALIGN;
+    switch (a->rb) {
+    case 0: /* Fetch and add */
+        tcg_gen_atomic_fetch_add_tl(dst, EA, src, ctx->mem_idx, memop);
+        break;
+    case 1: /* Fetch and xor */
+        tcg_gen_atomic_fetch_xor_tl(dst, EA, src, ctx->mem_idx, memop);
+        break;
+    case 2: /* Fetch and or */
+        tcg_gen_atomic_fetch_or_tl(dst, EA, src, ctx->mem_idx, memop);
+        break;
+    case 3: /* Fetch and 'and' */
+        tcg_gen_atomic_fetch_and_tl(dst, EA, src, ctx->mem_idx, memop);
+        break;
+    case 4: /* Fetch and max unsigned */
+        tcg_gen_atomic_fetch_umax_tl(dst, EA, src, ctx->mem_idx, memop);
+        break;
+    case 5: /* Fetch and max signed */
+        tcg_gen_atomic_fetch_smax_tl(dst, EA, src, ctx->mem_idx, memop);
+        break;
+    case 6: /* Fetch and min unsigned */
+        tcg_gen_atomic_fetch_umin_tl(dst, EA, src, ctx->mem_idx, memop);
+        break;
+    case 7: /* Fetch and min signed */
+        tcg_gen_atomic_fetch_smin_tl(dst, EA, src, ctx->mem_idx, memop);
+        break;
+    case 8: /* Swap */
+        tcg_gen_atomic_xchg_tl(dst, EA, src, ctx->mem_idx, memop);
+        break;
+
+    case 16: /* Compare and swap not equal */
+        if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
+            need_serial = true;
+        } else {
+            TCGv t0 = tcg_temp_new();
+            TCGv t1 = tcg_temp_new();
+
+            tcg_gen_qemu_ld_tl(t0, EA, ctx->mem_idx, memop);
+            if ((memop & MO_SIZE) == MO_64 || TARGET_LONG_BITS == 32) {
+                tcg_gen_mov_tl(t1, src);
+            } else {
+                tcg_gen_ext32u_tl(t1, src);
+            }
+            tcg_gen_movcond_tl(TCG_COND_NE, t1, t0, t1,
+                               cpu_gpr[(a->rt + 2) & 31], t0);
+            tcg_gen_qemu_st_tl(t1, EA, ctx->mem_idx, memop);
+            tcg_gen_mov_tl(dst, t0);
+        }
+        break;
+
+    case 24: /* Fetch and increment bounded */
+        if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
+            need_serial = true;
+        } else {
+            do_fetch_inc_conditional(ctx, memop, EA, a->rt, TCG_COND_NE, 1);
+        }
+        break;
+    case 25: /* Fetch and increment equal */
+        if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
+            need_serial = true;
+        } else {
+            do_fetch_inc_conditional(ctx, memop, EA, a->rt, TCG_COND_EQ, 1);
+        }
+        break;
+    case 28: /* Fetch and decrement bounded */
+        if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
+            need_serial = true;
+        } else {
+            do_fetch_inc_conditional(ctx, memop, EA, a->rt, TCG_COND_NE, -1);
+        }
+        break;
+
+    default:
+        /* invoke data storage error handler */
+        gen_exception_err(ctx, POWERPC_EXCP_DSI, POWERPC_EXCP_INVAL);
+        return true;
+    }
+
+    if (need_serial) {
+        /* Restart with exclusive lock.  */
+        gen_helper_exit_atomic(tcg_env);
+        ctx->base.is_jmp = DISAS_NORETURN;
+    }
+    return true;
+}
+
+static bool do_st_atomic(DisasContext *ctx, arg_X *a, MemOp memop)
+{
+    TCGv EA, src, discard;
+
+    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+
+    EA = do_ea_calc(ctx, a->ra, tcg_constant_tl(0));
+    src = cpu_gpr[a->rt];
+    discard = tcg_temp_new();
+
+    memop |= MO_ALIGN;
+    switch (a->rb) {
+    case 0: /* add and Store */
+        tcg_gen_atomic_add_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
+        break;
+    case 1: /* xor and Store */
+        tcg_gen_atomic_xor_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
+        break;
+    case 2: /* Or and Store */
+        tcg_gen_atomic_or_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
+        break;
+    case 3: /* 'and' and Store */
+        tcg_gen_atomic_and_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
+        break;
+    case 4: /* Store max unsigned */
+        tcg_gen_atomic_umax_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
+        break;
+    case 5: /* Store max signed */
+        tcg_gen_atomic_smax_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
+        break;
+    case 6: /* Store min unsigned */
+        tcg_gen_atomic_umin_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
+        break;
+    case 7: /* Store min signed */
+        tcg_gen_atomic_smin_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
+        break;
+    case 24: /* Store twin */
+        if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
+            /* Restart with exclusive lock.  */
+            gen_helper_exit_atomic(tcg_env);
+            ctx->base.is_jmp = DISAS_NORETURN;
+        } else {
+            TCGv t = tcg_temp_new();
+            TCGv t2 = tcg_temp_new();
+            TCGv s = tcg_temp_new();
+            TCGv s2 = tcg_temp_new();
+            TCGv ea_plus_s = tcg_temp_new();
+
+            tcg_gen_qemu_ld_tl(t, EA, ctx->mem_idx, memop);
+            tcg_gen_addi_tl(ea_plus_s, EA, memop_size(memop));
+            tcg_gen_qemu_ld_tl(t2, ea_plus_s, ctx->mem_idx, memop);
+            tcg_gen_movcond_tl(TCG_COND_EQ, s, t, t2, src, t);
+            tcg_gen_movcond_tl(TCG_COND_EQ, s2, t, t2, src, t2);
+            tcg_gen_qemu_st_tl(s, EA, ctx->mem_idx, memop);
+            tcg_gen_qemu_st_tl(s2, ea_plus_s, ctx->mem_idx, memop);
+        }
+        break;
+    default:
+        /* invoke data storage error handler */
+        gen_exception_err(ctx, POWERPC_EXCP_DSI, POWERPC_EXCP_INVAL);
+    }
+    return true;
+}
+
+TRANS(LWAT, do_ld_atomic, DEF_MEMOP(MO_UL))
+TRANS(STWAT, do_st_atomic, DEF_MEMOP(MO_UL))
+
+static bool trans_LDAT(DisasContext *ctx, arg_LDAT *a)
+{
+    REQUIRE_64BIT(ctx);
+#if defined(TARGET_PPC64)
+    return do_ld_atomic(ctx, a, DEF_MEMOP(MO_UQ));
+#else
+    qemu_build_not_reached();
+#endif
+    return true;
+}
+
+static bool trans_STDAT(DisasContext *ctx, arg_STDAT *a)
+{
+    REQUIRE_64BIT(ctx);
+#if defined(TARGET_PPC64)
+    return do_st_atomic(ctx, a, DEF_MEMOP(MO_UQ));
+#else
+    qemu_build_not_reached();
+#endif
+    return true;
+}
-- 
2.53.0


Reply via email to