Mac用のエミュレーターを探していると、「Apple Siliconネイティブ対応」「Universal」「Rosetta 2で動作」「JIT対応」「インタープリターのみ」といった言葉が並びます。どれも速度に関わることは分かるのですが、それぞれが何を指していて、どれが自分のMacで効くのかは、意外と説明されていません。

この記事では、これらの言葉を 「ゲーム機のCPU命令を、Macのどこで、どうやって実行しているか」 という1つの軸で整理します。

📌 この記事の3行まとめ
① 「ネイティブ対応」=アプリがApple Silicon(ARM64)のコードで配布されている。「Universal」はIntel用とARM64用の両方を含む
② エミュレーターは、ゲーム機の命令をその場でMacの命令に変換するJIT(動的再コンパイラ) で速くなる。JITはRosetta 2の上では性能が出にくい
③ iPhoneではアプリがJITを使えないが、MacではMac App Storeのアプリでも許可されている。だから同じエミュレーターでもMac版のほうが速い機種がある

「ネイティブ」は、アプリの話

まず、「ネイティブ対応」はアプリの配布形式の話です。

Apple Silicon(M1以降)のMacは、ARM64という命令セットのコードを直接実行します。2020年以前のIntel Macが実行していたのはx86-64というまったく別の命令セットです。Intel向けにしか作られていないアプリをApple Silicon Macで動かすとき、macOSはRosetta 2という翻訳層を自動で挟みます。ユーザーが何かをする必要はなく、多くのアプリはこれで問題なく動きます。

配布ファイルの表記は、次のように読みます。

表記中身Apple Silicon Macでの動き方
Apple Silicon/ARM64/arm64ARM64のコードのみネイティブ
UniversalARM64とx86-64の両方ネイティブ(Intel Macではx86-64側が動く)
Intel/x86-64/x64x86-64のコードのみRosetta 2で翻訳

エミュレーターは、この違いが普通のアプリより大きく効きます。理由は、エミュレーターの中でもう1段「翻訳」をしているからです。

エミュレーターの中で起きていること

エミュレーターは、ゲーム機のCPU(たとえばPlayStation 2のEmotion Engine、ゲームキューブのPowerPC)向けに書かれたゲームの命令を、Macで実行します。方法は大きく2つあります。

インタープリター

ゲームの命令を1つ読み、それが何をする命令かを判定し、対応する処理を実行する、を延々と繰り返します。仕組みが単純で正確に作りやすく、実行可能なメモリを書き換える必要がないので、どの環境でも動きます。反面、命令1つごとに判定と分岐が入るため、負荷の高い機種ではMacのCPUの多くを判定作業に使うことになります。

JIT(動的再コンパイラ)

ゲームの命令のまとまりを、その場でMacのCPUが直接実行できるコードに変換し、変換結果をメモリに置いて実行します。同じ場所を2回目に通るときは変換済みのコードをそのまま実行するので、判定の手間が消えます。ゲームキューブ、PS2、N64のような機種は、実用的な速度を出すためにこの方式に頼ります。

JITが動くには、アプリが「書き込んだメモリを、実行可能なメモリとして扱う」 ことを許可されている必要があります。ここが、この記事の残りの話につながります。

なぜJITはRosetta 2と相性が悪いのか

Rosetta 2は、Intel向けアプリのx86-64コードをARM64に翻訳して実行します。普通のアプリはコードがあらかじめ決まっているので、翻訳は起動前や初回にまとめて済ませられます。

JITを使うエミュレーターは違います。実行中に、新しいx86-64のコードを次々に生成するからです。Rosetta 2はそのたびに、生成されたx86-64コードをARM64に翻訳し直す必要があります。つまり「ゲーム機の命令 → x86-64(エミュレーターのJIT) → ARM64(Rosetta 2)」という二重の翻訳が、実行中にずっと走ります。

だから、Intel向けにしか配布されていないエミュレーターをApple Silicon Macで動かすと、動くには動いても、そのエミュレーターがWindowsやIntel Macで出していた速度にはなりにくいのです。たとえばPlayStation 2エミュレーターのPCSX2は、公式ドキュメントで「M系CPUのMacではRosetta 2を介して動作する」と明記しています。

