Hacker News new | ask | show | jobs
by flohofwoe 598 days ago
> it allows the program counter to be used a general purpose register

From a CPU emulator writer's perspective this isn't all that strange. For instance on Z80 the immediate jump instruction `JP nnnn` is loading a 16-bit immediate value into the internal PC register, which is the same thing as loading a 16-bit value into a regular register pair (e.g. 'LD HL,nnnn') - e.g. the mnemonics for the jump instruction could just as well be `LD PC,nnnn` ;)

A relative jump (which does a signed-add of an 8-bit offset value to the 16-bit address in PC) is the same math as the Z80 indexed addressing mode (IX+d) and (IY+d) (I don't know though if the same transistors are used).

A RET (load 16-bit value from stack into PC) is the the same operation as a POP (load 16-bit value from stack into a regular register pair).

...so it's almost surprising that the program counter isn't exposed as a regular register in most (traditional) CPUs. I guess in modern CPUs it's not so simple because of the internal pipelining though.

1 comments

The reason why the PC is not normally exposed as a regular register is that the set of operations needed for the PC is different than for the regular registers.

There are operations required for the PC that are not needed for regular registers, e.g. conditional add (a.k.a. conditional relative jump), add-and-store and load-and-store (a.k.a. procedure call).

On the other hand, there are many operations that are needed for regular registers and which are useless for the PC, e.g. logical operations, shift/rotate, multiplication and division and others.

Because of this, encoding the PC as a regular register is pointless and wasteful of the instruction encoding space.

Moreover, when the ISA has an implicit stack pointer, which is also the only register that can be used as a stack pointer, like the x86 ISA, the set of operations that are used with the SP is a very small subset of the operations available for the regular registers, so encoding the SP as a regular register is also wasteful. Especially in 32-bit x86, where the number of architectural registers was very small, it would have been better if the SP would not have been encoded as a regular register, wasting a register number.

> The reason why the PC is not normally exposed as a regular register is that the set of operations needed for the PC is different than for the regular registers.

I'd add to that, that what you give is the reason it's /okay/ to expose the PC as a special register instead of a GPR. The reason that it's /important/ to is that the PC is accessed on every instruction fetch, so if it's part of a uniform register file, it basically eats up an entire read port of that register file. Register file size scaled badly with port count (much worse than it does with register count), so this ends up adding quite a bit of area. (You can hack around this by having a single dedicated read port for just the PC register, but then you're half way to an SPR.)

It does not make sense to dedicate full read port for reading PC. Just run a bus directly from the register cells, which is exactly how it is done in ARM7TDMI in question.
Sure, but then you're half way to a special purpose register. And then you get to add in the logic to arbitrate writes from the GPR ports with reads from the PC-dedicated port. At which point you have more hardware complexity than just a dedicated SPR.