Comparing Datapoint 2200, 8008, 8080 and Z80 Instruction Sets

Before Intel created the 8080 it designed the 8008, the first eight bit microprocessor, and the first microprocessor to go on general sale. The 8008 was designed as a single chip version of the TTL processor in the Datapoint 2200, itself the first desktop computer.

I’ve long known that the Datapoint 2200 had a very similar register set to the Z80. That is to say that it had registers named A, B, C, D, E, H and L. And that the names H and L stood for ‘high’ and ‘low’ and they could be combined together to address memory.

What I didn’t know was how the rest of the Datapoint processor’s functionality compared to that of the 8080/Z80. In this article I’ll compare the instruction set of the Datapoint 2200 with that of the Intel 8080 and Zilog Z80. And since the Intel 8008 was sandwiched between the two in the timeline of history I’ll also compare that with the later processors.

Datapoint 2200

Let’s start with a table of Datapoint opcodes.

Fig 1. Table of Datapoint 2200 opcodes
Fig 1. Table of Datapoint 2200 opcodes. Click to enlarge.

And since those opcode names probably don’t mean much to you, here is the same table using Z80 syntax.

Fig 2: Table of Datapoint 2200 opcodes using Z80 syntax.
Fig 2: Table of Datapoint 2200 opcodes using Z80 syntax.

Registers and Flags

Before we dig into the instruction set itself it’s worth looking at what registers and flags are available on the Datapoint.

As I’ve already mentioned the register set of the Datapoint 2200 is similar to that of the Z80: A, B, C, D, E, H and L. The version 2 Datapoint processor also adds an alternate register set (A, B, C, D, E, H, L and control flip flips (aka flags)). The basic (version 1) register set is identical to that in the 8080 although the 8080 adds instructions which combine BC and DE into register pairs in addition to HL. The Z80 adds to this with the alternate register set as well as the IX, IY, I and R registers.

In terms of flags the Datapoint has four available: Carry, Zero, Sign and Parity. These are all equivalent to those of the Z80/8080 although the Z80 adds Negative and Half-carry flags and also uses the Parity flag as an Overflow flag depending on the instruction.

Load/Store/Move Instructions

The 8-bit register to register instructions on the Datapoint are named Lr1r2 where r1 is the destination register name and r2 that of the source. Where the register name is replaced my M this signifies a memory read or write operation with the address being the value in the HL register pair. Thus LAB is equivalent to the Z80 opcode LD A,B. LAM is equivalent to LD A,(HL) and LMA is equivalent to LD (HL),A.

The NOP opcode replaces LAA (LD A,A) but that’s really just a pseudo-opcode as loading a register into itself has no detectable affects. A HALT opcode replaces LMM, just as it does in the Z80 (LD (HL),(HL)).

There are also load immediate instructions Lr n which are equivalent to the Z80’s LD r,n.

In comparison to the Z80 it’s worth noting that the register encoding within the instructions is slightly different but the source and destination registers are encoded into the exact same bits within each opcode byte. In terms of operation all these instructions operate in exactly the same way within both the Datapoint and the Z80. The Z80, and 8080 before it, add a number of new load instructions and addressing modes.

ALU Operations

It’s when we move to the ALU that we start to see just how similar the 2200 and Z80 are. The main ALU opcodes take the form of a two character operation mnemonic followed by a single character register name (or M). Thus ADH is equivalent to ADD A,H, XRM equates to XOR (HL). All instructions operate on the A register and the result is placed in the A register.

The available instructions are:
ADr – Add
ACr – Add with carry
SUr – Subtract
SBr – Subtract with borrow (equivalent to subtract with carry)
NDr – AND
XRr – Exclusive OR
ORr – OR
CPr – Compare (sets flags equivalent to a subtract but the the result discarded)

As with the load instructions there is also a form which takes an immediate value in place of a register, thus SB n is the same as SBC A,n.

Compared to the Z80 these instructions function in exactly the same way as the equivalent Z80 instructions, with the exception of the Z80s additional flags. The register coding is slightly different, as with the load instructions. But it’s interesting to note the 2200 has the same eight basic functions as the Z80 and that the coding for those operation is the same as that in the Z80. And both the register and operation are coded into the exact same bits of the opcode as they are in both processors.

