前置き
どうも!!
マイコン部論理班のyamatyaです。
CPUを学んで約1年!!
自分がどれぐらい成長したか試したかったので、
今回は既存のCPUや独自のISAを組み合わせて新たなISAおよびCPUを自作していきたいと思います。
しかし、やることが多すぎるので2回に分けてやりたいと思います。
今回はISA(命令セット)について設計します。
では やっていきましょう!!
改造元:hackCPU(RISC)
0.CPUのある程度の仕組み
CPUの仕組みがわからないよー っていう人向けにCPUの仕組みをある程度解説しておこう。
CPUは、簡単に表すとメモリに並んでいる「命令」を1つずつ取り出して、
解読 → 計算 → 結果を保存
という流れをひたすら繰り返す装置です。
- 命令を読む場所 → PC(プログラムカウンタ)
- 計算をする場所 → ALU(演算装置)
- 計算結果の置き場 → レジスタ(小容量だが高速な記憶装置)
- データを取りに行く場所 → メモリ(ROM/RAMなど)
例えると「レジスタという机の上のメモ帳を使って、手元で計算している人」のようなイメージ!!
1.固定長ってなあに?
まず 固定長CPUってなんぞや って思う方がいると思うので解説しておきます。
固定長CPUとは要するに...
CPU の命令がすべて同じビット数(長さ)で構成されている方式!!
命令の長さが同じなのでいちいち命令を解読&変換する必要がない。
=なので構造が単純になる。
今回は構造が簡単で実行速度も速いRISCというタイプのCPUを作っていこうと思います。
(ちなみにARMはRISC CPUの一種)
RISCの特徴は以下の通り
- 1命令を1クロックで実行できる
=CPUの動作が速い
- 構造が単純なので難しい操作はできない
=足し算やコピーなど、すごくシンプルな動きしかできない
=難しい操作をするには単純な命令を大量に記述する必要がある
- 命令が全部同じ長さなので、CPU が命令を読み取るのが速い
=回路も単純になり作りやすい
RISCの理念
RISCの理念とはRISC CPUを作る上で心がけるべき考えです。
RISCの理念を一言で表すと 「命令をできるだけ単純にして、高速に実行できるCPUを作る」 です。
それを達成するには以下のことに心がけないといけません。
- メモリから直接複雑な操作を行う命令を避け、レジスタを中心に計算
- 単純命令を1サイクルで実行できるように設計
- 複雑命令のためにCPUの設計を複雑化しない
- 汎用レジスタだけで全部できる
- 特殊レジスタはできるだけ減らす
なので今回はこれらも意識して作りました。
2.ある程度の構想
アセンブリ
-
最初の3~4ビットで命令判断
2ビット2ビットに分ける
前半
00:A命令:データ転送系
01:B命令:演算系
10:C命令:ロードストア
11:D命令:CPU、周辺機器操作系
後半は分岐する時に使用。
-
固定長命令を採用すると「命令に載せられるデータのサイズ」が限られる
なので即値代入系はMOV reg,imm8のように最大8bitしか使えない
しかし「レジスタ同士の転送」などデータを入力しないものはビット幅の制限がないので、
MOV r1, r3のように16bitアクセスが可能
-
メモリアドレスはアドレスレジスタで指定する
レジスタ構想
レジスタは全部16bit。
❖r0(ゼロレジスタ)
常に0を出力するレジスタ。書き込みは無視。
❖r1~r7(汎用レジスタ)
演算・データ保持・アドレス計算などCPU内のあらゆる処理に使用されるレジスタ群。
❖PC(プログラムカウンタ)
次実行する命令のアドレスが格納されている特殊レジスタ。
❖AR(アドレスレジスタ)
メモリアクセスなどでメモリのアドレスを指定するときに用いられる特殊レジスタ
❖LR(リンクレジスタ)
関数呼び出し時に戻り先アドレスを保持、関数から復帰する際に使用される特殊レジスタ。
命令内でレジスタを選択するときのビットの組み合わせは以下の通り↓
| r/R | 名前 |
|---|---|
| 000 | r0 |
| 001 | r1 |
| 010 | r2 |
| 011 | r3 |
| 100 | r4 |
| 101 | r5 |
| 110 | r6 |
| 111 | r7 |
| 1000 | AR |
| 1001 | LR |
3.詳しく決める
A命令(MOV)
レジスタからレジスタに代入
0000 rrrRRR 000000
R->r
r,RレジスタID
レジスタの上位or下位に8bit即値を代入
0001 rrrh XXXXXXXX
rレジスタID
h h=0 上位/h=1 下位
X即値
レジスタからAR/LRに代入
0010 rrrA 00000000
rレジスタID
AAR/LR
AR/LRの上位or下位に8bit即値を代入
0011 00AH XXXXXXXX
AAR/LR
H上位/下位
X即値
B命令
ALU(Rにr,Ŕを操作した結果を代入する)
010RRR rrr ŔŔŔ 0ooo
r,R,Ŕ レジスタID
o op
| o | 意味 | 説明 |
|---|---|---|
| 000 | ADD | R=r+Ŕ |
| 001 | SUB | R=r-Ŕ |
| 010 | AND | R=r and Ŕ |
| 011 | OR | R=r or Ŕ |
| 100 | XOR | R=r XOR Ŕ |
| 101 | NOT | R=not r |
| 110 | SHL | R=r SHR Ŕ |
| 111 | SHR | R=r SHR Ŕ |
ALU(即値演算系)
011 RRR rrr ooo XXXX
| o | 意味 | 説明 |
|---|---|---|
| 000 | ADDI | R=r+X |
| 001 | SUBI | R=r-X |
| 010 | SUBI2 | R=X-r |
| 011 | ANDI | R=r AND X |
| 100 | ORI | R=r OR X |
| 101 | XORI | R=rXOR X |
| 110 | SHLI | R=r SHL X |
| 111 | SHRI | R=r SHR X |
C命令
レジスタにメモリ(アドレス:AR)を代入
100 rrr 000 0000000
rレジスタID
メモリ(アドレス:AR)にレジスタを代入
101 rrr 000 0000000
rレジスタID
D命令
CPU/ハード操作
110 oo ???????????
| o | ? | 意味 | 説明 |
|---|---|---|---|
| 00 | 00000000000 | HLT | CPU停止 |
| 01 | 00000000000 | RST | 初期化 |
| 10 | rrr00000000 | IN | ポートから取得した値をrに代入 |
| 11 | rrr00000000 | OUT | ポートにrの内容を出力 |
JMP(条件を満たしたらRRRのアドレスにジャンプ)
111 0jjj RRR rrr ŔŔŔ
jjjジャンプコード
| j | op | 条件 |
|---|---|---|
| 000 | JMP | 強制 |
| 001 | JEQ | r==Ŕ |
| 010 | JNE | r!=Ŕ |
| 011 | JGT | r>Ŕ |
| 100 | JLT | r<Ŕ |
| 101 | JGE | r>=Ŕ |
| 110 | JLE | r<=Ŕ |
| 111 | JO | オーバーフローしたら |
r,R,Ŕ レジスタID
あとがき
今回はこれでおしまいです
明日はこのISAを元にCPUの回路を実際に作っていきたいと思います。
お楽しみに!!