IM6100

Intersil社はアナログデジタル混在のCMOSプロセスICで有名で、積分型A/DコンバータICを代表としたCMOS ICを製造しています。そのIntersil社が1970年代に開発したマイクロプロセッサがIM6100です。
IM6100はDEC社のPDP-8/Eをワンチップに納めたような12 bitマイクロプロセッサでCMOSプロセスで製造されています。12 bit幅の語長のマイクロプロセッサは少ない品種しか存在しません。しかし、アルファベット大文字と数字と記号文字と少数のコントロールコードなら充分に6 bit幅で表現可能な64種の値で表現可能で1語に2文字を格納できますし、1語が8 bitだと1語で1命令の固定長命令セットは実現しにくいですが12 bitあれば固定長命令セットを採用して命令解釈実行回路を簡略化しやすいうえ、なによりアナログ計測データの扱いに適しているという特徴もあります。
アナログ信号をデジタル化して計測や制御を行う場合、12 bit精度で扱われること一般的です。8 bit精度だと有効数字2桁と符号程度の表現しかできませんが、12 bit精度なら有効数字3桁分と符号ビットとさらに1 bitほど、つまり約6 dB分の余裕が残ります。
その値に何らかの処理をして表示したり制御に利用する場合、8 bitプロセッサだと2回に分けて処理を行わなくてはならず、プログラムが長くなりがちです。DEC社のPDP-8が広く使われた1970年頃は1 bitあたりのメモリ単価が100円前後という状況ですから、演算回路の規模を押さえた8 bitプロセッサで低価格の制御用コンピュータを実現しようとしても、その結果プログラムが長くなるとそれを格納するメモリ価格が無視できません。16 bitプロセッサはプログラム処理のことを考えれば強力なのは理解できますが、プロセッサ自身の回路規模が大きくなります。そのため、アナログ計測値を用いて低コストで自動制御を実現するためのコンピュータとして、12 bitプロセッサが重要な選択肢として存在していました。PDP-8は1965年の発売時から低価格ということで工場でのプロセス制御用や実験室での自動計測用に普及しました。
Intelsil社が自社のCMOS A/Dコンバータなどと併用して自動制御を行うのに、得意なCMOSプロセスを用いたマイクロプロセッサを開発するのは当然の動きでした。CMOSプロセスはまだn-MOSプロセスほどの集積度を実現できませんから、回路規模は小さく限定しなくてはなりません。そのため、12 bitアーキテクチャが選ばれたのだと思われます。PDP-8と同一の命令体系にすることによって、過去のソフトウェア資産の流用も容易でしょう。
IM6100の実物は普通の40ピンパッケージに納められていて、特に珍しくはありません。

IM6100
IM6100CCPLで、鈴木様よりの頂きものです。

しかし、そのアーキテクチャは初期のミニコンピュータの、できる限り単純な回路でそれなりの性能を引き出そうとするための、最近のマイクロプロセッサには見られない特徴が多く存在します。

IM6100には最高クロック周波数の点で3種類のバージョンがあります。IM6100は5 V動作で最高クロック周波数4 MHzで、IM6100Aは10 V動作可能でその場合に最高クロック周波数8 MHz、IM6100Cは5 V動作で最高クロック周波数3.3 MHzとなっています。内部回路はスタティック設計となっていますので、クロック周波数を低くする方は自由で停止することも可能です。

IM6100のプログラマから見たレジスタモデルはこのようになっています。
IM6100 registers

なんというか、非常にシンプルなレジスタセットとなっています。レジスタや命令のビット番号の割り当ては、ミニコンピュータでよく見られた最上位ビット(MSB)が0で最下位ビット(LSB)が11という形式になっているのに注意してください。プログラマが意図的に操作できるレジスタは12 bitレジスタが3本に1 bitのフラグが2個だけです。
ACはアキュムレータで演算の中心となります。基本的にアキュムレータとメモリの間で演算が行われます。MQはテンポラリレジスタで、アキュムレータの内容を一時退避したりするためのレジスタです。
PCはプログラムカウンタで、やはり12 bit幅となっています。このことからわかるように、特にメモリ拡張ハードウエアを用意しない場合にはIM6100のメモリ空間は12 bitで指示できる4096語のサイズです。
Lはリンクフラグで、シフト・ローテート命令の際にACと接続して使用したり、加減算のキャリーが入ります。一般的なマイクロプロセッサではキャリーと呼ばれているフラグですね。
IEは割り込みイネーブルフラグです。割り込みを用いた入出力時に操作する場合があります。

インデックスレジスタやスタックポインタの類が見当たりません。IM6100ではサブルーチン呼び出しはスタックを使わない方式となっています。また、メモリ間接アドレッシングが扱えるので、インデックスレジスタやユーザプログラムによるスタックデータ構造はメモリ上に確保したポインタを利用します。

