target/ppc: Move cmp{rb, eqb}, tw[i], td[i], isel instructions to decodetree.

Moving the following instructions to decodetree specification :

	cmp{rb, eqb}, t{w, d}	: X-form
	t{w, d}i		: D-form
	isel			: A-form

The changes were verified by validating that the tcg ops generated by those
instructions remain the same, which were captured using the '-d in_asm,op' flag.
Also for CMPRB, following review comments :
Replaced repetition of arithmetic right shifting (tcg_gen_shri_i32) followed
by extraction of last 8 bits (tcg_gen_ext8u_i32) with extraction of the required
bits using offsets (tcg_gen_extract_i32).

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Chinmay Rath <rathc@linux.ibm.com>
[np: 32-bit compile fix]
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
This commit is contained in:
Chinmay Rath 2024-04-23 12:02:33 +05:30 committed by Nicholas Piggin
parent f424bc10eb
commit ae556c6a49
6 changed files with 157 additions and 136 deletions

View File

@ -2742,7 +2742,7 @@ void helper_rfmci(CPUPPCState *env)
}
#endif /* !CONFIG_USER_ONLY */
void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
void helper_TW(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
uint32_t flags)
{
if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
@ -2756,7 +2756,7 @@ void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
}
#ifdef TARGET_PPC64
void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
void helper_TD(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
uint32_t flags)
{
if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||

View File

@ -1,8 +1,8 @@
DEF_HELPER_FLAGS_3(raise_exception_err, TCG_CALL_NO_WG, noreturn, env, i32, i32)
DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_WG, noreturn, env, i32)
DEF_HELPER_FLAGS_4(tw, TCG_CALL_NO_WG, void, env, tl, tl, i32)
DEF_HELPER_FLAGS_4(TW, TCG_CALL_NO_WG, void, env, tl, tl, i32)
#if defined(TARGET_PPC64)
DEF_HELPER_FLAGS_4(td, TCG_CALL_NO_WG, void, env, tl, tl, i32)
DEF_HELPER_FLAGS_4(TD, TCG_CALL_NO_WG, void, env, tl, tl, i32)
#endif
DEF_HELPER_4(HASHST, void, env, tl, tl, tl)
DEF_HELPER_4(HASHCHK, void, env, tl, tl, tl)
@ -67,7 +67,7 @@ DEF_HELPER_FLAGS_2(PEXTD, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_1(CDTBCD, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_1(CBCDTD, TCG_CALL_NO_RWG_SE, tl, tl)
#if defined(TARGET_PPC64)
DEF_HELPER_FLAGS_2(cmpeqb, TCG_CALL_NO_RWG_SE, i32, tl, tl)
DEF_HELPER_FLAGS_2(CMPEQB, TCG_CALL_NO_RWG_SE, i32, tl, tl)
DEF_HELPER_FLAGS_1(popcntw, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_2(bpermd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_3(srad, tl, env, tl, tl)

View File

@ -29,6 +29,9 @@
&A_tb frt frb rc:bool
@A_tb ...... frt:5 ..... frb:5 ..... ..... rc:1 &A_tb
&A_tab_bc rt ra rb bc
@A_tab_bc ...... rt:5 ra:5 rb:5 bc:5 ..... . &A_tab_bc
&D rt ra si:int64_t
@D ...... rt:5 ra:5 si:s16 &D
@ -340,6 +343,19 @@ CMP 011111 ... - . ..... ..... 0000000000 - @X_bfl
CMPL 011111 ... - . ..... ..... 0000100000 - @X_bfl
CMPI 001011 ... - . ..... ................ @D_bfs
CMPLI 001010 ... - . ..... ................ @D_bfu
CMPRB 011111 ... - . ..... ..... 0011000000 - @X_bfl
CMPEQB 011111 ... -- ..... ..... 0011100000 - @X_bf
### Fixed-Point Trap Instructions
TW 011111 ..... ..... ..... 0000000100 - @X
TD 011111 ..... ..... ..... 0001000100 - @X
TWI 000011 ..... ..... ................ @D
TDI 000010 ..... ..... ................ @D
### Fixed-Point Select Instruction
ISEL 011111 ..... ..... ..... ..... 01111 - @A_tab_bc
### Fixed-Point Arithmetic Instructions

View File

@ -159,7 +159,7 @@ uint64_t helper_DIVDE(CPUPPCState *env, uint64_t rau, uint64_t rbu, uint32_t oe)
/* When you XOR the pattern and there is a match, that byte will be zero */
#define hasvalue(x, n) (haszero((x) ^ pattern(n)))
uint32_t helper_cmpeqb(target_ulong ra, target_ulong rb)
uint32_t helper_CMPEQB(target_ulong ra, target_ulong rb)
{
return hasvalue(rb, ra) ? CRF_GT : 0;
}

View File

@ -1563,66 +1563,6 @@ static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
}
}
/* cmprb - range comparison: isupper, isaplha, islower*/
static void gen_cmprb(DisasContext *ctx)
{
TCGv_i32 src1 = tcg_temp_new_i32();
TCGv_i32 src2 = tcg_temp_new_i32();
TCGv_i32 src2lo = tcg_temp_new_i32();
TCGv_i32 src2hi = tcg_temp_new_i32();
TCGv_i32 crf = cpu_crf[crfD(ctx->opcode)];
tcg_gen_trunc_tl_i32(src1, cpu_gpr[rA(ctx->opcode)]);
tcg_gen_trunc_tl_i32(src2, cpu_gpr[rB(ctx->opcode)]);
tcg_gen_andi_i32(src1, src1, 0xFF);
tcg_gen_ext8u_i32(src2lo, src2);
tcg_gen_shri_i32(src2, src2, 8);
tcg_gen_ext8u_i32(src2hi, src2);
tcg_gen_setcond_i32(TCG_COND_LEU, src2lo, src2lo, src1);
tcg_gen_setcond_i32(TCG_COND_LEU, src2hi, src1, src2hi);
tcg_gen_and_i32(crf, src2lo, src2hi);
if (ctx->opcode & 0x00200000) {
tcg_gen_shri_i32(src2, src2, 8);
tcg_gen_ext8u_i32(src2lo, src2);
tcg_gen_shri_i32(src2, src2, 8);
tcg_gen_ext8u_i32(src2hi, src2);
tcg_gen_setcond_i32(TCG_COND_LEU, src2lo, src2lo, src1);
tcg_gen_setcond_i32(TCG_COND_LEU, src2hi, src1, src2hi);
tcg_gen_and_i32(src2lo, src2lo, src2hi);
tcg_gen_or_i32(crf, crf, src2lo);
}
tcg_gen_shli_i32(crf, crf, CRF_GT_BIT);
}
#if defined(TARGET_PPC64)
/* cmpeqb */
static void gen_cmpeqb(DisasContext *ctx)
{
gen_helper_cmpeqb(cpu_crf[crfD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
cpu_gpr[rB(ctx->opcode)]);
}
#endif
/* isel (PowerPC 2.03 specification) */
static void gen_isel(DisasContext *ctx)
{
uint32_t bi = rC(ctx->opcode);
uint32_t mask = 0x08 >> (bi & 0x03);
TCGv t0 = tcg_temp_new();
TCGv zr;
tcg_gen_extu_i32_tl(t0, cpu_crf[bi >> 2]);
tcg_gen_andi_tl(t0, t0, mask);
zr = tcg_constant_tl(0);
tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rD(ctx->opcode)], t0, zr,
rA(ctx->opcode) ? cpu_gpr[rA(ctx->opcode)] : zr,
cpu_gpr[rB(ctx->opcode)]);
}
/* cmpb: PowerPC 2.05 specification */
static void gen_cmpb(DisasContext *ctx)
{
@ -4187,76 +4127,20 @@ static void gen_scv(DisasContext *ctx)
/*** Trap ***/
/* Check for unconditional traps (always or never) */
static bool check_unconditional_trap(DisasContext *ctx)
static bool check_unconditional_trap(DisasContext *ctx, int to)
{
/* Trap never */
if (TO(ctx->opcode) == 0) {
if (to == 0) {
return true;
}
/* Trap always */
if (TO(ctx->opcode) == 31) {
if (to == 31) {
gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
return true;
}
return false;
}
/* tw */
static void gen_tw(DisasContext *ctx)
{
TCGv_i32 t0;
if (check_unconditional_trap(ctx)) {
return;
}
t0 = tcg_constant_i32(TO(ctx->opcode));
gen_helper_tw(tcg_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
t0);
}
/* twi */
static void gen_twi(DisasContext *ctx)
{
TCGv t0;
TCGv_i32 t1;
if (check_unconditional_trap(ctx)) {
return;
}
t0 = tcg_constant_tl(SIMM(ctx->opcode));
t1 = tcg_constant_i32(TO(ctx->opcode));
gen_helper_tw(tcg_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
}
#if defined(TARGET_PPC64)
/* td */
static void gen_td(DisasContext *ctx)
{
TCGv_i32 t0;
if (check_unconditional_trap(ctx)) {
return;
}
t0 = tcg_constant_i32(TO(ctx->opcode));
gen_helper_td(tcg_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
t0);
}
/* tdi */
static void gen_tdi(DisasContext *ctx)
{
TCGv t0;
TCGv_i32 t1;
if (check_unconditional_trap(ctx)) {
return;
}
t0 = tcg_constant_tl(SIMM(ctx->opcode));
t1 = tcg_constant_i32(TO(ctx->opcode));
gen_helper_td(tcg_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
}
#endif
/*** Processor control ***/
/* mcrxr */
@ -6058,12 +5942,7 @@ GEN_HANDLER_E(brw, 0x1F, 0x1B, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA310),
GEN_HANDLER_E(brh, 0x1F, 0x1B, 0x06, 0x0000F801, PPC_NONE, PPC2_ISA310),
#endif
GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
#if defined(TARGET_PPC64)
GEN_HANDLER_E(cmpeqb, 0x1F, 0x00, 0x07, 0x00600000, PPC_NONE, PPC2_ISA300),
#endif
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_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),
@ -6160,12 +6039,6 @@ GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
/* Top bit of opc2 corresponds with low bit of LEV, so use two handlers */
GEN_HANDLER(sc, 0x11, 0x11, 0xFF, 0x03FFF01D, PPC_FLOW),
GEN_HANDLER(sc, 0x11, 0x01, 0xFF, 0x03FFF01D, PPC_FLOW),
GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW),
GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
#if defined(TARGET_PPC64)
GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B),
GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B),
#endif
GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC),
GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC),
GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC),

