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

Reply via email to