PDP-8

PDP-8は、世界で初めて商業的に成功した12ビットミニコンピュータであり、1960年代にディジタル・イクイップメント・コーポレーション (DEC) が製造した。1965年3月22日に登場し、5万システムを売り上げ、DECのPDPシリーズでも当時最も成功したコンピュータとなった。最初のPDP-8の設計を指揮したエドソン・デ・カストロは、後にデータゼネラルを創業した。
最初のPDP-8機種（非公式に "Straight-8" と呼ばれている）は diode-transistor logic (DTL) を採用したフリップチップ基板で構成されており、小型冷蔵庫ほどの大きさだった。
その後、デスクトップ型とラックマウント型のPDP-8/Sが登場。1ビット直列ALU実装で、小型化と低価格化を実現したが、最初のPDP-8に比べると性能がかなり低い。PDP-8/Sに接続可能な唯一のストレージがDF32というディスク装置（容量32Kワード）だった。
その後のシステム（PDP-8/I、/L、/E、/F、/M、/A）は並列実装で高速になった（元に戻った）が、TTLICを使用し、DTLより安価になっている。現存するPDP-8の多くはこの世代の機種である。中でもPDP-8/Eは豊富な各種周辺機器が接続可能で、よく使われていた。汎用コンピュータとしてもよく使われていた。
1975年、安価なマイクロプロセッサを使った Altair 8800 などの初期のパーソナルコンピュータが登場し、その後 TRS-80 や Apple II が登場すると、小型汎用コンピュータの市場はそれらに奪われることになった。
1979年にリリースされた PDP-8 の最後の機種は特製のCMOSマイクロプロセッサを使用しており、"CMOS-8s" などと呼ばれた。価格は他のマイクロプロセッサを使ったコンピュータと競合するような設定ではなく、市場には受け入れられなかった。1981年に登場した IBM PC がCMOS-8sにとどめを刺した。インターシルがこの集積回路を1982年まで Intersil 6100 として販売していた。CMOSであるため低電力であり、いくつかの軍用組み込みシステムに採用された。

概要

技術史的観点からもPDP-8は重要な位置を占めている。入出力機構、ソフトウェア開発、オペレーティングシステム設計などに影響を与えた。Apple IIのようなマイクロコンピュータが一般化するまで、PDP-8は世界で最も販売台数の多いコンピュータであった。
PDP-8はいくつかの12ビット機の先例を参考にしており、特に W.A. Clark と C.E. Molnar が設計したLINCに影響を受けている。LINC自体は、シーモア・クレイが設計したミニコンピュータ CDC 160 に影響を受けている。
単純なプログラムドI/O (PIO) バスを備え、それに加えてDMAチャネルがある。PIOバスは、プリンター、テレタイプ端末、紙テープパンチ/リーダーといった低速から中速の周辺機器を接続するのが一般的で、一方DMAはライトペン付きのブラウン管スクリーン、アナログ-デジタル変換回路、デジタル-アナログ変換回路、磁気テープドライブ、ディスクドライブなどで使用する。
ワード長は12ビットで、符号なし整数で0から4095までの範囲を扱え、単純な機械の制御には十分である。また、符号付整数なら -2048 から +2047 まで扱える。これは計算尺より高精度だし、多くのアナログコンピュータにも引けを取らない。12ビットはまた、ASCIIのサブセットを6ビットで表せば、1ワードに2文字を格納できる。
コスト削減のため、他のコンピュータならフリップフロップで構成するレジスタも安価な主記憶を使う設計になっていた。
PDP-8の基本構成では、主記憶容量は4,096ワードで、オプションのメモリ拡張ユニットでさらに拡張する場合は、後述のIOT命令でバンク切り換えをして使用する。
当初、ソフトウェアから見てPDP-8は8種類の命令しかなく、レジスタも2本（12ビットのアキュムレータ AC とキャリービットに相当するリンクレジスタ L）しか持たない。主記憶は磁気コアメモリでクロックサイクルは1.5μ秒である。典型的には1命令で命令とデータにアクセスするため2サイクルかかり、性能は0.333MIPSとなる。1974年の Pocket Reference Card では基本命令実行時間は1.2μ秒、メモリ参照命令の場合は2.6μ秒となっている。後期の機種では新たなレジスタが追加され(積/商レジスタ、MQ)、乗算命令と除算命令が追加された。
PDP-8は設計の単純さを重視して設計が最適化されている。直列化ALUを採用したPDP-8/Sでは、論理ゲートを519個しか使っていない。2008年現在、最も規模の小さいマイクロコントローラでも1万5千ゲート以上使っている。他のマシンと比較すると必須ではない部分がそぎ落とされ、可能な限り論理回路を共用する設計になっている。命令は自動インクリメントや自動クリアや間接アクセスを利用して性能向上を図りつつメモリ使用量を削減している。PDP-8のCPUには12ビットレジスタが4本しかない（アキュムレータ、プログラムカウンタ、メモリバッファレジスタ、メモリアドレスレジスタ）。これらのレジスタは処理サイクルの各時点で様々な用途に使われている。例えば、メモリバッファレジスタは算術演算のオペランドを供給し、磁気コアメモリに書き出すべきデータを一時的に保持する（また、磁気コアメモリからの読み出しで破壊されたデータを書き戻すのにも使われる）。このように基本は単純にも関わらず、モジュールを小型化するために価格は高くなった。PDP-8/Sは電源電圧を2種類使っているが、これは diode-transistor logic (DTL) でのファンアウト数を大きくする安価な技法である。