View File

@ -289,6 +289,50 @@ TRANS(CMPL, do_cmp_X, false);
TRANS(CMPI, do_cmp_D, true);
TRANS(CMPLI, do_cmp_D, false);
static bool trans_CMPRB(DisasContext *ctx, arg_CMPRB *a)
{
TCGv_i32 src1 = tcg_temp_new_i32();
TCGv_i32 src2 = tcg_temp_new_i32();
TCGv_i32 src2lo = tcg_temp_new_i32();
TCGv_i32 src2hi = tcg_temp_new_i32();
TCGv_i32 crf = cpu_crf[a->bf];
REQUIRE_INSNS_FLAGS2(ctx, ISA300);
tcg_gen_trunc_tl_i32(src1, cpu_gpr[a->ra]);
tcg_gen_trunc_tl_i32(src2, cpu_gpr[a->rb]);
tcg_gen_andi_i32(src1, src1, 0xFF);
tcg_gen_ext8u_i32(src2lo, src2);
tcg_gen_extract_i32(src2hi, src2, 8, 8);
tcg_gen_setcond_i32(TCG_COND_LEU, src2lo, src2lo, src1);
tcg_gen_setcond_i32(TCG_COND_LEU, src2hi, src1, src2hi);
tcg_gen_and_i32(crf, src2lo, src2hi);
if (a->l) {
tcg_gen_extract_i32(src2lo, src2, 16, 8);
tcg_gen_extract_i32(src2hi, src2, 24, 8);
tcg_gen_setcond_i32(TCG_COND_LEU, src2lo, src2lo, src1);
tcg_gen_setcond_i32(TCG_COND_LEU, src2hi, src1, src2hi);
tcg_gen_and_i32(src2lo, src2lo, src2hi);
tcg_gen_or_i32(crf, crf, src2lo);
}
tcg_gen_shli_i32(crf, crf, CRF_GT_BIT);
return true;
}
static bool trans_CMPEQB(DisasContext *ctx, arg_CMPEQB *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_INSNS_FLAGS2(ctx, ISA300);
#if defined(TARGET_PPC64)
gen_helper_CMPEQB(cpu_crf[a->bf], cpu_gpr[a->ra], cpu_gpr[a->rb]);
#else
qemu_build_not_reached();
#endif
return true;
}
/*
* Fixed-Point Arithmetic Instructions
*/
@ -690,6 +734,94 @@ static bool trans_DIVDEU(DisasContext *ctx, arg_DIVDEU *a)
TRANS64(MODSD, do_modd, true);
TRANS64(MODUD, do_modd, false);
/*
* Fixed-Point Select Instructions
*/
static bool trans_ISEL(DisasContext *ctx, arg_ISEL *a)
{
REQUIRE_INSNS_FLAGS(ctx, ISEL);
uint32_t bi = a->bc;
uint32_t mask = 0x08 >> (bi & 0x03);
TCGv t0 = tcg_temp_new();
TCGv zr;
tcg_gen_extu_i32_tl(t0, cpu_crf[bi >> 2]);
tcg_gen_andi_tl(t0, t0, mask);
zr = tcg_constant_tl(0);
tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[a->rt], t0, zr,
a->ra ? cpu_gpr[a->ra] : zr,
cpu_gpr[a->rb]);
return true;
}
/*
* Fixed-Point Trap Instructions
*/
static bool trans_TW(DisasContext *ctx, arg_TW *a)
{
TCGv_i32 t0;
if (check_unconditional_trap(ctx, a->rt)) {
return true;
}
t0 = tcg_constant_i32(a->rt);
gen_helper_TW(tcg_env, cpu_gpr[a->ra], cpu_gpr[a->rb], t0);
return true;
}
static bool trans_TWI(DisasContext *ctx, arg_TWI *a)
{
TCGv t0;
TCGv_i32 t1;
if (check_unconditional_trap(ctx, a->rt)) {
return true;
}
t0 = tcg_constant_tl(a->si);
t1 = tcg_constant_i32(a->rt);
gen_helper_TW(tcg_env, cpu_gpr[a->ra], t0, t1);
return true;
}
static bool trans_TD(DisasContext *ctx, arg_TD *a)
{
REQUIRE_64BIT(ctx);
#if defined(TARGET_PPC64)
TCGv_i32 t0;
if (check_unconditional_trap(ctx, a->rt)) {
return true;
}
t0 = tcg_constant_i32(a->rt);
gen_helper_TD(tcg_env, cpu_gpr[a->ra], cpu_gpr[a->rb], t0);
#else
qemu_build_not_reached();
#endif
return true;
}
static bool trans_TDI(DisasContext *ctx, arg_TDI *a)
{
REQUIRE_64BIT(ctx);
#if defined(TARGET_PPC64)
TCGv t0;
TCGv_i32 t1;
if (check_unconditional_trap(ctx, a->rt)) {
return true;
}
t0 = tcg_constant_tl(a->si);
t1 = tcg_constant_i32(a->rt);
gen_helper_TD(tcg_env, cpu_gpr[a->ra], t0, t1);
#else
qemu_build_not_reached();
#endif
return true;
}
static bool trans_INVALID(DisasContext *ctx, arg_INVALID *a)
{
gen_invalid(ctx);