Hello.
I am working on imx8mmevk, with linux image built from Yocto. And I found that there will be no exception raised when a number divide zero at runtime. Below is an example in C:
int a=2/0;
float b=1.2/0;
// the result is: a=0, b=inf
printf("a=%d, b=%f", a, b);
As I know, registers FPCR (floating-point control register) with DZE bit and FPSR (floating-point status register) with DZC bit were designed to handle the situation for armv8. But referring to reference documents from i.MX 8M Mini | Arm Cortex A53 | Cortex M4 | NXP Semiconductors, I found that there is no DZE bit in a53, and it seems no way to get the exception.
I don't know if I got some mistakes, and I wonder how to handle the problem.
Could someone give me a hand?
=============================================
Edit at 2023.11.24.
Further ask.
Can I write my own ISR to handle division by zero (especially for floating-point)? May someone could give me advise.
=============================================
Thanks.
fffengzia
As far as I can tell, no ARM cores (not even the Cortex-X1) support trapping floating-point exceptions. Actually, in most systems (CPU:s and operating systems) trapping floating-point exceptions are either turned off by default or not supported at all, usually for good reasons (floating-point exceptions hurt performance, are largely misunderstood and are usually unnecessary).
I recommend that you find other ways of dealing with the problem.
First of all, it should be noted that division by zero is a well defined operation in IEEE 754 floating-point arithmetic. It returns +/-infinity, which is a valid input to other operations (e.g. 42/infinity = 0, 42+infinity=infinity, and so on). In fact, many algorithms actually work out perfectly fine even when division by zero is involved.
Second, if you really need to prevent division by zero in your code (be sure to figure out why it is not allowed), the canonical way to do that is to check the value of the denominator before the division, and handle it appropriately (e.g. throw a C++ exception if the denominator is zero). Another way is to use isfinite() to check the result of the division.
Also, as others have pointed out your examples will be calculated at compile time. In order to really trigger division by zero at runtime, you need to put the division in a function in a separate compilation unit (e.g. main() in main.c calls divide() in division.c), so that the compiler does not know the input values to the division at compile time.
Some ARM's indeed do support FPU exceptions.
FPSCR
Bits[15, 12:8] Floating-point exception trap enable bits. These bits are supported only in VFPv2, VFPv3U, and VFPv4U. They are reserved, RAZ/WI, on a system that implements VFPv3 or VFPv4.
Yeah. Though this ARM FPU exception (they are configurable to enable /0, imprecise, etc) could be kept enabled without affecting performance of any decent code:
IOE, bit[8] Invalid Operation exception trap enable.
Yeah, but 0/0 is invalid operation, not a number, Nan. As well invalid is Inf/Inf or any operation with NaN.
int a=2/0; float b=1.2/0;
These ^^ are compile time constants in most of compilers, which just can't raise any exception at run time. Did your compiler emit any warnings?
Have you tried to write a kernel module to test? It is possible that the compiler will handle it if write it this way.
Regards
Harvey
Harvey,
Please note!
It is a question about armv8 instruction.
Related no to any OS.
Far away from kernel.
I am sorry that I haven't express it clearly.
I need the exception at runtime, for the real situation is that the dividend is a variable and it becomes 0 accidently and then got into calculation.
I wrote an example code in my reply to Harvey, may that would explain my problem clearly.
Regards
fffengzia
Maybe I haven't expressed my situation clearly. There is nothing to do with compiler because what I need is to get an exception at runtime.
If I wrote it "1/0" or "1.2/0" explicitly, the compile does through an error or warning. But what if the zero is a variable, and it becomes 0 accidently (or carelessly)?
$ cat main.c
#include <stdio.h>
int main(int argc, char* argv[])
{
int a = 1, b = 1;
float c = 1.2;
int iRes;
float fRes;
// Accidently or Carelessly
a -= 1;
iRes = b/a;
fRes = c/a;
printf("1/0=%d, 1.2/0=%f\n", iRes, fRes);
return 0;
}
$ gcc -Wall main.c #No warning or error here
$ ./a.out
1/0=0, 1.2/0=inf
Arm® Architecture Reference Manual
Armv8, for A-profile architecture
Copyright © 2013-2021 Arm Limited or its affiliates. All rights reserved.
ARM DDI 0487G.b (ID072021)
No indication of this overflow is produced
A division by zero results in a zero being written to the destination register, without any indication that the division by zero occurred.
(that is why you find a = 0)
Please search fdiv to find information. floating divide has too many informati1, can not paste everything here.
It is also related to IEEE 754
a=0, b=inf inf=infinity
When you compile, compiler will give warning. You can change warning as error to stop compiling.
aarch64-linux-gnu-gcc -static -o div0 div0.c
div0.c: In function ‘main’:
div0.c:7:9: warning: division by zero [-Wdiv-by-zero]
int a=2/0;
^
div0.c:8:13: warning: division by zero [-Wdiv-by-zero]
float b=1.2/0;
^
Here is the assembly code for
int a=2/0;
float b=1.2/0;
.arch armv8-a
.file "div0.c"
.text
.section .rodata
.align 3
.LC0:
.string "a=%d, b=%f"
.text
.align 2
.global main
.type main, %function
main:
stp x29, x30, [sp, -48]!
add x29, sp, 0
str w0, [x29, 28]
str x1, [x29, 16]
mov w0, 2
mov w1, 0
sdiv w0, w0, w1
str w0, [x29, 44]
movi d0, #0
mov x0, 3689348814741910323
movk x0, 0x3ff3, lsl 48
fmov d1, x0
fdiv d0, d1, d0
fcvt s0, d0
str s0, [x29, 40]
ldr s0, [x29, 40]
fcvt d0, s0
adrp x0, .LC0
add x0, x0, :lo12:.LC0
ldr w1, [x29, 44]
bl printf
mov w0, 0
ldp x29, x30, [sp], 48
ret
I am so glad that you got my point :-).
The problem of integer division by zero could get its answer now.
From the Architecture Reference Manual:
And from A1.5.7:
About the FPCR:
However, it seems that this register is not forced to be used in every armv8 core, at least for a53:
ARM® Cortex®-A53 MPCore Processor
Advanced SIMD and Floating-point
Copyright © 2013-2016 ARM. All rights reserved.
ARM DDI 0502G (ID041316)
But not all a53 cores don't raise exception if floating-point division by zero. I have ever used another board from other manufacturer, which raise an exception if floating-point division happens. And I need to know if the a53 on imx8mmevk does able or not able to act like it.
I have referred to documents about imx8mmevk and could not found some useful.
This again may be optimized out to avoid /0 and use compile time constants. Try making your "a" global scope and volatile, so that -=1 and further /=0 can't be optimized out.