GDB (API)
|
00001 /* Remote debugging interface for DINK32 (PowerPC) ROM monitor for 00002 GDB, the GNU debugger. 00003 Copyright (C) 1997-2013 Free Software Foundation, Inc. 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #include "defs.h" 00021 #include "gdbcore.h" 00022 #include "target.h" 00023 #include "monitor.h" 00024 #include "serial.h" 00025 #include "symfile.h" /* For generic_load() */ 00026 #include "inferior.h" 00027 #include "regcache.h" 00028 00029 static void dink32_open (char *args, int from_tty); 00030 00031 static void 00032 dink32_supply_register (struct regcache *regcache, char *regname, 00033 int regnamelen, char *val, int vallen) 00034 { 00035 int regno = 0; 00036 00037 if (regnamelen < 2 || regnamelen > 4) 00038 return; 00039 00040 switch (regname[0]) 00041 { 00042 case 'R': 00043 if (regname[1] < '0' || regname[1] > '9') 00044 return; 00045 if (regnamelen == 2) 00046 regno = regname[1] - '0'; 00047 else if (regnamelen == 3 && regname[2] >= '0' && regname[2] <= '9') 00048 regno = (regname[1] - '0') * 10 + (regname[2] - '0'); 00049 else 00050 return; 00051 break; 00052 case 'F': 00053 if (regname[1] != 'R' || regname[2] < '0' || regname[2] > '9') 00054 return; 00055 if (regnamelen == 3) 00056 regno = 32 + regname[2] - '0'; 00057 else if (regnamelen == 4 && regname[3] >= '0' && regname[3] <= '9') 00058 regno = 32 + (regname[2] - '0') * 10 + (regname[3] - '0'); 00059 else 00060 return; 00061 break; 00062 case 'I': 00063 if (regnamelen != 2 || regname[1] != 'P') 00064 return; 00065 regno = 64; 00066 break; 00067 case 'M': 00068 if (regnamelen != 3 || regname[1] != 'S' || regname[2] != 'R') 00069 return; 00070 regno = 65; 00071 break; 00072 case 'C': 00073 if (regnamelen != 2 || regname[1] != 'R') 00074 return; 00075 regno = 66; 00076 break; 00077 case 'S': 00078 if (regnamelen != 4 || regname[1] != 'P' || regname[2] != 'R') 00079 return; 00080 else if (regname[3] == '8') 00081 regno = 67; 00082 else if (regname[3] == '9') 00083 regno = 68; 00084 else if (regname[3] == '1') 00085 regno = 69; 00086 else if (regname[3] == '0') 00087 regno = 70; 00088 else 00089 return; 00090 break; 00091 default: 00092 return; 00093 } 00094 00095 monitor_supply_register (regcache, regno, val); 00096 } 00097 00098 /* This array of registers needs to match the indexes used by GDB. 00099 The whole reason this exists is because the various ROM monitors 00100 use different names than GDB does, and don't support all the 00101 registers either. */ 00102 00103 static char *dink32_regnames[] = 00104 { 00105 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 00106 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 00107 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 00108 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", 00109 00110 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", 00111 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", 00112 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", 00113 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", 00114 00115 "srr0", "msr", "cr", "lr", "ctr", "xer", "xer" 00116 }; 00117 00118 static struct target_ops dink32_ops; 00119 00120 static char *dink32_inits[] = 00121 {"\r", NULL}; 00122 00123 static struct monitor_ops dink32_cmds; 00124 00125 static void 00126 dink32_open (char *args, int from_tty) 00127 { 00128 monitor_open (args, &dink32_cmds, from_tty); 00129 } 00130 00131 extern initialize_file_ftype _initialize_dink32_rom; /* -Wmissing-prototypes */ 00132 00133 void 00134 _initialize_dink32_rom (void) 00135 { 00136 dink32_cmds.flags = MO_HEX_PREFIX | MO_GETMEM_NEEDS_RANGE 00137 | MO_FILL_USES_ADDR | MO_HANDLE_NL | MO_32_REGS_PAIRED 00138 | MO_SETREG_INTERACTIVE | MO_SETMEM_INTERACTIVE 00139 | MO_GETMEM_16_BOUNDARY | MO_CLR_BREAK_1_BASED | MO_SREC_ACK 00140 | MO_SREC_ACK_ROTATE; 00141 dink32_cmds.init = dink32_inits; 00142 dink32_cmds.cont = "go +\r"; 00143 dink32_cmds.step = "tr +\r"; 00144 dink32_cmds.set_break = "bp 0x%x\r"; 00145 dink32_cmds.clr_break = "bp %d\r"; 00146 #if 0 /* Would need to follow strict alignment rules.. */ 00147 dink32_cmds.fill = "mf %x %x %x\r"; 00148 #endif 00149 dink32_cmds.setmem.cmdb = "mm -b %x\r"; 00150 dink32_cmds.setmem.cmdw = "mm -w %x\r"; 00151 dink32_cmds.setmem.cmdl = "mm %x\r"; 00152 dink32_cmds.setmem.term = " ? "; 00153 dink32_cmds.getmem.cmdb = "md %x\r"; 00154 dink32_cmds.getmem.resp_delim = " "; 00155 dink32_cmds.setreg.cmd = "rm %s\r"; 00156 dink32_cmds.setreg.term = " ? "; 00157 dink32_cmds.getreg.cmd = "rd %s\r"; 00158 dink32_cmds.getreg.resp_delim = ": "; 00159 dink32_cmds.dump_registers = "rd r\r"; 00160 dink32_cmds.register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)"; 00161 dink32_cmds.supply_register = dink32_supply_register; 00162 /* S-record download, via "keyboard port". */ 00163 dink32_cmds.load = "dl -k\r"; 00164 dink32_cmds.loadresp = "Set Input Port : set to Keyboard Port\r"; 00165 dink32_cmds.prompt = "DINK32_603 >>"; 00166 dink32_cmds.line_term = "\r"; 00167 dink32_cmds.target = &dink32_ops; 00168 dink32_cmds.stopbits = SERIAL_1_STOPBITS; 00169 dink32_cmds.regnames = dink32_regnames; 00170 dink32_cmds.magic = MONITOR_OPS_MAGIC; 00171 00172 init_monitor_ops (&dink32_ops); 00173 00174 dink32_ops.to_shortname = "dink32"; 00175 dink32_ops.to_longname = "DINK32 monitor"; 00176 dink32_ops.to_doc = "Debug using the DINK32 monitor.\n\ 00177 Specify the serial device it is connected to (e.g. /dev/ttya)."; 00178 dink32_ops.to_open = dink32_open; 00179 00180 add_target (&dink32_ops); 00181 }