これらの命令の説明はややこしく, なかなか覚えられないが, 今回のブログはその機能を覚えるためのものでもある.
MORはmultiple orのことで, 命令MOR $X, $Y, $Zは, 64ビットのレジスタ$Yと$Zのビットに演算を施し, レジスタ$Xに置くものである. TAOCP V1F1では,
m($X) ← m($Z)vxm($Y)
と説明する. レジスタ$Zと$Yの順が命令での順と逆なことに注意. この演算は, 64ビットレジスタをそれぞれ8ビットの行が縦に8行並んだ8 × 8の行列とみて, 2つの行列の乗算のような演算をするのである.
行列の乗算では, 積のi,j要素は, 被演算子の左の行列のi行と, 右の行列のj列の要素を次々と掛けて全体を足すのであった. それを2つの行列の間の演算+xで表わす.
今は要素は0か1である. それを次々と掛けて全体のor(v)を取るのである. MXOR命令は全体のxorを取る.
使い方の例として, TAOCPには
$Z = #0102040810204080
とすると, $Yのバイトの順が逆になるというのがある. つまり(abcdefgh)256が(hgfedcba)256になる. それを説明するのが, 次の図の上だ.
まず$Xの左上, X0,0は, $Zの0行目, 000...01と$Yの0列目のそれぞれを掛けるが, 1が最後にしかないので, ここに来るのはhのバイトの左端のビットである. その右隣りX0,1も, 同じ0行目と掛けるから, hのさっきのバイトの右隣りになる. 同様にした結果, $Xの0行目はhのバイトになる.
$Xの1行目は, $Zの1行目が000...10, つまり最後の1つ前にだけ1があるから, gの行が来る.
hの行が0行へ移った理由を再確認すると, Zの0行目の1が右端にあるからだ. つまり0行目へ置きたい$Yのバイトの位置を1にする. 赤矢印が0行目へ来るバイトの位置を示す.
そういう次第で, このパターンを使うと, $Yのバイトが逆転するのである.
下の図は左右逆転, つまりバイトの順は同じだが, バイトのビットを逆転する方法を示す. 上と同じで, $Xの0列目は, $Yの0列目の最後だけが1なので, hの各ビットが移動してきて, hになる. そして結局左からhgf...aと並ぶ.
ビット交換では, Yの0列の1の位置がXの0列に持ってきたいビットの位置である. (赤矢印)
これだけ分かると, V4F0にある完全シャッフルの問題(演習問題7.1.3-204)が解ける.
64ビットのレジスタzは
z = (x31...x1x0y31...y1y0)2
である. それを
w = (x31y31...x1y1x0y0)2
にしたい. ヒントがあって,
t = (x31x27x30x26x29x25x28x24y31y27y30y26y29y25y28y24...
x7x3x6x2x5x1x4x0y7y3y6y2y5y1y4y0)2
u = (y27y31y26y30y25y29y24y28x27x31x26x30x25x29x24x28...
y3y7y2y6y1y5y0y4x3x7x2x6x1x5x0x4)2
を中間結果とし, tとuを
MOR t,z,p; MOR t,q,t; MOR u,t,r; MOR u,r,u;
で作り,
PUT rM,m; MUX w,t,u;
とすると, 6命令で完全シャッフルが出来る. パターンp, q, r, mは何かという問題である.
このうちMUX命令は多重化マスクレジスタrMを見ながら, そのビットが1の所は$Yから, 0の所は$Zからデータを取る. PUT rM,mはパターンmをrMへ設定する命令だ. そうすると,
w31はx31にしたいからtから取る.
w30はy31にしたいからuから取る.
w29はx30にしたいからtから取る.
...
28まで行くと, 取るレジスタが交代する. 従って, 1010101001010101の繰り返しになるのだ. m = #aa55aa55aa55aa55
さて, zとtとの関係は, 次の図の上半分にある通り. バイトの交換とビットの交換をしている. 命令列の最初はMOR t,z,p;なので, $Zの方がパターンになり, バイトの交換だ. バイト位置の0,1,2,3,4,5,6,7に持ってきたいのは, それぞれ0,4,1,5,2,6,3,7だから, 下に示す行列のようになり, p = #8008400420021001でよかろう.
次の命令はパターンが$Yにあるから, ビット交換である. ビットの取り先は同じ関係だが, 縦と横が違うから転置のパターンにしなければならない.
q = #8020080240100401.
最後にtからuへの変換も, バイト交換とビット交換になっている. これはどちらも隣り同士の交換なので, パターンは同じである.
r = #4080102004080102.
TAOCPの演習問題には解答があるから覗いてみると, 正解であった.
0 件のコメント:
コメントを投稿