]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/ppc-bdm.c
Protoization.
[thirdparty/binutils-gdb.git] / gdb / ppc-bdm.c
CommitLineData
c906108c
SS
1/* Remote target communications for the Macraigor Systems BDM Wiggler
2 talking to a Motorola PPC 8xx ADS board
3 Copyright 1996, 1997 Free Software Foundation, Inc.
4
c5aa993b 5 This file is part of GDB.
c906108c 6
c5aa993b
JM
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.
c906108c 11
c5aa993b
JM
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.
c906108c 16
c5aa993b
JM
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,
20 Boston, MA 02111-1307, USA. */
c906108c
SS
21
22#include "defs.h"
23#include "gdbcore.h"
24#include "gdb_string.h"
25#include <fcntl.h>
26#include "frame.h"
27#include "inferior.h"
28#include "bfd.h"
29#include "symfile.h"
30#include "target.h"
03f2053f 31#include "gdb_wait.h"
c906108c
SS
32#include "gdbcmd.h"
33#include "objfiles.h"
34#include "gdb-stabs.h"
35#include <sys/types.h>
36#include <signal.h>
37#include "serial.h"
38#include "ocd.h"
39
a14ed312 40static void bdm_ppc_open (char *name, int from_tty);
c906108c 41
a14ed312 42static int bdm_ppc_wait (int pid, struct target_waitstatus *target_status);
c906108c 43
a14ed312 44static void bdm_ppc_fetch_registers (int regno);
c906108c 45
a14ed312 46static void bdm_ppc_store_registers (int regno);
c906108c
SS
47
48extern struct target_ops bdm_ppc_ops; /* Forward decl */
49\f
c5aa993b 50/*#define BDM_NUM_REGS 71 */
c906108c
SS
51#define BDM_NUM_REGS 24
52
53#define BDM_REGMAP \
54 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, /* r0-r7 */ \
55 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, /* r8-r15 */ \
56 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, /* r16-r23 */ \
57 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, /* r24-r31 */ \
58\
59 2080, 2082, 2084, 2086, 2088, 2090, 2092, 2094, /* fp0->fp8 */ \
60 2096, 2098, 2100, 2102, 2104, 2106, 2108, 2110, /* fp0->fp8 */ \
61 2112, 2114, 2116, 2118, 2120, 2122, 2124, 2126, /* fp0->fp8 */ \
62 2128, 2130, 2132, 2134, 2136, 2138, 2140, 2142, /* fp0->fp8 */ \
63\
64 26, /* pc (SRR0 (SPR 26)) */ \
65 2146, /* ps (MSR) */ \
66 2144, /* cnd (CR) */ \
67 8, /* lr (SPR 8) */ \
68 9, /* cnt (CTR (SPR 9)) */ \
69 1, /* xer (SPR 1) */ \
c5aa993b 70 0, /* mq (SPR 0) */
c906108c 71\f
c5aa993b
JM
72
73char nowatchdog[4] =
74{0xff, 0xff, 0xff, 0x88};
c906108c
SS
75
76/* Open a connection to a remote debugger.
77 NAME is the filename used for communication. */
78
79static void
fba45db2 80bdm_ppc_open (char *name, int from_tty)
c906108c
SS
81{
82 CORE_ADDR watchdogaddr = 0xff000004;
83
84 ocd_open (name, from_tty, OCD_TARGET_MOTO_PPC, &bdm_ppc_ops);
85
86 /* We want interrupts to drop us into debugging mode. */
87 /* Modify the DER register to accomplish this. */
88 ocd_write_bdm_register (149, 0x20024000);
89
90 /* Disable watchdog timer on the board */
91 ocd_write_bytes (watchdogaddr, nowatchdog, 4);
92}
93
94/* Wait until the remote machine stops, then return,
95 storing status in STATUS just as `wait' would.
96 Returns "pid" (though it's not clear what, if anything, that
97 means in the case of this target). */
98
99static int
fba45db2 100bdm_ppc_wait (int pid, struct target_waitstatus *target_status)
c906108c
SS
101{
102 int stop_reason;
103
104 target_status->kind = TARGET_WAITKIND_STOPPED;
105
106 stop_reason = ocd_wait ();
107
108 if (stop_reason)
109 {
110 target_status->value.sig = TARGET_SIGNAL_INT;
111 return inferior_pid;
112 }
113
c5aa993b 114 target_status->value.sig = TARGET_SIGNAL_TRAP; /* XXX for now */
c906108c
SS
115
116#if 0
117 {
118 unsigned long ecr, der;
119
c5aa993b
JM
120 ecr = ocd_read_bdm_register (148); /* Read the exception cause register */
121 der = ocd_read_bdm_register (149); /* Read the debug enables register */
c906108c
SS
122 fprintf_unfiltered (gdb_stdout, "ecr = 0x%x, der = 0x%x\n", ecr, der);
123 }
124#endif
125
126 return inferior_pid;
127}
128\f
c5aa993b
JM
129static int bdm_regmap[] =
130{BDM_REGMAP};
c906108c
SS
131
132/* Read the remote registers into regs.
133 Fetch register REGNO, or all registers if REGNO == -1
134
135 The Wiggler uses the following codes to access the registers:
136
c5aa993b
JM
137 0 -> 1023 SPR 0 -> 1023
138 0 - SPR 0 - MQ
139 1 - SPR 1 - XER
140 8 - SPR 8 - LR
141 9 - SPR 9 - CTR (known as cnt in GDB)
142 26 - SPR 26 - SRR0 - pc
143 1024 -> 2047 DCR 0 -> DCR 1023 (IBM PPC 4xx only)
144 2048 -> 2079 R0 -> R31
145 2080 -> 2143 FP0 -> FP31 (64 bit regs) (IBM PPC 5xx only)
146 2144 CR (known as cnd in GDB)
147 2145 FPCSR
148 2146 MSR (known as ps in GDB)
c906108c
SS
149 */
150
151static void
fba45db2 152bdm_ppc_fetch_registers (int regno)
c906108c
SS
153{
154 int i;
155 unsigned char *regs, *beginregs, *endregs, *almostregs;
156 unsigned char midregs[32];
157 unsigned char mqreg[1];
158 int first_regno, last_regno;
159 int first_bdm_regno, last_bdm_regno;
160 int reglen, beginreglen, endreglen;
161
162#if 1
163 for (i = 0; i < (FPLAST_REGNUM - FP0_REGNUM + 1); i++)
164 {
165 midregs[i] = -1;
166 }
167 mqreg[0] = -1;
168#endif
169
170 if (regno == -1)
171 {
172 first_regno = 0;
173 last_regno = NUM_REGS - 1;
174
175 first_bdm_regno = 0;
176 last_bdm_regno = BDM_NUM_REGS - 1;
177 }
178 else
179 {
180 first_regno = regno;
181 last_regno = regno;
182
c5aa993b
JM
183 first_bdm_regno = bdm_regmap[regno];
184 last_bdm_regno = bdm_regmap[regno];
c906108c
SS
185 }
186
187 if (first_bdm_regno == -1)
188 {
189 supply_register (first_regno, NULL);
190 return; /* Unsupported register */
191 }
192
193#if 1
194 /* Can't ask for floating point regs on ppc 8xx, also need to
195 avoid asking for the mq register. */
196 if (first_regno == last_regno) /* only want one reg */
197 {
198/* printf("Asking for register %d\n", first_regno); */
199
200 /* if asking for an invalid register */
201 if ((first_regno == MQ_REGNUM) ||
c5aa993b 202 ((first_regno >= FP0_REGNUM) && (first_regno <= FPLAST_REGNUM)))
c906108c
SS
203 {
204/* printf("invalid reg request!\n"); */
c5aa993b
JM
205 supply_register (first_regno, NULL);
206 return; /* Unsupported register */
207 }
c906108c
SS
208 else
209 {
c5aa993b
JM
210 regs = ocd_read_bdm_registers (first_bdm_regno,
211 last_bdm_regno, &reglen);
212 }
c906108c 213 }
c5aa993b
JM
214 else
215 /* want all regs */
c906108c
SS
216 {
217/* printf("Asking for registers %d to %d\n", first_regno, last_regno); */
218 beginregs = ocd_read_bdm_registers (first_bdm_regno,
c5aa993b
JM
219 FP0_REGNUM - 1, &beginreglen);
220 endregs = (strcat (midregs,
221 ocd_read_bdm_registers (FPLAST_REGNUM + 1,
222 last_bdm_regno - 1, &endreglen)));
c906108c
SS
223 almostregs = (strcat (beginregs, endregs));
224 regs = (strcat (almostregs, mqreg));
225 reglen = beginreglen + 32 + endreglen + 1;
226 }
227
228#endif
229#if 0
230 regs = ocd_read_bdm_registers (first_bdm_regno, last_bdm_regno, &reglen);
231#endif
232
233 for (i = first_regno; i <= last_regno; i++)
234 {
235 int bdm_regno, regoffset;
236
c5aa993b 237 bdm_regno = bdm_regmap[i];
c906108c
SS
238 if (bdm_regno != -1)
239 {
240 regoffset = bdm_regno - first_bdm_regno;
241
242 if (regoffset >= reglen / 4)
243 continue;
244
245 supply_register (i, regs + 4 * regoffset);
246 }
247 else
c5aa993b 248 supply_register (i, NULL); /* Unsupported register */
c906108c
SS
249 }
250}
251
252/* Store register REGNO, or all registers if REGNO == -1, from the contents
253 of REGISTERS. FIXME: ignores errors. */
254
255static void
fba45db2 256bdm_ppc_store_registers (int regno)
c906108c
SS
257{
258 int i;
259 int first_regno, last_regno;
260 int first_bdm_regno, last_bdm_regno;
261
262 if (regno == -1)
263 {
264 first_regno = 0;
265 last_regno = NUM_REGS - 1;
266
267 first_bdm_regno = 0;
268 last_bdm_regno = BDM_NUM_REGS - 1;
269 }
270 else
271 {
272 first_regno = regno;
273 last_regno = regno;
274
c5aa993b
JM
275 first_bdm_regno = bdm_regmap[regno];
276 last_bdm_regno = bdm_regmap[regno];
c906108c
SS
277 }
278
279 if (first_bdm_regno == -1)
280 return; /* Unsupported register */
281
282 for (i = first_regno; i <= last_regno; i++)
283 {
284 int bdm_regno;
285
c5aa993b 286 bdm_regno = bdm_regmap[i];
c906108c
SS
287
288 /* only attempt to write if it's a valid ppc 8xx register */
289 /* (need to avoid FP regs and MQ reg) */
290 if ((i != MQ_REGNUM) && ((i < FP0_REGNUM) || (i > FPLAST_REGNUM)))
291 {
292/* printf("write valid reg %d\n", bdm_regno); */
c5aa993b
JM
293 ocd_write_bdm_registers (bdm_regno, registers + REGISTER_BYTE (i), 4);
294 }
c906108c 295/*
c5aa993b
JM
296 else if (i == MQ_REGNUM)
297 printf("don't write invalid reg %d (MQ_REGNUM)\n", bdm_regno);
298 else
299 printf("don't write invalid reg %d\n", bdm_regno);
300 */
c906108c
SS
301 }
302}
303\f
304/* Define the target subroutine names */
305
c5aa993b 306struct target_ops bdm_ppc_ops;
c906108c 307
c5aa993b
JM
308static void
309init_bdm_ppc_ops (void)
c906108c 310{
c5aa993b
JM
311 bdm_ppc_ops.to_shortname = "ocd";
312 bdm_ppc_ops.to_longname = "Remote target with On-Chip Debugging";
313 bdm_ppc_ops.to_doc = "Use a remote target with On-Chip Debugging. To use a target box;\n\
c906108c
SS
314specify the serial device it is connected to (e.g. /dev/ttya). To use\n\
315a wiggler, specify wiggler and then the port it is connected to\n\
c5aa993b
JM
316(e.g. wiggler lpt1)."; /* to_doc */
317 bdm_ppc_ops.to_open = bdm_ppc_open;
318 bdm_ppc_ops.to_close = ocd_close;
319 bdm_ppc_ops.to_attach = NULL;
c906108c
SS
320 bdm_ppc_ops.to_post_attach = NULL;
321 bdm_ppc_ops.to_require_attach = NULL;
c5aa993b 322 bdm_ppc_ops.to_detach = ocd_detach;
c906108c 323 bdm_ppc_ops.to_require_detach = NULL;
c5aa993b
JM
324 bdm_ppc_ops.to_resume = ocd_resume;
325 bdm_ppc_ops.to_wait = bdm_ppc_wait;
c906108c 326 bdm_ppc_ops.to_post_wait = NULL;
c5aa993b
JM
327 bdm_ppc_ops.to_fetch_registers = bdm_ppc_fetch_registers;
328 bdm_ppc_ops.to_store_registers = bdm_ppc_store_registers;
329 bdm_ppc_ops.to_prepare_to_store = ocd_prepare_to_store;
330 bdm_ppc_ops.to_xfer_memory = ocd_xfer_memory;
331 bdm_ppc_ops.to_files_info = ocd_files_info;
332 bdm_ppc_ops.to_insert_breakpoint = ocd_insert_breakpoint;
333 bdm_ppc_ops.to_remove_breakpoint = ocd_remove_breakpoint;
334 bdm_ppc_ops.to_terminal_init = NULL;
335 bdm_ppc_ops.to_terminal_inferior = NULL;
336 bdm_ppc_ops.to_terminal_ours_for_output = NULL;
337 bdm_ppc_ops.to_terminal_ours = NULL;
338 bdm_ppc_ops.to_terminal_info = NULL;
339 bdm_ppc_ops.to_kill = ocd_kill;
340 bdm_ppc_ops.to_load = ocd_load;
341 bdm_ppc_ops.to_lookup_symbol = NULL;
342 bdm_ppc_ops.to_create_inferior = ocd_create_inferior;
c906108c
SS
343 bdm_ppc_ops.to_post_startup_inferior = NULL;
344 bdm_ppc_ops.to_acknowledge_created_inferior = NULL;
c5aa993b
JM
345 bdm_ppc_ops.to_clone_and_follow_inferior = NULL;
346 bdm_ppc_ops.to_post_follow_inferior_by_clone = NULL;
c906108c
SS
347 bdm_ppc_ops.to_insert_fork_catchpoint = NULL;
348 bdm_ppc_ops.to_remove_fork_catchpoint = NULL;
349 bdm_ppc_ops.to_insert_vfork_catchpoint = NULL;
c5aa993b 350 bdm_ppc_ops.to_remove_vfork_catchpoint = NULL;
c906108c 351 bdm_ppc_ops.to_has_forked = NULL;
c5aa993b
JM
352 bdm_ppc_ops.to_has_vforked = NULL;
353 bdm_ppc_ops.to_can_follow_vfork_prior_to_exec = NULL;
c906108c
SS
354 bdm_ppc_ops.to_post_follow_vfork = NULL;
355 bdm_ppc_ops.to_insert_exec_catchpoint = NULL;
356 bdm_ppc_ops.to_remove_exec_catchpoint = NULL;
357 bdm_ppc_ops.to_has_execd = NULL;
358 bdm_ppc_ops.to_reported_exec_events_per_exec_call = NULL;
359 bdm_ppc_ops.to_has_exited = NULL;
c5aa993b
JM
360 bdm_ppc_ops.to_mourn_inferior = ocd_mourn;
361 bdm_ppc_ops.to_can_run = 0;
362 bdm_ppc_ops.to_notice_signals = 0;
363 bdm_ppc_ops.to_thread_alive = ocd_thread_alive;
364 bdm_ppc_ops.to_stop = ocd_stop;
c906108c 365 bdm_ppc_ops.to_pid_to_exec_file = NULL;
c5aa993b
JM
366 bdm_ppc_ops.to_core_file_to_sym_file = NULL;
367 bdm_ppc_ops.to_stratum = process_stratum;
368 bdm_ppc_ops.DONT_USE = NULL;
369 bdm_ppc_ops.to_has_all_memory = 1;
370 bdm_ppc_ops.to_has_memory = 1;
371 bdm_ppc_ops.to_has_stack = 1;
372 bdm_ppc_ops.to_has_registers = 1;
373 bdm_ppc_ops.to_has_execution = 1;
374 bdm_ppc_ops.to_sections = NULL;
375 bdm_ppc_ops.to_sections_end = NULL;
376 bdm_ppc_ops.to_magic = OPS_MAGIC;
377} /* init_bdm_ppc_ops */
c906108c
SS
378
379void
fba45db2 380_initialize_bdm_ppc (void)
c906108c 381{
c5aa993b 382 init_bdm_ppc_ops ();
c906108c
SS
383 add_target (&bdm_ppc_ops);
384}