mirror of
https://github.com/qemu/qemu.git
synced 2024-11-24 11:23:43 +08:00
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,
|
||||
TCGArg arg2, int label_index)
|
||||
static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
|
||||
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) {
|
||||
case TCG_COND_EQ:
|
||||
tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
|
||||
b_opc = OPC_BEQ;
|
||||
break;
|
||||
case TCG_COND_NE:
|
||||
tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
|
||||
b_opc = OPC_BNE;
|
||||
break;
|
||||
|
||||
case TCG_COND_LT:
|
||||
if (arg2 == 0) {
|
||||
tcg_out_opc_br(s, OPC_BLTZ, 0, arg1);
|
||||
} 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_GT:
|
||||
case TCG_COND_LE:
|
||||
case TCG_COND_GE:
|
||||
if (arg2 == 0) {
|
||||
tcg_out_opc_br(s, OPC_BGEZ, 0, arg1);
|
||||
} else {
|
||||
tcg_out_opc_reg(s, OPC_SLT, TCG_TMP0, arg1, arg2);
|
||||
tcg_out_opc_br(s, OPC_BEQ, TCG_TMP0, TCG_REG_ZERO);
|
||||
b_opc = b_zero[cond];
|
||||
arg2 = arg1;
|
||||
arg1 = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TCG_COND_GEU:
|
||||
tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, arg1, arg2);
|
||||
tcg_out_opc_br(s, OPC_BEQ, TCG_TMP0, TCG_REG_ZERO);
|
||||
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;
|
||||
s_opc = OPC_SLT;
|
||||
/* FALLTHRU */
|
||||
|
||||
case TCG_COND_LTU:
|
||||
case TCG_COND_GTU:
|
||||
tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, arg2, arg1);
|
||||
tcg_out_opc_br(s, OPC_BNE, TCG_TMP0, TCG_REG_ZERO);
|
||||
case TCG_COND_LEU:
|
||||
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;
|
||||
|
||||
default:
|
||||
tcg_abort();
|
||||
break;
|
||||
}
|
||||
|
||||
tcg_out_opc_br(s, b_opc, arg1, arg2);
|
||||
l = &s->labels[label_index];
|
||||
if (l->has_value) {
|
||||
reloc_pc16(s->code_ptr - 1, l->u.value_ptr);
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user