14

I am interested in the SKIP instructions on the PDP-8. These test the accumulator and Link bit, and they skip the next instruction if the condition holds.

The instructions are:

  • OR GROUP
    • SMA - Skip if the Accumulator is less than zero.
    • SZA - Skip if the Accumulator is zero.
    • SNL - Skip if the Link bit is 1.
  • AND GROUP
    • SPA - Skip if the Accumulator is zero or positive.
    • SNA - Skip if the Accumulator is unequal to zero.
    • SZL - Skip if the Link bit is 0.

And you can combine any of the three in each group into a single instruction. For example, if you wanted to skip the next instruction if the Accumulator is zero OR the Link bit is 1, then you may code SZA SNL as a single instruction. The OR group also has a "don't skip". The AND group also has a "skip unconditionally". So as you can see, each group has the opposite conditions of the other group.

This is quite different from the conditional branching on the PDP-11 and the 6502 computers.

So why did they design the PDP-8 in this way? Is there some logic to associating SPA SNA SZL with boolean AND, and SMA SZA SNL with boolean OR? Or is it some artifact of the underlying electronics?

  • 1
    DEC weren't the only ones with skip instructions. Data General and Prime also had skip instructions. In fact, the modern day PIC still has skip instructions. – cup Mar 2 '18 at 10:56
  • I heard Data General came from DEC, much like the MOS guys who did the 6502 came from Motorola. But who are Prime? – Wilson Mar 2 '18 at 10:59
  • It is just one of those minis I used when I was in Uni. It was the first multi-terminal mini. en.wikipedia.org/wiki/Prime_Computer – cup Mar 2 '18 at 11:01
  • Hewlett-Packard computers (HP2000) of that era also used skip instructions. – gbarry Mar 21 '18 at 4:52
  • @gbarry and the PDP-10 too, apparently. – Wilson Mar 21 '18 at 8:27
14

If you compare the octal opcodes for the skip instructions,

                 a bcd  
                 | |||
7500 SMA = 111 101 000 000
7440 SZA = 111 100 100 000
7420 SNL = 111 100 010 000
                 | |||
7510 SPA = 111 101 001 000 
7450 SNA = 111 100 101 000 
7430 SZL = 111 100 011 000

you see that in each group, there are three conditions that can be tested, each as a bit from a to c, and the bit d complements the test result. If you remember de Morgan's laws, complementing an or-term turns it into an and-term, and vice versa, and that's why you have an and-group and an or-group, and also why you can't combine instructions from different groups (there are only three bits for three conditions that can be set at maximum).

So it's an artifact of the very simple underlying electronics (an extra programmable inverter at the final output of the condition circuitry) that make up the CPU.

But choosing these specific conditions is also by design, because you can combine the conditions and get other useful conditions, e.g. "skip on less or equal than zero", or "skip on greater than zero".

As the CPU was made of discrete gates, keeping everything simple (and therefore comparatively cheap) was very important for the PDP-8.

The clear/complement instructions follow a similar scheme.

  • 1
    The description of deMorgan's laws omits that the result has to be complemented as well, but that's a nit, and the next paragraph mentions the programmable inverter that makes it all work. Very nice answer. – Wayne Conrad Mar 21 '18 at 19:49
4

It is an artifact of the underlying electronics.

The PDP-8 had a very small instruction set of just 8 elementary instructions.
The PDP-8 used core memory, predating RAM.
Remember that the act of reading a location of core memory had the side effect of setting it to zero - something I suspect would give modern software writers kittens.

The AND and OR groups you mention in your question are actually part of the OPERATE instruction. As you say, a bitwise OR of SMA and SML created a new, single word, instruction.

Software had to be written to optimise the use of the core. If you zero your memory, you have to write something back. The basic 8 instructions were designed with this optimisation in mind.

The 8 instructions didn't include OR (or XOR). To implement these in a program you had to construct them in code. This was done with the OPERATE instruction as you have found.

My memory of PDP-8s is a little rusty (I used the PDP-11 much more!), but I hope this gives some steer.
There is some good information on the PDP-8 at GRC. To quote a relevant section:

But this also means that CHANGING the contents of a memory location can be done "for free" if its new value is known immediately, as is the case with incrementation, where the value just read from the location immediately determines its next value.

The PDP-8 system cleverly used this characteristic in two places:

The Increment and Skip of Zero (ISZ) instruction would read, increment, and re-write a value one greater than the specified memory word previously contained. Since the system's core memory system needed to perform a memory rewrite anyway, rewriting the memory with its incremented value was a zero-cost operation - it took no additional time than writing-back the same data would have.

Much of the information posted in various places has come from old users putting up manuals that they have for others to find. It can be confusing to pull it all together.

  • 6
    For the programmer, the fact that the core was zeroed by reading wasn't visible at all - the instructions that didn't modify memory just wrote it back (which is why they took longer than some other instructions). Also, I don't think it's relevant for the question. – dirkt Oct 20 '16 at 13:47
3

I'd like to add a few words on conditional branching.

This is quite different from the conditional branching on the PDP-11 and the 6502 computers.

It simply doesn't fit into the PDP/8 instruction scheme, the 12 bits aren't enough for that. A conditional branch needs two aspects in one instruction:

  • defining the branch target (the jump address)
  • defining the condition (typically by having multiple opcodes)

The branch target would have to follow the memory-reference-instruction pattern of the PDP-8 to keep the gate count low and the range of reachable target addresses useful. So there'd be 9 bits for the branch target.

As you'd need at least a handful of different conditions (zero, nonzero, positive, negative, carry, noncarry), you'd consume a handful of opcodes. And the PDP/8 only devoted 3 bits to the opcode section, allowing for only 8 basic opcodes. Using 5 or more of them for the conditional branch was clearly impossible.

The PDP/8 also had no multiple-word instructions. So the "skip" trick allowed for a clever solution. Practically, combining a skip instruction with a jump gave a 2-word conditional branch instruction, although technically there were two individual ones. And I'm sure that clever assembler developers combined skips not only with jumps, but with other instructions as well. E.g. getting the absolute value could be simply done by

    SPA    skip the next instruction if positive or zero
    CIA    change the sign of the accumulator

No jump instruction needed.

  • On an architecture where all instructions are a single word, using a conditional-skip instruction can make things simpler, more versatile, and more efficient, than trying to squeeze in a conditional branch. Conditional branches are really only advantageous if either (1) the opcode is so huge that there's plenty of room for both the condition and destination, or (2) conditional-branch instructions can use an address which doesn't have to fit in the same word as the opcode. – supercat Mar 21 '18 at 22:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.