@@ -316,6 +316,7 @@ void debug_step(int mode, uint32_t addr) {
316316 gui_debug_close ();
317317 debug .untilRet = true;
318318 debug .untilRetBase = cpu_address_mode (cpu .registers .stack [cpu .L ].hl , cpu .L );
319+ debug .untilRetIndex = debug .stackIndex ;
319320 break ;
320321 case DBG_BASIC_STEP_IN :
321322 case DBG_BASIC_STEP_NEXT :
@@ -335,6 +336,48 @@ void debug_clear_step(void) {
335336 debug .tempExec = debug .stepOut = ~0u ;
336337 debug .untilRet = false;
337338 debug .untilRetBase = 0 ;
339+ debug .untilRetIndex = 0 ;
340+ }
341+
342+ bool debug_until_ret_handle_indirect_jump (uint32_t target , uint32_t currentSp ) {
343+ /* stop if this JP(rr) is an actual return for a
344+ * recorded call frame, where target matches its retAddr and
345+ * SP has been restored to that frame's precall stack
346+ * value (or frame was detected popped) */
347+ uint32_t idx = debug .stackIndex ;
348+ uint32_t sz = debug .stackSize ;
349+ debug_stack_entry_t * hit = NULL ;
350+ uint32_t hit_idx = ~0u ;
351+
352+ while (sz -- ) {
353+ debug_stack_entry_t * entry = & debug .stack [idx ];
354+ const uint32_t this_idx = idx ;
355+ idx = (idx - 1 ) & DBG_STACK_MASK ;
356+ if (entry -> mode == cpu .L &&
357+ /* only consider frames above current SP baseline. target
358+ * must also match the frame's retAddr window */
359+ entry -> stack >= debug .untilRetBase &&
360+ (target - entry -> retAddr ) <= entry -> range ) {
361+ hit = entry ;
362+ hit_idx = this_idx ;
363+ break ;
364+ }
365+ }
366+
367+ /* break if we are returning from the same frame
368+ * where DBG_UNTIL_RET started */
369+ if (hit && hit_idx == debug .untilRetIndex &&
370+ (currentSp == hit -> stack || hit -> popped )) {
371+ const uint32_t len = 1 + (cpu .PREFIX != 0 );
372+ const uint32_t start = cpu_mask_mode (
373+ cpu .registers .PC - (len + (cpu .SUFFIX ? 1u : 0u )),
374+ cpu .ADL );
375+ REG_WRITE_EX (PC , cpu .registers .PC , start );
376+ debug_open (DBG_STEP , cpu .registers .PC );
377+ return true;
378+ }
379+
380+ return false;
338381}
339382
340383void debug_clear_basic_step (void ) {
0 commit comments