5.57 ソフトウェアでのゼロによる浮動小数点除算エラーの識別

C ライブラリヘルパ関数 _fp_trapveneer() を使用すると、ソフトウェアでのゼロによる浮動小数点除算エラーの場所を特定できます。

_fp_trapveneer() は、例外が発生するたびに呼び出されます。この関数の呼び出し時、レジスタの状態は、例外が発生したときから変更されていません。そのため、ブレークポイントを関数 _fp_trapveneer() に設定し、LR を検査することにより、例外を返した演算が含まれている関数のアドレスをアプリケーションコードで見つけることができます。
例えば、以下のサンプル C コードを考えてみます。
#include <stdio.h>
#include <fenv.h>
int main(void)
{    float a, b, c;
    // 無効演算例外のトラップを有効にし、他のすべての例外のトラップを
    // 無効にする:
    __ieee_status(FE_IEEE_MASK_ALL_EXCEPT, FE_IEEE_MASK_DIVBYZERO);
    c = 0;
    b = 5.366789;
    a = b / c;
    printf("b / c = %f, ", a); // ゼロ除算エラーをトラップする
    return 0;
}
このサンプルコードは、以下のコマンドを使用してコンパイルされます。
armcc --fpmode ieee_full
コンパイルされたサンプルは、以下のコードに逆アセンブルされます。
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
_fp_trapveneer() にブレークポイントを設定し、デバッグモニタで逆アセンブリを実行すると、以下が生成されます。
> run
Execution stopped at breakpoint 1: S:0x0000BAC8
In _fp_trapveneer (no debug info)
S:0x0000BAC8   PUSH     {r12,lr}
次に、レジスタを調べると、以下が示されます。
  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
リンクレジスタ LR に含まれているアドレスは、0x8108(例外の原因となった命令 BL __aeabi_fdiv の後の命令のアドレス)に設定されます。
関連する概念
5.55 C コードのソフトウェアでのゼロによる浮動小数点除算エラー
5.56 ソフトウェアでのゼロによる浮動小数点除算エラーのトラップについて
5.58 ソフトウェアでのゼロによる浮動小数点除算エラーのデバッグ
非機密扱いPDF file icon PDF 版ARM DUI0472LJ
Copyright © 2010-2015 ARM.All rights reserved.