HN 日本語サマリー

← 一覧へ戻る
プログラミング

Gigatronのプログラミング

Programming the Gigatron (iwriteiam.nl)

14 pointsby shakna1 コメント

要約

この記事は、筆者がGigatron TTLカラーマイクロコンピュータの理解とプログラミングを試みた個人的な記録です。CPUのハーバードアーキテクチャや命令セットの詳細な解説に加え、`theloop.asm`ファイルで使用されている命令を分析し、その使用頻度とニーモニックをリストアップしています。

全文翻訳

Gigatronのプログラミング この記事は、Gigatron TTLカラーマイクロコンピュータの理解とプログラミングを試みた私の個人的な試みについてです。GitHubのkervinck/gigatron-romにあるファイルを利用しました。免責事項: これは公式のGigatronページではなく、含まれるエラーについて私は責任を負いません。ROMの新版がリリースされた場合、このページは古くなる可能性があります。 CPU GigatronのTTL ICで実装されているCPUはハーバードアーキテクチャを採用しており、ROMとRAMで共有バスを持たないことを意味します。実際、ROMは命令を格納するためだけに用いられ、ROMに直接アクセスする命令はありません。(それでも、ROMからデータを「読み取る」ことが可能な巧妙なトリックがあります。)CPUは8ビットプロセッサで、14ビットのプログラムカウンタと15ビットのRAM範囲を持ちます。3つの8ビットレジスタと、8ビットの入出力があります。 CPU命令 gtemu.cプログラムを書き直し、異なる命令が実際に行うことを擬似C言語で出力するようにしました。多くの改訂を経て、以下の表になりました。行と列の数字を足し合わせることで命令番号が得られます。類似した(または同じ)命令がグループ化されるように行の順序を変更しました。「function」hiは値の上位バイトを返します。RAMにアクセスするために使用される値は、RAMが32キロバイトしかないため、0x7fffに「クリップ」されることに注意してください。命令がプログラムカウンタを変更する場合を除き、プログラムカウンタはすべての命令の後にインクリメントされます。命令が2つの操作を実行する場合、区切り文字としてセミコロンが使用されます。 # 00 # 20 # 40 # 60 # 80 # a0 # c0 # e0 ---+-----------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+--------------------------+--------------------------------- 00 # A = oper # A &= oper # A |= oper # A ^= oper # A += oper # A -= oper # RAM[oper] = oper # PC = (Y>>8)|oper 04 # A = oper # A &= oper # A |= oper # A ^= oper # A += oper # A -= oper # RAM[X] = oper # if (A < 0) PC = hi(PC)|oper 08 # A = oper # A &= oper # A |= oper # A ^= oper # A += oper # A -= oper # RAM[(Y>>8)|oper] = oper # if (A > 0) PC = hi(PC)|oper 0c # A = oper # A &= oper # A |= oper # A ^= oper # A += oper # A -= oper # RAM[(Y>>8)|X] = oper # if (A != 0) PC = hi(PC)|oper 10 # X = oper # X = A & oper # X = A | oper # X = A ^ oper # X = A + oper # X = A - oper # RAM[oper] = oper; X = A # if (A == 0) PC = hi(PC)|oper 14 # Y = oper # Y = A & oper # Y = A | oper # Y = A ^ oper # Y = A + oper # Y = A - oper # RAM[oper] = oper; Y = A # if (A <= 0) PC = hi(PC)|oper 18 # OUT = oper # OUT = A & oper # OUT = A | oper # OUT = A ^ oper # OUT = A + oper # OUT = A - oper # RAM[oper] = oper # if (A >= 0) PC = hi(PC)|oper 1c # OUT = oper; X++ # OUT = A & oper; X++ # OUT = A | oper; X++ # OUT = A ^ oper; X++ # OUT = A + oper; X++ # OUT = A - oper; X++ # RAM[(Y>>8)|X++] = oper # PC = hi(PC)|oper 01 # A = RAM[oper] # A &= RAM[oper] # A |= RAM[oper] # A ^= RAM[oper] # A += RAM[oper] # A -= RAM[oper] # RAM[oper] = undef # PC = (Y>>8)|RAM[oper] 05 # A = RAM[X] # A &= RAM[X] # A |= RAM[X] # A ^= RAM[X] # A += RAM[X] # A -= RAM[X] # RAM[X] = undef # if (A < 0) PC = hi(PC)|RAM[oper] 09 # A = RAM[(Y>>8)|oper] # A &= RAM[(Y>>8)|oper] # A |= RAM[(Y>>8)|oper] # A ^= RAM[(Y>>8)|oper] # A += RAM[(Y>>8)|oper] # A -= RAM[(Y>>8)|oper] # RAM[(Y>>8)|oper] = undef # if (A > 0) PC = hi(PC)|RAM[oper] 0d # A = RAM[(Y>>8)|X] # A &= RAM[(Y>>8)|X] # A |= RAM[(Y>>8)|X] # A ^= RAM[(Y>>8)|X] # A += RAM[(Y>>8)|X] # A -= RAM[(Y>>8)|X] # RAM[(Y>>8)|X] = undef # if (A != 0) PC = hi(PC)|RAM[oper] 11 # X = RAM[oper] # X = A & RAM[oper] # X = A | RAM[oper] # X = A ^ RAM[oper] # X = A + RAM[oper] # X = A - RAM[oper] # RAM[oper] = undef; X = A # if (A == 0) PC = hi(PC)|RAM[oper] 15 # Y = RAM[oper] # Y = A & RAM[oper] # Y = A | RAM[oper] # Y = A ^ RAM[oper] # Y = A + RAM[oper] # Y = A - RAM[oper] # RAM[oper] = undef; Y = A # if (A <= 0) PC = hi(PC)|RAM[oper] 19 # OUT = RAM[oper] # OUT = A & RAM[oper] # OUT = A | RAM[oper] # OUT = A ^ RAM[oper] # OUT = A + RAM[oper] # OUT = A - RAM[oper] # RAM[oper] = undef # if (A >= 0) PC = hi(PC)|RAM[oper] 1d # OUT = RAM[(Y>>8)|X++] # OUT = A & RAM[(Y>>8)|X++] # OUT = A | RAM[(Y>>8)|X++] # OUT = A ^ RAM[(Y>>8)|X++] # OUT = A + RAM[(Y>>8)|X++] # OUT = A - RAM[(Y>>8)|X++] # RAM[(Y>>8)|X++] = undef # PC = hi(PC)|RAM[oper] 02 # /*nop*/ # /*nop*/ # /*nop*/ # A = 0 # A *= 2 # A = 0 # RAM[oper] = A # PC = (Y>>8)|A 06 # /*nop*/ # /*nop*/ # /*nop*/ # A = 0 # A *= 2 # A = 0 # RAM[X] = A # if (A < 0) PC = hi(PC)|A 0a # /*nop*/ # /*nop*/ # /*nop*/ # A = 0 # A *= 2 # A = 0 # RAM[(Y>>8)|oper] = A # if (A > 0) PC = hi(PC)|A 0e # /*nop*/ # /*nop*/ # /*nop*/ # A = 0 # A *= 2 # A = 0 # RAM[(Y>>8)|X] = A # if (A != 0) PC = hi(PC)|A 12 # X = A # X = A # X = A # X = 0 # X = 2*A # X = 0 # RAM[oper] = A; X = A # if (A == 0) PC = hi(PC)|A 16 # Y = A # Y = A # Y = A # Y = 0 # Y = 2*A # Y = 0 # RAM[oper] = A; Y = A # if (A <= 0) PC = hi(PC)|A 1a # OUT = A # OUT = A # OUT = A # OUT = 0 # OUT = 2*A # OUT = 0 # RAM[oper] = A # if (A >= 0) PC = hi(PC)|A 1e # OUT = A; X++ # OUT = A; X++ # OUT = A; X++ # OUT = 0; X++ # OUT = 2*A; X++ # OUT = 0; X++ # RAM[(Y>>8)|X++] = A # PC = hi(PC)|A 03 # A = IN # A &= IN # A |= IN # A ^= IN # A += IN # A -= IN # RAM[oper] = IN # PC = (Y>>8)|IN 07 # A = IN # A &= IN # A |= IN # A ^= IN # A += IN # A -= IN # RAM[X] = IN # if (A < 0) PC = hi(PC)|IN 0b # A = IN # A &= IN # A |= IN # A ^= IN # A += IN # A -= IN # RAM[(Y>>8)|oper] = IN # if (A > 0) PC = hi(PC)|IN 0f # A = IN # A &= IN # A |= IN # A ^= IN # A += IN # A -= IN # RAM[(Y>>8)|X] = IN # if (A != 0) PC = hi(PC)|IN 13 # X = IN # X = A & IN # X = A | IN # X = A ^ IN # X = A + IN # X = A - IN # RAM[oper] = IN; X = A # if (A == 0) PC = hi(PC)|IN 17 # Y = IN # Y = A & IN # Y = A | IN # Y = A ^ IN # Y = A + IN # Y = A - IN # RAM[oper] = IN; Y = A # if (A <= 0) PC = hi(PC)|IN 1b # OUT = IN # OUT = A & IN # OUT = A | IN # OUT = A ^ IN # OUT = A + IN # OUT = A - IN # RAM[oper] = IN # if (A >= 0) PC = hi(PC)|IN 1f # OUT = IN; X++ # OUT = A & IN; X++ # OUT = A | IN; X++ # OUT = A ^ IN; X++ # OUT = A + IN; X++ # OUT = A - IN; X++ # RAM[(Y>>8)|X++] = IN # PC = hi(PC)|IN 次に、どの命令が実際に使用されているかを調べるプログラムを作成し、theloop.asmファイルを解析しました。その結果、以下の出力が得られました。最初の列は16進数の命令番号、2番目の列はその命令がファイル内で言及された回数、3番目の列は擬似C言語コード、最後の列はファイル内で使用されているニーモニックです。$00 はオペランドを表します。 inst # pseudo-C mnemonic ------------------------------------------------------------- 02 586: /*nop*/ // nop 00 54305: A = oper // ld $00 01 505: A = RAM[oper] // ld [$00] 03 1: A = IN // ld in 05 26: A = RAM[X] // ld [x] 09 2: A = RAM[(Y<<8)|oper] // ld [y,$00] 0d 32: A = RAM[(Y<<8)|X] // ld [y,x] 10 1: X = oper // ld $00,x 11 27: X = RAM[oper] // ld [$00],x 12 11: X = A // ld ac,x 14 326: Y = oper // ld $00,y 15 19: Y = RAM[oper] // ld [$00],y 16 2: Y = A // ld ac,y 18 14: OUT = oper // ld $00,out 19 6: OUT = RAM[oper] // ld [$00],out 20 33: A &= oper // anda $00 21 8: A &= RAM[oper] // anda [$00] 25 2: A &= RAM[X] // anda [x] 29 2: A &= RAM[(Y<<8)|oper] // anda [y,$00] 30 9: X = A & oper // anda $00,x 40 14: A |= oper // ora $00 41 17: A |= RAM[oper] // ora [$00] 45 3: A |= RAM[X] // ora [x] 50 6: X = A | oper // ora $00,x 5d 3: OUT = A | RAM[(Y<<8)|X++] // ora [y,x++],out 60 16: A ^= oper // xora $bf 61 11: A ^= RAM[oper] // xora [$00] 69 5: A ^= RAM[(Y<<8)|oper] // xora [y,$00] 80 402: A += oper // adda $00 81 28: A += RAM[oper] // adda [$00] 82 36: A *= 2 // adda ac 85 2: A += RAM[X] // adda [x] 89 6: A += RAM[(Y<<8)|oper] // adda [y,$00] 8d 4: A += RAM[(Y<<8)|X] // adda [y,x] 90 11: X = A + oper // adda $00,x 91 1: X = A + RAM[oper] // adda [$00],x 92 2: X = 2*A // adda ac,x 95 1