2
$\begingroup$

For example, on x86, we have a set of general registers, each named to the function it carries out.

We have an Accumulator, which is a storage for a results of different fixed point operations, we have a Base register, which is used for addressing elements in the array, a Cycle register, which holds a incremented or decremented counter for cycles, we have a Data register, which can hold an operand for arithmetic operations, and many many others (like base and stack pointers, indexes, and etc.)

But on typical RISC architectures, like SH4, for example, you won't find such an explicit names for registers. On Sh4, for example, there's no explicit name for register, which must hold a stack pointer, so you can store it elsewhere upon your choice from 16 available registers. Same for arithmetic operations, and so on.

So why it is that?
It is simply a matter of design, choices, taken by Intel engineers, or some significant sign of RISC processors?

$\endgroup$
6
$\begingroup$

The main historical trend that accounts for the change in instruction sets is the dropping cost of memory. The x86 instruction set derives from the 8080, which derived from the 8008. The 8008 was first sold in 1972, when the cost of memory was about US\$0.05 per bit. 1 MByte would have cost about US\$400000, and even a KByte cost about \$400. Now you can get 4GB of DRAM for less than $40 (US\$0.00000000125 per bit) so the price has dropped by a factor of about 40 million in 40 years. (I may have missed a decimal place somewhere, and it also doesn't account for inflation (another factor of 5 or 6). But you get the idea.)

Expensive memory meant you needed to try to make the instructions as small as possible. There are a couple of ways you can do that. One way is using variable length instructions. The 8008 and 8080 had 1 byte instructions. If an instruction needed immediate data, the constant would be stored in the following byte (or bytes for 16-bit constants in the 8080). So instructions could vary between 1 byte and 3 bytes.

Another is to make the register operands implicit. The 8008 and 8080 each had 8 registers, so to specify two source registers and a destination register would have consumed 9 bits (already more than a byte!) Instead of having three operands, you can try to get away with 2. Most x86 instructions have 2 operands, one is the destination and also one of the sources, while the other is a source. But you can do still better. By assuming that all arithmetic instructions use the accumulator register as both the first source and the destination you only need to specify a single source operand. Similarly if you assume that all the stack manipulation instructions work on a specific stack register you can get away with not specifying the register holding the stack pointer. Similarly with loop counter increments and tests you can get away with no register specifiers if you have a dedicated loop counter.

Instruction compression of this kind is good but it comes at a couple of costs. The most important cost is that the instructions are variable length and hard to decode. The 8080 took several cycles to decode each instruction. By the 1980s the cost of memory had come down considerably, and people started to realize that by making instructions easier to decode it would be easier to design high-performance pipelined processors. RISC instructions are designed to be easy to decode (and to not have more than one memory operation so that they can be pipelined).

Instruction set design still has a small effect, mainly seen in power consumption. In general the decoders on x86 machines consume more area, and also more power, per instruction decoded than do machines with RISC instruction sets. On the other hand the x86 power consumption can be reduced somewhat during tight loops by caching a small number of decoded instructions. Additionally the number of instructions to encode a program in x86 is about half that to encode the same program with a RISC instruction set, so the instruction fetch bandwidth (and thus the power consumption for instruction fetch) is a bit lower with x86 than it is with RISC instruction sets.

| cite | improve this answer | |
$\endgroup$
  • $\begingroup$ It would be nice to mention the compiler benefit of general purpose registers (and 16+ of them) in terms of easier high-quality register allocation (e.g., avoiding cases where unused registers are of the wrong type). x86 has increasingly moved to a more general purpose model, particularly with the 80386 but recently a variable shift not using the Count register has been added. Singular registers can also introduce artificial dependencies. E.g.., this comp.arch post: $\endgroup$ – Paul A. Clayton Mar 20 '14 at 14:01
  • $\begingroup$ "The main problem is the serial dependencies on the shift count" $\endgroup$ – Paul A. Clayton Mar 20 '14 at 14:02
  • $\begingroup$ One thing I've sometimes wondered about is whether it would be better to have 64 instructions take the form [Rx=Rx+Ry] with x and y both 0..7, or 32 each of the forms [R0=R0+Rn] and [Rn=R0+Rn] with n=0..31, but have an 512 "extended operand select" opcodes which would allow the following instruction to make independent one-of-32 choices for both source operands and the destination [9 bits of the prefix plus 6 of the main opcode would yield a total of 15 bits to make three register selections]. I would expect a compiler could arrange things so most operations would fit the "compact" forms... $\endgroup$ – supercat Feb 9 '15 at 18:20
  • $\begingroup$ ...but the prefixes could be used in cases where it's necessary to operate on another register while r0 holds something useful. The Rx=Rx+Ry approach only allows 8 registers, rather than 32, and would end up requiring two instructions when it's necessary to compute Rz=Rx+Ry [putting it tied with the one that could, using two instructions, allow operands to be chosen from a set of 32 rather than 8]. $\endgroup$ – supercat Feb 9 '15 at 18:25
2
$\begingroup$

This comes from the misty prehistory of computing, when registers where one-purpose only. Remember that the i686 (and all previous ones of the line, i.e., i?86) contains an 8086 as a subset, and that one contains (almost) an 8080 as subset. Register names come from the use in the beginnings.

In contrast, RISC architectures were designed from scratch, with the explicit goal of simple (i.e., fast) instructions, and as regular as possible (all registers equivalent, all instructions can use any addressing mode, ...). Simple, regular instructions means simpler (faster) decoding, more uniform execution (everything takes almost the same time). This in turn means less circuitry for doing the above, can dedicate more silicon to registers.

| cite | improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.