📄 gdb-5.3-bdm-m68k.patch
字号:
+static int bdmDebugLevel;+static const char *downloadErrorString;++static void+downloadSection (bfd *abfd, sec_ptr sec, PTR ignore)+{+ unsigned long dfc;+ unsigned long address;+ unsigned long nleft, size;+ int count;+ file_ptr offset;+ char cbuf[1024];++ /*+ * See if the section needs loading+ */+ if (bdmDebugLevel)+ printf_filtered ("Section flags:%#x\n", bfd_get_section_flags (abfd, sec));+ if ((downLoaderReturn < 0) ||+ ((bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS) == 0) ||+ ((bfd_get_section_flags (abfd, sec) & SEC_LOAD) == 0))+ return;+ address = bfd_section_lma (abfd, sec);+ if (bdmDebugLevel)+ printf_filtered ("Section address:%#lx\n", address);+ if (downLoaderFirst && (bfd_get_section_flags (abfd, sec) & SEC_CODE)) {+ downLoadStartAddress = bfd_get_start_address (abfd);+ downLoadBaseAddress = address;+ downLoaderFirst = 0;+ if (bdmDebugLevel)+ printf_filtered ("Start address:%#lx Base address:%#lx\n",+ downLoadStartAddress, downLoadBaseAddress);+ }++ /*+ * Set the appropriate destination address space+ */+ if (bfd_get_section_flags (abfd, sec) & SEC_CODE)+ dfc = 0x6; /* Supervisor program space */+ else+ dfc = 0x5; /* Supervisor data space */+ if (bdmWriteSystemRegister (BDM_REG_DFC, dfc) < 0) {+ downLoaderReturn = -1;+ return;+ }++ /*+ * Load the section in `sizeof cbuf` chunks+ */+ size = nleft = bfd_get_section_size_before_reloc (sec);+ if (nleft == 0)+ return;++ /* Is this really necessary? I guess it gives the user something+ to look at during a long download. */+ ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n",+ sec->name, paddr_nz (size), paddr_nz (address));++ offset = 0;+ while (nleft) {+ if (nleft > sizeof cbuf)+ count = sizeof cbuf;+ else+ count = nleft;+ if (!bfd_get_section_contents (abfd, sec, cbuf, offset, count)) {+ downloadErrorString = "Error reading section contents";+ downLoaderReturn = -1;+ return;+ }+ if (bdmWriteMemory (address, cbuf, count) < 0) {+ downLoaderReturn = -1;+ return;+ }+ address += count;+ offset += count;+ nleft -= count;++ if (quit_flag+ || (ui_load_progress_hook != NULL+ && ui_load_progress_hook (sec->name, offset)))+ error ("Canceled the download");++ if (show_load_progress != NULL)+ show_load_progress (sec->name, offset, size, size, size);+ }+ downLoadDataCount += size;+}++/*+ * Load an executable image into the target+ */+static int+loadExecutable (const char *name)+{+ bfd *abfd;+ unsigned long dfc;+ unsigned long l;++ /*+ * Make sure target is there+ */+ if (!bdmCheck ())+ return -1;++ /*+ * Open and verify the file+ */+ bfd_init ();+ abfd = bfd_openr (name, "default");+ if (abfd == NULL) {+ downloadErrorString = bfd_errmsg (bfd_get_error());+ return -1;+ }+ if (!bfd_check_format (abfd, bfd_object)) {+ downloadErrorString = "Not an object file";+ return -1;+ }++ /*+ * Save the destination function code register+ */+ if (bdmReadSystemRegister (BDM_REG_DFC, &dfc) < 0)+ return -1;++ /*+ * Load each section of the executable file+ */+ downLoadDataCount = 0;+ downLoaderFirst = 1;+ downLoaderReturn = 0;+ bfd_map_over_sections (abfd, downloadSection, NULL);+ if (downLoaderReturn < 0)+ return -1;++ ui_out_text (uiout, "Start address ");+ ui_out_field_fmt (uiout, "address", "0x%s", paddr_nz (downLoadStartAddress));+ ui_out_text (uiout, ", load size ");+ ui_out_field_fmt (uiout, "load-size", "%lu", downLoadDataCount);+ ui_out_text (uiout, "\n");++ /*+ * Set program counter+ */+ if ((bdmWriteSystemRegister (BDM_REG_RPC, downLoadStartAddress) < 0)+ || (bdmWriteSystemRegister (BDM_REG_DFC, dfc) < 0))+ return -1;+ return 0;++ inferior_ptid = pid_to_ptid (1);++}++/*+ * The breakpoint codes for the different processors+ */+static char cpu32_breakpoint[] = {0x4a, 0xfa};+static char cf_breakpoint[] = {0x4a, 0xc8};+static char *breakpointCode;+static int breakpointSize;++static int cf_init_watchpoints();++/* Immediately after a function call, return the saved pc before the frame+ is setup. For uCLinux which uses a TRAP #0 for a system call we need to+ read the first long word of the stack to see if the stack frame format is+ type 4 and the vector is 32 (0x4080), and the opcode at the PC is+ "move.w #0x2700,sr". If it is then get the second long from the stack. */++CORE_ADDR+m68k_bdm_saved_pc_after_call (frame)+ struct frame_info *frame;+{+ unsigned int op;+ unsigned int eframe;+ int sp;+ + sp = read_register (SP_REGNUM);+ eframe = read_memory_integer (sp, 2);+ op = read_memory_integer (frame->pc, 4);++ /*+ * This test could break if some changes the syste call.+ */+ + if (eframe == 0x4080 && op == 0x46fc2700)+ return read_memory_integer (sp + 4, 4);+ else+ return read_memory_integer (sp, 4);+}+ +unsigned char *m68k_bdm_breakpoint_from_pc (pcptr, lenptr)+ CORE_ADDR *pcptr;+ int *lenptr;+{+ *lenptr = breakpointSize;+ return breakpointCode;+}++/*+ * Short pause+ */+static void+nap (int microseconds)+{+ struct timeval tv;++ tv.tv_sec = microseconds / 1000000;+ tv.tv_usec = microseconds % 1000000;+ select (0, NULL, NULL, NULL, &tv);+}++/*+ * Display error message and jump back to main input loop+ */+static void+bdm_report_error (void)+{+ error ("BDM error: %s", bdmErrorString ());+}++/*+ * Initialize bdm interface port+ */+static void+bdm_init (int tty, char *arg)+{+}++/*+ * Return interface status+ */+static int+bdm_get_status (void)+{+ int status;++ if ((status = bdmStatus ()) < 0)+ bdm_report_error ();+ return status;+}++static void+bdm_get_status_interactive (int pid, char *arg)+{+ printf ("BDM status: 0x%x\n", bdm_get_status ());+}++/*+ * release chip: reset and disable bdm mode+ */+static void+bdm_release_chip (void)+{+ haveAtemp = 0;+ registers_changed ();+ if (bdmRelease () < 0)+ bdm_report_error ();+}++/*+ * stop chip+ */+static void+bdm_stop_chip (void)+{+ if (bdmStop () < 0)+ bdm_report_error ();+}++/*+ * Allow chip to resume execution+ */+static void+bdm_go (void)+{+ haveAtemp = 0;+ if (bdmGo () < 0)+ bdm_report_error ();+}++/*+ * Reset chip, enter BDM mode+ */+static void+bdm_reset (void)+{+ registers_changed ();+ if (bdmReset () < 0)+ bdm_report_error ();+ nap (TIME_TO_COME_UP);+}++/*+ * step cpu32 chip: execute a single instruction+ * This is complicated by the presence of interrupts.+ * Consider the following sequence of events:+ * - User attempts to `continue' from a breakpoint.+ * - Gdb calls bdm_step_chip to single-step the instruction that+ * had been replaced by the BGND instruction.+ * - The target processor executes the instruction and stops.+ * - GDB replaces the instruction with a BGND instruction to+ * force a breakpoint the next time the instruction is hit.+ * - GDB calls bdm_go and the target resumes execution.+ * This all seems fine, but now consider what happens when a interrupt+ * is pending:+ * - User attempts to `continue' from a breakpoint.+ * - Gdb calls bdm_step_chip to single-step the instruction that+ * had been replaced by the BGND instruction.+ * - The target processor does not execute the replaced instruction,+ * but rather executes the first instruction of the interrupt+ * service routine, then stops.+ * - GDB replaces the instruction with a BGND instruction to+ * force a breakpoint the next time the instruction is hit.+ * - GDB calls bdm_go and the target resumes execution.+ * - The target finishes off the interrupt, and upon returing from+ * the interrupt generates another breakpoint!+ * The solution is simple -- disable interrupts when single stepping.+ * The problem then becomes the handling of instructions which involve+ * the program status word!+ */+static void+bdm_step_cpu32_chip (void)+{+ unsigned long pc;+ unsigned short instruction;+ unsigned short immediate;+ unsigned long d7;+ unsigned long sr;+ unsigned long nsr;+ enum {+ op_other,+ op_ANDIsr,+ op_EORIsr,+ op_ORIsr,+ op_TOsr,+ op_FROMsr,+ op_FROMsrTOd7+ } op;++ /*+ * Get the existing status register+ */+ if (bdmReadSystemRegister (BDM_REG_SR, &sr) < 0)+ bdm_report_error ();++ /*+ * Read the instuction about to be executed+ */+ if ((bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0)+ || (bdmReadWord (pc, &instruction) < 0))+ bdm_report_error ();++ /*+ * See what operation is to be performed+ */+ if (instruction == 0x027C)+ op = op_ANDIsr;+ else if (instruction == 0x0A7C)+ op = op_EORIsr;+ else if (instruction == 0x007C)+ op = op_ORIsr;+ else if (instruction == 0x40C7)+ op = op_FROMsrTOd7;+ else if ((instruction & 0xFFC0) == 0x40C0)+ op = op_FROMsr;+ else if ((instruction & 0xFFC0) == 0x46C0)+ op = op_TOsr;+ else+ op = op_other;++ /*+ * Set things up for the single-step operation+ */+ switch (op) {+ case op_FROMsr:+ /*+ * It's storing the SR somewhere.+ * Store the SR in D7 and change the instruction+ * to save D7. This fails if the addressing mode+ * is one of the esoteric modes that uses D7 as+ * and index register, but we'll just have to hope+ * that doesn't happen too often.+ */+ if ((bdmReadRegister (7, &d7) < 0)+ || (bdmWriteRegister (7, sr) < 0)+ || (bdmWriteWord (pc, 0x3007 |+ ((instruction & 0x38) << 3) |+ ((instruction & 0x07) << 9)) < 0))+ bdm_report_error ();+ break;++ case op_ANDIsr:+ case op_EORIsr:+ case op_ORIsr:+ /*+ * It's an immediate operation to the SR -- pick up the value+ */+ if (bdmReadWord (pc+2, &immediate) < 0)+ bdm_report_error ();+ break;++ case op_TOsr:+ case op_other:+ break;+ }++ /*+ * Ensure the step is done with interrupts disabled+ */+ if (bdmWriteSystemRegister (BDM_REG_SR, sr | 0x0700) < 0)+ bdm_report_error ();++ /*+ * Do the single-step+ */+ if (bdmStep () < 0)+ bdm_report_error ();++ /*+ * Get the ATEMP register since the following operations may+ * modify it.+ */+ if (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0)+ bdm_report_error ();+ haveAtemp = 1;++ /*+ * Clean things up+ */+ switch (op) {+ case op_FROMsr:+ if ((bdmWriteRegister (7, d7) < 0)+ || (bdmWriteWord (pc, instruction) < 0)+ || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0))+ bdm_report_error ();+ break;++ case op_FROMsrTOd7:+ if ((bdmReadRegister (7, &d7) < 0)+ || (bdmWriteRegister (7, (d7 & ~0xFFFF) | (sr & 0xFFFF)) < 0)+ || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0))+ bdm_report_error ();+ break;++ case op_ANDIsr:+ if (bdmWriteSystemRegister (BDM_REG_SR, sr & immediate) < 0)+ bdm_report_error ();+ break;+ + case op_EORIsr:+ if (bdmWriteSystemRegister (BDM_REG_SR, sr ^ immediate) < 0)+ bdm_report_error ();+ break;++ case op_ORIsr:+ if (bdmWriteSystemRegister (BDM_REG_SR, sr | immediate) < 0)+ bdm_report_error ();+ break;++ case op_TOsr:+ break;++ case op_other:+ if ((bdmReadSystemRegister (BDM_REG_SR, &nsr) < 0)+ || (bdmWriteSystemRegister (BDM_REG_SR, (nsr & ~0x0700) | (sr & 0x0700)) < 0))+ bdm_report_error ();+ break;+ }+}++static void+bdm_step_chip (void)+{+ /*+ * The cpu32 is harder to step than the Coldfire.+ */+ if (cpu_type == BDM_CPU32) {+ bdm_step_cpu32_chip();+ return;+ }++ /*+ * Do the single-step+ */+ if (bdmStep () < 0)+ bdm_report_error ();+}++/*+ * true if runnable+ */+static int+bdm_can_run (void)+{+ return 1;+}++static void+bdm_setdelay(int delay)+{+ if (bdmSetDelay (delay) < 0)+ bdm_report_error ();+}++static void +bdm_setdelay_interactive (char *arg, int from_tty)+{+ char *dummy;++ if (!arg) {+ if (bdm_delay >= 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -