SSEを用いたbsr/bsf命令の実現に向けて その3

さて、SSEでbsr/bsfを実現するためには、まず_mm_cvtepi32_ps(アセンブリ命令はCVTDQ2PS)という整数をfloatに変換する命令を使います。


というか、一昨日の記事のコメントで、すでにそのことは指摘されています

ktanaka 2011/09/16 11:29
CVTDQ2PSを使う方法でしょうか? unsigned intからfloatへの変換があれば扱いやすいのですが,なさそうですね.


「いきなり、そんな的確なコメントをするとは、お主、只者ではないな!特別にワシの弟子にして進ぜよう!」と江戸時代なら言っていたかも知れませんが、現代ではググれば一発…あっ。動物将棋を完全解析した東大の田中哲朗先生*1でした。――むしろ私が弟子にしていただきたく。



それはそうと、読者の方には、何故CVTDQ2PSでbsr/bsf相当の処理が実現出来るのかが今ひとつ見えないと思うので、以下にざっと書いていきます。


まず、次のようなマクロを用意します。

// integer→float変換
#define Bitboard_Cvt(b,b1)        (b).m0 = _mm_cvtepi32_ps( (b1).m )


float(単精度浮動小数)の表現形式は当然ながらIEEE754でしょうから、32bit floatなら最上位bitに符号が来て、そのあと8bitに指数部が来ます。「指数部」は「2の何乗したやつ?」ってことなので要するに変換前の整数の、1であった最上位のビットの位置が書かれています。


例えば変換前の値が16だとしたら…


16 = 2の4乗 = 4 に 0x7fのオフセットがかかった0x83が、この変換後の指数部に来ています。
0x7fはおまじないだと思ってください。詳しくはIEEE754の仕様書なりなんなりをご覧ください。


e.g.
変換前の数字が0→指数部0 , 変換前の数字が1→指数部0x7f , 変換前の数字が2→指数部0x80 , …


そこで、変換後のこの部分に0x81を加算してやれば、
変換前の数字が0→指数部0x81 , 変換前の数字が1 → 指数部0 , 変換前の数字が2 → 指数部1 , …


のようにbsrしたときの数字らしきものが指数部に得られることがわかります。


つづく