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