TTL でCPUを作成、16bitの手作りコンピューター TANACOM-1 誕生

命令

TANACOM-1の命令セット



TANACOM-1 の命令は、16bit固定長です。

メモリ参照命令系


15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 OP Code R1/
R0
Ix Id M/
im
Address or  immediate


OP Code ニーモニック 命  令 動    作
  0 0 0 L  Load Rx  Rx ← □
  0 0 1 ST  Store Rx  Rx → □
  0 1 0 A  Add Rx  Rx ← Rx + □
  0 1 1 IA  If Add Rx  Rx ← Rx + □  ( もしR1のLSB=1ならば )
  1 0 0 S  Subtrect Rx  Rx ← Rx - □
  1 0 1 N  And Rx  Rx ← Rx AND  □
  1 1 0 X  Xor Rx  Rx ← Rx XOR □
  1 1 1 C  Compare Rx  Rx - □ ( 比較する )

 1.レジスタの指定
 R1/R0   0=R0 , 1=R1

 2.アドレッシング
 TANACOM-1は、ページアドレッシング方式を採用している。
 1ページの大きさは、256 wordである。
指示内容 オペランド対象(□)となる実アドレス
無指定  ページベース値 + Address
Ix  = 1  ページベース値 + Address + R1  ・・・インデックス方式
Id  = 1 ( ページベース値+Address ) の値が実アドレス  ・・・間接方式
Ix  = 1、Id  = 1 ( ページベース値+Address )の値 + R1 が実アドレス・・・間接インデックス方式


 3.メモリ参照か即値データ

 M/im   1=メモリ参照方式 , 0=即値データ方式( immediateそのものをデータとする)



 4.コンディション・フラグへの反映について

メモリ参照系命令に於いて、メモリ参照か即値かに関わらず、ロード( L )とストア( ST )を除く、残り6つの命令の実行後の結果について、コンディション・フラグへの反映をされます。
但し、I/O空間( 0x8000 ~ 0xFFFF)に対するロード( L )命令が実行された場合に限り、ロードした結果について、コンディション・フラグへの反映をされます(当初設計時では、そうではなかったのですが、後日改良しました)。

Branch命令系


15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1 OP Code CNT Ix Id C/
Z
Address


OP Code ニーモニック 命  令 動    作
  0 0 0 B  Branch  指定されたアドレスにジャンプ
  0 0 1 BAL  Branch And Link  PC値をR1に待避して、指定されたアドレスにジャンプ
  0 1 0 BNZ  Branch Non Zero  コンディションフラグ ZERO=0 ならば、ジャンプ
  0 1 1 BNM  Branch Non Minus  〃    MINUS=0 ならば、ジャンプ
  1 0 0 BNP  Branch Non Plus  〃    PLUS=0 ならば、ジャンプ
  1 0 1 BZ  Branch Zero  〃    ZERO=1 ならば、ジャンプ
  1 1 0 BC  Branch Carry  〃    CARRY=1 ならば、ジャンプ
 注.PLUS=1 とは、MSBが0で、かつALL Zeroでない事を意味する

 1.CNT指定
 CNT  0=そのままジャンプを継続
 1=CNTが非0ならば、CNTを+1して、ジャンプを実施( 0なら何もしない )
注.CNTは8bitカウンタなので、255に+1の時点で、桁溢れして結果0となる。

 2.アドレッシング

   上記メモリ参照命令と同様

 3.ページベースの指示
C / Z  1=カレントページを指定  , 0=ゼロページを指定

  注.ゼロページとは、メモリ上の 0x0000 ~ 0x00FF 番地の256wordを意味します。
  注.ゼロページ直接の場合、アドレス修飾(IxやId)は無効となります、注意してください。


コントロール命令系


  • Shift Right
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1 1 1 1 OP Code R0 1/
0
Arth Carry R1 1/
0
Arth Carry

OP Code ニーモニック 命  令 動    作
0 1 0 1 SR  Shift Right  指定したレジスタ(上記R0、R1に1が立ったもの)を、右に1bitシフト
 その際、MSBより何をいれるのかを1/0、Arth、Carryで指定可。
 Arthとは、MSBを引き継ぎながらシフトすること、算術的シフト。
 R0とR1同時指定の場合は連結され、R0のLSBもR1のMSBに入っていく。

  • Shift Left
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1 1 1 1 OP Code R0 1/
0
MSB - R1 1/
0
Sin Carry

