joe7 wrote:
Because of the compatibility requirement, it's probably unfair to compare the '816 to other processors. (I don't think copying the 6502 instruction set verbatim would have made sense for a completely new 16-bit design, though.)
I see now that considering all the addressing modes, adding ADD/SUB would have gobbled up a bunch of opcodes. WDC did squeeze a lot of power out of the existing instructions, by adding the movable direct-page, banking, 24-bit addressing, etc.
What you are highlighting is the dichotomy of backward compatibility versus new features. Clearly, Bill Mensch had to carefully pick and choose what could be added without taking away the bulk of the existing 6502/65C02 instructions. Furthermore, he was working with an ISA in which all opcodes are one byte, thus setting a hard limit on the number of instructions that could be supported. This is where the reserved
WDM instruction was supposed to help.
Quote:
There is a 16-bit branch that I forgot about (BRL), but it takes 1 more cycle than JMP and it's unclear to me what this is for.
BRL is primarily of value in developing relocatable code. A
JMP instruction is an absolute reference to a specific address that is generated at assembly time. The
JMP instruction's target address is only valid if the program is loaded to the original assembly address. Relocating the program when it is loaded would cause
JMPs (and
JSRs) to direct the MPU to undefined locations, at best causing bizarre behavior and at worst, causing a crash.
On the other hand,
BRL, like all relative branch instructions, references the current program counter at run-time, which means it will land the MPU in the right place without regard to where the program has been loaded. As
BRL's operand is a 16 bit signed offset, it can branch forward
$7FFF bytes or
$8000 bytes backward. Incidentally,
BRL in conjunction with
PER can be used to synthesize the
BSR (branch to subroutine) instruction of the Motorola 68000. It's one of those things best buried in a macro.
Quote:
Also, what are the stack relative addressing modes for?
Stack pointer relative instructions allow the programmer to conveniently use the hardware stack as a scratch pad in function calls. Rather than predefine storage for a function call (aka subroutine), the programmer would reserve some space on the stack when the function is entered and then use stack pointer relative addressing to read and write on that space. Upon exit, the function would relinquish the extra space and the stack would be back in balance. The allocation and deallocation of the stack space is made convenient by the fact that the (16 bit) stack pointer can be copied to and from the accumulator and thus readily manipulated with 16 bit arithmetic.
Another use for stack pointer relative addressing involves passing parameters into functions via a stack frame that is generated by the caller. The function would then "cherry pick" parameters from the stack as needed. There is a good discussion of the use of stack pointer relative addressing in the
Lichty and Eyes programming manual (jump to page 240 in the PDF copy). I use stack pointer relative addressing extensively in my POC unit's firmware and in a lot of programs.