2

CP/M was mostly portable across systems but most of them were z80 based. It was ported to 8086, 68000 and maybe more but without binary compatibility.

No z80 systems that wanted CP/M compatibility often had an additional z80 just for this (c128, BBC, apple II, etc...)

What prevented, at least on more powerful 68000 and 8086 systems, the creation of a loader that translated z80 instructions in native machine language?

I guess self modifying code was not used on professional CP/M applications like dBASE 2, etc...

8
  • 3
    Opinion: the more "powerful" systems were simply not powerful enough. Data point: There was an Apple II (6502) emulator for the early IBM PC, which also on the faster ones was still slower than the original Apple. Now that was emulation, not translation, but still. Another datapoint: QEMU (which to my knowledge does translation) was first released in 2003.
    – dirkt
    Commented Aug 10, 2023 at 13:31
  • @dirkt Yes, after all, the memory thruput of a 4.77 MHz PC/XT is at max 1.1 MiB/s. Close to what a ~1 MHz 6052 or a ~3 MHz Z80 offers. So even with either CPU as hardware it would barely be equal. Which it could have worked out with translated code, as it is asked about,but never using a full emulation.
    – Raffzahn
    Commented Aug 10, 2023 at 14:19
  • 1
    Self-modifying code is actually quite hard to avoid - basically the operating system must tell the hardware which part of memory contains code so trying to write to those parts of memory was caught. That took quite a while to get on personal machines - for PC's you needed 286 and 386 which in turn had much more memory. Commented Aug 10, 2023 at 14:31
  • Not for CP/M, but for another famous Z80 computer: There were quite a number of Sinclair ZX Spectrum emulators for the Sinclair QL, at least one of them claiming to support on-the-fly transcoding features. They ran with acceptable (close to original or even faster) speed if you upgraded to a full 68000 or 68020.
    – tofro
    Commented Aug 10, 2023 at 15:05
  • @ThorbjørnRavnAndersen - What you're describing is the OS enforcing rules against self-modifying code: that needs some kind of hardware support. It's actually not hard for the developer to avoid. But translation is nevertheless not easy as data is mixed with code in R/O segments - e.g., jump tables, and those aren't clearly marked for a translator to find. There's a lot of literature on translation of machine code - on-the-fly and otherwise. Takes a lot of work to accomplish.
    – davidbak
    Commented Aug 10, 2023 at 16:42

3 Answers 3

9

TL;DR:

Early on the user side need was covered by hardware add on, as software couldn't deliver, while later on (>1985) no market existed to pay for such a product.


CP/M was mostly portable across systems but most of them were z80 based.

While many CP/M systems were Z80 based, CP/M software tend to stay within 8080 boundaries. That was not so much due to the Z80 gains being minor, but a basic need to be compatible across all platforms.

What prevented, at least on more powerful 68000 and 8086 systems, the creation of a loader that translated z80 instructions in native machine language?

Nothing. The question is rather who would have the benefit and be willing to pay for it. After all, such software would be more than a weekend job when done as a product. It's way more challenging than emulating a CPU - not to mention that it would still need an OS translation layer in addition.

Anyone who willing to spend money did rather go for straight hardware add on. There existed several cards for the PC, like the BabyBlue, as well as add-ons for 68k machines like the Atari ST. Of course, one could also use an emulator - which came with some speed penalty(*1).

The situation was different for manufacturers of software. For them, source (semi-) automated conversation was the way to go - such as XLT86 for 8080 to 8086 Assembler.

The 1984 NEC V20 finally offered cheap way to get a hardware-supported 8080 emulation, enabling users to run CP/M software on a PC (XT), needing only a thin call and OS translation layer. Except, by 1984 CP/M-80 was already on the way out. Software manufacturers delivered native versions of their products, or had switched development completely over to DOS. Which usually came with switching for a more modern language such as Pascal or C. At that time interest in CP/M compatibility was mostly a wish in the home/hobby market - not exactly the environment known for paying adequately.

The same is even more true for 68k machines - that era only started in 1985 when machines like Atari and Amiga were introduced. And while Atari did manage to acquire a considerable foothold of the professional market (at least in Europe), the majority of converted applications came from the IBM PC, where, as already mentioned, development had moved to HLL, which in turn allowed automated conversion by recompilation.

