整数演算命令 整数演算の例

整数演算命令
z 加算命令(add instruction)
add $Ri, $Rj, $Rk
動作 : $Ri ← $Rj + $Rk
レジスタ$Rjと$Rkの値の和をRiに格納する
z 減算命令(subtract instruction)
sub $Ri, $Rj, $Rk
動作 : $Ri ← $Rj - $Rk
レジスタ$Rjと$Rkの値の差をRiに格納する
整数演算の例
z $s0 ← $s1 + $s2 + $s3
add $s0, $s1, $s2
add $s0, $s0, $s3
# $s0 ← $s1 + $s2
# $s0 ← $s0 + $s3
# 以降の文字列は コメント
z $s2 ← $s0 + 2×$s1
add $s2, $s0, $s1
add $s2, $s2, $s1
# $s2 ← $s0 + $s1
# $s2 ← $s2 + $s1 = $s0 + 2×$s1
($s1の2倍の計算は $s1+$s1 で求まる)
1
用語
z オペコード(operation code の略) : 命令コード
z オペランド(operand) : 演算対象(のデータ)
− ソース(source:元): 被演算対象となるデータ
− デスティネーション
(destination:目的): 演算結果のデータ
add $s0, $s1, $s2
# $s0←$s1+$s2
第2 ソースオペランド
第1ソースオペランド
デスティネーションオペランド
ソース
レジスタ
デスティネーション
レジスタ
オペコード
代入文
x = 2 * a + 4 * b - c のプログラム
(x, a, b, c は変数)
1
2
3
4
5
6
7
8
9
lw $s0, 0($gp)
add $s0, $s0, $s0
lw $s1, 4($gp)
add $t0, $s1, $s1
add $t0, $t0, $t0
add $t0, $s0, $t0
lw $s2, 8($gp)
sub $s3, $t0, $s2
sw $s3, 12($gp)
# $s0 ← a
# $s0 ← a+a
$gp
# $s1 ← b
# $t0 ← 2*b
# $t0 ← 4*b
# $t0 ←2*a+4*b
# $s2 ← c
# $s3 ← 2*a+4*b-c
# x ← $s3
2
a
b
c
x
加算命令の命令形式
add $s1,$s2,$s3
# $s1← $s2+$s3
第2ソースレジスタ(rt)
第1ソースレジスタ(rs)
デスティネーションレジスタ(rd)
オペコード(op)
functフィールド(6ビット)
命令の詳細機能を示す:
加算指定
opフィールド(6ビット)
命令の分類を表す:演算命令
op
rs
rt
rd
shamt
funct
000000 10010 10011 10001 00000 100000
31
26 25
21 20
16 15
11 10
0
6 5
rsフィールド(5ビット) rtフィールド(5ビット) rdフィールド(5ビット)
shamtフィールド(5ビット)
ソースレジスタを示す ソースレジスタを示す デスティネーションレジスタ シフト命令でシフト量を示す
$s2 (18)
$s3 (19)
を示す $s1 (17)
加算命令の場合は0
減算命令の命令形式
sub $s1,$s2,$s3
# $s1← $s2-$s3
第2ソースレジスタ(rt)
第1ソースレジスタ(rs)
デスティネーションレジスタ(rd)
functフィールド(6ビット)
命令の詳細機能を示す:
減算指定
opフィールド(6ビット)
命令の分類を表す:演算命令
op
rs
rt
rd
shamt
funct
000000 10010 10011 10001 00000 100010
31
26 25
21 20
16 15
11 10
6 5
0
rsフィールド(5ビット) rtフィールド(5ビット) rdフィールド(5ビット)
shamtフィールド(5ビット)
ソースレジスタを示す ソースレジスタを示す デスティネーションレジスタ シフト命令でシフト量を示す
$s2 (18)
$s3 (19)
を示す $s1 (17)
減算命令の場合も0
3
整数演算命令
z 即値加算命令(add immediate instruction)
addi $Ri, $Rj, C
動作 : $Ri ← $Rj + C
- レジスタ$Rjと即値(定数)Cの値の和をRiに格納する。
- 即値Cは16bitの2の補数表現のもとで -32768~
32767の範囲(-215~215-1)を指定できる。
- 定数の減算は C に負の値を使えばよい。
addi $s1, $s2, C
(rt) (rs)
op
# $s1← $s2 + C
rs
rt
imm
C
001000 10010 10001
31
26 25
21 20
16 15
0
整数演算命令の使い道
z レジスタのデータセット(16bitデータ,2の補数)
addi $Ri, $zero, 128
: $Ri ← 128
z レジスタ間のデータ移動(コピー)
add $Ri, $Rj, $zero
: $Ri ← $Rj + 0
z 符号反転
: $Ri ← -$Rj
sub $Ri, $zero, $Rj
z 定数の減算
addi $Ri, $Rj, -50
: $Ri ← $Rj -50
4
論理演算
z 論理積
0100 0110 1010 0110 1100 1100 1010 0101
& 0000 0000 0000 0000 1111 1111 1111 1111
0000 0000 0000 0000 1100 1100 1010 0101
z 論理和
0100 0110 1010 0110 1100 1100 1010 0101
| 0000 0000 0000 0000 1111 0000 1111 0000
0100 0110 1010 0110 1111 1100 1111 0101
z 排他的論理和
0100 0110 1010 0110 1100 1100 1010 0101
0000 0000 0000 0000 1111 0000 1111 0000
0100 0110 1010 0110 0011 1100 0101 0101
論理演算命令
z 論理積命令(and instruction)
and $Ri, $Rj, $Rk
動作 : $Ri ← $Rj & $Rk
- レジスタ$Rjと$Rkの論理積を$Riに格納する。
z 論理和命令(or instruction)
or $Ri, $Rj, $Rk
動作 : $Ri ← $Rj | $Rk
- レジスタ$Rjと$Rkの論理和を$Riに格納する。
z 排他的論理和命令(exclusive-or instruction)
xor $Ri, $Rj, $Rk
動作 : $Ri ← $Rj $Rk
- レジスタ$Rj と$Rkの排他的論理和を$Ri に格納する。
5
論理演算命令の命令形式
and $s1,$s2,$s3
(rd) (rs) (rt)
op
# $s1← $s2 & $s3
rs
rt
rd
shamt
funct
000000 10010 10011 10001 00000 011000
31
26 25
21 20
16 15
or $s1,$s2,$s3
op
0
6 5
11 10
# $s1← $s2 | $s3
rs
rt
rd
shamt
funct
000000 10010 10011 10001 00000 011001
31
26 25
21 20
16 15
xor $s1,$s2,$s3
op
6 5
11 10
0
# $s1← $s2 $s3
rs
rt
rd
shamt
funct
000000 10010 10011 10001 00000 011010
31
26 25
21 20
16 15
11 10
6 5
0
論理シフト演算
‹ 指定されたビット数,左あるいは右に論理シフトする
z 左論理シフト(shift left logical)
命令 : sll $Ri, $Rj, k
レジスタ$Rjの内容を k ビット左に論理シフトした値を$Riに格納する
z 右論理シフト(shift right logical)
命令 : srl $Ri, $Rj, k
レジスタ$Rjの内容を k ビット右に論理シフトした値を$Riに格納する
6
算術シフト演算
‹ 指定されたビット数,左あるいは右に算術シフトする
z MIPSでは左論理シフト命令はあるが,左算術シフト命令はない
(左シフトを行う場合は,左論理シフト命令を使う)
z 右算術シフト(shift right arithmetic)
はみ出したビットは捨てられ,空いた部分には符号ビットの値が入る
命令 : sra $Ri, $Rj, k
レジスタ$Rjの内容を k ビット右に算術シフトした値を$Riに格納する
左シフトと数値との関係
整数 100(100) の2進表現
0000 0000 0000 0000 0000 0000 0110 0100 = 100(10)
2 ビット左にシフト
0000 0000 0000 0000 0000 0001 1001 0000 = 400(10)
整数 -100(100) の2進表現
1111 1111 1111 1111 1111 1111 1001 1100 = -100(10)
2ビット左にシフト
1111 1111 1111 1111 1111 1110 0111 0000 = - 400(10)
n ビットの左シフト = 2n 倍
7
右算術シフトと数値との関係
整数 400(100) の2進表現
0000 0000 0000 0000 0000 0001 1001 0000 = 400(10)
2 ビット右に算術シフト
0000 0000 0000 0000 0000 0000 0110 0100 = 100(10)
整数 -400(100) の2進表現
1111 1111 1111 1111 1111 1110 0111 0000 = - 400(10)
2 ビット右にシフト
1111 1111 1111 1111 1111 1111 1001 1100 = -100(10)
n ビットの右算術シフト : 2-n 倍(2nでの割ったときの商)
rd
シフト命令の命令形式
rt
sll $s1, $s2, 3
op
# $s1← $s2 << 3
rs
rt
rd
shamt
funct
000000 00000 10010 10001 00011 000000
31
26 25
21 20
16 15
0
6 5
11 10
シフト量はshamt
(shift amount)
フィールドで指定
※ rs フィールドは使われないので何でもよい。ここでは 00000 としてある。
srl $s1,$s2, 8
op
rs
# $s1← $s2 >> 8
rt
rd
shamt
funct
000000 00000 10010 10001 01000 000010
31
26 25
21 20
16 15
# $s1← $s2 >> 4 (算術シフト)
sra $s1,$s2, 4
op
rs
0
6 5
11 10
rt
rd
shamt
funct
000000 00000 10010 10001 00100 000011
31
26 25
21 20
16 15
6 5
11 10
8
0
代入文 x = 10 * a のプログラム
(シフト命令使用)
1
2
3
4
5
lw $s0, 0($gp)
sll $t0, $s0, 2
add $t0, $t0, $s0
sll $s1, $t0, 1
sw $s1, 4($gp)
# $s0 ← a
# $t0 ← 4*a
$gp
# $t0 ← 5*a
# $s1 ← 10*a
# x ← $s1
a
x
代入文 x = 2 * a + 4 * b - c のプログラム
(シフト命令使用)
1
2
3
4
5
6
7
8
lw $s0, 0($gp)
sll $s0, $s0, 1
lw $s1, 4($gp)
sll $s1, $s1, 2
add $s3, $s0, $s1
lw $s2, 8($gp)
sub $s3, $s3, $s2
sw $s3, 12($gp)
# $s0 ← a
# $s0 ← 2*a
$gp
# $s1 ← b
# $s1 ← 4*b
# $s3 ←2*a+4*b
# $s2 ← c
# $s3 ← 2*a+4*b-c
# x ← $s3
9
a
b
c
x