Combinando prefixos em SSE
Pergunta
No SSE os prefixos 066h
(substituição do tamanho do operando) 0F2H
(REPNE) e 0F3h
(REPE) fazem parte do opcode.
Em não-SSE 066h
alterna entre operação de 32 bits (ou 64 bits) e 16 bits. 0F2h
e 0F3h
são usados para operações de string.Eles podem ser combinados para que 066h
e 0F2h
(ou 0F3h
) pode ser usado na mesma instrução, porque isso é significativo.Qual é o comportamento em uma instrução SSE?Por exemplo, temos (ignorando mod/rm por enquanto):
0f 58
--> addps
66 0f 58
--> addpd
f2 0f 58
--> addsd
f3 0f 58
--> addss
Mas o que é isso?
66 f2 0f 58
E que tal?
f2 66 0f 58
Sem mencionar o seguinte, que possui dois prefixos REP conflitantes:
f2 f3 0f 58
Qual é a especificação para estes?
Solução
Não me lembro de ter visto nenhuma especificação sobre o que você deveria esperar no caso de combinação descontrolada de prefixos aleatórios, então acho que o comportamento da CPU pode ser "indefinido" e possivelmente específico da CPU.(Claramente, algumas coisas são especificadas, por ex.Documentos da Intel, mas muitos casos não são cobertos).E algumas combinações podem ser reservadas para uso futuro.
Minhas suposições ingênuas geralmente seriam de que prefixos adicionais não funcionariam, mas não há garantia.Isso parece razoável, dado que, e.alguns manuais de otimização recomendam multi-byte NOP
(canonicamente 90h
) prefixando com 66h
, por exemplo.:
db 66h, 90h; 2-byte NOP
db 66h, 66h, 90h; 3-byte NOP
db 66h, 66h, 66h, 90h; 4-byte NOP
Contudo, também sei que CS
e DS
prefixos de substituição de segmento adquiriram novas funções como prefixos de dica de ramificação SSE2 (prever ramificação tomada = 3Eh
= DS
sobrepor;prever ramo não tomado = 2Eh
= CS
override) quando aplicado a instruções de salto condicional.
Enfim, olhei seus exemplos acima, sempre definindo XMM1
para todos 0
e XMM7
para todos 0FFh
por
pxor xmm1, xmm1 ; xmm1 <- 0s
pcmpeqw xmm7, xmm7 ; xmm7 <- FFs
e então o código em questão, com xmm1, xmm7
argumentos.O que observei (código de 32 bits no sistema Win64 e Intel T7300 Core 2 Duo) foi:
1) nenhuma mudança observada para addsd
adicionando 66h
prefixo
db 66h
addsd xmm1, xmm7 ;total sequence = 66 F2 0F 58 CF
2) nenhuma mudança observada para addss
adicionando 0F2h
prefixo
db 0f2h
addss xmm1,xmm7 ;total sequence = F2 F3 0F 58 CF
3) Porém, observei uma mudança ao prefixar addpd
por 0F2h
:
db 0f2h
addpd xmm1, xmm7 ;total sequence = F2 66 0F 58 CF
Neste caso, o resultado em XMM1 foi 0000000000000000FFFFFFFFFFFFFFFFh
em vez de FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFh
.
Então minha conclusão é que não se deve fazer suposições e esperar um comportamento "indefinido".Eu não ficaria surpreso, entretanto, se você pudesse encontrar algumas pistas no nevoeiro de Agner. manuais.