2
\$\begingroup\$

I have a question regarding a PC register (IP in x86 lingo). In most architectures it is updated during an execution stage and thus stores an address of a next instruction to be fetched. It seemed clear to me until I started to reason about a pipelined architecture. For example, imagine the following classic RISC pipeline with 5 stages (Fetch, Decode, Execute, Memory access, Write back) which is filled with the following instructions (designated as "a", "b", "c", "d"):

F D E M W
c b a - -

0x12 call [0x100] ; a
0x14 mov ax, 10   ; b
0x16 add ax, 2    ; c
0x18 nop          ; d <- IP

By the time an instruction "a" reaches the E (Execute) stage in the pipeline, it is already full with subsequent instructions and IP points to an instruction at address 0x18 (the next one to fetch). When "call [0x100]" executes, it saves the contents of the IP (a return address) on the stack. But it's obviously not the address of the instruction following "call [0x100]"! So, as we return from the CALL, we effectively jump over 2 instructions since pipeline is flushed during the CALL execution!

Which means that:

  • There is another hidden register storing the address of the instructions being executed and it's stored on the stack instead of IP
  • It doesn't work this way
  • I am missing something :)
\$\endgroup\$
1
  • \$\begingroup\$ For part of the answer, search for "MIPS branch delay slot". (generally regarded by later designers as a Really Bad Idea...) \$\endgroup\$
    – user16324
    Feb 5, 2016 at 11:13

1 Answer 1

1
\$\begingroup\$

Reading through the reference manual on the X86 assembly... https://courses.cs.washington.edu/courses/cse548/05wi/files/x86-reference-long.pdf

you will find this... "The call instruction calls near procedures using a full pointer. call causes the procedure named in the operand to be executed. When the called procedure completes, execution flow resumes at the instruction following the call instruction (see the return instruction)"

This tells you that the call has to return first. This means that when run, noop instructions will be placed after it until it returns.

Immediately after this is called, the Control block will determine it is a call, which is a command requiring action by the hazard detection unit. This unit fires off what is essentially a call interrupt. So immediately upon seeing this instruction this interrupt occurs to call noops and will not allow PC to increment.

\$\endgroup\$
8
  • \$\begingroup\$ What you described is clear to me, but my question is different. Unless pipeline is involved, the mechanism of saving/restoring program counter is straightforward - when CALL executes, next instruction's address gets pushed on the stack stack and gets popped into program counter upon return. I'm, however, curious how the same is done in pipelined architectures since program counter will point several instructions ahead by the time CALL gets to the Execute stage. How this is addressed is what interests me. \$\endgroup\$
    – raiks
    Feb 5, 2016 at 19:09
  • \$\begingroup\$ @raiks Gotcha. Your're overthinking it :) I'll edit. \$\endgroup\$
    – mcmiln
    Feb 5, 2016 at 19:37
  • \$\begingroup\$ So you are basically saying that an early CALL detection makes a CPU insert bubbles in the pipeline preventing a program counter from being incremented until CALL executes, right? This scheme would be viable in my example only if detection was done in the very first stage (Fetch). Then a program counter would still point to the instruction following CALL and would retain its value up to the point where CALL reached Execute stage. If I got you right, it's interesting how early detection is accomplished before Decode stage, especially in very long pipelines where each stage is very specialized. \$\endgroup\$
    – raiks
    Feb 5, 2016 at 21:05
  • \$\begingroup\$ @raiks Exactly. This early detection is crucial once we step into a world of peripherals and look past the processor. The processor must have the ability to be interrupted at any point and put in noops. The call has a spot in the ISR table which allows it to follow this early detection scheme. MIPS does the same thing with syscall. \$\endgroup\$
    – mcmiln
    Feb 5, 2016 at 21:13
  • \$\begingroup\$ @raiks To comment on the very long specialize processors, this is broken up much like and larger system. You pick and choose what needs to interrupt where and in some architectures you can find start signals which must latch to the next register but get flushed by the same principle. \$\endgroup\$
    – mcmiln
    Feb 5, 2016 at 21:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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