diff --git a/src/libsys/boards/denano/board.c b/src/libsys/boards/denano/board.c index 861e72e..c417bff 100644 --- a/src/libsys/boards/denano/board.c +++ b/src/libsys/boards/denano/board.c @@ -5,8 +5,8 @@ */ #include - #include "board.h" +#include "../../regdef.h" extern uart_if_t uart_if[]; @@ -26,6 +26,8 @@ con_if_t con_if = con_if_entry, ARRAYSIZE(con_if_entry) }; +void dbg_uart_setup(); + void board_init(void) { uint32_t volatile *pITIM_ctrl = (uint32_t*)SYS_ITIM_CTRL; @@ -33,18 +35,53 @@ void board_init(void) // Disable timers *pITIM_ctrl = 0; - // Initialzie syscall support + // Setup syscall support syscalls_init(); - // Initialzie interrupt support - interrupt_init(); + // Setup Uart ISR + dbg_uart_setup(); - // Initalize debugger + // Setup debugger dbg_init(); + // Setup interrupt support + interrupt_init(); + // Do some initializations here } +extern void dbg_handler(struct xcptcontext * xcp); +void dbg_uart_isr(struct xcptcontext *xcp); +void dbg_uart_setup() +{ + uart_if_t *pUart = (uart_if_t*)con_getInstanceByName("UART-1"); + + *pUart->pCTRL = SYS_UART_BIT_RX_INTEN; + interrupt_register(SYS_INT_UART1, dbg_uart_isr); + interrupt_enable(SYS_INT_UART1); +} + +void dbg_uart_isr(struct xcptcontext *xcp) +{ + uart_if_t *pUart = (uart_if_t*)con_getInstanceByName("UART-1"); + + if(SYS_UART_BIT_RX_AVAIL & *pUart->pCTRL) + { + char c = *pUart->pDATA; + if (c == 3) + { + // Disable UART interrupt + // to prevent consuming uart data in ISR during single step + // Interrupts mask bits are recovered on return from exception + //interrupt_disable(SYS_INT_UART1); + //uint32_t im = 1 << SYS_INT_UART1; + //xcp->sr &= ~(SR_MASK_IM & (im << 8)); + //*pUart->pCTRL &= ~SYS_UART_BIT_RX_INTEN; + dbg_handler(xcp); + } + } +} + void dbg_putchar(char c) { writechar(4, c); diff --git a/src/libsys/kernel.S b/src/libsys/kernel.S index d4215fe..de78847 100644 --- a/src/libsys/kernel.S +++ b/src/libsys/kernel.S @@ -15,7 +15,8 @@ LEAF(_xcpt_handler) */ /* allocate exception stack frame (on 8-byte boundary) */ - subu k1, sp, XCP_SIZE + li k1, XCP_SIZE + subu k1, sp, k1 srl k1, 3 /* shift right/left -> alligned on boundary */ sll k1, 3 diff --git a/src/libsys/libsys.c b/src/libsys/libsys.c index 05217c9..92c844b 100644 --- a/src/libsys/libsys.c +++ b/src/libsys/libsys.c @@ -33,6 +33,7 @@ void exit_critical() void _exit (int exitcode) { + sputs("\n\rexit\n\r"); fflush(stdout); fflush(stderr); while(1); diff --git a/src/libsys/mips_dbg.c b/src/libsys/mips_dbg.c index 8073f6c..c7be2f6 100644 --- a/src/libsys/mips_dbg.c +++ b/src/libsys/mips_dbg.c @@ -6,6 +6,9 @@ #include "libsys.h" #include "mips_dis.h" +extern int instr_info(unsigned iword, instr_info_t *pInfo); +extern int tdisasm(char *buffer, unsigned address, unsigned iword, unsigned char ext, unsigned *regmask, unsigned *symbol_value, unsigned *ls_register); + #define DBG_PRINT_REG(tag_str, reg) \ dbg_puts(tag_str); \ dbg_print_word(reg); \ @@ -34,6 +37,7 @@ #define BP_MGMT_RU(id) (((BP_MGMT_BASE_RU + id) << 6) | 0x0D) static char g_buf[80]; +static int DEBUG_PRINT = 1; enum { @@ -134,6 +138,23 @@ int dbg_gets(char *buffer, size_t size) dbg_putchar(0x0A); return len; } + +void dbg_puts_d(const char *buffer) +{ + if (DEBUG_PRINT) + { + dbg_puts(buffer); + } +} + +void dbg_print_word_d(int word) +{ + if (DEBUG_PRINT) + { + dbg_print_word(word); + } +} + #endif int IsBreak(uint32_t instr) @@ -158,24 +179,25 @@ char* reg_changed(uint32_t reg1, uint32_t reg2) return chg_str; } -void set_mgmt_break(uint32_t *pAddr_break) +void set_mgmt_break(uint32_t *pAddr_break, int index) { - mgmt_bp_ss[0].pAddr = NULL; - mgmt_bp_ss[0].pAddr = 0; + mgmt_bp_ss[index].pAddr = NULL; + mgmt_bp_ss[index].instr = 0; + dbg_puts_d("Set management break at ");dbg_print_word_d((long)pAddr_break);dbg_puts_d("\n\r"); // Don't overwrite user breaks if (IsBreak(*pAddr_break) && (BreakGetType(*pAddr_break) == BP_USER_BASE)) { -// dbg_puts("Instruction at address ");dbg_print_word((long)pAddr_break);dbg_puts(" is user break\n"); + dbg_puts_d("Instruction at address ");dbg_print_word_d((long)pAddr_break);dbg_puts_d(" is user break\n"); } else { // Save original instruction - mgmt_bp_ss[0].pAddr = pAddr_break; - mgmt_bp_ss[0].instr = *(mgmt_bp_ss[0].pAddr); + mgmt_bp_ss[index].pAddr = pAddr_break; + mgmt_bp_ss[index].instr = *(mgmt_bp_ss[index].pAddr); // Replace instruction with managment breakpoint - *(mgmt_bp_ss[0].pAddr) = BP_MGMT_SS(1); - ICACHE_invalidate_at(mgmt_bp_ss[0].pAddr); + *(mgmt_bp_ss[index].pAddr) = BP_MGMT_SS(index+1); + ICACHE_invalidate_at(mgmt_bp_ss[index].pAddr); } } @@ -183,42 +205,49 @@ void singlestep(struct xcptcontext * xcp, uint32_t *pAddr_curr, uint32_t is_bran { int junk; - uint32_t branch_addr, reg, result, bp_type; + uint32_t branch_addr, reg, bp_type; uint32_t *pInstr, *pAddr_prev, *pAddr_next; + instr_info_t info; + int set_break_at_jump_target = 0; + + dbg_puts_d("is_branch_shadow = ");dbg_print_word_d((long)is_branch_shadow);dbg_puts_d("\n\r"); pAddr_prev = pAddr_curr - 1; pAddr_next = pAddr_curr + 1; - set_mgmt_break(pAddr_next); - mgmt_bp_ss[1].pAddr = NULL; - mgmt_bp_ss[1].pAddr = 0; + mgmt_bp_ss[1].instr = 0; // We have two possible management breaks, if previous instruction was branch or jump if (is_branch_shadow) { - result = tdisasm(g_buf, (long)pAddr_prev, *pAddr_prev, 0, &junk, &branch_addr, ®); - // Is jump target stored in register - if (result == 3) - { - branch_addr = xcp->regs[reg&0x1F]; - } + int type = instr_info(*pAddr_prev, &info); - // Don't overwrite user breaks + tdisasm(g_buf, (unsigned int)pAddr_prev, (unsigned int)*pAddr_prev, 0, &junk, (unsigned int*)&branch_addr, (unsigned int*)®); + // Is jump target stored in register + if (type == INSTR_TYPE_JUMP || type == INSTR_TYPE_BRANCH) + { + if (info.flags & (INSTR_FLAGS_JUMP_REGISTER|INSTR_FLAGS_BRANCH_REGISTER)) + { + branch_addr = xcp->regs[reg&0x1F]; + } + } + // Don't overwrite user breaks if (IsBreak(branch_addr) && (BreakGetType(branch_addr) == BP_USER_BASE)) { -// dbg_puts("Instruction at branch address ");dbg_print_word((long)branch_addr);dbg_puts(" is user break\n"); + dbg_puts_d("Instruction at branch address ");dbg_print_word_d((long)branch_addr);dbg_puts_d(" is user break\n"); } else { - // Save original instruction - mgmt_bp_ss[1].pAddr = (uint32_t*)branch_addr; - mgmt_bp_ss[1].instr = *(mgmt_bp_ss[1].pAddr); - // Replace instruction with managment breakpoint - *(mgmt_bp_ss[1].pAddr) = BP_MGMT_SS(2); - ICACHE_invalidate_at(mgmt_bp_ss[1].pAddr); + set_break_at_jump_target = 1; } } + set_mgmt_break(pAddr_next, 0); + if (set_break_at_jump_target) + { + set_mgmt_break((uint32_t*)branch_addr, 1); + } + } void dbg_handler(struct xcptcontext * xcp) @@ -238,6 +267,8 @@ void dbg_handler(struct xcptcontext * xcp) pAddr_prev = pAddr_curr - 1; pAddr_next = pAddr_curr + 1; + dbg_puts_d("\n\r");dbg_puts_d(g_state_names[g_state]);dbg_puts_d("\n\r"); + if (IsBreak(*pAddr_curr)) { bp_type = BreakGetType(*pAddr_curr); @@ -247,12 +278,12 @@ void dbg_handler(struct xcptcontext * xcp) case BP_MGMT_BASE_SS: // Restore original instructions after single-step -// dbg_puts("1. Restore after single-step at ");dbg_print_word((long)mgmt_bp_ss[0].pAddr);dbg_puts("\n\r"); + dbg_puts_d("1. Restore after single-step at ");dbg_print_word_d((long)mgmt_bp_ss[0].pAddr);dbg_puts_d("\n\r"); *(mgmt_bp_ss[0].pAddr) = mgmt_bp_ss[0].instr; ICACHE_invalidate_at(mgmt_bp_ss[0].pAddr); if (mgmt_bp_ss[1].pAddr) { -// dbg_puts("2. Restore after single-step at ");dbg_print_word((long)mgmt_bp_ss[1].pAddr);dbg_puts("\n\r"); + dbg_puts_d("2. Restore after single-step at ");dbg_print_word_d((long)mgmt_bp_ss[1].pAddr);dbg_puts_d("\n\r"); *(mgmt_bp_ss[1].pAddr) = mgmt_bp_ss[1].instr; ICACHE_invalidate_at(mgmt_bp_ss[1].pAddr); } @@ -262,19 +293,19 @@ void dbg_handler(struct xcptcontext * xcp) case BP_MGMT_BASE_RU: bp_index = BP_GET_ID(*pAddr_curr); -// dbg_puts("Restore user break at ");dbg_print_word((long)user_bp[bp_index].pAddr);dbg_puts("\n\r"); + dbg_puts_d("Restore user break at ");dbg_print_word_d((long)user_bp[bp_index].pAddr);dbg_puts_d("\n\r"); *(user_bp[bp_index].pAddr) = BP_USER(bp_index); ICACHE_invalidate_at(user_bp[bp_index].pAddr); *(mgmt_bp_ru[0].pAddr) = mgmt_bp_ru[0].instr; ICACHE_invalidate_at(mgmt_bp_ru[0].pAddr); -// dbg_puts("1. Restore after RU at ");dbg_print_word((long)mgmt_bp_ru[0].pAddr);dbg_puts("\n\r"); + dbg_puts_d("1. Restore after RU at ");dbg_print_word_d((long)mgmt_bp_ru[0].pAddr);dbg_puts_d("\n\r"); if (mgmt_bp_ru[1].pAddr) { *(mgmt_bp_ru[1].pAddr) = mgmt_bp_ru[1].instr; ICACHE_invalidate_at(mgmt_bp_ru[1].pAddr); -// dbg_puts("2. Restore after RU at ");dbg_print_word((long)mgmt_bp_ru[1].pAddr);dbg_puts("\n\r"); + dbg_puts_d("2. Restore after RU at ");dbg_print_word_d((long)mgmt_bp_ru[1].pAddr);dbg_puts_d("\n\r"); } if (!g_is_ss) return; @@ -285,13 +316,13 @@ void dbg_handler(struct xcptcontext * xcp) is_user_bp = 1; bp_index = BP_GET_ID(*pAddr_curr); -// dbg_puts("Restore instruction at ");dbg_print_word((long)user_bp[bp_index].pAddr);dbg_puts("\n\r"); + dbg_puts_d("Restore instruction at ");dbg_print_word_d((long)user_bp[bp_index].pAddr);dbg_puts_d("\n\r"); *(user_bp[bp_index].pAddr) = user_bp[bp_index].instr; ICACHE_invalidate_at(user_bp[bp_index].pAddr); break; default: -// dbg_puts("Found ordinary break at ");dbg_print_word((long)pAddr_curr);dbg_puts("\n\r"); + dbg_puts_d("Found ordinary break at ");dbg_print_word_d((long)pAddr_curr);dbg_puts_d("\n\r"); break; } @@ -339,8 +370,8 @@ void dbg_handler(struct xcptcontext * xcp) DBG_PRINT_REG_CHG("22 (s6) : ", xcp->regs[22], reg_changed(xcp->regs[22], xcp_last.regs[22])); DBG_PRINT_REG_CHG("23 (s7) : ", xcp->regs[23], reg_changed(xcp->regs[23], xcp_last.regs[23])); dbg_puts("\n\r"); - DBG_PRINT_REG_CHG("24 (s8) : ", xcp->regs[24], reg_changed(xcp->regs[24], xcp_last.regs[24])); - DBG_PRINT_REG_CHG("25 (s9) : ", xcp->regs[25], reg_changed(xcp->regs[25], xcp_last.regs[25])); + DBG_PRINT_REG_CHG("24 (t8) : ", xcp->regs[24], reg_changed(xcp->regs[24], xcp_last.regs[24])); + DBG_PRINT_REG_CHG("25 (t9) : ", xcp->regs[25], reg_changed(xcp->regs[25], xcp_last.regs[25])); DBG_PRINT_REG_CHG("26 (k0) : ", xcp->regs[26], reg_changed(xcp->regs[26], xcp_last.regs[26])); DBG_PRINT_REG_CHG("27 (k1) : ", xcp->regs[27], reg_changed(xcp->regs[27], xcp_last.regs[27])); dbg_puts("\n\r"); @@ -349,10 +380,6 @@ void dbg_handler(struct xcptcontext * xcp) DBG_PRINT_REG_CHG("30 (fp) : ", xcp->regs[30], reg_changed(xcp->regs[30], xcp_last.regs[30])); DBG_PRINT_REG_CHG("31 (ra) : ", xcp->regs[31], reg_changed(xcp->regs[31], xcp_last.regs[31])); dbg_puts("\n\r"); - dbg_puts("\n\r"); - -// dbg_puts(g_state_names[g_state]);dbg_puts("\n\r"); -// dbg_puts("\n\r"); pInstr = pAddr_prev; // Disassemble instructions @@ -398,17 +425,21 @@ void dbg_handler(struct xcptcontext * xcp) *(mgmt_bp_ru[0].pAddr) = BP_MGMT_RU(bp_index); ICACHE_invalidate_at(mgmt_bp_ru[0].pAddr); mgmt_bp_ru[1].pAddr = NULL; - mgmt_bp_ru[1].pAddr = 0; -// dbg_puts("1. Insert RU-break at ");dbg_print_word((long)mgmt_bp_ru[0].pAddr);dbg_puts("\n\r"); + mgmt_bp_ru[1].instr = 0; + dbg_puts_d("1. Insert RU-break at ");dbg_print_word_d((long)mgmt_bp_ru[0].pAddr);dbg_puts_d("\n\r"); // We have two possible management breaks, if previous instruction was branch or jump if (is_branch_shadow) { - result = tdisasm(g_buf, (long)pAddr_prev, *pAddr_prev, 0, &junk, &branch_addr, ®); + int type = instr_info(*pAddr_prev, &info); + tdisasm(g_buf, (long)pAddr_prev, *pAddr_prev, 0, &junk, (unsigned int*)&branch_addr, (unsigned int*)®); // Is jump target stored in register - if (result == 3) + if (type == INSTR_TYPE_JUMP || type == INSTR_TYPE_BRANCH) { - branch_addr = xcp->regs[reg&0x1F]; + if (info.flags & (INSTR_FLAGS_JUMP_REGISTER|INSTR_FLAGS_BRANCH_REGISTER)) + { + branch_addr = xcp->regs[reg&0x1F]; + } } // Save original instruction mgmt_bp_ru[1].pAddr = (uint32_t*)branch_addr; @@ -416,7 +447,7 @@ void dbg_handler(struct xcptcontext * xcp) // Replace instruction with managment breakpoint *(mgmt_bp_ru[1].pAddr) = BP_MGMT_RU(bp_index); ICACHE_invalidate_at(mgmt_bp_ru[1].pAddr); -// dbg_puts("2. Insert RU-break at ");dbg_print_word((long)mgmt_bp_ru[1].pAddr);dbg_puts("\n\r"); + dbg_puts_d("2. Insert RU-break at ");dbg_print_word_d((long)mgmt_bp_ru[1].pAddr);dbg_puts_d("\n\r"); } } @@ -516,8 +547,8 @@ void dbg_handler(struct xcptcontext * xcp) pInstr++; } while(1); -// dbg_puts("Return found at "); dbg_print_word((long)pInstr);dbg_puts("\n\r"); - set_mgmt_break(pInstr); + dbg_puts_d("Return found at "); dbg_print_word_d((long)pInstr);dbg_puts_d("\n\r"); + set_mgmt_break(pInstr, 0); break; case 'p': @@ -544,7 +575,7 @@ void dbg_handler(struct xcptcontext * xcp) if ((result == INSTR_TYPE_JUMP) && (info.flags & INSTR_FLAGS_JUMP_LINK)) { singlestep(xcp, pAddr_next, 0); -// printf("Skip sub-routine\n"); + dbg_puts_d("Skip sub-routine\n\r"); } else { diff --git a/src/libsys/xcpt_asm.h b/src/libsys/xcpt_asm.h index 7a454b6..1fcdbd8 100644 --- a/src/libsys/xcpt_asm.h +++ b/src/libsys/xcpt_asm.h @@ -16,7 +16,7 @@ symbol: .frame sp, 0, ra /* Exception stack size */ #ifndef XCP_SIZE -#define XCP_SIZE 32768 +#define XCP_SIZE 65536 #endif /* save location for registers */