Introduce the 'Parallel Subtract' opcodes: - PSUBB (Parallel Subtract Byte) - PSUBH (Parallel Subtract Halfword) - PSUBW (Parallel Subtract Word)
Signed-off-by: Philippe Mathieu-Daudé <f4...@amsat.org> --- target/mips/tx79.decode | 6 ++++ target/mips/tx79_translate.c | 61 ++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/target/mips/tx79.decode b/target/mips/tx79.decode index 26c80b9bce5..d1c07c7d901 100644 --- a/target/mips/tx79.decode +++ b/target/mips/tx79.decode @@ -29,6 +29,12 @@ MTHI1 011100 ..... 0000000000 00000 010001 @rs MFLO1 011100 0000000000 ..... 00000 010010 @rd MTLO1 011100 ..... 0000000000 00000 010011 @rs +# MMI0 + +PSUBW 011100 ..... ..... ..... 00001 001000 @rs_rt_rd +PSUBH 011100 ..... ..... ..... 00101 001000 @rs_rt_rd +PSUBB 011100 ..... ..... ..... 01001 001000 @rs_rt_rd + # MMI2 PCPYLD 011100 ..... ..... ..... 01110 001001 @rs_rt_rd diff --git a/target/mips/tx79_translate.c b/target/mips/tx79_translate.c index 28d07baaa73..23146f6bfac 100644 --- a/target/mips/tx79_translate.c +++ b/target/mips/tx79_translate.c @@ -115,6 +115,67 @@ static bool trans_MTLO1(DisasContext *ctx, arg_rtype *a) * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word */ +static bool trans_parallel_substract(DisasContext *ctx, arg_rtype *a, unsigned wlen) +{ + TCGv_i64 ax, bx, t0, t1, t2; + + if (a->rd == 0) { + /* nop */ + return true; + } + + 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_sub_i64(t2, t0, t1); + 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_sub_i64(t2, t0, t1); + 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); + + return true; +} + +/* Parallel Subtract Byte */ +static bool trans_PSUBB(DisasContext *ctx, arg_rtype *a) +{ + return trans_parallel_substract(ctx, a, 8); +} + +/* Parallel Subtract Halfword */ +static bool trans_PSUBH(DisasContext *ctx, arg_rtype *a) +{ + return trans_parallel_substract(ctx, a, 16); +} + +/* Parallel Subtract Word */ +static bool trans_PSUBW(DisasContext *ctx, arg_rtype *a) +{ + return trans_parallel_substract(ctx, a, 32); +} + /* * Min/Max (4 instructions) * ------------------------ -- 2.26.2