Visual walkthrough — Instruction-level semantics and exceptions
Step 1 — What "one instruction at a time" actually looks like
WHAT. Picture a factory conveyor belt. Each box on the belt is one instruction — a single command the CPU obeys, like "add these two numbers" or "load this value from memory". They enter on the left in program order (the order you wrote them) and are supposed to finish on the right, one after another.
WHY. Before we can talk about something going wrong, we must nail down what "going right" means. The CPU promises that the visible state — the values a programmer can read back — always looks as if the boxes were processed strictly left-to-right, fully, one box before the next begins. We call this the sequential execution model. It is the yardstick everything else is measured against.
PICTURE. Four boxes on the belt. "Program order" is the arrow pointing right.
Here
"Visible state looks as if boxes ran left-to-right" is the name for
Step 2 — Each box changes the state by a small rule
WHAT. Every box does at most four things: read some inputs, compute a result, write one output, and update the (pick the next box). We write this as a state-transition:
Term by term: is everything visible before the box; is the box's command; is the box-specific rule; is everything visible after.
WHY. If each box is just a rule that maps "state before" to "state after", then a whole program is those rules composed in order. That composition is the promise from Step 1, written in maths.
PICTURE. A box with an input slot (state flowing in) and an output slot (state flowing out), the little rule stamped on top.
Step 3 — The trouble: boxes are not really processed one at a time
WHAT. Real hardware is impatient. To go fast it works on many boxes at once (a pipeline) and may even finish a later box before an earlier one (out-of-order execution). So inside the machine, the belt is a blur — boxes overlap and even overtake each other.
WHY show this. Because it seems to break Step 1! If finishes its computation before , how can the visible state still look left-to-right? We must resolve this tension, and the resolution is the whole point of the page.
PICTURE. The same four boxes, now stacked in overlapping pipeline stages, with 's compute already done while is still working — an arrow showing "overtaking".
The trick that saves the promise
Step 4 — The rescue: compute freely, but commit strictly in order
WHAT. We split a box's life into two moments. Execute = do the arithmetic / touch the cache (may happen any time, any order). Commit (also called retire) = the instant the result is allowed to change the visible architectural state. The rule is:
WHY. The reader watching the visible state only ever sees commits, and commits march left-to-right. So the outside looks perfectly sequential even while the inside is chaos. The waiting-room (reorder buffer) holds finished results until it is their turn to commit.
PICTURE. Two lanes: a scrambled "executed" lane on top, and a tidy in-order "commit gate" at the bottom letting boxes through one at a time, oldest first.
Step 5 — Now something goes wrong: an exception on a box
WHAT. Suppose box is a load, LW R5, 0(R6), and the page it needs isn't in memory — a
page fault. This is detected during 's execution, before commits.
WHY here. An exception is an unexpected transfer of control away from the belt: the OS must step in. But the OS can only help if it is handed a clean machine. "Clean" is what we define next; this step just marks the guilty box.
PICTURE. The belt with flashing a red ⚡ fault marker, safely to its left, to its right.
at the moment of the fault
Step 6 — The clean stopping point: a precise exception
WHAT. The hardware now enforces a razor-sharp picture:
- Every box before (that is ) has fully committed — their results are visible.
- and every box after it () are squashed: their computed results are thrown away and never reach the visible state.
Term by term: the left side is what the OS sees; the right side is the tidy left-to-right state as if the belt had halted cleanly on the boundary between and .
WHY. This is what makes recovery possible. The page-fault handler can load the missing page and then say "run again" — and because changed nothing, re-running it is safe and correct. If some later box had already polluted a register, restarting would be impossible.
PICTURE. The belt cut by a clean vertical "commit boundary" line: green (committed) on the left, greyed-out squashed on the right, arrow pointing to the boundary labelled "clean state".
Step 7 — Which address does the handler return to? (fault vs trap)
WHAT. The EPC (Step 5) is chosen by the type of exception. Two cases:
- Fault (e.g. page fault): the box did not finish its meaning. Return to the same box.
- Trap (e.g.
syscall): the box did finish its meaning (it asked for a service on purpose). Return to the next box.
Term by term: the is one box-width, so "" literally means "the next box on the belt".
WHY. A fault says "try me again" — retry after the OS fixes the cause. A trap says "I did my job, move on" — re-running it would double the request. The entire difference between the two families is this one choice of return address.
PICTURE. Two little belts side by side: a fault belt with the return arrow curving back onto the same red box; a trap belt with the return arrow landing on the next box.
See System Calls and Privilege Levels for how a trap hands control to the OS, and Interrupts and I/O for the asynchronous cousin of exceptions.
Step 8 — Two exceptions in the same cycle: the oldest wins
WHAT. Suppose has a divide-by-zero and has a page fault, both spotted the same cycle. The hardware reports the exception of the oldest (earliest in program order) faulting box — here .
WHY. Precise semantics (Step 6) demands that everything before the reported fault has committed. In the tidy left-to-right world, comes before , so the belt should have "stopped" at already — 's fault shouldn't even have happened yet. Reporting keeps the fiction consistent.
PICTURE. Belt with two ⚡ markers on (magenta) and (orange); a crown on labelled "reported — oldest wins", greyed and squashed.
The one-picture summary
Everything above in a single frame: boxes flow in on the left (program order); they execute in a scrambled inner lane; a commit gate serialises them; box faults; a clean boundary freezes as committed and squashes ; the handler is entered at the vector with EPC pointing back to (fault) or forward to (trap).
Recall Feynman retelling — say it in plain words
Imagine a kitchen. Tickets (instructions) arrive in order. Cooks prepare dishes in whatever order is fastest, but a single serving hatch sends dishes out strictly in ticket order — so diners always see an orderly meal even though the kitchen is chaos. One day a dish can't be finished because an ingredient is missing (a page fault). The rule: everything before that ticket has already been served, and that ticket plus everything after it is thrown in the bin — untouched, as if never started. The manager (OS) is called to the front door (vector) and handed a note (EPC) saying where to resume: for a missing ingredient we retry the same dish (fault ⇒ same address); for a customer who asked for something and got it, we move to the next dish (trap ⇒ address + 4). If two dishes fail at once, we blame the one with the earlier ticket, because in the orderly world its failure happens first. That single hatch — commit in program order — is the whole trick that makes exceptions precise and programs restartable.
Recall Quick self-test
Fault returns to which address? ::: the same faulting instruction ( its own address)
Trap returns to which address? ::: the next instruction ( address )
Why can be safely retried after a page fault on LW R5,...? ::: the load never committed, so is unchanged
What single mechanism makes exceptions precise? ::: in-order commit/retire, even under out-of-order execution
Two same-cycle faults — which is reported? ::: the oldest in program order
Prev / context: this deep dive expands the precise exception result of the parent topic note, and rests on the idea that the ISA as a Hardware–Software Contract guarantees the sequential model regardless of implementation.