OP Code ニーモニック 命  令 動    作
0 1 1 0 SL  Shift Left  指定したレジスタ(上記R0、R1に1が立ったもの)を、左に1bitシフト
 その際、LSBより何をいれるのかを1/0、MSB、Sin、Carryで指定可。
 MSB指定あればローテートすることになる。
 Sinとは、シリアル入力からのデータを取り込む。
 R0とR1同時指定の場合は連結され、R1のMSBもR0のLSBに入っていく。

  • ループ専用カウンタ
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1 1 1 1 OP Code Count Data

OP Code ニーモニック 命  令 動    作
0 1 1 1 CNT  Count Set  CNTにCount Dataをセットする

  • Set Timer
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1 1 1 1 OP Code - - - - Timer Code

OP Code ニーモニック 命  令 動    作
1 0 1 0 STM  Set Timer Code  インターバルタイマーにタイマーコードをセットする
 タイマーカウンタとタイマーフラグはこの時リセットされる。
 割込許可フラグがセットされておれば指定時間後に割込がかかる
  TimerCode 時間 TimerCode 時間  
  0000 100μS 0111 500mS  
  0001 500μS 1000 1S  
  0010 1mS 1001 5S  
  0011 5mS 1010 10S  
  0100 10mS 1011 50S  
  0101 50mS 1100 100S  
  0110 100mS 1111 マスク  
 

  • その他のコントロール
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1 1 1 1 OP Code - - - - - - - -

OP Code ニーモニック 命  令 動    作
0 0 0 0 NOP  No Operation  なにもしない
0 0 0 1 HALT  Halt  CPU停止
0 0 1 1 MOV  Move R1,R0  R0の内容を、R1にコピー
0 1 0 0 LSW  Load Switch  SWRの値をR0に読み込む
1 0 0 0 SE  Set Enable  割込許可フラグをセットする
1 0 0 1 RE  Reset Enable  割込許可フラグをリセットする
1 1 0 0 FLG  Flag Out  R0のMSBを、シリアル出力FLGに出力する



以上、 26命令


このCPUで工夫した点

掛け算、割り算をスピードアップ

TANACOM-1には、ALU ( Arithmetic and Logic Unit、算術論理演算装置 ) として、SN74181を採用しており、16bitの加算、減算は、ハードウェア的に出来ます。
しかし、掛け算、割り算は、その機構を持たないので、ソフトウェアで行うしかありません。
私は、とにかく、この「掛け算、割り算」のスピードを上げたかったのです。
それは、より短いステップ数でその演算が出来れば良いのです。
そこで私は、命令に下記のような工夫をしました。

掛け算において

TANACOM-1において、メモリ上のa番地の値とb番地の値を掛け、答えをc番地に入れるプログラムは、下記のように書きます。
16bit×16bitの積は32bitになります。但し、あくまでも使用する数値は16bitにしたいので、答えの上位16bitは捨て下位16bitのみ採用します。

      L    0,0 ; R0をゼロにする
      L    1,b ; R1にb番地の値を
      CNT  0x0F1 ; 16回ループする値をカウンタにセット
Loop  IA   0,a ; R1のLSBが1であれば、R0にa番地を加算
      SR   R0.Carry.R1 ; Carry-R0-R1右に1bitシフト 
      B_cnt Loop ; カウンタが回りきるまでジャンプ
      ST   1,c ; 積をc番地に格納
      HALT ; 停止

掛け算では、おなじ計算を16回ループさせるのですが、ここで登場するのが「ループ専用カウンタ」です。
TANACOM-1には、8bit長のカウンタ ( SN74161 x 2 ) 1個を持ち、ここに1~255の数値をセット出来ます。
これが1つ目の工夫、CNT命令です。

これとセットで使用するのが、2つ目の工夫、B_cnt命令です。
これは「カウンタを調べ、0ならば、何もしない。非0ならば、カウンタを+1してから、ジャンプを実行する」という働きをします。
カウンタは、8bitしかないので、255の時点でカウントアップされると、桁溢れしてオール0に戻ってくれます。
これらを使う事で、本来であれば、R0やR1にある計算途中の数値をどこか待避させ、ループ役の変数を更新し16回まわったかを判断させるステップが必要なのですが、R0やR1にさわる事なく、それらが出来るのが、「CNTとB_cnt命令」のセットなのです。

3つ目の工夫は、IA( if-ADD )命令です。
掛け算の中で、「桁送りをしながら、R1のLSB( 最下位bit )が 1 だったら、R0にb番地の値を加える」という作業があるのですが、それを1ステップでやるのが、この「IA命令」なのです。文字通り「イフ-アッド、もし~だったら足せ」です。
しかし、この「IA命令」を増設するために、「OR命令」オア(論理和)命令を削ってしまいました。
前記命令セットの表を見ていただけると解りますが、TANACOM-1には何と「OR命令」が存在しないのです(ORは、ANDと加算の組み合わせで、代替出来るので、良し、としました)。

