Wed Aug 6 16:15:31 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 static void
54 bdm_ppc_open (name, from_tty)
55      char *name;
56      int from_tty;
57 {
58   wiggler_open (name, from_tty, WIGGLER_TARGET_MOTO_PPC, &bdm_ppc_ops);
59 }
60
61 /* Wait until the remote machine stops, then return,
62    storing status in STATUS just as `wait' would.
63    Returns "pid" (though it's not clear what, if anything, that
64    means in the case of this target).  */
65
66 static int
67 bdm_ppc_wait (pid, target_status)
68      int pid;
69      struct target_waitstatus *target_status;
70 {
71   int stop_reason;
72
73   target_status->kind = TARGET_WAITKIND_STOPPED;
74
75   stop_reason = wiggler_wait ();
76
77   if (stop_reason)
78     {
79       target_status->value.sig = TARGET_SIGNAL_INT;
80       return inferior_pid;
81     }
82
83   target_status->value.sig = TARGET_SIGNAL_TRAP; /* XXX for now */
84
85   {
86     unsigned long ecr, der;
87
88     ecr = wiggler_read_bdm_register (148); /* Read the exception cause register */
89     der = wiggler_read_bdm_register (149); /* Read the debug enables register */
90     fprintf_unfiltered (gdb_stdout, "ecr = 0x%x, der = 0x%x\n", ecr, der);
91   }
92
93   return inferior_pid;
94 }
95 \f
96 static int bdm_regmap[] = {BDM_REGMAP};
97
98 /* Read the remote registers into regs.
99
100    The Wiggler uses the following codes to access the registers:
101
102    0 -> 1023            SPR 0 -> 1023
103         0 - SPR 0 - MQ
104         1 - SPR 1 - XER
105         8 - SPR 8 - LR
106         9 - SPR 9 - CTR (known as cnt in GDB)
107         26 - SPR 26 - SRR0 - pc
108    1024 -> 2047         DCR 0 -> DCR 1023 (IBM PPC 4xx only)
109    2048 -> 2079         R0 -> R31
110    2080 -> 2143         FP0 -> FP31 (64 bit regs)
111    2144                 CR (known as cnd in GDB)
112    2145                 FPCSR
113    2146                 MSR (known as ps in GDB)
114  */
115
116 static void
117 bdm_ppc_fetch_registers (regno)
118      int regno;
119 {
120   int i;
121   unsigned char *regs;
122   int first_regno, last_regno;
123   int first_bdm_regno, last_bdm_regno;
124   int reglen;
125
126   if (regno == -1)
127     {
128       first_regno = 0;
129       last_regno = NUM_REGS - 1;
130
131       first_bdm_regno = 0;
132       last_bdm_regno = BDM_NUM_REGS - 1;
133     }
134   else
135     {
136       first_regno = regno;
137       last_regno = regno;
138
139       first_bdm_regno = bdm_regmap [regno];
140       last_bdm_regno = bdm_regmap [regno];
141     }
142
143   if (first_bdm_regno == -1)
144     {
145       supply_register (first_regno, NULL);
146       return;                   /* Unsupported register */
147     }
148
149   regs = wiggler_read_bdm_registers (first_bdm_regno, last_bdm_regno, &reglen);
150
151   for (i = first_regno; i <= last_regno; i++)
152     {
153       int bdm_regno, regoffset;
154
155       bdm_regno = bdm_regmap [i];
156       if (bdm_regno != -1)
157         {
158           regoffset = bdm_regno - first_bdm_regno;
159
160           if (regoffset >= reglen / 4)
161             continue;
162
163           supply_register (i, regs + 4 * regoffset);
164         }
165       else
166         supply_register (i, NULL); /* Unsupported register */
167     }
168 }
169
170 /* Store register REGNO, or all registers if REGNO == -1, from the contents
171    of REGISTERS.  FIXME: ignores errors.  */
172
173 static void
174 bdm_ppc_store_registers (regno)
175      int regno;
176 {
177   int i;
178   int first_regno, last_regno;
179   int first_bdm_regno, last_bdm_regno;
180
181   if (regno == -1)
182     {
183       first_regno = 0;
184       last_regno = NUM_REGS - 1;
185
186       first_bdm_regno = 0;
187       last_bdm_regno = BDM_NUM_REGS - 1;
188     }
189   else
190     {
191       first_regno = regno;
192       last_regno = regno;
193
194       first_bdm_regno = bdm_regmap [regno];
195       last_bdm_regno = bdm_regmap [regno];
196     }
197
198   if (first_bdm_regno == -1)
199     return;                     /* Unsupported register */
200
201   for (i = first_regno; i <= last_regno; i++)
202     {
203       int bdm_regno;
204
205       bdm_regno = bdm_regmap [i];
206
207       wiggler_write_bdm_registers (bdm_regno, registers + REGISTER_BYTE (i), 4);
208     }
209 }
210 \f
211 /* Define the target subroutine names */
212
213 struct target_ops bdm_ppc_ops = {
214   "wiggler",                    /* to_shortname */
215   "",                           /* to_longname */
216   "",                           /* to_doc */
217   bdm_ppc_open,                 /* to_open */
218   wiggler_close,                /* to_close */
219   NULL,                         /* to_attach */
220   wiggler_detach,               /* to_detach */
221   wiggler_resume,               /* to_resume */
222   bdm_ppc_wait,                 /* to_wait */
223   bdm_ppc_fetch_registers,      /* to_fetch_registers */
224   bdm_ppc_store_registers,      /* to_store_registers */
225   wiggler_prepare_to_store,     /* to_prepare_to_store */
226   wiggler_xfer_memory,          /* to_xfer_memory */
227   wiggler_files_info,           /* to_files_info */
228   memory_insert_breakpoint,     /* to_insert_breakpoint */
229   memory_remove_breakpoint,     /* to_remove_breakpoint */
230   NULL,                         /* to_terminal_init */
231   NULL,                         /* to_terminal_inferior */
232   NULL,                         /* to_terminal_ours_for_output */
233   NULL,                         /* to_terminal_ours */
234   NULL,                         /* to_terminal_info */
235   wiggler_kill,                 /* to_kill */
236   wiggler_load,                 /* to_load */
237   NULL,                         /* to_lookup_symbol */
238   wiggler_create_inferior,      /* to_create_inferior */
239   wiggler_mourn,                /* to_mourn_inferior */
240   0,                            /* to_can_run */
241   0,                            /* to_notice_signals */
242   wiggler_thread_alive,         /* to_thread_alive */
243   wiggler_stop,                 /* to_stop */
244   process_stratum,              /* to_stratum */
245   NULL,                         /* to_next */
246   1,                            /* to_has_all_memory */
247   1,                            /* to_has_memory */
248   1,                            /* to_has_stack */
249   1,                            /* to_has_registers */
250   1,                            /* to_has_execution */
251   NULL,                         /* sections */
252   NULL,                         /* sections_end */
253   OPS_MAGIC                     /* to_magic */
254 };
255
256 void
257 _initialize_bdm_ppc ()
258 {
259   add_target (&bdm_ppc_ops);
260 }