In this tool-assisted programming video, I create a portable emulator for a certain architecture that can run Linux, using C++11. The source code is about 780 lines in total.
Patreon: https://patreon.com/Bisqwit (alternatives at https://iki.fi/bisqwit/donate.html)
Approximate count of lines of code per topic, in the source code:
- 80 lines, CPU: Registers and constants
- 230 lines, CPU: Interpreting and parsing CPU opcodes
- 80 lines, CPU: Exceptions and Interrupts
- 100 lines, CPU: Memory Management Unit (MMU)
- 50 lines, I/O framework: Memory map, endianness and integer sizes
- 50 lines, Device: UART (console I/O)
- 60 lines, Device: Timer
- 50 lines, Device: Interrupt Controller
- 20 lines, Loading of Linux kernel from disk file
- 60 lines, (other, and inaccuracies in the above numbers)
All resources concerning this video can be downloaded from https://bisqwit.iki.fi/jutut/kuvat/programming_examples/microblaze/ .
I do not own a MicroBlaze chip, nor any FPGA platform by Xilinx or anyone else.
I just wanted to create an emulator that can run Linux, inspired by Fabrice Bellard's JSLinux at http://bellard.org/jslinux/ .
For the emulator programming example that I wanted to create, I started looking for the simplest possible platform that can run Linux, and from reading GXemul source code, I initially went with DEC Alpha.
However, after writing most of the CPU emulator for Alpha, I perceived that by adding the remaining parts, such as PALCODE emulation, the emulator easily grows far beyond what people could read and understand in 15 minutes (YouTube's currently enforced limit on my account). Thus I gave up with DEC Alpha.
Then, when studying QEMU source code, I learned about MicroBlaze.
I downloaded the official documentation of MicroBlaze, and found that it was possible to emulate it with a relatively few lines of code.
I had the kernel up and booting in a few days, but I ran into serious problems when trying to get userspace programs work. Turns out, the GNU toolchain for MicroBlaze is not as robust as I thought it would be. I won't enumerate the exact list of problems I had, but metaphorically speaking, I spent two weeks wading a poisonous swamp, trying to find a way around thorny bushes that seemed to extend for miles in all directions. It was quite exhausting.
Thanks to the MicroBlaze target GCC maintainer, Michael Eager, for being patient with me and my many questions and/or complaints.
In the end, I settled for less-than-perfect and this is what you have. After all, my focus was in the emulator, not in Linux...
Examples on how the MicroBlaze CPU differs from Intel 386/Pentium family (x86):
- Many categories of instructions are optional, even ones that have been always present on x86.
- All instructions are 32 bits in length (with an optional 32-bit prefix for long immediates). In x86, instructions are of varying lengths.
- All memory access must be properly aligned. In x86, only a handful of SIMD instructions require memory addresses to be aligned.
- MicroBlaze is big-endian (12345678h is stored in memory as 12 34 56 78). x86 is little-endian (78 56 34 12). There is also a little-endian version of MicroBlaze.
- MicroBlaze has instructions with a "delay slot", where a branch/return will not take immediately effect, but after one extra instruction. x86 does not have delay slots.
- Support for "flags" is very minimal. Only a handful operations support the carry flag. With x86, almost every operation affects the zero, sign, carry and other flags.
- Floating point functionality is greatly reduced, and in fact, optional. In x86, the FPU is built-in (since Pentium), and supports more precision.
- The TLB is software-managed, by the kernel software. In x86, it is hardware-managed from the paging tables that are stored in system RAM.
Apologies if the text's tininess bothers anyone. From my previous videos I received feedback suggesting that I should try to maintain a broader visual to the source code rather than zooming in at times for focus, so I did exactly that. I also experimented with some ways to keep the aspect ratio natural even as it varies. Tip: HD.
The ending cuts a few seconds short due to an unidentified encoding mishap. I put the text in annotations instead.
The music in this video is played through ADLMIDI using OPL3 emulation.
The songs are from SNES games Thunder Spirits, Bahamut Lagoon and Fire Emblem 4.
I do some tool-assisted voiceover in the video. I had great fun doing that, not taking my cumbersome pronounciation too seriously. English is very difficult to pronounce, very difficult sequences of consonants and sometimes hard to choose the right phonemes to begin with. I have found Hebrew and Japanese to be significantly easier.
Anyway, does anyone want to contribute closed-captions?