作業しようと思って会社来たが作業する気が起きなくて調べものしてた。
http://www.brightsideofnews.com/news/2012/7/13/xeon-phi-lacks-binary-compatibility2c-breaks-amd64-conventions.aspx
なんでMICってABI互換無くす必要があるんだっけ…とか調べてたがよくわからんかった。
まあ副産物としてMVEXについて調べたので適当にまとめておく。
作業しようと思って会社来たが作業する気が起きなくて調べものしてた。
http://www.brightsideofnews.com/news/2012/7/13/xeon-phi-lacks-binary-compatibility2c-breaks-amd64-conventions.aspx
なんでMICってABI互換無くす必要があるんだっけ…とか調べてたがよくわからんかった。
まあ副産物としてMVEXについて調べたので適当にまとめておく。
REX/VEXエンコーディングによって16本のレジスタをx86命令中にエンコードすることに成功したAMD/Intelであったが、MICではzmmレジスタは32個あって困るのだった。
ModR/M,REX, VEX そして MVEXまで、またそのうち調べる気がするのでメモ。というかModR/Mとか、多分メモするの3回目くらいだがメモの意味とは…
x86命令はレジスタだけでなくメモリをオペランドに取れる。オペランドの種類が、命令の次に続くModR/Mというバイトにエンコードしてある。8bitのうち、2bitで種類を、3bit x 2 で、8本のレジスタのdst/srcのペアを指定する(この解説はかなり正しくないので、真面目にやる場合はIntel Manual 2Aの最初を見たほうがいい)
Mod | Reg | R/M | |||||
オペランド種類 | レジスタ3bit | レジスタ3bit | |||||
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
64bit拡張するついでにレジスタも増やそうぜと思ったAMDは、いくつかのどうでもいい命令を無効命令にして、それのうち2個の命令をREX prefixとした。INC/DECは犠牲になったのだ…
$ cat fmt.s inc %edx dec %edx $ as -o fmt.o -32 fmt.s $ objdump -d fmt.o fmt.o: ファイル形式 elf32-i386 セクション .text の逆アセンブル: 00000000 <.text>: 0: 42 inc %edx 1: 4a dec %edx $ as -o fmt.o -64 fmt.s $ objdump -d fmt.o fmt.o: ファイル形式 elf64-x86-64 セクション .text の逆アセンブル: 0000000000000000 <.text>: 0: ff c2 inc %edx 2: ff ca dec %edx }
INC/DECは、オペコードの中にレジスタを含めることができ、実際には、
という8x2個の合計16個の命令があると言ったほうがいい。これが無くなったことで、x86-64では、4bit分自由に使えるビットが増えた。REX prefixは、この4bitを使って
のふたつを行なった。
4bit それぞれに、W/R/X/Bという名前が付いていて、
で、
0: 44 01 04 00 add %r8d,(%rax,%rax,1) # WRXB = 0100 = 0x44 4: 4c 01 04 00 add %r8,(%rax,%rax,1) # WRXB = 1100 = 0x4c 8: 41 01 04 00 add %eax,(%r8,%rax,1) # WRXB = 0001 = 0x41 c: 43 01 04 00 add %eax,(%r8,%r8,1) # WRXB = 0011 = 0x43
こんな感じになる。
これを見てIntelの人は、「お前また prefix 増やしたのかよクソが」とか思った…か、どうかは知らないが、(というかIntelが増やしたほうが多いが)
66 44 0f 38 00 3c 00 pshufb (%rax,%rax,1),%xmm15 ^ ^ ^ ^ ^ ^ ^ | | | | | | SIB | | | | | ModR/M | | | | opcode +--+--+--+ prefix
もはやプリフィクスのほうが命令より長いという状態になりつつあった。
あと、長いだけでなく、依存の長さも問題になる。上の7byteのうち、
5byteが命令長に影響を与えるという状態だった。こんなのを4並列同時デコードしてるのが今のx86である。
このプレフィクスをまとめようと努力した結果がVEX prefixなのだった。あと3オペランドになる。
66 44 0f 38 00 3c 00 pshufb (%rax,%rax,1),%xmm15 c4 62 01 00 3c 00 vpshufb (%rax,%rax,1),%xmm15,%xmm15
32bitでも実現できるようにするためだと思うが、REX prefixと違って、VEX prefixは、既存の命令を破壊していない。
Q. すでに1byte命令空間は全て埋まっているCPUがあります。これに1byte prefixを増やすにはどうすればよいでしょう?
A. よく見るとビットが余ってるしそれ使えばいい。
LES/LDS という命令があって、レジスタ間接アドレシングしてロードする命令なのだが、これは、レジスタをオペランドにとれない
lds 0, %eax # 有効 lds (%ecx), %eax # 有効 lds %ecx, %eax # 無効
つまり、ModR/MのModには、レジスタオペランド(11)が指定されることは無い。VEX prefixはそこを突いた。
VEX prefixの2byte目のこの上位2bitは、既存の命令とかぶらないように設計されてて、
32bitモードだと、レジスタが8本しかないので、REXのR,Xは意味が無い。つまり、常に0。そして、VEXのWRXBは反転した値が入ってる。つまり、32bitモードでは、常に、この部分が11になり、64bitモードでは、LES/LDS命令は未定義なので、このビットを自由に使って16本のレジスタを指定できる。
と、なっている。
まあ、そういう努力によって、1byteのプレフィクスを増やして、x86はREXのWRXBを含めて16bit使えるビットを手に入れた。
この16bitのうちわけは、
となる。これによって、REX prefixの機能に加えて、
を実現した。
Larrabee とか KNC とか Knights Corner とか MIC とか Xeon Phi とか k1om とか呼ばれるものがあった。俺の名前はいっぱいあってな…
これ用にもっと拡張したくなったのか、MVEXというprefixが増えた。今回犠牲になったのは、bound命令である。bound命令は、配列境界を超えてないかどうかをチェックする命令である。「Java用に、配列チェックする命令があればいいんではないか」とか考える人は、x86を使うべきである。
bound命令もLES/LDSと一緒でメモリしかオペランドにとらないので、VEXと同じような形で利用されることになった。MVEXは、VEXよりもさらに1byte多い(1+3=4byte)。つまり8bit自由に使える。
詳細は、
http://software.intel.com/en-us/forums/topic/278102
の Instruction Set Reference Manual にある。KNC_goldとか書いてあるやつを展開して中のRPM入れればk1om用のbinutilsが使える。
8bitのうちわけは、
レジスタを32本にするため、最初の2byteもVEXから少し変更が入っている。
これによって、
を実現している。