[llvm-dev] Having trouble getting started on writing a WDC 65816 backend
Jay K via llvm-dev
llvm-dev at lists.llvm.org
Mon Jul 15 00:14:01 PDT 2019
>> As I recall the big one is that LLVM isn't well adapted to instruction
>> sets without fungible registers.
>What does this mean exactly? How does the WDC 65816 not have fungible registers, while other processors do?
>> One idea is to use some of bank 0 as
>> a source of registers, maybe with a custom pass to promote things to
>> real registers where possible after the fact.
>How would I end up doing this? Do you mean bank 0 of the actual SNES ROM?
Probably meant page 0, from a 6502 nomenclature, or "direct page" in 65816.
Ah, so the 6502 and 65816.
As I recall...
These processors have one general purpose
register "accumulator" and two limited-use index registers "x" and "y".
So basically no registers.
Therefore there is a reported style of
programming the 6502 where the first 256
bytes of memory -- "page 0" --
are used as general purpose registers instead.
The stack pointer "S" btw is an 8 bit register,
implicitly referencing the second 256 bytes
of memory -- "page 1".
And silently wrapping around.
Instructions referencing page 0 are smaller and
faster than instructions referencing the rest of the 16bit
address space.
The 65816 is slightly less bad.
It has a 24 bit address space (24 MB).
It's stack pointer is widened to 16 bits, referencing
anywhere in the first 64K.
It also renames "page 0" to be "direct page",
based via a new 16 bit "direct page" "D" register.
If you assume a pushy/poppy ABI (like NT/x86,
unlike NT/amd64), then these two registers combine
to give you a semblance of a modern call sequence.
D is like ebp.
When it was said "bank 0" it was probably meant "page 0".
Though 64K in 65816 might be a "bank" and the first
64K "bank 0".
There is also a bank "K" register that implies the high
8 bits of most 16bit addresses (unless S- or D-relative).
I'm still not sure what you'd do with this.
I guess you can try picking a small number of general
purpose registers. No more than 8, since x86 does "ok" with that.
Model them as all volatile.
?
Despite their historical high usefuless and that I programmed
both of these, they are difficult for me to imagine using
today.
For the morbidly curious: The compare instruction only yields
status bits useful for a conditional compare if the inputs
are considered unsigned. To do a "compare" of signed integers,
requires a destructive subtract. (but if accumulator does not count
as a register, maybe you have not destroyed anything..)
The interrupt enable/disable flag has a reversed meaning
but same instruction mnemonics compared to x86.
So people write the code backwards.
sei/cli, but interrupt flag enabling vs. inhibiting interrupts.
There is no add without carry instruction.
You have to clear carry first, like always (unless
doing multi-precision math).
The subtract/borrow meaning I believe is also same mnemonic
but reversed meaning from x86.
You set carry before sbc, or such.
It made sense to me at the time based on elementary school math at least.
- Jay
More information about the llvm-dev
mailing list