[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