mirror of
https://github.com/qemu/qemu.git
synced 2026-04-05 21:50:33 +00:00
target/hexagon: use TCG_COND_TSTEQ/TSTNE for predicate branches
Replace TCG_COND_EQ/NE comparisons against 0 with TCG_COND_TSTEQ/TSTNE comparisons against 1 for all predicate-conditional branches. This tests bit 0 of the predicate register directly, eliminating redundant andi operations that previously extracted the LSB before the comparison. For predicate-conditional jumps (jumpt, jumpf, jumptnew, etc.) and jump-register variants (jumprt, jumprf, etc.), pass the raw predicate value directly instead of going through fLSBOLD/fLSBNEW extraction. For callers that produce a 0/1 result via setcond (compare-and-jump, jumprz, etc.), the TSTEQ/TSTNE test on bit 0 is equivalent to the previous EQ/NE test against 0. Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
This commit is contained in:
@@ -696,13 +696,13 @@
|
||||
gen_callr(ctx, RsV)
|
||||
|
||||
#define fGEN_TCG_J2_callt(SHORTCODE) \
|
||||
gen_cond_call(ctx, PuV, TCG_COND_EQ, riV)
|
||||
gen_cond_call(ctx, PuV, TCG_COND_TSTEQ, riV)
|
||||
#define fGEN_TCG_J2_callf(SHORTCODE) \
|
||||
gen_cond_call(ctx, PuV, TCG_COND_NE, riV)
|
||||
gen_cond_call(ctx, PuV, TCG_COND_TSTNE, riV)
|
||||
#define fGEN_TCG_J2_callrt(SHORTCODE) \
|
||||
gen_cond_callr(ctx, TCG_COND_EQ, PuV, RsV)
|
||||
gen_cond_callr(ctx, TCG_COND_TSTEQ, PuV, RsV)
|
||||
#define fGEN_TCG_J2_callrf(SHORTCODE) \
|
||||
gen_cond_callr(ctx, TCG_COND_NE, PuV, RsV)
|
||||
gen_cond_callr(ctx, TCG_COND_TSTNE, PuV, RsV)
|
||||
|
||||
#define fGEN_TCG_J2_loop0r(SHORTCODE) \
|
||||
gen_loop0r(ctx, RsV, riV)
|
||||
@@ -893,21 +893,21 @@
|
||||
gen_cmpnd_cmp_n1_jmp_f(ctx, 1, TCG_COND_GT, RsV, riV)
|
||||
|
||||
#define fGEN_TCG_J4_tstbit0_tp0_jump_nt(SHORTCODE) \
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_EQ, riV)
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_TSTEQ, riV)
|
||||
#define fGEN_TCG_J4_tstbit0_tp0_jump_t(SHORTCODE) \
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_EQ, riV)
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_TSTEQ, riV)
|
||||
#define fGEN_TCG_J4_tstbit0_fp0_jump_nt(SHORTCODE) \
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_NE, riV)
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_TSTNE, riV)
|
||||
#define fGEN_TCG_J4_tstbit0_fp0_jump_t(SHORTCODE) \
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_NE, riV)
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_TSTNE, riV)
|
||||
#define fGEN_TCG_J4_tstbit0_tp1_jump_nt(SHORTCODE) \
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_EQ, riV)
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_TSTEQ, riV)
|
||||
#define fGEN_TCG_J4_tstbit0_tp1_jump_t(SHORTCODE) \
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_EQ, riV)
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_TSTEQ, riV)
|
||||
#define fGEN_TCG_J4_tstbit0_fp1_jump_nt(SHORTCODE) \
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_NE, riV)
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_TSTNE, riV)
|
||||
#define fGEN_TCG_J4_tstbit0_fp1_jump_t(SHORTCODE) \
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_NE, riV)
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_TSTNE, riV)
|
||||
|
||||
/* p0 = cmp.eq(r0, #7) */
|
||||
#define fGEN_TCG_SA1_cmpeqi(SHORTCODE) \
|
||||
@@ -933,31 +933,24 @@
|
||||
do { \
|
||||
TCGv LSB = tcg_temp_new(); \
|
||||
COND; \
|
||||
gen_cond_jump(ctx, TCG_COND_EQ, LSB, riV); \
|
||||
gen_cond_jump(ctx, TCG_COND_TSTEQ, LSB, riV); \
|
||||
} while (0)
|
||||
#define fGEN_TCG_cond_jumpf(COND) \
|
||||
do { \
|
||||
TCGv LSB = tcg_temp_new(); \
|
||||
COND; \
|
||||
gen_cond_jump(ctx, TCG_COND_NE, LSB, riV); \
|
||||
} while (0)
|
||||
|
||||
#define fGEN_TCG_J2_jumpt(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumpt(fLSBOLD(PuV))
|
||||
gen_cond_jump(ctx, TCG_COND_TSTEQ, PuV, riV)
|
||||
#define fGEN_TCG_J2_jumptpt(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumpt(fLSBOLD(PuV))
|
||||
gen_cond_jump(ctx, TCG_COND_TSTEQ, PuV, riV)
|
||||
#define fGEN_TCG_J2_jumpf(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumpf(fLSBOLD(PuV))
|
||||
gen_cond_jump(ctx, TCG_COND_TSTNE, PuV, riV)
|
||||
#define fGEN_TCG_J2_jumpfpt(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumpf(fLSBOLD(PuV))
|
||||
gen_cond_jump(ctx, TCG_COND_TSTNE, PuV, riV)
|
||||
#define fGEN_TCG_J2_jumptnew(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumpt(fLSBNEW(PuN))
|
||||
gen_cond_jump(ctx, TCG_COND_TSTEQ, PuN, riV)
|
||||
#define fGEN_TCG_J2_jumptnewpt(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumpt(fLSBNEW(PuN))
|
||||
gen_cond_jump(ctx, TCG_COND_TSTEQ, PuN, riV)
|
||||
#define fGEN_TCG_J2_jumpfnewpt(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumpf(fLSBNEW(PuN))
|
||||
gen_cond_jump(ctx, TCG_COND_TSTNE, PuN, riV)
|
||||
#define fGEN_TCG_J2_jumpfnew(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumpf(fLSBNEW(PuN))
|
||||
gen_cond_jump(ctx, TCG_COND_TSTNE, PuN, riV)
|
||||
#define fGEN_TCG_J2_jumprz(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_NE, LSB, RsV, 0))
|
||||
#define fGEN_TCG_J2_jumprzpt(SHORTCODE) \
|
||||
@@ -975,35 +968,22 @@
|
||||
#define fGEN_TCG_J2_jumprltezpt(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_LE, LSB, RsV, 0))
|
||||
|
||||
#define fGEN_TCG_cond_jumprt(COND) \
|
||||
do { \
|
||||
TCGv LSB = tcg_temp_new(); \
|
||||
COND; \
|
||||
gen_cond_jumpr(ctx, RsV, TCG_COND_EQ, LSB); \
|
||||
} while (0)
|
||||
#define fGEN_TCG_cond_jumprf(COND) \
|
||||
do { \
|
||||
TCGv LSB = tcg_temp_new(); \
|
||||
COND; \
|
||||
gen_cond_jumpr(ctx, RsV, TCG_COND_NE, LSB); \
|
||||
} while (0)
|
||||
|
||||
#define fGEN_TCG_J2_jumprt(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumprt(fLSBOLD(PuV))
|
||||
gen_cond_jumpr(ctx, RsV, TCG_COND_TSTEQ, PuV)
|
||||
#define fGEN_TCG_J2_jumprtpt(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumprt(fLSBOLD(PuV))
|
||||
gen_cond_jumpr(ctx, RsV, TCG_COND_TSTEQ, PuV)
|
||||
#define fGEN_TCG_J2_jumprf(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumprf(fLSBOLD(PuV))
|
||||
gen_cond_jumpr(ctx, RsV, TCG_COND_TSTNE, PuV)
|
||||
#define fGEN_TCG_J2_jumprfpt(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumprf(fLSBOLD(PuV))
|
||||
gen_cond_jumpr(ctx, RsV, TCG_COND_TSTNE, PuV)
|
||||
#define fGEN_TCG_J2_jumprtnew(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumprt(fLSBNEW(PuN))
|
||||
gen_cond_jumpr(ctx, RsV, TCG_COND_TSTEQ, PuN)
|
||||
#define fGEN_TCG_J2_jumprtnewpt(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumprt(fLSBNEW(PuN))
|
||||
gen_cond_jumpr(ctx, RsV, TCG_COND_TSTEQ, PuN)
|
||||
#define fGEN_TCG_J2_jumprfnew(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumprf(fLSBNEW(PuN))
|
||||
gen_cond_jumpr(ctx, RsV, TCG_COND_TSTNE, PuN)
|
||||
#define fGEN_TCG_J2_jumprfnewpt(SHORTCODE) \
|
||||
fGEN_TCG_cond_jumprf(fLSBNEW(PuN))
|
||||
gen_cond_jumpr(ctx, RsV, TCG_COND_TSTNE, PuN)
|
||||
|
||||
/*
|
||||
* New value compare & jump instructions
|
||||
@@ -1101,13 +1081,13 @@
|
||||
gen_cmpi_jumpnv(ctx, TCG_COND_LE, NsN, -1, riV)
|
||||
|
||||
#define fGEN_TCG_J4_tstbit0_t_jumpnv_t(SHORTCODE) \
|
||||
gen_testbit0_jumpnv(ctx, NsN, TCG_COND_EQ, riV)
|
||||
gen_testbit0_jumpnv(ctx, NsN, TCG_COND_TSTEQ, riV)
|
||||
#define fGEN_TCG_J4_tstbit0_t_jumpnv_nt(SHORTCODE) \
|
||||
gen_testbit0_jumpnv(ctx, NsN, TCG_COND_EQ, riV)
|
||||
gen_testbit0_jumpnv(ctx, NsN, TCG_COND_TSTEQ, riV)
|
||||
#define fGEN_TCG_J4_tstbit0_f_jumpnv_t(SHORTCODE) \
|
||||
gen_testbit0_jumpnv(ctx, NsN, TCG_COND_NE, riV)
|
||||
gen_testbit0_jumpnv(ctx, NsN, TCG_COND_TSTNE, riV)
|
||||
#define fGEN_TCG_J4_tstbit0_f_jumpnv_nt(SHORTCODE) \
|
||||
gen_testbit0_jumpnv(ctx, NsN, TCG_COND_NE, riV)
|
||||
gen_testbit0_jumpnv(ctx, NsN, TCG_COND_TSTNE, riV)
|
||||
|
||||
/* r0 = r1 ; jump address */
|
||||
#define fGEN_TCG_J4_jumpsetr(SHORTCODE) \
|
||||
@@ -1150,14 +1130,14 @@
|
||||
gen_jumpr(ctx, hex_gpr[HEX_REG_LR])
|
||||
|
||||
#define fGEN_TCG_SL2_jumpr31_t(SHORTCODE) \
|
||||
gen_cond_jumpr31(ctx, TCG_COND_EQ, hex_pred[0])
|
||||
gen_cond_jumpr31(ctx, TCG_COND_TSTEQ, hex_pred[0])
|
||||
#define fGEN_TCG_SL2_jumpr31_f(SHORTCODE) \
|
||||
gen_cond_jumpr31(ctx, TCG_COND_NE, hex_pred[0])
|
||||
gen_cond_jumpr31(ctx, TCG_COND_TSTNE, hex_pred[0])
|
||||
|
||||
#define fGEN_TCG_SL2_jumpr31_tnew(SHORTCODE) \
|
||||
gen_cond_jumpr31(ctx, TCG_COND_EQ, ctx->new_pred_value[0])
|
||||
gen_cond_jumpr31(ctx, TCG_COND_TSTEQ, ctx->new_pred_value[0])
|
||||
#define fGEN_TCG_SL2_jumpr31_fnew(SHORTCODE) \
|
||||
gen_cond_jumpr31(ctx, TCG_COND_NE, ctx->new_pred_value[0])
|
||||
gen_cond_jumpr31(ctx, TCG_COND_TSTNE, ctx->new_pred_value[0])
|
||||
|
||||
/* Count trailing zeros/ones */
|
||||
#define fGEN_TCG_S2_ct0(SHORTCODE) \
|
||||
|
||||
@@ -455,7 +455,7 @@ static void gen_write_new_pc_addr(DisasContext *ctx, TCGv addr,
|
||||
TCGLabel *pred_false = NULL;
|
||||
if (cond != TCG_COND_ALWAYS) {
|
||||
pred_false = gen_new_label();
|
||||
tcg_gen_brcondi_tl(cond, pred, 0, pred_false);
|
||||
tcg_gen_brcondi_tl(cond, pred, 1, pred_false);
|
||||
}
|
||||
|
||||
if (ctx->pkt->pkt_has_multi_cof) {
|
||||
@@ -579,9 +579,7 @@ static void gen_cond_jumpr(DisasContext *ctx, TCGv dst_pc,
|
||||
|
||||
static void gen_cond_jumpr31(DisasContext *ctx, TCGCond cond, TCGv pred)
|
||||
{
|
||||
TCGv LSB = tcg_temp_new();
|
||||
tcg_gen_andi_tl(LSB, pred, 1);
|
||||
gen_cond_jumpr(ctx, hex_gpr[HEX_REG_LR], cond, LSB);
|
||||
gen_cond_jumpr(ctx, hex_gpr[HEX_REG_LR], cond, pred);
|
||||
}
|
||||
|
||||
static void gen_cond_jump(DisasContext *ctx, TCGCond cond, TCGv pred,
|
||||
@@ -609,14 +607,14 @@ static void gen_cmpnd_cmp_jmp_t(DisasContext *ctx,
|
||||
int pnum, TCGCond cond, TCGv arg1, TCGv arg2,
|
||||
int pc_off)
|
||||
{
|
||||
gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_EQ, pc_off);
|
||||
gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_TSTEQ, pc_off);
|
||||
}
|
||||
|
||||
static void gen_cmpnd_cmp_jmp_f(DisasContext *ctx,
|
||||
int pnum, TCGCond cond, TCGv arg1, TCGv arg2,
|
||||
int pc_off)
|
||||
{
|
||||
gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_NE, pc_off);
|
||||
gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_TSTNE, pc_off);
|
||||
}
|
||||
|
||||
static void gen_cmpnd_cmpi_jmp_t(DisasContext *ctx,
|
||||
@@ -624,7 +622,7 @@ static void gen_cmpnd_cmpi_jmp_t(DisasContext *ctx,
|
||||
int pc_off)
|
||||
{
|
||||
TCGv tmp = tcg_constant_tl(arg2);
|
||||
gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_EQ, pc_off);
|
||||
gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_TSTEQ, pc_off);
|
||||
}
|
||||
|
||||
static void gen_cmpnd_cmpi_jmp_f(DisasContext *ctx,
|
||||
@@ -632,7 +630,7 @@ static void gen_cmpnd_cmpi_jmp_f(DisasContext *ctx,
|
||||
int pc_off)
|
||||
{
|
||||
TCGv tmp = tcg_constant_tl(arg2);
|
||||
gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_NE, pc_off);
|
||||
gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_TSTNE, pc_off);
|
||||
}
|
||||
|
||||
static void gen_cmpnd_cmp_n1_jmp_t(DisasContext *ctx, int pnum, TCGCond cond,
|
||||
@@ -665,9 +663,7 @@ static void gen_cmpnd_tstbit0_jmp(DisasContext *ctx,
|
||||
static void gen_testbit0_jumpnv(DisasContext *ctx,
|
||||
TCGv arg, TCGCond cond, int pc_off)
|
||||
{
|
||||
TCGv pred = tcg_temp_new();
|
||||
tcg_gen_andi_tl(pred, arg, 1);
|
||||
gen_cond_jump(ctx, cond, pred, pc_off);
|
||||
gen_cond_jump(ctx, cond, arg, pc_off);
|
||||
}
|
||||
|
||||
static void gen_jump(DisasContext *ctx, int pc_off)
|
||||
@@ -698,11 +694,9 @@ static void gen_cond_call(DisasContext *ctx, TCGv pred,
|
||||
TCGCond cond, int pc_off)
|
||||
{
|
||||
TCGv lr = get_result_gpr(ctx, HEX_REG_LR);
|
||||
TCGv lsb = tcg_temp_new();
|
||||
TCGLabel *skip = gen_new_label();
|
||||
tcg_gen_andi_tl(lsb, pred, 1);
|
||||
gen_write_new_pc_pcrel(ctx, pc_off, cond, lsb);
|
||||
tcg_gen_brcondi_tl(cond, lsb, 0, skip);
|
||||
gen_write_new_pc_pcrel(ctx, pc_off, cond, pred);
|
||||
tcg_gen_brcondi_tl(cond, pred, 1, skip);
|
||||
tcg_gen_movi_tl(lr, ctx->next_PC);
|
||||
gen_set_label(skip);
|
||||
}
|
||||
@@ -710,10 +704,8 @@ static void gen_cond_call(DisasContext *ctx, TCGv pred,
|
||||
static void gen_cond_callr(DisasContext *ctx,
|
||||
TCGCond cond, TCGv pred, TCGv new_pc)
|
||||
{
|
||||
TCGv lsb = tcg_temp_new();
|
||||
TCGLabel *skip = gen_new_label();
|
||||
tcg_gen_andi_tl(lsb, pred, 1);
|
||||
tcg_gen_brcondi_tl(cond, lsb, 0, skip);
|
||||
tcg_gen_brcondi_tl(cond, pred, 1, skip);
|
||||
gen_callr(ctx, new_pc);
|
||||
gen_set_label(skip);
|
||||
}
|
||||
@@ -955,7 +947,7 @@ static void gen_cmp_jumpnv(DisasContext *ctx,
|
||||
{
|
||||
TCGv pred = tcg_temp_new();
|
||||
tcg_gen_setcond_tl(cond, pred, val, src);
|
||||
gen_cond_jump(ctx, TCG_COND_EQ, pred, pc_off);
|
||||
gen_cond_jump(ctx, TCG_COND_TSTEQ, pred, pc_off);
|
||||
}
|
||||
|
||||
static void gen_cmpi_jumpnv(DisasContext *ctx,
|
||||
@@ -963,7 +955,7 @@ static void gen_cmpi_jumpnv(DisasContext *ctx,
|
||||
{
|
||||
TCGv pred = tcg_temp_new();
|
||||
tcg_gen_setcondi_tl(cond, pred, val, src);
|
||||
gen_cond_jump(ctx, TCG_COND_EQ, pred, pc_off);
|
||||
gen_cond_jump(ctx, TCG_COND_TSTEQ, pred, pc_off);
|
||||
}
|
||||
|
||||
/* Shift left with saturation */
|
||||
|
||||
@@ -163,7 +163,7 @@ static void gen_end_tb(DisasContext *ctx)
|
||||
if (ctx->branch_cond != TCG_COND_NEVER) {
|
||||
if (ctx->branch_cond != TCG_COND_ALWAYS) {
|
||||
TCGLabel *skip = gen_new_label();
|
||||
tcg_gen_brcondi_tl(ctx->branch_cond, ctx->branch_taken, 0, skip);
|
||||
tcg_gen_brcondi_tl(ctx->branch_cond, ctx->branch_taken, 1, skip);
|
||||
gen_goto_tb(ctx, 0, ctx->branch_dest, true);
|
||||
gen_set_label(skip);
|
||||
gen_goto_tb(ctx, 1, ctx->next_PC, false);
|
||||
|
||||
Reference in New Issue
Block a user