19

DEC, and at least some of their computers, especially those in the 18-bit family and 12-bit family, had these opr instructions, which contained many bitfields which encoded something like "subinstructions". Things like

  • clear the accumulator
  • increment the accumulator
  • rotate the accumulator one place leftward
  • complement the accumulator
  • skip if the accumulator is zero

The nature of these simple operations is such that it's convenient to encode each one in some bit or bitfield in the instruction word, and to have the computer execute each one in a statically scheduled manner. My understanding is that's because they are often used together1, and have simple encodings.

A later computer like the Z80 or ARM7 needs to fetch, decode and execute a separate instruction to perform each of these operations, which might not be as space or time efficient.

From what I can tell, using DEC-style microcoded instructions to perform any number of monadic operations on a single register, has fallen out of vogue, or are at least not nearly as common on modern instruction set architectures. Why is this?


1: Not only to load small integers into the accumulator, as in cla cll cml inc rtl to set the accumulator to 6 on the PDP-8, but also for examining or manipulating bitfields, probably long division, etc.

10
  • 3
    What you're describing are VLIW architectures - except the question you have is quite unclear - adding 'Why this' to a description isn't exactly a question.
    – Raffzahn
    Commented Apr 12, 2019 at 14:19
  • @Raffzahn I think I've identified a trend; I am asking if it's there, and if so, what's motivated it. My understanding of VLIW is that the operations are dyadic, or have variable transitivities, but on the PDP 7 et al., the operations were all strictly monadic. Commented Apr 12, 2019 at 14:26
  • 4
    This is a little off topic. The DEC PDP-6 had 16 variations on the Boolean operations. It used four bits out of the opcode field to specify a truth table for the corresponding Boolean operation. Thus it was able to implement 16 operations with about the same logic that it would have taken to implement just one. Commented Apr 12, 2019 at 14:36
  • @Wilson VLIW is not intrinsic tied to any kind of operation. The basic idea is that there is no (general) decoding, but each function unit that can be initiated separate will get it's own mark in the instruction field. THus the decoder stage can be removed - or at least quite simplified.
    – Raffzahn
    Commented Apr 12, 2019 at 14:48
  • 2
    Yes these opcodes are in the PDP-10 as well. Open the opcode list and take a close look at opcodes 400-477. If you convert the opcodes from octal to binary, you will find four bits that provide a truth table for the operation in question. SETZ has all four of these bits set to zero, and SETO has all four set to one. AND has three zeroes and a one. Commented Apr 13, 2019 at 13:36

5 Answers 5

23

[...] had these opr instructions, which contained many bitfields which encoded something like "subinstructions"[...]

What you describe is basically a (V)LIW instruction format - at least that's what it might be called today. That's what computers started out with. Separate bits for each function to be applied to the value addressed.

The DEC is somewhat of a bad example here, as its accumulator instructions are a special kind, already a bastard between clean all over LIW and dedicated encoding. The LIW aspect is used only for this accumulator subset.

Zuse's machines, like the Z22, might make a better example with their ability to have each and every instruction carry multiple operations.

A later computer like the Z80 or ARM7 needs to fetch, decode and execute a separate instruction to perform each of these operations,

Yes - and no. For one, not all possible combinations could be used together, resulting in illegal instructions. In fact, depending on the machine's construction, most of these combinations were illegal. And that's why dedicated instructions took over. Let's assume, there are like 8 different operational units in the data path. Having one bit for each in the instruction word makes easy decoding, as each would just be wired up with the enable for a single function, resulting in a fast and simple machine structure.

Of these 256 combinations (of which one would be a nop), many would not make sense - think shifting left and shifting right, or adding and subtracting at the same time. By encoding only the 20 useful combinations into a 5 bit field, 3 bits (almost half) could be freed - at the cost of an additional decoding stage.

Now, back in the old times, when machines were word-orientated (e.g. 36 bits in one word), there was much space - even resulting in unused bits. No need to add a decoding stage. Even worse, doing so would slow down the execution. Well, only a bit, but it would.

The situation changed when machines became byte-orientated and variable length instruction formats were used. Here cramping down the 8 unit lines into a single encoded 5-bit field enabled it to squeeze into a byte while leaving room for more (like a register number), without the need to fetch two bytes. Heck, it even leaves 12x8 instruction points for other encodings/irregular instructions without needing more.

which might not be as space or time efficient.

That's partially true for the time efficiency, but not space - space-wise it's an extreme saving enabling more compact code. The inner workings are (can be) still (mostly) the same, but less visible. Instead of setting a shift and an add bit, there's now a Add-And-Shift instruction.

