calico
CalicoCPUは「Calculator IC organized CPU」の略である。
「74シリーズのロジックICで作る、ある程度本格的な計算ができるCPU」を目指した設計。
hardware_cpu/cpus/calico_cpu at main · mikecat/hardware_cpu · GitHub
CalicoCPUは、8ビットの入出力ポートを2個持つ。
各ビットごとに、出力(HIGH/LOW)か入力(Hi-Z)かを選択できる。
ポートからの入力は、バッファなどの影響で遅れることがある。(実装依存)
CalicoCPUは、以下のレジスタを持つ。
A
、B
、C
、D
: 汎用レジスタ (8ビット×4)PC
: プログラムカウンタ (8ビット)P0OUT
、P1OUT
: ポート出力値レジスタ (8ビット×2)P0DRIVE
、P1DRIVE
: ポート出力モードレジスタ (8ビット×2)
MikeAssemblerでは、以下の命令をサポートしている。
命令およびレジスタ名の大文字・小文字は区別しない。
rd
、rs
、rt
: 汎用レジスタ (A
or B
or C
or D
)
width
: シフト幅 (0以上8以下の整数)
imm
: 即値 (整数、許される範囲は命令による)
preg
: ポート用レジスタ・ポート入力
汎用レジスタは、2ビットで以下のように表す。
レジスタ | ビット |
---|---|
A | 00 |
B | 01 |
C | 10 |
D | 11 |
preg
としては、以下のものを用いることができる。
x
には、0
(PORT0
用) または 1
(PORT1
用) が入る。
「出力」は汎用レジスタからpreg
にデータをコピーすること、「入力」はpreg
から汎用レジスタにデータをコピーすることである。
preg | 方向 | 説明 |
---|---|---|
PxOUT | 出力・入力 | ポートに出力する値を表す。 |
PxDRIVE | 出力 | ポートの各ビットに値を出力するかを表す。(1:出力する、0:出力しない(Hi-Z)) |
PxIN | 入力 | ポートから読み取った値を表す。 |
CalicoCPU自体で定義されている命令である。
命令 | 意味 | 命令コード (ビット) | 動作 |
---|---|---|---|
MOV rd, rs | レジスタ代入 | dd00ss00 | rd ← rs |
ADD rd, rs | レジスタ加算 | dd00ss01 | rd ← rd + rs |
NAND rd, rs | レジスタビットNAND | dd00ss10 | rd ← rd NAND rs |
SHL1 rd, width | 左シフト | dd000w11 width=2 → w=0, width=4 → w=1 | rd ← rd << width |
SHR1 rd, width | 右シフト | dd001w11 width=1 → w=0, width=2 → w=1 | rd ← rd >> width (論理シフト) |
MOVP rd, preg | ポート状態入力 | dd01xp00 preg=PxIN → p=0, preg=PxOUT → p=1 | rd ← preg |
MOVP preg, rd | ポート状態出力 | dd01xp10 preg=PxOUT → p=0, preg=PxDRIVE → p=1 | preg ← rd |
JAL rd, rs | サブルーチン呼び出し | dd01ss01 | rd ← PC+1 |
JNZ rd, rs | 分岐 | dd01ss11 | if (rd != 0) PC ← rs |
MOVI1 rd, imm | 即値代入 | dd10mmmm immは0~15が有効である。 | rd ← imm (ゼロ拡張) |
ADDI rd, imm | 即値加算 | dd11mmmm immは-8~7が有効である。 | rd ← rd + imm (符号拡張) |
アセンブラがネイティブ命令を組み合わせて実現する命令である。
命令数を指定する命令で、指定された命令数で表現できない場合はエラーになる。
命令 | 意味 | 動作 | ネイティブ命令数 |
---|---|---|---|
NOP | 何もしない | A ← A | 1 |
NOT rd | レジスタビットNOT | rd ← NOT rd | 1 |
AND rd, rs (rdとrsは別のレジスタ) | レジスタビットAND | rd ← rd AND rs | 2 |
OR rd, rs (rdとrsは別のレジスタ) | レジスタビットOR | rd ← rd OR rs | 4 |
OR! rd, rs (rdとrsは別のレジスタ) | レジスタビットOR (rsの値を保持しない) | rd ← rd OR rs | 3 |
XOR rd, rs, rt (rd、rs、rtは全て別のレジスタ) | レジスタビットXOR (rtを作業用に用いる) | rd ← rd XOR rs | 5 |
SHL rd, width | 左シフト (命令数は自動) | rd ← rd << width | 0~3 |
SHLk rd, width (k=1,2,3) | 左シフト (命令数をkに指定) | rd ← rd << width | k |
SHR rd, width | 右シフト (命令数は自動) | rd ← rd >> width (論理シフト) | 0~4 |
SHRk rd, width (k=1,2,3,4) | 右シフト (命令数をkに指定) | rd ← rd >> width (論理シフト) | k |
IN rd, x (x=0,1 (式使用可)) | ポート入力 | rd ← PxIN | 1 |
OUT x, rd (x=0,1 (式使用可)) | ポート出力 | PxOUT ← rd | 1 |
DRIVE x, rd (x=0,1 (式使用可)) | ポート出力モード設定 | PxDRIVE ← rd | 1 |
MOVI rd, imm (-128≦imm≦255) | 即値代入 (命令数は自動) | rd ← imm | 1~3 |
MOVIk rd, imm (-128≦imm≦255、k=1,2,3) | 即値代入 (命令数をkに指定) | rd ← imm | k |
直接ジャンプ命令は存在しない。
0番地でないaddr
にジャンプしたい場合は、作業用レジスタをrd
として、
MOVI3 rd, addr
JNZ rd, rd
とすればよい。
使える場合は、MOVI3
のかわりにより少ない命令数のMOVIk
を使ってもよい。
MOVI3
のかわりに命令数を自動で決定するMOVI
を用いると、ラベルが収束しなくなる可能性がある。