Копирование разрядов

Последнее обновление: 12.07.2023

Инструкции SBFM и UBFM копируют определенное количество бит из одного регистра в другой. Они имеют следующие формы:

SBFM Xd, Xs, #r, #s
UBFM Xd, Xs, #r, #s

Первый операнд - Xd указывает, в какой регистр копируются биты, а второй операнд - из какого регистра копируются биты. Третий операнд #r задает, с какого бита в Xs начинается копирование, а четвертый операнд - по какой бит идет копирование. В первый операнд биты копируются в самое начало.

В качестве регистров могут использоваться как 64-разрядные X0-X30, так и 32-разрядные W0-W30. SBFM учитывает знак при копировании и предназначена для чисел со знаком, а UBFM применяется для беззнаковых чисел.

Например, используем инструкцию SBFM:

mov x1, 47      // 0b00101111
sbfm x0, x1, #1, #4     // X0 = 0b000000111

Здесь в регистр X1 помещается число 47 или 0b00101111. Далее с помощью инструкции SBFM из регистра X1 извлекаем биты с номера 1 (нумерация начинается с нуля, поэтому бит с номером 1 по сути будет вторым битом), по бит с номером 4:

X1 = 0b00101111
X0 = 0b00000111

Таким образом, в регистр X0 будет помещаться число 0b0111, то есть число 7. При этом инструкция SBFM применяет копирование битов со знаком - все остальные биты первого регистра заполняются знаковым битом из второго регистра. Так, в предыдущем случае копируемое значение было равно 0111, где старший, он же знаковый бит был равен 0. Поэтому после копирования все остальные биты в X0 получали значение 0. Но теперь извлекем из числа 47 только два бита:

mov x1, #47      // 0b00101111
sbfm x0, x1, #1, #2     // X0 = 0b11111111

Извлекаемые два бита равны 11 - старший бит здесь равен 1, следовательно, знаковый бит, которым будет заполняться первый операнд, тоже равен 1, поэтому в результате мы получим число -1:

X1 = 0b00101111
X0 = 0b11111111

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

Инструкция UBFM работает похожим образом, только для беззнаковых чисел:

mov x1, #47      // 0b11110111
ubfm x0, x1, #1, #2     // X0 = 0b00000011

Инструкция EXTR

Инструкция EXTR извлекает биты из пары регистров:

EXTR Xd, Xs1, Xs2, count

Из регистра Xs1 берутся младшие count битов, а из Xs2 берутся все биты, кроме младших count битов. Взятые из обоих регистров биты объединяются и помещаются в Xd. Например:

mov w1, #7      // 0b00000000_00000000_00000000_00000111
mov w2, #255      // 0b00000000_00000000_00000000_11111111

extr w0, w1, w2, #2     // смещение два бита
// w0 = 11_000000_00000000_00000000_00111111

Здесь в качестве смещения применяется число 2. Поэтому сначала берем из второго операнда - регистра W2 2 младших бита (из 0b00000000_00000000_00000000_00000111 берем 11), затем из третьего операнда - регистра W3 берем все биты, кроме 2 младших бита (из 0b00000000_00000000_00000000_11111111 берем 0b00000000_00000000_00000000_111111). Таким образом, в W0 будет располагаться число 11_000000_00000000_00000000_00111111

Для определенных форм этих инструкций также можно использовать псевдонимы:

Инструкция

Условие

Псевдоним

SBFM Xd, Xn, #r, #s

#s == 63

ASR Xd, Xn, #shift

SBFM Wd, Wn, #r, #s

#s == 31

ASR Wd, Wn, #shift

UBFM Xd, Xn, #r, #s

#s != 63 && #s+1 == #r

LSL Xd, Xn, #shift

#s == 63

LSR Xd, Xn, #shift

UBFM Wd, Wn, #r, #s

#s != 31 && #s+1 == #r

LSL Wd, Wn, #shift

#s == 31

LSR Wd, Wn, #shift

EXTR Xd, Xn, Xm, #lsb

Xn == Xm

ROR Xd, Xn, #shift

EXTR Wd, Wn, Wm, #lsb

Wn == Wm

ROR Wd, Wn, #shift

Извлечение битов со вставкой

Ряд инструкций выполняют извлечение битов со вставкой

BFI Xd, Xn, #lsb, #width
BFXIL Xd, Xn, #lsb, #width
SBFIZ Xd, Xn, #lsb, #width
SBFX Xd, Xn, #lsb, #width
UBFIZ Xd, Xn, #lsb, #width
UBFX Xd, Xn, #lsb, #width

BFI Wd, Wn, #lsb, #width
BFXIL Wd, Wn, #lsb, #width
SBFIZ Wd, Wn, #lsb, #width
SBFX Wd, Wn, #lsb, #width
UBFIZ Wd, Wn, #lsb, #width
UBFX Wd, Wn, #lsb, #width

Эти инструкции копируют набор битов из второго операнда-регистра в определенное местоположение в первом операнде. Количество копируемых битов задается с помощью четвертого операнда - #width.

Третий операнд - #lsb для инструкций SBFX, UBFX, BFXIL задает позицию во втором операнде, с которой надо извлечь #width битов, а для инструкций SBFIZ, UBFIZ, BFI задает номер бита в первом операнде, с которого происходит вставка копируемых битов .

  • BFI: извлекает из второго операнда с нулевого байта и вставляет их на определенную позицию в первом операнде, остальные биты в первом операнде остаются неизменными

  • BFXIL: извлекает из второго операнда с определенной позиции и вставляет их начиная с нулевого байта в первом операнде, остальные биты в первом операнде остаются неизменными

  • SBFIZ: извлекает из второго операнда с нулевого байта и вставляет их на определенную позицию в первом операнде, остальные старшие биты в первом операнде заполняются знаковым битом, младшие биты - нулями

  • SBFX: извлекает из второго операнда с определенной позиции и вставляет их начиная с нулевого байта в первом операнде, остальные биты в первом операнде заполняются знаковым битом

  • UBFIZ: извлекает из второго операнда с нулевого байта и вставляет их на определенную позицию в первом операнде, остальные биты в первом операнде заполняются нулями

  • UBFX: извлекает из второго операнда с определенной позиции и вставляет их начиная с нулевого байта в первом операнде, остальные биты в первом операнде заполняются нулями

Рассмотрим самую сложную операцию из вышеперечисленных - SBFIZ:

mov x1, #-2         // 0b11111110
mov x0, #0b00011111  // 31
sbfiz x0, x1, #1, #2    // X0 = 0b11111100

Здесь из числа в X1 извлекает 2 бита с начала - 0b11111110 и вставляем из со бита номер 1 в регистр X0.

X0 = 0b00011111
X1 = 0b11111110
-----------
X0 = 0b11111100

Все младшие биты в X0, которые идут до вставленных, заполняются нулями, а старшие биты, которые идут после вставленных, заполняются знаковым битом, который в данном случае равен 1. Поэтому в X0 в итоге будет число 0b11111100 или -4

Ряд других примеров. BFI оставляет все биты, кроме вставленных, без изменений:

mov x1, #-2         // 0b11111110
mov x0, #0b0011111  // 13
bfi x0, x1, #1, #2    // X0 = 0b0011101 = 29

UBFIZ все биты, кроме вставленных, заполняет нулями:

mov x1, #-2         // 0b11111110
mov x0, #0b0011111  // 13
ubfiz x0, x1, #1, #2    // X0 = 0b00000100 = 4
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850