Vintage Computing RPC-4000

Dissecting the Story of Mel

One of the things that piqued my interest in the RPC-4000 was the role it plays in the “Story of Mel”. A famous piece of hacker folklore describing the early days of programming – when “abstraction” and “modularity” were not a thing yet. To the contrary, programmers aimed to make full use of all intricacies of a machine to optimize their programs. Any side effect that let you squeeze out another instruction cycle or save a word in memory was fair game!

The story is set around 1960, after Royal Precision had adapted their trusty Blackjack tradeshow demo from the LGP-30 to the new RPC-4000. Ed Nather was asked to fix a small bug in the program after the original programmer, Mel, had left the company. Ed describes the close-to-the metal programming of the day, Mel’s skill and ambition to optimize his code, and how Ed had a hard time figuring out Mel’s coding tricks.

Ed recounted and posted his story on Usenet in 1983. I won’t retell it here – Ed does a much better job at that. Please treat yourself to the original story if you have not read it!

But is it true?

Mel was for real, and he was indeed the programmer of the RPC-4000 Blackjack version. We now know that his full name was Mel Kaye (Americanized from Melvin Kornitzky); he is included in a group picture in a 1956 Librascope company journal; and his name appears on the Blackjack program documentation and a few other programming artefacts from his Librascope days. There is a great fan website researching Mel’s background and CV.

Mel Kaye as one of the instructors of a Librascope programming class. From the 'Librazette' company journal, August 1956.

There is no reason to doubt that Mel did employ intricate and creative optimization tricks, and that his colleague Ed struggled mightily to figure them out. But Ed also describes in specific technical detail how the particular hack – finding a way out of an apparently infinite loop – supposedly worked. And some of those details don’t align with the actual RPC-4000 instruction set, which is well-known from the preserved manuals. Which leads to the question how Mel could actually have implemented such a hack on the RPC-4000.

Here’s the catch

Ed Nather describes how Mel routinely used self-modifying code to let his programs loop through array elements: Increase the address field in the instruction and write the modified instruction back to program memory, shunning the newfangled “indexed addressing” alternative offered by the RPC-4000. And he explains how Mel “abused” that mechanism to let the address field overflow into the opcode field – creating an entirely new instruction, which provided the only way to exit the otherwise endless loop he had set up.

Ed also recounts how Mel’s use of the Index flag gave him the vital clue in his reverse-engineering: In any given instruction, that flag bit activates the use of indexed addressing in the RPC-4000. And since Mel was known to never use that mode, something funny must be going on with an instruction which had the bit set. Ed explains that Mel needed to set the Index bit to ‘1’ to allow his overflow trick to work – because “the bit lay between the address and the operation code in the instruction word”. And that, unfortunately, is not the case:

The RPC-4000 instruction word format. Note that bit zero on the left is the most significant bit.

This figure from the RPC-4000 Features Manual shows that the Command (opcode) bits are located directly above the Operand Address bits. Incrementing the Operand Adress to create an overflow into the Command field works nicely. But it works totally independent of the Index bit, which sits innocently at the very end of the instruction word as the least significant bit.

So there was no reason for Mel to set that bit – and give Ed the “vital clue” he needed to figure out Mel’s trickery. The story does not check out in this respect.

High memory is precious!

Ed also writes that Mel “had located the data he was working on near the top of memory — the largest locations the instructions could address”. That seems vital for the hack to work, because incrementing the address eventually needs to produce an overflow into the opcode field.

But the “top of memory” addresses are special in the RPC-4000. The five highest track addresses (123 to 127) refer to tracks which can hold fewer data words, but allow faster access to those words. Track 127 in particular holds only 8 words of data and automatically repeats them 8 times per revolution. In a program optimized for speed those words are nearly as valuable as the CPU registers for holding often-used variables. There is no way Mel would have wasted all of them on an array!

The RPC-4000's Recirculating Track allows fast access to eight memory words. A dedicated pair of read/write heads replicates data in the background, so they appear eight times per drum revolution.

I think we can “rescue” this part of the story. It seems very likely to me that Mel was using the same sector number but different tracks for each of his array elements. Hence, to move forward to the next element, he would increment the track address by adding to bit 11. This can still produce the overflow into the opcode field, and uses only one word in each of the precious fast-access tracks.

