68040 принимает неправильную ветвь If Else - PullRequest
8 голосов
/ 14 ноября 2011

Есть какие-нибудь хорошие 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 / и т. Д., Но я далеко не эксперт по сборке.

Любые идеи приветствуются!

Ответы [ 2 ]

2 голосов
/ 15 ноября 2011

Для дальнейшего использования проблема действительно была связана с тем, что компилятор не сохранял значение регистров состояния с плавающей запятой.Я связался с 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");
}
2 голосов
/ 14 ноября 2011

Я не занимался программированием 68K со времен 68020, но постараюсь проникнуть в серую материю и / или веб-ресурсы: -)

Отвечая на ваши конкретные вопросы:

Есть ли проблема с созданной сборкой в ​​том, что она не сохраняет регистры FPSR, FPCR и FPIAR?

Я бы сказал, что да, но только если что-то есть вISR, который влияет на им.Хотя это кажется маловероятным (ISR должны быть быстрыми, поэтому я не ожидал бы, что они будут дурачиться с вещами с плавающей запятой), благоразумие, кажется, предполагает, что обычное сохранение всего просто на случайный случайэтот код может изменить его.

Сказав это, я не уверен, как вы компилируете ISR (или вообще, является ли он вашим кодом).Возможно, для того, чтобы компилятор генерировал больше кода для сохранения других вещей, необходим специальный флаг.

Правильно ли я сохраняю значения регистров при входе и выходе из ISR?

Опять же, это зависит.Это выглядит хорошо, но я бы немного беспокоился об использовании определенных областей памяти, таких как fpiar_backup или debug26, если вы не очень уверены, что сам ISR не склонен к другому прерыванию.

Если прерывания отключены во время обработки ISR, то вы, вероятно, в порядке.

Кроме того, это зависит от того, что обслуживает этот ISR.Документы, кажется, указывают, что любые ISR, обслуживающие проблемы с плавающей запятой, всегда должны делать сначала fsave.

Было бы полезно, если вы выгрузили значения этих debugX местоположений, чтобы вы могли видеть, какие значенияотличается между входом и выходом из ISR.И убедитесь, что они нужного размера.И будьте осторожны, чтобы вы не смотрели на них в середине ISR, где они почти наверняка будут другими.

...