更新処理
普通に頭からビットを詰めていったら更新処理はこんな感じになります。
for (; count != 0; count -= 1) { <%= gen_update(0, 3, 4, 12, 12, "mask1") %> <%= gen_update(1, 4, 0, 12, 29, "mask2") %> <%= gen_update(2, 0, 1, 29, 29, "mask2") %> <%= gen_update(3, 1, 2, 29, 29, "mask2") %> <%= gen_update(4, 2, 3, 29, 29, "mask2", "mask3") %> }
例えば mt_bs[i][0] を更新するときは 396から523番目の入ったqwordとXORしないといけません。
これらはmt_bs[i][3]とmt_bs[i][4]にまたがっていて、前者からの116ビットと後者から12ビットを
くっつけて128ビットを作らないといけません。
こういうときはrlqwとselbを使います。rlqwを使うと、回転した後の値を次の行の更新で使うことができます。
このインデックスと回転ビット数とselbのマスクを引数にしてコードを生成します。
回転ビット数とその回数を調べてみると、
ビット数 | 回数 | 一回当たりの命令数 |
1 | 5 | 1 |
12 | 64 | 2 |
29 | 128 | 2 |
となります。見れば分かるように一番多い29ビット回転に2命令かかるのは無駄です。
というわけで、29ビット回転を1命令でやります。
最初から0ビット目の隣に29ビット目、その隣に58ビット目、その隣に87ビット目……というように並べておけば、
1ビット回転しただけで29ビット回転したことになります。
これは29と128が互いに素だからできるわけで、128と互いに素な全ての数、ようするに128までの奇数に対して、
同じように並べ替えてみて、29ビット回転と12ビット回転がどのように変化していくか調べてみました。
結局、使えそうなのは29ごとに並べて
元 | 1 | 12 | 29 |
新(左回転) | 75 | -4 | 1 |
になる場合と、99ごとに並べて
元 | 1 | 12 | 29 |
新(左回転) | -75 | 4 | -1 |
だけになりました。
上を採用すると、29ビット回転が1命令になりそのほかは2命令になります。