The Z80's secret feature discovered after 40 years!
The Zilog Z80 has a protected mode. To those of you who know what a Z80 is and what protected mode is, this should be impossible. In fact, it has been impossible for more than 40 years, since the introduction of the original Z80 in 1976. That is until now. Hi, I'm Andy and welcome to my retro attic.
[Music]
Foreign [Music]
How this seemingly impossible feat is pulled off. This is the Zilog Z80, the CMOS version of it to be precise. If you don't know what a Z80 is, there are lots and lots of videos on YouTube that are far better at explaining it than I am. Therefore, I won't go into the details about the history or architecture of this chip. Feel free to pause this video and watch those if you need a recap on a Z80. Links in the description below.
In short, the Z80 is one of the most popular CPUs in history, alongside the 6502. It is the heart of consoles, home computers, game consoles, arcade machines, and more, including this beautiful Sony HitBit MSX2 right next to me. However, you didn't click this video to see what the Z80 can do, but what it cannot, or should I say, what it's not supposed to do.
The Z80 doesn't have a protected mode, which means it cannot run a preemptive multitasking OS. It cannot perform memory protection, it cannot be virtualized, and, most importantly, it cannot stop misbehaving or malicious programs from overriding system variables or accessing sensitive data. The last one is the most frustrating for programmers since it means that like a half-written, buggy program may easily scramble system RAM values and crash the entire computer, making debugging virtually impossible.
These limitations are not simply a result of primitive operating systems of the ‘80s or all programmers not wanting to spend time and space supporting this feature. It was in the hardware. Protected mode requires specific support within the logic circuit of the CPU itself—support that the Z80 does not have, or at least not as a part of its documented features.
[Music]
So today's topic is about a secret undocumented instruction that enables a secret protected mode, right? Well, not really. You see, the Z80 happens to be one of the most studied and most documented CPUs. Features left out by the official documentation have been dug out by people who want to know more about their favorite microprocessor. There are many blogs about reverse engineering the Z80 at silicon level and, like the 6502, the Z80 has its own Z80 visualization website showing the role of each individual transistor in live action. There is even a book named "The Undocumented Z80 Documented," explaining all secret undocumented instructions in great detail.
Therefore, the meaning of the thumbnail of this video is actually twofold: The Z80 can possibly support a protected mode, and second, even if it does, this feature can possibly go unnoticed for 40 years. Or can it?
It turns out that the Z80 does have a little-known feature hidden in plain sight. In order to understand it, we start off at one of its most well-known features: the I/O bus. I think it's safe to assume that most people making it this far into the video would have known that the Z80 uses a separate address space for the memory and I/O operations. As a result, it has an I/O request or IORQ pin to indicate that it is doing an I/O operation.
Now imagine we hooked the IORQ pin directly to the non-maskable interrupt pin (NMI) of the CPU. This will trigger a non-maskable interrupt each time a program does an I/O operation. What does that do, you may ask? Well, at this moment, pretty much nothing, but it gives us a chance to examine the output operation in order to translate the I/O access.
Take the SVI 328 and the MSX as an example. Assume we want to run MSX software on the SVI 328. We can capture each I/O access made by the program, determine which device it is accessing, and forward that access to the corresponding I/O port on the SVI 328. There is only one small problem: the I/O operation issued by our translation program will also trigger a non-maskable interrupt, creating an infinite loop and ultimately overflowing our stack. Therefore, we need some sort of circuit to prevent this from happening.
Here, we use a single RS flip-flop. We connect one of the inputs to the NMI pin and the output Q to an OR gate alongside the IORQ line. Finally, we use the output of the OR gate as the new NMI input. As a result, an NMI will set the flip-flop, preventing further interrupts.
How to reset the flip-flop? Simple, just hook the reset signal to your unused device select on this board. It accesses the flip-flop to go to the original state, waiting for the next I/O access to occur. Another translation program can return control to the original program.
Alright, well not so fast. Remember that the original I/O write operation, the one that triggers the interrupt, didn’t go to nowhere. If a device is present on the wrong I/O port, it will still receive a piece of information. Let's imagine our MSX program makes a write to the VDP register at port 98. Our translator will catch the write and forward it to port 80 on the SVI. However, port 98 on the SVI is the A port of the 8255 PPI (Programmable Peripheral Interface). As a result, the data on the PPI’s GPI opening is probably altered, which can potentially damage our system.
To solve this problem, we just need to add another wire connecting the output of the flip-flop to the enabling of the I/O decoder. If our OS is written carefully enough to reset the flip-flop each time control is returned to our user program, this circuit will ensure that each and every one of our I/O operations is performed by the OS, not some random, potentially buggy, and potentially even malicious user code.
And suddenly, a little Z80 is now running in protected mode. Believe it or not, we are 90% there. The only things left are memory protection and a way for our user program to actually call the system routines other than making a read or write to a port and wait for the system to translate it.
The first one is easy enough since the memory management unit (MMU), commonly found in 386s or 60 or 30s, is just a super beefed-up version of the memory chips for 8-bit computers. Many MMUs are controlled by I/O ports, which are already protected by the circuit we just talked about. Our OS just needs to bank out the system variables in RAM so that they are not visible to the user program and bank them back in whenever a system routine is executed.
Here I choose the simplest kind of mapper: a 256-byte static RAM connected to the high end of the address bus. This will have an added benefit of being able to fill the memory with a single OUT instruction. Another second task is not difficult either, thanks to another feature of the Z80: its RST or reset command. More like the IN command of the x86, it is encoded with five ones and three bits to indicate the reset address. This makes it very easy to detect. By just ending those pins together with the inverted M1 signal, we can then add a gate to the input of the Z80 so the kernel mode is entered whenever an NMI or reset instruction is issued. Plus, such an instruction caused into a routine within the zero page of memory makes a perfect way to do system calls.
And that's pretty much it. I also added other features, but they are all design choices and mostly just to speed things up or provide extra functionality. For example, I used bigger mapper RAM chips to provide hardware-accelerated task swapping, added a second mapper RAM to increase the maximum physical RAM size supported, still two physical address lines to mark a page as non-writable and non-executable in order to tighten memory access control, added a bunch of peripheral chips to provide graphics, sound, a timer, some GPIO, and your input phase.
So, final conclusion: Here is this really a secret Z80 feature that's been hidden for years? No, it's not. It's just a clever combination of several documented features and an external circuit. Technically, this can be done to any 8-bit processors like the 8085, the 8080, and even the 6502 and 6800, but it will be much more difficult and require much more external circuitry because this circuit does rely on some of the Z80's unique features to work efficiently. Namely, the separate I/O address space, the block I/O command with register B output to the high byte of the address bus, and special encoding of the reset instruction.
However, it is almost certain that the Z80 is not designed to be used in this way since many of the Z80's other features will be rendered completely useless, like the powerful interrupt mode 2, the entire multiple interrupt system, including many instructions dedicated to it such as the RETI and RETN, EI and DI, and the IFF registers, and the second set of genuine purpose registers for fast context switch.
I think it's safe to say that Mr. Zilog designed the Z80 to work with his own dedicated chipset running engineering well-tested programs, mainly in embedded systems. Ironically, most Z80s found themselves in desktop and home computers with an Intel chipset running whatever program a user throws at them.
Then is this video clickbait? Yes. Now big disclaimer: I hate clickbait videos, but I did it anyway in the title and thumbnail of this video. To be fair, I did include a hint that this required external hardware at the beginning of this video so that professionals can understand the whole thing and click away at that point if they pay enough attention.
Nonetheless, I have made a clickbait video—the type of video that I hate to see—but I guess this is what you will get from a small YouTuber watching other big virtual channels getting hundreds of thousands of views as soon as a new video is released. But do I think this is cool though? Oh boy, I do! Just imagine what can be achieved by this technique: You can virtualize your computer to create independent virtual machines. You can tweak those virtual machines to emulate different platforms like the Colecovision, the Sega X3 1000, the SVI 328, the MSX, and even the rare MTX 512 made by Memotech, as they share similar hardware.
There can be slowdowns and incompatibilities, but the truth is that few games make use of full CPU time and will run just fine. You can run many programs concurrently. You can implement a virtual VDP in the OS and set aside some RAM to create a shadow VRAM and drag all VDP access of one program, say a spreadsheet, to that virtual VDP, then direct that of another program, say again to the actual screen.
Then you can use a boss key to tell the system to swap the contents of the VRAM and shadow VRAM and exchange the registers of the physical and virtual VDP within seconds so that your boss won't notice you playing Galaga at work. You can even add another physical VDP to your system and run dual monitors with different programs.
Going further, you can also add multiple keyboards or game controllers and map those to different virtual environments, creating a linear stacked-style two gamers, one CPU experience, but with all the ‘80s retro fashion.
That's about it for this video, but before the end of it, I have a small story to tell. During the making of this video, I remember seeing somewhere claiming that the reason why the Z80 has so many undocumented instructions is that Falcon used spare spaces in the edge of the silicon die to implement them as actual instructions.
However, early production units showed that those instructions worked unreliably. As a result, Falcon just dropped those instructions out of the documentation to artificially boost yield since he had now market chips that don't execute those instructions as good ones as the fabrication process made sure most chips run those instructions just fine.
But the instruction set was not updated for consistency as those instructions were originally documented. Once they are very reliable and useful, so many software started using them, causing them to be re-edited in many of the Z80's upgraded versions like the Z180 and R800 as extensions to the instruction set.
I think this story is fun, but I cannot find where I saw it, so I left it out of the script. If anyone knows whether this story is true or not or can point me to the website where I saw it, no matter if it's a true story, please leave a comment below. I would appreciate it. But that's it for today's video for real this time. Bye!
[Applause]