target/ppc: Move add and subf type fixed-point arithmetic instructions to decodetree

This patch moves the below instructions to decodetree specification:

        {add, subf}[c,e,me,ze][o][.]       : XO-form
        addic[.], subfic                   : D-form
        addex                              : Z23-form

This patch introduces XO form instructions into decode tree
specification, for which all the four variations([o][.]) have been
handled with a single pattern. The changes were verified by validating
that the tcg ops generated by those instructions remain the same, which
were captured with the '-d in_asm,op' flag.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
Signed-off-by: Chinmay Rath <rathc@linux.ibm.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
This commit is contained in:
Chinmay Rath 2024-02-14 15:10:27 +05:30 committed by Nicholas Piggin
parent 623d9065b6
commit a9bd40d937
3 changed files with 96 additions and 136 deletions

View File

@ -187,6 +187,12 @@
&X_a ra
@X_a ...... ra:3 .. ..... ..... .......... . &X_a
&XO rt ra rb oe:bool rc:bool
@XO ...... rt:5 ra:5 rb:5 oe:1 ......... rc:1 &XO
&XO_ta rt ra oe:bool rc:bool
@XO_ta ...... rt:5 ra:5 ..... oe:1 ......... rc:1 &XO_ta
%xx_xt 0:1 21:5
%xx_xb 1:1 11:5
%xx_xa 2:1 16:5
@ -322,10 +328,30 @@ CMPLI 001010 ... - . ..... ................ @D_bfu
### Fixed-Point Arithmetic Instructions
ADD 011111 ..... ..... ..... . 100001010 . @XO
ADDC 011111 ..... ..... ..... . 000001010 . @XO
ADDE 011111 ..... ..... ..... . 010001010 . @XO
# ADDEX is Z23-form, with CY=0; all other values for CY are reserved.
# This works out the same as X-form.
ADDEX 011111 ..... ..... ..... 00 10101010 - @X
ADDI 001110 ..... ..... ................ @D
ADDIS 001111 ..... ..... ................ @D
ADDIC 001100 ..... ..... ................ @D
ADDIC_ 001101 ..... ..... ................ @D
ADDPCIS 010011 ..... ..... .......... 00010 . @DX
ADDME 011111 ..... ..... ----- . 011101010 . @XO_ta
ADDZE 011111 ..... ..... ----- . 011001010 . @XO_ta
SUBF 011111 ..... ..... ..... . 000101000 . @XO
SUBFIC 001000 ..... ..... ................ @D
SUBFC 011111 ..... ..... ..... . 000001000 . @XO
SUBFE 011111 ..... ..... ..... . 010001000 . @XO
SUBFME 011111 ..... ..... ----- . 011101000 . @XO_ta
SUBFZE 011111 ..... ..... ----- . 011001000 . @XO_ta
## Fixed-Point Logical Instructions

View File