In addition the Datapoint also has two shift instructions, SLC and SRC, mnemonics for ‘shift left with carry’ and ‘shift right with carry’. They’re actually rotate instructions operating on the A register and are the same as the RLA and RRA instructions on the Z80.

Flow Control

In terms of flow control instructions the Datapoint 2200 has:
JMP nn – Unconditional jump
Jcc nn – Conditional jump where cc represents the flag test to perform
CALL nn – Unconditional call to subroutine
Ccc nn – Conditional call to subroutine
RETURN – Unconditional return from subroutine
Rcc – Conditional return from subroutine

The flag tests available are:
FC – Carry false (clear)
FZ – Zero false (clear)
FS – Sign false (clear)
FP – Parity false (clear)
TC – Carry true (set)
TZ – Zero true (set)
TS – Sign true (set)
TP – Parity true (set)

Thus the Datapoint has the same basic control flow functions as the 8080, the exception being the restart (RST) instructions in the latter. The Z80 also adds the relative jumps and DJNZ (decrement B and jump relative if not zero). The set of available flag tests is identical to that of the 8080/Z80 and those tests are encoded into the same bits of the opcode across the processors, although the actual codings are different.

The Datapoint uses an in-processor stack with 15 levels in the version 1 (serial) processor and 16 in the version 2 (parallel) compared to the in-memory stack of the 8080 and Z80.

Input and Output

The Datapoint has a single input instruction, INPUT, which reads the contents of the data bus into the A register.

For output it has a number of EX <function> instructions – 24 to be precise ,although a few are unused. The EX mnemonic stands for ‘execute’, meaning that each instruction commands a device to execute the selected operation. The EX instructions place the A register on the bus. Some of those operations may select a device and/or tell the selected device to output data to the data bus to be read by an INPUT instruction. Thus in input operation will usually need to be preceded by an EX operation.

This is an area where there is significant difference between the Datapoint and the 8080 and Z80.

Miscellaneous

Which brings us to the last few Datapoint instructions.

It has the HALT instruction coded into three(!) bytecodes (which is documented behaviour). As mention previously the one with the $ff bytecode replacing what would otherwise be the LMM (LD (HL),(HL)) instruction as in the 8080/Z80.

As mention above the LAA (LD A,A) instruction doesn’t officially exist and is replaced by the NOP instruction, unlike the separate NOP bytecode of the 8080/Z80.

ALPHA and BETA instructions flip between the basic and alternate register sets in the version 2 processor. Note that this is functions slightly differently than the various EX and EXX instructions used by the Z80 to switch between register sets.

The version 2 processor also adds DI and EI opcodes to enable and disable interrupts respectively. (The version 1 processor has no interrupt functionality). I’ve not researched the functionality but I expect it will be somewhat different to that of the 8080/Z80.

And finally the version 2 processor also adds PUSH and POP instructions to push or pop the HL register pair (and only the HL register pair) onto or off the stack. Programmers will need to be cautious when using them with the 16 item limit on the in-processor stack. Maybe it’s just as well that there aren’t a wider range of stack instructions available!

Datapoint Versus 8080/Z80 Summary

At this point it’s interesting to summarise what Datapoint functionality is present in the Z80. Noting that most of the bytecodes are different, we have:

Every Datapoint register is present in the Z80.
The alternate register set of the version 2 Datapoint processor is also present in the Z80 (although accessed differently).
Every Datapoint flag is present in the Z80 and functions in the same way.
Every Datapoint load/store/move instruction is still present in the Z80.
Every Datapoint ALU instruction is still present in the Z80.
Every Datapoint flow control instruction is still present in the Z80.
Input and output is very different.
Miscellaneous instructions have many similarities, especially the extra instructions in the version 2 processor.

Flipping things in the other direction:
The Z80 and 8080 add extra load instructions, including 16-bit and direct memory load/store instructions.
The Z80 and 8080 add a lot of extra ALU features including add 16-bit add and subtract, more shift/rotate instructions, INCremet and DECrement instructions and extra flag features (Z80 only, but mostly for internal use only) but the eight basic ALU operations remain the same as that of the Datapoint.
The 8080 adds restart instructions, the Z80 adds relative jump and looping instructions, but the basic flow control instructions are the same as that in the Datapoint.

Intel 8008

The Intel 8008 occupies a place in history between the Datapoint 2200 and the Z80. It was created as a single chip version of the Datapoint (or the Datapoint was created as a TTL version of the 8008, depending on your version of history).

Again, here is a table of the 8008’s instruction set,

Fig 3. Opcode table for the Intel 8008.
Fig 3. Opcode table for the Intel 8008.

And again here’s the table with Z80 equivalents,

Fig 4. Intel 8008 opcode table using Z80 equivalent mnemonics.
Fig 4. Intel 8008 opcode table using Z80 equivalent mnemonics.

The first thing to notice is that the byte codings for all instructions in the 8008 is the same as that in the Datapoint. The 8008 only adds extra instructions (when compared with the version 1 Datapoint – the version 2 was on a separate timeline by the time it was created). This probably shouldn’t be too surprising given that the 8008 was specified by CTC as a single chip version of the 2200.

Load/Store/Move instructions

Here the 8008 has the same operations as the Datapoint although there’s a slight difference in the naming scheme. Those instructions which take an immediate value append the I character to the name. Thus LEI n is the equivalent of LE n on the Datapoint and LD E,n on the Z80.

Also there is no official NOP instruction so LAA is listed but there is no difference in terms of operation.

ALU operations

Again the basic ALU operations are copied but again with I added to the name of instructions which take an immediate value (i.e. SUI n replaces SU n equivalent to SUB A,n on the Z80).

However the 8008 does add increment and decrement instructions, INr and DCr respectively. Interestingly there are no increment or decrement instructions for the A register or memory (equivalent to INC (HL) or DEC (HL) on the Z80).

I assume the lack of instructions to operate on the accumulator was because of the lack of suitable free space in the opcode table and the ability to perform ADD A,1 and SUB A,1 operations meant the additional complexity required for a different opcode encoding was considered unnecessary. Although doing so would only have meant doing away with two of the redundant HALT instructions.

The variants that operate on memory they would have added a lot of extra complexity given the need to both read from and write back to memory and their omission makes a lot of sense.

The 8008 also adds two extra shift instructions (this time more sensibly referred to as rotates). RAL and RAR are rotate through carry operations equivalent to the Z80s RLCA and RRCA respectively. Thus the 8080 has the same four rotate operations as the 8080. The Z80 though, adds a lot more with the a quarter of the ‘bitwise’ extended operations devoted to shifts and rotates.

Flow Control

This is where things get interesting as far as I’m concerned. The 8008 adds a set of restart instructions that function in the same manner as those in the 8080 and Z801. I find it amazing not only that the instructions are there but that they call the same locations as those in the 8080/Z80. Thus feels like a surprisingly advanced feature for such a basic processor.

The 8008 user guide doesn’t specify a syntax, or give any examples, for the RST instructions so I’ve assumed one with the ‘&’ hex prefix. The 8008 (and Datapoint) assemblers usually used numbers in octal format so expect to say that in any old code.

As an interesting quirk the unconditional jump, call and return instructions each map to eight bytecodes, and this is documented behaviour. It’s interesting to think about the issues this would have given the designers of the 8080 and Z80 had they been designed as a superset of the 8008.

And, whereas the Datapoint had a 15 or 16 entry in processor stack, the 8008’s in processor stack is limited to only eight entries.

Input/Output

The Intel 8008 expands the input functionality to be able to access eight ports. The output instructions can write to up to 24 ports. The actual operation is different to that of the Datapoint (and more akin to that of the 8080) but they use the same 24 bytecodes as their Datapoint equivalents so I’d consider them to be the same.

In the table above I’ve given the port numbers in decimal for clarity, but actual 8008 assembler(s) would have used octal.

Miscellaneous

As far as other instructions go the 8008 retains the three HALT bytecodes and nothing else. Obviously the ‘virtual’ NOP (using a load from a register into itself) is still available but not documented.

The miscellaneous instructions available on the Datapoint were all a feature of the version 2 processor which was created after Datapoint had ceased working with Intel, so it is no surprise that they aren’t included.

What is surprising is that the 8008 has hardware support for interrupts (which the version 1 Datapoint doesn’t) including the restart instructions2 although it has no way to enable or disable interrupts and, even more surprisingly, no way to store or retrieve registers or flags, whether onto the stack3 or elsewhere. This means that when an interrupt routine is called the only way for it to do useful work is for it to trash registers and flags being used by the foreground process!4.

The only realistic way to use interrupts is to execute a HALT instruction and have the interrupt resume execution (a capability not available on the Datapoint version 1 where a HALT is, as far as I’m aware, final and absolute until the user reboots the machine. It had a HALT light and reboot key on the keyboard for that purpose).

8008 Summary

So, the 8008 is a direct superset of the version 1 Datapoint 2200 and all the additional instructions have been directly carried forward into the 8080/Z80 with the exception of the input and output instructions. Thus comments made above with respect to the Z80/8080 versus 2200 mostly still stand with regards to the 8008.

At this point it’s worth looking at the Z80’s base opcode table to show at what point on the timeline each instruction was introduced, whether in the Datapoint 2200 version 1, Intel 8008, Intel 8080 or Zilog Z80.

Fig 5. The base Z80 opcode table showing the origins of each instruction.
Fig 5. The base Z80 opcode table showing the origins of each instruction.

I find it fascinating to see the large swathe of green Datapoint instructions which have carried through into the Z80. It’s also interesting to see that the restart instructions were introduced by the 8008, especially since their use-case was so badly hobbled by the otherwise almost unusable interrupt functionality.

The Datapoint 2200’s Place in History

Most people (who know the subject area) accept that the 8086 was a superset of the 8080 functionality using different bytecodes. Few realise that the 8080 was closer to the 8008 than the 8086 was to the 8080 – since it inherited the exact same instructions merely with changed bytecodes. And even fewer are even aware of the Datapoint 2200 let alone that it is merely a bytecode compatible subset of the 8008, and thus also a subset of the 8080 and Z80 with different bytecodes.

The Datapoint 2200 is not merely the machine which initiated Intel’s role as a processor manufacturer5., it is the machine which creates the architecture used by the 8080 and all it’s descendants right down until todays Pentiums. And it also directly influenced the design of the worlds best selling processor, the Zilog Z80.

I think it deserves to be better known and better understood.

Resources

You can find various Datapoint 2200 resources, including original and reverse engineered schematics and user manuals, in my Github https://github.com/Bread80/Datapoint2200

Datapoint 2200 Reference Manual at Archive.org.

Intel 8008 User Manual (datasheet) at Bitsavers.

Ken Shirriff’s website has a number of interesting in depth articles about most of the processors mentioned here: Datapoint, 8008, Z80, 8086.

Datapoint: The Lost Story of the Texans Who Invented the Personal Computer Revolution by Lamond Wood (Book) (Amazon affiliate link).

Silicon: From the Invention of the Microprocessor to the New Science of Consciousness by Federico Faggin (Book) (Amazon affiliate link)

Footnotes

  1. For those unfamiliar with the Z80, the restart instructions are single byte opcodes which function as subroutine calls to specific memory locations. They are intended to be used as part of the interrupt handling behaviour and to call operating system functions
  2. The official way to implement interrupts was for the interrupting device to ‘jam’ (their word not mine) an instruction into the processor, the expectation being, presumably, that the instruction would be one of the restarts, the same technique as is recommended on the 8080 and some Z80 interrupt modes
  3. Given the in-processor stack only has eight entries that might not be much of a limitation in actual use.
  4. You may think that you could reserve a spare register or two to use in an interrupt handler, but you can’t input or output data without using the accumulator, and you can’t write a value to RAM without using the HL register pair. You could write a value to a spare register to indicate the interrupt has happened and poll that in your main code but by the time you get to that point you might as well just poll the I/O device directly
  5. The 4004 was Intel’s first processor design but it was designed for a specific customer. The 8008 was also designed for a specific customer but was put on general sale after they rejected the design. It was these general sales which led to the creation of the improved 8080. It’s possible they would have had more commissions after this but they considered themselves to be a memory chip manufacturer and had no interest in processors.

Leave a Reply

Your email address will not be published. Required fields are marked *