|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Wait-for-interrupt idle-spin detector (see emu_exc.h). More...
Go to the source code of this file.
Functions | |
| static RA8_INTERNAL bool | internal_idle_back_edge (uc_engine *uc, uint32_t at, uint16_t hw, uint32_t aligned, bool *done) |
Does the halfword at at close a tight idle loop around aligned? | |
| bool | idle_spin_at (uc_engine *uc, uint32_t pc) |
True if pc sits in a wait-for-interrupt spin (the core is idle). | |
Wait-for-interrupt idle-spin detector (see emu_exc.h).
Decides whether the guest PC is parked in a wait-for-interrupt spin so the run loop can cap the idle chunk's instruction budget instead of burning a full chunk on a loop that cannot make progress until an interrupt arrives. Pure Thumb instruction decoding over a read-only view of guest memory: it recognises the one-instruction forms (b ., wfi) directly and otherwise walks forward to a backward b.n that brackets the PC, requiring a wait signature inside the bracketed body so a tight busy loop is not mistaken for an idle one.
Split out of emu_exc.c: the detector shares none of the exception engine's state, and both translation units are clearer for the separation.
Definition in file emu_idle.c.
| bool idle_spin_at | ( | uc_engine * | uc, |
| uint32_t | pc ) |
True if pc sits in a wait-for-interrupt spin (the core is idle).
Reports whether the core at pc is parked in a loop that can only make progress once an interrupt arrives – genuine idle, where the next thing that can happen is the periodic SysTick. Two cases are recognised:
pc is itself a halt: b . (0xE7FE, branch-to-self) or wfi (0xBF30).pc is ENCLOSED by a wait-for-interrupt poll loop: scanning forward a few halfwords finds an unconditional backward b.n (the loop back-edge) whose target is at or before pc (so the loop wraps around pc), and the loop body holds a wfi or a cpsie i – the "re-enable interrupts
and poll" idiom ThreadX's __tx_ts_wait uses (cpsid/ldr/str/cbnz/cpsie/ b .-N, spinning on execute_ptr until a tick makes a thread runnable).The enclosing-loop test is deliberately tight: it requires the back-edge to bracket pc, so STRAIGHT-LINE code is never matched even when it sits in memory next to an idle loop (an ISR returns via bx lr, not a backward branch over itself – matching a nearby opcode would wrongly truncate it). A compute/busy loop is also excluded: it exits on a conditional branch and never re-enables interrupts mid-loop, so it carries no wfi/cpsie wait. The run loop uses this to cap the idle chunk's budget to k_idle_spin_insns instead of spinning a full k_run_chunk_insns to reach the same already-armed tick. Tick COUNT is unchanged; only idle wall-time is skipped.
| [in,out] | uc | Unicorn engine (instructions are read from its memory). |
| [in] | pc | Program counter to inspect (Thumb bit ignored). |
pc is on, or enclosed by, a wait-for-interrupt idle loop.uc has the code region containing pc mapped. pc is halfword-aligned once the Thumb bit is cleared. uc is unchanged (a read-only probe). Definition at line 120 of file emu_idle.c.
References emu_mem_read(), internal_idle_back_edge(), k_idle_scan_fwd, k_op_branch_self, k_op_wfi, and k_thumb_hw_bytes.
Referenced by internal_run_inner_budget().
|
static |
Does the halfword at at close a tight idle loop around aligned?
Decodes an unconditional Thumb b.n and requires three things of it: the branch goes backwards, its target brackets aligned within k_idle_loop_max bytes, and the bracketed body contains a wait signature (cpsie i or wfi). A tight backward loop with no wait is a busy loop, not an idle one, and must not be reported as idle.
| [in] | uc | Engine to read instruction memory from. |
| [in] | at | Address of the candidate branch halfword. |
| [in] | hw | The halfword already read at at. |
| [in] | aligned | The PC under test, halfword-aligned. |
| [out] | done | Set true when the answer is final either way. |
at closes an idle loop around aligned.uc and done are non-NULL. hw is the halfword actually stored at at. | true | The idle back edge condition holds or completed successfully; false otherwise. |
Definition at line 54 of file emu_idle.c.
References emu_mem_read(), k_bn_imm_sext_shl, k_bn_imm_sext_shr, k_idle_loop_max, k_op_bn_base, k_op_bn_imm, k_op_bn_mask, k_op_cpsie_i, k_op_wfi, k_thumb2_insn_bytes, and k_thumb_hw_bytes.
Referenced by idle_spin_at().