Возврат регистра SSE с отключенным SSE

Я в следующей ситуации:

  • Я пишу код для ядра, которое не поддерживает инструкции SSE.
  • Мне нужно сделать арифметику с плавающей запятой
  • Я компилирую для платформы x86_64

Вот пример кода, иллюстрирующий проблему:

int
main(int argc, char** argv)
{
    double d = 0.0, dbase;
    uint64_t base_value = 300;

    d = (2200.0 - 1000.0)/(1000.0);
    dbase = d * base_value;
    printf("d = %f, dbase = %f\n", d, dbase);
    base_value = dbase;
    printf("base_value = %llu\n", (long long unsigned)base_value);
    return 0;
}

А вот соответствующая строка из make-файла:

CFLAGS +=   -mcmodel=kernel -mno-red-zone -mfpmath=387 -mno-sse -mno-sse2 -mno-mmx -mno-3dnow \
            -msoft-float -fno-asynchronous-unwind-tables -fno-omit-frame-pointer

Когда я запускаю сборку, я получаю эту ошибку:

SSE register return with SSE disabled

(Ошибка указывает на строку, которая умножает d и base_value)

Любая идея, что я могу сделать, чтобы исправить это? Удаление -mno-sse не вариант, но похоже, что компилятор должен иметь возможность генерировать не-sse код для выполнения умножения.

Спасибо, Натан.


person Nathan    schedule 12.10.2009    source источник
comment
Возможно, gcc не может справиться с этим случаем, потому что предполагает, что все процессоры x86-64 имеют SSE.   -  person Amok    schedule 12.10.2009
comment
Означает ли это, что никто и никогда ничего не умножает внутри ядра FreeBSD на 64-битных сборках?   -  person Nathan    schedule 12.10.2009
comment
Любое ядро, над которым я работал, стремится максимально избегать операций с плавающей запятой.   -  person Carl Norum    schedule 12.10.2009
comment
Карл, интересно, почему это так. Регистры FP обычно не сохраняются при переключении режима?   -  person avakar    schedule 12.10.2009
comment
Да. Разработчики ядра ненавидят необходимость сохранять и восстанавливать больше регистров.   -  person Stephen Canon    schedule 12.10.2009
comment
gcc отлично справляется с математикой x87 (если вы скажете ядру сохранить/восстановить состояние FPU x87 пользовательского пространства). Проблема заключается в передаче double в качестве аргумента функции, поскольку вы компилируете соглашение о вызовах, которое передает double аргументов в регистры XMM. Если вы опустите printf("d = %f, dbase = %f\n", d, dbase);, вы сможете писать функции, использующие FP-математику, даже с -mno-sse: например. см. godbolt.org/g/oIM1rS для вывода ассемблера из простой функции.   -  person Peter Cordes    schedule 29.11.2016


Ответы (1)


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

Если в вашем ядре вообще возможно использовать числа с плавающей запятой, должна быть специальная библиотека времени выполнения для выполнения операций с мягким числом с плавающей запятой, которая не использует обычные (пользовательские) соглашения о передаче и возврате аргументов. Однако, насколько мне известно, в ядре BSD нет поддержки операций с плавающей запятой. Так было, конечно, несколько лет назад.

Вероятно, вам следует просто спросить список рассылки разработчиков ядра BSD, возможно ли использовать числа с плавающей запятой; Я подозреваю, что это даст вам более быстрый и точный ответ, чем SO.

person Stephen Canon    schedule 12.10.2009
comment
Вместо этого я решил просто использовать арифметику с фиксированной запятой (ядро, о котором идет речь, основано на ядре FreeBSD, но значительно изменено, поэтому я не был уверен, что какой-либо из официальных списков рассылки даст лучший ответ, чем не делайте этого). . - person Nathan; 13.10.2009
comment
Ах. Извините, что на этот вопрос нет более счастливого ответа. - person Stephen Canon; 13.10.2009