mirror of https://github.com/xemu-project/xemu.git
tcg-mips: Simplify brcond
Use the same table to fold comparisons as with setcond. Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
fd1cf66630
commit
c068896f7f
|
@ -634,70 +634,65 @@ static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGArg arg1,
|
static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
|
||||||
TCGArg arg2, int label_index)
|
TCGReg arg2, int label_index)
|
||||||
{
|
{
|
||||||
TCGLabel *l = &s->labels[label_index];
|
static const MIPSInsn b_zero[16] = {
|
||||||
|
[TCG_COND_LT] = OPC_BLTZ,
|
||||||
|
[TCG_COND_GT] = OPC_BGTZ,
|
||||||
|
[TCG_COND_LE] = OPC_BLEZ,
|
||||||
|
[TCG_COND_GE] = OPC_BGEZ,
|
||||||
|
};
|
||||||
|
|
||||||
|
TCGLabel *l;
|
||||||
|
MIPSInsn s_opc = OPC_SLTU;
|
||||||
|
MIPSInsn b_opc;
|
||||||
|
int cmp_map;
|
||||||
|
|
||||||
switch (cond) {
|
switch (cond) {
|
||||||
case TCG_COND_EQ:
|
case TCG_COND_EQ:
|
||||||
tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
|
b_opc = OPC_BEQ;
|
||||||
break;
|
break;
|
||||||
case TCG_COND_NE:
|
case TCG_COND_NE:
|
||||||
tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
|
b_opc = OPC_BNE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TCG_COND_LT:
|
case TCG_COND_LT:
|
||||||
if (arg2 == 0) {
|
case TCG_COND_GT:
|
||||||
tcg_out_opc_br(s, OPC_BLTZ, 0, arg1);
|
case TCG_COND_LE:
|
||||||
} else {
|
|
||||||
tcg_out_opc_reg(s, OPC_SLT, TCG_TMP0, arg1, arg2);
|
|
||||||
tcg_out_opc_br(s, OPC_BNE, TCG_TMP0, TCG_REG_ZERO);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TCG_COND_LTU:
|
|
||||||
tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, arg1, arg2);
|
|
||||||
tcg_out_opc_br(s, OPC_BNE, TCG_TMP0, TCG_REG_ZERO);
|
|
||||||
break;
|
|
||||||
case TCG_COND_GE:
|
case TCG_COND_GE:
|
||||||
if (arg2 == 0) {
|
if (arg2 == 0) {
|
||||||
tcg_out_opc_br(s, OPC_BGEZ, 0, arg1);
|
b_opc = b_zero[cond];
|
||||||
} else {
|
arg2 = arg1;
|
||||||
tcg_out_opc_reg(s, OPC_SLT, TCG_TMP0, arg1, arg2);
|
arg1 = 0;
|
||||||
tcg_out_opc_br(s, OPC_BEQ, TCG_TMP0, TCG_REG_ZERO);
|
break;
|
||||||
}
|
}
|
||||||
break;
|
s_opc = OPC_SLT;
|
||||||
case TCG_COND_GEU:
|
/* FALLTHRU */
|
||||||
tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, arg1, arg2);
|
|
||||||
tcg_out_opc_br(s, OPC_BEQ, TCG_TMP0, TCG_REG_ZERO);
|
case TCG_COND_LTU:
|
||||||
break;
|
|
||||||
case TCG_COND_LE:
|
|
||||||
if (arg2 == 0) {
|
|
||||||
tcg_out_opc_br(s, OPC_BLEZ, 0, arg1);
|
|
||||||
} else {
|
|
||||||
tcg_out_opc_reg(s, OPC_SLT, TCG_TMP0, arg2, arg1);
|
|
||||||
tcg_out_opc_br(s, OPC_BEQ, TCG_TMP0, TCG_REG_ZERO);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TCG_COND_LEU:
|
|
||||||
tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, arg2, arg1);
|
|
||||||
tcg_out_opc_br(s, OPC_BEQ, TCG_TMP0, TCG_REG_ZERO);
|
|
||||||
break;
|
|
||||||
case TCG_COND_GT:
|
|
||||||
if (arg2 == 0) {
|
|
||||||
tcg_out_opc_br(s, OPC_BGTZ, 0, arg1);
|
|
||||||
} else {
|
|
||||||
tcg_out_opc_reg(s, OPC_SLT, TCG_TMP0, arg2, arg1);
|
|
||||||
tcg_out_opc_br(s, OPC_BNE, TCG_TMP0, TCG_REG_ZERO);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TCG_COND_GTU:
|
case TCG_COND_GTU:
|
||||||
tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, arg2, arg1);
|
case TCG_COND_LEU:
|
||||||
tcg_out_opc_br(s, OPC_BNE, TCG_TMP0, TCG_REG_ZERO);
|
case TCG_COND_GEU:
|
||||||
|
cmp_map = mips_cmp_map[cond];
|
||||||
|
if (cmp_map & MIPS_CMP_SWAP) {
|
||||||
|
TCGReg t = arg1;
|
||||||
|
arg1 = arg2;
|
||||||
|
arg2 = t;
|
||||||
|
}
|
||||||
|
tcg_out_opc_reg(s, s_opc, TCG_TMP0, arg1, arg2);
|
||||||
|
b_opc = (cmp_map & MIPS_CMP_INV ? OPC_BEQ : OPC_BNE);
|
||||||
|
arg1 = TCG_TMP0;
|
||||||
|
arg2 = TCG_REG_ZERO;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
tcg_abort();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tcg_out_opc_br(s, b_opc, arg1, arg2);
|
||||||
|
l = &s->labels[label_index];
|
||||||
if (l->has_value) {
|
if (l->has_value) {
|
||||||
reloc_pc16(s->code_ptr - 1, l->u.value_ptr);
|
reloc_pc16(s->code_ptr - 1, l->u.value_ptr);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue