tcg-mips: Use EXT for AND on mips32r2

At the same time, tidy deposit by introducing tcg_out_opc_bf.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Richard Henderson 2014-04-15 09:27:40 -07:00
parent f216a35f36
commit 1c4182687e
2 changed files with 50 additions and 14 deletions

View File

@ -155,6 +155,16 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type,
reloc_pc16(code_ptr, (tcg_insn_unit *)value); reloc_pc16(code_ptr, (tcg_insn_unit *)value);
} }
#define TCG_CT_CONST_ZERO 0x100
#define TCG_CT_CONST_U16 0x200
#define TCG_CT_CONST_S16 0x400
#define TCG_CT_CONST_P2M1 0x800
static inline bool is_p2m1(tcg_target_long val)
{
return val && ((val + 1) & val) == 0;
}
/* parse target specific constraints */ /* parse target specific constraints */
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
{ {
@ -200,6 +210,9 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
case 'J': case 'J':
ct->ct |= TCG_CT_CONST_S16; ct->ct |= TCG_CT_CONST_S16;
break; break;
case 'K':
ct->ct |= TCG_CT_CONST_P2M1;
break;
case 'Z': case 'Z':
/* We are cheating a bit here, using the fact that the register /* We are cheating a bit here, using the fact that the register
ZERO is also the register number 0. Hence there is no need ZERO is also the register number 0. Hence there is no need
@ -220,16 +233,19 @@ static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
{ {
int ct; int ct;
ct = arg_ct->ct; ct = arg_ct->ct;
if (ct & TCG_CT_CONST) if (ct & TCG_CT_CONST) {
return 1; return 1;
else if ((ct & TCG_CT_CONST_ZERO) && val == 0) } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
return 1; return 1;
else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) } else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
return 1; return 1;
else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) } else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
return 1; return 1;
else } else if ((ct & TCG_CT_CONST_P2M1)
return 0; && use_mips32r2_instructions && is_p2m1(val)) {
return 1;
}
return 0;
} }
/* instruction opcodes */ /* instruction opcodes */
@ -293,6 +309,7 @@ enum {
OPC_MUL = OPC_SPECIAL2 | 0x002, OPC_MUL = OPC_SPECIAL2 | 0x002,
OPC_SPECIAL3 = 0x1f << 26, OPC_SPECIAL3 = 0x1f << 26,
OPC_EXT = OPC_SPECIAL3 | 0x000,
OPC_INS = OPC_SPECIAL3 | 0x004, OPC_INS = OPC_SPECIAL3 | 0x004,
OPC_WSBH = OPC_SPECIAL3 | 0x0a0, OPC_WSBH = OPC_SPECIAL3 | 0x0a0,
OPC_SEB = OPC_SPECIAL3 | 0x420, OPC_SEB = OPC_SPECIAL3 | 0x420,
@ -329,6 +346,22 @@ static inline void tcg_out_opc_imm(TCGContext *s, int opc,
tcg_out32(s, inst); tcg_out32(s, inst);
} }
/*
* Type bitfield
*/
static inline void tcg_out_opc_bf(TCGContext *s, int opc, TCGReg rt,
TCGReg rs, int msb, int lsb)
{
int32_t inst;
inst = opc;
inst |= (rs & 0x1F) << 21;
inst |= (rt & 0x1F) << 16;
inst |= (msb & 0x1F) << 11;
inst |= (lsb & 0x1F) << 6;
tcg_out32(s, inst);
}
/* /*
* Type branch * Type branch
*/ */
@ -1455,7 +1488,14 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_and_i32: case INDEX_op_and_i32:
if (const_args[2]) { if (const_args[2]) {
tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]); if (args[2] == (uint16_t)args[2]) {
tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
} else {
int msb = ctz32(~args[2]) - 1;
assert(use_mips32r2_instructions);
assert(is_p2m1(args[2]));
tcg_out_opc_bf(s, OPC_EXT, args[0], args[1], msb, 0);
}
} else { } else {
tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]); tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
} }
@ -1535,8 +1575,8 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break; break;
case INDEX_op_deposit_i32: case INDEX_op_deposit_i32:
tcg_out_opc_imm(s, OPC_INS, args[0], args[2], tcg_out_opc_bf(s, OPC_INS, args[0], args[2],
((args[3] + args[4] - 1) << 11) | (args[3] << 6)); args[3] + args[4] - 1, args[3]);
break; break;
case INDEX_op_brcond_i32: case INDEX_op_brcond_i32:
@ -1604,7 +1644,7 @@ static const TCGTargetOpDef mips_op_defs[] = {
{ INDEX_op_remu_i32, { "r", "rZ", "rZ" } }, { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_sub_i32, { "r", "rZ", "rJ" } }, { INDEX_op_sub_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_and_i32, { "r", "rZ", "rI" } }, { INDEX_op_and_i32, { "r", "rZ", "rIK" } },
{ INDEX_op_nor_i32, { "r", "rZ", "rZ" } }, { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_not_i32, { "r", "rZ" } }, { INDEX_op_not_i32, { "r", "rZ" } },
{ INDEX_op_or_i32, { "r", "rZ", "rIZ" } }, { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },

View File

@ -67,10 +67,6 @@ typedef enum {
TCG_AREG0 = TCG_REG_S0, TCG_AREG0 = TCG_REG_S0,
} TCGReg; } TCGReg;
#define TCG_CT_CONST_ZERO 0x100
#define TCG_CT_CONST_U16 0x200
#define TCG_CT_CONST_S16 0x400
/* used for function call generation */ /* used for function call generation */
#define TCG_TARGET_STACK_ALIGN 8 #define TCG_TARGET_STACK_ALIGN 8
#define TCG_TARGET_CALL_STACK_OFFSET 16 #define TCG_TARGET_CALL_STACK_OFFSET 16