[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:13:17 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.​
Store them all on the direct page.
 ​
 ​
?​
 ​
​
Despite their historical high usefuless and that I programmed​ and used 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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190715/b9fef32f/attachment.html>


More information about the llvm-dev mailing list