Then again, by now encoding it into a single byte instead of a full 36 bit word, the CPU can fetch the instructions at the same speed (byte bus vs. word bus) or even 4 times the speed (word sized bus) than before. So with memory always being the slowest part, tighter encoding does not only save space, but also speeds up execution - despite the additional decoding stage.

From what I can tell, [this] has fallen out of vogue, or are at least not nearly as common on modern instruction set architectures.

Not nearly as common on the surface is maybe the point here. For one, explicit VLIW instructions are still a thing (think Itanium), but more importantly, they are always an option for internal workings of modern CPUs. Where 'traditional' code gets first decoded into sub-operations, and these later get either combined to LIW instructions again, or scheduled in parallel over different function units.

In fact, the mentioned ARM makes another good point for it to vanish. ARM had traditionally the ability to have every instruction being executed conditionally (much like Zuse did first). Cool when thinking in sequential execution, but a gigantic hurdle when it comes to modern CPUs with the ability to reorder instructions according to available data and function units. It makes rescheduling not just a hard task, but almost impossible. Even worse, ARM featured DEC-like condition handling, where each and every load did change the flags.

Bottom line: Just because something isn't (always) visible to the user-side programmer, doesn't mean it isn't there.

10
  • 5
    The Transmeta CPUs were a somewhat recent example of CPUs that used a (proprietary) VLIW instruction set internally, and another completely different one (namely x86) externally. In the Itanium, the VLIW bundles have explicit parallelism semantics (Intel calls this Explicit Parallel Instruction Computing (EPIC)), i.e. one VLIW bundle is 2 64 bit words with 3 41 bit instructions and a 5 bit "template" that tells the CPU what kinds of instructions the three instructions are and what the data dependencies are. Commented Apr 13, 2019 at 7:06
  • @Wilson Ouch. Ok, to start with, Z4 is an original Zuse (the man himself) design, while the Z22 was imagined by Theodor Fromme (call it design lead) with much help from Heinz Zemanek and Rudolf Bodo both designed the Mailüfterl and made the schematics for the Z22. The idea was to design the tube based Z22 in a way that it may be transistorized later. Which happend with the Z23. Which is a quite remarkable planing at that time. ... more to follow
    – Raffzahn
    Commented Apr 13, 2019 at 13:52
  • 2
    @Wilson you asked for it: how-were Zuse Z22 Instructions Encoded? ... wasted another perfect good day - even included some German for you to test your knowledge :))
    – Raffzahn
    Commented Apr 14, 2019 at 0:10
  • 1
    You've got some terrific information there! I can see that this kind of instruction word easily encodes many useless combinations. Much worse than the PDP 10 for example. Commented Apr 14, 2019 at 7:44
  • think shifting left and shifting right – easy to fix, make it a 1-bit shift right and a two-bit shift left → all combinations are useful. Same for subtraction, it can be encoded as operand inversion, and let's have another operation "increment" and we again get four useful combinations.
    – Janka
    Commented May 21, 2019 at 11:58
21

The PDP-7 was a one address machine. All instructions occupied 18 bits. The operations that manipulated the accumulator didn't reference memory, and therefore didn't need an address. But the address bits were in the instruction anyway, because all instructions were encoded in an 18 bit word. So why not use these unused bits to get more use out of the instruction bits?

Once you get to opcodes with a variable number of operand addresses, the need to economize in this way goes away.

5
  • 8
    To add to this, the PDP-7 is from an era when it was common for the width of the address bus to be less than the width of the data bus. In this case, you could fit a full 13-bit address into an 18-bit instruction word, which meant that you could pack an entire instruction (including the operand address) into a single word. Compare this to a CPU like the 6502 with 8-bit words and 16-bit addresses: if you can't fit an address into an instruction word then naturally they must come in extra bytes that follow the opcode byte. (continued)
    – Ken Gober
    Commented Apr 13, 2019 at 14:56
  • 5
    The flip side of being able to fit the address into the instruction word was that you wasted a lot of bits for instructions that did not need an operand address or jump address. So the PDP-7 style sub-instructions were essentially a way to use unused bits in the instruction word to encode additional instructions, allowing many more instructions to be added without the cost of widening the word size, the only caveat being that the extra instructions had to be ones that didn't need to include an address.
    – Ken Gober
    Commented Apr 13, 2019 at 15:00
  • 3
    @KenGober, I think you and I are saying the same thing, in different words. Thanks for adding a little clarity. Commented Apr 13, 2019 at 19:36
  • Worth mentioning that the HP minis had very similar stuffed instructions. Commented May 22, 2019 at 19:16
  • 1
    The designers of the DEC machines before the PDP-11 got this from the MIT Lincoln Labs TX-0, designed by Wesley Clark. It had 2 opcode bits: store AC, add to AC, cond jump, and operate on the AC (the "microcoded" instruction). [When the machine moved from MIT LL to the MIT campus, the memory was replaced with a smaller one, so fewer address bits were needed, so the opcode size was increased, and more instructions were added.] Wes used a very similar 2-bit opcode instruction set in a later 10-bit machine at LL, the L-10. bitsavers.org/pdf/mit/tx-0/MIT_TX-0_InstructionSet.txt Commented May 22, 2023 at 15:30
