6/1

MIPSの主記憶の構成
z 主記憶の各ワード(語)は,番地(アドレス)によって識別され
る。(番地はbyte単位で付けられる)
語(ワード)の番地
プロセッサからは
4の倍数の番地
で各ワードを指定
する
byte単位での番地
0番地
0番地
1番地
2番地
3番地
4番地
4番地
5番地
6番地
7番地
8番地
8番地
9番地
10番地
11番地
…………
4n番地
4n
4n+1
4n+2
4n+3
…………
1073741820番地
(230-4)
230-4
230-3
230-2
230-1
最初のワードの番地は0番地,次は4番地,次は8番地... ,となる
MIPSのレジスタ
z 32個のレジスタ
– 機械語では0から31までの番号で識別される
– アセンブラ言語では名前(レジスタ名)で識別できる
z 使用目的により32個のレジスタを分類(規約)
– レジスタ $s0,$s1,$s2,……,$s7
• C言語などの高級言語でプログラム中の変数の値を保持する目的
– レジスタ $t0,$t1,$t2,……,$t7
• 演算の途中での一時的なデータを保持する目的
– レジスタ $zero
• 特別なレジスタで,常に 0 を値としてもつ
(どのような値を書き込んでも,値は0のまま = データは保存できない)
1
MIPSのレジスタ番号とレジスタ名
レジスタ番号
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
レジスタ名
$zero
$at
$v0
$v1
$a0
$a1
$a2
$a3
$t0
$t1
$t2
$t3
$t4
$t5
$t6
$t7
レジスタ番号
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
レジスタ名
$s0
$s1
$s2
$s3
$s4
$s5
$s6
$s7
$t8
$t9
$k0
$k1
$gp
$sp
$fp
$ra
※ アセンブリ言語では,レジスタ名で表記する
例 変数 a と b の値を交換するプログラム
アセンブリ言語のプログラム
C言語のプログラム
w=a;
a=b;
b=w;
$gp
a
1
2
lw $t0, 0($gp)
sw $t0,8($gp)
w = a;
3
4
lw $t0, 4($gp)
sw $t0, 0($gp)
a = b;
5
6
lw $t0, 8($gp)
sw $t0, 4($gp)
b = w;
これは説明用の行番号
b
w
ある変数の値を別の変数に代入するには,
ロード命令とストア命令を使い,レジスタを
経由しなければならない
2
代入文の意味
「代入文」
変数 = 式 ;
「式」: 単独の定数や変数,配列要素,及び
それらを演算記号で結合したもの。
記号「=」は,右辺の式の「値」を左辺の変数に「格納」するという作用をもつ。
a=5 ;
a
5
b=8;
b
8
h=4;
h
4
s=(a+b)* h / 2;
s
26
右辺の式の値を求めてから,変数に格納する。
整数演算命令
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に格納する
3
整数演算の例
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 で求まる)
用語
z オペコード(operation code の略) : 命令コード
z オペランド(operand) : 演算対象(のデータ)
− ソース(source:元): 被演算対象となるデータ
− デスティネーション
(destination:目的): 演算結果のデータ
add $s0, $s1, $s2
# $s0←$s1+$s2
第2 ソースオペランド
第1ソースオペランド
デスティネーションオペランド
オペコード
4
ソース
デスティネーション
代入文
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
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
6 5
0
rsフィールド(5ビット) rtフィールド(5ビット) rdフィールド(5ビット)
shamtフィールド(5ビット)
ソースレジスタを示す ソースレジスタを示す デスティネーションレジスタ シフト命令でシフト量を示す
$s2 (18)
$s3 (19)
を示す $s1 (17)
加算命令の場合は0
5
減算命令の命令形式
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
整数演算命令
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
001000 10010 10001
31
26 25
21 20
16 15
6
C
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
論理演算
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
7
論理演算命令
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 に格納する。
論理演算命令の命令形式
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
8
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に格納する
算術シフト演算
‹ 指定されたビット数,左あるいは右に算術シフトする
z MIPSでは左論理シフト命令はあるが,左算術シフト命令はない
(左シフトを行う場合は,左論理シフト命令を使う)
z 右算術シフト(shift right arithmetic)
はみ出したビットは捨てられ,空いた部分には符号ビットの値が入る
命令 : sra $Ri, $Rj, k
レジスタ$Rjの内容を k ビット右に算術シフトした値を$Riに格納する
9
左シフトと数値との関係
整数 100(10) の2進表現
0000 0000 0000 0000 0000 0000 0110 0100 = 100(10)
2 ビット左にシフト
0000 0000 0000 0000 0000 0001 1001 0000 = 400(10)
整数 -100(10) の2進表現
1111 1111 1111 1111 1111 1111 1001 1100 = -100(10)
2ビット左にシフト
1111 1111 1111 1111 1111 1110 0111 0000 = - 400(10)
n ビットの左シフト ⇔ 2n 倍
右算術シフトと数値との関係
整数 400(10) の2進表現
0000 0000 0000 0000 0000 0001 1001 0000 = 400(10)
2 ビット右に算術シフト
0000 0000 0000 0000 0000 0000 0110 0100 = 100(10)
整数 -400(10) の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での割ったときの商)
10
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
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
# $t0 ← 5*a
# $s1 ← 10*a
# x ← $s1
11
$gp
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 ← a+4*b-c
# x ← $s3
12
a
b
c
x