On 09:18 Mon 10 Nov , Eric Fisher wrote:
> > So I think one of the possible solution would be to reverse the div.g and
> > teq insn.
> > And I think this is not hard to do, just modify mips_output_division()
> > function.
> > Also I think this is a better solution, since we can save a register.
>
> Do you mean the modification like this?
>
> +
> +
> +/* Used to output (d)div(u).g or (d)mod(u).g instruction of loongson,
> + + which takes three operands, and put the result in the rd register.
> + + Hence emit the divide-by-zeor check before the DIVISION, in case
> + + that the rd and rt are the same one. */
> +const char *
> +mips_output_division_g (const char *division, rtx *operands)
> +{
> + if (TARGET_CHECK_ZERO_DIV)
> + {
> + output_asm_insn ("bne\t%2,%.,1f%#\n\tbreak\t7\n1:", operands);
> + }
> + return division;
> +}
> +
>
> +;; For loongson
> +
> +(define_insn "divsi3"
> + [(set (match_operand:SI 0 "register_operand" "=d")
> + (div:SI (match_operand:SI 1 "register_operand" "d")
> + (match_operand:SI 2 "register_operand" "d")))]
> + "TARGET_LOONGSON2E || TARGET_LOONGSON2F"
> + { return mips_output_division_g ("div.g\t%0,%1,%2", operands); }
> + [(set_attr "type" "divg")
> + (set_attr "mode" "SI")
> + (set (attr "length")
> + (if_then_else (ne (symbol_ref "TARGET_CHECK_ZERO_DIV") (const_int 0))
> + (const_int 16)
> + (const_int 4)))])
> +
> +(define_insn "udivsi3"
> + [(set (match_operand:SI 0 "register_operand" "=d")
> + (udiv:SI (match_operand:SI 1 "register_operand" "d")
> + (match_operand:SI 2 "register_operand" "d")))]
> + "TARGET_LOONGSON2E || TARGET_LOONGSON2F"
> + { return mips_output_division_g ("divu.g\t%0,%1,%2", operands); }
> + [(set_attr "type" "divg")
> + (set_attr "mode" "SI")
> + (set (attr "length")
> + (if_then_else (ne (symbol_ref "TARGET_CHECK_ZERO_DIV") (const_int 0))
> + (const_int 16)
> + (const_int 4)))])
Hi, Eric. This is my version:
--- trunk/gcc/config/mips/mips.c.orig 2008-11-10 02:23:33.000000000 +0800
+++ trunk/gcc/config/mips/mips.c 2008-11-10 02:24:56.000000000 +0800
@@ -10359,8 +10359,15 @@
}
else if (GENERATE_DIVIDE_TRAPS)
{
- output_asm_insn (s, operands);
- s = "teq\t%2,%.,7";
+ if (TARGET_LOONGSON_2EF)
+ {
+ output_asm_insn ("teq\t%2,%.,7", operands);
+ }
+ else
+ {
+ output_asm_insn (s, operands);
+ s = "teq\t%2,%.,7";
+ }
}
else
{
I have tried it. It seems to be working.
However, now I think adding a earlyclobber constraint may be the way to go.
Since it is a less intrusive and more elegant (comparing with my patch above)
change.
Zhang, Le