
Why do C to Z80 compilers produce poor code? (2018) - eklitzke
https://retrocomputing.stackexchange.com/questions/6095/why-do-c-to-z80-compilers-produce-poor-code
======
userbinator
As noted in the first post, the Z80 is still much easier to generate code for
than the 6502.

I see everyone there seems to be referring to free/open-source compilers, but
I know of one commercial compiler for Z80 (IAR) whose output is quite good,
and I have linked to in this previous comment I made on a different article
about Z80 C compilation:

[https://news.ycombinator.com/item?id=18902501](https://news.ycombinator.com/item?id=18902501)

If one didn't know better, it would look almost like handwritten Asm.

On the topic of architectures which are difficult to compile C to, I can also
think of several more: 8051, low-end PIC series, and these:
[https://cpldcpu.wordpress.com/2019/08/12/the-
terrible-3-cent...](https://cpldcpu.wordpress.com/2019/08/12/the-
terrible-3-cent-mcu/)

...and most of those have C (or at least C-subset) compilers too.

~~~
Someone
One thing that, I think, won’t work well is adding a backend to generate code
for such much less powerful CPUs to a compiler-linker system designed for more
powerful CPUs.

Because saving and restoring register values is fairly expensive (both in time
and in memory) you shouldn’t do register allocation per function, or commit to
a fixed ABI. The best assembly to generate for a function often will depend on
what it calls or where it is called from. Let’s say you need a register or
flag to be clear at some time. A function you just called might accidentally
already do that, or it might be cheaper to change that function’s code or
register allocation to give it the desired side-effect than to have the
function that needs the register or flag cleared waste an entire byte to do
that.

You basically need a whole-program (compiler-linker) to generate good code for
these CPUs.

That also helps in moving local variables to global addresses (you likely will
have to, because of limited stack space) and in having such variables share
memory locations as much as possible (if _foo_ doesn’t (indirectly) call _bar_
and vice versa, ant hey aren’t recursively called, their local variables can
share the same memory addresses. Again, you’ll likely have to, because memory
is limited)

~~~
MaxBarraclough
> You basically need a whole-program (compiler-linker) to generate good code
> for these CPUs.

Modern compilers can do this, 'link time optimisation'.

~~~
loeg
See also the GCC flag, "-fwhole-program."

~~~
eqvinox
To my knowledge, none of the compilers that support these architectures
support LTO... bit of a chicken and egg; since C historically wasn't a great
fit, support never grew to that point where it'd fit better.

------
dialamac
The accepted answer is somewhat true but also has some glaring inaccuracies.

The fact is that there are/were some very effective C compilers for Z80, none
of them free and far from it. By the time compiler technology advanced through
the 80s and 90s the market for a non commercial optimizing compiler for the
Z80 and 6502 rapidly diminished. gcc has _never_ in its history been a
fantastic 8 or 16 bit compiler. By the time egcs was merged even 68k was
rapidly losing relevance.

It is totally possible with modern techniques to make a very effective
optimizing C compiler for Z80, but who’s going to do it? There are very few
hobbyists with both the chops _and_ the time for something with little
commercial value.

The answer is correct in implying that the PDP was better suited as a CISC
target for C when optimization is not done.

------
billforsternz
I see a lot of Z80 enthusiasm on the web, is there a good forum/website to
talk to the hard core? I just finished porting the classic Sargon Z80 chess
program to run on x86, [https://github.com/billforsternz/retro-
sargon](https://github.com/billforsternz/retro-sargon) . One of the side
effects of the project is Sargon in real Z80 assembly language, rather than
the weird 8080 hybrid it was originally coded and published in, and I am sure
there will be a hard core Z80 fan or two who would appreciate that.

~~~
apple4ever
This is the best one I found. Quite active too.

[https://groups.google.com/forum/#!forum/retro-
comp](https://groups.google.com/forum/#!forum/retro-comp)

------
smcl
So if C paradigm doesn't fit the Z80 architecture, does anyone know if there's
a language (other than Z80 assembler) that _does_. Or do Z80 enthusiasts
generally just write everything in asm?

~~~
siraben
It is possible to write a Forth implementation[0] for the Z80 that uses just
enough registers to get the execution model on top.

[0]
[https://github.com/siraben/ti84-forth/blob/bc0140d641a121a4f...](https://github.com/siraben/ti84-forth/blob/bc0140d641a121a4f2e43a2ccb796e42d58ead44/forth.asm#L63-66)

~~~
Zardoz84
Not only is possible. Even was a comercial computer using Forth instead of
BASIC. And it was pretty similar to the ZX Spectrum... I'm talking about the
Jupiter Ace

[https://en.wikipedia.org/wiki/Jupiter_Ace](https://en.wikipedia.org/wiki/Jupiter_Ace)

Also, there is an obscure french Z80 computer that uses Forth : Hector HRX

------
timonoko
Goddammerung, I cannot find my Lisp interprete/compiler source code for Z80.
Especially from time before I constructed the external memory bank. There was
nothing comparable anywhere until Turbo-Pascal came to be. It was originally
Forth-like stack machine, but then I implemented another stack, the "execution
stack". "(" and and ")" symbols were push/pops on that stack and thus "(+ 1
2)" was directly executable in my Forth. OTH in this machine the "compiling"
was just replacing symbolic linked lists with a sequence of direct subroutine
calls.
[https://timonoko.github.io/Nokolisp.htm](https://timonoko.github.io/Nokolisp.htm)

------
pjmlp
Nice to see this here, yes in what concerned the 8 bit world and the 16 bit
home micros (PC, Amiga, Atari) C compilers just sucked.

Anyone that was writing code where performance mattered was using Assembly.

Even on 16 bit platforms, although high level languages were already quite
common, in what concerns games (or demoscene), they were our "Unity".

Good enough for prototyping, but also full of inline assembly.

I once saw a game submission to a Portuguese newspaper (for a MS-DOS game),
which the only C that it had were data structures and function declarations,
the bodies were 100% inline Assembly.

And by the time Pentium arrived, unless one was buying Watcom, there wasn't a
good C / C++ compiler that could take advantage of the pipelines and
instruction scheduling in a proper way, as described by Abrash books.

~~~
karmakaze
Yeah, I was so excited to get my hands on UCSD Pascal because there wasn't a C
compiler for Atari 8-bit. It was multi-diskette and sooo slow I never really
ended up using it.

The "Action!" programming language cartridge was the best thing ever.
Somewhere between C and machine language. Being in ROM it booted instantly and
contained a built-in editor, compiler, runtime, and monitor. It compiled about
as fast as Go does now on modern hardware.

It wasn't until I got an Atari ST (Megamax was good) or PCs that C I got to
use C compilers at home.

[0]
[https://en.wikipedia.org/wiki/Action!_(programming_language)](https://en.wikipedia.org/wiki/Action!_\(programming_language\))

~~~
pjmlp
Cool, I wasn't aware of Action!.

------
s_gourichon
Well, while certainly imperfect, some like SDCC are good enough to write some
games with nontrivial logic.

Here’s an open source game (disclosure: I wrote it) that compiles with SDCC
and runs a game involving a flood fill algorithm, a tiny GUI with checkboxes
and buttons and only one assembly routine, all running on the Amstrad CPC464
and above: [https://github.com/cpcitor/color-flood-for-amstrad-
cpc](https://github.com/cpcitor/color-flood-for-amstrad-cpc)

It’s much easier to write and much faster (and probably smaller) to run than
the same in BASIC.

~~~
loeg
From what I've heard, SDCC generates pretty bad z80 code. It might be good
enough if your application isn't super demanding.

~~~
vardump
Write in C and implement portions requiring higher performance in assembler.

Nineties style.

------
NanoWar
I think one solution would be to have another language that's a bit more
abstract than ASM maybe with some variables and register spilling and some
macros, so you can write ASM more easily. That language could be transpiled
into ASM, but would need to be debugged as ASM as well then, so you still need
to know assembler very well.

I tried to do that a couple years ago with little success (readme and feature
list missing, sorry but maybe you get the idea from the repo):
[https://github.com/NanoWar/FunkCompiler](https://github.com/NanoWar/FunkCompiler)

------
zabzonk
They produce about as good code as can be produced for any 8-bit (accumulator
size) processor (there are some 16-bit instructions for some registers). The
PDP-11, for which C was designed, has a 16-bit register architecture for all
registers.

~~~
SomeoneFromCA
avrgcc would disagree.

