Sun Aug 10 16:49:09 1997 Geoffrey Noer <noer@cygnus.com>
[platform/upstream/binutils.git] / gdb / ppc-bdm.c
1 /* Remote target communications for the Macraigor Systems BDM Wiggler
2    talking to a Motorola PPC 505.
3    Copyright 1996, 1997 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #include "defs.h"
22 #include "gdbcore.h"
23 #include "gdb_string.h"
24 #include <fcntl.h>
25 #include "frame.h"
26 #include "inferior.h"
27 #include "bfd.h"
28 #include "symfile.h"
29 #include "target.h"
30 #include "wait.h"
31 #include "gdbcmd.h"
32 #include "objfiles.h"
33 #include "gdb-stabs.h"
34 #include <sys/types.h>
35 #include <signal.h>
36 #include "serial.h"
37 #include "ocd.h"
38
39 static void bdm_ppc_open PARAMS ((char *name, int from_tty));
40
41 static int bdm_ppc_wait PARAMS ((int pid,
42                                  struct target_waitstatus *target_status));
43
44 static void bdm_ppc_fetch_registers PARAMS ((int regno));
45
46 static void bdm_ppc_store_registers PARAMS ((int regno));
47
48 extern struct target_ops bdm_ppc_ops;   /* Forward decl */
49 \f
50 /* Open a connection to a remote debugger.
51    NAME is the filename used for communication.  */
52
53 char nowatchdog[4] = {0xff,0xff,0xff,0x88};
54
55 static void
56 bdm_ppc_open (name, from_tty)
57      char *name;
58      int from_tty;
59 {
60   CORE_ADDR watchdogaddr = 0xff000004;
61
62   ocd_open (name, from_tty, OCD_TARGET_MOTO_PPC, &bdm_ppc_ops);
63
64   /* We want interrupts to drop us into debugging mode. */
65   /* Modify the DER register to accomplish this. */
66   ocd_write_bdm_register (149, 0x20024000);
67
68   /* Disable watchdog timer on the board */
69   ocd_write_bytes (watchdogaddr, nowatchdog, 4);
70 }
71
72 /* Wait until the remote machine stops, then return,
73    storing status in STATUS just as `wait' would.
74    Returns "pid" (though it's not clear what, if anything, that
75    means in the case of this target).  */
76
77 static int
78 bdm_ppc_wait (pid, target_status)
79      int pid;
80      struct target_waitstatus *target_status;
81 {
82   int stop_reason;
83
84   target_status->kind = TARGET_WAITKIND_STOPPED;
85
86   stop_reason = ocd_wait ();
87
88   if (stop_reason)
89     {
90       target_status->value.sig = TARGET_SIGNAL_INT;
91       return inferior_pid;
92     }
93
94   target_status->value.sig = TARGET_SIGNAL_TRAP; /* XXX for now */
95
96   {
97     unsigned long ecr, der;
98
99     ecr = ocd_read_bdm_register (148); /* Read the exception cause register */
100     der = ocd_read_bdm_register (149); /* Read the debug enables register */
101     fprintf_unfiltered (gdb_stdout, "ecr = 0x%x, der = 0x%x\n", ecr, der);
102   }
103
104   return inferior_pid;
105 }
106 \f
107 static int bdm_regmap[] = {BDM_REGMAP};
108
109 /* Read the remote registers into regs.
110
111    The Wiggler uses the following codes to access the registers:
112
113    0 -> 1023            SPR 0 -> 1023
114         0 - SPR 0 - MQ
115         1 - SPR 1 - XER
116         8 - SPR 8 - LR
117         9 - SPR 9 - CTR (known as cnt in GDB)
118         26 - SPR 26 - SRR0 - pc
119    1024 -> 2047         DCR 0 -> DCR 1023 (IBM PPC 4xx only)
120    2048 -> 2079         R0 -> R31
121    2080 -> 2143         FP0 -> FP31 (64 bit regs)
122    2144                 CR (known as cnd in GDB)
123    2145                 FPCSR
124    2146                 MSR (known as ps in GDB)
125  */
126
127 static void
128 bdm_ppc_fetch_registers (regno)
129      int regno;
130 {
131   int i;
132   unsigned char *regs;
133   int first_regno, last_regno;
134   int first_bdm_regno, last_bdm_regno;
135   int reglen;
136
137   if (regno == -1)
138     {
139       first_regno = 0;
140       last_regno = NUM_REGS - 1;
141
142       first_bdm_regno = 0;
143       last_bdm_regno = BDM_NUM_REGS - 1;
144     }
145   else
146     {
147       first_regno = regno;
148       last_regno = regno;
149
150       first_bdm_regno = bdm_regmap [regno];
151       last_bdm_regno = bdm_regmap [regno];
152     }
153
154   if (first_bdm_regno == -1)
155     {
156       supply_register (first_regno, NULL);
157       return;                   /* Unsupported register */
158     }
159
160   regs = ocd_read_bdm_registers (first_bdm_regno, last_bdm_regno, &reglen);
161
162   for (i = first_regno; i <= last_regno; i++)
163     {
164       int bdm_regno, regoffset;
165
166       bdm_regno = bdm_regmap [i];
167       if (bdm_regno != -1)
168         {
169           regoffset = bdm_regno - first_bdm_regno;
170
171           if (regoffset >= reglen / 4)
172             continue;
173
174           supply_register (i, regs + 4 * regoffset);
175         }
176       else
177         supply_register (i, NULL); /* Unsupported register */
178     }
179 }
180
181 /* Store register REGNO, or all registers if REGNO == -1, from the contents
182    of REGISTERS.  FIXME: ignores errors.  */
183
184 static void
185 bdm_ppc_store_registers (regno)
186      int regno;
187 {
188   int i;
189   int first_regno, last_regno;
190   int first_bdm_regno, last_bdm_regno;
191
192   if (regno == -1)
193     {
194       first_regno = 0;
195       last_regno = NUM_REGS - 1;
196
197       first_bdm_regno = 0;
198       last_bdm_regno = BDM_NUM_REGS - 1;
199     }
200   else
201     {
202       first_regno = regno;
203       last_regno = regno;
204
205       first_bdm_regno = bdm_regmap [regno];
206       last_bdm_regno = bdm_regmap [regno];
207     }
208
209   if (first_bdm_regno == -1)
210     return;                     /* Unsupported register */
211
212   for (i = first_regno; i <= last_regno; i++)
213     {
214       int bdm_regno;
215
216       bdm_regno = bdm_regmap [i];
217
218       ocd_write_bdm_registers (bdm_regno, registers + REGISTER_BYTE (i), 4);
219     }
220 }
221 \f
222 /* Define the target subroutine names */
223
224 struct target_ops bdm_ppc_ops = {
225   "ocd",                        /* to_shortname */
226   "",                           /* to_longname */
227   "",                           /* to_doc */
228   bdm_ppc_open,                 /* to_open */
229   ocd_close,            /* to_close */
230   NULL,                         /* to_attach */
231   ocd_detach,           /* to_detach */
232   ocd_resume,           /* to_resume */
233   bdm_ppc_wait,                 /* to_wait */
234   bdm_ppc_fetch_registers,      /* to_fetch_registers */
235   bdm_ppc_store_registers,      /* to_store_registers */
236   ocd_prepare_to_store, /* to_prepare_to_store */
237   ocd_xfer_memory,              /* to_xfer_memory */
238   ocd_files_info,               /* to_files_info */
239   ocd_insert_breakpoint,        /* to_insert_breakpoint */
240   ocd_remove_breakpoint,        /* to_remove_breakpoint */
241   NULL,                         /* to_terminal_init */
242   NULL,                         /* to_terminal_inferior */
243   NULL,                         /* to_terminal_ours_for_output */
244   NULL,                         /* to_terminal_ours */
245   NULL,                         /* to_terminal_info */
246   ocd_kill,                     /* to_kill */
247   ocd_load,                     /* to_load */
248   NULL,                         /* to_lookup_symbol */
249   ocd_create_inferior,  /* to_create_inferior */
250   ocd_mourn,            /* to_mourn_inferior */
251   0,                            /* to_can_run */
252   0,                            /* to_notice_signals */
253   ocd_thread_alive,             /* to_thread_alive */
254   ocd_stop,                     /* to_stop */
255   process_stratum,              /* to_stratum */
256   NULL,                         /* to_next */
257   1,                            /* to_has_all_memory */
258   1,                            /* to_has_memory */
259   1,                            /* to_has_stack */
260   1,                            /* to_has_registers */
261   1,                            /* to_has_execution */
262   NULL,                         /* sections */
263   NULL,                         /* sections_end */
264   OPS_MAGIC                     /* to_magic */
265 };
266
267 void
268 _initialize_bdm_ppc ()
269 {
270   add_target (&bdm_ppc_ops);
271 }