アーキテクチャ

CPU

8ビットのCPUです。1フレームにつき1命令を実行します。

レジスタ

汎用レジスタ(8ビット)

レジスタ説明
Aアキュムレータ。演算命令の主要なオペランドです。
B, C汎用レジスタ。BCレジスタペアとしても使用します。
D, E汎用レジスタ。DEレジスタペアとしても使用します。
H, L汎用レジスタ。HLレジスタペアとしてメモリアドレス指定に使用します。

特殊レジスタ

レジスタビット幅説明
PC16ビットプログラムカウンタ。次に実行する命令のアドレスを保持します。
SP16ビットスタックポインタ。スタックの先頭アドレスを保持します。
PTBR16ビットページテーブルベースレジスタ。ページテーブルの先頭物理アドレスを保持します。
IVTBR16ビット割り込みベクタテーブルベースレジスタ。ベクタテーブルの先頭仮想アドレスを保持します。
PFAR16ビットページフォルトアドレスレジスタ。ページフォルト発生時のフォルトした仮想アドレスを保持します。読み取り専用です。

レジスタペア

2つの8ビットレジスタを組み合わせて16ビットの値として扱います。上位バイトが先のレジスタです。

ペア名上位下位
BCBC
DEDE
HLHL
PSWAF(フラグレジスタ)

メモリ参照(M)

命令中のオペランド「M」は、HLレジスタペアが指すメモリアドレスの内容を意味します。

フラグレジスタ(F)

演算結果に応じて自動的に更新されるフラグの集合です。条件分岐命令で参照されます。

フラグビット位置説明
S(サイン)7演算結果のビット7が1のとき1になります。
Z(ゼロ)6演算結果が0のとき1になります。
AC(補助キャリー)4ビット3からビット4へのキャリー(またはボロー)が発生したとき1になります。
P(パリティ)2演算結果のビット中の1の個数が偶数のとき1になります。
CY(キャリー)0演算結果でキャリー(またはボロー)が発生したとき1になります。

フラグレジスタのビット配置

ビット:  7   6   5   4   3   2   1   0
        [S] [Z] [0] [AC] [0] [P] [1] [CY]

ビット5と3は常に0、ビット1は常に1です。

メモリ

64KB(65,536バイト)のメモリ空間を持ちます。アドレス範囲は0x0000〜0xFFFFです。

マルチバイトデータはリトルエンディアン(下位バイトが低位アドレス)で格納されます。

起動時の初期状態

起動時、メモリの先頭3バイトには0番地への無限ループが配置されています。

0x0000: 0xC3  (JMP)
0x0001: 0x00  (ジャンプ先 下位バイト)
0x0002: 0x00  (ジャンプ先 上位バイト)

それ以外のアドレスは0x00で初期化されています。

スタック

スタックはメモリ上に確保され、SPレジスタが先頭を指します。スタックは下位アドレス方向に成長します。

MMU(メモリ管理ユニット)

ページング方式の仮想メモリ機構です。有効時、CPUが発行するアドレスは仮想アドレスとして扱われ、ページテーブルを参照して物理アドレスに変換されます。

無効時は、アドレスがそのまま物理アドレスとして扱われます。

ページング仕様

項目
ページサイズ256バイト
ページ数256ページ
ページテーブルエントリ(PTE)サイズ2バイト
ページテーブルサイズ512バイト

アドレス変換

仮想アドレスは以下のように分解されます。

仮想アドレス(16ビット):
  上位8ビット → ページテーブル内インデックス(0〜255)
  下位8ビット → ページ内オフセット(0〜255)

変換手順は以下の通りです。

  1. PTBRの上位8ビットをページテーブルの先頭物理アドレスとします(PTBRは物理アドレスを保持するため、MMUによるアドレス変換は行われません)。
  2. 先頭アドレス + ページテーブル内インデックス × 2 がPTEのアドレスです。
  3. PTEの上位8ビットが物理ページの先頭アドレスです。
  4. 物理ページの先頭アドレス + ページ内オフセット が物理アドレスです。

PTEフラグ

PTEの下位8ビットはフラグ領域です。現在、ビット0がValidビットとして使用されています。

ビット名前説明
0Valid1のとき有効なページです。0のときページフォルトが発生します。
1〜7(予約)将来のフラグ用に予約されています。

ページフォルト