次にメモリ構成ですが、メモリ拡張ハードウエアを使用しない場合4096語が全アドレス空間になりますが、この4096語は128語を1ページとする32ページに分割されています。実行中の命令が存在するページをカレントページと呼び、32ページ中の先頭の(アドレスの小さな)ページを普通に0ページと呼びます。メモリ参照命令では、0ページかカレントページのどちらかについて、直接参照、あるいは間接参照を行うことができるようになっています。0ページについては全メモリ空間の任意の位置の命令から参照できますから、ここをスクラッチパッドレジスタやひんぱんに使用されるグローバル変数として使用すれば、プログラムの短縮につながります。
なお、0ページの08Hから0FHまでの8語に対する間接参照については、自動的にプリインクリメントされます。つまり、このアドレス範囲のメモリをポインタとして使用すると、メモリ内容の検索やコピーが容易になります。
なお、標準的なメモリ拡張ハードウエアが存在する場合も以上の内容にはかわりありませんが、4096語の全体がフィールドと呼ばれる単位で管理され、システムで参照できるアドレス空間は8フィールドから構成されます。つまり32 K語までのアドレス拡張が行われます。
入出力機器のアドレス空間はメモリとは別に存在し、最大64種の入出力機器を利用できます。

では命令体系に取り組みましょう。
IM6100の命令は、6種のメモリ参照命令、3種の演算(OPR)命令、1種の入出力転送(IOT)命令から構成されます。すべて1語命令です。メモリ参照命令はアキュムレータかプログラムカウンタとメモリの間で何かを実行する命令です。OPR命令は内部レジスタに対する演算を実行する命令で、IOT命令は入出力機器とのデータ転送を行う命令です。たった10種の命令なのですが、OPR命令にはそれぞれ演算操作を指示するビットが複数存在し、その組み合わせによって多様なアキュムレータに対する演算を指示できます。IOT命令はプロセッサ側では1種類だけの命令で、デバイスアドレスと動作指定コードを外部に出力するだけの命令ですが、入出力機器側からプロセッサに対し特別な制御信号を与えることによって実際の入出力動作を行いますので、多様な入出力動作が可能となっています。
この命令種別はオペコードの上位3 bitによって明確に区分されていて、その3 bitが0 - 5までがメモリ参照命令、6がIOT命令、7がOPR命令です。

