CPU設計実習(授業用) - 5章 CDECv標準命令の命令サイクル

# 5章 CDECv標準命令の命令サイクル

CDECvでは、命令は1ステップ(1クロック)で行われるのではなく、複数のステップを経て実行されます。
一つの命令を実行するのに必要なすべてのステップは命令サイクル(Instruction Cycle)と呼ばれます。
この命令サイクルは、命令をメモリから取り出しどの命令を実行するのかを確定するまでのフェッチサイクル(Fetch Cycle)と、取り出した命令を実際に実行するまでの実行サイクル(Execute Cycle)とに分けられます。

CDECvの標準命令は図5.1に示す命令サイクルで行われます。
F0からF2はフェッチサイクルで、それ以降は実行サイクルです。
フェッチサイクルで行う処理は命令によらず同じですが、実行サイクルは命令によって行う処理が異なります。
そのため、命令の種類により、フェッチサイクルの最後のステップF2から実行サイクルへは分岐が生じます。
図5.1中の各ステップの名前とその意味を、表5.1に示します。

![instruction_cycle.png](https://qiita-image-store.s3.amazonaws.com/0/25656/b3a30eb0-d2c6-4b8c-4a29-123754613969.png)

<図5.1 CDECv標準命令の命令サイクル>

<表5.1 CDECv標準命令の命令サイクルの各ステップ名>

| ステップ名 | 意味          | 該当する命令 |
|-----|---------------------|---|
| Fn  | フェッチサイクル  | |
| MVn | レジスタ間データ転送命令 | MOV |
| P2n | 2オペランド命令 | ADD, ADC, SUB, SBB, AND, OR, EOR |
| P1n | 1オペランド命令 | INC, DEC, NOT |
| LDn | ロード命令 | LD |
| STn | ストア命令               | ST |
| JPn | 無条件分岐命令 | JMP |
| JCn | 条件付き分岐命令    | JS, JZ, JC |


以下ではまず、フェッチサイクルの各ステップでどのような処理を行うのかを説明します。
その後、それぞれの実行サイクルの各ステップで行う処理について見ていきます。


## フェッチサイクル (F0-F2)

フェッチサイクルでは、これから実行しようとする命令の機械語コードをメモリから取得します。

フェッチサイクルの各ステップで行う処理を表5.2に示します。
表5.2の各行は、各ステップにおいて、Xbus を介して行うデータ転送、メモリ操作、 AUL に関連した操作を示しています。
表中の reg <- data という表記は右辺のデータ data を左辺のレジスタ reg へ転送することを表します。
例えば MAR <- PC はプログラムカウンタPCに格納されたデータを MAR に転送することを表し、 R <- PC + 1 は(ALUにおいて) PC に1を加えた結果をRレジスタへ転送することを表します。

<表5.2 フェッチサイクルで行う処理>

|ステップ| Xbus | Memory | ALU |
|---|---|---|---|
| F0 | MAR <- PC |                | R <- PC + 1 |
| F1 | PC <- R   | RD <- MEM[MAR] |             |
| F2 | I <- RD   |                |             |

F0 では、PC が指し示すメモリのアドレスに格納されたデータ(命令の機械語コード)にアクセスするため、PC の内容を MAR に転送します。
同時に ALU では PC をインクリメントした結果をRレジスタへ格納します。

F1 では R レジスタの内容を PC に書き込むことで、結果的に PC がインクリメントされます。これにより次の命令の取得に備えます。
メモリでは読出し操作を行います。表中 RD <- MEM[MAR] は MAR で指定されたアドレスに格納されたデータを RD へ出力することを意味しています。
MAR が確定してからメモリの内容を読みだすまでに1クロック必要であったことを注意してください。
F0 で MAR が確定され、1クロック後の F1 でメモリの内容が RD に出力されます。
この時点で(インクリメントされる前の) PC が指し示すアドレスに格納されていた命令の機械語コードがRDに出力されていることになります。

F2 では RD の値、すなわち命令の機械語コードを命令レジスタ I へ転送します。
I レジスタの内容は制御部へ送られるため、この時点で制御部はこれから実行する命令を知ることができます。


## 実行サイクル

上記で説明したフェッチサイクルは命令によらず同じ処理を行います。
フェッチサイクルが終了すると、取得した命令に応じた実行サイクルに移ります。
実行サイクルが終了した時点で1つの命令が実行されたことになります。
実行サイクルの最後のステップが終わると、フェッチサイクルの最初のステップ F0 へ戻り、次の命令の取得が行われます。

以下では命令の種類ごとにそれぞれの命令サイクルでどのような処理を行うかを説明します。


### レジスタ間データ転送命令の実行サイクル (MV0)

レジスタ間データ転送命令 `MOV sreg, dreg` の実行サイクルで行われる処理を表5.2に示します。

<表5.3 `MOV sreg, dreg` の実行サイクルで行う処理>

|ステップ| Xbus | Memory | ALU |
|---|---|---|---|
| MV0 | dreg <- sreg |  |  |

実行サイクルは MV0 のみです。
Xbus を介して転送元の汎用レジスタ sreg から転送先の汎用レジスタ dreg へデータ転送が行われます。
これで、MOV 命令は終了します。


### 2オペランド命令の実行サイクル (P20-P22)

2オペランド命令として `ADD reg` を例にして、実行サイクルで行われる処理を説明します(表5.4)。
 この命令は A レジスタと汎用レジスタ reg を加算しその結果を A レジスタへ格納します(A + reg -> A)。

<表5.4  `ADD reg` の実行サイクルで行う処理>

|ステップ| Xbus | Memory | ALU |
|---|---|---|---|
| P20 | T <- reg | | |
| P21 | A <- A   | | R <- A + T, FLG <- Flag(A + T) |
| P22 | A <- R   | | |

P20 では被加算数となる reg のデータを T レジスタへ転送します。

P20では加算数となる A レジスタのデータを Xbus へ出力するため、A レジスタから自分自身(Aレジスタへの)データ転送を行います。
ALU においては Xbus に出力されたAレジスタの値と、T レジスタの値を加算し、その演算結果をRレジスタへ転送します。
同時に、演算結果によって生じたフラグ信号(S, Z, Cy)をフラグレジスタFLGへ格納します。表中の FLG <- Flag(A + T) は A + T の演算によって生じたフラグ信号を FLG へ転送することを表します。

最後のステップである P22 では、R レジスタに保持されている演算結果を A レジスタに転送し、ADD命令が終了します。


### 1オペランド命令の実行サイクル (P10-P11)

1オペランド命令として `INC reg` を例にして、実行サイクルで行われる処理を説明します(表5.5)。
この命令は汎用レジスタ reg の値を1増加させます(reg + 1 -> reg)。


<表5.5  `INC reg` の実行サイクルで行う処理>

|ステップ| Xbus | Memory | ALU |
|---|---|---|---|
| P10 | reg <- reg   | | R <- reg + 1, FLG <- Flag(reg + 1) |
| P11 | reg <- R     | | |


P10では、汎用レジスタregから自身へのデータ転送によりXbusへregの値を出力し、ALUにおいて reg + 1 を計算します。
その演算結果をRレジスタ、フラグ信号をFLGへ格納します。

最後のステップであるP11では、演算結果が保持されているRレジスタから汎用regへデータが転送され、INC命令が終了します。


### ロード命令の実行サイクル (LD0-LD4)

ロード命令 `LD adrs, dreg` の実行サイクルで行われる処理を説明します(表5.6)。
この命令はアドレス adrs に格納されたメモリのデータを汎用レジスタ dreg へ転送します。

<表5.6 `LD adrs, dreg` の実行サイクルで行う処理 >

|ステップ| Xbus | Memory | ALU |
|---|---|---|---|
| LD0 | MAR <- PC  |                | R <- PC + 1 |
| LD1 | PC <- R    | RD <- MEM[MAR] | |
| LD2 | MAR <- RD  |                | |
| LD3 | (PC <- PC) | RD <- MEM[MAR] | |
| LD4 | dreg <- RD |                | |

LD命令は2バイト命令であり、データの転送元となるメモリのアドレス adrs は2バイト目に示されます。
LD0 では、アドレス adrs を取得するため、フェッチサイクルで値がインクリメントされたPCの値をMARに転送します。
併せて、ALU では R に PC + 1 を転送します。

LD1　では PC に R を転送し、次の命令に備えます。
フェッチサイクルと合わせると PC の値が 2 増加していることに注意してください。
LD命令は2バイト命令ですので、この時点でPCは次の命令のアドレスを示すことになります。
メモリでは、データの読出し(RD <- MEM[MAR])を行います。
RDには転送元のアドレス adrs が出力されます。

LD2では転送元のアドレスにアクセスするため、RD の値、すなわち adrs を MAR に格納します。

LD3ではアドレス adrs に格納されたメモリのデータを読みだします。
なお、Xbusにおいては特にデータの転送を行う必要はないのですが、CDECvの仕様としてXbusのデータの転送元(xsrc)と転送先(xdst)を必ず指定する必要がありますので、ここでは特に意味のないデータ転送 PC <- PC を行っています。
今後は PC <- PC のような意味のないデータ転送については記述を省略します。

最後のステップ LD4 では、RDからdregへのデータ転送を行います。

### ストア命令の実行サイクル (ST0-ST4)

ストア命令 `ST sreg, adrs` の実行サイクルで行われる処理を説明します(表5.7)。
この命令は汎用レジスタ sreg のデータをメモリに書き込みます。
メモリの書き込み先のアドレスは adrs で指定されます。

<表5.7 `ST sreg, adrs`の実行サイクルで行う処理 >

|ステップ| Xbus | Memory | ALU |
|---|---|---|---|
| ST0 | MAR <- PC   |                 | R <- PC + 1 |
| ST1 | PC <- R     | RD <- MEM[MAR]  | |
| ST2 | MAR <- RD   |                 | |
| ST3 | WDR <- sreg |                 | |
| ST4 |             | MEM[MAR] <- WDR | |

ストア命令 ST は2バイト命令で、データの書き込み先アドレス adrs は命令の2バイト目で指定されます。
ST0からST1までは、LD命令のLD0からLD2と同様に、adrs の取得と PC の更新を行います。

ST2ではデータの書き込み先のアドレス指定を行います(MAR <- RD)。

ST3ST3ではメモリへ書き込むデータ( sreg )を WDR へ格納します。

ST2とST3で書き込み先アドレス(MAR)と、書き込みデータ(WDR)が確定したので、次のステップ ST4 ではメモリへのデータの書き込を行います。表中 MEM[MAR] <- WDR はMARで指定されるアドレスを書き込み先として、WDRの内容をメモリへ書き込むことを表します。
以上で、ST命令は終了します。

### 無条件分岐命令の実行サイクル (JP0-JP2)

無条件分岐命令 `JMP adrs` の実行サイクルで行われる処理を説明します(表5.8)。
この命令は adrs で指定されるアドレスの命令へ分岐(ジャンプ)します。
これは、PC を adrs の値で更新することで実現できます。

<表5.8 `JMP adrs`の実行サイクルで行う処理 >

|ステップ| Xbus | Memory | ALU |
|---|---|---|---|
| JP0 | MAR <- PC   |                 | |
| JP1 |             | RD <- MEM[MAR]  | |
| JP2 | PC <- RD    |                 | |

JP0 と JP1 ではメモリから adrs の値を取得します。

JP2で取得した adrs の値を PC に格納し、JMP命令が終了します。

### 条件付き分岐命令の実行サイクル (JC0-JC2)

条件付き分岐命令として`JS adrs`を例にして、実行サイクルで行われる処理を説明します(表5.9)。
この命令は、サインフラグSが立っている場合(S == 1)はアドレス adrs にある命令へ分岐し、そうでない場合(S==0)の場合は次の命令へ移ります。

<表5.9 `JMP adrs`の実行サイクルで行う処理 >

|ステップ| Xbus | Memory | ALU |
|---|---|---|---|
| JC0 | MAR <- PC   |                 | R <- PC + 1 |
| JC1 | PC <- R     | RD <- MEM[MAR]  | |
| JC2 | PC <- RD (S == 1の場合) |     | |

JC0 と JC1 ではメモリから adrs の値を取得します。
同時に PC をインクリメントします。
この時点で PC は次の命令のアドレスを指し示しています。

JC2で行われる処理は、サインフラグSが立っているかどうかによって異なります。
サインフラグが立っている場合(S == 1)は、 PC を取得した adrs の値で更新します(PC <- RD)。
サインフラグが立っていないの場合(S == 0)は、特に何もせず PC の値は更新しません。
以上でJS命令が終了します。

## 演習問題

1. 本章の説明で取り上げなかった命令(例えば、2オペランド命令の SUB や条件付き分岐命令の JC など)について、実行サイクルの各ステップでどのような処理を行えばよいか検討しましょう。

2. 例えばST命令など、命令を1つ取り上げ、その命令サイクル(フェッチサイクルと実行サイクル)の各ステップの処理を行うには、どのような制御信号(xsrc, xdst, aluop, Rwe, FLGwe, MEMwe)をデータパス部に送ればよいかを検討しましょう。