3

Suppose an external interrupt request is made to 8086. Processor will handle the interrupt after completing the current instruction being executed (if any). Before handling of the interrupt, the state of the program will also be saved (PSW flag, registers etc.) by pushing data onto the stack segment.

Now, most tutorials/documents describe that instruction pointer is also pushed onto the stack segment, which is okay because it was pointing to the next byte of instruction in the code segment (just before interrupt request was made).

But what happens to the instruction queue? Is it also pushed onto the stack segment when an interrupt request is being handled? Or is it that its contents are cleared to zero? In this case, shouldn't the instruction pointer be decremented so that it can be made to point back to the previous instructions in the code segment (after interrupt has been served)?

IP pushed onto the stack

Here, After interrupt request actually means After interrupt request has been served. What this diagram shows is that before interrupt request came, the instructions were cached, with IP pointing to the address of the next byte of instruction in the CS memory segment. To serve the interrupt request, the contents of registers (incl. IP and flags) are pushed onto the stack segment. After request is served, the previous contents are loaded back - with IP still pointing to the location of the 7th byte (of instruction), with queue (cache) being empty. This is what my doubt is. Is IP decremented to point back to i1? Secondly, do we need to manually handle the IP (like, push it onto the stack upon interrupt) or does the interrupt-service-routine handles this for us? Please, any help is appreciated, thanks!


Note: Instruction Queue - The 8086 architecture has a six-byte prefetch instruction pipeline. As the Execution Unit is executing the current instruction, the bus interface unit reads up to six bytes of opcodes in advance from the memory.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Patt Mehta
  • 4,110
  • 1
  • 23
  • 47
  • (Speculation, not fact) The pipeline mechanism is an implementation detail, not something that's exposed by the ISA. – Oliver Charlesworth May 23 '14 at 21:16
  • 1
    As @OliCharlesworth says. Building the "instruction queue" (by which I assume you mean the order of the next to process instructions) happens on the hardware level (using out of execution engine etc); so when the order is changed because of an interrupt, any adjustments to it are also hardware-handled. As a user, you generally have no idea what's really next in the pipeline, so it would be hard/impossible to get involved. – gnometorule May 23 '14 at 21:21
  • 4
    Instruction queue is invalidated (and all look-ahead executed instructions are rolled back) when interrupt occurs. – Egor Skriptunoff May 23 '14 at 22:04
  • 1
    Maybe chapter 6 of this PDF will help you: http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.html – Alexis Wilke May 24 '14 at 06:00
  • @AlexisWilke Thanks! :) I am going through it – Patt Mehta May 24 '14 at 06:03
  • @OliCharlesworth I have modified the question. Thanks in advance! – Patt Mehta May 24 '14 at 08:29
  • @EgorSkriptunoff I have modified the question. If possible, please suggest any changes. Thanks! – Patt Mehta May 24 '14 at 08:30
  • @AlexisWilke I have modified the question. Please help :) thanks! – Patt Mehta May 24 '14 at 08:31
  • @GLES: assembler is *not* at the hardware level on a modern x86... – Oliver Charlesworth May 24 '14 at 08:33
  • I agree. But I have made my question more presentable :) I am expecting an authoritative answer to learn from. Thanks in advance! – Patt Mehta May 24 '14 at 08:34
  • You say the 8086 has a 6 byte prefetch "instruction pipeline" (bad term IMHO). There may have been one with that property, but that's a detail of the implementation and there's no good reason to believe this is a property of all 8086s. For modern CPUs, the way the instruction prefetch is implemented is simply dependent on the cleverness of the designers. About all you can reasonably predict is there will be some prefetch scheme, and it will be difficult for you to detect its presence in your application program except for impact on performance and funny rules about self-modifying code. – Ira Baxter May 24 '14 at 08:59
  • I read about `self-modifying codes` today :) indeed they are funny :-) – Patt Mehta May 24 '14 at 09:03
  • You can add this in your answer - "but that's a detail of the implementation and there's no good reason to believe this is a property of all 8086s". i will mark it as the answer. also please answer the 2nd question - `Secondly, do we need to manually handle the IP (like, push it onto the stack upon interrupt) or does the interrupt-service-routine handles this for us? ` – Patt Mehta May 24 '14 at 09:05
  • For modern x86, see [When an interrupt occurs, what happens to instructions in the pipeline?](https://stackoverflow.com/q/8902132). The interrupt semantics are defined on paper in Intel's (and AMD's) manuals; speculative prefetch is transparent except for self-modifying code (in old CPUs); interrupts rewind to a consistent state. – Peter Cordes Dec 23 '22 at 07:32

3 Answers3

3

You aren't very clear about what you mean by "instruction queue".

One meaning might be "prefetched instructions". In practice, the processor has speculatively read-ahead in the instruction stream from the point of the last completed instruction, following branches or not based on various types of branch prediction algorithms. Since these are reads, if the processor decides to abandon the current instruction "stream" for another (e.g., the interrupt routine), it simply ignores its read-ahead.

Another meaning might be "instructions partly executed (in flight/in the 'pipeline')", which frequently happens with super-scalar CPUs. In the case of an asynchronous interrupt, the processor must complete those that have affected the visible state of the system (e.g, has committed a write to a register or memory), and may or may not complete other instructions depending on the whims of the specific processor's designers. In the case of a synchronous trap, the processor has to complete instructions that affected state, but simply abandons the rest (OP's phrase was "zeros the queue" which has the right concept but the wrong phrasing).

