
コンピュータにおいて、エミュレータとは、あるコンピュータシステム(ホストと呼ばれる)が別のコンピュータシステム(ゲストと呼ばれる)のように動作できるようにするハードウェアまたはソフトウェアのことです。エミュレータは通常、ホストシステムがゲストシステム用に設計されたソフトウェアを実行したり、周辺機器を使用したりできるようにします。エミュレーションとは、電子機器内のコンピュータプログラムが、別のプログラムやデバイスを模倣(または再現)する能力を指します。
例えば、多くのプリンターはHP LaserJetプリンターをエミュレートするように設計されています。これは、ソフトウェアの大部分がHPモデル専用に作成されているためです。HP以外のプリンターがHPプリンターをエミュレートする場合、実際のHPプリンター用に設計されたソフトウェアはHP以外のデバイスでも動作し、同等の印刷結果が得られます。少なくとも1990年代以降、多くのビデオゲーム愛好家やホビイストは、エミュレータを使用して、1980年代のクラシックアーケードゲームを、ゲームのオリジナルの1980年代のマシンコードとデータを使用してプレイし、それを現在のシステムで解釈したり、古いビデオゲームコンソールをエミュレートしたりしてきました(ビデオゲームコンソールエミュレータを参照)。
ハードウェアエミュレータとは、ハードウェアデバイスの形態をとるエミュレータのことです。例としては、1990年代のMacintoshコンピュータ(Centris 610やPerforma 630など)に搭載されていたDOS互換カードがあり、これによりPCソフトウェアプログラムを実行できました。また、フィールドプログラマブルゲートアレイ(FPGA )ベースのハードウェアエミュレータも存在します。チャーチ=チューリングのテーゼは、理論的には、メモリ制限を無視すれば、あらゆるオペレーティング環境を他のあらゆる環境でエミュレートできることを示唆しています。しかし実際には、特にエミュレート対象システムの正確な動作が文書化されておらず、リバースエンジニアリングによって推測する必要がある場合、非常に困難です。また、タイミング制約については何も言及されていません。エミュレータが元のハードウェアを使用したときほど高速に動作しない場合、エミュレーション内のソフトウェアははるかに低速で動作する可能性があります(動作を変更するタイマー割り込みをトリガーする可能性があります)。
「コモドール64でMS-DOSをエミュレートできますか?」はい、コモドール64でIBM PC(MS-DOSを使用)をエミュレートすることは可能ですが、それはティースプーンでミシガン湖の水を汲み出すのと同じくらい不可能なことです。


