up much larger, and could in theory run much faster. For instance, a string of instructions carrying out a series of mathematical operations might require only a few loads from memory, while the majority of the numbers being used would be either constants in the instructions, or intermediate values left in the registers from prior calculations. In a sense, in this technique some registers are used to shadow memory locations, so that the registers are used as proxies for the memory locations until their final values after a group of instructions have been determined. To the casual observer, it was not clear that the RISC concept would improve performance, and it might even make it worse. The only way to be sure was to simulate it. The results of such simulations were clear; in test after test, every simulation showed an enormous overall benefit in performance from this design. Where the two projects, RISC and MIPS, differed was in the handling of the registers. MIPS simply added lots of registers and left it to the compilers (or assembly language programmers) to make use of them. RISC, on the other hand, added circuitry to the CPU to assist the compiler. RISC used the concept of register windows, in which the entire "register file" was broken down into blocks, allowing the compiler to "see" one block for global variables, and another for local variables. The idea was to make one particularly common instruction, the procedure call, extremely easy to implement. Almost all programming languages use a system known as an activation record or stack frame for each procedure which contains the address from which the procedure was called, the data (parameters) that were passed in, and space for any result values that need to be returned. In the vast majority of cases these frames are small, typically with three or fewer inputs and one or no outputs (and sometimes an input is reused as an output). In the Berkeley design, then, a register window was a set of several registers, enough of them that the entire procedure stack frame would most likely fit entirely within the register window. In this case, the call into and return from a procedure is simple and extremely fast. A single instruction is called to set up a new block of registers—a new register window—and then, with operands passed into the procedure in the "low end" of