Emulasi adalah bidang multi-segi. Berikut adalah ide-ide dasar dan komponen fungsional. Saya akan memecahnya menjadi beberapa bagian dan kemudian mengisi rincian melalui suntingan. Banyak hal yang akan saya uraikan akan membutuhkan pengetahuan tentang cara kerja prosesor - pengetahuan perakitan diperlukan. Jika saya agak terlalu kabur dalam hal-hal tertentu, silakan ajukan pertanyaan agar saya dapat terus meningkatkan jawaban ini.
Ide dasar:
Emulasi bekerja dengan menangani perilaku prosesor dan komponen individual. Anda membangun masing-masing bagian sistem dan kemudian menghubungkan potongan seperti kabel dalam perangkat keras.
Emulasi prosesor:
Ada tiga cara menangani emulasi prosesor:
- Penafsiran
- Kompilasi dinamis
- Kompilasi ulang statis
Dengan semua jalur ini, Anda memiliki tujuan keseluruhan yang sama: mengeksekusi kode untuk memodifikasi keadaan prosesor dan berinteraksi dengan 'perangkat keras'. Status prosesor adalah konglomerasi register prosesor, interrupt handler, dll untuk target prosesor yang diberikan. Untuk 6502, Anda akan memiliki sejumlah bilangan bulat 8-bit yang mewakili register: A
, X
, Y
, P
, dan S
; Anda juga akan memiliki PC
register 16-bit .
Dengan interpretasi, Anda mulai pada IP
(penunjuk instruksi - juga disebut PC
, penghitung program) dan membaca instruksi dari memori. Kode Anda mem-parsing instruksi ini dan menggunakan informasi ini untuk mengubah kondisi prosesor seperti yang ditentukan oleh prosesor Anda. Masalah inti dengan interpretasi adalah bahwa itu sangat lambat; setiap kali Anda menangani instruksi yang diberikan, Anda harus memecahkan kode dan melakukan operasi yang diperlukan.
Dengan kompilasi ulang yang dinamis, Anda beralih pada kode seperti interpretasi, tetapi alih-alih hanya menjalankan opcode, Anda membangun daftar operasi. Setelah Anda mencapai instruksi cabang, Anda mengkompilasi daftar operasi ini ke kode mesin untuk platform host Anda, kemudian Anda men-cache kode yang dikompilasi ini dan menjalankannya. Kemudian ketika Anda menekan kelompok instruksi yang diberikan lagi, Anda hanya perlu menjalankan kode dari cache. (BTW, kebanyakan orang tidak benar-benar membuat daftar instruksi tetapi mengompilasinya ke kode mesin dengan cepat - ini membuatnya lebih sulit untuk dioptimalkan, tapi itu di luar cakupan jawaban ini, kecuali cukup banyak orang yang tertarik)
Dengan kompilasi ulang statis, Anda melakukan hal yang sama seperti pada kompilasi ulang dinamis, tetapi Anda mengikuti cabang. Anda akhirnya membangun sepotong kode yang mewakili semua kode dalam program, yang kemudian dapat dieksekusi tanpa gangguan lebih lanjut. Ini akan menjadi mekanisme yang hebat jika bukan karena masalah berikut:
- Kode yang tidak ada dalam program untuk memulai (misalnya dikompresi, dienkripsi, dihasilkan / dimodifikasi saat runtime, dll) tidak akan dikompilasi ulang, sehingga tidak akan berjalan
- Sudah terbukti bahwa menemukan semua kode dalam biner yang diberikan setara dengan masalah Berhenti
Ini bergabung untuk membuat kompilasi statis sepenuhnya tidak mungkin dilakukan pada 99% kasus. Untuk informasi lebih lanjut, Michael Steil telah melakukan penelitian besar dalam kompilasi statis - yang terbaik yang pernah saya lihat.
Sisi lain dari emulasi prosesor adalah cara Anda berinteraksi dengan perangkat keras. Ini benar-benar memiliki dua sisi:
- Waktu prosesor
- Penanganan interupsi
Waktu prosesor:
Platform tertentu - terutama konsol yang lebih tua seperti NES, SNES, dll - mengharuskan emulator Anda memiliki waktu yang ketat agar sepenuhnya kompatibel. Dengan NES, Anda memiliki PPU (unit pengolah piksel) yang mengharuskan CPU memasukkan piksel ke dalam memorinya pada saat-saat yang tepat. Jika Anda menggunakan interpretasi, Anda dapat dengan mudah menghitung siklus dan meniru waktu yang tepat; dengan kompilasi dinamis / statis, semuanya menjadi / lot / lebih kompleks.
Penanganan interupsi:
Interupsi adalah mekanisme utama yang berkomunikasi dengan perangkat keras oleh CPU. Secara umum, komponen perangkat keras Anda akan memberi tahu CPU apa gangguan yang dipedulikannya. Ini cukup mudah - ketika kode Anda memberikan interupsi yang diberikan, Anda melihat tabel penangan interrupt dan memanggil callback yang tepat.
Emulasi perangkat keras:
Ada dua sisi untuk meniru perangkat perangkat keras yang diberikan:
- Meniru fungsi perangkat
- Meniru antarmuka perangkat yang sebenarnya
Ambil kasus hard drive. Fungsionalitas ditiru dengan membuat penyimpanan backing, rutinitas baca / tulis / format, dll. Bagian ini umumnya sangat mudah.
Antarmuka sebenarnya dari perangkat ini sedikit lebih kompleks. Ini umumnya merupakan kombinasi dari register yang dipetakan memori (mis. Bagian memori yang diperhatikan oleh perangkat untuk melakukan pensinyalan) dan menyela. Untuk hard drive, Anda mungkin memiliki area yang dipetakan memori tempat Anda menempatkan perintah baca, tulis, dll, lalu baca kembali data ini.
Saya akan membahas lebih detail, tetapi ada sejuta cara Anda bisa melakukannya. Jika Anda memiliki pertanyaan khusus di sini, jangan ragu untuk bertanya dan saya akan menambahkan informasinya.
Sumber:
Saya pikir saya sudah memberikan intro yang cukup bagus di sini, tetapi ada satu ton area tambahan. Saya sangat senang membantu dengan pertanyaan apa pun; Saya sudah sangat kabur dalam sebagian besar ini hanya karena kompleksitas yang sangat besar.
Tautan Wikipedia wajib:
Sumber daya emulasi umum:
- Zophar - Di sinilah saya memulai dengan emulasi, pertama mengunduh emulator dan akhirnya menjarah arsip dokumentasi mereka yang sangat besar. Ini adalah sumber daya terbaik mutlak yang mungkin Anda miliki.
- NGEmu - Tidak banyak sumber daya langsung, tetapi forum mereka tidak ada duanya.
- RomHacking.net - Bagian dokumen berisi sumber daya mengenai arsitektur mesin untuk konsol populer
Proyek emulator untuk referensi:
- IronBabel - Ini adalah platform emulasi untuk .NET, ditulis dalam Nemerle dan mengkompilasi ulang kode ke C # on the fly. Penafian: Ini adalah proyek saya, jadi maafkan colokan yang tidak tahu malu.
- BSnes - Emulator SNES yang mengagumkan dengan tujuan akurasi siklus sempurna.
- MAME - The arcade emulator. Referensi yang bagus.
- 6502asm.com - Ini adalah emulator JavaScript 6502 dengan forum kecil yang keren.
- dynarec'd 6502asm - Ini adalah hack kecil yang saya lakukan selama satu atau dua hari. Saya mengambil emulator yang ada dari 6502asm.com dan mengubahnya untuk secara dinamis mengkompilasi ulang kode ke JavaScript untuk peningkatan kecepatan besar.
Referensi kompilasi ulang prosesor:
- Penelitian tentang kompilasi statis yang dilakukan oleh Michael Steil (dirujuk di atas) memuncak dalam makalah ini dan Anda dapat menemukan sumber dan semacamnya di sini .
Tambahan:
Sudah lebih dari setahun sejak jawaban ini diajukan dan dengan semua perhatian yang didapat, saya pikir sudah waktunya untuk memperbarui beberapa hal.
Mungkin hal yang paling menarik dalam persaingan saat ini adalah libcpu , dimulai oleh Michael Steil yang disebutkan di atas. Ini adalah perpustakaan yang dimaksudkan untuk mendukung sejumlah besar inti CPU, yang menggunakan LLVM untuk kompilasi (statis dan dinamis!). Itu punya potensi besar, dan saya pikir itu akan melakukan hal-hal hebat untuk dicontoh.
emu-docs juga telah menarik perhatian saya, yang menampung repositori sistem dokumentasi yang bagus, yang sangat berguna untuk tujuan emulasi. Saya belum menghabiskan banyak waktu di sana, tetapi sepertinya mereka memiliki banyak sumber daya yang hebat.
Saya senang posting ini telah membantu, dan saya berharap saya bisa keluar dari pantat saya dan menyelesaikan buku saya pada subjek pada akhir tahun / awal tahun depan.