x86 (IA32) の命令は Prefix を追加し op code 長を増やすことで拡張されてきました。
SSE の命令は 2byte escape 0F + 1byte opcode の空間に割り当てられています。
例えば ADDPS は 0F 58 です。バリエーションであるスカラー ADDSS は Prefix と
して F3 が追加され、SSE2 の倍精度命令はさらに 66 と F2 も加わります。
ADDPS 0F 58 ~ ADDSS F3 0F 58 ~ ADDPD 66 0F 58 ~ ADDSD F2 0F 58 ~
x64 (AMD64/Intel64/EM64T) の拡張レジスタ xmm8~xmm15 にアクセスするには
上記にさらに REX Prefix が追加されます。
40~4F が REX Prefix で、4bit 分のオプション bit を持っています。
ADDPS 45 0F 58 ~ ADDSS F3 45 0F 58 ~ ADDPD 66 45 0F 58 ~ ADDSD F2 45 0F 58 ~
IA32 命令のレジスタフィールドは 3bit しかなく、レジスタ上限は 8個でした。
64bit モードでは REX Prefix 内の機能 bit を追加して、レジスタフィールドを
4bit とみなすことができます。
これで最大 16個のレジスタを指定可能です。
REX Prefix H---------------L [0|1|0|0|W|R|X|B]
REX.RXB の 3bit がレジスタ/Index フィールド拡張用です。
残り 1bit REX.W が 64bit オペランドサイズの指定に使われます。
SSE4.x ではさらに opcode が拡張されて 3byte escape の 0F 38 や 0F 3A で
始まるスペースが割り当てられています。(SSE5 は 0F 24)
// SSE4.1 DPPS 66 [REX] 0F 3A 40 ~ BLENDPS 66 [REX] 0F 3A 0C ~ EXTRACTPS 66 [REX] 0F 3A 17 ~ // SSE4.2 CRC32 F2 [REX] 0F 38 F0 ~
追加命令が増える度に命令は長くなる一方です。
AVX でも命令を区別するために、さらに VEX Prefix が定義されています。
今までの命令 Prefix と違うのは、最初から 2~3byte の長さを確保したことと、
その中に従来使われていた Prefix や opcode を組み込んでしまったことです。
例えば SSE 命令の前に付く 66/F2/F3 Prefix は無印を含めて 4通りしかありません。
これは 2bit にエンコードできます。
最初から REX も opcode の機能 bit に組み込んでしまえば 8bit フルに割り
当てる必要もなくなります。
必ず 0F が含まれるとわかっているなら、これを命令から取り除くことが可能です。
2byte-VEX (C5+1byte) H---C5---L H---------------L [11000101] [R|V|V|V|V|L|P|P] 3byte-VEX (C4+2byte) H---C4---L H---------------L H---------------L [11000100] [R|X|B|M|M|M|M|M] [W|V|V|V|V|L|P|P]
2bit の PP がまさに Prefix の有無を表しています。
0= なし
1= 66
2= F3
3= F2
L は 256bit (ymm) モードの指定です。0 なら 128bit (xmm)
R X B W は REX Prefix に含まれていた機能 bit です。
4bit の VVVV は追加のレジスタフィールドです。
AVX は 3オペランド命令で source/destination が分離されているので、増えた
レジスタオペランドの指定にここが使われます。
5bit の MMMMM は拡張命令用フィールドでその多くが予約されています。
現在定義されているのは次の 3パターンのみ。
1= 0F (2byte escape)
2= 0F 38 (3byte escape)
3= 0F 3A (3byte escape)
2byte-VEX には MMMMM は含まれていませんが、無条件で 0F とみなします。
これで上で紹介した多くの命令が VEX Prefix で置き換えられることがわかります。
VEX Prefix 以降の 1byte opcode や ModR/M 等のフィールドには互換性があります。
また MMMMM の多くが余っているので、例えば、まず無いとは思いますが
MMMMM: 4= 0F 24
と定義してしまえば AMD SSE5 の VEX 化も可能でしょう。
今後はおそらく命令が長くなることもなく ぐっすり眠れます。
Intel AVX は IA64 のような全く新しい互換性のない命令セットではなく、
x86 (IA32) の命令を圧縮してエンコードしたものです。
追加されたレジスタフィールド以外はこれまでの命令や prefix と同じもの。
従来の命令形式にデコード可能な互換性を保っています。
命令長は必ずしも短くなるわけではなく、ADDPS などは VEX 化することで 1byte
増えそうです。
ただし x64 拡張レジスタへアクセスする場合は長さは変わらず、source と
destination を別指定できるため場合によっては MOV 命令を減らすことができるでしょう。
関連エントリ
・Intel AVX その2 転送
・Intel AVX