> 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)))]) 2008/11/10 Andrew Haley <[EMAIL PROTECTED]>: > Zhang Le wrote: > >> >> The other would be make sure the destination register is different from >> source registers. >> I have read some docs, but still not sure how to do it. > > That's just an earlyclobber. Search for that. > > Andrew. >