序
二つの数値を合成したい場合、たとえば、あるワードサイズの変数の上位バイトと、他の変数の下位バイトを一つのワードサイズにまとめたい場合、以下のような処理をする。
|
w = (w0 & 0xff00) | (w1 & 0x00ff); dw = (dw0 & 0xff00ff00) | (dw1 & 0x00ff00ff); |
また、ゲームなどで使われる、背景とその上に重ねられる画像の合成では、以下のような処理を見かける。
// C
キャラクターのピクセルデータ |
最適化
これらの演算はどちらも、(C & M) | (B & ~M) = ((C ^ B) & M) ^ B と最適化できる。Cライクに書けば、以下のようになる。
| w = w0 ^ w1; w &= 0x00ff; w ^= w0; dw = dw0 ^ dw1; |
| D = C ^ B; D &= M; D ^= B; |
このようにすることで、マスクパターンを減らし、余分な演算をなくすことができる。
証明
|
(C & M) | (B & ~M) |
= (C & M) ^ (B & ~M) |
| = (C & M) ^ (B & M) ^ B | |
| 分配法則、A & (B ^ C) = (A & B) ^ (A & C)より、 | |
| = ((C ^ B) & M) ^ B |
証明終わり。
余談
MMXテクノロジ命令ではサチュレーション付き減算ができるため、以下のようなマスク処理も可能である。
//
マスク用にレジスタを余分に使ってしまう例
|
//
マスク用レジスタを最小限にしたコード
|
MMXテクノロジ命令を使ったコーディングでは、カラーキーの処理をするときなどにpcmpeqwなどで動的にマスクを生成することもあるが、そのときにもこのテクニックは役に立つ。
数少ないMMXレジスタは、少しでも有効に使いたいものです。