このページの目次

演算命令

汎用レジスタと汎用レジスタまたは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

拡張ニーモニック

減算

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