Sie sind auf Seite 1von 2

Informaes sobre programao em Assembly da unidade SSE2

1.

Introduo

A unidade SSE2, disponvel a partir dos processadores Pentium IV, faz uso dos registradores de 128
bits XMM0 a XMM7 (para programao em modo de operao de 32 bits), permitindo operar sobre 16 bytes, 8 words, 4 dwords, 2 qwords ou 1 dqword inteiros simultaneamente. Este documento visa fornecer algumas informaes teis para um primeiro uso dessas facilidades no que diz respeito a processamento de inteiros. As operaes com operandos no formato ponto flutuante,
tambm disponveis na unidade SSE2, no sero abordadas aqui.

2.

Acesso memria e especificao da largura dos operandos

Duas instrues permitem carregar um bloco de 16 bytes diretamente da memria para um registrador XMM:
movdqa

move double quadword aligned

movdqu

utilizada para acessos a blocos de 16 bytes alinhados em uma fronteira de 16 bytes


move double quadword unaligned
utilizada para acessos a blocos de 16 bytes sem qualquer alinhamento.

A largura de 16 bytes dos operandos pode ser especificada com xmmword ptr:
movdqu xmm0, xmmword ptr [esi+ecx*8-16]

Note-se, no exemplo acima, que foi utilizado um fator de escala 8 com o registrador ecx, o qual o
maior fator de escala suportado pelo Pentium. A utilizao de fatores de escala 16 no portanto
possvel, mas pode ser simulada alterando-se a forma de decremento/incremento do registrador.
Por exemplo, supondo que desejemos carregar sucessivamente 4 blocos contguos de 16 bytes
cada da memria para o registrador XMM0, partindo do ltimo bloco, utilizando o registrador ecx
como contador de blocos e o registrador esi apontando para o primeiro bloco. Nesse caso, supondo os blocos alinhados na fronteira de 16 bytes, teremos o seguinte fragmento de programa:

loop1:

mov ecx, 8
; ecx = nr. de blocos x 2
movdqa xmm0, xmmword ptr [esi+ecx*8-16] ; carrega o bloco
processa o bloco
sub ecx, 2

; ecx decr. de 2 em 2

jnz

; fica em loop at esgotar ecx

loop1

Note-se que a instruo PMADDWD, que pode ser utilizada com um operando sendo um registrador XMM e o outro um bloco de 16 bytes na memria, tambm requer alinhamento na fronteira
de 16 bytes, ainda que no explicitamente especificado no manual do Pentium.

3.

Alocao de memria alinhada

No existe uma API no Windows especfica para alocao de memria com um determinado ali-

Informaes sobre programao SSE2 Arq. e Org. Computadores - Prof. Gortan

fl. 1/2

nhamento. A API GlobalAlloc() garante alinhamento em fronteira de 8 bytes apenas. Como,


para operaes com SSE2, geralmente desejvel um alinhamento em fronteira de 16 bytes, esse
ajuste fica por conta do programador.
H duas possibilidades nesse caso: pode-se utilizar, quando vivel, a funo
_aligned_malloc(), da biblioteca de tempo de execuo da linguagem C (CRT- Library) , ou, sabendo-se que o bloco de memria retornado por GlobalAlloc() estar alinhado em uma fronteira de 8 bytes, pode-se alocar um bloco 8 bytes maior e forar o alinhamento tomando o incio
do bloco ou o incio deslocado de 8 bytes, conforme a necessidade, notando-se que o ponteiro s
estar alinhado em 16 bytes se seus 4 bits menos significativos forem nulos. importante atentar
para o detalhe que a liberao do bloco alocado, nesse caso com GlobalFree(), dever ser feita
com o ponteiro original retornado por GlobalAlloc() e no com o ponteiro deslocado. Por outro lado, se _aligned_maloc() for utilizado, ento a liberao dever ser feita com
_aligned_free(). O fragmento de programa a seguir exemplifica a possibilidade com
GlobalAlloc():

USHORT ptr,ptr1

; declara ponteiros para words

DWORD ptrMask = 0xf

; declara/inicializa mscara alinham.

ptr=(USHORT)GlobalAlloc(GPTR,size+8) ; size o tamanho desejado do bloco


ptr1 = ptr

; salva cpia para liberar no final

if(((DWORD)ptr)&ptrMask)

; se estiver desalinhado

{
ptr+=4

; avana ptr de 8 bytes (4 posies)

4.

Detalhes de aplicao Filtro FIR com nmero de taps no divisvel por 8

Na experincia 6 de laboratrio foi solicitado implementar a convoluo de um sinal com um filtro


pr-determinado, com 52 coeficientes (104 bytes). Como esse nmero de coeficientes no divisvel por 8, surge a pergunta de como fazer para processar 8 coeficientes (16 bytes) por vez com a
SSE2. Nesse caso a soluo estender a quantidade de taps para o inteiro mais prximo divisvel
por 8 (nesse caso 56), zerando todos os coeficientes adicionais (nesse caso 4). O acrscimo de 4 coeficientes nulos no altera o resultado da convoluo.
DWORD dwItems

; dwItems = nr. de taps do filtro

if(dwItems%8)

; se no divisvel por 8 (resto zero)

{
dwItems = ((dwItems/8)+1)*8

; arredonda para o prximo divisvel

O quadro acima ilustra uma forma simples de arredondar a quantidade de taps para o inteiro mais
prximo divisvel por 8.

Informaes sobre programao SSE2 Arq. e Org. Computadores - Prof. Gortan

fl. 2/2

Das könnte Ihnen auch gefallen