Study of the Techniques for Emulation Programming
Total Page:16
File Type:pdf, Size:1020Kb
Study of the techniques for emulation programming (By a bored and boring guy) The Author: Victor Moya del Barrio Director: Agustin Fernandez Computer Science Engenieering – FIB UPC 18 June 2001 2 Contents Chapter 1. Introduction. 9 1. Motivation and purpose of the study. 9 2. What do we call an emulator? 10 3. Small history of emulation. 11 4. Related topics. 12 Chapter 2. Introduction to the process of emulation. 14 1. Basic structure/algortihm of an emulator. 14 2. The CPU emulation core. 17 2.1. CPU emulator: Interpreter 18 2.2. CPU emulator: Binary Translation. 18 3. The memory emulation subsistem. 20 4. CPU and emulated devices communication. Interrupts and timing. 21 5. Graphic hardware emulation. 22 6. Sound hardware emulation. 23 7. Other devices. 24 8. Testing the emulator. 24 9. Searching for information and other aspects of emulation. 25 Chapter 3. CPU emulation: Interpreters. 26 1. Basic interpreter CPU emulator. 26 The CPU status. 26 The fetch-decode loop. 30 Instruction emulation. 36 Flags. 38 Memory. 39 Interrupts. 41 Core interface. 42 Appendix A: Space Invaders/i8080 Tutorial. 44 2. Assembly Emulators. 44 Portabilty vs performace. 45 Similiraties between CPUs. 46 Register usage. 46 Optimizations. 47 Code emitters vs assembly macros. 50 3. Threaded Code. 51 3 Basic concept behind threaded code. 52 Types of threaded code. 55 Implementation of threaded code. 56 Related works. 58 4. Advanced questions about interpreters. 58 Intepreters for simulators. 58 First pass interpreter and profiler. 59 Advanced: Inlining. Pipelined interpreters for VLIW CPUs. 60 Integrated CPU cores. 61 Using library CPU cores. 62 Related works. 62 Chapter 4. CPU emulation: Binary translation. 64 1. Introduction to binary translation. 64 Binary translation. 64 Types of binary translation. 67 Basic concepts. 69 Examples. 69 2. Static binary translation. 70 Basic algorithm. 71 Intermediate representations. 72 Local and global optimizations. 73 Code generation. 74 Run-time. 75 Implementations. 76 3. Dynamic binary translation. 77 Basic algorithm of dynamic binary translation. 78 Translation cache. 82 Interpreter and profiler. 83 Translation unit. 84 Optimizations. 85 Register allocation. 86 Code generation. 86 Implementations. 87 Chapter 5. Memory, Interrupts and Timing. 89 1. Memory Emulation. 89 Memory Map. Region list. 91 Memory banking. 93 Other implementations. 94 Memory management unit (MMU). 95 Endianness and CPU data size. 97 2. Interrupts and exceptions. 100 Interrupts. 100 Exceptions. 101 3. Timing. 101 4. Others. 103 High level emulation (HLE). 104 Float point emulation. 104 Vector instruction emulation. 105 4 Chapter 6. Graphic emulation. 106 1. Graphics in computers. 106 2. Types of graphic hardware. 107 3. Tiled basedgraphic engine emulation. 110 The SMS VDP. 111 The background layer. 111 The sprite layer. 113 Handling priorities. 113 The palette. 116 Vertical and horziontal interrupts. 117 Emulating the SMS VDP. 118 A more advanced VDP: Genesis. 121 4. Plain 2D graphic generation. 123 5. How to find more information. 124 Chapter 7. Sound emulation. 126 1. Sound in computers. 126 2. Types of sound hardware. 126 3. Wave generator based sound hardware. 128 PSG emulation. 129 FM emulation. 133 4. Sample based sound generation. 135 5. How to find more information. 137 Chapter 8. Information, testing and legal. 138 1. The information. Research. Reverse engineering. 138 2. Testing and debugging. 138 3. Legal and commercial aspects of emulation. 139 Chapter 9. Conclusions. 141 1. Initial objectives. 141 2. Objectives acomplished. 141 3. Further work. 142 References. 143 Bibliography. 145 5 Acknowledgements. 151 Appendix A. Space Invaders and i8080 emulation tutorial. 152 Appendix B. CD-ROM contents. 152 Appendix C. User manuals. 152 6 Index of figures. Figure 1. Von Neuman architectore. 14 Figure 2. Basic emulator main algorithm. 15 Figure 3. Interpreter emulator. 18 Figure 4. Endianness. 21 Figure 5. CPU context structure (i8080 emulator). 28 Figure 6. Multisize register emulation using union data type. 29 Figure 7. Multisize register emulation using pointers and type cast. 29 Figure 8. Example of CPU flags. 30 Figure 9. Opcode examples. 31 Figure 10. CPU core main loop. 32 Figure 11. RISC instruction decoding (fixed lenght). 33 Figure 12. RISC instruction decoding (variable lenght). 33 Figure 13. Decoding using conditional statements. 34 Figure 14. Decoding using switch-case statement. 35 Figure 15. i8080 instruction description (8080 datasheet). 36 Figure 16. Instruction basic algorithm. 36 Figure 17. Some i8080 instruction implementation. 38 Figure 18. Flag calculation in the i8080 emulator. 39 Figure 19. Direct access to the memory buffer. 40 Figure 20. Access through a list of memory regions. 40 Figure 21. Memory banks and emulation. 41 Figure 22. i8080 emulator CPU interface. 44 Figure 23. Z80 to x86 flag calculation. C and asm version. 48 Figure 24. m68000 SUBX instruction in x86 (Bart Trzy Gen68K). 48 Figure 25. Timing update and instruction decode inlined at the end of the instruction. 49 Figure 26. A single function or multiple functions for each instruction type (mov rd. rs) 50 Figure 27. Using macros for expanding generic instruction implementation. 50 Figure 28. Using a code emitter for generating multiple versions. 51 Figure 29. Normal emulation vs threaded code emulation. 53 Figure 30. Static threaded code emulator. 54 Figure 31. Dynamic threaded code emulator. 54 Figure 32. Example of NEXT. 55 Figure 33. Indirect threaded code. 55 Figure 34. High level emulation of threaded code. 57 Figure 35. Threaded code and macroopcodes. 60 Figure 36. Interpreter pipelining. 61 Figure 37. Binary translation and compilers phases. 65 Figure 38. Binary translation with or without IR. 65 Figure 39. Types of binary translation. 67 Figure 40. Static translation algorithm. 71 Figure 41. Dynamic binary translation algorithm (interpreter profiler based). 79 Figure 42. Dynamic binary translation algorithm (pure). 81 Figure 43. Translation cache. 83 Figure 44. Intrepreter + profiler. 83 Figure 45. Master System memory map (banks, page registers). 90 Figure 46. Genesis memory map (with memory mapped IO). 91 Figure 47. Master System memory and IO region lists. 92 Figure 48. ReadByte() through a memory region list. 93 Figure 49. Bank access emulation. 94 Figure 50. Vector based memory access. 95 Figure 51. Endianness. 97 Figure 52. Endianness conversion algorithm (basic). 98 Figure 53. Access modes for byte swapped memory buffers. 99 Figure 54. Screenshot of Star Wars vector game. 108 Figure 55. Framebuffer and palette graphic system overview. 109 Figure 56. BG and sprite layers. 111 Figure 57. Background layer. 112 7 Figure 58. Background and scrolling. 113 Figure 59. Background and sprite layer with priorities in the Master System. 115 Figure 60. Palette overview. 116 Figure 61. Vertical and Horizontal retrace and signals. 118 Figure 62. Pixel codification in Master System pattern lines. 119 Figure 63. Genesis VDP overview. 121 Figure 64. Framebuffer based system. Blit. 124 Figure 65. SN6489 schematics. 130 Figure 66. PSG sound generation algorithm. 132 Figure 67. Envelopes for FM sound generation. 134 Figure 68. YM2413 schematics. 135 Figure 69. Sample based sound generation. 137 8 Chapter 1. Introduction. 1. Motivation and Purpose of the Study. I still remember the first emulator I ever tested, it was Marat Fayzullin’s VGB-DOS, an early GameBoy emulator for MS-DOS, ... or it was FMSX-DOS, the MSX emulator by the same author? In any case that was my first introduction to emulation. Since that date, in the last six years, I have been using, playing and enjoying with console, home computer and arcade machine emulators. And perhaps also learning a bit, about how those machines worked, about how (good, very good) the games were and how an emulator works. I planned many times how I could introduce myself in the world of emulation. Programming an emulator was the first choice in any case, I have been more or less a programmer for almost ten years now so it made sense. I always have enjoyed with the hardware internals and assembler programming. And although now I’m a (modest one) emulator programmer I want also to contribute in another way (because who will actually play with my boring emus?) to the emulation scene. In the time I started to learn about how an emulator is programmed I found that there was a limited amount of documentation. Documentation about how an emulator should be programmed or about the characteristics of the machines to be emulated. Thinking about how to contribute to the emulation I found that the second part would mean the construction of a database with all the information available of a large amount of computers and systems. This wasn’t very suited neither with a university project for with my own preferences, and there are a few sites in Internet which more or less serve to that purpose. The first part meant to study and learn the various techniques and knowledges related to emulator programming. Since I like a lot learning and also writing I thought that could be my way to contribute. So I thought it would be nice to have a large, ordered and precise documentation about how to program an emulator. That is the purpose of this document and my work in the last months. After about a year of study, programming and thinking (well, only sometimes) I think now that a ‘complete’ document about emulation programming is almost impossible. There are too many specific techniques, too many ways to implement things and many kinds of hardware to emulate. And for each kind of hardware there are ways best suited than others. Nor to say that every programmer has it owns ideas and preferences, and they can be all correct. So I think that finally this document will be just generic, rather complete, but specific in some important points, about programming emulators. Perhaps it will not arrive to be a real reference about emulation programming but I hope it will be useful for someone, like many other documents from other people were useful for me.