8

優れた 68k アセンブリ プログラマーはいますか?? Motorola 68040 用に商用の Green Hills コンパイラを使用していますが、コードから非常に奇妙な動作が見られます。場合によっては、コードが if/else 比較を行い、間違った分岐を取ることがあります。例えば:

float a = 1, b = 2;

if (a < b)
    do c;
else 
    do d;

コードは時々 d!? になります。このエラーが発生するたびに、比較を中断する特定の ISR が常に 1 つあります。ISR 用に生成されたアセンブリを調べたところ、意味をなさないものがいくつかありました。まず、浮動小数点ステータス レジスタ、FPSR、FPCR、および FPIAR が ISR に保存されていないようです。これは、if/else が間違った分岐を取っている理由を説明します。FPSR レジスタは比較の結果を決定するために使用され、そのレジスタが ISR で上書きされた場合、分岐は間違ったパスを取る可能性があります。以下は、コンパイラーによって生成された入り口と出口のアセンブリーです。

isr_function:
    FSAVE   -(%SP)
    LINK    %A6,#-192
    MOVEM.L %D0/%D1/%D2/%A0/%A1,-(%SP)
    FMOVEM  %FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7,-(%SP)

    ; isr code ...

    FMOVEM  -308(%A6),%FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7
    MOVEM.L -212(%A6),%D0/%D1/%D2/%A0/%A1
    UNLK    %A6
    FRESTORE    (%SP)+
    RTE

Programmer's Reference Manual を調べましたが、FSAVE または FMOVEM が FP ステータス レジスタを保存することを示唆するものは見つかりません。実際、「FSAVE はプログラマの浮動小数点ユニットのモデル レジスタを保存しません。マシンのユーザーの目に見えない部分だけを保存します。」というコメントを見ました。そのため、ISR の開始時にレジスタを保存し、最後に復元するために独自のアセンブリを追加しました。これにより、パフォーマンスが劇的に改善されましたが、まだいくつかの問題が見られます。以下は私が行った追加です。C コードでは、バックアップ変数は unsigned long として入力されます。

isr_function:
    FSAVE   -(%SP)
    LINK    %A6,#-192
    MOVEM.L %D0/%D1/%D2/%A0/%A1,-(%SP)
    FMOVEM  %FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7,-(%SP)

    FMOVE %FPIAR,fpiar_backup
    FMOVE %FPSR,fpsr_backup
    FMOVE %FPCR,fpcr_backup

    ; isr code ...

    FMOVE fpiar_backup,%FPIAR
    FMOVE fpsr_backup,%FPSR
    FMOVE fpcr_backup,%FPCR

    FMOVEM  -308(%A6),%FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7
    MOVEM.L -212(%A6),%D0/%D1/%D2/%A0/%A1
    UNLK    %A6
    FRESTORE    (%SP)+
    RTE

レジスターを保存しないことで、コンパイラーに実際にバグがあるとは信じられませんでした。そこで、FPx と Dx の値を調べて、それらが適切な値に復元されていることを確認しましたが、そうではないようです。ただし、アセンブリ コードに変更を加えていないということは 100% ではありません。以下は、レジスタを保存するために追加したコードです。デバッグ変数は unsigned long として入力されます。

isr_function:
    FMOVE   %FP0,debug3
    FMOVE   %FP1,debug5
    FMOVE   %FP2,debug7
    FMOVE   %FP3,debug9
    FMOVE   %FP4,debug11
    FMOVE   %FP5,debug13
    FMOVE   %FP6,debug15
    FMOVE   %FP7,debug17
    FMOVE   %FPCR,debug19
    FMOVE   %FPIAR,debug23
    FMOVE   %FPSR,debug25   

    FSAVE   -(%SP)
    LINK    %A6,#-192
    MOVEM.L %D0/%D1/%D2/%A0/%A1,-(%SP)
    FMOVEM  %FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7,-(%SP)

    ; isr code ...

    FMOVEM  -308(%A6),%FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7
    MOVEM.L -212(%A6),%D0/%D1/%D2/%A0/%A1
    UNLK    %A6

    FMOVE   %FP0,debug4
    FMOVE   %FP1,debug6
    FMOVE   %FP2,debug8
    FMOVE   %FP3,debug10
    FMOVE   %FP4,debug12
    FMOVE   %FP5,debug14
    FMOVE   %FP6,debug16
    FMOVE   %FP7,debug18
    FMOVE   %FPCR,debug20
    FMOVE   %FPIAR,debug24
    FMOVE   %FPSR,debug26

    FRESTORE    (%SP)+
    RTE

要するに、私の質問は、

1) FPSR、FPCR、および FPIAR レジスターを保存しないという点で、生成されたアセンブリーに問題がありますか?

2) ISR に出入りするときに、レジスタの値を適切に保存していますか?

比較する別のコンパイラがあれば、それは素晴らしいことです。残念ながら、デバッガーをコードにアタッチできません。私は C/C++/C#/Java/Python/PHP などの経験が豊富ですが、アセンブリの専門家にはほど遠いです。

どんなアイデアでも大歓迎です!

4

2 に答える 2

3

将来の参考のために、問題は確かにコンパイラが浮動小数点ステータスレジスタの値を保存しないことに関連していました。Green Hills に連絡したところ、これはバグではなく、レジスタの値を保存するのはプログラマの責任であるとのことでした。コンパイラは FPU の内部状態を含む他のすべての内部レジスタを保存するので、これは私にとって奇妙です。なぜステータスレジスタで停止するのですか??

つまり、入ってくる FPSR と FPIAR の値を保存し、ISR を出るときに問題を修正します。次のようにしてください。

void isr(void)
{
    // variable declarations ...

    __asm("    FMOVE %FPIAR,-(%SP)"); 
    __asm("    FMOVE %FPSR,-(%SP)"); 

    // some code ...


    __asm("    FMOVE (%SP)+,%FPSR"); 
    __asm("    FMOVE (%SP)+,%FPIAR");
}
于 2011-11-15T16:19:14.063 に答える
2

私は 68020 の時代から 68K プログラミングを行っていませんが、関連する灰白質および/または Web リソースに手を差し伸べようとします :-)

特定の質問に答える:

FPSR、FPCR、および FPIAR レジスターが保存されないという点で、生成されたアセンブリーに問題はありますか?

私はそう言いますが、ISR に影響を与える何かがある場合に限ります。これはありそうにないように思えますが (ISR は高速であると想定されているため、浮動小数点を扱うことはないと思います)、コード変更される可能性がある場合に備えて、ルーチンがすべてを保存することを慎重に提案しているようです。

そうは言っても、ISR をどのようにコンパイルしているのか (または、それがあなたのコードなのかどうかさえも) わかりません。他のものを保存するためのコードをコンパイラに生成させるには、特別なフラグが必要な場合があります。

ISR に出入りするときに、レジスタの値を適切に保存していますか?

繰り返しますが、これは依存します。問題ないように見えますが、ISR 自体が別の割り込みを起こしにくいと確信していない限り、 fpiar_backuporのような特定のメモリ位置を使用することについては少し心配です。debug26

ISR 処理中に割り込みが無効になっている場合は、おそらく問題ありません。

さらに、その ISR が何を提供しているかによって異なります。ドキュメントは、浮動小数点の問題を処理するすべての ISR が常にfsave最初に実行する必要があることを示しているようです。

debugXISR の入口と出口でどの値が異なるかを確認できるように、これらの場所の値をダンプすると役立ちます。そして、それらが適切なサイズであることを確認してください。そして、ほぼ確実に異なる ISR の途中でそれらを見ないように注意してください。

于 2011-11-14T06:24:26.663 に答える