68040错误的分支

Sam*_*uel 8 compiler-construction assembly 68000 isr

有没有好的68k组装程序员在那里?我正在为摩托罗拉68040使用商业Green Hills编译器,我从代码中看到一些非常奇怪的行为.有时,代码会执行if/else比较,并采用错误的分支.例如:

float a = 1, b = 2;

if (a < b)
    do c;
else 
    do d;
Run Code Online (Sandbox Code Playgroud)

代码有时会d !? 我发现,当发生此错误时,总会有一个特定的ISR中断比较.我看了一下ISR生成的程序集,看到了一些对我没有意义的事情.首先,看起来浮点状态寄存器FPSR,FPCR和FPIAR不会保存在ISR中.这可以解释为什么if/elses采取了错误的分支.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
Run Code Online (Sandbox Code Playgroud)

我查看了程序员参考手册,但我找不到任何暗示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
Run Code Online (Sandbox Code Playgroud)

我很难相信编译器实际上有一个错误就是没有保存寄存器.所以我开始查看FPx和Dx的值,看它们是否恢复到正确的值,看起来它们不是.但是,我不是百分之百,我没有修改汇编代码.以下是我为保存寄存器而添加的代码; 调试变量的类型为unsigned longs:

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
Run Code Online (Sandbox Code Playgroud)

总之我的问题是,

1)生成的程序集是否存在问题,因为它不保存FPSR,FPCR和FPIAR寄存器,以及

2)当我进入和退出ISR时,我是否正确保存了寄存器的值?

如果我有另一个编译器进行比较,那将是很好的.不幸的是我无法将调试器附加到代码中.我在C/C++/C#/ Java/Python/PHP /等方面有丰富的经验,但我远非装配专家.

任何想法都表示赞赏!

pax*_*blo 3

自从 68020 时代以来,我就没有做过 68K 编程,但我会尝试深入研究相关的灰质和/或网络资源:-)

回答您的具体问题:

生成的程序集是否存在问题,因为它没有保存 FPSR、FPCR 和 FPIAR 寄存器?

我会说是的,但前提是 ISR 中存在影响他们的内容。虽然这似乎不太可能(ISR 应该很快,所以我不会指望它们会搞乱浮点的东西),但谨慎起见似乎建议例程保存所有内容,以防代码可能会更改它。

话虽如此,我不确定你是如何编译 ISR 的(甚至不确定它是否是你的代码)。可能需要一个特殊的标志来让编译器生成更多代码来保存其他内容。

当我进入和退出 ISR 时,我是否正确保存了寄存器的值?

同样,这取决于。看起来不错,但我会有点担心使用特定的内存位置,例如fpiar_backupdebug26,除非你非常确定 ISR 本身不会再次中断。

如果在 ISR 处理期间禁用中断,那么您可能没问题。

此外,这还取决于 ISR 所服务的内容。文档似乎表明任何处理浮点问题的 ISR 都应该首先执行fsave

如果您转储这些debugX位置的值将会很有帮助,这样您就可以看到 ISR 的入口和出口之间的值有何不同。并确保它们的尺寸合适。请注意,不要在 ISR 中间查看它们,因为它们几乎肯定会有所不同。