| |||||||||||||
Technical Support On-Line Manuals RealView Compiler User's Guide | (Software) Floating point division
Floating‑point division‑by‑zero errors in software can be trapped and identified using a combination of intrinsics and C library helper functions. To trap floating‑point division‑by‑zero errors in your code, use the intrinsic: __ieee_status(FE_IEEE_MASK_ALL_EXCEPT, FE_IEEE_MASK_DIVBYZERO); This traps any division‑by‑zero errors in code, and untraps all other exceptions, as illustrated in Example 4.5. Example 4.5. Division by zero error #include <stdio.h> #include <fenv.h> int main(void)
{
float a, b, c;
// Trap the Invalid Operation exception and untrap all other exceptions:
__ieee_status(FE_IEEE_MASK_ALL_EXCEPT, FE_IEEE_MASK_DIVBYZERO);
c = 0;
a = b / c;
printf("b / c = %f, ", a); // trap division‑by‑zero error
return 0;
}
The C library helper function For example, suppose the C code of Example 4.5 is compiled from the command line using the string: armcc --fpmode ieee_full When the assembly language code produced by the compiler is disassembled, RealView Debugger produces the output shown in Example 4.6. Example 4.6. Disassembly of division by zero error
main:
00008080 E92D4010 PUSH {r4,lr}
00008084 E3A01C02 MOV r1,#0x200
00008088 E3A00C9F MOV r0,#0x9f00
0000808C EB000F1A BL __ieee_status <0xbcfc>
00008090 E59F0020 LDR r0,0x80b8
00008094 E3A01000 MOV r1,#0
00008098 EB000DEA BL _fdiv <0xb848>
0000809C EB000DBD BL _f2d <0xb798>
000080A0 E1A02000 MOV r2,r0
000080A4 E1A03001 MOV r3,r1
000080A8 E28F000C ADR r0,{pc}+0x14 ; 0x80bc
000080AC EB000006 BL __0printf <0x80cc>
000080B0 E3A00000 MOV r0,#0
000080B4 E8BD8010 POP {r4,pc}
000080B8 40A00000 <Data> 0x00 0x00 0xA0 '@'
000080BC 202F2062 <Data> 'b' ' ' '/' ' '
000080C0 203D2063 <Data> 'c' ' ' '=' ' '
000080C4 202C6625 <Data> '%' 'f' ',' ' '
000080C8 00000000 <Data> 0x00 0x00 0x00 0x00
Placing a breakpoint on > go Stopped at 0x0000BF6C due to SW Instruction BreakpointStopped at 0x0000BF6C: TRAPV_S\_fp_trapveneer Then, inspection of the registers shows: r0: 0x40A00000 r1: 0x00000000 r2: 0x00000000 r3: 0x00000000 r4: 0x0000C1DC r5: 0x0000C1CC r6: 0x00000000 r7: 0x00000000 r8: 0x00000000 r9: 0x00000000 r10: 0x0000C0D4 r11: 0x00000000 r12: 0x08000004 SP: 0x07FFFFF8 LR: 0x0000809C PC: 0x0000BF6C CPSR: nzcvIFtSVC The address contained in the link register To save parameters for post-mortem debugging you must intercept AREA foo, CODE IMPORT |$Super$$_fp_trapveneer| EXPORT |$Sub$$_fp_trapveneer| |$Sub$$_fp_trapveneer| ;; Add code to save whatever registers you need here ;; Take care not to corrupt any needed registers B |$Super$$_fp_trapveneer| END For more information see:
| ||||||||||||
| |||||||||||||