One of the most interesting features was a built-in hardware stack capable of holding up to 16 48-bit words. This was known as the "nesting store" or "nest". A 'fetch' operation from memory copied the word from memory into the top of the nest, pushing all other values down one position. Arithmetic operations were carried out on the top few values in the nest, replacing the operands by the results. A typical sequence of instructions might look like:
Y0; Y1; +; =Y2;This would fetch a word from each of locations Y0 and Y1 into the nesting store, add them, and place the result in location Y2. This sequence removed all the words that had been loaded, leaving the nest in the same state as before the sequence shown.
FORTH experts will recognize code like this - you could almost say that the KDF9 was an early implementation in hardware.
Another hardware feature was a second nesting store, capable of holding up to sixteen return addresses for subroutines.
The third essential feature of the CPU and instruction set was a set of sixteen 48-bit registers known as "Q-stores". They were numbered Q0 to Q15; however, Q0 was a 'magic' register that always held the value zero - ie, storing into it didn't work. Each was normally used as 3 16-bit registers, numbered C1, I1 and M1 for example. They carried these names because they were designed for controlling loops, where the "C" part of the register was used as a counter, the "I" part was an increment, and the "M" part was a modifier, which could be used as an address index.
Thus, the following pseudo-code would be implemented as shown:
float y[60]; for {i=0; i<20; i+=2} { y[40+i]=y[i]+y[20+i]; } ----------------------------------------------- set 10; =C1; set 2; =I1; set 0; =M1; 1; Y0M1; Y20M1; +F; =Y40M1Q; J1C1NZ;In the first line, "set 10;" puts the value "10" into the top of the nest, and "=C1" stores it in the C-part of Q1. I1 is set to 2 and M1 to 0 similarly.
In the second line, "1;" is a label. In "Y0M1", the address Y0 modified by the value of M1 will be fetched into the nest, followed by Y(20+M1). They will then be added as floating-point numbers, and the result stored into Y(40+M1). The final "Q" on the store instruction causes the counter to be decremented by 1, and the modifier to be incremented by the value "2" that is in the increment register I1.
Finally, the instruction "J1C1NZ" tells the CPU to branch back to the label while C1 is still not zero, and continue to the next instruction when it is.
Two Algol compilers were available for the KDF9, written I suspect in competition with one another. One, the Kidsgrove compiler, was a highly optimised version intended for production use. The second was known as the Whetstone compiler, and was intended for much faster compilation and debugging. Algol 60 was my first 'real' programming language, and it was sad that it was ruined by the over-ambitious Algol 68 specification - a perfect example of a design by committee. If they had only added character-mode variables and a few other items to Algol 60, there would never have been a need for Pascal - or C. (I expect this comment to draw a few flames...)
I still have a copy of the KDF9 User Code manual. Click here