[PATCH] RISC-V: align RISC-V software division with hardware specification in case of division by zero

MOSER Virginie virginie.moser@csem.ch
Fri May 29 08:53:01 GMT 2020


The assembly code in libgcc/config/riscv/div.S does not handle the division by zero as specified in the riscv-spec v2.2 chapter 6.2 in case of signed division:

"The quotient of division by zero has all bits set, i.e. 2XLEN−1 for unsigned division or−1 for signed division."

When a negative number is divided by zero in the __divdi3 function, the result is 1 instead of -1.

As soon as there exists a specific implementation for the software division for the RISC-V and although that the C language allows unspecified result in case of division by zero, it would be worth aligning the software RISC-V division with the hardware implementation so that the compliance tests could pass whatever the -mno-div or -mdiv flag value.
Especially in the case where the patch is simple, does not add additional code size nor execution time.

The patch proposes that when the dividend is negative, a zero divisor is considered as negative so that the result of the unsigned division will not be inverted. This consists of exchanging a "branch greater or equal zero (bgez)" with a "branch greater than zero (bgtz)".

Virginie

-------------------------------------------

ChangeLog

*libgcc/config/riscv/div.S: Change handling of signed division by zero in case of negative dividend to align with RISC-V specification for hardware division.

--------------------------------------------

diff --git a/libgcc/config/riscv/div.S b/libgcc/config/riscv/div.S
index 922a4338042..57f5856e11d 100644
--- a/libgcc/config/riscv/div.S
+++ b/libgcc/config/riscv/div.S
@@ -107,7 +107,8 @@ FUNC_END (__umoddi3)
   /* Handle negative arguments to __divdi3.  */
.L10:
   neg   a0, a0
-  bgez  a1, .L12      /* Compute __udivdi3(-a0, a1), then negate the result.  */
+  bgtz  a1, .L12      /* Compute __udivdi3(-a0, a1), then negate the result.  */
+                      /* Zero is handled as a negative so that the result will not be inverted */
   neg   a1, a1
   j     __udivdi3     /* Compute __udivdi3(-a0, -a1).  */


More information about the Gcc-patches mailing list