cj7hawk
Veteran Member
FWIW, here’s another place where the “Z80 = CP/M” framework you’ve adopted here breaks down. ”Proper” portable CP/M software isn’t written for the Z80, it targets the 8080, and while a few programs violated that rule late in the life of the platform for the most part it stuck. (I’m not going to count here programs that were really written specifically for Amstrad CPCs or MSX or whatever because those are obviously *not* portable CP/M programs.)
The Z80 is 8080 binary backwards compatible. Great. But it’s also not really better than an 8080 unless you take advantage of its enhancements and then, BAM, you’re not actually writing according-to-Hoyle CP/M programs anymore, are you? The 8088 is *not* binary compatible… but Intel went to significant lengths to make it Assembly *source* compatible. If you machine translate 8080 source to x86 the results aren’t as good as if you sat down and rewrote it from scratch, sure, but for a quick and dirty start of a port *it worked mostly fine*. So… this seems obvious, doesn’t it? If enhancing for Z80 breaks backwards compatibility for new programs for your computer with the legacy platform it’s supposedly compatible with, why not just rip the bandaid off and go to an even more capable CPU that makes it easy enough to bring stuff forward that a lot of software just needs to be reassembled? Because of the nature of CP/M moving to a new computer always needed patching for the video terminal and stuff anyway…
I dunno, it’s almost like Intel knew what they were doing or something.
You may be overthinking my original premise. It's not a zilog/intel thing in my mind - it's like a PC vs CP/M thing, and I would probably lump the z80, 8080 and 8085 together in a single high level architecture... And yes, I'm probably one of the only writers of such z80-only CP/M OS software since I use the Index Registers a lot. Most of my early z80 code was probably nearly entirely 8080 compatible, but when I wrote my first emulator as a part of the Loki project, it really reminded me about all of the other instructions and I spent enough time with them to want to use them. So my current code is z80 CP/M compatible and not really CP/M conforming.
The discussion has brought up some interesting thoughts.
There is a thought experiment what-if article about this at http://www.desertpenguin.org/blog/what-if-the-zilog-z180-z280.html that I think is a good read, even if it does gloss over the 68000 and 6502 and all the systems based on them. The 68000 was and is a great chip, and really should have been the basis for the IBM PC, but not to be. 8088 was just too similar to the 8085 and associated peripheral chips....but the reasons IBM went 8088 are better documented by experts with more knowledge of those circumstances than I in other places.
The thought experiment is interesting, but I think that had DRI produced PCDOS that PCs would no longer be around today... Maybe they would have held on until OS/2 came out. Then who knows what direction they would have gone.
I doubt Microsoft would have gotten into the OS business... The deal with IBM made them and set them down that path
This is the standard alternate universe line and, sure, a 68000 based PC would have been great, but the resulting machine would have been gobsmackingly more expensive, and the chip wasn’t even really available in quantity yet when IBM went shopping. If the base price of the PC had been $5,000 instead of $1,595 and it came out a year later I’m definitely thinking we’d all be using something else today. Very possibly Macintoshes, or machines descended from Atari ST-style knockoffs.
What would have possibly made a difference, though it's time was yet to come, was overclocking.
We didn't really see widespread overclocking before the 486 came out - not on any real scale that I can remember. People clocked their CPU at whatever it was rated at.
But from 1985 onwards, 30 Mhz could have been quite reliably achieved with the CMOS z80 as has been demonstrated. And that would have kickstarted the need for speed and if you add a pipelined architecture, maybe something like the ez80 would have come out around 1988.
It's interesting that this approach has only been proven in recent years. But at 30MHz a z80 would outperform a typical 12 MHz 286 and probably even a 16 MHz one. All for the cost of a cheap home computer.
Also, a good MMU strategy can easily do the same as segmenting. All you would need is a jump table that set the MMU to switch in the correct pages and make the jump and a similar return strategy. This could have been implemented in an assembler as "LJUMP and LRET" with a known routine in stable memory space to make the jump. That's what I did to move my video drivers entirely out of the TPA. I preserve the AF pair, set the MMU update byte the reconfigure the main memory space and then make the jump. I return the same way. In CP/M I have to preserve the stack as well, but that could be omitted if a shared stack segment was used. Even so, a long jump in such a table is only 8 bytes long and the return only 5-7 bytes since it also has to restore the stack and an interrupt return is a bit longer. I store the common return at 0050 and 0055 and then I can install drivers at any RST ( I use 0040 and 0048 since CP/M doesn't define this space ).
z80 would have been cheap and screamed along enabling a new wave of software. Memory of the era would have needed quite a few wait states though, but at that kind of speed, even LDIR should eliminate the need for DMA and outperformed the z80 DMA which was only around 4MHz then IIRC.
Though overclocking was talked about back then, it was still a long way from being accepted IIRC in 1985
As a better description, this is the code I use for installing a "Long Jump" dynamicaly - it's not as clean as segments, but a compiler or assemble would have no problems with it;
INTHOOK: ; Code to hook the Interrupt, Install the device driver, rebuild the handler and write it all to M:
LD DE,VIDEO
LD HL,INT40
LD BC,$08
LDIR ; Install RST40 hook.
LD DE,$0050
LD HL,RET50
LD BC,$05
LDIR ; Install RET50 return hook.
LD DE,$0055
LD HL,RET55
LD BC,$07
LDIR
ret
INT40: ; Standing to copy relative code to move to $0040 (VIDEO). 8 bytes.
PUSH AF ; Protect the A register.
LD A,$08 ; We're going to run video as Process 8 (reserved)
OUT (PID),A ; Switch to the Video Process.
JP $1000 ; Jump to the next segment at the 4K Boundary where the real handler lies.
; Map - $0000 to $0FFF - Handler, Install routines, Initialise routines.
; $1000 to $1FFF - Routines.
; $2000 to $2FFF - More Routines.
; $3000 to $3FFF - Video Map (Character Based )
; RET50 is 5 bytes exactly.
RET50: ; Return location for 50 where we install the "Return to previous call".
OUT (PID),A ; Switch to the calling process. ( A contains the process - don't set it here. )
POP AF ; Recover A ( and maybe other registers )
ret ; And return to where we were called from.
; Note - Return programs from 50 to 5B...
NOP ; So I can see a single 0.
; DO NOT CHANGE THE ABOVE....... below follows on.
RET55: ; RET55 is exactly 7 bytes.
OUT (PID),A ; Switch to the calling process.
POP AF
RETI ; And the RETI version if it's called by an interrupt.
NOP
NOP