MTM0 loads the low Octeon3 multiplier operand pair from rs/rt into MPL[0] and MPL[3], starts a new multiplier chain, clears the upper multiplier limbs not populated by MTM0, and resets partial products.
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. --- target/mips/tcg/octeon.decode | 2 ++ target/mips/tcg/octeon_translate.c | 53 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode index 5377f7b3ef..bf1dab61e1 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 3373f4532c..126aa41b21 100644 --- a/target/mips/tcg/octeon_translate.c +++ b/target/mips/tcg/octeon_translate.c @@ -198,6 +198,58 @@ 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_clear_upper_multiplier_state(void) +{ + TCGv_i64 zero = tcg_constant_i64(0); + + 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_clear_upper_multiplier_state(); + } + octeon_zero_partial_product_state(); + return true; +} + TRANS(SAA, trans_saa, MO_UL); TRANS(SAAD, trans_saa, MO_UQ); TRANS(LBX, trans_lx, MO_SB); @@ -207,3 +259,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
