_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, consider the following example C code:
#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;
b = 5.366789;
a = b / c;
printf("b / c = %f, ", a); // trap division-by-zero error
return 0;
}
This example code is compiled with the following command:
armcc --fpmode ieee_full
The compiled example disassembles to the following code:
main:
0x000080E0 : PUSH {r4,lr}
0x000080E4 : MOV r1,#0x200
0x000080E8 : MOV r0,#0x9f00
0x000080EC : BL __ieee_status ; 0xB9B8
0x000080F0 : MOV r4,#0
0x000080F4 : LDR r0,[pc,#40] ; [0x8124] = 0x891E2153
0x000080F8 : LDR r1,[pc,#40] ; [0x8128] = 0x40157797
0x000080FC : BL __aeabi_d2f ; 0xA948
0x00008100 : MOV r1,r4
0x00008104 : BL __aeabi_fdiv ; 0xB410
0x00008108 : BL __aeabi_f2d ; 0xB388
0x0000810C : MOV r2,r0
0x00008110 : MOV r3,r1
0x00008114 : ADR r0,{pc}+0x18 ; 0x812c
0x00008118 : BL __2printf ; 0x813C
0x0000811C : MOV r0,#0
0x00008120 : POP {r4,pc}
0x00008124 : DCD 0x891E2153
0x00008128 : DCD 0x40157797
0x0000812C : DCD 0x202F2062
0x00008130 : DCD 0x203D2063
0x00008134 : DCD 0x202C6625
0x00008138 : DCD 0x00000000
Placing a breakpoint on _fp_trapveneer()
and executing the disassembly in
the debug monitor produces:
> run
Execution stopped at breakpoint 1: S:0x0000BAC8
In _fp_trapveneer (no debug info)
S:0x0000BAC8 PUSH {r12,lr}
Then, inspection of the registers shows:
r0: 0x40ABBCBC r1: 0x00000000 r2: 0x00000000 r3: 0x00000000
r4: 0x0000C1DC r5: 0x0000BD44 r6: 0x00000000 r7: 0x00000000
r8: 0x00000000 r9: 0x00000000 r10: 0x0000BC1C r11: 0x00000000
r12: 0x08000004 SP: 0x0FFFFFF8 LR: 0x00008108 PC: 0x0000BAC8
CPSR: 0x000001D3
The address contained in the link register LR
is set to 0x8108, the
address of the instruction after the instruction BL __aeabi_fdiv
that resulted in
the exception.