diff mbox series

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

Message ID 20240214094027.895376-1-rathc@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series [v2] target/ppc: Move add and subf type fixed-point arithmetic instructions to decodetree | expand

Commit Message

Chinmay Rath Feb. 14, 2024, 9:40 a.m. UTC
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.

Signed-off-by: Chinmay Rath <rathc@linux.ibm.com>
---
Changes v1 -> v2 :
Reused X format for ADDEX instead of creating a new Z23_tab_cy
format. (Richard)
Added necessary instruction flag checks for ADDEX. (self-review)
---
 target/ppc/insn32.decode                   |  26 ++++
 target/ppc/translate.c                     | 136 ---------------------
 target/ppc/translate/fixedpoint-impl.c.inc |  70 +++++++++++
 3 files changed, 96 insertions(+), 136 deletions(-)

Comments

Richard Henderson Feb. 14, 2024, 7:09 p.m. UTC | #1
On 2/13/24 23:40, Chinmay Rath wrote:
> 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.
> 
> Signed-off-by: Chinmay Rath<rathc@linux.ibm.com>
> ---
> Changes v1 -> v2 :
> Reused X format for ADDEX instead of creating a new Z23_tab_cy
> format. (Richard)
> Added necessary instruction flag checks for ADDEX. (self-review)
> ---
>   target/ppc/insn32.decode                   |  26 ++++
>   target/ppc/translate.c                     | 136 ---------------------
>   target/ppc/translate/fixedpoint-impl.c.inc |  70 +++++++++++
>   3 files changed, 96 insertions(+), 136 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~
Harsh Prateek Bora Feb. 19, 2024, 4:22 a.m. UTC | #2
On 2/14/24 15:10, Chinmay Rath wrote:
> 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.
> 
> Signed-off-by: Chinmay Rath <rathc@linux.ibm.com>

Reviewed-by: Harsh Prateek Bora <harshpb@linux.ibm.com>

> ---
> Changes v1 -> v2 :
> Reused X format for ADDEX instead of creating a new Z23_tab_cy
> format. (Richard)
> Added necessary instruction flag checks for ADDEX. (self-review)
> ---
>   target/ppc/insn32.decode                   |  26 ++++
>   target/ppc/translate.c                     | 136 ---------------------
>   target/ppc/translate/fixedpoint-impl.c.inc |  70 +++++++++++
>   3 files changed, 96 insertions(+), 136 deletions(-)
> 
> diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
> index 4fcf3af8d0..eada59f59f 100644
> --- a/target/ppc/insn32.decode
> +++ b/target/ppc/insn32.decode
> @@ -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
>   
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index 049f636927..51dc1e79cc 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -1697,61 +1697,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)
> @@ -2172,47 +2117,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)
> @@ -6486,8 +6390,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),
> @@ -6498,7 +6400,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),
> @@ -6709,25 +6610,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)
> @@ -6766,24 +6648,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)                                 \
> diff --git a/target/ppc/translate/fixedpoint-impl.c.inc b/target/ppc/translate/fixedpoint-impl.c.inc
> index 51c6fa7330..0c66465d96 100644
> --- a/target/ppc/translate/fixedpoint-impl.c.inc
> +++ b/target/ppc/translate/fixedpoint-impl.c.inc
> @@ -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);
diff mbox series

Patch

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 4fcf3af8d0..eada59f59f 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -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
 
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 049f636927..51dc1e79cc 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -1697,61 +1697,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)
@@ -2172,47 +2117,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)
@@ -6486,8 +6390,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),
@@ -6498,7 +6400,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),
@@ -6709,25 +6610,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)
@@ -6766,24 +6648,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)                                 \
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc b/target/ppc/translate/fixedpoint-impl.c.inc
index 51c6fa7330..0c66465d96 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -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);