GDB (API)
|
00001 /* Remote debugging interface for PPCbug (PowerPC) Rom monitor 00002 for GDB, the GNU debugger. 00003 Copyright (C) 1995-2013 Free Software Foundation, Inc. 00004 00005 Written by Stu Grossman of Cygnus Support 00006 00007 This file is part of GDB. 00008 00009 This program is free software; you can redistribute it and/or modify 00010 it under the terms of the GNU General Public License as published by 00011 the Free Software Foundation; either version 3 of the License, or 00012 (at your option) any later version. 00013 00014 This program is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU General Public License for more details. 00018 00019 You should have received a copy of the GNU General Public License 00020 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00021 00022 #include "defs.h" 00023 #include "gdbcore.h" 00024 #include "target.h" 00025 #include "monitor.h" 00026 #include "serial.h" 00027 #include "regcache.h" 00028 00029 static void 00030 ppcbug_supply_register (struct regcache *regcache, char *regname, 00031 int regnamelen, char *val, int vallen) 00032 { 00033 int regno = 0; 00034 00035 if (regnamelen < 2 || regnamelen > 4) 00036 return; 00037 00038 switch (regname[0]) 00039 { 00040 case 'R': 00041 if (regname[1] < '0' || regname[1] > '9') 00042 return; 00043 if (regnamelen == 2) 00044 regno = regname[1] - '0'; 00045 else if (regnamelen == 3 && regname[2] >= '0' && regname[2] <= '9') 00046 regno = (regname[1] - '0') * 10 + (regname[2] - '0'); 00047 else 00048 return; 00049 break; 00050 case 'F': 00051 if (regname[1] != 'R' || regname[2] < '0' || regname[2] > '9') 00052 return; 00053 if (regnamelen == 3) 00054 regno = 32 + regname[2] - '0'; 00055 else if (regnamelen == 4 && regname[3] >= '0' && regname[3] <= '9') 00056 regno = 32 + (regname[2] - '0') * 10 + (regname[3] - '0'); 00057 else 00058 return; 00059 break; 00060 case 'I': 00061 if (regnamelen != 2 || regname[1] != 'P') 00062 return; 00063 regno = 64; 00064 break; 00065 case 'M': 00066 if (regnamelen != 3 || regname[1] != 'S' || regname[2] != 'R') 00067 return; 00068 regno = 65; 00069 break; 00070 case 'C': 00071 if (regnamelen != 2 || regname[1] != 'R') 00072 return; 00073 regno = 66; 00074 break; 00075 case 'S': 00076 if (regnamelen != 4 || regname[1] != 'P' || regname[2] != 'R') 00077 return; 00078 else if (regname[3] == '8') 00079 regno = 67; 00080 else if (regname[3] == '9') 00081 regno = 68; 00082 else if (regname[3] == '1') 00083 regno = 69; 00084 else if (regname[3] == '0') 00085 regno = 70; 00086 else 00087 return; 00088 break; 00089 default: 00090 return; 00091 } 00092 00093 monitor_supply_register (regcache, regno, val); 00094 } 00095 00096 /* 00097 * This array of registers needs to match the indexes used by GDB. The 00098 * whole reason this exists is because the various ROM monitors use 00099 * different names than GDB does, and don't support all the 00100 * registers either. So, typing "info reg sp" becomes an "A7". 00101 */ 00102 00103 static char *ppcbug_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 "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7", 00111 "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15", 00112 "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23", 00113 "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31", 00114 00115 /* pc ps cnd lr cnt xer mq */ 00116 "ip", "msr", "cr", "spr8", "spr9", "spr1", "spr0" 00117 }; 00118 00119 /* 00120 * Define the monitor command strings. Since these are passed directly 00121 * through to a printf style function, we need can include formatting 00122 * strings. We also need a CR or LF on the end. 00123 */ 00124 00125 static struct target_ops ppcbug_ops0; 00126 static struct target_ops ppcbug_ops1; 00127 00128 static char *ppcbug_inits[] = 00129 {"\r", NULL}; 00130 00131 static void 00132 init_ppc_cmds (char *LOAD_CMD, 00133 struct monitor_ops *OPS, 00134 struct target_ops *targops) 00135 { 00136 OPS->flags = MO_CLR_BREAK_USES_ADDR | MO_HANDLE_NL; 00137 OPS->init = ppcbug_inits; /* Init strings */ 00138 OPS->cont = "g\r"; /* continue command */ 00139 OPS->step = "t\r"; /* single step */ 00140 OPS->stop = NULL; /* interrupt command */ 00141 OPS->set_break = "br %x\r"; /* set a breakpoint */ 00142 OPS->clr_break = "nobr %x\r"; /* clear a breakpoint */ 00143 OPS->clr_all_break = "nobr\r"; /* clear all breakpoints */ 00144 OPS->fill = "bf %x:%x %x;b\r"; /* fill (start count val) */ 00145 OPS->setmem.cmdb = "ms %x %02x\r"; /* setmem.cmdb (addr, value) */ 00146 OPS->setmem.cmdw = "ms %x %04x\r"; /* setmem.cmdw (addr, value) */ 00147 OPS->setmem.cmdl = "ms %x %08x\r"; /* setmem.cmdl (addr, value) */ 00148 OPS->setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */ 00149 OPS->setmem.resp_delim = NULL; /* setreg.resp_delim */ 00150 OPS->setmem.term = NULL; /* setreg.term */ 00151 OPS->setmem.term_cmd = NULL; /* setreg.term_cmd */ 00152 OPS->getmem.cmdb = "md %x:%x;b\r"; /* getmem.cmdb (addr, len) */ 00153 OPS->getmem.cmdw = "md %x:%x;b\r"; /* getmem.cmdw (addr, len) */ 00154 OPS->getmem.cmdl = "md %x:%x;b\r"; /* getmem.cmdl (addr, len) */ 00155 OPS->getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */ 00156 OPS->getmem.resp_delim = " "; /* getmem.resp_delim */ 00157 OPS->getmem.term = NULL; /* getmem.term */ 00158 OPS->getmem.term_cmd = NULL; /* getmem.term_cmd */ 00159 OPS->setreg.cmd = "rs %s %x\r"; /* setreg.cmd (name, value) */ 00160 OPS->setreg.resp_delim = NULL; /* setreg.resp_delim */ 00161 OPS->setreg.term = NULL; /* setreg.term */ 00162 OPS->setreg.term_cmd = NULL; /* setreg.term_cmd */ 00163 OPS->getreg.cmd = "rs %s\r"; /* getreg.cmd (name) */ 00164 OPS->getreg.resp_delim = "="; /* getreg.resp_delim */ 00165 OPS->getreg.term = NULL; /* getreg.term */ 00166 OPS->getreg.term_cmd = NULL; /* getreg.term_cmd */ 00167 /* register_pattern */ 00168 OPS->register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)"; 00169 OPS->supply_register = ppcbug_supply_register; 00170 OPS->dump_registers = "rd\r"; /* dump all registers */ 00171 OPS->load = LOAD_CMD; /* download command */ 00172 OPS->loadresp = NULL; /* load response */ 00173 OPS->prompt = "PPC1-Bug>"; /* monitor command prompt */ 00174 OPS->line_term = "\r"; /* end-of-line terminator */ 00175 OPS->cmd_end = NULL; /* optional command terminator */ 00176 OPS->target = targops; /* target operations */ 00177 OPS->stopbits = SERIAL_1_STOPBITS; /* number of stop bits */ 00178 OPS->regnames = ppcbug_regnames; /* registers names */ 00179 OPS->magic = MONITOR_OPS_MAGIC; /* magic */ 00180 } 00181 00182 00183 static struct monitor_ops ppcbug_cmds0; 00184 static struct monitor_ops ppcbug_cmds1; 00185 00186 static void 00187 ppcbug_open0 (char *args, int from_tty) 00188 { 00189 monitor_open (args, &ppcbug_cmds0, from_tty); 00190 } 00191 00192 static void 00193 ppcbug_open1 (char *args, int from_tty) 00194 { 00195 monitor_open (args, &ppcbug_cmds1, from_tty); 00196 } 00197 00198 extern initialize_file_ftype _initialize_ppcbug_rom; /* -Wmissing-prototypes */ 00199 00200 void 00201 _initialize_ppcbug_rom (void) 00202 { 00203 init_ppc_cmds ("lo 0\r", &ppcbug_cmds0, &ppcbug_ops0); 00204 init_ppc_cmds ("lo 1\r", &ppcbug_cmds1, &ppcbug_ops1); 00205 init_monitor_ops (&ppcbug_ops0); 00206 00207 ppcbug_ops0.to_shortname = "ppcbug"; 00208 ppcbug_ops0.to_longname = "PowerPC PPCBug monitor on port 0"; 00209 ppcbug_ops0.to_doc = "Debug via the PowerPC PPCBug monitor using port 0.\n\ 00210 Specify the serial device it is connected to (e.g. /dev/ttya)."; 00211 ppcbug_ops0.to_open = ppcbug_open0; 00212 00213 add_target (&ppcbug_ops0); 00214 00215 init_monitor_ops (&ppcbug_ops1); 00216 00217 ppcbug_ops1.to_shortname = "ppcbug1"; 00218 ppcbug_ops1.to_longname = "PowerPC PPCBug monitor on port 1"; 00219 ppcbug_ops1.to_doc = "Debug via the PowerPC PPCBug monitor using port 1.\n\ 00220 Specify the serial device it is connected to (e.g. /dev/ttya)."; 00221 ppcbug_ops1.to_open = ppcbug_open1; 00222 00223 add_target (&ppcbug_ops1); 00224 }