[Adding at OP's request a comment I made]: You say the 8086 has a 6 byte prefetch "instruction pipeline" (bad term IMHO). There may have been one with that property, but that's a detail of the implementation and there's no good reason to believe this is a property of all 8086s. For modern CPUs, the way the instruction prefetch is implemented is simply dependent on the cleverness of the designers. About all you can reasonably predict is there will be some prefetch scheme, and it will be difficult for you to detect its presence in your application program except for impact on performance and funny rules about self-modifying code.

[Answering OP's second question]: Secondly, do we need to manually handle the IP (like, push it onto the stack upon interrupt) or does the interrupt-service-routine handles this for us?

For any type of trap or interrupt, it is sufficient to store the architecturally defined state (the "registers", PC, etc.). For many processors, it is sufficient for the hardware to store a critical subset of the architectural state, and let the interrupt routine store (and eventually restore) the rest. So the responsibility for storing the entire state is split between hardware and software (to save implementation effort in the hardware).

For the x86 family, typically the instruction pointer (IP) and the flags register are pushed by the hardware onto the current stack, control transfers to the interrupt, and the interrupt routine has instructions that store the rest of the registers typically in an operating-system defined data structure often called a "context block". The interrupt routine does its job, and either returns control to the application by reloading the registers, and then reloading the IP and flags by using a special IRET instruction, or it transfers control to an OS scheduler which chooses to run some other activity, eventually using the saved context block content to restart the application.

A really fast interrupt routine might save just enough registers to do its critical work, and then restore those registers before returning to the interruptee.

Ira Baxter
  • 93,541
  • 22
  • 172
  • 341
  • Nice answer :) yes, `instruction queue` is the queue that stores the `pre-fetched instructions` from the code segment. – Patt Mehta May 24 '14 at 08:50
  • The 6-byte instruction queue is part of the 8086 datasheet, so it's a property of all 8086s. It's not just an implementation detail. – Ken Shirriff Dec 23 '22 at 23:58
2

The 8086 processor has a 6-byte instruction prefetch queue. To answer the question, when an interrupt happens, the program counter (instruction pointer) is pushed on the stack and the queue is discarded. The tricky part is that the internal program counter points to the next byte to be prefetched, which is different from the next byte to execute. The solution is that the program counter value is corrected by subtracting the queue size, using a small constant table and the addressing adder. The same correction takes place for subroutine calls and relative jumps since they also require the real PC value.

To quote from the 8086 patent column 8 line 27:

PC is not a real or true program counter in that it does not, nor does any other register within CPU, maintain the actual execution point at any time. PC actually points to the next byte to be input into queue. The real program counter is calculated by instruction whenever a relative jump or call is required by subtracting the number of accessed instructions still remaining unused in queue from PC.

Ken Shirriff
  • 1,654
  • 16
  • 20
  • Related: the 8088 has a 4-byte prefetch queue, 4 bus-widths of data, vs. 6 bytes (3 bus-widths) in 8086. ([how many instructions can be stored in instruction queue of 8086 microprocessor?](https://stackoverflow.com/q/48437881)) – Peter Cordes Dec 23 '22 at 03:00
  • 1
    Ah cool, that "no other register within [the] CPU" confirms that's why `#DE` on 8086 points after the `div` instruction, vs. at the faulting instruction on later CPU. Also mostly explains why `rep cs movsb` is interrupted with IP pointing at the last prefix, so it doesn't resume properly. Because it doesn't keep track of where it started decoding prefixes, and just has to backtrack one prefix which happens to work for `rep movsb` but not with a segment override. That's what I'd guessed in [x86 division exception-return address](https://stackoverflow.com/q/71070990) – Peter Cordes Dec 23 '22 at 05:30
-1
  • When an interrupt or trap occurs, the CPU synchronizes with the cache by stalling until all pending cache operations are either complete or preempted.
  • If a cache load was already in progress it completes, but other operations waiting in the queue are preempted.
  • The queue is stored as part of the cache internal state so when the context is restored the preempted operations are re-queued.
Patt Mehta
  • 4,110
  • 1
  • 23
  • 47
  • Which document spells that out? I can see in `Volume 3A -- System Programming Guide, Part 1` that they talk a lot about interrupts and exceptions, but nothing about how the cache is being handled. Plus, I do not recall ever seeing something saying that the CPU state would be restored, although now that we can save the state between threads, I suppose that can be applied to interrupts. Also, your answer does not make any difference between processor brands or generations... – Alexis Wilke May 24 '14 at 05:58
  • No processor design I have ever seen stores anything resembling an "instruction queue" as "part of the cache internal state". That might be technically possible, but it isn't worth the transistors or complexity for the payoff, if there was one. It is sufficient to store the *architecturally* defined state (the "registers", PC, etc.). For many processors, it is sufficient to store a critical subset of the architectural state (e.g, PC and flags), and let the interrupt routine store (and eventually restore) the rest. – Ira Baxter May 24 '14 at 08:50
  • http://en.wikipedia.org/wiki/Prefetch_input_queue#Instruction_queue The 8086 architecture has a six-byte prefetch instruction pipeline. As the Execution Unit is executing the current instruction, the bus interface unit reads up to six bytes of opcodes in advance from the memory. – Patt Mehta May 24 '14 at 08:52
  • `pre-fetch instruction pipeline` and `pre-fetch instruction queue` on 8086 mean the same thing - they cache the instructions (by loading them from the CS memory segment) by looking-ahead into the CS memory segment (asynchronously) for keeping the execution-unit busy :) – Patt Mehta May 24 '14 at 09:00
  • To clarify my answer, I distinguish the "processor internal state" (which often has some kind of instruction prefetch data), and the "cache (internal? your term) state" which I think of as representing an image of the *memory* state, and which generally survives (well, with continuous updating) transfers of control by the processor. – Ira Baxter May 24 '14 at 09:05
  • @IraBaxter Thanks so much for all your time :) – Patt Mehta May 24 '14 at 09:15
  • that's what i wanted to read - " it is sufficient to store the architecturally defined state" - thanks again :) that is called an authoritative answer :D for someone who is going to give his MP exam one day after asking this :) – Patt Mehta May 24 '14 at 09:19
  • by the way, this article confused the hell out of me - http://www.viewdocsonline.com/document/uetqrq - see the 4th point – Patt Mehta May 24 '14 at 09:20
  • I suspect that this answer is mixing up 8086 and x86. I'm examining the 8086 prefetch hardware in detail and nothing in this answer makes sense. – Ken Shirriff Dec 23 '22 at 00:57
  • 8086 doesn't have cache. In modern x86, interrupts aren't *serializing*. `iret` is serializing, but the actual interrupt itself does *not* wait for the store buffer to drain before starting to execute code from the interrupt handler. For modern x86, see Andy Glew's answer on [When an interrupt occurs, what happens to instructions in the pipeline?](https://stackoverflow.com/q/8902132) - he was an architect on Pentium Pro. – Peter Cordes Dec 23 '22 at 07:30