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=1rd ← rd << width
SHR1 rd, width
右シフト
dd001w11
width=1 → w=0, width=2 → w=1rd ← rd >> width
(論理シフト)
MOVP rd, preg
ポート状態入力
dd01xp00
preg=PxIN → p=0, preg=PxOUT → p=1rd ← preg
MOVP preg, rd
ポート状態出力
dd01xp10
preg=PxOUT → p=0, preg=PxDRIVE → p=1preg ← rd
JAL rd, rs
サブルーチン呼び出し
dd01ss01
rd ← PC+1
PC ← rs
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
rs ← 不定
3
XOR rd, rs, rt
(rd、rs、rtは全て別のレジスタ)レジスタビットXOR
(rtを作業用に用いる) rd ← rd XOR rs
rt ← 不定
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
を用いると、ラベルが収束しなくなる可能性がある。