後の実装例

PDP-8のアーキテクチャは非常に単純なので、それをエミュレートするのは容易である。愛好家がPDP-8全体を1個のFPGAで実装した例もある。
インターネット上にはPDP-8をシミュレート/エミュレートするソフトウェアもいくつか存在する。うまく実装されたものはDECのOSや診断プログラムを実行可能である。後期のPDP-8に可能な限りの周辺機器を接続した状態をシミュレートすることが多い。そこまでしても、現代のパーソナルコンピュータのリソースのほんの一部しか占めない。

プログラミング環境

PDP-8の最も基本的なソフトウェア開発システムは、機械語をバイナリ形式でフロントパネルから入力するものであった。その後、PAL-8アセンブリ言語のソースコードを紙テープに格納し、メモリにロードし、紙テープにセーブし、紙テープからアセンブルされてメモリに格納されるようになった。紙テープ方式のプログラミング言語としては他に FOCAL インタプリタや 4K FORTRANコンパイラなどがある。最終的には OS/8 や COS-310 といったオペレーティングシステムによって、ラインエディタやコマンドラインコンパイラといった開発システムが構築された。サポート言語としては、PAL-IIIアセンブリ言語、FORTRAN、BASIC、DIBOLなどがある。
初期のPDP-8システムにはオペレーティングシステムがなく、フロントパネルのスイッチしかなかった。様々な紙テープ式「オペレーティングシステム」が開発されたが、いずれもシングルユーザー方式であった。最後期には先進的なRTOSやプリエンプティブ・マルチタスク/マルチユーザーシステムが利用可能となった。例えば RTOSの RTS-8、マルチユーザーシステムの COS-300 や COS-310、シングルユーザー用ワードプロセッシングシステム WPS-8 などがある。
タイムシェアリングシステム TSS-8 も使用可能であった。TSS-8 では複数のユーザーが110ボーの端末からシステムにログインすることができ、プログラムのエディット/コンパイル/デバッグが同時にできた。言語としては、BASICの特別バージョン、FORTRANのサブセット(サブルーチンを書けない)、ALGOLのサブセット版、FOCAL、PAL-Dアセンブラなどが利用可能である。
DECUS (Digital Equipment Computer User Society) はPDP-8用にユーザーが寄贈した相当量のソフトウェアを保有している。

メモリページ