まずはメモリ参照命令で、オペコードは一般的に次のような形式となっています。
0  1  2  3  4  5  6  7  8  9  10  11
Op Op Op IA MP A5 A6 A7 A8 A9 A10 A11
ビット0 - 2の上位3 bitは、すでに述べたように命令種別を表します。逆に下位のビット5 - 11の7 bitはページ内アドレスオフセットを意味します。IM6100は128語が1ページとなり、語単位でアドレスが割り振られていますから、7 bitでページ内オフセットを表現できます。ビット4のMPはメモリページの略で、このビットが0なら0ページを参照、1ならカレントページを参照という意味となります。ビット3のIAは間接アドレッシングビットで、このビットが0なら直接アドレッシング、1なら間接アドレッシングとなります。0ページの08Hから0FHまでの8語に対する間接アドレッシングについては、プリインクリメントが行われます。つまり、間接参照を行う前に1だけ加算されて書き戻され、その加算後のアドレスを用いて参照が行われます。
具体的に考えると、Op部がすべて0の命令はAND命令ですが、000Hという命令なら、オペランドは0ページのアドレス0に格納された値となります。082HならMPが1ですからカレントページのオフセット2の内容がオペランドで、123Hなら0ページのアドレス23Hに納められているアドレスによって指されたメモリの内容がオペランドとなります。108Hというオペコードで、アドレス008Hのメモリの内容が234Hだったとしたら、アドレス008Hの内容が235Hに書き換えられて、アドレス235Hのメモリの内容が取り出されてオペランドとなります。
具体的な命令表はこのようになっています。
Mne.      Code        Cycles   動作
AND  000I PAAA AAAA  10/15/16  (AC) <- (AC) & (Op)
TAD  001I PAAA AAAA  10/15/16  (AC) <- (AC) + (Op)
ISZ  010I PAAA AAAA  16/21/22  (Op)++; If (Op) == 0, (PC)++
DCA  011I PAAA AAAA  11/16/17  (Op) <- (AC); (AC) <- 0
JMS  100I PAAA AAAA  11/16/17  (Op) <- (PC), (PC) <- Op + 1
JMP  101I PAAA AAAA  10/15/16  (PC) <- Op
Mne.は命令ニーモニックで、Codeは2進数で表示したオペコードです。ただしIは間接アドレッシングビット、Pはメモリページビット、Aはページ内オフセットを意味します。Cyclesは命令実行サイクル数で、3種類の数値が並んでいます。Iが0の直接アドレッシングの場合が左、Iが1の間接アドレッシングの場合が中央、間接アドレッシングでもプリインクリメント付きのものなら右のサイクル数が適用されます。4 MHzクロックのIM6100の場合、1サイクルは500 nsとなります。3.3 MHzクロックなら600 nsです。動作の欄は簡単に命令動作を示しています。ここでOpはメモリオペランドアドレスを意味します。
AND命令はACとオペランドの論理積を行う命令で、TAD命令はACとオペランドのバイナリ加算命令です。
ISZ命令はIncrement and Skip if Zeroの略で、オペランドをインクリメントして、その結果が0なら直後の命令をスキップする命令です。ループ制御などに使えますね。
DCA命令はDeposit and Clear the ACの略で、オペランドの位置にACの内容を格納した後、ACを0クリアします。
JMS命令はJump to Subroutineの略で、サブルーチン呼び出し、JMP命令はジャンプ命令ですね。
これらのメモリ参照命令を眺めると、思い切った命令の省略が行われていることに気づくと思います。AND命令はあってもOR命令は存在しません。加算はあっても減算はありません。DCA命令でストアはできてもロードする命令はありません。OR演算はOPR命令の中にACとMQのORがありますし、減算はOPR命令の中にACの2の補数を求める命令があるので、加算命令と組み合わせれば可能となります。しかし、ロード命令が存在しないというのはずいぶんと思い切ったものです。
ACにメモリの内容をロードできないようだと、まともなプログラムを書けそうにありません。それを解決する鍵がストアを行うDCA命令です。DCA命令はメモリにACの内容を書き込んだ後、ACを0クリアするという変わった仕様になっています。この0になったACにTAD命令でメモリの内容を加算すれば、メモリの内容がそのままACに格納されたことになります。そもそも、ACにメモリの内容をロードする場合、それまでのACの内容が上書きされて消えてしまいます。ACには、それまでの演算結果が入っているはずで、普通なら演算結果が消えてしまうのは困るため、メモリに保存してから別の値をロードするのが普通でしょう。つまりストアとロードは連続して使用する場面が多いと考えられます。それならTAD命令でロードの代用を行える、このDCA命令の仕様と割り切りは見事なものです。ただ、一連の計算の途中結果を後で使用するためにメモリに保存しておき、さらにACに対しての演算を行うようなことはできなくなります。こんな場合はいちいちACの内容をMQレジスタに退避させたりする必要があります。逆に、条件判定のためにACの内容を使用し、そのままACにメモリのデータをロードしたい場合、DCA命令がロードの直前に存在しない場合があります。このような場合、OPR命令でACの内容を0クリアする必要があります。
このように、IM6100というかPDP-8の命令体系は判じ物的な、一見奇妙な定石のようなテクニックを多用しないとプログラミングできない傾向が見られます。しかし、PDP-8のアーキテクチャが開発されたのは1965年です。初期のICを利用できるかどうかという時代で、1ゲートあたりのコストが千円以上といった頃に低価格コンピュータを実現しなければならなかったわけで、多様な命令を実装できるはずもありません。いかに単純な少数の命令で、それなりのプログラムを書けるようなアーキテクチャを設計するか、その挑戦の成果が、このような命令の割り切りに出たわけです。
サブルーチン呼び出しも変わった形式となっています。オペランドで指定されたサブルーチンの先頭アドレスに戻りアドレスを格納し、PCにはサブルーチンの先頭ではなく、その次のアドレスが書きこまれます。つまり、実際のサブルーチンのコードは指示されたアドレスの次のアドレスから始まるのです。こうすることによって、スタックポインタが存在しないIM6100で、サブルーチンを実現しているわけです。サブルーチンから戻るには、サブルーチンの先頭アドレスを間接参照するJMP命令を使用します。このような方式なので、そのままでは再帰可能なサブルーチンとはなりません。サブルーチンの先頭とリターンする場所が同一のページに存在しないと、何らかの対応策をプログラミングしない限りカレントページ内の間接参照JMP命令が使えませんから、面倒なことになります。なにより、このような方式ではプログラムをROM化できません。なにしろ、サブルーチンの先頭部分は書き込み可能でなくてはならないのですから。
もっともPDP-8開発時にはこれらはそれほどの問題ではありませんでした。もともと小さなプログラムを動かすための小型コンピュータで、ビット単価が数百円の時代でメモリもそれほど実装できませんから、サブルーチンが1ページに納まる方が普通でしょう。当時の高級言語はFORTRANやCOBOLで再帰呼出しなどできませんでしたし、アセンブリ言語によるプログラミングテクニックとしてもほとんど使われていませんでした。しかも、当時の一般的なメモリはコアメモリで、不揮発性で書き換え可能というメモリでした。磁気的に記憶するため、電源を切断しても内容は消えませんし、コンピュータプログラムから自由に書き換え可能ですから、ROM代わりにアプリケーションプログラムを格納したまま電源を切断しておけば、次の日に電源を投入してそのままメモリに残されたプログラムを実行することができます。自然とターンキーシステムになってしまうのです。書き換え可能なので、PDP-8方式のサブルーチン呼び出しでも別に問題にはなりません。
IM6100の場合には、時代的にコアメモリを採用しにくいでしょうから、プログラムのROM化ができないのでは困ります。詳細は後で触れますが、IM6100には制御パネルメモリ空間が存在し、その制御パネルメモリ空間の小さなブートストラップローダによって同じ制御パネルメモリ空間内のROMからメインメモリにプログラムを自動的にコピーすることができます。そのようにして、メインメモリが揮発性の一般的な半導体RWMで構成されていても、ROMに格納されたアプリケーションプログラムを実行できます。

OPR命令は命令コードの上位3 bitが7であるような命令で、主に内部レジスタの間の演算に用いられます。
0 1 2 3 4 5 6 7 8 9 10 11
1 1 1 a * * * * * *  *  b
上の命令コードのビットパターンのaとbの値によって、3種類のグループ命令に分類されます。残りの*のビットで、どのような演算を行うかが決められます。個々の*のビットにはそれぞれマイクロ命令が割り当てられています。そのマイクロ命令を組み合わせることによって、多数の演算を実行できるようになっています。たとえば、ACを反転させるマイクロ命令とACをインクリメントさせるマイクロ命令のビットを1にすれば、ACの内容の2の補数を求められます。
 
a b グループ
0 - グループ1(ACとLの操作)
1 0 グループ2(条件スキップ)
1 1 グループ3(ACとMQの操作)

グループ1マイクロ命令フォーマットは次のようになっています。
0 1 2 3  4   5   6   7     8       9     10  11
1 1 1 0 CLA CLL CMA CML RAR/RTR RAL/RTL SEL IAC
ここで、各ビットはこのような演算を表します。
CLA Clear AC
CLL Clear Link
CMA Complement AC
CML Complement Link
RAR Rotate AC Right
RTR Rotate Two Right
RAL Rotate AC Left
RTL Rotate Two Left
SEL ビット8, 9の役割を選択する
IAC Increment AC
CLAとCLLはそれぞれACとリンクフラグを0クリアする命令で、CMAとCMLは同じくビット反転させる命令です。
ビット8と9には2種類のマイクロ命令が割り当てられていますが、どちらが使われるか選択するのがビット10のSELビットです。このビットが0ならビット8, 9はそれぞれRAR, RAL命令に、1ならそれぞれRTR, RTL命令となります。なお、例外的にビット8, 9共に0でビット10が1の場合には、BSWマイクロ命令の意味になります。BSW命令はByte Swapの略で、ACの上下6 bitを入れ換えます。1文字を6 bitで表現しているので、 Byteといっても6 bit単位なんですよね。
RAR命令とRAL命令は、それぞれACのMSBとLSBの間にLフラグを入れて1 bit分の右回転ないし左回転させる命令です。RTR命令とRTL命令は、同じく右回転と左回転ですが2 bit分行うところが異なります。単純なシフト命令はありませんが、CLLマイクロ命令とRTR, RTL命令を併用すれば、0をつめていくシフト命令を実現できます。
IACはACを1だけインクリメントする命令です。
以上のマイクロ命令が複数選択されたときに実行される順序は決まっていて、このような優先順位に従います。
1 - CLA, CLL
2 - CMA, CML
3 - IAC
4 - RAR, RAL, RTR, RTL, BSW
したがって、CMAとIACをセットしておけば2の補数表示での符号反転ができて、CLAとRTLの組み合わせでLの内容をACのLSBに移動する命令となります。
このような合成命令も含めて、意味のありそうな命令には次のようなものがあり、中には新たにニーモニックが与えられているものもあります。
Mnemonic      Code     Cycles  動作
NOP      1110 0000 0000  10  No Operation
IAC      1110 0000 0001  10  Increment AC
RAL      1110 0000 0100  15  Rotate AC Left
RTL      1110 0000 0110  15  Rotate Two Left
RAR      1110 0000 1000  15  Rotate AC Right
RTR      1110 0000 1010  15  Rotate Two Right
BSW      1110 0000 0010  15  Byte Swap
CML      1110 0001 0000  10  Complement Link
CMA      1110 0010 0000  10  Complement AC
CIA      1110 0010 0001  10  Complement and Increment AC
CLL      1110 0100 0000  10  Clear Link
CLL RAL  1110 0100 0100  15  Clear Link, Rotate AC Left
CLL RTL  1110 0100 0110  15  Clear Link, Rotate Two Left
CLL RAR  1110 0100 1000  15  Clear Link, Rotate AC Left
CLL RTR  1110 0100 1010  15  Clear Link, Rotate Two Left
STL      1110 0101 0000  10  Set Link
CLA      1110 1000 0000  10  Clear AC
CLA IAC  1110 1000 0001  10  Clear AC, Increment AC
GLK      1110 1000 0100  15  Get Link
CLA CLL  1110 1100 0000  10  Clear AC and Link
STA      1110 1010 0000  10  Set AC
マイクロ命令のビットがひとつもセットされていなければ、マイクロ命令をひとつも実行しないわけですからNOP命令ということになります。
マイクロ命令単独の命令を飛ばすと、次はCIA命令ですね。CIA命令はACのビット反転後にインクリメントを行いますから、ACの2の補数を得る命令となります。これと加算命令を組み合わせれば、減算が可能になります。
CLLと組み合わせたローテート命令は、0をつめていくシフト命令として使えます。
STL命令は、一度Linkをクリアしてから反転させますから、Lに1をセットする命令となるわけです。
CLA IAC命令は、ACに1をロードする命令ですね。
GLK命令はLフラグをACのLSBに転送する命令です。結果的にLフラグはクリアされます。
CLA CLL命令はACとLを同時にクリアする命令です。
STA命令はACを0クリアしてから反転させますから、ACのすべてのビットが1になります。符号付き整数として考えれば-1なので、これと加算命令を組み合わせればデクリメントに使えるかもしれません。

グループ2マイクロ命令は、このようなビット割り当てが行われています。
0 1 2 3  4     5       6       7     8   9  10 11
1 1 1 1 CLA SMA/SPA SZA/SNA SNL/SZL SEL OSR HLT 0
ここで、各ビットの記号はこのような操作を表します。
CLA Clear AC
SMA Skip on Minus AC
SPA Skip on Positive AC
SZA Skip on Zero AC
SNA Skip on Non-zero AC
SNL Skip on Non-zero Link
SZL Skip on Zero Link
SEL ビット5, 6, 7の役割を選択する
OSR Or with Switch Register
HLT Halt
CLAはグループ1と共通でACを0クリアする命令です。
SMA, SPA, SZA, SNA, SNL, SZLはスキップ動作を指示するマイクロ命令で、それぞれACの内容が負、ACが正、ACが0、ACが0以外、Lが0以外、Lが0という条件でスキップします。条件が成立すると、この命令の次の命令をひとつ飛ばして、その先の命令を実行するわけです。
SELビットは条件の選択と複合条件の成立に関係するビットです。SELビットが0ならビット5, 6, 7はSMA, SZA, SNLの役割を果たし、1ならSPA, SNA, SZLの役割となります。また、SELビットが0の場合にビット5, 6, 7の複数が1となっていれば、条件のひとつが成立しただけでスキップが生じます。つまりOR条件となります。逆にSELビットが1だとAND条件となり、指定された条件のすべてが成立しないとスキップしません。こういったマイクロ命令の仕様により、多様な条件判定命令を実現できます。
OSRマイクロ命令はスキップ動作とは無関係で、スイッチレジスタを読み込んでACの内容とORした結果をACに入れる命令です。スイッチレジスタとは、ミニコンピュータタイプのコンピュータのコンソールパネルにある、メモリにデータを書き込むためのデータスイッチをモデル化したもので、このマイクロ命令の実行時に特別な信号がバスに出力されて、スイッチの状態が読み込まれるようになっています。IM6100では、そういったコンソールパネルの機能を制御パネルメモリ空間という特別なメモリ空間に配置したモニタプログラムで実装できるように工夫されていて、そのモニタプログラムで使用することもできますし、普通のプログラムの中で単純な入力ポートとして利用することもできるでしょう。
HLTマイクロ命令はプログラム実行を停止させる命令です。HLTと同時にスキップマイクロ命令やOSRマイクロ命令が指示されていると、それらの実行を終えてから停止します。
マイクロ命令間の優先順位は、次のようになっています。
1 - SMA or SZA or SNL / SPA and SNA and SZL
2 - CLA
3 - OSR, HLT
スキップ条件判定が最初に行われて、それからアキュムレータのクリアとOSRやHLTが続くわけですね。この順序ならCLAとOSRを組み合わせて、単にスイッチレジスタの内容をACにロードすることも可能です。また、スキップ判定を行ってからACを0にすることもできます。この組み合わせを使うと、次にTAD命令でACに別の値をロードできて効率的です。
そういったグループ2マイクロ命令の合成命令には、次のようなものがあります。
Mnemonic      Code     Cycles  動作
NOP      1111 0000 0000  10  No Operation
HLT      1111 0000 0010  10  Halt
OSR      1111 0000 0100  15  OR with Switch Register
SKP      1111 0000 1000  10  Skip (always)
SNL      1111 0001 0000  10  Skip on Non-zero Link
SZL      1111 0001 1000  10  Skip on Zero Link
SZA      1111 0010 0000  10  Skip on Zero AC (AC == 0)
SNA      1111 0010 1000  10  Skip on Non-zero AC (AC != 0)
SZA SNL  1111 0011 0000  10  Skip on Zero AC or Non-zero Link
SNA SZL  1111 0011 1000  10  Skip on Non-zero AC and Zero Link
SMA      1111 0100 0000  10  Skip on Minus AC (AC < 0)
SPA      1111 0100 1000  10  Skip on Positive AC (AC >= 0)
SMA SNL  1111 0101 0000  10  Skip on Minus AC or Non-zero Link
SPA SZL  1111 0101 1000  10  Skip on Positive AC and Zero Link
SMA SZA  1111 0110 0000  10  Skip on Minus AC or Zero AC (AC <= 0)
SPA SNA  1111 0110 1000  10  Skip on Positive AC and Non-zero AC (AC > 0)
SMA SZA SNL 1111 0111 0000  10  Skip on Minus AC or Zero AC or Non-zero Link
SPA SNA SZL 1111 0111 1000  10  Skip on Positve AC and Non-Zero AC and Zero Link
CLA      1111 1000 0000  10  Clear AC
LAS      1111 1000 0100  15  Load AC with Switch Register
SZA CLA  1111 1010 0000  10  Skip on Zero AC then Clear AC
SNA CLA  1111 1010 1000  10  Skip on Non-Zero AC then Clear AC
SMA CLA  1111 1100 0000  10  Skip on Minus AC then Clear AC
SPA CLA  1111 1100 1000  10  Skip on Positive AC then Clear AC
グループ1マイクロ命令と同じニーモニックと機能でビットパターンの異なる命令が存在しますね。たいていのマイクロ命令には説明不要でしょう。
表の4番目のSKP命令は常にスキップする命令です。SELビットで条件のORを指定して、具体的な条件を指定しないと、無条件にスキップが成立します。
LASはスイッチレジスタを1命令でACに読み込む命令で、最後の4種はスキップ動作の後でACをクリアします。SZA CLAでACが0か判定してからACを0にするのは無駄なようですが、ACのクリアはスキップが行われた場合も行われなかった場合にも実行されますから、実際に意味があります。

