* [Qemu-devel] [PATCH] tcg/arm: Fix double-word comparisons
@ 2018-01-10 5:39 Richard Henderson
2018-01-10 19:26 ` Michael Roth
2018-01-15 14:27 ` Peter Maydell
0 siblings, 2 replies; 8+ messages in thread
From: Richard Henderson @ 2018-01-10 5:39 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, david, pbonzini, mdroth
The code sequence we were generating was only good for unsigned
comparisons. For signed comparisions, use the sequence from gcc.
Fixes booting of ppc64 firmware, with a patch changing the code
sequence for ppc comparisons.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/arm/tcg-target.inc.c | 112 +++++++++++++++++++++++++++++++++--------------
1 file changed, 80 insertions(+), 32 deletions(-)
diff --git a/tcg/arm/tcg-target.inc.c b/tcg/arm/tcg-target.inc.c
index 98a1253..b9890c8 100644
--- a/tcg/arm/tcg-target.inc.c
+++ b/tcg/arm/tcg-target.inc.c
@@ -239,10 +239,11 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type,
}
}
-#define TCG_CT_CONST_ARM 0x100
-#define TCG_CT_CONST_INV 0x200
-#define TCG_CT_CONST_NEG 0x400
-#define TCG_CT_CONST_ZERO 0x800
+#define TCG_CT_CONST_ARM 0x0100
+#define TCG_CT_CONST_INV 0x0200
+#define TCG_CT_CONST_NEG 0x0400
+#define TCG_CT_CONST_INVNEG 0x0800
+#define TCG_CT_CONST_ZERO 0x1000
/* parse target specific constraints */
static const char *target_parse_constraint(TCGArgConstraint *ct,
@@ -258,6 +259,9 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
case 'N': /* The gcc constraint letter is L, already used here. */
ct->ct |= TCG_CT_CONST_NEG;
break;
+ case 'M':
+ ct->ct |= TCG_CT_CONST_INVNEG;
+ break;
case 'Z':
ct->ct |= TCG_CT_CONST_ZERO;
break;
@@ -351,8 +355,7 @@ static inline int check_fit_imm(uint32_t imm)
static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
{
- int ct;
- ct = arg_ct->ct;
+ int ct = arg_ct->ct;
if (ct & TCG_CT_CONST) {
return 1;
} else if ((ct & TCG_CT_CONST_ARM) && check_fit_imm(val)) {
@@ -361,6 +364,9 @@ static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
return 1;
} else if ((ct & TCG_CT_CONST_NEG) && check_fit_imm(-val)) {
return 1;
+ } else if ((ct & TCG_CT_CONST_INVNEG)
+ && check_fit_imm(~val) && check_fit_imm(-val)) {
+ return 1;
} else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
return 1;
} else {
@@ -1103,6 +1109,64 @@ static inline void tcg_out_mb(TCGContext *s, TCGArg a0)
}
}
+static TCGCond tcg_out_cmp2(TCGContext *s, const TCGArg *args,
+ const int *const_args)
+{
+ TCGReg al = args[0];
+ TCGReg ah = args[1];
+ TCGArg bl = args[2];
+ TCGArg bh = args[3];
+ TCGCond cond = args[4];
+ int const_bl = const_args[2];
+ int const_bh = const_args[3];
+
+ switch (cond) {
+ case TCG_COND_EQ:
+ case TCG_COND_NE:
+ case TCG_COND_LTU:
+ case TCG_COND_LEU:
+ case TCG_COND_GTU:
+ case TCG_COND_GEU:
+ /* We perform a conditional comparision. If the high half is
+ equal, then overwrite the flags with the comparison of the
+ low half. The resulting flags cover the whole. */
+ tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0, ah, bh, const_bh);
+ tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0, al, bl, const_bl);
+ return cond;
+
+ case TCG_COND_LT:
+ case TCG_COND_GE:
+ /* We perform a double-word subtraction and examine the result.
+ We do not actually need the result of the subtract, so the
+ low part "subtract" is a compare. For the high half we have
+ no choice but to compute into a temporary. */
+ tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0, al, bl, const_bl);
+ tcg_out_dat_rIK(s, COND_AL, ARITH_SBC | TO_CPSR, ARITH_ADC | TO_CPSR,
+ TCG_REG_TMP, ah, bh, const_bh);
+ return cond;
+
+ case TCG_COND_LE:
+ case TCG_COND_GT:
+ /* Similar, but with swapped arguments. And of course we must
+ force the immediates into a register. */
+ if (const_bl) {
+ tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP, bl);
+ bl = TCG_REG_TMP;
+ }
+ tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0, bl, al, 0);
+ if (const_bh) {
+ tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP, bh);
+ bh = TCG_REG_TMP;
+ }
+ tcg_out_dat_rIK(s, COND_AL, ARITH_SBC | TO_CPSR, ARITH_ADC | TO_CPSR,
+ TCG_REG_TMP, bh, ah, 0);
+ return tcg_swap_cond(cond);
+
+ default:
+ g_assert_not_reached();
+ }
+}
+
#ifdef CONFIG_SOFTMMU
#include "tcg-ldst.inc.c"
@@ -1964,22 +2028,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]],
arg_label(args[3]));
break;
- case INDEX_op_brcond2_i32:
- /* The resulting conditions are:
- * TCG_COND_EQ --> a0 == a2 && a1 == a3,
- * TCG_COND_NE --> (a0 != a2 && a1 == a3) || a1 != a3,
- * TCG_COND_LT(U) --> (a0 < a2 && a1 == a3) || a1 < a3,
- * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
- * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
- * TCG_COND_GT(U) --> (a0 > a2 && a1 == a3) || a1 > a3,
- */
- tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
- args[1], args[3], const_args[3]);
- tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
- args[0], args[2], const_args[2]);
- tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]],
- arg_label(args[5]));
- break;
case INDEX_op_setcond_i32:
tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
args[1], args[2], const_args[2]);
@@ -1988,15 +2036,15 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
ARITH_MOV, args[0], 0, 0);
break;
+
+ case INDEX_op_brcond2_i32:
+ c = tcg_out_cmp2(s, args, const_args);
+ tcg_out_goto_label(s, tcg_cond_to_arm_cond[c], arg_label(args[5]));
+ break;
case INDEX_op_setcond2_i32:
- /* See brcond2_i32 comment */
- tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
- args[2], args[4], const_args[4]);
- tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
- args[1], args[3], const_args[3]);
- tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[5]],
- ARITH_MOV, args[0], 0, 1);
- tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[5])],
+ c = tcg_out_cmp2(s, args + 1, const_args + 1);
+ tcg_out_dat_imm(s, tcg_cond_to_arm_cond[c], ARITH_MOV, args[0], 0, 1);
+ tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(c)],
ARITH_MOV, args[0], 0, 0);
break;
@@ -2093,9 +2141,9 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
static const TCGTargetOpDef sub2
= { .args_ct_str = { "r", "r", "rI", "rI", "rIN", "rIK" } };
static const TCGTargetOpDef br2
- = { .args_ct_str = { "r", "r", "rIN", "rIN" } };
+ = { .args_ct_str = { "r", "r", "rIM", "rIM" } };
static const TCGTargetOpDef setc2
- = { .args_ct_str = { "r", "r", "r", "rIN", "rIN" } };
+ = { .args_ct_str = { "r", "r", "r", "rIM", "rIM" } };
switch (op) {
case INDEX_op_goto_ptr:
--
1.8.3.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] tcg/arm: Fix double-word comparisons
2018-01-10 5:39 [Qemu-devel] [PATCH] tcg/arm: Fix double-word comparisons Richard Henderson
@ 2018-01-10 19:26 ` Michael Roth
2018-01-15 14:27 ` Peter Maydell
1 sibling, 0 replies; 8+ messages in thread
From: Michael Roth @ 2018-01-10 19:26 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: peter.maydell, david, pbonzini
Quoting Richard Henderson (2018-01-09 23:39:08)
> The code sequence we were generating was only good for unsigned
> comparisons. For signed comparisions, use the sequence from gcc.
>
> Fixes booting of ppc64 firmware, with a patch changing the code
> sequence for ppc comparisons.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
Tested-by: Michael Roth <mdroth@linux.vnet.ibm.com>
> ---
> tcg/arm/tcg-target.inc.c | 112 +++++++++++++++++++++++++++++++++--------------
> 1 file changed, 80 insertions(+), 32 deletions(-)
>
> diff --git a/tcg/arm/tcg-target.inc.c b/tcg/arm/tcg-target.inc.c
> index 98a1253..b9890c8 100644
> --- a/tcg/arm/tcg-target.inc.c
> +++ b/tcg/arm/tcg-target.inc.c
> @@ -239,10 +239,11 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type,
> }
> }
>
> -#define TCG_CT_CONST_ARM 0x100
> -#define TCG_CT_CONST_INV 0x200
> -#define TCG_CT_CONST_NEG 0x400
> -#define TCG_CT_CONST_ZERO 0x800
> +#define TCG_CT_CONST_ARM 0x0100
> +#define TCG_CT_CONST_INV 0x0200
> +#define TCG_CT_CONST_NEG 0x0400
> +#define TCG_CT_CONST_INVNEG 0x0800
> +#define TCG_CT_CONST_ZERO 0x1000
>
> /* parse target specific constraints */
> static const char *target_parse_constraint(TCGArgConstraint *ct,
> @@ -258,6 +259,9 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
> case 'N': /* The gcc constraint letter is L, already used here. */
> ct->ct |= TCG_CT_CONST_NEG;
> break;
> + case 'M':
> + ct->ct |= TCG_CT_CONST_INVNEG;
> + break;
> case 'Z':
> ct->ct |= TCG_CT_CONST_ZERO;
> break;
> @@ -351,8 +355,7 @@ static inline int check_fit_imm(uint32_t imm)
> static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
> const TCGArgConstraint *arg_ct)
> {
> - int ct;
> - ct = arg_ct->ct;
> + int ct = arg_ct->ct;
> if (ct & TCG_CT_CONST) {
> return 1;
> } else if ((ct & TCG_CT_CONST_ARM) && check_fit_imm(val)) {
> @@ -361,6 +364,9 @@ static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
> return 1;
> } else if ((ct & TCG_CT_CONST_NEG) && check_fit_imm(-val)) {
> return 1;
> + } else if ((ct & TCG_CT_CONST_INVNEG)
> + && check_fit_imm(~val) && check_fit_imm(-val)) {
> + return 1;
> } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
> return 1;
> } else {
> @@ -1103,6 +1109,64 @@ static inline void tcg_out_mb(TCGContext *s, TCGArg a0)
> }
> }
>
> +static TCGCond tcg_out_cmp2(TCGContext *s, const TCGArg *args,
> + const int *const_args)
> +{
> + TCGReg al = args[0];
> + TCGReg ah = args[1];
> + TCGArg bl = args[2];
> + TCGArg bh = args[3];
> + TCGCond cond = args[4];
> + int const_bl = const_args[2];
> + int const_bh = const_args[3];
> +
> + switch (cond) {
> + case TCG_COND_EQ:
> + case TCG_COND_NE:
> + case TCG_COND_LTU:
> + case TCG_COND_LEU:
> + case TCG_COND_GTU:
> + case TCG_COND_GEU:
> + /* We perform a conditional comparision. If the high half is
> + equal, then overwrite the flags with the comparison of the
> + low half. The resulting flags cover the whole. */
> + tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0, ah, bh, const_bh);
> + tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0, al, bl, const_bl);
> + return cond;
> +
> + case TCG_COND_LT:
> + case TCG_COND_GE:
> + /* We perform a double-word subtraction and examine the result.
> + We do not actually need the result of the subtract, so the
> + low part "subtract" is a compare. For the high half we have
> + no choice but to compute into a temporary. */
> + tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0, al, bl, const_bl);
> + tcg_out_dat_rIK(s, COND_AL, ARITH_SBC | TO_CPSR, ARITH_ADC | TO_CPSR,
> + TCG_REG_TMP, ah, bh, const_bh);
> + return cond;
> +
> + case TCG_COND_LE:
> + case TCG_COND_GT:
> + /* Similar, but with swapped arguments. And of course we must
> + force the immediates into a register. */
> + if (const_bl) {
> + tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP, bl);
> + bl = TCG_REG_TMP;
> + }
> + tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0, bl, al, 0);
> + if (const_bh) {
> + tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP, bh);
> + bh = TCG_REG_TMP;
> + }
> + tcg_out_dat_rIK(s, COND_AL, ARITH_SBC | TO_CPSR, ARITH_ADC | TO_CPSR,
> + TCG_REG_TMP, bh, ah, 0);
> + return tcg_swap_cond(cond);
> +
> + default:
> + g_assert_not_reached();
> + }
> +}
> +
> #ifdef CONFIG_SOFTMMU
> #include "tcg-ldst.inc.c"
>
> @@ -1964,22 +2028,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
> tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]],
> arg_label(args[3]));
> break;
> - case INDEX_op_brcond2_i32:
> - /* The resulting conditions are:
> - * TCG_COND_EQ --> a0 == a2 && a1 == a3,
> - * TCG_COND_NE --> (a0 != a2 && a1 == a3) || a1 != a3,
> - * TCG_COND_LT(U) --> (a0 < a2 && a1 == a3) || a1 < a3,
> - * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
> - * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
> - * TCG_COND_GT(U) --> (a0 > a2 && a1 == a3) || a1 > a3,
> - */
> - tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
> - args[1], args[3], const_args[3]);
> - tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
> - args[0], args[2], const_args[2]);
> - tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]],
> - arg_label(args[5]));
> - break;
> case INDEX_op_setcond_i32:
> tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
> args[1], args[2], const_args[2]);
> @@ -1988,15 +2036,15 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
> tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
> ARITH_MOV, args[0], 0, 0);
> break;
> +
> + case INDEX_op_brcond2_i32:
> + c = tcg_out_cmp2(s, args, const_args);
> + tcg_out_goto_label(s, tcg_cond_to_arm_cond[c], arg_label(args[5]));
> + break;
> case INDEX_op_setcond2_i32:
> - /* See brcond2_i32 comment */
> - tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
> - args[2], args[4], const_args[4]);
> - tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
> - args[1], args[3], const_args[3]);
> - tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[5]],
> - ARITH_MOV, args[0], 0, 1);
> - tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[5])],
> + c = tcg_out_cmp2(s, args + 1, const_args + 1);
> + tcg_out_dat_imm(s, tcg_cond_to_arm_cond[c], ARITH_MOV, args[0], 0, 1);
> + tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(c)],
> ARITH_MOV, args[0], 0, 0);
> break;
>
> @@ -2093,9 +2141,9 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
> static const TCGTargetOpDef sub2
> = { .args_ct_str = { "r", "r", "rI", "rI", "rIN", "rIK" } };
> static const TCGTargetOpDef br2
> - = { .args_ct_str = { "r", "r", "rIN", "rIN" } };
> + = { .args_ct_str = { "r", "r", "rIM", "rIM" } };
> static const TCGTargetOpDef setc2
> - = { .args_ct_str = { "r", "r", "r", "rIN", "rIN" } };
> + = { .args_ct_str = { "r", "r", "r", "rIM", "rIM" } };
>
> switch (op) {
> case INDEX_op_goto_ptr:
> --
> 1.8.3.1
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] tcg/arm: Fix double-word comparisons
2018-01-10 5:39 [Qemu-devel] [PATCH] tcg/arm: Fix double-word comparisons Richard Henderson
2018-01-10 19:26 ` Michael Roth
@ 2018-01-15 14:27 ` Peter Maydell
2018-01-15 16:18 ` Richard Henderson
` (2 more replies)
1 sibling, 3 replies; 8+ messages in thread
From: Peter Maydell @ 2018-01-15 14:27 UTC (permalink / raw)
To: Richard Henderson
Cc: QEMU Developers, David Gibson, Paolo Bonzini, Michael Roth
On 10 January 2018 at 05:39, Richard Henderson <rth@twiddle.net> wrote:
> The code sequence we were generating was only good for unsigned
> comparisons. For signed comparisions, use the sequence from gcc.
>
> Fixes booting of ppc64 firmware, with a patch changing the code
> sequence for ppc comparisons.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> tcg/arm/tcg-target.inc.c | 112 +++++++++++++++++++++++++++++++++--------------
> 1 file changed, 80 insertions(+), 32 deletions(-)
>
> diff --git a/tcg/arm/tcg-target.inc.c b/tcg/arm/tcg-target.inc.c
> index 98a1253..b9890c8 100644
> --- a/tcg/arm/tcg-target.inc.c
> +++ b/tcg/arm/tcg-target.inc.c
> @@ -239,10 +239,11 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type,
> }
> }
>
> -#define TCG_CT_CONST_ARM 0x100
> -#define TCG_CT_CONST_INV 0x200
> -#define TCG_CT_CONST_NEG 0x400
> -#define TCG_CT_CONST_ZERO 0x800
> +#define TCG_CT_CONST_ARM 0x0100
> +#define TCG_CT_CONST_INV 0x0200
> +#define TCG_CT_CONST_NEG 0x0400
> +#define TCG_CT_CONST_INVNEG 0x0800
> +#define TCG_CT_CONST_ZERO 0x1000
>
> /* parse target specific constraints */
> static const char *target_parse_constraint(TCGArgConstraint *ct,
> @@ -258,6 +259,9 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
> case 'N': /* The gcc constraint letter is L, already used here. */
> ct->ct |= TCG_CT_CONST_NEG;
> break;
> + case 'M':
> + ct->ct |= TCG_CT_CONST_INVNEG;
> + break;
In GCC constraint "M" is "integer in the range 0 to 32", which this clearly
isn't. Can we have a comment saying what it is? (may be worth mentioning
in particular how "rIM" differs from "rINK" -- I think the answer is that
we want to say "valid-immediate OR (valid-if-inverted AND valid-if-negated)",
whereas 'rINK' is "valid-immediate OR valid-if-inverted OR valid-if-negated".)
The code looks OK to me. I'm guessing the sparc guest failure is
just because we now generate more code for some of the comparison
cases and that doesn't fit in the buffer...
We could avoid the annoying "load LE/GE immediates to tempreg"
extra code by having tcg_out_cmp2() return a flag to tell
the caller which way round to put the conditions for its two
conditional ARITH_MOV insns (for setcond2) or which condition
to use for the branch (brcond2), right?
thanks
-- PMM
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] tcg/arm: Fix double-word comparisons
2018-01-15 14:27 ` Peter Maydell
@ 2018-01-15 16:18 ` Richard Henderson
2018-01-15 16:27 ` Peter Maydell
2018-01-15 16:46 ` Richard Henderson
2018-01-15 17:31 ` Richard Henderson
2 siblings, 1 reply; 8+ messages in thread
From: Richard Henderson @ 2018-01-15 16:18 UTC (permalink / raw)
To: Peter Maydell; +Cc: QEMU Developers, David Gibson, Paolo Bonzini, Michael Roth
On 01/15/2018 06:27 AM, Peter Maydell wrote:
> On 10 January 2018 at 05:39, Richard Henderson <rth@twiddle.net> wrote:
>> The code sequence we were generating was only good for unsigned
>> comparisons. For signed comparisions, use the sequence from gcc.
>>
>> Fixes booting of ppc64 firmware, with a patch changing the code
>> sequence for ppc comparisons.
>>
>> Signed-off-by: Richard Henderson <rth@twiddle.net>
>> ---
>> tcg/arm/tcg-target.inc.c | 112 +++++++++++++++++++++++++++++++++--------------
>> 1 file changed, 80 insertions(+), 32 deletions(-)
>>
>> diff --git a/tcg/arm/tcg-target.inc.c b/tcg/arm/tcg-target.inc.c
>> index 98a1253..b9890c8 100644
>> --- a/tcg/arm/tcg-target.inc.c
>> +++ b/tcg/arm/tcg-target.inc.c
>> @@ -239,10 +239,11 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type,
>> }
>> }
>>
>> -#define TCG_CT_CONST_ARM 0x100
>> -#define TCG_CT_CONST_INV 0x200
>> -#define TCG_CT_CONST_NEG 0x400
>> -#define TCG_CT_CONST_ZERO 0x800
>> +#define TCG_CT_CONST_ARM 0x0100
>> +#define TCG_CT_CONST_INV 0x0200
>> +#define TCG_CT_CONST_NEG 0x0400
>> +#define TCG_CT_CONST_INVNEG 0x0800
>> +#define TCG_CT_CONST_ZERO 0x1000
>>
>> /* parse target specific constraints */
>> static const char *target_parse_constraint(TCGArgConstraint *ct,
>> @@ -258,6 +259,9 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
>> case 'N': /* The gcc constraint letter is L, already used here. */
>> ct->ct |= TCG_CT_CONST_NEG;
>> break;
>> + case 'M':
>> + ct->ct |= TCG_CT_CONST_INVNEG;
>> + break;
>
> In GCC constraint "M" is "integer in the range 0 to 32", which this clearly
> isn't. Can we have a comment saying what it is? (may be worth mentioning
> in particular how "rIM" differs from "rINK" -- I think the answer is that
> we want to say "valid-immediate OR (valid-if-inverted AND valid-if-negated)",
> whereas 'rINK' is "valid-immediate OR valid-if-inverted OR valid-if-negated".)
Exactly.
> The code looks OK to me. I'm guessing the sparc guest failure is
> just because we now generate more code for some of the comparison
> cases and that doesn't fit in the buffer...
I don't recall having seen a sparc failure...
> We could avoid the annoying "load LE/GE immediates to tempreg"
> extra code by having tcg_out_cmp2() return a flag to tell
> the caller which way round to put the conditions for its two
> conditional ARITH_MOV insns (for setcond2) or which condition
> to use for the branch (brcond2), right?
Um... we do return a condition. I must have missed a trick or made a mistake
somewhere.
r~
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] tcg/arm: Fix double-word comparisons
2018-01-15 16:18 ` Richard Henderson
@ 2018-01-15 16:27 ` Peter Maydell
0 siblings, 0 replies; 8+ messages in thread
From: Peter Maydell @ 2018-01-15 16:27 UTC (permalink / raw)
To: Richard Henderson
Cc: QEMU Developers, David Gibson, Paolo Bonzini, Michael Roth
On 15 January 2018 at 16:18, Richard Henderson <rth@twiddle.net> wrote:
> On 01/15/2018 06:27 AM, Peter Maydell wrote:
>> The code looks OK to me. I'm guessing the sparc guest failure is
>> just because we now generate more code for some of the comparison
>> cases and that doesn't fit in the buffer...
>
> I don't recall having seen a sparc failure...
See the backtrace in my reply to your tcg pullrequest email :-)
>> We could avoid the annoying "load LE/GE immediates to tempreg"
>> extra code by having tcg_out_cmp2() return a flag to tell
>> the caller which way round to put the conditions for its two
>> conditional ARITH_MOV insns (for setcond2) or which condition
>> to use for the branch (brcond2), right?
>
> Um... we do return a condition. I must have missed a trick or
> made a mistake somewhere.
Oh, yes, rather than returning "condition and flag to tell caller
to invert it" we could just flip which condition we return,
couldn't we.
thanks
-- PMM
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] tcg/arm: Fix double-word comparisons
2018-01-15 14:27 ` Peter Maydell
2018-01-15 16:18 ` Richard Henderson
@ 2018-01-15 16:46 ` Richard Henderson
2018-01-15 17:31 ` Richard Henderson
2 siblings, 0 replies; 8+ messages in thread
From: Richard Henderson @ 2018-01-15 16:46 UTC (permalink / raw)
To: Peter Maydell, Richard Henderson
Cc: Michael Roth, Paolo Bonzini, QEMU Developers, David Gibson
On 01/15/2018 06:27 AM, Peter Maydell wrote:
> (may be worth mentioning
> in particular how "rIM" differs from "rINK" -- I think the answer is that
> we want to say "valid-immediate OR (valid-if-inverted AND valid-if-negated)",
> whereas 'rINK' is "valid-immediate OR valid-if-inverted OR valid-if-negated".)
I also just realized that N & K is only true for -256 thru -1. Which is
certainly a simpler test to go with that verbiage.
r~
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] tcg/arm: Fix double-word comparisons
2018-01-15 14:27 ` Peter Maydell
2018-01-15 16:18 ` Richard Henderson
2018-01-15 16:46 ` Richard Henderson
@ 2018-01-15 17:31 ` Richard Henderson
2018-01-15 17:39 ` Richard Henderson
2 siblings, 1 reply; 8+ messages in thread
From: Richard Henderson @ 2018-01-15 17:31 UTC (permalink / raw)
To: Peter Maydell, Richard Henderson
Cc: Michael Roth, Paolo Bonzini, QEMU Developers, David Gibson
On 01/15/2018 06:27 AM, Peter Maydell wrote:
> We could avoid the annoying "load LE/GE immediates to tempreg"
> extra code by having tcg_out_cmp2() return a flag to tell
> the caller which way round to put the conditions for its two
> conditional ARITH_MOV insns (for setcond2) or which condition
> to use for the branch (brcond2), right?
No.
We do return a condition to use for the user. When we do the LE/GT load
immediates to temp path, we do apply tcg_cond_swap(cond), which converts the
condition as for swapped arguments, i.e. to GE/LT.
But we can't *not* swap the arguments to the generated comparison. Otherwise
we're computing the wrong thing.
r~
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] tcg/arm: Fix double-word comparisons
2018-01-15 17:31 ` Richard Henderson
@ 2018-01-15 17:39 ` Richard Henderson
0 siblings, 0 replies; 8+ messages in thread
From: Richard Henderson @ 2018-01-15 17:39 UTC (permalink / raw)
To: Peter Maydell, Richard Henderson
Cc: Michael Roth, Paolo Bonzini, QEMU Developers, David Gibson
On 01/15/2018 09:31 AM, Richard Henderson wrote:
> But we can't *not* swap the arguments to the generated comparison. Otherwise
> we're computing the wrong thing.
Bah. I have of course forgotten about the RSC instruction, which takes an
immediate. Will fix.
r~
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2018-01-15 17:39 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-01-10 5:39 [Qemu-devel] [PATCH] tcg/arm: Fix double-word comparisons Richard Henderson
2018-01-10 19:26 ` Michael Roth
2018-01-15 14:27 ` Peter Maydell
2018-01-15 16:18 ` Richard Henderson
2018-01-15 16:27 ` Peter Maydell
2018-01-15 16:46 ` Richard Henderson
2018-01-15 17:31 ` Richard Henderson
2018-01-15 17:39 ` Richard Henderson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).