GDB (API)
/home/stan/gdb/src/gdb/ppcbug-rom.c
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines