提交 0085bd51 编写于 作者: R Richard Henderson 提交者: Aurelien Jarno

tcg-hppa: Constrain immediate inputs to and_i32, or_i32, andc_i32.

Define "M" constraint for and_mask_p and "O" constraint for or_mask_p.
Assume that inputs are correct in tcg_out_ori and tcg_out_andi.
Signed-off-by: NRichard Henderson <rth@twiddle.net>
Signed-off-by: NAurelien Jarno <aurelien@aurel32.net>
上级 ed18c5ce
...@@ -97,6 +97,9 @@ static inline int check_fit_tl(tcg_target_long val, unsigned int bits) ...@@ -97,6 +97,9 @@ static inline int check_fit_tl(tcg_target_long val, unsigned int bits)
Copied from gcc sources. */ Copied from gcc sources. */
static inline int or_mask_p(tcg_target_ulong mask) static inline int or_mask_p(tcg_target_ulong mask)
{ {
if (mask == 0 || mask == -1) {
return 0;
}
mask += mask & -mask; mask += mask & -mask;
return (mask & (mask - 1)) == 0; return (mask & (mask - 1)) == 0;
} }
...@@ -213,6 +216,12 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) ...@@ -213,6 +216,12 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
case 'K': case 'K':
ct->ct |= TCG_CT_CONST_MS11; ct->ct |= TCG_CT_CONST_MS11;
break; break;
case 'M':
ct->ct |= TCG_CT_CONST_AND;
break;
case 'O':
ct->ct |= TCG_CT_CONST_OR;
break;
default: default:
return -1; return -1;
} }
...@@ -236,6 +245,10 @@ static int tcg_target_const_match(tcg_target_long val, ...@@ -236,6 +245,10 @@ static int tcg_target_const_match(tcg_target_long val,
return check_fit_tl(val, 11); return check_fit_tl(val, 11);
} else if (ct & TCG_CT_CONST_MS11) { } else if (ct & TCG_CT_CONST_MS11) {
return check_fit_tl(-val, 11); return check_fit_tl(-val, 11);
} else if (ct & TCG_CT_CONST_AND) {
return and_mask_p(val);
} else if (ct & TCG_CT_CONST_OR) {
return or_mask_p(val);
} }
return 0; return 0;
} }
...@@ -474,70 +487,54 @@ static void tcg_out_vshd(TCGContext *s, int ret, int hi, int lo, int creg) ...@@ -474,70 +487,54 @@ static void tcg_out_vshd(TCGContext *s, int ret, int hi, int lo, int creg)
static void tcg_out_ori(TCGContext *s, int ret, int arg, tcg_target_ulong m) static void tcg_out_ori(TCGContext *s, int ret, int arg, tcg_target_ulong m)
{ {
if (m == 0) { int bs0, bs1;
tcg_out_mov(s, ret, arg);
} else if (m == -1) { /* Note that the argument is constrained to match or_mask_p. */
tcg_out_movi(s, TCG_TYPE_I32, ret, -1); for (bs0 = 0; bs0 < 32; bs0++) {
} else if (or_mask_p(m)) { if ((m & (1u << bs0)) != 0) {
int bs0, bs1; break;
for (bs0 = 0; bs0 < 32; bs0++) {
if ((m & (1u << bs0)) != 0) {
break;
}
} }
for (bs1 = bs0; bs1 < 32; bs1++) { }
if ((m & (1u << bs1)) == 0) { for (bs1 = bs0; bs1 < 32; bs1++) {
break; if ((m & (1u << bs1)) == 0) {
} break;
} }
assert(bs1 == 32 || (1ul << bs1) > m);
tcg_out_mov(s, ret, arg);
tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(-1)
| INSN_SHDEP_CP(31 - bs0) | INSN_DEP_LEN(bs1 - bs0));
} else {
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R1, m);
tcg_out_arith(s, ret, arg, TCG_REG_R1, INSN_OR);
} }
assert(bs1 == 32 || (1ul << bs1) > m);
tcg_out_mov(s, ret, arg);
tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(-1)
| INSN_SHDEP_CP(31 - bs0) | INSN_DEP_LEN(bs1 - bs0));
} }
static void tcg_out_andi(TCGContext *s, int ret, int arg, tcg_target_ulong m) static void tcg_out_andi(TCGContext *s, int ret, int arg, tcg_target_ulong m)
{ {
if (m == 0) { int ls0, ls1, ms0;
tcg_out_mov(s, ret, TCG_REG_R0);
} else if (m == -1) {
tcg_out_mov(s, ret, arg);
} else if (and_mask_p(m)) {
int ls0, ls1, ms0;
for (ls0 = 0; ls0 < 32; ls0++) { /* Note that the argument is constrained to match and_mask_p. */
if ((m & (1u << ls0)) == 0) { for (ls0 = 0; ls0 < 32; ls0++) {
break; if ((m & (1u << ls0)) == 0) {
} break;
} }
for (ls1 = ls0; ls1 < 32; ls1++) { }
if ((m & (1u << ls1)) != 0) { for (ls1 = ls0; ls1 < 32; ls1++) {
break; if ((m & (1u << ls1)) != 0) {
} break;
} }
for (ms0 = ls1; ms0 < 32; ms0++) { }
if ((m & (1u << ms0)) == 0) { for (ms0 = ls1; ms0 < 32; ms0++) {
break; if ((m & (1u << ms0)) == 0) {
} break;
} }
assert (ms0 == 32); }
assert (ms0 == 32);
if (ls1 == 32) { if (ls1 == 32) {
tcg_out_extr(s, ret, arg, 0, ls0, 0); tcg_out_extr(s, ret, arg, 0, ls0, 0);
} else {
tcg_out_mov(s, ret, arg);
tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(0)
| INSN_SHDEP_CP(31 - ls0) | INSN_DEP_LEN(ls1 - ls0));
}
} else { } else {
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R1, m); tcg_out_mov(s, ret, arg);
tcg_out_arith(s, ret, arg, TCG_REG_R1, INSN_AND); tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(0)
| INSN_SHDEP_CP(31 - ls0) | INSN_DEP_LEN(ls1 - ls0));
} }
} }
...@@ -1539,10 +1536,13 @@ static const TCGTargetOpDef hppa_op_defs[] = { ...@@ -1539,10 +1536,13 @@ static const TCGTargetOpDef hppa_op_defs[] = {
{ INDEX_op_add_i32, { "r", "rZ", "ri" } }, { INDEX_op_add_i32, { "r", "rZ", "ri" } },
{ INDEX_op_sub_i32, { "r", "rI", "ri" } }, { INDEX_op_sub_i32, { "r", "rI", "ri" } },
{ INDEX_op_and_i32, { "r", "rZ", "ri" } }, { INDEX_op_and_i32, { "r", "rZ", "rM" } },
{ INDEX_op_or_i32, { "r", "rZ", "ri" } }, { INDEX_op_or_i32, { "r", "rZ", "rO" } },
{ INDEX_op_xor_i32, { "r", "rZ", "rZ" } }, { INDEX_op_xor_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_andc_i32, { "r", "rZ", "ri" } }, /* Note that the second argument will be inverted, which means
we want a constant whose inversion matches M, and that O = ~M.
See the implementation of and_mask_p. */
{ INDEX_op_andc_i32, { "r", "rZ", "rO" } },
{ INDEX_op_mul_i32, { "r", "r", "r" } }, { INDEX_op_mul_i32, { "r", "r", "r" } },
{ INDEX_op_mulu2_i32, { "r", "r", "r", "r" } }, { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
......
...@@ -73,6 +73,8 @@ enum { ...@@ -73,6 +73,8 @@ enum {
#define TCG_CT_CONST_S5 0x0200 #define TCG_CT_CONST_S5 0x0200
#define TCG_CT_CONST_S11 0x0400 #define TCG_CT_CONST_S11 0x0400
#define TCG_CT_CONST_MS11 0x0800 #define TCG_CT_CONST_MS11 0x0800
#define TCG_CT_CONST_AND 0x1000
#define TCG_CT_CONST_OR 0x2000
/* used for function call generation */ /* used for function call generation */
#define TCG_REG_CALL_STACK TCG_REG_SP #define TCG_REG_CALL_STACK TCG_REG_SP
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册