@ -1735,61 +1735,6 @@ static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
tcg_gen_mov_tl(ret, t0);
}
}
/* Add functions with two operands */
#define GEN_INT_ARITH_ADD(name, opc3, ca, add_ca, compute_ca, compute_ov) \
static void glue(gen_, name)(DisasContext *ctx) \
{ \
gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
ca, glue(ca, 32), \
add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
}
/* Add functions with one operand and one immediate */
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, ca, \
add_ca, compute_ca, compute_ov) \
static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv t0 = tcg_constant_tl(const_val); \
gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
cpu_gpr[rA(ctx->opcode)], t0, \
ca, glue(ca, 32), \
add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
}
/* add add. addo addo. */
GEN_INT_ARITH_ADD(add, 0x08, cpu_ca, 0, 0, 0)
GEN_INT_ARITH_ADD(addo, 0x18, cpu_ca, 0, 0, 1)
/* addc addc. addco addco. */
GEN_INT_ARITH_ADD(addc, 0x00, cpu_ca, 0, 1, 0)
GEN_INT_ARITH_ADD(addco, 0x10, cpu_ca, 0, 1, 1)
/* adde adde. addeo addeo. */
GEN_INT_ARITH_ADD(adde, 0x04, cpu_ca, 1, 1, 0)
GEN_INT_ARITH_ADD(addeo, 0x14, cpu_ca, 1, 1, 1)
/* addme addme. addmeo addmeo. */
GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, cpu_ca, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, cpu_ca, 1, 1, 1)
/* addex */
GEN_INT_ARITH_ADD(addex, 0x05, cpu_ov, 1, 1, 0);
/* addze addze. addzeo addzeo.*/
GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, cpu_ca, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, cpu_ca, 1, 1, 1)
/* addic addic.*/
static inline void gen_op_addic(DisasContext *ctx, bool compute_rc0)
{
TCGv c = tcg_constant_tl(SIMM(ctx->opcode));
gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
c, cpu_ca, cpu_ca32, 0, 1, 0, compute_rc0);
}
static void gen_addic(DisasContext *ctx)
{
gen_op_addic(ctx, 0);
}
static void gen_addic_(DisasContext *ctx)
{
gen_op_addic(ctx, 1);
}
static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
TCGv arg2, int sign, int compute_ov)
@ -2210,47 +2155,6 @@ static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
tcg_gen_mov_tl(ret, t0);
}
}
/* Sub functions with Two operands functions */
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
static void glue(gen_, name)(DisasContext *ctx) \
{ \
gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
}
/* Sub functions with one operand and one immediate */
#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
add_ca, compute_ca, compute_ov) \
static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv t0 = tcg_constant_tl(const_val); \
gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
cpu_gpr[rA(ctx->opcode)], t0, \
add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
}
/* subf subf. subfo subfo. */
GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
/* subfc subfc. subfco subfco. */
GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
/* subfe subfe. subfeo subfo. */
GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
/* subfme subfme. subfmeo subfmeo. */
GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
/* subfze subfze. subfzeo subfzeo.*/
GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
/* subfic */
static void gen_subfic(DisasContext *ctx)
{
TCGv c = tcg_constant_tl(SIMM(ctx->opcode));
gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
c, 0, 1, 0, 0);
}
/* neg neg. nego nego. */
static inline void gen_op_arith_neg(DisasContext *ctx, bool compute_ov)
@ -6524,8 +6428,6 @@ GEN_HANDLER_E(cmpeqb, 0x1F, 0x00, 0x07, 0x00600000, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x00000001, PPC_NONE, PPC2_ISA205),
GEN_HANDLER_E(cmprb, 0x1F, 0x00, 0x06, 0x00400001, PPC_NONE, PPC2_ISA300),
GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER),
GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER),
GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER),
@ -6536,7 +6438,6 @@ GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B),
#endif
GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER),
GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER),
GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER),
@ -6747,25 +6648,6 @@ GEN_HANDLER_E(maddhd_maddhdu, 0x04, 0x18, 0xFF, 0x00000000, PPC_NONE,
GEN_HANDLER_E(maddld, 0x04, 0x19, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA300),
#endif
#undef GEN_INT_ARITH_ADD
#undef GEN_INT_ARITH_ADD_CONST
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER),
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \
add_ca, compute_ca, compute_ov) \
GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER),
GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
GEN_HANDLER_E(addex, 0x1F, 0x0A, 0x05, 0x00000000, PPC_NONE, PPC2_ISA300),
GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
#undef GEN_INT_ARITH_DIVW
#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)
@ -6804,24 +6686,6 @@ GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02),
GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17),
#endif
#undef GEN_INT_ARITH_SUBF
#undef GEN_INT_ARITH_SUBF_CONST
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER),
#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
add_ca, compute_ca, compute_ov) \
GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER),
GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
#undef GEN_LOGICAL1
#undef GEN_LOGICAL2
#define GEN_LOGICAL2(name, tcg_op, opc, type) \

View File

@ -325,6 +325,76 @@ static bool trans_ADDPCIS(DisasContext *ctx, arg_DX *a)
return true;
}
static bool trans_ADDEX(DisasContext *ctx, arg_X *a)
{
REQUIRE_INSNS_FLAGS2(ctx, ISA300);
gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
cpu_ov, cpu_ov32, true, true, false, false);
return true;
}
static bool do_add_D(DisasContext *ctx, arg_D *a, bool add_ca, bool compute_ca,
bool compute_ov, bool compute_rc0)
{
gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra],
tcg_constant_tl(a->si), cpu_ca, cpu_ca32,
add_ca, compute_ca, compute_ov, compute_rc0);
return true;
}
static bool do_add_XO(DisasContext *ctx, arg_XO *a, bool add_ca,
bool compute_ca)
{
gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
cpu_ca, cpu_ca32, add_ca, compute_ca, a->oe, a->rc);
return true;
}
static bool do_add_const_XO(DisasContext *ctx, arg_XO_ta *a, TCGv const_val,
bool add_ca, bool compute_ca)
{
gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], const_val,
cpu_ca, cpu_ca32, add_ca, compute_ca, a->oe, a->rc);
return true;
}
TRANS(ADD, do_add_XO, false, false);
TRANS(ADDC, do_add_XO, false, true);
TRANS(ADDE, do_add_XO, true, true);
TRANS(ADDME, do_add_const_XO, tcg_constant_tl(-1LL), true, true);
TRANS(ADDZE, do_add_const_XO, tcg_constant_tl(0), true, true);
TRANS(ADDIC, do_add_D, false, true, false, false);
TRANS(ADDIC_, do_add_D, false, true, false, true);
static bool trans_SUBFIC(DisasContext *ctx, arg_D *a)
{
gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra],
tcg_constant_tl(a->si), false, true, false, false);
return true;
}
static bool do_subf_XO(DisasContext *ctx, arg_XO *a, bool add_ca,
bool compute_ca)
{
gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
add_ca, compute_ca, a->oe, a->rc);
return true;
}
static bool do_subf_const_XO(DisasContext *ctx, arg_XO_ta *a, TCGv const_val,
bool add_ca, bool compute_ca)
{
gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], const_val,
add_ca, compute_ca, a->oe, a->rc);
return true;
}
TRANS(SUBF, do_subf_XO, false, false)
TRANS(SUBFC, do_subf_XO, false, true)
TRANS(SUBFE, do_subf_XO, true, true)
TRANS(SUBFME, do_subf_const_XO, tcg_constant_tl(-1LL), true, true)
TRANS(SUBFZE, do_subf_const_XO, tcg_constant_tl(0), true, true)
static bool trans_INVALID(DisasContext *ctx, arg_INVALID *a)
{
gen_invalid(ctx);