4つ目の工夫は、シフト命令にあります。
上記の「SR R0.Carry.R1」とは、手前の加算演算での「桁上がり」を示すCarryフラグをR0のMSB( 最上位bit )に入れ、R0のLSB( 最下位bit )をR1のMSBに入れながら、R0R1を同時に右へ1bitシフトさせる事を1ステップでやるのがこの命令です。

これら4つの工夫により、掛け算プログラムのステップ数は大幅に減り、スピードは約2倍になり、およそ52μSで掛け算が出来るようになりました。

割り算において

TANACOM-1において、メモリ上のa番地の値をb番地の値で割り、商をc番地に、余りをd番地に入れるプログラムは、下記のように書きます。
割り算は、32bit÷16bitとし、答えは商16bitおよび余り16bitになります。
被除数自身は16bitですが、上位16bitがオール0である32bitとして計算開始します。

      L    1,a ; R1にa番地の値を
      L    0,0 ; R0をゼロにする
      CNT  0x0F0 ; 17回ループする値をカウンタにセット
Loop  C    0,b ; R0とb番地を比較
      BZ   J1 ; ゼロであればJ1にジャンプ
      BNP  J2 ; 正でなければJ2にジャンプ
J1    S    0,b ; R0からb番地を引く 
J2    SL   R0.R1.Carry ; R0-R1-Carry左に1bitシフト
      B_cnt Loop ; カウンタが回りきるまでジャンプ
      SR   R0 ; 行き過ぎを戻し
      ST   0,d ; 余りR0をd番地に格納
      ST   1,c ; 商R1をc番地に格納
      HALT ; 停止

5つ目の工夫は、シフト命令にあります。
上記の「SL R0.R1.Carry」とは、手前の減算演算での「桁下がり、ボロー」を示すCarryフラグをR1のLSB( 最下位bit )に入れ、R1のMSB( 最上位bit )を、R0のLSB( 最下位bit )に入れながら、R0R1を同時に左へ1bitシフトさせる事を1ステップでやるのがこの命令です。

この工夫と、先の「CNTとB_cnt命令」の組み合わせにより、割り算プログラムのステップ数も大幅に減り、スピードは約1.5倍になり、およそ110μSで割り算が出来るようになりました。

簡易UARTの仕組みを実装

TANACOM-1本体が完成して間もない頃、TANACOM-1には何の入出力装置も存在していませんでした(キャラクタディスプレーもまだ先です)。
構想としては、IOボックスを作り、それにコントローラー回路を組み込み、入出力(キーボード、シリアルイン、シリアルアウト、Beepスピーカー等)を行う計画でした。
しかし、実現にはまだまだ時間が掛かる状況でした。
このままでは、書き込んだプログラムを保存する手段すら存在しません。

電源を入れるたびに、毎回すべてのプログラムは、SWR( フロントパネルにあるスイッチ )でパチパチと入力しなければなりません。
当時、プログラムの保存には、オーディオカセットテープレコーダーを使うのが主流でした。
「あ~TANACOM-1にも、まずはカセットインターフェースが必要だ。でも、IOボックスはいつになったら完成するやら」と嘆いているとふと気づきました。

汎用レジスタのR0、R1には、両方ともシフトレジスタであるSN74198を使っています。
この機能を利用しない手はありません。
さっそく、回路変更を考え、命令自身も改造しました。

  • シリアルアウト機能
    R0のMSB( 最上位bit )の状態をSN7474を使って記憶させ、これを「FLG」と
    命名しました( UARTでいうTx )。
    そして、FLG専用命令を増設しました。
    FLGの出力は、簡単なレベル変換をしてアナログ化し、イヤホンジャック( OUT )
    から出します。

  • シリアルイン機能
    イヤホンジャック( IN )を設置し、オーディオ信号を入れます。
    それをトランジスタを使った簡単な復調回路を通し、0か1の信号に替えR1のLSB
    ( 最下位bit )に接続し、左シフト命令で取り込ませるのです( UARTでいうRx )。


この仕組みを作った事により、TANACOM-1にシリアル入力、シリアル出力を持つ事が出来て、ほどなくカセットインターフェースが完成しました。
そこから先、カセットインターフェースを通じて、作ったプログラムのLOADとSAVEが出来るようになり、飛躍的に進歩したのです。



powered by Quick Homepage Maker 5.3
based on PukiWiki 1.4.7 License is GPL. QHM

最新の更新 RSS  Valid XHTML 1.0 Transitional