Есть какие-нибудь хорошие 68k программисты на ассемблере? Я использую коммерческий компилятор Green Hills для Motorola 68040, и я вижу очень странное поведение из кода. Иногда код выполняет сравнение if / else и принимает неправильную ветвь. Например:
float a = 1, b = 2;
if (a < b)
do c;
else
do d;
Код иногда будет 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
Я просмотрел Справочное руководство программиста и не могу найти ничего, что указывало бы на то, что FSAVE или FMOVEM сохраняет регистры состояния FP. На самом деле, я видел один комментарий, который предполагает, что это не так: «FSAVE не сохраняет регистры модели программиста модуля с плавающей точкой; он сохраняет только невидимую пользователем часть машины». Поэтому я добавил несколько собственных сборок, чтобы сохранить регистры в начале ISR и восстановить их в конце, и это значительно улучшило производительность, но я все еще вижу некоторые проблемы. Ниже приведены дополнения, которые я сделал; переменные резервного копирования набираются как unsigned long в коде C:
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 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
Короче мои вопросы,
1) есть проблема с сгенерированной сборкой в том, что она не сохраняет регистры FPSR, FPCR и FPIAR, и
2) Правильно ли я сохраняю значения регистров при входе и выходе из ISR?
Было бы здорово, если бы у меня был другой компилятор для сравнения. К сожалению, я не могу прикрепить отладчик к коду. У меня большой опыт в C / C ++ / C # / Java / Python / PHP / и т. Д., Но я далеко не эксперт по сборке.
Любые идеи приветствуются!