Подготовка в 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 будет включен по умолчанию, необходимость в этом отпадёт