Преобразование между прямым и обратным порядком байтов в RISC-V - PullRequest
0 голосов
/ 30 августа 2018

Какой самый простой способ работы со значениями с прямым порядком байтов в RISC-V на уровне ассемблера? То есть, как загрузить значение с прямым порядком байтов из памяти в регистр, поработать со значением в регистре с прямым порядком байтов (little-endian), а затем сохранить его в памяти с прямым порядком байтов. 16, 32 и 64-битные значения используются во многих сетевых протоколах и форматах файлов.

Я не смог найти инструкцию по замене байтов (эквивалентную BSWAP на x86 или REV на ARM) в руководстве , и ничего о загрузках и хранилищах с прямым порядком байтов.

Ответы [ 2 ]

0 голосов
/ 04 октября 2018

RISC-V ISA не имеет явных инструкций по замене байтов. Лучше всего использовать встроенный C для выполнения этого расчета, который на земле GCC будет примерно равен __builtin_bswap32(). Это дает компилятору максимально возможную информацию, чтобы он мог принимать правильные решения. С текущим набором определенных ISA вы почти наверняка закончите вызовом подпрограммы, но если расширение B когда-либо будет определено, вы прозрачно получите лучше сгенерированный код. Полный набор определенных встроенных функций доступен онлайн: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.

Если вы застряли, выполняя это в сборке, тогда вам лучше всего обратиться к существующей процедуре замены байтов. Каноническим для 32-битного свопа является __bswapsi2, который является частью libgcc - вы, вероятно, используете его в любом случае, так что он будет рядом. Это то, что в настоящее время делает компилятор, поэтому все, что вы теряете - это исключение вызова функции, когда есть лучшая доступная реализация.

В качестве конкретного примера, вот мой пример функции C

unsigned swapb(unsigned in) { return __builtin_bswap32(in); }

и сгенерированная сборка

swapb:
    addi    sp,sp,-16
    sd  ra,8(sp)
    call    __bswapsi2
    ld  ra,8(sp)
    sext.w  a0,a0
    addi    sp,sp,16
    jr  ra
0 голосов
/ 30 августа 2018

По состоянию на август 2018 года:

В самой последней инструкции RISC-V User-Level *1004* (версия 2.1) нет инструкции по замене байтов. Однако в руководстве есть заполнитель для «B» стандартного расширения для битовой манипуляции . Некоторые черновые материалы рабочей группы этого расширения собраны на GitHub . В частности, проект спецификации говорит о команде grev (обобщенная обратная), которая может выполнять 16, 32 и 64-битные перестановки байтов:

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

Однако рабочая группа по продлению B была "распущена по бюрократическим причинам в ноябре 2017 года", прежде чем они смогли завершить разработку спецификации.

В результате, в настоящее время, кажется, нет ничего проще, чем делать обычную сменную маску или танец. Я не смог найти встроенного языка ассемблера bswap в портах GCC или clang riscv. В качестве примера приведем разбор функции bswapsi2 (которая заменяет 32-битное значение в байтах), испускаемой компилятором riscv64-linux-gnu-gcc версии 8.1.0-12:

000000000000068a <__bswapsi2>:
 68a:   0185169b                slliw   a3,a0,0x18
 68e:   0185579b                srliw   a5,a0,0x18
 692:   8fd5                    or      a5,a5,a3
 694:   66c1                    lui     a3,0x10
 696:   4085571b                sraiw   a4,a0,0x8
 69a:   f0068693                addi    a3,a3,-256 # ff00 <__global_pointer$+0xd6a8>
 69e:   8f75                    and     a4,a4,a3
 6a0:   8fd9                    or      a5,a5,a4
 6a2:   0085151b                slliw   a0,a0,0x8
 6a6:   00ff0737                lui     a4,0xff0
 6aa:   8d79                    and     a0,a0,a4
 6ac:   8d5d                    or      a0,a0,a5
 6ae:   2501                    sext.w  a0,a0
 6b0:   8082                    ret
...