Having trouble getting started on writing a WDC 65816 backend

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