ほとんどのエミュレータはハードウェアアーキテクチャをエミュレートするだけです。目的のソフトウェアにオペレーティングシステムのファームウェアやソフトウェアが必要な場合は、それらも提供する必要があります(そして、それ自体がエミュレートされる場合もあります)。OSとソフトウェアは、ネイティブハードウェアで実行されるのではなく、エミュレータによって解釈されます。エミュレートされたバイナリマシンの言語のこのインタプリタとは別に、他のハードウェア(入力デバイスや出力デバイスなど)も仮想形式で提供する必要があります。たとえば、特定のメモリ位置への書き込みが画面に表示される内容に影響を与える必要がある場合は、それをエミュレートする必要があります。エミュレーションは、極限まで進めば、仮想電源からの実際の回路のシミュレーションに基づいて出力を行う原子レベルまで到達できますが、これは非常にまれなソリューションです。エミュレータは通常、文書化されたハードウェア仕様とデジタルロジックのシミュレーションで止まります。一部のハードウェアプラットフォームを十分にエミュレートするには、個々のクロックサイクル、文書化されていない機能、予測不可能なアナログ要素、実装バグのレベルまで極めて高い精度が必要です。これは特に、コモドール64のような古典的な家庭用コンピュータに当てはまります。これらのコンピュータのソフトウェアは、ゲームプログラマーや「デモシーン」によって考案された、高度に洗練された低レベルのプログラミング技術に依存していることが多いのです。
対照的に、PlayStation 4 のエミュレータのように、直接ハードウェア アドレス指定をほとんど使用していないプラットフォームもあります。このような場合、単純な互換性レイヤーで十分です。これは、外部システムのシステム コールをホスト システムのシステム コールに変換します。たとえば、 FreeBSDおよびNetBSDでクローズド ソースの Linux ネイティブ ソフトウェアを実行するために *BSD で使用される Linux 互換性レイヤーです。[ 2 ]たとえば、Nintendo 64 のグラフィック プロセッサは完全にプログラム可能でしたが、ほとんどのゲームは、ほとんどが自己完結型でFIFOを介してゲームと通信する、いくつかの既製のプログラムのいずれかを使用していました。そのため、多くのエミュレータはグラフィック プロセッサをまったくエミュレートせず、単に CPU から受信したコマンドを元のプログラムが行うように解釈します。組み込みシステムやビデオゲーム コンソールのソフトウェア開発者は、実際のハードウェアで試す前に、シミュレータと呼ばれる特に正確なエミュレータでソフトウェアを設計することがよくあります。これは、最終的なハードウェアが大量生産される前にソフトウェアを製造およびテストできるようにし、低レベルでデバッグするプログラムをコピーする時間をかけずに、またデバッガの副作用を導入することなくテストできるようにするためです。多くの場合、シミュレータはハードウェアを提供する会社によって実際に製造されるため、理論的には精度が向上します。数学コプロセッサエミュレータを使用すると、数学命令でコンパイルされたプログラムを、コプロセッサがインストールされていないマシンで実行できますが、CPU が行う追加の作業によりシステムが遅くなる可能性があります。数学コプロセッサがインストールされていないか、CPU に存在しない場合、CPU がコプロセッサ命令を実行すると、特定の割り込み (コプロセッサが利用できません) が発生し、数学エミュレータルーチンが呼び出されます。命令が正常にエミュレートされると、プログラムの実行が続行されます。
論理シミュレーションとは、プロセッサなどのデジタル回路の動作をシミュレートするためにコンピュータプログラムを使用することです。[ 3 ]これは、デジタル回路が論理方程式で設計された後、ハードウェアで回路が製造される前に行われます。
機能シミュレーションとは、バイナリマシンコードではなく、シンボリックアセンブリ言語またはコンパイラ言語で記述された別のコンピュータプログラムの実行をシミュレートするためにコンピュータプログラムを使用することです。機能シミュレータを使用することで、プログラマはバイナリコードを生成することなく、ソースコードの選択したセクションを実行してトレースし、プログラミングエラー(バグ)を探すことができます。これは、ソフトウェアエミュレーションであるバイナリコードの実行のシミュレートとは異なります。最初の機能シミュレータは、軍用コンピュータD-17Bで後から実行するためのアセンブリ言語プログラムのテスト用に、 1960年頃にAutoneticsによって作成されました。これにより、D-17Bコンピュータハードウェアが構築される前に、飛行プログラムを作成、実行、テストすることが可能になりました。Autoneticsはまた、軍用コンピュータD-37Cで後から実行するための飛行プログラムのテスト用の機能シミュレータも作成しました。
ビデオゲーム機エミュレータは、パーソナルコンピュータやビデオゲーム機が別のビデオゲーム機をエミュレートできるようにするプログラムです。これらは、1980年代から2000年代の古いビデオゲームを最新のパーソナルコンピュータや最新のビデオゲーム機でプレイするために最もよく使用されます。また、ゲームを他の言語に翻訳したり、既存のゲームを改造したり、「自作」デモの開発プロセスや古いシステム向けの新しいゲームの作成にも使用されます。インターネットはコンソールエミュレータの普及に貢献しており、ほとんどすべて(すべてではないにしても)は小売店では入手できません。過去数十年にリリースされたコンソールエミュレータの例としては、RPCS3、Dolphin、Cemu、PCSX2、PPSSPP、ZSNES、Citra、ePSXe、Project64、Visual Boy Advance、Nestopia、Yuzuなどがあります。
エミュレータは人気が高いため、マルウェアに偽装されることがあります。これらのエミュレータのほとんどは、Xbox 360、Xbox One、Nintendo 3DSなどのビデオゲーム機用です。一般的に、このようなエミュレータは、 1つのプログラムでXbox OneとXbox 360のゲームを実行できるなど、現状では不可能な主張をしています。[ 4 ]
コンピュータとグローバルコンピュータネットワークが進化を続け、エミュレータ開発者のスキルが向上するにつれて、コンソールの市販リリースからエミュレーションの成功までの期間は短縮され始めました。Nintendo 64、PlayStationなどの第5世代コンソールや、Game Boy Advanceなどの第6世代携帯ゲーム機では、製造中にエミュレーションに向けて大きな進歩が見られました。これにより、コンソールメーカーは非公式のエミュレーションを阻止しようとしましたが、Sega v. Accolade 977 F.2d 1510 (9th Cir. 1992)、Sony Computer Entertainment, Inc. v. Connectix Corporation 203 F.3d 596 (2000)、Sony Computer Entertainment America v. Bleem 214 F.3d 1022 (2000) [ 5 ]などの度重なる失敗により、逆の効果が生じました。すべての法的判例によれば、エミュレーションは米国では合法です。しかし、著作権で保護されたコードの無断配布は、各国固有の著作権法とベルヌ条約に基づく国際著作権法の両方で違法である。[ 6 ]米国法では、ユーザーが合法的に購入したマシンのコピーを入手した限り、 Lewis Galoob Toys, Inc. v. Nintendo of America, Inc. , 964 F.2d 965 (9th Cir. 1992)の判決により、元のマシンのBIOSのダンプコピーを取得することはフェアユースとして合法である。しかし、これを軽減するために、 Game Boy Advanceなどのプラットフォーム用のいくつかのエミュレータは、BIOS ファイルなしで動作することができ、エミュレーション精度をわずかに犠牲にして、高レベルのエミュレーションを使用して BIOS サブルーチンをシミュレートする。[ 7 ] [ 8 ] [ 9 ]
端末エミュレータは、現代のコンピュータやデバイスが、メインフレームコンピュータのオペレーティングシステムや、 HP-UXやOpenVMSなどのホストシステム上で動作するアプリケーションに対話的にアクセスできるようにするソフトウェアプログラムです。IBM 3270やVT100などの端末は、もはや物理的なデバイスとしては製造されていません。代わりに、最新のオペレーティングシステム上で動作するソフトウェアが「ダム」端末をシミュレートし、ホストアプリケーションのグラフィック要素やテキスト要素を表示したり、キーストロークを送信したり、適切な端末プロトコルを使用してコマンドを処理したりすることができます。端末エミュレーションアプリケーションには、Attachmate Reflection、IBM Personal Communications、Micro Focus Rumbaなどがあります。
その他のエミュレータの種類には以下のようなものがあります。
一般的に、エミュレータは、エミュレート対象のコンピュータのサブシステムにほぼ対応するモジュールに分割されます。多くの場合、エミュレータは以下のモジュールで構成されます。
パフォーマンス上の理由、あるいは簡便性の観点から、バスはエミュレートされないことが多く、仮想周辺機器はCPUまたはメモリサブシステムと直接通信する。
メモリサブシステムのエミュレーションは、エミュレートされたワードと同じサイズの要素の配列に単純に縮小できますが、コンピュータの論理メモリ内のいずれかの場所が物理メモリと一致しなくなると、このモデルはすぐに破綻します。これは、エミュレートされたハードウェアが高度なメモリ管理を可能にする場合に明らかです(この場合、MMUロジックはメモリエミュレータに組み込むか、独自のモジュールにするか、またはCPUシミュレータに統合することができます)。ただし、エミュレートされたコンピュータにMMUが搭載されていない場合でも、論理メモリと物理メモリの等価性を破る要因が通常は他にもあります。多くの(ほとんどの)アーキテクチャはメモリマップドI/Oを提供しており、そうでない場合でも、 ROMにマッピングされた論理メモリのブロックを持つことがよくあります。つまり、ROMの読み取り専用性をエミュレートする場合は、メモリ配列モジュールを破棄する必要があります。バンク切り替えやセグメンテーションなどの機能も、メモリエミュレーションを複雑にする可能性があります。そのため、ほとんどのエミュレータは論理メモリへの書き込みと読み出しのための少なくとも2つの手順を実装しており、これらの手順はすべてのアクセスを正しいオブジェクトの正しい場所にマッピングする役割を担っています。
アドレス0からアドレスROMSIZE-1までのメモリが読み出し専用メモリであり、残りがRAMであるベースリミットアドレッシングシステムでは、以下のような手順が一般的です。
void WriteMemory ( word Address , word Value ) { word RealAddress ; RealAddress = Address + BaseRegister ; if (( RealAddress < LimitRegister ) && ( RealAddress > ROMSIZE )) { Memory [ RealAddress ] = Value ; } else { RaiseInterrupt ( INT_SEGFAULT ); } }word ReadMemory ( word Address ) { word RealAddress ; RealAddress = Address + BaseRegister ; if ( RealAddress < LimitRegister ) { return Memory [ RealAddress ]; } else { RaiseInterrupt ( INT_SEGFAULT ); return NULL ; } }CPUシミュレータは、エミュレータの中で最も複雑な部分であることが多い。多くのエミュレータは、特定のマシンの効率的かつ適切なエミュレーションに集中するために、「パッケージ化された」CPUシミュレータを使用して作成されている。CPUシミュレータの最も単純な形式はインタプリタであり、これはエミュレートされたプログラムコードの実行フローを追跡し、遭遇したすべてのマシンコード命令に対して、元の命令と意味的に同等の操作をホストプロセッサ上で実行するコンピュータプログラムである。これは、シミュレートされたCPUの各レジスタとフラグに変数を割り当てることによって可能になる。シミュレートされたCPUのロジックは、ほぼ直接ソフトウェアアルゴリズムに変換でき、基本的に元のハードウェア実装を反映するソフトウェアによる再実装が作成される。
次の例は、インタープリタによってCPUシミュレーションを実現する方法を示しています。この例では、すべての命令実行前に割り込みの有無がチェックされますが、実際のエミュレータではパフォーマンス上の理由からこのような動作はまれです(一般的に、割り込み処理をサブルーチンで行う方が高速です)。
void Execute ( void ) { if ( Interrupt != INT_NONE ) { SuperUser = TRUE ; WriteMemory ( ++ StackPointer , ProgramCounter ); ProgramCounter = InterruptPointer ; } switch ( ReadMemory ( ProgramCounter ++ )) { /* * すべての有効な命令の処理 * はここに記述します... */ default : Interrupt = INT_ILLEGAL ; } }インタプリタは、より効率的な代替ソリューションよりも実装がはるかに簡単で、現代のマシンで約 10 年以上前のコンピュータをエミュレートするのに十分な速度を備えているため、コンピュータ シミュレータとして非常に人気があります。しかし、インタプリタに内在する速度低下は、プロセッサ速度がホスト マシンと同程度のコンピュータをエミュレートする場合に問題となる可能性があります。ほんの 1 年前までは、このような状況でのエミュレーションは、多くの人にとって全く実用的ではないと考えられていました。
この制約を打破できたのは、動的再コンパイル技術の進歩によるものです。エミュレートされたプログラムコードをホストアーキテクチャ上で実行可能なコードに単純に事前変換することは、通常、いくつかの理由から不可能です。
人気のJust In Timeコンパイラ(JIT)技術を含むさまざまな形式の動的再コンパイルは、プロセッサの制御フローが未翻訳コードを含む場所にジャンプするまで待機し、その時点で(「ジャストインタイム」で)コードブロックを実行可能なホストコードに変換することで、これらの問題を回避しようとします。翻訳されたコードはコードキャッシュに保持され、元のコードは失われたり影響を受けたりしません。このようにして、データセグメントでさえも再コンパイラによって(意味なく)翻訳される可能性があり、結果として翻訳時間の無駄になるだけです。一部の古いゲームは高速コンピュータの速度を念頭に置いて設計されていないため、速度は望ましくない場合があります。レベルタイマーが300ゲーム秒の30MHz PC用に設計されたゲームは、300MHz PCではプレイヤーに30秒しか与えられない可能性があります。一部のDOSプログラムなどの他のプログラムは、より高速なコンピュータでは実行されない可能性があります。特に、システムの中核部分への変更が一般的ではない「クローズドボックス」型のコンピュータをエミュレートする場合、ソフトウェアは実行されるコンピュータの特定の特性(例えば、CPUの速度)に依存する技術を使用することがあるため、そのようなアプリケーションを適切にエミュレートするには、エミュレーション速度を正確に制御することが重要です。
前述のとおり、ほとんどのエミュレータはメインシステムバスをエミュレートしません。そのため、各I/Oデバイスは多くの場合、特別なケースとして扱われ、仮想周辺機器用の統一されたインターフェースは提供されません。各I/Oモジュールをエミュレート対象デバイスの特性に合わせて調整できるため、パフォーマンス上の利点が得られる場合があります。しかし、標準的で統一されたI/O APIに基づく設計は、よく考え抜かれていれば、このような単純なモデルに匹敵する性能を発揮でき、さらに、サードパーティ製の仮想デバイスをエミュレータ内で使用できるプラグインサービスを「自動的に」提供するという利点もあります。統一されたI/O APIは、必ずしも実際のハードウェアバスの構造を反映するとは限りません。バス設計は、いくつかの電気的な制約と、ソフトウェア実装ではほとんど無視できるハードウェアの同時実行管理の必要性によって制限されます。
各デバイスを個別のケースとして扱うエミュレータであっても、通常は以下のような共通の基本インフラストラクチャが存在する。