「ネイティブ対応」のエミュレーターは、JITがARM64のコードを直接生成します。翻訳は「ゲーム機の命令 → ARM64」の1段だけです。

iPhoneでは使えず、Macでは使えるJIT

iOSでは、App Storeから配信されるアプリが実行可能なメモリを自分で書き換えることは許可されていません。iPhoneのエミュレーターがすべてインタープリターで動いているのはこのためで、iOS向けに配信されているRetroArchなども、その制約の中で動いています。

macOSは違います。Hardened Runtimeのもとで、アプリは com.apple.security.cs.allow-jit というエンタイトルメントを宣言することでJITを使えます。これはMac App Storeが受け付ける唯一のJIT用エンタイトルメントで、審査を通ったサンドボックス内のアプリでも許可されます。実行可能なメモリは MAP_JIT で確保し、書き込みと実行を切り替えながら使います。

同じエミュレーターでも「Mac版のほうがiPhone版より速い機種がある」のは、Macの性能差だけではなく、このJITの可否が理由です。

「ネイティブ対応」でも、機種ごとに違う

ここまでを踏まえると、エミュレーターの説明文にある「ネイティブ対応」は、さらに機種ごとに読み分ける必要があることが分かります。

同じアプリの中でも、機種(コア)によって、JITを持つものとインタープリターしかないものがあります。当社のemuを例にすると、次のようになります。

機種Mac版での実行方式
ゲームキューブ(Dolphinコア)ARM64向けJIT
PlayStation 2(Play!コア)ARM64向けJIT
NINTENDO 64(aresコア)ARM64向けJIT
PSP(PPSSPPコア)インタープリター
セガサターン(Yaba Sanshiroコア)ソフトウェアレンダリングのインタープリター
Xbox(xemuコア)実行可能メモリを使わない方式
NES・SNES・GB・GBA・MD・SMS・GG・PCE・NGP・WS(aresコア)インタープリター(負荷が低く十分な速度)

負荷の低い8bit・16bit機はインタープリターで十分な速度が出ます。JITが本当に効くのは、ゲームキューブ・PS2・N64のような、Macの1コアを使い切りかねない機種です。emuがApple Silicon限定(M1以降、macOS 14以降)で、Intel Macに対応していないのは、この3機種のJITをARM64向けだけに絞っているからです。

描画も「翻訳」している

CPUだけでなく、GPUにも同じ構図があります。多くのエミュレーターはVulkanやOpenGLで描画しますが、macOSが直接サポートするのはMetalです。VulkanのエミュレーターをMacで動かすときは、MoltenVKという変換層を挟むのが一般的で、これも性能と互換性に影響します。Wii UエミュレーターのCemuのように、Metalバックエンドを開発中のプロジェクトがあるのはこのためです。

自分のMacで確認する方法

いま動いているアプリがネイティブかRosetta 2かは、macOSのアクティビティモニタで確認できます。「CPU」タブの表の見出しを右クリック(またはcontrolキーを押しながらクリック)して「種類」 列を表示すると、各プロセスに「Apple」または「Intel」と表示されます。「Intel」がRosetta 2経由です。

アプリを入れる前に知りたい場合は、配布ページの表記(Universal/Apple Silicon/Intel)と、Finderでアプリを選んで「情報を見る」を開いたときの「種類」欄(「アプリケーション(Universal)」「アプリケーション(Intel)」)で分かります。

まとめ

  • ネイティブはアプリの配布形式の話。Universalなら、Apple Silicon Macではネイティブで動く
  • JITはエミュレーターの内部方式の話。ゲームキューブ・PS2・N64のような機種の速度を決める
  • JITを持つエミュレーターほど、Rosetta 2の上では本来の速度が出にくい。「ネイティブ対応」が効くのはここ
  • iPhoneではJITが使えず、Macでは使える。同じアプリでもMac版のほうが速い機種があるのはこのため
  • 「ネイティブ対応」でも、機種ごとにJITかインタープリターかは異なる。遊びたい機種で確認する

関連する記事

Macで配布されている各エミュレーターのApple Silicon対応状況は、Macで使えるエミュレーター一覧に比較表でまとめています。この記事の内容を実際の設計に落とし込んだ経緯は、emu for Macのリリース記事をご覧ください。

emuをMac App Storeで見る(1,000円)