このように命令はアドレスの下位7ビットだけを直接指定するので、4,096ワードのメモリは128ワードの「ページ」に分割されることになり、命令のビット4でカレントページかページ0（アドレス範囲を八進法で示すと 0000 から 0177）を指定する。ページ0に変数を置くと、どのページを実行中でもそれにアクセスできるため、ページ0のメモリは特別である。また、アドレス 0000 は割り込み処理ルーチンのスタートアドレスでもある。また、アドレス 0010 から 0017 までは自動インクリメント機構という特殊性がある。
標準的アセンブラは算術用定数をカレントページに置く。同様に、ページ間ジャンプやサブルーチンコールはカレントページ内から間接アドレス指定で行う（つまりアドレスがカレントページ内に置かれている）。
ページをまたいだ参照や分岐は余分なワードを必要とするため、ルーチンを128ワードのページ境界に収まるように書くか、なるべくページからページへの移行が少なくなるように書くことが重要だった。そのため、何ワードかをいかに節約するかに頭を悩ませることが多かった。PCのインクリメントで自動的に次のページに移行できるため、プログラムを意図的にページの最後尾に置くことが多かった。

OPR (OPeRate) 命令

条件付き操作のほとんどを含め、多くの操作はOPR命令として実行される。OPR命令ではメモリ位置をアドレスで示すということがない。条件付き操作は1命令をスキップするか否かを判断する命令であり、通常はその1命令をJMP命令とすることで条件分岐として機能させる。
OPR命令はマイクロコード化されている。これはマイクロプログラム方式だということを意味しているのではなく、命令語の各ビットがそれぞれ特定の動作に対応しており、複数のビットをセットすることでそれらを1命令で実行できる場合があることを意味している。アセンブリ言語で記述する際には複数のニーモニックを並列に書く。するとアセンブラがそれらのコードをORして1命令にする。上述のIOT命令も周辺機器がマイクロコード化している。
マイクロコード化された動作の実行順序は決まっており、多くの組合せが最も便利になるような順序で実行される。
OPR命令にはいくつかのグループがある。ビット3、ビット8、ビット11 でグループが識別され、異なるグループのマイクロコード化操作は1命令で指定できない。

メモリ制御

12ビットワードは4,096種類の値をとることができ、それは最初のPDP-8がワードポインタで間接的にアドレス指定できる最大のワード数でもあった。プログラムが複雑化し、メモリ価格が下落してくると、この制限を拡張することが望ましくなってきた。
既存プログラムとの互換性を保つため、当初設計になかった新ハードウェアはプログラムが生成する実効アドレスにさらに上位のビット群を追加した。メモリ拡張コントローラはアドレス指定範囲を8倍にし、32,768ワードまで扱えるようにした。当時の磁気コアメモリは1ワード当たり50セントのコストであり、32Kワードを実装するとCPUと同程度のコストになるため、この程度の拡張で十分だとされた。
4Kワードぶんのメモリをフィールドと呼ぶ。メモリ拡張コントローラは、DF (Data Field) と IF (Instruction Field) という2つの3ビットレジスタを備えている。それらのレジスタはデータアクセスや命令フェッチの際にどのフィールドにアクセスするかを指定するもので、アドレスは実質15ビットに拡張される。IFレジスタは命令フェッチと直接メモリ参照の際のフィールドを指定する。DFレジスタは間接データアクセスの際のフィールドを指定する。あるフィールドで動作中のプログラムは、直接アドレッシングでは同じフィールドにアクセスし、間接アドレッシングでは別のフィールドにアクセスできる。
IOT命令の 6200 から 6277 までの範囲がメモリ拡張コントローラに対応しており、DFレジスタとIFレジスタへのアクセスが可能である。62X1 命令 (CDF, Change Data Field) はDFレジスタの値をXにする。同様に62X2 (CIF) 命令はIFレジスタの値をXに、62X3 命令は両方をXにセットする。既存プログラムはCIFもCDFも実行しない。DFもIFも同じフィールドを指すので、既存プログラムは単一フィールドだけで動作する。CIF命令の効果は、次のJMPまたはJMS命令まで遅延されるので、CIF命令によって即座にジャンプするわけではない。
フィールド境界とDF/IFレジスタの関係を考えると、複数フィールドを使うプログラムはさらに複雑化する。単純に15ビットのアドレスを生成するのではなく、12ビット・アーキテクチャとの一貫性と互換性を保つよう設計されているためである。後の Intel 8086 では、Intel 8080 で16ビットだったアドレスを20ビットに拡張したが、拡張部分はセグメントレジスタで指定する方式だった。
このメモリ拡張方式により、既存のプログラムを少し修正するだけで扱えるメモリ範囲を拡大することができた。例えば、4K FOCAL は、自身のコードが3Kあってユーザープログラムやデータに使えるメモリは1Kしかなかった。そのFOCALに若干パッチを当てるだけで、ユーザープログラムとデータに別の4Kフィールドを割り当てることができる。さらに、4Kフィールドを別のユーザーに割り当てることもでき、マルチユーザーのタイムシェアリングシステムを構成できる。

