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 /等方面有丰富的经验,但我远非装配专家.
任何想法都表示赞赏!
自从 68020 时代以来,我就没有做过 68K 编程,但我会尝试深入研究相关的灰质和/或网络资源:-)
回答您的具体问题:
生成的程序集是否存在问题,因为它没有保存 FPSR、FPCR 和 FPIAR 寄存器?
我会说是的,但前提是 ISR 中存在影响他们的内容。虽然这似乎不太可能(ISR 应该很快,所以我不会指望它们会搞乱浮点的东西),但谨慎起见似乎建议例程保存所有内容,以防代码可能会更改它。
话虽如此,我不确定你是如何编译 ISR 的(甚至不确定它是否是你的代码)。可能需要一个特殊的标志来让编译器生成更多代码来保存其他内容。
当我进入和退出 ISR 时,我是否正确保存了寄存器的值?
同样,这取决于。看起来不错,但我会有点担心使用特定的内存位置,例如fpiar_backup或debug26,除非你非常确定 ISR 本身不会再次中断。
如果在 ISR 处理期间禁用中断,那么您可能没问题。
此外,这还取决于 ISR 所服务的内容。文档似乎表明任何处理浮点问题的 ISR 都应该首先执行fsave。
如果您转储这些debugX位置的值将会很有帮助,这样您就可以看到 ISR 的入口和出口之间的值有何不同。并确保它们的尺寸合适。请注意,不要在 ISR 中间查看它们,因为它们几乎肯定会有所不同。