MTM0 loads the low Octeon3 multiplier operand pair from rs/rt into MPL[0] and MPL[3], starts a new multiplier chain, sets MPL[1] to zero, and resets partial products. Model the architecturally unpredictable MPL[2], MPL[4], and MPL[5] lanes as zero for deterministic emulation.
Legacy single-source encodings have rt encoded as $zero, so the same translator path also preserves the older Octeon behavior. Signed-off-by: James Hilliard <[email protected]> --- Changes v2 -> v3: - Split MTM0 out of the combined Octeon arithmetic and memory instruction patch. (requested by Richard Henderson) Changes v3 -> v4: - Keep the Octeon3 two-source rt high-lane operand and document that legacy one-source MTM encodings use rt == $zero. Changes v5 -> v6: - Clarify the CN71XX-defined MPL1 zeroing and the modeled-zero unpredictable MPL lanes. --- target/mips/tcg/octeon.decode | 2 ++ target/mips/tcg/octeon_translate.c | 58 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode index 01ed3b50be..5f5a509106 100644 --- a/target/mips/tcg/octeon.decode +++ b/target/mips/tcg/octeon.decode @@ -43,6 +43,8 @@ SEQ 011100 ..... ..... ..... 00000 101010 @r3 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 +&r2 rs rt +MTM0 011100 rs:5 rt:5 00000 00000 001000 &r2 &saa base rt @saa ...... base:5 rt:5 ................ &saa diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c index d89e53045e..5c2575a5be 100644 --- a/target/mips/tcg/octeon_translate.c +++ b/target/mips/tcg/octeon_translate.c @@ -203,6 +203,63 @@ static bool trans_ZCB(DisasContext *ctx, arg_ZCB *a) return true; } + +static void octeon_store_mpl(unsigned int index, TCGv_i64 value) +{ + tcg_gen_st_i64(value, tcg_env, + offsetof(CPUMIPSState, active_tc.octeon.MPL) + + index * sizeof(uint64_t)); +} + +static void octeon_store_p(unsigned int index, TCGv_i64 value) +{ + tcg_gen_st_i64(value, tcg_env, + offsetof(CPUMIPSState, active_tc.octeon.P) + + index * sizeof(uint64_t)); +} + +static void octeon_zero_partial_product_state(void) +{ + TCGv_i64 zero = tcg_constant_i64(0); + + for (int i = 0; i < OCTEON_MULTIPLIER_REGS; i++) { + octeon_store_p(i, zero); + } +} + +static void octeon_reset_mtm0_mpl_state(void) +{ + TCGv_i64 zero = tcg_constant_i64(0); + + /* + * MTM0 defines MPL1 as zero; model the architecturally unpredictable + * MPL2/MPL4/MPL5 lanes as zero for deterministic emulation. + */ + octeon_store_mpl(1, zero); + octeon_store_mpl(2, zero); + octeon_store_mpl(4, zero); + octeon_store_mpl(5, zero); +} + +static bool trans_mtm(DisasContext *ctx, arg_r2 *a, unsigned int index) +{ + TCGv_i64 value = tcg_temp_new_i64(); + + /* + * Octeon3 two-source MTM forms load lane index from rs and lane index + 3 + * from rt. Legacy one-source forms encode rt as $zero. + */ + gen_load_gpr(value, a->rs); + octeon_store_mpl(index, value); + gen_load_gpr(value, a->rt); + octeon_store_mpl(index + 3, value); + if (index == 0) { + octeon_reset_mtm0_mpl_state(); + } + octeon_zero_partial_product_state(); + return true; +} + TRANS(LBX, trans_lx, MO_SB); TRANS(LBUX, trans_lx, MO_UB); TRANS(LHX, trans_lx, MO_SW); @@ -210,3 +267,4 @@ TRANS(LHUX, trans_lx, MO_UW); TRANS(LWX, trans_lx, MO_SL); TRANS(LWUX, trans_lx, MO_UL); TRANS(LDX, trans_lx, MO_UQ); +TRANS(MTM0, trans_mtm, 0); -- 2.54.0