仮想化

PDP-8/Eとその後の機種では、メモリ拡張コントローラは仮想化も可能なように拡張された。PDP-8の全リソースを使用するようなプログラムが1台のPDP-8上に複数並存でき、仮想機械マネージャの制御下で動作可能だった。このマネージャは（メモリ拡張コントローラの操作も含む）全IO命令に対してトラップが可能である（割り込みを起こしてマネージャがそれを処理できる）。そのようにしてマネージャがデータや命令のフィールドのマッピングを制御でき、入出力を他のデバイスにリダイレクトできる。それぞれのゲストプログラムは、マネージャが提供する「仮想機械」への完全なアクセスを持つ。
新たなIOT命令で、メモリ拡張コントローラのDF/IFレジスタの現在値を読み出すことができ、トラップ前後のマシンの状態をセーブ/リストアできる。しかし、CIF命令の効果が遅延している状態（CIF命令を実行後、最初の分岐を行うまでの状態）かどうかは判別できない。マネージャは完全なPDP-8エミュレータを含んでいる必要がある（8命令のマシンなので難しくはない）。CIF命令をトラップした際、マネージャは次のジャンプ命令までの命令列をエミュレートする必要がある。実際、ジャンプ命令はCIF命令の直後にあるのが一般的で、エミュレーションで性能が大きく低下することはないが、小さな設計上の欠陥への対策としては大きい。
PDP-8/Aのころメモリ価格はさらに下落し、32Kワード以上も可能なレベルとなった。そこでPDP-8/Aでは8フィールド以上を扱える新たな命令群が追加された。フィールド番号は命令にハードコーディングされるのではなく、ACで指定できるようになった。しかし、そのころにはPDP-8は市場から消えつつあり、この新機能を使うよう修正された主要ソフトウェアはごく一部だけだった。

コーディング例

PDP-8のアセンブリ言語プログラムを例として示す。以下のコード例はPAL-IIIアセンブラによる。

2つの数の比較

単に2つの数を比較するだけでどれだけのコードが必要となるかを示したコード断片。
   /Compare numbers in memory at OPD1 and OPD2
           CLA CLL     /Must start with 0 in AC and link
           TAD OPD1    /Load first operand into AC (by adding it to 0); link is still clear
           CIA         /Complement, then increment AC, negating it
           TAD OPD2    /AC now has OPD2-OPD1; if OPD2≥OPD1, sum overflows and link is set
           SZL         /Skip if link is clear
           JMP OP2GT   /Jump somewhere in the case that OPD2≥OPD1;
                       /Otherwise, fall through to code below.
見ての通り、PDP-8の典型的なプログラムは作者が意図したアルゴリズムよりも低レベルな機構に集中する傾向がある。また、可読性を損なうもう1つの問題として、条件分岐部分のコーディングがある。上の例で判るとおり条件判断命令（JMP命令をスキップしている命令）は、注目している条件とは反対の条件判断をしなければならない。

