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