Introduce the 'Parallel Compare for Equal' opcodes:
- PCEQB (Parallel Compare for Equal Byte)
- PCEQH (Parallel Compare for Equal Halfword)
- PCEQW (Parallel Compare for Equal Word)
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
target/mips/tx79.decode | 3 ++
target/mips/tx79_translate.c | 66 ++++++++++++++++++++++++++++++++++++
2 files changed, 69 insertions(+)
diff --git a/target/mips/tx79.decode b/target/mips/tx79.decode
index 98f21d33e3f..cfe721755ca 100644
--- a/target/mips/tx79.decode
+++ b/target/mips/tx79.decode
@@ -40,6 +40,9 @@ PEXTLB 011100 ..... ..... ..... 11010 001000 @rs_rt_rd
# MMI1
+PCEQW 011100 ..... ..... ..... 00010 101000 @rs_rt_rd
+PCEQH 011100 ..... ..... ..... 00110 101000 @rs_rt_rd
+PCEQB 011100 ..... ..... ..... 01010 101000 @rs_rt_rd
PEXTUW 011100 ..... ..... ..... 10010 101000 @rs_rt_rd
# MMI2
diff --git a/target/mips/tx79_translate.c b/target/mips/tx79_translate.c
index 11968d6edab..f084faa48a7 100644
--- a/target/mips/tx79_translate.c
+++ b/target/mips/tx79_translate.c
@@ -279,6 +279,72 @@ static bool trans_PNOR(DisasContext *ctx, arg_rtype *a)
* PCEQW rd, rs, rt Parallel Compare for Equal Word
*/
+static bool trans_parallel_compare(DisasContext *ctx, arg_rtype *a,
+ TCGCond cond, unsigned wlen)
+{
+ TCGv_i64 c0, c1, ax, bx, t0, t1, t2;
+
+ if (a->rd == 0) {
+ /* nop */
+ return true;
+ }
+
+ c0 = tcg_const_tl(0);
+ c1 = tcg_const_tl(0xffffffff);
+ ax = tcg_temp_new_i64();
+ bx = tcg_temp_new_i64();
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ t2 = tcg_temp_new_i64();
+
+ /* Lower halve */
+ gen_load_gpr(ax, a->rs);
+ gen_load_gpr(bx, a->rt);
+ for (int i = 0; i < (64 / wlen); i++) {
+ tcg_gen_sextract_i64(t0, ax, wlen * i, wlen);
+ tcg_gen_sextract_i64(t1, bx, wlen * i, wlen);
+ tcg_gen_movcond_i64(cond, t2, t1, t0, c1, c0);
+ tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], t2, wlen * i, wlen);
+ }
+ /* Upper halve */
+ gen_load_gpr_hi(ax, a->rs);
+ gen_load_gpr_hi(bx, a->rt);
+ for (int i = 0; i < (64 / wlen); i++) {
+ tcg_gen_sextract_i64(t0, ax, wlen * i, wlen);
+ tcg_gen_sextract_i64(t1, bx, wlen * i, wlen);
+ tcg_gen_movcond_i64(cond, t2, t1, t0, c1, c0);
+ tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], t2, wlen * i, wlen);
+ }
+
+ tcg_temp_free(t2);
+ tcg_temp_free(t1);
+ tcg_temp_free(t0);
+ tcg_temp_free(bx);
+ tcg_temp_free(ax);
+ tcg_temp_free(c1);
+ tcg_temp_free(c0);
+
+ return true;
+}
+
+/* Parallel Compare for Equal Byte */
+static bool trans_PCEQB(DisasContext *ctx, arg_rtype *a)
+{
+ return trans_parallel_compare(ctx, a, TCG_COND_EQ, 8);
+}
+
+/* Parallel Compare for Equal Halfword */
+static bool trans_PCEQH(DisasContext *ctx, arg_rtype *a)
+{
+ return trans_parallel_compare(ctx, a, TCG_COND_EQ, 16);
+}
+
+/* Parallel Compare for Equal Word */
+static bool trans_PCEQW(DisasContext *ctx, arg_rtype *a)
+{
+ return trans_parallel_compare(ctx, a, TCG_COND_EQ, 32);
+}
+
/*
* LZC (1 instruction)
* -------------------
--
2.26.2