In fact, Atari even packaged a Z80 and CP/M 2.2 Emulator with their machines for free to corner exactly that need. In reality it was more of a marketing argument than really useful, as the performance lingered somewhere around a 1-4 MHz Z80. It worked, but not as great as one would expect.

There were at least two hardware add-ons for the Atari ST with Z80, but neither achieved big sales due to the very same reason as before: not many private users would spend much money to run outdated software that doesn't utilize the features of their new machines.

I guess self modifying code was not used on professional CP/M applications like dBASE 2, etc...

Oh, don't underestimate that part.


*1 - An 8088 is, when it comes to memory, clock for clock about the same as a Z80 or even slower. Any emulation would suffer greatly.

4
  • 1
    On the self-modification part, Microsoft BASIC is an example I'm confident of: it does a form of dynamic linking by taking addresses out of the jump table at the beginning of the BIOS area and modifying its into-the-BIOS calls appropriately. Which seems sane and tame. Though it is one of the few applications I'm aware of that requires the BIOS to start on a 256-byte boundary as a result of the way that startup code is written.
    – Tommy
    Commented Aug 10, 2023 at 19:38
  • Was that the SoftDesign Munich CP/M emulator?
    – scruss
    Commented Aug 11, 2023 at 17:17
  • @scruss could well be. I only remember the name as it was CPMZ80 as one word, which I thought (at that time) to be weird, as it was CP/M-80, wasn't it?
    – Raffzahn
    Commented Aug 11, 2023 at 20:31
  • A lot of code was machine converted but for speed reasons you did at build time. Many early 8086 apps were the 8080 one rammed through XLT86 and other tools that did the conversion (or almost all of it) for you. CP/M 68K was a total flop so it may have been that it would have acquired tools if not - other 68K OS did.
    – Alan Cox
    Commented Aug 15, 2023 at 18:22
5

In addition to issues with self-modifying code, many instructions on the 68000 affect flags differently from their Z80 counterparts. If a Z80 program does something like:

    ADD B
    LD  B,A
    LD  A,(456)
    RET

and calling code performs a jump based on the "Z" flag, that flag would need to be set based upon whether the result of the addition was zero, rather than whether A became zero as a result of the last load instruction. In most cases, it wouldn't matter whether translated code for the 68000 undertook extra steps to record the state of the Z flag before returning, but it would likely be difficult in most cases and essentially impossible in some to reliably determine such that code may be omitted (except by assuming it can never be). This difficulty would apply even in a program that was free of self-modifying code.

4
  • 1
    Not to mention that you need to implement the parity flag of the 8080 and the half carry flag/BCD adjust
    – JeremyP
    Commented Aug 13, 2023 at 9:59
  • I appreciate this question may be too nebulous to answer, but how much software would actually suffer from this kind of thing not being implemented? AFAIK, no software written for the 8080 fails on the Z80 (other than programs purposely written to do just that) Commented Aug 14, 2023 at 7:53
  • 2
    @Lorraine: Software on the 8080 would be unlikely to care about the P/V flag except when it was last changed by an add or subtract, or use DAA except after an addition, so having the Z80 change behaviors in cases not meeting those criteria wouldn't be a problem. My answer initially covered those flags, but I thought the Z flag would actually be more problematic.
    – supercat
    Commented Aug 14, 2023 at 15:06
  • 1
    you can convert Z80 code to 68000 but you have to review a lot of things manually. You didn't even mention half address registers like H, L, then HL... Then C and X flags and RL/RR instructions Globally automatic, but Devil is in the details. Commented Aug 18, 2023 at 8:37
4

What prevented, at least on more powerful 68000 and 8086 systems, the creation of a loader that translated z80 instructions in native machine language?

Any machine from that period with 128kb of RAM could implement a caching JIT translator and have a 64kb Z80 address space mapped to RAM. Why JIT? Because memory contents change during normal program operation - overlays were common on larger CP/M applications, and thus a "fire once and forget" loader wouldn't be appropriate.

There was a Scandinavian-made (sorry, don't remember the details) JIT translator for "generic" Z80 system that I used on a PC/XT clone in the 80s. It performed rather admirably. The CP/M system state could be suspended to and restored from a disk file. It was not a cheap piece of software - probably cost $1k in today's money. It came with an SDK that let you define software-emulated peripherals, and was targeted for embedded development work.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .