Rockwell PPS-8


The Rockwell PPS-8, short for "Parallel Processing System, 8-bit", was an early 8-bit microprocessor from Rockwell International, announced in 1974. It had a number of unique design features, which Adam Osborne described as "most unusual... more powerful... also one of the most difficult to understand." It was released with a suite of support chips, including ROM and RAM, parallel and serial controllers, and a direct memory access system.
The release of simpler and less expensive designs like the MOS 6502 around the same time led Rockwell to pull the design from the market without entering widespread production. National Semiconductor had a cross-licensing arrangement with Rockwell, but they did not produce the PPS-8. The simpler Rockwell PPS-4 did not suffer the same fate, finding a number of roles in low-end systems and being produced into the 1980s.

Description

Physical construction

The PPS-8 was built on a metal gate PMOS logic process, compared to the contemporary Intel 8008 and similar designs which were based on the more advanced silicon gate process. PMOS logic required large amounts of power; the PPS-8 ran on a -17 VDC power supply and also needed separate -12V, +5V and ground. The circuitry dissipated so much power that the chip could not generate a strong enough clock signal internally, and the clock had to be an external chip in its own TO-100 package. Like the PPS-4, the clock was based on a standard NTSC timing crystal as these were widely available. Inside the CPU, the clock's two-phase output, A and B', was used to build a four-phase internal clock running at four times the external clock rate. For instance, the normal 250 kHz clock became 1 MHz inside the CPU.
Like the PPS-4, the PPS-8 was packaged in a 42-pin quad in-line package. The system had a 14-pin address bus, allowing it to address up to 16 KB of main memory. This was normally used in conjunction with the read inhibit and write inhibit lines to address two banks of memory, up to 16 KB of ROM containing a program, and up to 16 KB of RAM for data storage. In an era when memory was very expensive and machines often used 2 to 4 KB of ROM and even less RAM, the limited address space of the PPS-8 was not a significant limitation. The CPU treated the two banks differently, one was for ROM containing program code, while the other was for RAM and contained data. The shared data bus was 8-bit wide, allowing it to read one instruction or word of data in a single cycle.

Registers and memory

The PPS-8 is an accumulator-based design with only one general purpose 8-bit processor register, A. A second 8-bit register, W, was used to buffer data for some of the accumulator instructions, but could be used for general storage otherwise. It also had three 8-bit "data counters", X, Y and Z. X and Z mostly acted as index registers, but could only access "data memory", whereas Y was a secondary accumulator and also a buffer for the X register. The 16-bit L register, for Link, was used as an index register to program memory. There was also a 14-bit program counter and 5-bit stack pointer.
Referring to a location in the data memory required a 14-bit address to be constructed with a 7-bit "page number" in the Z register and another 7-bit "byte number" in X. If bit 7 of the X register was 0, then the Z register value was ignored. This was used as a form of short addressing, which was more commonly seen in other processors as a "zero page" or "base page", the idea being that only a single byte was needed to specify and address and thus save memory in the program code and the time needed to load an extra byte in the instruction. A single index register is a limitation, and additional addressing could be arranged using the L and Y registers. One operation swapped the values in X and Y, allowing Y to be used as a direct backup for X. A second allowed the values in Z and X to both be copied into L, allowing L to be used as a buffer for a complete 14-bit address.
Additionally, the value in the X register could be automatically incremented or decremented by certain branch instructions. This improved the speed of loops as a single instruction would increment or decrement the value, test to see if it crossed zero, and if it had, skipped forward one or two bytes. To use this feature you would write a loop with one of these instructions at the bottom, followed by the address of the top of the loop. Normally it would not cross zero and the PC would be loaded with the following address. When it did cross, the address would be skipped over and the program would continue at the next instruction. Addresses could be 1 or 2 byte depending on whether the 7th bit of the first byte was a zero or one.
The 5-bit stack pointer is normally implemented in 32-bytes of RAM. Like most systems, the S register is updated when data is pushed or pulled. If S ever reaches 31, indicating the stack is full, the next instruction will be skipped, similar to the increment/decrement modes. This feature allows one to place a branch or return instruction just after the push or pop, and then place a branch into a handler for the stack full beyond that. Normally the execution would continue with the first branch, but in the case the stack fills alternate code can be called which might, for instance, write out the stack to memory and clear it to provide more room. While small by standards set by processors like the Zilog Z80 or even the MOS 6502, this size of stack is suitable for systems that generally used it only for subroutine calls into ROM or interrupt handlers.
Among its more curious features was that it only had two status bits, carry and intermediate carry. These were placed in bits 15 and 16 in L, which was otherwise unused due to the 14-bit addresses. Most processors of the era had additional status bits to indicate the outcome of comparisons, like whether the value in A is zero, but in the PPS-8 these were combined with the branch instructions so they did not have to be user-visible.

Instruction set

The instruction set in the PPS-8 was relatively simple in terms of the numbers and types of instructions, including add and subtract, increment and decrement, logical operations for AND, OR and XOR, shifts and rotates. As was typical for the era, the PPS-8 included instructions for directly working with binary-coded decimal data. This is a numeric format that stores a decimal digit in 4-bits, with two digits per byte. BCD is generally slower to process than binary numbers due to the "decimal adjust" step that is not needed for binary data, but can more than make up for this because it is very easy to convert to and from ASCII values. Not only did the PPS-8 offer BCD addition and subtraction, it also had instructions that shifted an 8-bit value by 4-bits, making it easier to extract individual digits. The system also had instructions to load values from memory to registers, save from registers to memory, and, somewhat uncommon, exchange them in a single operation. Note that it does not have compare operations, as these are combined with the branches into a single operation.
Although the instructions were fairly typical, there were a large number of addressing modes and thus a large number of opcodes. The load/store operations generally came in five versions, the base instructions, L, S or X, which used the addresses referred to data memory pointed to in Z+X. Adding N to the assembler mnemonic post-incremented the X value after the instruction ran, D post-decremented instead, while NXL and DXL did the same but also then swapped the ZX value into L, and NXY which incremented X and then swapped it with Y. Finally, the NCX instruction incremented X and then compared it with Y as the decision of whether or not the branch was complete, rather than crossing zero, and DCX was the same with a decrement. Access to the program memory was only through the PC or the L register; when using L, bits 16 and 8 were ignored to produce the 14-bit value. With all of these modes, if the upper bit of the lower byte of the address was zero, the upper byte would be ignored and thus allowed a form of short addressing similar to a zero page.

Data pools

One of the unique features of the PPS-8 was the concept of "data pooling". This was similar to the concept of a zero page in that it allowed instructions to be written in fewer bytes, normally two instead of three, but took this one level further to produce instructions that required only a single byte. To do this, several "pools" of memory were set aside for special purposes.
The first pool, the first four bytes in memory, were used to point to the power-on routines. Similar concepts were used in most processors of the era, either the first few bytes of addressable memory, or the last few. The next 60 bytes, making up the rest of the first half of page zero, contained the "command pool". These were single byte values that held the second or third bytes of multi-byte instructions. The idea was to allow those instructions that were widely used in the program to be placed in the command pool and then referred to using a single byte whose lower 6 bits encoded one of the locations in the pool.
The second half of page zero was used as the "literal pool". These could only be used with the instructions LXI, LYI, LZI/AISK and LAI/ANI. Each of these instructions was given its own set of 15 bytes, with a 16th slot left empty. The "I" in these instructions indicated that they used "immediate" addressing, meaning the operand was a literal value in the code. If that literal value appeared in many places, which is often the case for hardware addresses and loop counters, moving it to the literal pool would reduce them all by one byte. This could be combined with the command pool to reduce the remaining instruction to a single opcode as well, making these common instructions go from three bytes to one.
Finally, the first half of page one held the "subroutine entry pool", a list of addresses in program memory. These were stored with the high bytes in locations 0 to 31, and the low bytes in 32 to 63. Using these slots, branches and subroutine calls could also be reduced to a single byte opcode. The use of data pools and the increment-compare-and-branch instructions allowed the PPS-8 to build loop structures in very little code, often as few as three instructions, and by using the command pool, reduced those to a single byte each. This made the system extremely efficient, but at the cost of being much more complex to program.