This explanation also seems plausible because it preserves optimum timing for the array access – assuming Mel had optimized the relative locations of instructions and data on the drum to minimize waits, as was his standard. The array elements would all reside in the same sector, i.e. would be accessible at the same optimized time relative to the prior instruction fetch.

Hence, while Ed’s description of Mel having used “the top of memory” is probably not accurate, it does not get in the way of a plausible hack based on an address overflow.

A tangent about self-modifying code

As a side note, one of the shortcuts Ed attributes to Mel’s self-modifying code does not check out either. He mentions that, after incrementing and storing the modified instruction, Mel would “execute the modified instruction right from the register”. That’s not a facility available to RPC-4000 programs: The user can execute an instruction from the accumulator interactively from the front panel, as a way of bootstrapping the machine. But under program control there is no instruction to achieve the same effect.

While this is not a required feature for the hack described in the story, it is another indication that Ed’s memory of the technical details was a bit blurry – very understandable given that more than 20 years had passed.

Side note to the side note: “Read – modify – write back – read to execute” was a rather unfavorable sequence of actions on the RPC-4000. Three of those four operations require access to the same memory location on the drum, hence the total sequence takes more than two full drum revolutions. To make effective use of the computer, you would either have to interleave these operations with other code. Or you could place that critical self-modified instruction in one of the eight precious memory words on the RPC-4000’s “Recirculating Track” 127, where it would appear eight times per drum revolution for much faster access.

Or, if you could afford to reserve an accumulator for the duration of the loop: You could keep and increment the operand address in the accumulator and use a dedicated “Store Address” command to patch just the address field of an instruction in memory. That saved one memory access of the read – modify – write cycle, but you still needed another access to fetch and execute the instruction. The existence of a dedicated address patching command shows how commonly self-modifying code was used!

The SAU instruction. Self-modifying code was so common that the RPC-4000 provided a dedicated instruction to patch operand addresses in memory.

What others think

Several enthusiasts have looked into the technical details of the Story of Mel. But I am not convinced by any published analysis so far. In chronological order:

How did Mel really do it?

Key ingredients of the hack

There are several technical details of Mel’s hack which I assume Ed Nather remembered and recounted correctly, because they are so central to the story:

So, assuming the above is right – what are the potential hacks Mel could have implemented on the RPC-4000?

Create a TBC instruction

TBC stands for Transfer on Branch Control, opcode 101112. It’s a conditional jump which is taken when the machine’s internal Branch Control flip-flop was set by a preceding operation – by an overflow, a comparison or by checking external switches. The bit field that serves as the operand address for most instructions becomes the Target Address, i.e. the address where program execution continues if the branch is taken.

David Nugent has previously proposed TBC as the likely “hidden jump” instruction used by Mel. It resonates with some of the aspects we expect to find in the hack, but I see a major stumbling block:

So I don’t think this conversion of a TMI into a TBC instruction is the specific opcode modification that Mel used.

The TBC instruction. The operand address becomes the 'transfer address' here, i.e. the address of the next instruction if the branch is taken.

Create a TMI instruction

As just mentioned, TMI is the other conditional branch available in the RPC-4000: Transfer on Minus, opcode 101102. Again, this could be created from its “precursor” instruction via an overflow of the operand address into the opcode field.

The TMI instruction works analogous to TBC, but branches upon negative values in the accumulator.

Create a SNS instruction

This is my favorite theory. The SNS instruction, Sense (opcode 000002), checks the status of a set of switches on the front panel (and/or of the active I/O devices) and sets the Branch Control flag accordingly. The track part of the operand address field is interpreted as a mask that defines which inputs are to be checked.

The SNS instruction checks switches on the RPC-4000 front panel. The operand address field is used as a mask defining which switches are evaluated.

If the mask field in D-TRACK is zero, the SNS instruction turns into a HLT which stops program execution.

Conclusions

So, do we know the true details of Mel’s hack now? Not really…

Among the three scenarios I came up with, I would rule out the TBC variant and consider the creation of a SNS instruction the best fit, for the reasons discussed above. But there is no hard-and-fast argument that it’s the only plausible implementation. And of course there might be other variants which I have not even thought of!

I am currently revisiting my RPC-4000 replica project and plan to get in touch with a couple of collectors. Maybe there is still a chance that the original RPC-4000 Blackjack program will resurface and give us a definite answer…