Расширения SSE/AVX поддерживают инструкции логического и арифметического сдвига:
pslldq: сдвигает данные в регистре XMM влево на количество байтов, указанное в операнде imm8. В освободившиеся младшие байты помещаются нули.
pslldq xmmdest, imm8
vpslldq: берет значение из второго операнда-регистра XMM или YMM, сдвигает это значение влево на количество байт, указанное в третьем операнде. Затем сохраняет результат в регистре из первого операнда.
vpslldq xmmdest, xmmsrc, imm8 vpslldq ymmdest, ymmsrc, imm8
128-битный вариант инструкция также заполняет нулями биты со 128 по 255 регистра YMM.
psrldq: сдвигает данные в регистре XMM вправо на количество байтов, указанное в операнде imm8. В освободившиеся старшие байты помещаются нули.
psrldq xmmdest, imm8
vpsrldq: сдвигает вправл значение из второго операнда-регистра XMM или YMM на количество байт, указанное в третьем операнде. Затем сохраняет результат в первом операнде.
vpsrldq xmmdest, xmmsrc, imm8 vpsrldq ymmdest, ymmsrc, imm8
Стоит отметить, что эти инструкции сдвигают по байтам (то есть как минимум можно сдвинуть 8 разрядов). Но также есть ряд инструкций, которые сдвигают по отдельным битам причем не весь регистр в целом, а отдельные элементы в векторе в регистре. То есть каждый элемент вектора сдвигается на определенное количество бит. Это инструкции:
(v)psllw: сдвигает влево слово (значение word)
(v)pslld: сдвигает влево двойное слово (значение dword)
(v)psllq: сдвигает влево четверное слово (значение qword)
(v)psrlw: сдвигает вправо слово
(v)psrld: сдвигает вправо двойное слово
(v)psrlq: сдвигает вправо четверное слово
(v)psraw: арифметический сдвиг слова вправо
(v)psrad: арифметический сдвиг двойного слова вправо
(v)psraq: арифметический сдвиг четверного слова вправо
Синтаксис инструкций на примере (v)psllw
(остальные инструкции принимают те же операнды)
psllw xmmdest, imm8 psllw xmmdest, xmmsrc/mem128 vpsllw xmmdest, xmmsrc, imm8 vpsllw xmmdest, xmmsrc, mem128 vpsllw ymmdest, ymmsrc, imm8 vpsllw ymmdest, ymmsrc, xmm/mem128
В инструкции с двумя операндами первый операнд представляет сдвигаемое значение, а второй операнд указывает количество битов для сдвига. (это либо 8-битная непосредственная константа, либо регистр XMM, либо в 128-битная переменная).
В инструкции с тремя операндами второй операнд представляет сдвигаемое значение, а третий - количество битов для сдвига. Результат сдвига помещается в первый операнд. Исходный регистр остается неизменным (если, конечно, инструкция не указывает один и тот же регистр для исходного и целевого операндов).
Пример:
.data nums0 dword 1, 2, 4, 8 .code main proc movaps xmm0, nums0 pslld xmm0, 2 ; сдвигаем влево на 2 бита ret main endp end
Здесь сдвигаются влево на 2 разряда числа dword. Фактически каждое число будет умножено на 4. В итоге в XMM0 будет вектор 4, 8, 16, 32