MMU有効時、アドレス変換でPTEのValidビットが0のページにアクセスすると、ページフォルト例外が発生します。

ページフォルトが発生すると、以下の処理が行われます。

  1. PFARにフォルトした仮想アドレスを設定します。
  2. レジスタ・フラグ・SPをフォルト命令の実行前の状態に戻します。
  3. PCをフォルトした命令の先頭アドレスに戻し、それをスタックにプッシュします。
  4. 割り込みを禁止します(INTE=0)。
  5. ベクタテーブルからハンドラアドレスを取得し、そこへジャンプします。

ページフォルトのベクタ番号は1です。ハンドラの末尾でRET命令を実行すると、フォルトした命令へ戻り、再実行できます。

ページフォルトは割り込み許可フラグ(INTE)の状態に関係なく発生します。

メモリへの書き込み副作用はロールバックされません。レジスタ・フラグ・SPのみが復元されます。

ハンドラ内でPFARの値を読み出すことで、どの仮想アドレスでフォルトが発生したかを知ることができます。PFARの読み出しにはMOV rp, PFAR命令を使用します。

ベクタテーブル

例外発生時にジャンプするハンドラのアドレスを格納するテーブルです。ベース仮想アドレスはIVTBRレジスタで指定します。

各エントリは2バイト(リトルエンディアン)で、ハンドラの16ビットアドレスを格納します。

ベクタ番号アドレス用途
0IVTBR+0x0000〜IVTBR+0x0001予約
1IVTBR+0x0002〜IVTBR+0x0003ページフォルト
2〜7IVTBR+0x0004〜IVTBR+0x000FIRQ #0〜#5(外部割り込み)

ベクタ番号0は予約、ベクタ番号1はページフォルト専用です。外部割り込み(IRQ)はベクタ番号2〜7を使用します。

ベクタテーブルのベース仮想アドレスはIVTBRレジスタで指定します。初期値は0x0000です。

IVTBRは仮想アドレスを保持するため、MMU有効時はベクタテーブルの読み出しがMMUによるアドレス変換を経由します。MMU無効時はIVTBRの値がそのまま物理アドレスとして使用されます。

MMU有効時にベクタテーブルのページがマッピングされていない場合、ページフォルトが連続して発生(ダブルフォルト)するため、CPUは停止します。

I/Oポート

256個のI/Oポート(0x00〜0xFF)を持ちます。IN命令とOUT命令でアクセスします。

現在の実装では、IN命令は常に0xFFを返し、OUT命令は何もしません。周辺機器との連携は今後追加予定です。

割り込み

割り込みの許可・禁止をEI/DI命令で制御できます。割り込み許可フラグ(INTE)は起動時に0(禁止)です。

ページフォルト等の同期例外はINTEの状態に関係なく発生します。例外発生時はINTEが0に設定されます。

外部割り込み(IRQ)

外部デバイスやUIからIRQを発生させることができます。IRQは6本(IRQ#0〜#5)あり、ベクタ番号2〜7に対応します。保留中のIRQはCPUが受け付け可能な状態(INTE=1)になるまで保持されます。

画面上の外部割り込みボタンをクリック(ボタン上でマウスボタンを離した時)すると、IRQ#0が発生します。操作方法の詳細は操作方法を参照してください。

割り込み受付の流れは以下の通りです。

  1. INTE=1かつ保留中のIRQがある場合、最小番号のIRQを選択します。
  2. スタックプッシュ先のアドレスを事前検証します。ページフォルトが発生した場合はIRQ受付をスキップして通常の命令実行フローへ遷移します(IRQは保留のまま残ります)。検証に成功した場合は、以下の手順(3〜5)に進みます。
  3. 現在のPCをスタックにプッシュします(CALL命令と同じ形式)。
  4. INTEを0に設定します。
  5. ベクタテーブルからハンドラアドレスを取得し、PCに設定します。

ハンドラの末尾でEI命令とRET命令を実行することで、次の割り込みを受け付け可能にしつつ、割り込み前のアドレスに戻ります。

HLT命令でCPUが停止中の場合も、INTE=1かつ保留IRQがあればCPUが復帰し、割り込みを受け付けます。ただし、スタック領域のページフォルトが検出された場合はHLT状態を維持します。

ページフォルト例外はベクタテーブルを使用してハンドラにジャンプします。詳細はページフォルトベクタテーブルを参照してください。