Mon Apr 27 13:46:40 1998 John Metzler <jmetzler@cygnus.com>
[platform/upstream/binutils.git] / gdb / ppcbug-rom.c
1 /* Remote debugging interface for PPCbug (PowerPC) Rom monitor
2    for GDB, the GNU debugger.
3    Copyright 1995 Free Software Foundation, Inc.
4
5    Written by Stu Grossman of Cygnus Support
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
22
23 #include "defs.h"
24 #include "gdbcore.h"
25 #include "target.h"
26 #include "monitor.h"
27 #include "serial.h"
28
29 static void ppcbug_open PARAMS ((char *args, int from_tty));
30
31 static void
32 ppcbug_supply_register (regname, regnamelen, val, vallen)
33      char *regname;
34      int regnamelen;
35      char *val;
36      int vallen;
37 {
38   int regno = 0, base = 0;
39
40   if (regnamelen < 2 || regnamelen > 4)
41     return;
42
43   switch (regname[0])
44     {
45     case 'R':
46       if (regname[1] < '0' || regname[1] > '9')
47         return;
48       if (regnamelen == 2)
49         regno = regname[1] - '0';
50       else if (regnamelen == 3 && regname[2] >= '0' && regname[2] <= '9')
51         regno = (regname[1] - '0') * 10 + (regname[2] - '0');
52       else
53         return;
54       break;
55     case 'F':
56       if (regname[1] != 'R' || regname[2] < '0' || regname[2] > '9')
57         return;
58       if (regnamelen == 3)
59         regno = 32 + regname[2] - '0';
60       else if (regnamelen == 4 && regname[3] >= '0' && regname[3] <= '9')
61         regno = 32 + (regname[2] - '0') * 10 + (regname[3] - '0');
62       else
63         return;
64       break;
65     case 'I':
66       if (regnamelen != 2 || regname[1] != 'P')
67         return;
68       regno = 64;
69       break;
70     case 'M':
71       if (regnamelen != 3 || regname[1] != 'S' || regname[2] != 'R')
72         return;
73       regno = 65;
74       break;
75     case 'C':
76       if (regnamelen != 2 || regname[1] != 'R')
77         return;
78       regno = 66;
79       break;
80     case 'S':
81       if (regnamelen != 4 || regname[1] != 'P' || regname[2] != 'R')
82         return;
83       else if (regname[3] == '8')
84         regno = 67;
85       else if (regname[3] == '9')
86         regno = 68;
87       else if (regname[3] == '1')
88         regno = 69;
89       else if (regname[3] == '0')
90         regno = 70;
91       else
92         return;
93       break;
94     default:
95       return;
96     }
97
98   monitor_supply_register (regno, val);
99 }
100
101 /*
102  * This array of registers needs to match the indexes used by GDB. The
103  * whole reason this exists is because the various ROM monitors use
104  * different names than GDB does, and don't support all the
105  * registers either. So, typing "info reg sp" becomes an "A7".
106  */
107
108 static char *ppcbug_regnames[NUM_REGS] =
109 {
110   "r0",   "r1",   "r2",   "r3",   "r4",   "r5",   "r6",   "r7",
111   "r8",   "r9",   "r10",  "r11",  "r12",  "r13",  "r14",  "r15",
112   "r16",  "r17",  "r18",  "r19",  "r20",  "r21",  "r22",  "r23",
113   "r24",  "r25",  "r26",  "r27",  "r28",  "r29",  "r30",  "r31",
114
115   "fr0",  "fr1",  "fr2",  "fr3",  "fr4",  "fr5",  "fr6",  "fr7",
116   "fr8",  "fr9",  "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
117   "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",
118   "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31",
119
120 /* pc      ps      cnd     lr      cnt     xer     mq */
121   "ip",   "msr",  "cr",   "spr8", "spr9", "spr1", "spr0"
122 };
123
124 /*
125  * Define the monitor command strings. Since these are passed directly
126  * through to a printf style function, we need can include formatting
127  * strings. We also need a CR or LF on the end.
128  */
129
130 static struct target_ops ppcbug_ops0;
131 static struct target_ops ppcbug_ops1;
132
133 static char *ppcbug_inits[] = {"\r", NULL};
134
135 static void init_ppc_cmds(
136                           char  * LOAD_CMD,
137                           struct monitor_ops * OPS,
138                           struct target_ops * targops)
139 {
140  OPS->flags =   MO_CLR_BREAK_USES_ADDR | MO_HANDLE_NL;  
141  OPS->init =   ppcbug_inits;                    /* Init strings */
142  OPS->cont =   "g\r";                   /* continue command */          
143  OPS->step =   "t\r";                   /* single step */               
144  OPS->stop =   NULL;                            /* interrupt command */ 
145  OPS->set_break =   "br %x\r";                  /* set a breakpoint */  
146  OPS->clr_break =   "nobr %x\r";                        /* clear a breakpoint */
147  OPS->clr_all_break =   "nobr\r";                       /* clear all breakpoints */
148  OPS->fill =   "bf %x:%x %x;b\r";               /* fill (start count val) */            
149  OPS->setmem.cmdb =     "ms %x %02x\r";         /* setmem.cmdb (addr, value) */         
150  OPS->setmem.cmdw =     "ms %x %04x\r";         /* setmem.cmdw (addr, value) */         
151  OPS->setmem.cmdl =     "ms %x %08x\r";         /* setmem.cmdl (addr, value) */         
152  OPS->setmem.cmdll =     NULL;                  /* setmem.cmdll (addr, value) */        
153  OPS->setmem.resp_delim =     NULL;                     /* setreg.resp_delim */         
154  OPS->setmem.term =     NULL;                   /* setreg.term */                       
155  OPS->setmem.term_cmd =     NULL;                       /* setreg.term_cmd */           
156  OPS->getmem.cmdb =     "md %x:%x;b\r";         /* getmem.cmdb (addr, len) */           
157  OPS->getmem.cmdw =     "md %x:%x;b\r";         /* getmem.cmdw (addr, len) */           
158  OPS->getmem.cmdl =     "md %x:%x;b\r";         /* getmem.cmdl (addr, len) */           
159  OPS->getmem.cmdll =     NULL;                  /* getmem.cmdll (addr, len) */          
160  OPS->getmem.resp_delim =     " ";                      /* getmem.resp_delim */         
161  OPS->getmem.term =     NULL;                   /* getmem.term */                       
162  OPS->getmem.term_cmd =     NULL;                       /* getmem.term_cmd */           
163  OPS->setreg.cmd =     "rs %s %x\r";            /* setreg.cmd (name, value) */          
164  OPS->setreg.resp_delim =     NULL;                     /* setreg.resp_delim */         
165  OPS->setreg.term =     NULL;                   /* setreg.term */                       
166  OPS->setreg.term_cmd =     NULL        ;               /* setreg.term_cmd */                   
167  OPS->getreg.cmd =     "rs %s\r";                       /* getreg.cmd (name) */         
168  OPS->getreg.resp_delim =     "=";                      /* getreg.resp_delim */         
169  OPS->getreg.term =     NULL;                   /* getreg.term */                       
170  OPS->getreg.term_cmd =     NULL        ;               /* getreg.term_cmd */                   
171  OPS->register_pattern =   "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)"; /* register_pattern */ 
172  OPS->supply_register =   ppcbug_supply_register;       /* supply_register */           
173  OPS->load_routine =   NULL;                    /* load_routine (defaults to SRECs) */  
174  OPS->load =   LOAD_CMD;                        /* download command */                          
175  OPS->loadresp =   NULL;                                /* load response */                     
176  OPS->prompt =   "PPC1-Bug>";                   /* monitor command prompt */            
177  OPS->line_term =   "\r";                               /* end-of-line terminator */    
178  OPS->cmd_end =   NULL;                         /* optional command terminator */       
179  OPS->target =   targops ;                              /* target operations */                 
180  OPS->stopbits =   SERIAL_1_STOPBITS;           /* number of stop bits */               
181  OPS->regnames =   ppcbug_regnames;             /* registers names */                   
182  OPS->magic =   MONITOR_OPS_MAGIC       ;       /* magic */                             
183 }
184
185
186 static struct monitor_ops ppcbug_cmds0 ;
187 static struct monitor_ops ppcbug_cmds1 ;
188
189 static void
190 ppcbug_open0(args, from_tty)
191      char *args;
192      int from_tty;
193 {
194   monitor_open (args, &ppcbug_cmds0, from_tty);
195 }
196
197 static void
198 ppcbug_open1(args, from_tty)
199      char *args;
200      int from_tty;
201 {
202   monitor_open (args, &ppcbug_cmds1, from_tty);
203 }
204
205 void
206 _initialize_ppcbug_rom ()
207 {
208   init_ppc_cmds("lo 0\r", &ppcbug_cmds0, &ppcbug_ops0) ;
209   init_ppc_cmds("lo 1\r", &ppcbug_cmds1, &ppcbug_ops1);
210   init_monitor_ops (&ppcbug_ops0);
211
212   ppcbug_ops0.to_shortname = "ppcbug";
213   ppcbug_ops0.to_longname = "PowerPC PPCBug monitor on port 0";
214   ppcbug_ops0.to_doc = "Debug via the PowerPC PPCBug monitor using port 0.\n\
215 Specify the serial device it is connected to (e.g. /dev/ttya).";
216   ppcbug_ops0.to_open = ppcbug_open0;
217
218   add_target (&ppcbug_ops0);
219
220   init_monitor_ops (&ppcbug_ops1);
221
222   ppcbug_ops1.to_shortname = "ppcbug1";
223   ppcbug_ops1.to_longname = "PowerPC PPCBug monitor on port 1";
224   ppcbug_ops1.to_doc = "Debug via the PowerPC PPCBug monitor using port 1.\n\
225 Specify the serial device it is connected to (e.g. /dev/ttya).";
226   ppcbug_ops1.to_open = ppcbug_open1;
227
228   add_target (&ppcbug_ops1);
229 }