8-Bit CPU Comparison
BMOW’s instruction set was a close cousin to the 6502’s, and so when I started on CPLD CPU, I initially intended to try something different. I looked at the Intel 8008 and 8080, Zilog Z80, and Motorola 6800 and 6809, which were all popular 8-bit CPUs back in the 1970’s and 80’s. After studying up on the architecture of all these different CPUs, I decided that the 6502 was still the best choice to use as a model, because I believe it can be implemented using the least CPLD resources.
The cross-CPU comparisons were very interesting. The key differences between these early 8-bit CPUs fell into four main areas: number of data registers, 16-bit instruction support, address registers, indexed addressing.
Number of Data Registers
More registers are just about always better, except where you’re starved for logic resources in a tiny CPLD. While the 6502 has three 8-bit registers A, X, and Y, my plan is to only include A and X in the CPLD CPU instruction set.
CPU 8-Bit Data Registers:
- 8008 – 7, ABCDEHL
- 8080 – 7, ABCDEHL
- Z80 – 7, ABCDEHL
- 6800 – 2, AB
- 6809 – 2, AB
- 6502 – 3, AXY
16-bit Extensions
While all the CPUs in this group are 8-bit designs, some support a limited number of 16-bit operations too. These are very handy for the programmer, but any 16-bit operation can also be performed as a series of 8-bit operations, so the difference is one of speed and not capability.
CPU 16-bit Support:
- 8008 – none
- 8080 – BC, DE, HL can be joined to form 16-bit registers. They support load/store of 16-bit values, and increment/decrement. Addition/subtraction of 16-bit registers is supported when HL is used as an accumulator.
- Z80 – Same as 8080, with some added flexibility on supported operations.
- 6800 – none
- 6809 – AB can be joined to form a 16-bit register D. It supports load/store of 16-bit values, and addition/subtraction/compare with a 16-bit value in memory.
- 6502 – none
Address Registers
Most modern CPUs store an address in a user-visible register, then use other instructions to manipulate the data at that address. These may be registers used specifically for holding addresses, or general purpose data/address registers, but either way the size of the register must be at least as large as the address space of the CPU. For example, the 8008 and 8080 have the M register, which can hold a 16-bit address. A byte can then be fetched from that address into the accumulator with the instruction MOV A,M. This is convenient, because you can do things like perform arithmetic on M in order to construct the right address for a value in a struct.
Another way of approaching addresses is to include them directly in the instruction itself. For example, the 6502 can fetch a byte from address $0123 into the accumulator with the instruction LDA $0123. This has the advantage that you don’t have to load $0123 into an address register first, but it means you can’t do arbitrary arithmetic on the address.
A CPU that supports absolute addresses directly in the instruction must have a hidden, temporary address register. That address in the program code has to be loaded somewhere, so that it can then drive the address bus, and a user-hidden address register fits the bill nicely.
In a CPLD CPU, the user-visible and user-hidden address registers both require space: one macrocell per bit. 10 macrocells for an address register is expensive, when your entire device only has 128. Having only a user-visible address register creates a fairly clunky programming experience, because it rules out having absolute addresses in the instruction, and forces the programmer to manually load the address register first before every memory reference. This is what the 8008 does. Most CPUs have both. The 6502 is unique in this group by having only a hidden address register, and no user-visible one. This gives up some flexibility, but is still a workable solution and eliminates one large register from the CPLD. The 6502’s zero page mode can also turn the first 256 bytes of memory into 128 pseudo-address registers.
CPU Has a User-Visible Address Register?
- 8008 – Yes, HL (also called M). ALL memory references must be done with this (no absolute addressing). Must load L and H separately.
- 8080 – Yes, BC, DE, HL. Can swap DE<->HL. Also supports absolute memory addresses.
- Z80 – Yes, Same as 8080. Adds some additional flexibility for addressing modes.
- 6800 – Yes, has a 16-bit X register. This functions like an address register when used with a absolute base address of 0. Only limited support for arithmetic with X. Also supports absolute memory addresses.
- 6809 – Yes, has 16-bit X and Y registers. Otherwise same as 6800.
- 6502 – No. Supports absolute memory addresses, and page 0 of memory as a set of pseudo-address registers.
Indexed Addressing
A very common pattern in assembly language programming is to reference a memory location using a combination of a base address and an offset. When performing some operation to many consecutive memory locations, this is generally faster and more convenient than altering the base pointer each time through the loop. For example, the 6502 can load a byte to the accumulator at some offset from address $0123 with the instruction LDA $0123,X. This takes the value currently in the X register, adds it to $1023, and uses the resulting address as the location from which to load a byte. Here’s an example 6502 programming using indexed addressing to sum all the values in memory locations $1000 to $100F:
ldx #$0F ; initialize X index
lda #$00 ; register A holds sum, initialize to 0
clc ; clear carry flag
- adc $1000,X ; add the byte from memory to the running total
dex ; decrement X index
bpl - ; if index is >= 0, branch to start of loop and keep going
Not all those early 8-bit CPUs supported indexed addressing. For CPUs with a user-visible address register, it’s not strictly necessary, because the programmer can accomplish a similar result by doing arithmetic on the value in the register. But even where it’s not necessary, it’s still a very handy feature. The 6502 supports indexed addressing in the most resource-efficient manner of the CPUs in this group.
CPU Supports Indexed Addressing?
- 8008 – No, must manipulate the address register manually.
- 8080 – No, must manipulate the address register manually.
- Z80 – Yes, uses two 16-bit address registers, and an 8-bit offset that’s part of the instruction.
- 6800 – Yes, uses one 16-bit address register, and an 8-bit offset that’s part of the instruction.
- 6809 – Yes, uses two 16-bit address registers, and an 8-bit offset that’s part of the instruction.
- 6502 – Yes, uses one 8-bit offset register, and a 16-bit address that’s part of the instruction.
18 Comments so far
Leave a reply. For customer support issues, please use the Customer Support link instead of writing comments.
I had a lot of fun programming the 6809 when I was younger. It can actually do a little more than you describe.
In addition to the 16-bit X and Y registers, there’s also a 16-bit U register. The U register can be used just like X and Y (for example, indexed addressing), but it also can be used as a secondary stack pointer. At the other extreme, if you are willing to do without any stack, the S (stack pointer) register can be used exactly like X and Y as well.
For the indexed addressing modes, the offset was signed and could be 0, 5, 8, or 16 bits in size (the different formats allowed more common cases to fit into as small of an instruction as possible) and you could use X, Y, U, or S. The offset could also come from the accumulator registers A, B, or D.
Indexed addressing mode with the stack pointer (S) made using local variables kept on the stack trivial. You could also index using an 8 or 16 bit signed offset relative to the program counter.
Using the indexed addressing modes with the load effective address instruction, you could easily do 16-bit addition and subtraction. Whether or not the result was actually an address didn’t matter. So examples:
LEAX 5,X X = 5+X
LEAY D,U Y = D+Y
LEAU -1234,X U = X-1234
I didn’t know HL was also called M on the 8008; interesting (it had already been displaced by the 8080 by the time I looked at that family of architectures).
Oops, that should have been:
LEAY D,U Y = D+U
I also forgot about the 6809’s indirect indexed addressing modes where the indexed address specifies the address of a pointer to the actual memory operand. The 6502 could do something like that with its Y register too, I think. The fancier indexed addressing modes do come at the expense of longer and more complicated instructions to decode so I agree that the 6502 is probably a better source of inspiration for you CPLD CPU.
Cool, sounds like the 6809 was pretty advanced for its time. Too bad it never caught on very widely.
不知道能不能看的懂啊,也是爱好者,羡慕并学习中……
The IX and IY indexed addressing modes on the Z80 were not of much use, unfortunately.
However, you can treat them as two extra 16-bit registers — and on most Z80’s you could do a bit more than that, although it was never architected.
Let me explain: the IX and IY indexed addressing modes are really just ordinary HL indexed addressing instructions with a special prefix byte in front + a suffix displacement byte at the end. Those prefix bytes can on most Z80’s be used in front of any instruction that uses HL or H or L to make it operate on IX, IY, or their individual bytes instead. Neat, huh?
The Z80 also has a set of “shadow” registers that can be swapped with the normal ones with a single 4-cycle instruction (EXX).
I wish that instead of the IX/IY indexing nonse they would have given us SP+displacement indexed addressing (for parameter passing on the stack)…
@Peter, use IX or IY as a data stack pointer, and leave SP as the return stack pointer. I can’t think of anything that would =require= a single stack for C or Pascal compilers. Also, IX and IY are just what the doctor ordered for referencing fields of data structures, which was their original intent.
One thing I wish this little CPU survey had addressed is support for position-independent code. On a 6502 the only purely relative addressing is found in the branch instructions, which include a signed 8-bit displacement that gets added to the PC if the branch is taken; all other instructions (barring the register-only stuff like operations using immediate data, index-register increments, and register-to-register transfers) require at least one memory address to be hard-coded in the instruction. Can anyone comment on how the other five CPUs considered here stack up in this regard?
gsteemso, the 6809 allowed fully position independent, reentrant code. The stack pointers were 16 bit so the stack could be anywhere, and branch operations all had ‘long branch’ versions, so you could use something like a BEQ (branch if equal) to go up to 127 bytes forward or 128 bytes backwards, or an LBEQ (long branch if equal) to go up to 32767 bytes forward or 32768 bytes backwards (covering the whole address space). The index registers were all 16 bit as well, and you could generate their addresses relative to PC, so those could be position independent as well.
OS-9 was a full multi-tasking/multi-user OS written for the 6809 processor which relied on position independent/reentrant code. Modules (including device drivers & user programs) could be loaded anywhere there was a gap in memory (without having to be ‘fixed up’) and they’d just work, and if two users each ran the spreadsheet, it would just load the module once (to save memory), and give each instance a different stack & data address space.
this is wrong:
“the 8008 and 8080 have the M register, which can hold a 16-bit address. A byte can then be fetched from that address into the accumulator with the instruction MOV A,M”
there is no such thing as an m register. here m is just shorthand for ‘the byte at the address held in hl’, translated for the 8080’s absolutely horribly set of mnemonics. the z80 mercifully just calls this ld a,(hl)
Fascinating write-up. I think it is worth noting that the big commercial successes were the Z80 and the 6502. But, of course, those were both designed to be low-cost knock-offs of the 8080 and the 6800, respectively. Motorola fired back by creating the 6809. While not commercially that successful, it probably should hold the distinction for being the best of the lot, technically. I think it’s noteworthy that OS-9 is likely the most modern’ish and capable full-featured OS ever made for an 8-bit CPU, and could only be done for the 6809. Intel fired back by making the 16-bit 8086, releasing the scaled-down 8/16-bit 8088, and getting it selected for the IBM PC – the rest, as they say, is history. If (big if) IBM had decided to go with the 6809 instead, the microprocessor would might look a lot different today.
Actually Steve the 6809 was quite popular in many roles outside the desktop microcomputer, its Wikipedia article gives more. In fact, it is still being made by Rochester and I am currently working on a highly specialized, new project that may use it. Why still use it, because it is all I need; and the way many newer systems based on popular chips are hacked, a less popular chip is less prone to attack.
CPU 16-bit Support:
6800 – none
6809 – AB can be joined to form a 16-bit register D. It supports load/store of 16-bit values, and addition/subtraction/compare with a 16-bit value in memory.
Several things seems to be missing:
On a 6800 X there is a 16 bit wide index register, generally for reaching out to any address of the whole address space. The 16 bit support for this register is limited. Beside increment and decrement only a compare instruction does exist.
As previously mentioned, the 6809 has also a 16 bit register name U (symetric to S) and in addressing modes equivalent to X and Y.
It’s fairly accurate to say that although the 6809 is the most elegant and powerful design of the 8bitters, its illegitimate sibling the Hitachi 6309 takes the ultimate 8 bit crown with 6809 compatibility and a hugely more powerful extended mode, featuring:
* another pair of 8 bit Accumulators E & F
* a further 16 bit accumulator combined from these – W
* a 32-bit accumulator combining D & W – Q
* Hardware multiply for these registers upto the 32 bit Q
* Hardware division instructions
* A zero register
* A value register preserved across processor resets
* Memory transfer loop instruction
* Bit level register transfer instructions
* New interrupt modes
* Illegal instruction and /0 trapping
IBM did not consider 8-bit CPUs for the PC; they were looking at 16-bit CPUs, so the choice was quickly narrowed down to the Motorola 68000 vs. the Intel 808x … If they had gone with the M680x0 family, as you said, the PC world might look very different today, both in terms of hardware and software.
Good point that the 68k was around by the time the IBM PC was finally being architected. I wish they had selected it and moved the microcomputer industry to 16/32-bit systems with linear address space years soon. It would have saved a lot of hassle with segmented memory, getting protected mode to work, and building bigger apps that needed many megabytes.
If IBM dismissed the 6809 out of hand for having only a 16-bit address bus, then they aren’t winning any innovation awards. My CoCo 3 has 512KB of RAM “factory-installed”, can be upgraded to 2MB, and all easily usable within OS/9.
A certain other company we now know as APPLE did choose to use the 68000 Motorola and for a decade and a half. They later switched to the PowerPC (IBM) for the next decade and a half (with some overlap of course). Finally we move to the modern era (as of this writing) they are using the same Core2Duo and i5 line of processors from INTEL that we typically refer to as PCs.
So should IBM have gone with 68000 Motorola they would have likely moved onto the PowerPC line eventually also and as I see it the real wild card is how INTEL would eventually have entered the game. Like Microsoft they were in the right place at the right time in their contracts with IBM.
As a CoCo user from way back it’s fun remembering when 1200bps was considered fast and 64kb was considered large.
@Aland Coons ok, it seems to me, that if IBM chose 68K, Intel would have no chance for such rapid development. It is possible that then, there simply could be no question of switching from PPC to Intel, so the future of PC market could be different.
It seems nobody commented the “twin” registers of Z80, the alternative AF’, BC’, etc…