Out of respect to a much admired friend, I should point out that Jacob Schwartz is more famous for his great contributions to mathematics and computer science than for a old programming trick. And, come to think of it, I'm not sure that he's the one responsible for the trick; I heard it that way once, but I now recall someone telling me I had it wrong.
If you haven't heard this one, you're probably wondering what it's about. On 6600's you loaded and stored X registers by loading A registers with the addresses; if you loaded A0, X0 got stored; if you loaded A1 to A4, the corresponding X got loaded. To store an A register, you moved it to a free X register; to load it, you got the address into an X register. So X0 (I may have which registers did what a bit wrong; it's been ten years) mostly had to be kept empty.
Now suppose you're writing an interrupt routine (not common; the PP's took care of the I/O); you need to save the registers. But you have no right to assume that any register is free. Later 6600's had the exchange jump (XJ) instruction to deal with that case, but not the one at Courant. How do you get X0 free so you can save registers? Answer:
Branch to A1 on X0 negative store 0 at location c1 Branch to B1 A1 store 1 at location c1 B1 Shift X0 left Branch to A2 on X0 negative store 0 at location c2 Branch to B2 A2 store 1 at location c2 ..... 58 more times. Save the rest of the registers. Reconstruct X0 from c1-c60. Store it.
This is my memory of what I was told by various friends. Anyone with more direct knowledge, please correct me where I'm wrong.
I learned this one while working at the Courant Institute of Mathematical Sciences, New York University:
Courant had vast sums of money from the Atomic Energy Commission (later ERDA, then DOE). They ran a major computer installation which featured one of the first CDC 6600's; in fact, serial number 3. Many wonderful things were done on this machine, and many to it. Ever hear of the supercritical wing?
Well, the CDC had a bad habit of crashing at 3:00 or so weekdays. It was fairly regular about this; every few weeks, at 3:00, it would crash. The repairman would come in, find one of the "cordwood" PC cards burnt out, replace it, and things would be back to normal for a while. But everyone worried about the mystery of the regular crash.
Turns out that, because the machine was number 3, the backplane had been hand wire-wrapped. The technicians had left fingerprints all over the place. A fungus was growing on the backplane, apparently fed by the oils in the fingerprints. Most of the time, the air in the room was very dry, and the fungus didn't grow. But when the operators came in on weekdays, the moisture in their breath was enough for the fungus to grow a bit. Eventually it would short a couple of pins (remember, the 6600's circuitry was run at the ragged edge) causing something to burn out. Of course, that bit of fungus would get incinerated too.
An application of spray fungicide cured the problem.
This machine is the subject of a bazillion stories, as are some of the people around it. It's the machine that Ken Kesey and the merry pranksters threatened to blow up (hence, despite programming on it for a year, I never saw it; the floor it was on was locked up). Jacob Schwartz, my old boss, was famous for inventing the first way to save one register when you couldn't touch the rest: a long series of test and branch instructions (the Courant 6600 didn't have an exchange jump instruction; that came later). Garabedian and Jameson did the first numerical simulations of the supercritical wing on it; that idea later resulted in 30% fuel savings for jet engines. Charles Peskin used it to simulate blood flow in a dog's heart. I used UT LISP on it; the only LISP with CONS, CAR, CDR, and CSR (cooser); addresses were 18 bits, words were 60 bits, so they put another pointer in a CONS cell.
In article <1989Dec14.064508.17...@cs.rochester.edu>, f...@cs.rochester.edu (Mark Fulk) writes:
> If you haven't heard this one, you're probably wondering what it's about. > On 6600's you loaded and stored X registers by loading A registers with > the addresses; if you loaded A0, X0 got stored; if you loaded A1 to A4, > the corresponding X got loaded. To store an A register, you moved it to > a free X register; to load it, you got the address into an X register. > So X0 (I may have which registers did what a bit wrong; it's been ten years) > mostly had to be kept empty.
Some details deleted.
> This is my memory of what I was told by various friends. Anyone with more > direct knowledge, please correct me where I'm wrong.
The above is sort of right, but here are the gory details, (taken from 20 years of CDC assembler experience, plus the old listing still stored next to my desk!)
OK, there are 3 register sets:
B (18 bit index registers) 1 through 7. B0 is write-only, it always reads as 0.
X (60 bit data registers)
A (18 bit address registers) Writing into A1 - A5 reads the contents of that memory address into the corresponding X register. Writing into A6 or 7 causes the contents of X6 or 7 into memory. Modifying A0 does not perform any memory access.
Now, note that the only way to store anything into memory is writing into (and thus destroying the contents of) A6 or A7. But.. an Return Jump instruction (used for calling subroutines) will write a return branch instruction into memory. We now have the basis for setting memory flags depending on B register bits.
OK, so the sequence for freeing up 1 B register is: PL B7,BRANCH1 (jump to BRANCH1 if B7 is positive) RJ BRANCH1A (stores return in BRANCH1A and starts executing at BRANCH1) BRANCH1A DATA 0 BRANCH1 SB7 B7+B7 (sets B7 = B7*2, shifting the next bit to the sign position) PL B7,BRANCH2 . . continue for all 18 bits. .
B7 is now free to save A7, so X7 can be saved without loss, etc. BRANCH1A, etc. contain indications of the previous values of the 18 bits of B7.
Whew! Register restore was handled by instruction modification. (Hey, it worked. What can I say?) I might add that this register saving was done very seldom; I have seen it used only in debugging packages. Subroutines simply documented which registers were destroyed, and the system monitor didn't have to worry about such trivia, since the user's registers were already saved by hardware. ------------------------------------------------------------------------- Steve Roseman Lehigh University Computing Center LU...@VAX1.CC.Lehigh.EDU
In article <1989Dec14.064508.17...@cs.rochester.edu> f...@cs.rochester.edu (Mark Fulk) writes: >If you haven't heard this one, you're probably wondering what it's about. >On 6600's you loaded and stored X registers by loading A registers with >the addresses; if you loaded A0, X0 got stored; if you loaded A1 to A4, >the corresponding X got loaded. To store an A register, you moved it to >a free X register; to load it, you got the address into an X register. >So X0 (I may have which registers did what a bit wrong; it's been ten years) >mostly had to be kept empty.
Ok. Here's the register scoop on a Cyber 170-state machine: it has 24 registers. 8 B registers, 8 X registers, and 8 A registers. The A and B registers are address registers (B being called 'index' registers) and are 18 bits wide; X are data registers, and are 60 bites wide (one's complement, yet...). B0 is hardwired 0 (very useful, actually), and A0 is a "normal" register. A1-A5, however, are "load" registers, and A6,A7 are "store" registers (loading, for example, 100 into A1 would cause X1 to be loaded from location 100; loading 100 into A6 would cause X6 to be written into location 100).
-- Sean Eric Fagan | "Time has little to do with infinity and jelly donuts." se...@sco.COM | -- Thomas Magnum (Tom Selleck), _Magnum, P.I._ (408) 458-1422 | Any opinions expressed are my own, not my employers'.