4

Another good example of this basic architecture is the HP2100 series, which had a series of bit-field instructions that performed things like test-and-branch. They could combine up to eight instructions in some cases. This basic idea was relatively common in the few minicomputers I've looked at.

The reason they fell out of favor was that they require expansion of the microcode engine to store more state, and thus they make simple pipelining more difficult.

Consider the 6502; it ran at roughly 2x the speed of other CPUs of the era at any given clock rate because it was always fetching the next instruction while the last was completing. This was simple to implement even though the instructions took anywhere from 2 to 7 cycles to complete.

But imagine if those instructions are, effectively, macros. In that case you have to decode and the feed the individual sub-instructions into the pipeline. Not impossible, but certainly complex. So the question ultimately comes down to code density - the 6502 was designed as a microcontroller, so density was not super-important while gate count was. In a mini, which cost the equivalent of $100,000 but may have still only had 4k of memory, things look very different.

I'm not sure I would say these are VLIW. As I understand it, VLIW extracts parallelism by encoding different instructions for different functional units into a single instruction. This is not the same; these multi-instructions loops over the same functional units. It seems more in keeping with something like the 68k's microprogram, no?

1
  • Maybe a little (late) nitpicking: The 6502 doesn't run twice as fast lock wise because of fetching an instruction in parallel, which it didn't, but because it's internally double clocked. It's clock generator turns one clock phase into two used to perform two steps per cycle. Also, it didn't fetch another instruction, but finished the previous instruction while fetching the first byte of the next - a feature other 8 bit show as well.
    – Raffzahn
    Commented Aug 27 at 16:55
1

Modern CPU architectures also need to facilitate things like memory protection, so they need to implement restrictions on what machine code can and cannot effect depending on context. You do not want normal application code to be able to mess with other code in a multiuser/multitasking environment, and you certainly do not want it to be able to crash the machine wholesale.

An architecture allowing a near arbitrary number of instructions with unintuitive effects, maybe even side effects of "illegal" instructions that arise from causing hardware-level conflicts, or even worse creating odd conditions that will cause unexpected behaviour of instructions further down the line, will make this very hard.

In a security context, even something that has the side effect of probabilistically or deterministically defining the behaviour of an undefined action can be bad news - this can facilitate unwanted monitoring of or communication with other running code....

3
  • Could you say exactly how this kind of instruction word gives rise to the security risks you mean? Commented Jan 16, 2020 at 6:58
  • Think of spectre/meltdown .... and how much in that direction you could do in a CPU that lets you mess with its component parts unchecked! Commented Jan 16, 2020 at 18:41
  • 1
    The effect of the "operate" instruction is well-defined. Suppose, for example, N different single-function instructions were provided instead of the N bits of "operate". Why would that be more secure?
    – dave
    Commented Apr 19 at 20:58
0

Skipping an instruction meant that the machine had to know how many addressing-units (words or bytes) were in the next instruction (typically 1). When they put variable-length instructions in the PDP-11, the old way was no longer possible (at least without expensive look-ahead). And testing the AC meant there was one AC to test but the PDP-11 had 8 registers instead. I believe the idea of using the address field of one ('operate') instruction to represent a number of functions was first found on the TX-0 computer and was simply carried on by its successors at MIT Lincoln Lab and the early DEC architectures.

2
  • Skipping an instruction on the PDP-11 would be complicated by the fact instructions which use program counter postincrement mode are treated as a one-word instruction that, during execution, bumps the program counter past a fetched operand word, and skipping the effects of the instruction entirely would cause the following word that would normally be treated as data to instead be executed as an instruction. Were it not for that, I would think than an instruction skip could be handled by having LSB of the program counter (not needed for accessing) suppress register updates etc. that would...
    – supercat
    Commented Aug 27 at 15:19
  • ...otherwise be performed by an instruction and then clear itself once execution was complete. If an interrupt happens immediately after a "skip" instruction, the saved PC value would have bit 0 set, and on return from interrupt the "skip" instruction would be "executed", but without being allowed to actually do anything.
    – supercat
    Commented Aug 27 at 15:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .