Подготовка в lcc-1.29 для E2K к будущим несовместимым изменениям при работе с register asm переменными типа long double¶
Вводное описание¶
Вводное описание и терминология полностью совпадают с разделом “Вводное описание” из статьи Подготовка в lcc-1.28 для E2K к будущим несовместимым изменениям при работе с аргументами ассемблерных вставок, имеющих тип long double или 16-байтный GNU-vector, поэтому мы не будем его дублировать
Старое поведение¶
В компиляторах версии lcc-1.28 и ниже имелось несимметричное поведение при работе
с register asm переменными типа long double (для которого sizeof равен 16
байтам), которое можно продемонстрировать на следующем примере:
/* 16-байтная переменная типа __int128_t будет распределена на quadro регистр
* (т.е. на пару регистров %g2-%g3).
* Поведение lcc симметрично поведению gcc на прочих архитектурах,
* где имеется поддержка 16-байтного целочисленного типа */
register __int128_t i asm ("%g2");
/* Реальный битовый размер long double равен 80 битам, но с точки зрения
* языка его размер равен 128 битам (16 байтам).
* 16-байтная переменная типа long double будет распределена на extended fx-регистр
* (т.е. на один регистр %xg4) */
register long double ld asm ("%g4");
Как мы видим, работа с разными типами, имеющими номинальный размер в 16 байт (128 бит), была построена несимметрично. Поведение зависело от конкретного типа переменной, что само по себе уже противоречило общим правилам построения register asm переменных в gcc. К тому же такой вариант работы предполагал, что пользователь напрямую был лишён простой возможности выбора между quadro-регистром и extended регистром. При необходимости использования конкретного типа регистра, отличного от того, какой использует компилятор, требовалось применение технических трюков
Тип long double вываливался из общего подхода работы с register asm переменными из-за
его несимметричной обработки компилятором lcc
Новое поведение¶
Начиная с lcc-1.29 для описания используемого регистра для register asm переменных в компилятор введены псевдоимена регистров. Теперь для явного описания extended регистра следует использовать префикс ‘x’ перед именем регистра. Без префикса регистр всегда будет трактоваться как не-extended. Например:
/* Переменная будет распределена на quadro-регистр,
* т.е. на пару регистров %g2-%g3 */
register __int128_t i1 asm ("%g2");
/* Переменная будет распределена на quadro-packed регистр,
* т.е. на один extended регистр %qpg5.
* Поскольку регистр только один, то можно использовать нечётный номер.
* Quadro-packed регистры доступны только для процессоров elbrus-v5 и выше */
register __int128_t i2 asm ("%xg5");
/* Переменная будет распределена на quadro-регистр,
* т.е. на пару регистров %g6-%g7, в регистре %g7 будут использованы только 16 бит */
register long double ld1 asm ("%g6");
/* Переменная будет распределена на fx-регистр,
* т.е. на один extended регистр %xg9.
* Поскольку регистр только один, то можно использовать нечётный номер */
register long double ld2 asm ("%xg9");
Переходный период¶
Новое поведение компилятора противоречит старому поведению только в тех случаях, когда
используется не-extended регистр (т.е. без префикса ‘x’ в имени) для типа long double.
Поэтому в компиляторе начиная с версии lcc-1.29 на промежуточный период введена опция
-mold-register-asm-long-double, по которой использование не-extended регистра для
register asm переменных типа long double будет рассматриваться как использование
extended-регистра с выдачей дополнительного предупреждения. Это означает повторение
старого поведения плюс предупреждение о проблемном месте, которое необходимо исправить
для компиляторов версии lcc-1.29 и выше. Использование опции -mold-register-asm-long-double
никак не затрагивает исходники, явно использующие extended регистры
В компиляторе lcc-1.29 режим -mold-register-asm-long-double включен по умолчанию.
Однако такое поведение компилятора объявлено устаревшим (DEPRECATED). В будущем по
умолчанию будет включен инвертированный режим -mno-old-register-asm-long-double,
который уже будет не совместим со старыми исходниками. В режиме
-mno-old-register-asm-long-double никаких предупреждений уже не будет выдаваться,
т.к. использование не-extended регистра в отношении типа long double будет иметь новую
трактовку. При этом для возможности компиляции старых исходников по прежнему будет
возможно использовать опцию -mold-register-asm-long-double (включая выдачу
предупреждения), но опцию нужно будет явно указывать в строке компиляции. В совсем
далёком будущем опции -mold-register-asm-long-double и -mno-old-register-asm-long-double
будут удалены, и останется только режим работы с новым поведением без возможности
повторения старого поведения
Если в компиляторе lcc-1.29 и выше нужно собрать программу, в которой не-extended регистр
используется для register asm переменных типа long double в новой трактовке,
то придётся подавать инвертированную опцию -mno-old-register-asm-long-double.
В будущем, когда инвертированный режим -mno-old-register-asm-long-double будет
включен по умолчанию, необходимость в этом отпадёт