エミュレーションは、デジタル保存と陳腐化対策の戦略の一つです。エミュレーションは、元のコンピュータ環境を再現することに重点を置いており、時間と労力がかかる場合もありますが、デジタルオブジェクト、オペレーティングシステム、あるいはゲームプラットフォームの真正性をより密接に維持できるため価値があります。[ 10 ]エミュレーションは、デジタルオブジェクトの元のハードウェアおよびソフトウェア環境を対象とし、それを現在のマシン上で再現します。[ 11 ] エミュレータを使用すると、ユーザーは現在のプラットフォーム上であらゆる種類のアプリケーションやオペレーティングシステムにアクセスできますが、ソフトウェアは元の環境と同じように動作します。[ 12 ]デジタル保存戦略 としてのエミュレーションの初期の提唱者であるジェフリー・ローゼンバーグは、「理想的なアプローチは、一度設計すれば、あらゆる種類のドキュメントやメディアに均一に、自動的に、そして組織的に同期して(例えば、更新サイクルごとに)適用できる、拡張可能で長期的な単一のソリューションを提供することです」と述べています。[ 13 ] 彼はさらに、これは時代遅れのシステムだけでなく、将来の未知のシステムにも適用できるべきだと述べています。[ 14 ]実際には、あるアプリケーションが新しいバージョンでリリースされた場合、そのアプリケーションの以前のバージョンで作成されたすべてのデジタルオブジェクトの互換性の問題と移行に対処する代わりに、アプリケーションのエミュレータを作成して、それらのすべてのデジタルオブジェクトにアクセスできるようにすることができます。
ニューメディアアートは主にデジタルフォーマットを使用するため、保存戦略としてエミュレーションに大きく依存しています。コーリー・アーカンジェルなどのアーティストは、作品の中で時代遅れのテクノロジーを復活させることを専門としており、デジタル文化の保存には分散型で非制度化されたプロセスが重要であることを認識しています。多くの場合、ニューメディアアートにおけるエミュレーションの目的は、デジタルメディアを保存して、永久に保存でき、エラーなく複製できるようにすることで、老朽化して時代遅れになるハードウェアに依存しないようにすることです。パラドックスは、エミュレーションとエミュレーターが将来のコンピュータでも動作するように作られなければならないことです。[ 15 ]
エミュレーション技術は、新しいシステムの設計と開発において一般的に使用されています。システムが実際に構築される前に、設計上の欠陥を検出、再現、修復する機能を提供することで、開発プロセスを容易にします。[ 16 ]特にマルチコアシステムの設計において有用です。マルチコアシステムでは、仮想ハードウェアによって提供される制御された環境がないと、並行処理エラーを検出して修正することが非常に困難になる場合があります。[ 17 ]また、これにより、ハードウェアが準備できる前にソフトウェア開発を行うことが可能になり、[ 18 ]設計上の決定を検証し、より多くの制御を与えるのに役立ちます。
「エミュレータ」という言葉は、1963 年に IBM [ 19 ]でNPL ( IBM System/360 ) 製品ラインの開発中に、「ソフトウェア、マイクロコード、ハードウェアの新しい組み合わせ」を使用して造語されました。[ 20 ]彼らは、以前の IBM コンピュータ用に書かれたプログラムを実行するために、標準命令のみを使用するソフトウェア シミュレーションではなく、マイクロコードとハードウェアに実装された追加の命令を使用したシミュレーションによって、シミュレーション速度が劇的に向上することを発見しました。それ以前に、IBM は、たとえば705上で650 用のシミュレータを提供していました。[ 21 ]シミュレータに加えて、IBM は709および7090に互換性機能を備えており、[ 22 ] IBM は、IBM 709 コンピュータに、IBM 704用に書かれたレガシー プログラムを709上で、後に IBM 7090 上で実行するためのプログラムを提供しました。このプログラムは、互換性機能によって追加された命令[ 23 ]を使用して、特別な処理が必要な命令を捕捉しました。他のすべての 704 命令は 7090 で同じように実行されました。1410 [ 24 ]の互換性機能では、サポート プログラムではなく、コンソール トグル スイッチを設定するだけで済みました。
1963年、このシミュレーション処理を高速化するためにマイクロコードが初めて使用されたとき、IBMのエンジニアは概念を説明するために「エミュレータ」という用語を作り出しました。2000年代には、ソフトウェアの文脈で「エミュレート」という言葉を使うのが一般的になりました。しかし、1980年以前は、「エミュレーション」はハードウェアまたはマイクロコードの支援によるエミュレーションのみを指し、「シミュレーション」は純粋なソフトウェアエミュレーションを指していました。[ 25 ]例えば、別のアーキテクチャ用に設計されたプログラムを実行するために特別に構築されたコンピュータはエミュレータです。対照的に、シミュレータはPC上で実行されるプログラムであり、古いAtariゲームをシミュレートすることができます。純粋主義者はこの区別を主張し続けていますが、現在では、「エミュレーション」という用語はバイナリコードを実行するマシンの完全な模倣を意味することが多く、「シミュレーション」はコンピュータプログラムを使用して抽象モデルをシミュレートするコンピュータシミュレーションを指すことが多いです。コンピュータシミュレーションは事実上あらゆる科学および工学分野で使用されており、コンピュータサイエンスも例外ではなく、ネットワークシミュレーションなど、コンピュータシステムの抽象モデルをシミュレートするプロジェクトがいくつかあり、これは実際的にも意味的にもネットワークエミュレーションとは異なります。[ 26 ]
ハードウェア仮想化とは、コンピュータを完全なハードウェア プラットフォーム、そのコンポーネントの特定の論理的抽象化、またはさまざまなオペレーティングシステムを実行するために必要な機能のみとして仮想化することです。仮想化は、コンピューティング プラットフォームの物理的な特性をユーザーから隠蔽し、代わりに抽象的なコンピューティング プラットフォームを提供します。[ 27 ] [ 28 ]当初、仮想化を制御するソフトウェアは「制御プログラム」と呼ばれていましたが、時間の経過とともに「ハイパーバイザ」または「仮想マシンモニタ」という用語が好まれるようになりました。[ 29 ]各ハイパーバイザは、複数の仮想マシンを管理または実行できます。
{{cite book}}: CS1 メンテナンス: その他 (リンク)