SAA is an Octeon+ instruction that atomically adds rt to the naturally aligned 32-bit word at base and discards the old memory value.
Add an Octeon+ feature bit, enable it for Octeon68XX, and implement the common SAA/SAAD translator with TCG atomic_fetch_add_i64. The MemOp selects the word or doubleword transaction size. Signed-off-by: James Hilliard <[email protected]> --- Changes v2 -> v3: - Split SAA out of the combined Octeon arithmetic and memory instruction patch. (requested by Richard Henderson) Changes v3 -> v4: - Gate SAA/SAAD behind an Octeon+ feature bit. (reported by Richard Henderson) - Use the i64 TCG atomic add path for both word and doubleword sizes. (suggested by Richard Henderson) --- target/mips/cpu-defs.c.inc | 2 +- target/mips/mips-defs.h | 1 + target/mips/tcg/octeon.decode | 4 ++++ target/mips/tcg/octeon_translate.c | 19 +++++++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/target/mips/cpu-defs.c.inc b/target/mips/cpu-defs.c.inc index faefab0473..69e02532c4 100644 --- a/target/mips/cpu-defs.c.inc +++ b/target/mips/cpu-defs.c.inc @@ -1014,7 +1014,7 @@ const mips_def_t mips_defs[] = .CP0_Status_rw_bitmask = 0x12F8FFFF, .SEGBITS = 42, .PABITS = 49, - .insn_flags = CPU_MIPS64R2 | INSN_OCTEON, + .insn_flags = CPU_MIPS64R2 | INSN_OCTEON | INSN_OCTEONP, .mmu_type = MMU_TYPE_R4000, }, diff --git a/target/mips/mips-defs.h b/target/mips/mips-defs.h index 9d4d292586..386e7179c8 100644 --- a/target/mips/mips-defs.h +++ b/target/mips/mips-defs.h @@ -41,6 +41,7 @@ #define INSN_LOONGSON2F 0x0000080000000000ULL #define INSN_LOONGSON3A 0x0000100000000000ULL #define INSN_OCTEON 0x0000200000000000ULL +#define INSN_OCTEONP 0x0000400000000000ULL /* * bits 52-63: vendor-specific ASEs */ diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode index db7d5f55f0..d6b241de42 100644 --- a/target/mips/tcg/octeon.decode +++ b/target/mips/tcg/octeon.decode @@ -44,6 +44,10 @@ SNE 011100 ..... ..... ..... 00000 101011 @r3 SEQI 011100 rs:5 rt:5 imm:s10 101110 &cmpi SNEI 011100 rs:5 rt:5 imm:s10 101111 &cmpi +&saa base rt +@saa ...... base:5 rt:5 ................ &saa +SAA 011100 ..... ..... 00000 00000 011000 @saa + &lx base index rd @lx ...... base:5 index:5 rd:5 ...... ..... &lx LWX 011111 ..... ..... ..... 00000 001010 @lx diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c index c93eff59a5..548ab1b220 100644 --- a/target/mips/tcg/octeon_translate.c +++ b/target/mips/tcg/octeon_translate.c @@ -161,6 +161,25 @@ static bool trans_lx(DisasContext *ctx, arg_lx *a, MemOp mop) return true; } +static bool trans_saa(DisasContext *ctx, arg_saa *a, MemOp mop) +{ + TCGv_i64 addr = tcg_temp_new_i64(); + TCGv_i64 value = tcg_temp_new_i64(); + TCGv_i64 old = tcg_temp_new_i64(); + MemOp amo = mo_endian(ctx) | mop | MO_ALIGN; + + if (unlikely(!(ctx->insn_flags & INSN_OCTEONP))) { + gen_reserved_instruction(ctx); + return true; + } + + gen_base_offset_addr(ctx, addr, a->base, 0); + gen_load_gpr(value, a->rt); + tcg_gen_atomic_fetch_add_i64(old, addr, value, ctx->mem_idx, amo); + return true; +} + +TRANS(SAA, trans_saa, MO_UL); TRANS(LBX, trans_lx, MO_SB); TRANS(LBUX, trans_lx, MO_UB); TRANS(LHX, trans_lx, MO_SW); -- 2.54.0
