| 49 | } |
| 50 | |
| 51 | void debug_open(int reason, uint32_t data) { |
| 52 | if ((cpu_check_signals() & CPU_SIGNAL_EXIT) || debug_is_open()) { |
| 53 | return; |
| 54 | } |
| 55 | |
| 56 | /* fixup reason for basic debugger */ |
| 57 | if (debug.basicMode) { |
| 58 | if (reason == DBG_WATCHPOINT_WRITE) { |
| 59 | if (data == DBG_BASIC_CURPC+2) { |
| 60 | if (debug.basicDeferPC) { |
| 61 | return; |
| 62 | } |
| 63 | reason = DBG_BASIC_CURPC_WRITE; |
| 64 | } else if (data == DBG_BASIC_BEGPC+2) { |
| 65 | /* in the case where the program is returning from a subprogram, the updates |
| 66 | to the pc haven't finished yet on endpc or program name, so defer to the |
| 67 | program name write */ |
| 68 | debug.basicDeferPC = true; |
| 69 | reason = DBG_BASIC_BEGPC_WRITE; |
| 70 | } else if (data == DBG_BASIC_ENDPC+2) { |
| 71 | debug.basicDeferPC = false; |
| 72 | reason = DBG_BASIC_ENDPC_WRITE; |
| 73 | } else if (data == DBG_BASIC_BASIC_PROG+8) { |
| 74 | debug.basicDeferPC = false; |
| 75 | reason = DBG_BASIC_BASIC_PROG_WRITE; |
| 76 | } |
| 77 | } |
| 78 | if (reason == DBG_WATCHPOINT_READ) { |
| 79 | if (data == DBG_BASIC_SYSHOOKFLAG2) { |
| 80 | debug.basicDeferPC = false; |
| 81 | /* verify basic program execution */ |
| 82 | if ((mem_peek_byte(DBG_BASIC_NEWDISPF) & DBG_BASIC_PROGEXECUTING_BIT) && |
| 83 | (mem_peek_byte(DBG_BASIC_CMDFLAGS) & DBG_BASIC_CMDEXEC_BIT)) { |
| 84 | |
| 85 | /* check current pc for instruction "bit 1,(iy+$36)" */ |
| 86 | static const uint8_t instr[] = { 0xFD, 0xCB, 0x36, 0x4E }; |
| 87 | const void *ptr = phys_mem_ptr(cpu.registers.PC - sizeof(instr), sizeof(instr)); |
| 88 | if(ptr && !memcmp(ptr, instr, sizeof(instr))) { |
| 89 | debug.basicLastHookPC = cpu.registers.PC; |
| 90 | reason = DBG_BASIC_CURPC_WRITE; |
| 91 | } |
| 92 | } else { |
| 93 | return; |
| 94 | } |
| 95 | } |
| 96 | } |
| 97 | if (debug.stepBasic && (reason == DBG_BASIC_CURPC_WRITE || reason == DBG_BASIC_BASIC_PROG_WRITE)) { |
| 98 | uint32_t offset = mem_peek_long(DBG_BASIC_CURPC) - mem_peek_long(DBG_BASIC_BEGPC); |
| 99 | /* Allow self-looping with Step In, but only if the hook PC is the same as what was stepped from */ |
| 100 | bool inRange = offset >= (uint32_t)debug.stepBasicBegin + (!debug.stepBasicNext && debug.basicLastHookPC == debug.stepBasicFromPC) && |
| 101 | offset <= (uint32_t)debug.stepBasicEnd && |
| 102 | !strncmp(debug.stepBasicPrgm, phys_mem_ptr(DBG_BASIC_BASIC_PROG, 9), 9); |
| 103 | if (!inRange ^ debug.stepBasicNext) { |
| 104 | reason = DBG_BASIC_STEP; |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | if (!debug.basicModeLive && reason > DBG_BASIC_LIVE_START && reason < DBG_BASIC_LIVE_END) { |
no test coverage detected