Subject: [RFC] MIPS division by zero and libgcj...

From: David Daney <[email-masked]>
Date: Thu, 10 Jun 2004 12:12:27 -0700

It appears that gcc configured for mipsel-linux will execute a "break 7" 
instruction on integer division by zero.

This causes the kernel (I am using 2.4.25) to send SIGTRAP.

Gcj when configured for this platform uses the -f-use-divide-subroutine 
option, causing it to never generate inline division instructions (nor 
the accompanying break 7), but instead call a runtime function that 
properly handles throwing ArithmeticException.

Q1:  Is this behavior (use of break 7 and SIGTRAP) part of some ABI 
specification?  I'll admit a bit of ignorance in this area.

Q2: Does anyone see any reason that libgcj should not be configured to 
handle the SIGTRAP and throw the ArithmeticException from the signal 
handler (similar to what is done on i386).

Q3: Will using SIGTRAP in this manner make debugging programs that 
divide things by zero very difficult to debug under gdb?

Q4: I appears that on the i386, a divide overflow causes SIGFPE.  Why 
doesn't the mips-linux kernel sent SIGFPE on "break 7"

Q5: prims.cc in libgcj implies that we should be handling SIGFPE to do 
all this.  If I make these changes, won't it be a little confusing that 
all references to SIGFPE are really SIGTRAP?

David Daney

---

From: Andrew Haley <[email-masked]>
Date: Thu, 10 Jun 2004 20:31:47 +0100

> instruction on integer division by zero.

I thought that the MIPS never generated a hardware trap for division,
but instead there was an assembler macro that did the test for
overflow, and the "div" instruction actually generates this test
inline.  Maybe do a disassembly to check.

 > specification?  I'll admit a bit of ignorance in this area.

See above.

 > handler (similar to what is done on i386).

No, there's no reason not to do it.  You'll have to write some hairy
code to satisfy all the rules, though.

 > divide things by zero very difficult to debug under gdb?

No.

 > all references to SIGFPE are really SIGTRAP?

Feel free to change the comments.  :-)

Andrew.

---

From: Andrew Haley <[email-masked]>
Date: Thu, 10 Jun 2004 20:39:25 +0100

> inline.  Maybe do a disassembly to check.

Here we are:

MIPS Dependent Features

--trap
--no-break

    automatically macro expands certain division and multiplication
    instructions to check for overflow and division by zero. This
    option causes to generate code to take a trap exception rather
    than a break exception when an error is detected. The trap
    instructions are only supported at Instruction Set Architecture
    level 2 and higher.

--break
--no-trap

    Generate code to take a break exception rather than a trap
    exception when an error is detected. This is the default.

Andrew.

---

From: David Daney <[email-masked]>
Date: Thu, 10 Jun 2004 12:48:00 -0700

>inline.  Maybe do a disassembly to check.
MIPS div instructions never trap.  However I think that GCC always emits 
things like this when it cannot determine that the divisor is non zero:

        div     $0,$17,$16
        bne     $16,$0,1f
        nop
        break   7

>code to satisfy all the rules, though.
What are the rules?  Are they more complicated then throw an 
ArithmeticException when the divisor is zero?

> > divide things by zero very difficult to debug under gdb?
I have not tried it.  But I think gdb uses "break" and SIGTRAP for 
breakpoints.  Is it possible to get gdb to pass the signal to the 
debugee, so that it could be handled by the runtime support?

---

From: Andrew Haley <[email-masked]>
Date: Thu, 10 Jun 2004 20:58:00 +0100

> ArithmeticException when the divisor is zero?

Yes.  You also have to do

  if (dividend == (jint) 0x80000000L && divisor == -1)
    return dividend;
  
and not throw an exception.

 > debugee, so that it could be handled by the runtime support?

Well, gcj will generate either break or trap instructions.  You can
tell gdb to ignore either.

Andrew.

---

From: Ralf Baechle <[email-masked]>
Date: Thu, 10 Jun 2004 22:27:51 +0200

> inline.  Maybe do a disassembly to check.

Linux/MIPS's behaviour is consistent with all MIPS UNIX flavours I know
of both those following the SysV ABI and others such as Ultrix.

  Ralf

---

From: David Daney <[email-masked]>
Date: Thu, 10 Jun 2004 13:31:14 -0700

>and not throw an exception.
That is evidently what you have to do on i386.  MIPS gives the right 
answer without faulting (i.e. hitting the break 7).

David Daney.

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Fri, 11 Jun 2004 16:01:42 +0200 (CEST)

> This causes the kernel (I am using 2.4.25) to send SIGTRAP.

 It looks like you have a problem in your configuration.  A "break 7"  
(or "teq <divisor>,$zero,7" -- but that's currently implemented in gas
only) is indeed emitted and exectuted in the case of division by zero, but
Linux has the ability to recognize this special break code and sends
SIGFPE instead.  There are actually two special codes defined, the other
being "6" for an overflow.  Both are handled by Linux, with si_code in
struct siginfo being set to FPE_INTDIV or FPE_INTOVF, respectively.  You
can handle this appropriately in a signal handler.

-- 
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: [email-masked], PGP key available        +

---

From: David Daney <[email-masked]>
Date: Fri, 11 Jun 2004 08:34:25 -0700

>can handle this appropriately in a signal handler.
My kernel sources are from linux-mips.org, it is little-endian running on:

# cat /proc/cpuinfo
system type             : ATI-Xilleon
processor               : 0
cpu model               : MIPS 4Kc V0.7
BogoMIPS                : 299.00
wait instruction        : yes
microsecond timers      : yes
tlb_entries             : 16
extra interrupt vector  : yes
hardware watchpoint     : yes
VCED exceptions         : not available
VCEI exceptions         : not available

Could you point me to where in the kernel source this is handled?  I 
will try to see what when wrong.

David Daney.

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Fri, 11 Jun 2004 17:39:57 +0200 (CEST)

> will try to see what when wrong.

 For 2.4 it's arch/mips{,64}/kernel/traps.c, functions do_bp() and
do_tr().