10.ビット操作と論理演算

CPU命令の解説の最後はビット操作と論理演算(AND、OR、XOR)です。ビット操作は、とてもアセンブラーっぽいプログラミング技法です。1バイトあれば8つの情報を持てますし、使いこなせるとプログラムはとてもスマートになります。

ビット操作の命令

TM(Test under Mask)

第2オペランドで指定した主記憶の1バイトが、第1オペランドで指定されたビットパターン(マスクビット)でテストされます。マスク中のビットが0の場合、対応する主記憶側のビットはテストされません。マスクがx80であれば先頭ビットのON/OFFがテストされ、xFFであれば全てのビットのON/OFFがテストされます。主記憶の内容は変わりません。

テストの結果、PSWに条件コードがセットされます。

0 … 選択されたビットはすべて0、またはマスクビットが0
1 … 選択されたビットは0と1が混在している
2 … 使用されない
3 … 選択されたビットはすべて1

TM命令はOSの出口ルーチン等のシステム系プログラムを作る場合、比較的使用頻度の高い命令です。誤りやすいのはTM命令自体ではなく、その後の分岐命令でのマスクビットの指定等の条件指定です。特に、複数のビットをテストする場合などに間違えやすいです。BNOとBZ、BOとBNZを混同しないように注意します。

SLL、SRL(Shift Left|Right single Logical)

第1オペランドで指定したレジスター内の各ビットが、第2オペランドで指定した数だけSLL命令では左へ、SRL命令では右にシフトします。r2レジスターを0にした場合はオペランドに指定した数はシフト数そのものになります。例えば、SLL R1,8(R0)はSLL R1,8と同じで、この場合の数字の8は変位8と見なされシフト数として扱われます。0以外のレジスターを指定した場合は、そのレジスターにシフトする数を格納しておきます。同時に変位も指定すればその値もシフト数に加算されます。第1オペランド側レジスターの左端(ビット0)あるいは右端(ビット31)にあるビットはシフトの度にこぼれ落ちます。

シフト動作によって空いたビット位置には0がセットされます。条件コードはセットされません。
SLL,SRLは論理シフト(レジスター内の全ビットが操作対象になる)動作です。符号ビットはずらされない算術シフト命令もあります。
なお、左へシフトすることは2のn乗を掛け算することと同じです。右へシフトすることは2のn乗で割り算することと同じです。乗除数が2のべき乗である時は乗除算命令の代わりにシフト命令を使うと計算が簡単です。

SLDL、SRDL(Shift Left|Right Double Logical)

第1オペランドには、乗除算命令同様に偶数・奇数番号の対になったレジスターを指定します。それ以外はSLL、SRL命令と同じです。
シフト動作は対になった2つのレジスターのすべてのビット(64ビット)について行われます。奇数番号レジスターの左端ビットは、偶数番号レジスターの右端ビットに移ります。偶数番号レジスターの左端ビットと奇数番号レジスターの右端ビットはこぼれ落ちます。

S/370のシフト命令ではインテルCPUのようなキャリーフラグが使えません。シフトしてドロップしたビットが0か1かを調べるには、SLDL又はSRDL命令で隣のレジスターにビットをこぼしてその値をテストするような事が行われます。

論理演算命令(And、Or、Exclusive Or)

OR、OI、O、OC

いずれの命令も「OR」(論理和)を取ります。第1オペランドと第2オペランドで示す値の論理和が、第1オペランドで示すレジスターあるいは主記憶に格納されます。第2オペランドの内容は変更されません。命令の構文はすでに出てきた同形式の命令と同じです。ORはARやSRと、OIはMVIと、OCはMVCの各命令と同じ構文を持ちます。それぞれRR形式、SI形式及びSS形式の命令です。

NR、NI、N、NC

いずれの命令も「AND」(論理積)を取ります。第1オペランドと第2オペランドで示す値の論理積が、第1オペランドで示すレジスターあるいは主記憶に格納されます。第2オペランドの内容は変更されません。

XR、XI、X、XC

いずれの命令も「eXclusive OR」(排他的論理和)を取ります。第1オペランドと第2オペランドで示す値の排他的論理和が、第1オペランドで示すレジスターあるいは主記憶に格納されます。第2オペランドの内容は変更されません。

論理演算命令は条件コードがセットされます。OR、AND及びXORとも同じです。

0 … 結果がゼロ(すべてのビットが0になった)
1 … 結果がゼロでない(0でないビットが少なくとも1つはある)
2 … 使用されない
3 … 使用されない

上記サンプルのように、1バイトの領域に異なる意味を持つビットを割り当てて、そのONかOFFの状態でプログラムの実行を制御する手法はシステム系プログラム(制御系プログラム)では非常によく使われます。それぞれのビットはフラグと呼ばれ、YES又はNOのスイッチの意味を持たせます。フラグビットを格納する領域がフラグバイトです。2ビット使って4種類の意味を持たせることもあります。1バイトのフラグバイトには8つのフラグビットを持てますから、YESかNOかの情報なら8種類持てるわけです。必要ならフラグバイトを延ばし、2バイトで16種類、3バイトで24種類と拡張できます。
フラグビットを1にするにはOR、0にするにはAND、反転ならXOR命令が使えます。OI、NI命令によるフラグ操作がポピュラーです。ORはそのままフラグビットを指定すればいいので簡単ですが、ANDはサンプルのように255から引き算した結果で行うことを知っておいて下さい。フラグビット値をそのまま指定すると他のビットをすべて落としてしまいます。MVS自身もこのようなフラグを多用してOSとしての制御を行っています。