演算命令
汎用レジスタと汎用レジスタまたは16bitの数値(即値)間で演算し、その結果を汎用レジスタに格納します。直接、メモリの内容を演算に使用することはできず、レジスタに転送してから演算する必要があります。
加減算命令
単純な加算、減算を行う命令です。ただし減算の場合は右辺の順序が逆になっている事に注意してください。通常の減算は拡張ニーモニックを使います。
add r3, r4, r5 # r3 = r4 + r5
subf r3, r4, r5 # r3 = r5 - r4
レジスタ間の減算は 「subf r3, r5, r4」とすることで「r3 = r4 - r5」のように表現できます。指定した数値(即値)を加減算する場合は、符号付16ビット整数(-32768から+32767)の範囲が可能です。
addi r3, r4, 12345 # r3 = r4 + 12345
subfi r3, r4, 12345 # r3 = 12345 - r4
「r3 = r4 - 12345」のように即値を減算する場合は、「addi r3, r4, -12345」のように負の値を加算します。
オペランド(引数)が3つあるため、結果を代入するレジスタは右辺のレジスタとは別のレジスタを使用できるため、計算に用いる右辺のレジスタの内容は変化しません。
加減算命令の種類
| 加算 | 逆減算 | 意味 | |
|---|---|---|---|
| add[o][.] | subf[o][.] | 加算または逆減算 | |
| addc[o][.] | subfc[o][.] | Carrying | キャリーフラグを更新 |
| adde[o][.] | subfe[o][.] | Extended | キャリーフラグも加算 |
| addi | Immediate | 符号付16ビット数値を直接指定(即値) | |
| addic | subfic | Immediate Carrying | 符号付16ビット数値を直接指定、キャリーフラグも更新 |
| addic. | Immediate Carrying and record | 同上、+条件レジスタを更新 | |
| addis | Immediate Shifted | 符号付16ビット数値を16ビット左シフトした値と加算 | |
| addme[o][.] | subfme[o][.] | Minus One Extended | |
| addze[o][.] | subfze[o][.] | Zero Extended | キャリーのみ加減算 |
上の表で [o] となっているところは、例えば 「addo」「addco」などのように命令(オペコード)に追加することができ、オーバーフローが発生した場合にオーバーフローフラグ(XER[OV])に反映します。 [.](ピリオド)を付加した場合は、演算結果にしたがって条件レジスタ(cr0)を更新します。
add命令のバリエーションの例とその動作の簡単な説明です。
add r3, r4, r5 # r3 = r4 + r5
add. r3, r4, r5 # r3 = r4 + r5, cr0 を更新
addc r3, r4, r5 # r3 = r4 + r5, XER[CA] を更新
addc. r3, r4, r5 # r3 = r4 + r5, cr0 と XER[CA] を更新
addco r3, r4, r5 # r3 = r4 + r5, XER[CA,OV,SO] を更新
adde r3, r4, r5 # r3 = r4 + r5 + carry
addi r3, r4, S16 # r3 = r4 + S16
addic r3, r4, S16 # r3 = r4 + S16
addis r3, r4, r5 # r3 = r4 + S16<<16
addme r3, r4 # r3 = r4 + carry - 1
addze r3, r4 # r3 = r4 + carry
- S16は符号付16ビット整数です。
- carry は整数例外レジスタのCAビット(XER[CA])を示します。
- cr0は条件レジスタの第0-3ビットを示します。
拡張ニーモニック
減算
PowerPCが減算命令を持たないため、加算または逆減算命令で実現します。
| 拡張ニーモニック | 標準ニーモニック | ニーモニックの意味 |
|---|---|---|
| sub rD,rA,rB | subf rD,rB,rA | Subtract from |
| subc rD,rA,rB | subfc rD,rB,rA | Subtract from carrying |
| subi rD,rA,S16 | addi rD,rA,-S16 | Subtract immediate |
| subic rD,rA,S16 | addic rD,rA,-S16 | Subtract immediate carrying |
| subic. rD,rA,S16 | addic. rD,rA,-S16 | Subtract immediate carrying |
| subis rD,rA,S16 | addis rD,rA,-S16 | Subtract immediate signed |
数値の代入
レジスタに数値を代入する li は非常によく使う命令です。「addi」を使って実現します。第2オペランドの「r0」は数値の「0」と解釈されるため、結果的に16ビットの符号付整数の代入となります。
| 拡張ニーモニック | 標準ニーモニック | ニーモニックの意味 |
|---|---|---|
| li rD,S16 | addi rD,r0,S16 | Load Immediate |
| lis rD,S16 | addis rD,r0,S16 | Load Immediate Shifted |
レジスタに32ビットのアドレスや数値を代入するには、次のように2つの命令を組み合わせて使います。
たとえば r3 レジスタに代入する場合、上位16ビットは
| lis r3,0,symbol@ha |
のように記述できます。@ha はシンボルの上位16ビットを取得する演算子です。
下位16ビットは、
| addi r3,r3,symbol@l |
とします。@l でシンボルの下位16ビットが得られます。符号拡張 (下位16ビットの最上位ビットが1の場合は、上位16ビットにも1を補う)が発生しても補正されます。
論理演算命令
32ビット整数の対応するビットを論理演算する命令です。
| 論理積 | 論理和 | 排他的論理和 | 意味 |
|---|---|---|---|
| and[.] | or[.] | xor[.] | レジスタ間の演算 |
| andc[.] | orc[.] | ビット反転した後に演算 | |
| andi. | ori | xori | 直接数値指定(即値)との演算 |
| andis. | oris | xoris | 16bit左シフトした即値との演算 |
and命令のバリエーションの例とその動作の簡単な説明です。
and r3, r4, r5 # r3 = r4 and r5
andc r3, r4, r5 # r3 = r4 and not(r5)
andi r3, r4, S16 # r3 = r4 and S16
andis r3, r4, S16 # r3 = r4 and S16<<16
and、or、xorの結果をビット反転する命令も用意されています。neg命令は2の補数 (正負反転)を求める命令です。単にビット反転するには nor 命令を使用します (拡張ニーモニックで用意されています)。
| 命令 | 例 | 意味 |
|---|---|---|
| eqv[.] | eqv r3, r4, r5 | r3 = not(r4 xor r5) |
| nand[.] | nand r3, r4, r5 | r3 = not(r4 and r5) |
| nor[.] | nor r3, r4, r5 | r3 = not(r4 or r5) |
| neg[o][.] | neg r3, r4 | r3 = not(r4) + 1 |
eqv r3, r4, r5 # r3 = not (r4 xor r5)
nand r3, r4, r5 # r3 = not (r4 and r5)
nor r3, r4, r5 # r3 = not (r4 or r5)
neg r3, r4 # r3 = not(r4) + 1
2の補数を求めるneg命令は 0x8000000 のとき 0x8000000 を返します。 0x8000000の2の補数は32ビットに収まらないためです。
次は 0 または 1 で6種類の論理演算を行って得られる値を表にしたものです。
| ?は演算子 | and | or | xor | eqv | nand | nor |
|---|---|---|---|---|---|---|
| 0 ? 0 | 0 | 0 | 0 | 1 | 1 | 1 |
| 0 ? 1 | 0 | 1 | 1 | 0 | 1 | 0 |
| 1 ? 0 | 0 | 1 | 1 | 0 | 1 | 0 |
| 1 ? 1 | 1 | 1 | 0 | 1 | 0 | 0 |
PowerPCで実際に論理演算を行った結果です。 r4 と r9 (またはr7) レジスタの間で演算して、r10 に結果が代入された場合の各レジスタの値を示しています。レジスタの値は2進数と16進数で表示しています。上の表と見比べてください。
and r10, r4, r9 r4: 00110011001100110011001100110011 33333333 r9: 01010101010101010101010101010101 55555555 r10: 00010001000100010001000100010001 11111111 or r10, r4, r9 r4: 00110011001100110011001100110011 33333333 r9: 01010101010101010101010101010101 55555555 r10: 01110111011101110111011101110111 77777777 xor r10, r4, r9 r4: 00110011001100110011001100110011 33333333 r9: 01010101010101010101010101010101 55555555 r10: 01100110011001100110011001100110 66666666 eqv r10, r4, r9 r4: 00110011001100110011001100110011 33333333 r9: 01010101010101010101010101010101 55555555 r10: 10011001100110011001100110011001 99999999 nand r10, r4, r9 r4: 00110011001100110011001100110011 33333333 r9: 01010101010101010101010101010101 55555555 r10: 11101110111011101110111011101110 EEEEEEEE nor r10, r4, r9 r4: 00110011001100110011001100110011 33333333 r9: 01010101010101010101010101010101 55555555 r10: 10001000100010001000100010001000 88888888 andc r10, r4, r7 r4: 00110011001100110011001100110011 33333333 r7: 11111111111111111111111111111111 FFFFFFFF r10: 00000000000000000000000000000000 00000000 orc r10, r4, r7 r4: 00110011001100110011001100110011 33333333 r7: 11111111111111111111111111111111 FFFFFFFF r10: 00110011001100110011001100110011 33333333
拡張ニーモニック
レジスタのコピー、NOP、NOTは論理演算を使って実現します。レジスタのコピーをする mr は、良く使われる命令ですから覚えておきましょう。
| 拡張ニーモニック | 標準ニーモニック | ニーモニックの意味 | 説明 |
|---|---|---|---|
| nop | ori r0,r0,0 | No OPeration | 何もしない |
| not rD,rS | nor rD,rS,rS | NOT | 1の補数(ビット反転) |
| mr rD,rS | add rD,r0,rS | Move Register | レジスタのコピー |
乗除算命令
整数間の乗算と除算の命令です。結果が32ビットを超える場合には、整数例外レジスタのオーバーフローフラグ(XER[OV])に反映されます。
乗算
乗算には4種類の命令があります。32bitの数値の乗算によって64bitの数値が得られるため、64bitの数値が必要な場合は、乗算を2度に分けて実行する必要があります。
mullw によって乗算結果の下位32bitを求めることができます。乗算の結果として求められる下位32bitは数値が符号付、符号無しで変化しないため、下位32bitを求める乗算命令は1つです。
一方、上位32bitを求める乗算命令は2種類あり、「mulhw」は符号付乗算、「mulhwu」は符号無し乗算の上位32bitを求めます。
「mulli」は命令中に埋め込まれた16bitの符号付整数を32bitに拡張した数値と指定したレジスタの数値を乗算します。乗算結果の下位32bitが指定したレジスタに返ります。
| 命令 | ニーモニックの意味 |
|---|---|
| mulhw[.] | MULtiply High Word |
| mulhwu[.] | MULtiply High Word Unsigned |
| mulli | MULtiply Low Immediate |
| mullw[o][.] | MULtiply Low Word |
除算
整数間で除算する命令です。
| 命令 | ニーモニックの意味 |
|---|---|
| divw[o][.] | DIVide Word |
| divwu[o][.] | DIVide Word Unsigned |
以下の例では、r4が被除数、r5が除数で r3 に商が返ります。除算命令では剰余は求めることができません。
divw r3, r4, r5 # r3 = r4 / r5
被除数、除数、商、剰余の符号の関係は次のようになります。
被除数 = 商 * 除数 + 剰余
被除数が正の場合は、剰余は0か正
被除数が負の場合は、剰余は0か負
剰余を求める
除算命令では剰余は求めることができないため、次のようにして求めます。
符号付除算
次の例は、符号付整数の除算の場合の r4/r5 の余りを r3 に代入します。
divw r3, r4, r5
mullw r3, r3, r5
subf r3, r3, r4
無符号除算
次の例は、符号無し整数の除算の場合の r4/r5 の余りを r3 に代入します。
divwu r3, r4, r5
mullw r3, r3, r5
subf r3, r3, r4