グループ3マイクロ命令は、MQマイクロ命令という呼び方もされ、MQレジスタ関係の操作を行います。具体的にはこのようなビット割り当てが行われています。
0 1 2 3  4   5  6  7  8 9 10 11
1 1 1 1 CLA MQA * MQL * *  *  1
*のビットは無視されます。意味のあるビットは3種だけで、その記号はこのような操作を表します。
CLA Clear AC
MQA OR MQ register into AC
MQL MQ register Load from AC
MQAはMQレジスタとACの内容をビットごとのOR演算を行ってACに結果を入れます。MQLはACの内容をMQレジスタに転送する命令です。CLAは今までと同じACのクリアです。
マイクロ命令間の優先順位は、次のようになっています。
1 - CLA
2 - MQA, MQL
MQA単独でもメモリ参照命令には存在しなかったビットごとの論理演算であるORが可能になりますし、CLAとMQAを組み合わせればMQからACへのデータ転送が行えます。
そういった合成命令には、このようなものがあります。
Mnemonic      Code     Cycles  動作
NOP      1111 0000 0001  10  No Operation
MQL      1111 0001 0001  10  MQ register Load (MQ <- AC)
MQA      1111 0100 0001  10  MQ register into AC (AC <- AC | MQ)
SWP      1111 0101 0001  10  Swap AC and MQ register (MQ <-> AC)
CLA      1111 1000 0001  10  Clear AC
CAM      1111 1001 0001  10  Clear AC and MQ register (MQ, AC <- 0)
ACL      1111 1100 0001  10  Clear AC and Load MQ register into AC (AC <- MQ)
CLA SWP  1111 1101 0001  10  Clear AC and Swap AC and MQ (AC <- MQ, MQ <- 0)
有効なビットが3 bitですから、すべての組み合わせは8種類。NOPとCLAはグループ1や2にもありました。MQLやMQAは単純なマイクロ命令ですから、もう説明の必要はありませんね。
SWP命令はMQAとMQLを組み合わせたもので、単純な組み合わせでは入れ換えにならないはずですが、とにかく入れ換え動作となっています。
CAMはACをクリアしてからMQへも転送しますから、ACとMQの両方に0が入ります。
ACLはACをクリアしてからMQとのORをとりますから、単純なMQからACへのデータ転送の意味になります。
CLA SWP命令はACをクリアしてからMQとACを入れ換えますから、結局MQをACに転送すると同時にMQを0クリアすることになります。

残るはIOT命令だけです。この、入出力機器とのデータ転送を行う命令は、次のようなただ1種類しかありません。
0 1 2 3 4 5 6 7 8 9 10 11
1 1 0 d d d d d d c  c  c
ここでdはデバイス選択コード、まぁI/Oポートアドレスといってもかまわないのですが、を表します。cは動作指定コードで、指定したデバイスが何を行うべきか指示するためのものです。デバイス選択コードのビット幅から最大64個の入出力機器を接続できることがわかります。ただし後で触れますが、プロセッサ自身も特殊な入出力機器としてデバイス選択コード0が割り当てられて、プロセッサ固有の制御が行われます。なお、IOT命令は17サイクルの命令実行時間を消費します。
この命令には、入力を行うのか出力を行うのかといった具体的な動作を表すものはまったくありません。デバイスを識別する選択コードと、デバイスごとに自由に決められる動作指定コードだけです。では、動作を決定する方法はどのようになっているのかというと、IM6100のIOT命令特有のバスサイクルと特殊な制御信号によります。
IM6100はIOT命令をフェッチした後の実行サイクルで、アドレスの代わりにフェッチしたIOT命令そのものを出力して、メモリ用のストローブ信号の代わりにデバイス用のストローブ信号DEVSELをアサートします。したがって、デバイス側ではDEVSEL信号がアサートされたときのアドレス3 - 8にデバイス選択コード、アドレス9 - 11に動作指定コードがあるとして、自分が選択されたか、そしてその時の動作指示は何かを読み取ることができます。そのDEVSEL信号で選択されたデバイスは、いきなりデータ転送を行うのではなく、まずC0, C1, C2, SKPという特別な制御線に指示を行います。この指示に従って、プロセッサが次の動作を行うのです。つまり、IOT命令で何を行うのか指示を出すのは、プロセッサ側ではなくてデバイス側です。
C0, C1, C2の意味は、次のようになっています。
 