文字列出力

PDP-8で "Hello, world" をテレタイプ端末に出力するアセンブリ言語のプログラム。
   *10                   / Set current assembly origin to address 10,
   STPTR,    STRNG-1     / An auto-increment register (one of eight at 10-17)
 
   *200                  / Set current assembly origin to program text area
   HELLO,  CLA CLL       / Clear AC and Link again (needed when we loop back from tls)
           TAD I Z STPTR / Get next character, indirect via PRE-auto-increment address from the zero page
           SNA           / Skip if non-zero (not end of string)
           HLT           / Else halt on zero (end of string)
           TLS           / Output the character in the AC to the teleprinter
           TSF           / Skip if teleprinter ready for character
           JMP .-1       / Else jump back and try again
           JMP HELLO     / Jump back for the next character
 
   STRNG,  310           / H
           345           / e
           354           / l
           354           / l
           357           / o
           254           /,
           240           / (space)
           367           / w
           357           / o
           362           / r
           354           / l
           344           / d
           241           / !
           0             / End of string
   $HELLO                /DEFAULT TERMINATOR

ソフトウェアスタック

PDP-8 はスタックをハードウェアでサポートしていないが、ソフトウェアでの実装は可能である。以下はPUSHとPOPというサブルーチンの実装例だが、単純化するためスタックのオーバーフローやアンダーフローはチェックしていない。
   PUSH, 0
         DCA DATA
         CLA CMA     / -1
         TAD SP
         DCA SP
         TAD DATA
         DCA I SP
         JMP I PUSH     /Return
   POP,  0
         CLA CLL
         TAD I SP
         ISZ SP
         JMP I POP
   DATA, 0
   SP, 0
以下は、"Hello World" を "OUT" というサブルーチンとこのスタックを使って実装したものである。
   *200
   MAIN,  CLA CLL         /Set the message pointer
          TAD (MESSG      /To the beginning of the message (literal)
          DCA SP
   LOOP,  JMS POP
          SNA             /Stop execution if zero
          HLT
          JMS OUT         /Otherwise, output a character
          JMP LOOP
   MESSG, "H
          "e
          "l
          "l
          "o
          ",
          "
          "w
          "o
          "r
          "l
          "d
          "!
          015
          012
          0
   OUT,    0               / Will be replaced by caller's updated PC
           TSF             / Skip if printer ready
           JMP .-1         / Wait for flag
           TLS             / Send the character in the AC
           CLA CLL         / Clear AC and Link for next pass
           JMP I OUT      / Return to caller

連結リスト

PDP-8での連結リストの実装例。
    GETN, 0     /Gets the number pointed to and moves the pointer
    CLA CLL     /Clear accumulator
    TAD I PTR   /Gets the number pointed to
    DCA TEMP    /Save current value
    ISZ    PTR     /Increment pointer
    TAD I PTR   /Get next address
    DCA PTR     /Put in pointer
    JMP I GETN  /return
    PTR,  0
    TEMP, 0

割り込み

PDP-8の入出力バスには1本の割り込みラインがあり、割り込みが発生すると割り込み不可状態となって 0番地のサブルーチンを呼び出すように動作する。サブルーチンと同様、割り込みもリエントラント性は無く、割り込みを不可とした状態で割り込みハンドラが動作し、JMP I 0 命令で割り込まれた箇所に戻るとき割り込み可とする。
I/Oバスの割り込みラインが1本なので、割り込み発生源が何かということは分からない。そのため、割り込み処理ルーチンは順に各デバイスのステータスをポーリングしてチェックし、割り込み元を識別した。この処理は条件スキップ命令が並ぶので "skip chain" と呼ばれた。skip chain の最後まで実行しても割り込み元が見つからないことは珍しいことではなかった。相対的な割り込みの優先順位は skip chain でチェックする順番で決定され、先に見つかった割り込みの処理が優先される。