> Gosh, we got one of those too, though, I don't know how much worse
> your machine is than mine, in at all.

In the RL78 case, it's basically a modern Z80 clone.  It has eight
8-bit registers (er, four banks of those, one active at a time) which
can be combined into four 16-bit registers, but for each addressing
mode there's specific register pairs that can be used as base
registers, and sometimes the "base register" is 8-bits and sometimes
it's 16, and sometimes you can combine them (i.e. [HL+B]) in weird
ways.  Worse, most of the MOV operations and all of the math/logic
operations *only* use the A/AX register, and the ones that use other
registers are often asymmetrical.  For example, you can move data from
memory to BC, but not from BC to memory.

It's the weird addressing modes that confuse gcc.  (I had similar
problems with the m32c port, although it was "clean" enough to
eventually force it to work right.  Er, "right enough".  There's still
one double-indirect addressing mode that I can't tell gcc about
because it makes reload vomit.)

Fortunately, there's an addressing mode that covers a small range of
RAM with relatively flexible addressing, and that range happens to
overlap the memory-mapped registers.  So, we tell GCC to use some of
that memory as "virtual registers" and after reload the
devirtualization pass shuffles data in and out of real registers to do
whatever operations are required, based on what addressing modes are
used and what operations need be done.  The post-reload optimizations
then clean up unneeded moves etc.

I.e. we built a micro-interpreter with a compile-time JIT :-)

To do this, we have separate "virtual" and "real" *.md files and
patterns, and the devirtualizer has some standard rules for copying
data, which it applies until the pattern's predicates and constraints
match.  There are some hints in the patterns to tell it which rules to
use, too.  We do a recog on the virtual pattern to get the hints and
operands, then recog on the real one until it works.

> As we move to C++, I'd love for port maintainers to be able to get
> together and hoist _up_ code from the port so other ports can use it
> and thus, have more sharing.

The one bit of code I seem to need more often than usual is an
"unneeded move elimination" pass or helper.  I'd like to be able to
call that at arbitrary times after (or before, or during) other passes
to clean up unneeded moves.  My implementations are fairly trivial
because they cater to my ports, but a generic one that covers all
ports generically would be much more appropriate.

Reply via email to