La combinación de prefijos en SSE
Pregunta
En SSE la 066h
prefijos (operando override tamaño) 0F2H
(REPNE) y 0F3h
(REPE) son parte del código de operación.
En interruptores 066h
no SSE entre 32 bits (o 64 bits) y la operación de 16 bits. 0F2h
y 0F3h
se utilizan para operaciones de cadenas. Se pueden combinar de modo que 066h
y 0F2h
(o 0F3h
) se pueden utilizar en la misma instrucción, porque esto es significativo. ¿Cuál es el comportamiento de una instrucción SSE? Por ejemplo, hemos (ignorando mod / rm por ahora):
0f 58
-> addps
66 0f 58
-> addpd
f2 0f 58
-> addsd
f3 0f 58
-> addss
Pero ¿qué es esto?
66 f2 0f 58
Y ¿qué tal?
f2 66 0f 58
Por no mencionar lo siguiente, que tiene dos prefijos REP en conflicto:
f2 f3 0f 58
¿Cuál es la especificación de estos?
Solución
No recuerdo haber visto ninguna especificación sobre lo que debe esperar en el caso de la combinación de prefijos violentamente al azar, así que supongo que el comportamiento de la CPU puede ser "indefinido" y posiblemente específico de la CPU. (Es evidente que algunas cosas se especificarán en documentos de Intel, por ejemplo, pero muchos casos no están cubiertos). Y algunas combinaciones pueden ser reservados para uso futuro.
Mis supuestos ingenuos en general, habría sido que los prefijos adicionales serían no-ops, pero no hay garantía. Eso parece razonable que, por ejemplo, GIVEN algunos manuales recomiendan optimizando NOP
de varios bytes (canónicamente 90h
) prefijando 66h
, por ejemplo:.
db 66h, 90h; 2-byte NOP
db 66h, 66h, 90h; 3-byte NOP
db 66h, 66h, 66h, 90h; 4-byte NOP
Sin embargo, también sé que prefijos CS
y el segmento DS
de anulación han adquirido nuevos funciona como SSE2 prefijos de sugerencia rama (predecir rama tomado = 3Eh
= DS
anular; predecir rama no tomada = 2Eh
= CS
override) cuando se aplica a las instrucciones de salto condicional .
De todos modos, miré sus ejemplos anteriores, siempre ha marcado a todos XMM1
0
y XMM7
a todos 0FFh
por
pxor xmm1, xmm1 ; xmm1 <- 0s
pcmpeqw xmm7, xmm7 ; xmm7 <- FFs
y luego el código en cuestión, con argumentos xmm1, xmm7
. Lo que he observado (código de 32 bits en un sistema Win64 e Intel T7300 Core 2 Duo) era:
1) ningún cambio observado para addsd
mediante la adición de prefijo 66h
db 66h
addsd xmm1, xmm7 ;total sequence = 66 F2 0F 58 CF
2) ningún cambio observado para addss
mediante la adición de prefijo 0F2h
db 0f2h
addss xmm1,xmm7 ;total sequence = F2 F3 0F 58 CF
3) Sin embargo, he observado un cambio prefijando addpd
por 0F2h
:
db 0f2h
addpd xmm1, xmm7 ;total sequence = F2 66 0F 58 CF
En este caso, el resultado en XMM1 se 0000000000000000FFFFFFFFFFFFFFFFh
en lugar de FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFh
.
Entonces Mi conclusión es que no hay que hacer ninguna hipótesis y esperar un comportamiento "indefinido" . No me sorprende, sin embargo, si se pudiera encontrar algunas pistas en la niebla de Agner manuales .