|
| 1 | +# `halt` |
| 2 | + |
| 3 | +`halt` is an instruction that pauses the CPU (during which less power is |
| 4 | +consumed) when executed. The CPU wakes up as soon as an interrupt is pending, |
| 5 | +that is, when the bitwise AND of [`IE`](<#FFFF - IE - Interrupt Enable (R/W)>) |
| 6 | +and [`IF`](<#FF0F - IF - Interrupt Flag (R/W)>) is non-zero. |
| 7 | + |
| 8 | +Most commonly, [`IME`](<#IME - Interrupt Master Enable Flag (Write Only)>) is |
| 9 | +set. In this case, the CPU simply wakes up, and before executing the instruction |
| 10 | +after the `halt`, the [interrupt handler is called](<#Interrupt Handling>) |
| 11 | +normally. |
| 12 | + |
| 13 | +If `IME` is *not* set, there are two distinct cases, depending on whether an |
| 14 | +interrupt is pending as the `halt` instruction is first executed. |
| 15 | + |
| 16 | +- If no interrupt is pending, `halt` executes as normal, and the CPU resumes |
| 17 | + regular execution as soon as an interrupt becomes pending. However, since |
| 18 | + `IME`=0, the interrupt is not handled. |
| 19 | +- If an interrupt is pending, `halt` immediately exits, as expected, however |
| 20 | + the "`halt` bug", explained below, is triggered. |
| 21 | + |
| 22 | +## `halt` bug |
| 23 | + |
| 24 | +Under some circumstances, `pc` fails to be normally incremented. |
| 25 | + |
| 26 | +The most typical trigger, `halt` with `IME`=0 and `[IE] & [IF] != 0`, causes |
| 27 | +the byte after the `halt` to be read twice. |
| 28 | + |
| 29 | +The behavior is different when `ei` (whose effect is typically delayed by one |
| 30 | +instruction) is followed immediately by a `halt`, and an interrupt is pending |
| 31 | +as the `halt` is executed. The interrupt is serviced and the handler called, |
| 32 | +but the interrupt returns to the `halt`, which is executed again, and thus |
| 33 | +waits for another interrupt. |
| 34 | +([Source](https://github.com/LIJI32/SameSuite/blob/master/interrupt/ei_delay_halt.asm)) |
0 commit comments