C0 C1 C2 動作 説明
H H H Dev <- AC ACの内容をデバイスへ出力
L H H Dev <- AC, CLA ACの内容をデバイスへ出力した後ACをクリア
H L H AC <- AC | Dev デバイスから入力した値とACの論理和を求める
L L H AC <- Dev デバイスからACへ入力する
* H L PC <- PC + Dev PCにデバイスから送られてきた値を加算、相対ジャンプ
* L L PC <- Dev PCにデバイスから送られてきた値を入れ、絶対ジャンプ

SKP制御線がアサートされていると、プロセッサに次の命令をスキップさせる効果があります。このスキップ動作はC0, C1, C2によって指定された動作が完了してから行われます。ジャンプ指示の場合なら、ジャンプしてからスキップが行われるわけです。
たとえば、プリンタインターフェースのようなものを考えてみましょう。デバイスの初期化、バッファが空かの判定、データ出力の3種類の動作が必要だとします。動作指定コード0を送った場合に特に初期化用のコマンド不要で自動的に初期化が行われるとすれば、その際の応答は0オフセットの相対ジャンプを指示すれば良いわけです。データバッファが空か、つまり次のデータを送ってよいかどうかの判定は、普通のプロセッサならステータスレジスタからの入力を行ってAND演算で必要なビットをマスクして条件判定となりますが、IM6100の場合なら動作指定コード1を送った場合がバッファ空判定の意味になるとして、0オフセットの相対ジャンプを指定すると同時にバッファが空ならSKPをアサートして空でなければネゲートするようなインターフェース回路を製作すれば、そのIOT命令がバッファが空のときにスキップする命令となります。プログラムでAND演算や条件判定を行う必要がなくなるわけです。プログラムを格納するメモリが高価な時代のアーキテクチャとしては合理的ですね。ハードウエア的にはステータスレジスタを用意して、それが読み出されたらデータバスにステータスビットを出力するのと、SKP制御信号にステータスビットを出力するのでは、それほど回路に違いがあるわけではありませんから。最後にデータ出力動作を動作指定コードの2にでも割り当てて、その場合にはC0, C1, C2にすべてHを指定すれば単純なデータ出力動作を実現できます。ついでに動作指定コード3の場合の応答として、C0, C1, C2にL, H, Hを出力するようにしておけば、出力動作の後でACをクリアしますから、プログラムのほうで次の値をロードしやすくなります。
このように、プロセッサとデバイスが協調しながらデバイス固有の入出力命令を定義して実行するのが、IM6100というかPDP-8の入出力動作です。PDP-8/Eとの互換性を保つには、こういった入出力機能もPDP-8/Eシステムと互換になるようなインターフェース回路を設計して外付けする必要があります。別のコンピュータでソフトウェア開発を行う際のクロスコンパイラやクロスアセンブラを利用したり、演算ライブラリの流用などを考えるだけなら、入出力回路は単純な独自設計のものでかまわないでしょうけど。

プロセッサ自身の割り込みイネーブルフラグなどの操作にもIOT命令が使用されます。プロセッサにはデバイス番号0が割り当てられていて、その0番への動作指定コードで
Mnemonic      Code     Cycles  動作
SKON     1100 0000 0000  17  Skip if Interrupt On
ION      1100 0000 0001  17  Interrupt Turn On
IOF      1100 0000 0010  17  Interrupt Turn Off
SRQ      1100 0000 0011  17  Skip if Interrupt Request
GTF      1100 0000 0100  17  Get Flags
RTF      1100 0000 0101  17  Restore Flags
SGT      1100 0000 0110  17  (Skip if Greater Than Flag)
CAF      1100 0000 0111  17  Clear All Flags
SKON命令は割り込みイネーブルフラグが有効ならスキップします。そうして、無条件に割り込み禁止とします。
ION命令とIOF命令はそれぞれ割り込みの許可と禁止です。正確にはION命令の次の命令の実行後に割り込みが許可されます。SRQ命令は外部回路の割り込み要求がアサートされている場合にスキップする命令です。
GTF命令は、ACのビット0にLinkフラグ、2に外部の割り込み状態、4に割り込みイネーブルフラグを読み込みます。RTF命令はその逆で、ACのビット0がLinkフラグに、4が割り込みイネーブルフラグにセットされます。実際の割り込みイネーブルが変更されるのは、RTF命令の次の命令が実行終了してからですが。残りのビットはIM6100単体では無視されます。ただし、メモリ拡張ハードウエアなどが存在する場合には、使用される場合があります。
SGT命令はPDP-8/E互換とするためにニーモニックが割り当てられて、外部回路で利用されることがありますが、IM6100単体では無視されます。
CAF命令は、ACとLinkとIEがすべてクリアされ、その結果として割り込みも禁止されます。

IM6100のハードウエア面についてはごく簡単にふれます。
ピン配置は、このようになっています。
VCC      1      40 DATAF
RUN      2      39 INTGNT
DMAGNT   3      38 CPSEL*
DMAREQ*  4      37 MEMSEL*
CPREQ*   5      36 IFETCH
RUN/HLT* 6      35 SKP*
RESET*   7      34 C2*
INTREQ*  8      33 C1*
XTA      9      32 C0*
LXMAR   10      31 SWSEL*
WAIT*   11      30 DEVSEL*
XTB     12      29 LINK
XTC     13      28 DX11
CLOCK   14      27 DX10
CLOCK*  15      26 GND
DX0     16      25 DX9
DX1     17      24 DX8
DX2     18      23 DX7
DX3     19      22 DX6
DX4     20      21 DX5
VCCとGNDが電源です。
CLOCKとCLOCK*がクロック発振回路で、水晶発振子を外付けしてクロックを生成できます。外部回路で生成したクロック信号を入力したい場合はCLOCKの方がTTLレベル入力です。
DX0 - DX11がデータやアドレスがマルチプレクスされたバスで、XTA, LXMAR, WAIT, XTB, XTC, DEVSEL*, MEMSEL*がバスとメモリやI/Oとのデータ転送に関するタイミング信号となります。
C0*, C1*, C2*, SKP*はIOT命令のところで説明した入出力制御用の信号です。
RESET*はリセット信号で、PCに0FFFH、つまり全ビットがすべて1となる値をロードし、CPUを停止状態に遷移させます。したがって、プログラムで最初に実行される命令はアドレス0FFFHに納められたものになります。普通はここに間接ジャンプ命令を置いて、本来のコールドスタート地点にジャンプします。
さて、リセット後はCPUが停止状態ですから、実行状態に遷移させなくてはプログラムの実行が始まりません。それを行うのがRUN/HLT*信号で、ここにLパルスを与えるたびにそのポジティブエッジで交互に停止状態と実行状態が入れ代わります。CPUがどちらの状態にあるかを示すのが、RUN出力信号で、この端子がHなら実行状態です。RUNがLのときには外部回路をパワーダウンするといった、CMOSプロセッサならではの使いみちもあります。
割り込みに関係するのはINTREQ*とINTGNTです。INTREQ*が割り込み要求信号で、INTGNT信号が割り込み応答出力信号となります。IM6100では割り込みを受け付けるとPCの内容をアドレス000Hのメモリに書き込み、001Hから命令フェッチを開始します。あたかもアドレス000Hへのサブルーチン呼び出しのような処理が行われます。INTGNTは通常は不要ですが、メモリ拡張ハードウエアを装備している場合、正しく割り込みサービスルーチンの存在するメモリをアクセスできるようにするため、使われます。なんらかのIOT命令が実行されると、INTGNTはネゲートされます。
特別な割り込みとして、CPREQ*とCPSEL*信号が制御パネル割り込みの要求信号とサービス中を示す出力信号として用意されています。ミニコンピュータタイプのコンソールパネルを実現するのに、この制御パネル割り込みが使用されます。制御パネル割り込みでも、アドレス000HへとPCが格納されますが、新しいPCは0FFFHにセットされます。しかも制御パネル割り込みルーチンのメモリアクセスストローブ信号としてCPSEL*信号が出力されているため、そのタイミングで特別なメモリを読み書きすることによって、通常のメモリには影響を与えずに特別な制御パネルルーチンを実行することができます。ただし例外があって、間接アドレッシングを用いたTAD, ISZ, DCA命令のオペランドの読み書きには通常通りMEMSEL*信号が出力されます。そのため、通常メモリ空間のメモリにも制御パネル割り込みルーチンからアクセスできます。制御パネル割り込みルーチンの実行中はDMAも通常の割り込みも受け付けられません。特別な命令列を実行することにより、制御パネル割り込みルーチンを終了して通常のプログラム実行を継続することができます。
DMAREQ*とDMAGNTがDMA用の信号で、DMAREQ*を与えると実行中の命令処理が終わってからDX信号をスリーステート状態にしてDMAGNTをアサートします。その状態で、外部回路によって安全にメモりアクセスが可能となります。DMAREQ*をネゲートすれば、CPUの内部状態に同期してからDMAGNTをネゲートして、通常の命令実行処理が再開されます。
IFETCHとDATAFは外部回路のメモリ拡張ハードウエアによって利用される信号です。それぞれ命令フェッチと間接アドレッシングのTAD, ISZ, DCA命令のオペランドの読み書きを意味して、メモリ拡張ハードウエアで特別に解釈すべき命令がフェッチされたか、あるいはデータ用のメモリ空間をアクセスするのか、判定するのに用いられます。
LINK信号はLINKフラグの内容がそのまま出力されます。

かなり手短な説明となりましたが、ハードウエア面はこのようなものに仕上がっています。コンソールパネル用の機能が組み込まれていたり、PDP-8/Eと同様にミニコンピュータ的システムを構成する工夫がされています。単純な組み込み用として使用する場合も、メモリ拡張をしなければそれほど複雑な外付け回路は要りません。逆にPDP-8/Eと完全互換にしようとするなら、主要な命令は互換性があるとしてもIOT命令まで互換動作となるように入出力インターフェース回路を製作する必要があり、結構面倒だと思います。

Return to IC Collection