| |||
| Home > Compiler Coding Practices > Identification of software floating-point division-by-zero errors | |||
The C library helper function _fp_trapveneer() is
called whenever an exception occurs. On entry into this function,
the state of the registers is unchanged from when the exception occurred.
Therefore, to find the address of the function in the application
code that contains the arithmetic operation that resulted in the
exception, a breakpoint can be placed on the function _fp_trapveneer() and LR can
be inspected.
For example, suppose the C code of Example 38 is compiled from the command line using the string:
armcc --fpmode ieee_full
When the assembly language code produced by the compiler is disassembled, the debugger produces the output shown in Example 39.
Example 38. Trapped 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;
}
Example 39. 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 _fp_trapveneer and
executing the disassembly in the debug monitor produces:
> 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 LR is
set to 0x809c, the address of the instruction after the instruction BL
_fdiv that resulted in the exception.