2
\$\begingroup\$

While designing my own 16-bit CPU I wonder how the register-register XCHG instruction is executed internally. From computer science I know the DLX which doesn't provide XCHG and therefore doesn't need to access two registers in write-back (would this even be possible?), but only the destination register. I guess this isn't done in one cycle, right?

Thx in advance

\$\endgroup\$
  • \$\begingroup\$ Of course accessing two registers in write-back is possible, if you have a register file with two write ports. \$\endgroup\$ – immibis Jan 30 '15 at 8:43
  • \$\begingroup\$ Hm, ok, when I would take a second decoder it would work. But is this the normal approach? \$\endgroup\$ – Benjoyo Jan 30 '15 at 9:16
  • \$\begingroup\$ Which architectures have XCHG besides x86 (and x64)? \$\endgroup\$ – immibis Jan 30 '15 at 9:20
  • \$\begingroup\$ Well, ARM has SWP \$\endgroup\$ – Benjoyo Jan 30 '15 at 9:27
  • 1
    \$\begingroup\$ To expand on @immibis: why does your architecture need XCHG? x86 has it because the first implementation was severely register-starved and many instructions could only address specific registers, so there was a need to move values between registers without having to spill to the stack. If your CPU has more registers than original x86 or can use arbitrary registers with operations, there is no use for an XCHG instruction. \$\endgroup\$ – Simon Richter May 3 '18 at 11:03
1
\$\begingroup\$

You have a couple of options.

You can add the extra hardware in the data path to allow it to occur in one cycle. This has difficulties in a pipelining architecture because a dual port register file is often used for simultaneous reads and writes for the different stages. This adds the need for a second write port. Without this, there really is not a way to prevent a bubble in the pipeline from eventually having to occur.

A generally better option is to simply have a multicycle instruction. The important thing here is to make sure you prevent any other operation such as interrupts or other bus masters (in the case of a memory swap) from make this appear non-atomic.

The multicycle instruction option is what is generally done. For example, the ARM SWP and the XCHG instructions are multicycle.

\$\endgroup\$
  • \$\begingroup\$ Thank you. But is this done by the assembler via two instructions or is it one instruction that locks the PC for one instruction cycle and therefore can do two "rounds" through the circuit? \$\endgroup\$ – Benjoyo Jan 30 '15 at 15:43
  • \$\begingroup\$ A multicycle instruction is one opcode that takes more than one CPU clock cycle to execute; roughly "multiple rounds", yes. Lots of instructions are multicycle. \$\endgroup\$ – pjc50 Jan 30 '15 at 16:08
  • \$\begingroup\$ For a pipelined processor, how about having a special form of some instructions which would disable both interrupts and register forwarding for the next cycle, so something like dmov r0,r1 ["delayed move"] would cause r1 to be stored in r0 but the store wouldn't take place until after the next instruction's operand fetches [which would receive data from registers, rather than from forwarding circuitry]. A delayed-move and delayed-load would allow easy two-instruction swaps between two registers, or between a register and memory. \$\endgroup\$ – supercat Jan 30 '15 at 17:57
  • 1
    \$\begingroup\$ Alternatively, if one didn't mind having to use some extra context-save/restore hardware for interrupt handling, I wonder how well it would work to have a processor with a fixed pipeline delay but have one particular "register number" decoded to enable a bypass stage rather than enabling a bypass when one instruction's destination is used as the next instruction's source? If there were 15 "real" registers R0-R14, an instruction like "ADD R0,R1,R2" would effectively store R1+r2 to "R15" immediately, and to R0 after the following instruction's operand fetch. \$\endgroup\$ – supercat Jan 30 '15 at 18:02
  • \$\begingroup\$ Note that this is a non-restartable multicycle operation, unless "load multiple" or "store multiple", so interrupts cannot be taken in the middle of the instruction, leading to jitter in interrupt entry time, which is bad for realtime applications. \$\endgroup\$ – Simon Richter May 3 '18 at 10:58
0
\$\begingroup\$

Another option is to mess with the register addressing, I suspect this is how the Z80 EXX opcode swaps register banks in 4 cycles. it's possibly also how EX DE,HL swaps two register pairs registers in 4 cycles on the same micro. the same cycle count it takes to copy one 8-bit register to another.

\$\endgroup\$
0
\$\begingroup\$

This instruction is most likely implemented using register renaming. With register renaming, the register contents are assigned to registers names with tags. This makes swapping registers very easy - just swap the tags. No need for multiple register writes in the same cycle.

This is how the Z80 implemented the EX instruction. See: http://www.righto.com/2014/10/how-z80s-registers-are-implemented-down.html

Swapping registers through register renaming

The Z80 has several instructions to swap registers or register sets. The EX DE, HL instruction exchanges the DE and HL registers. The EX AF, AF' instruction exchanges the AF and AF' registers. The EXX instruction exchanges the BC, DE, and HL registers with the BC', DE', and HL' registers. These instructions complete very quickly, which raises the question of how multiple 16-bit register values can move around the chip at once.

It turns out that these instructions don't move anything. They just toggle a bit that renames the appropriate registers. For example, consider exchanging the DE and HL registers. If the DE/HL bit is set, an instruction acting on DE uses the first register and an instruction acting on HL uses the second register. If the bit is cleared, a DE instruction uses the second register and a HL instruction uses the first register. Thus, from the programmer's perspective, it looks like the values in the registers have been swapped, but in fact just the meanings/names/labels of the registers have been swapped. Likewise, a bit selects between AF and AF', and a bit selects between BC, DE, HL and the alternates. In all, there are four registers that can be used for DE or HL; physically there aren't separate DE and HL registers.

The hardware to implement register renaming is interesting, using four toggle flip flops.[7] These flip flops are toggled by the appropriate EX and EXX instructions. One flip flop handles AF/AF'. The second flip flop handles BC/DE/HL vs BC'/DE'/HL'. The last two flip flops handle DE vs HL and DE' vs HL'. Note that two flip flops are required since DE and HL can be swapped independently in either register bank.

\$\endgroup\$
  • \$\begingroup\$ This still involves a swap of two tags, which must look much like registers internally, albeit narrower and not exposed to the programming model. \$\endgroup\$ – Russell Borogove May 3 '18 at 14:44

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.