1b725ae77Skettenis /* Remote target communications for the Macraigor Systems BDM Wiggler
2b725ae77Skettenis talking to a Motorola PPC 8xx ADS board
3b725ae77Skettenis Copyright 1996, 1997, 1998, 1999, 2000, 2001
4b725ae77Skettenis Free Software Foundation, Inc.
5b725ae77Skettenis
6b725ae77Skettenis This file is part of GDB.
7b725ae77Skettenis
8b725ae77Skettenis This program is free software; you can redistribute it and/or modify
9b725ae77Skettenis it under the terms of the GNU General Public License as published by
10b725ae77Skettenis the Free Software Foundation; either version 2 of the License, or
11b725ae77Skettenis (at your option) any later version.
12b725ae77Skettenis
13b725ae77Skettenis This program is distributed in the hope that it will be useful,
14b725ae77Skettenis but WITHOUT ANY WARRANTY; without even the implied warranty of
15b725ae77Skettenis MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16b725ae77Skettenis GNU General Public License for more details.
17b725ae77Skettenis
18b725ae77Skettenis You should have received a copy of the GNU General Public License
19b725ae77Skettenis along with this program; if not, write to the Free Software
20b725ae77Skettenis Foundation, Inc., 59 Temple Place - Suite 330,
21b725ae77Skettenis Boston, MA 02111-1307, USA. */
22b725ae77Skettenis
23b725ae77Skettenis #include "defs.h"
24b725ae77Skettenis #include "gdbcore.h"
25b725ae77Skettenis #include "gdb_string.h"
26b725ae77Skettenis #include <fcntl.h>
27b725ae77Skettenis #include "frame.h"
28b725ae77Skettenis #include "inferior.h"
29b725ae77Skettenis #include "bfd.h"
30b725ae77Skettenis #include "symfile.h"
31b725ae77Skettenis #include "target.h"
32b725ae77Skettenis #include "gdbcmd.h"
33b725ae77Skettenis #include "objfiles.h"
34b725ae77Skettenis #include "gdb-stabs.h"
35b725ae77Skettenis #include <sys/types.h>
36b725ae77Skettenis #include "serial.h"
37b725ae77Skettenis #include "ocd.h"
38b725ae77Skettenis #include "ppc-tdep.h"
39b725ae77Skettenis #include "regcache.h"
40*11efff7fSkettenis #include "gdb_assert.h"
41b725ae77Skettenis
42b725ae77Skettenis static void bdm_ppc_open (char *name, int from_tty);
43b725ae77Skettenis
44b725ae77Skettenis static ptid_t bdm_ppc_wait (ptid_t ptid,
45b725ae77Skettenis struct target_waitstatus *target_status);
46b725ae77Skettenis
47b725ae77Skettenis static void bdm_ppc_fetch_registers (int regno);
48b725ae77Skettenis
49b725ae77Skettenis static void bdm_ppc_store_registers (int regno);
50b725ae77Skettenis
51b725ae77Skettenis extern struct target_ops bdm_ppc_ops; /* Forward decl */
52b725ae77Skettenis
53b725ae77Skettenis /*#define BDM_NUM_REGS 71 */
54b725ae77Skettenis #define BDM_NUM_REGS 24
55b725ae77Skettenis
56b725ae77Skettenis #define BDM_REGMAP \
57b725ae77Skettenis 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, /* r0-r7 */ \
58b725ae77Skettenis 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, /* r8-r15 */ \
59b725ae77Skettenis 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, /* r16-r23 */ \
60b725ae77Skettenis 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, /* r24-r31 */ \
61b725ae77Skettenis \
62b725ae77Skettenis 2080, 2082, 2084, 2086, 2088, 2090, 2092, 2094, /* fp0->fp8 */ \
63b725ae77Skettenis 2096, 2098, 2100, 2102, 2104, 2106, 2108, 2110, /* fp0->fp8 */ \
64b725ae77Skettenis 2112, 2114, 2116, 2118, 2120, 2122, 2124, 2126, /* fp0->fp8 */ \
65b725ae77Skettenis 2128, 2130, 2132, 2134, 2136, 2138, 2140, 2142, /* fp0->fp8 */ \
66b725ae77Skettenis \
67b725ae77Skettenis 26, /* pc (SRR0 (SPR 26)) */ \
68b725ae77Skettenis 2146, /* ps (MSR) */ \
69b725ae77Skettenis 2144, /* cnd (CR) */ \
70b725ae77Skettenis 8, /* lr (SPR 8) */ \
71b725ae77Skettenis 9, /* cnt (CTR (SPR 9)) */ \
72b725ae77Skettenis 1, /* xer (SPR 1) */ \
73b725ae77Skettenis 0, /* mq (SPR 0) */
74b725ae77Skettenis
75b725ae77Skettenis
76b725ae77Skettenis char nowatchdog[4] =
77b725ae77Skettenis {0xff, 0xff, 0xff, 0x88};
78b725ae77Skettenis
79b725ae77Skettenis /* Open a connection to a remote debugger.
80b725ae77Skettenis NAME is the filename used for communication. */
81b725ae77Skettenis
82b725ae77Skettenis static void
bdm_ppc_open(char * name,int from_tty)83b725ae77Skettenis bdm_ppc_open (char *name, int from_tty)
84b725ae77Skettenis {
85b725ae77Skettenis CORE_ADDR watchdogaddr = 0xff000004;
86b725ae77Skettenis
87b725ae77Skettenis ocd_open (name, from_tty, OCD_TARGET_MOTO_PPC, &bdm_ppc_ops);
88b725ae77Skettenis
89b725ae77Skettenis /* We want interrupts to drop us into debugging mode. */
90b725ae77Skettenis /* Modify the DER register to accomplish this. */
91b725ae77Skettenis ocd_write_bdm_register (149, 0x20024000);
92b725ae77Skettenis
93b725ae77Skettenis /* Disable watchdog timer on the board */
94b725ae77Skettenis ocd_write_bytes (watchdogaddr, nowatchdog, 4);
95b725ae77Skettenis }
96b725ae77Skettenis
97b725ae77Skettenis /* Wait until the remote machine stops, then return,
98b725ae77Skettenis storing status in STATUS just as `wait' would.
99b725ae77Skettenis Returns "pid" (though it's not clear what, if anything, that
100b725ae77Skettenis means in the case of this target). */
101b725ae77Skettenis
102b725ae77Skettenis static ptid_t
bdm_ppc_wait(ptid_t ptid,struct target_waitstatus * target_status)103b725ae77Skettenis bdm_ppc_wait (ptid_t ptid, struct target_waitstatus *target_status)
104b725ae77Skettenis {
105b725ae77Skettenis int stop_reason;
106b725ae77Skettenis
107b725ae77Skettenis target_status->kind = TARGET_WAITKIND_STOPPED;
108b725ae77Skettenis
109b725ae77Skettenis stop_reason = ocd_wait ();
110b725ae77Skettenis
111b725ae77Skettenis if (stop_reason)
112b725ae77Skettenis {
113b725ae77Skettenis target_status->value.sig = TARGET_SIGNAL_INT;
114b725ae77Skettenis return inferior_ptid;
115b725ae77Skettenis }
116b725ae77Skettenis
117b725ae77Skettenis target_status->value.sig = TARGET_SIGNAL_TRAP; /* XXX for now */
118b725ae77Skettenis
119b725ae77Skettenis #if 0
120b725ae77Skettenis {
121b725ae77Skettenis unsigned long ecr, der;
122b725ae77Skettenis
123b725ae77Skettenis ecr = ocd_read_bdm_register (148); /* Read the exception cause register */
124b725ae77Skettenis der = ocd_read_bdm_register (149); /* Read the debug enables register */
125b725ae77Skettenis fprintf_unfiltered (gdb_stdout, "ecr = 0x%x, der = 0x%x\n", ecr, der);
126b725ae77Skettenis }
127b725ae77Skettenis #endif
128b725ae77Skettenis
129b725ae77Skettenis return inferior_ptid;
130b725ae77Skettenis }
131b725ae77Skettenis
132b725ae77Skettenis static int bdm_regmap[] =
133b725ae77Skettenis {BDM_REGMAP};
134b725ae77Skettenis
135b725ae77Skettenis /* Read the remote registers into regs.
136b725ae77Skettenis Fetch register REGNO, or all registers if REGNO == -1
137b725ae77Skettenis
138b725ae77Skettenis The Wiggler uses the following codes to access the registers:
139b725ae77Skettenis
140b725ae77Skettenis 0 -> 1023 SPR 0 -> 1023
141b725ae77Skettenis 0 - SPR 0 - MQ
142b725ae77Skettenis 1 - SPR 1 - XER
143b725ae77Skettenis 8 - SPR 8 - LR
144b725ae77Skettenis 9 - SPR 9 - CTR (known as cnt in GDB)
145b725ae77Skettenis 26 - SPR 26 - SRR0 - pc
146b725ae77Skettenis 1024 -> 2047 DCR 0 -> DCR 1023 (IBM PPC 4xx only)
147b725ae77Skettenis 2048 -> 2079 R0 -> R31
148b725ae77Skettenis 2080 -> 2143 FP0 -> FP31 (64 bit regs) (IBM PPC 5xx only)
149b725ae77Skettenis 2144 CR (known as cnd in GDB)
150b725ae77Skettenis 2145 FPCSR
151b725ae77Skettenis 2146 MSR (known as ps in GDB)
152b725ae77Skettenis */
153b725ae77Skettenis
154b725ae77Skettenis static void
bdm_ppc_fetch_registers(int regno)155b725ae77Skettenis bdm_ppc_fetch_registers (int regno)
156b725ae77Skettenis {
157*11efff7fSkettenis struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
158b725ae77Skettenis int i;
159*11efff7fSkettenis unsigned char *regs;
160b725ae77Skettenis int first_regno, last_regno;
161b725ae77Skettenis int first_bdm_regno, last_bdm_regno;
162*11efff7fSkettenis int reglen;
163b725ae77Skettenis
164b725ae77Skettenis if (regno == -1)
165b725ae77Skettenis {
166b725ae77Skettenis first_regno = 0;
167b725ae77Skettenis last_regno = NUM_REGS - 1;
168b725ae77Skettenis
169b725ae77Skettenis first_bdm_regno = 0;
170b725ae77Skettenis last_bdm_regno = BDM_NUM_REGS - 1;
171b725ae77Skettenis }
172b725ae77Skettenis else
173b725ae77Skettenis {
174b725ae77Skettenis first_regno = regno;
175b725ae77Skettenis last_regno = regno;
176b725ae77Skettenis
177b725ae77Skettenis first_bdm_regno = bdm_regmap[regno];
178b725ae77Skettenis last_bdm_regno = bdm_regmap[regno];
179b725ae77Skettenis }
180b725ae77Skettenis
181b725ae77Skettenis if (first_bdm_regno == -1)
182b725ae77Skettenis {
183*11efff7fSkettenis regcache_raw_supply (current_regcache, first_regno, NULL);
184b725ae77Skettenis return; /* Unsupported register */
185b725ae77Skettenis }
186b725ae77Skettenis
187*11efff7fSkettenis /* FIXME: jimb/2004-05-04: I'm not sure how to adapt this code to
188*11efff7fSkettenis processors that lack floating point registers, and I don't have
189*11efff7fSkettenis have the equipment to test it. So we'll leave that case for the
190*11efff7fSkettenis next person who encounters it. */
191*11efff7fSkettenis gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
192*11efff7fSkettenis
193b725ae77Skettenis #if 1
194b725ae77Skettenis /* Can't ask for floating point regs on ppc 8xx, also need to
195b725ae77Skettenis avoid asking for the mq register. */
196b725ae77Skettenis if (first_regno == last_regno) /* only want one reg */
197b725ae77Skettenis {
198b725ae77Skettenis /* printf("Asking for register %d\n", first_regno); */
199b725ae77Skettenis
200b725ae77Skettenis /* if asking for an invalid register */
201b725ae77Skettenis if ((first_regno == gdbarch_tdep (current_gdbarch)->ppc_mq_regnum)
202b725ae77Skettenis || (first_regno == gdbarch_tdep (current_gdbarch)->ppc_fpscr_regnum)
203*11efff7fSkettenis || ((first_regno >= tdep->ppc_fp0_regnum)
204*11efff7fSkettenis && (first_regno < tdep->ppc_fp0_regnum + ppc_num_fprs)))
205b725ae77Skettenis {
206b725ae77Skettenis /* printf("invalid reg request!\n"); */
207*11efff7fSkettenis regcache_raw_supply (current_regcache, first_regno, NULL);
208b725ae77Skettenis return; /* Unsupported register */
209b725ae77Skettenis }
210b725ae77Skettenis else
211b725ae77Skettenis {
212b725ae77Skettenis regs = ocd_read_bdm_registers (first_bdm_regno,
213b725ae77Skettenis last_bdm_regno, ®len);
214b725ae77Skettenis }
215b725ae77Skettenis }
216b725ae77Skettenis else
217*11efff7fSkettenis internal_error (__FILE__, __LINE__,
218*11efff7fSkettenis "ppc_bdm_fetch_registers: "
219*11efff7fSkettenis "'all registers' case not implemented");
220b725ae77Skettenis
221b725ae77Skettenis #endif
222b725ae77Skettenis #if 0
223b725ae77Skettenis regs = ocd_read_bdm_registers (first_bdm_regno, last_bdm_regno, ®len);
224b725ae77Skettenis #endif
225b725ae77Skettenis
226b725ae77Skettenis for (i = first_regno; i <= last_regno; i++)
227b725ae77Skettenis {
228b725ae77Skettenis int bdm_regno, regoffset;
229b725ae77Skettenis
230b725ae77Skettenis bdm_regno = bdm_regmap[i];
231b725ae77Skettenis if (bdm_regno != -1)
232b725ae77Skettenis {
233b725ae77Skettenis regoffset = bdm_regno - first_bdm_regno;
234b725ae77Skettenis
235b725ae77Skettenis if (regoffset >= reglen / 4)
236b725ae77Skettenis continue;
237b725ae77Skettenis
238*11efff7fSkettenis regcache_raw_supply (current_regcache, i, regs + 4 * regoffset);
239b725ae77Skettenis }
240b725ae77Skettenis else
241*11efff7fSkettenis regcache_raw_supply (current_regcache, i, NULL); /* Unsupported register */
242b725ae77Skettenis }
243b725ae77Skettenis }
244b725ae77Skettenis
245b725ae77Skettenis /* Store register REGNO, or all registers if REGNO == -1, from the contents
246b725ae77Skettenis of REGISTERS. FIXME: ignores errors. */
247b725ae77Skettenis
248b725ae77Skettenis static void
bdm_ppc_store_registers(int regno)249b725ae77Skettenis bdm_ppc_store_registers (int regno)
250b725ae77Skettenis {
251*11efff7fSkettenis struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
252b725ae77Skettenis int i;
253b725ae77Skettenis int first_regno, last_regno;
254b725ae77Skettenis int first_bdm_regno, last_bdm_regno;
255b725ae77Skettenis
256b725ae77Skettenis if (regno == -1)
257b725ae77Skettenis {
258b725ae77Skettenis first_regno = 0;
259b725ae77Skettenis last_regno = NUM_REGS - 1;
260b725ae77Skettenis
261b725ae77Skettenis first_bdm_regno = 0;
262b725ae77Skettenis last_bdm_regno = BDM_NUM_REGS - 1;
263b725ae77Skettenis }
264b725ae77Skettenis else
265b725ae77Skettenis {
266b725ae77Skettenis first_regno = regno;
267b725ae77Skettenis last_regno = regno;
268b725ae77Skettenis
269b725ae77Skettenis first_bdm_regno = bdm_regmap[regno];
270b725ae77Skettenis last_bdm_regno = bdm_regmap[regno];
271b725ae77Skettenis }
272b725ae77Skettenis
273b725ae77Skettenis if (first_bdm_regno == -1)
274b725ae77Skettenis return; /* Unsupported register */
275b725ae77Skettenis
276*11efff7fSkettenis /* FIXME: jimb/2004-05-04: I'm not sure how to adapt this code to
277*11efff7fSkettenis processors that lack floating point registers, and I don't have
278*11efff7fSkettenis have the equipment to test it. So we'll leave that case for the
279*11efff7fSkettenis next person who encounters it. */
280*11efff7fSkettenis gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
281*11efff7fSkettenis
282b725ae77Skettenis for (i = first_regno; i <= last_regno; i++)
283b725ae77Skettenis {
284b725ae77Skettenis int bdm_regno;
285b725ae77Skettenis
286b725ae77Skettenis bdm_regno = bdm_regmap[i];
287b725ae77Skettenis
288b725ae77Skettenis /* only attempt to write if it's a valid ppc 8xx register */
289b725ae77Skettenis /* (need to avoid FP regs and MQ reg) */
290b725ae77Skettenis if ((i != gdbarch_tdep (current_gdbarch)->ppc_mq_regnum)
291b725ae77Skettenis && (i != gdbarch_tdep (current_gdbarch)->ppc_fpscr_regnum)
292*11efff7fSkettenis && ((i < tdep->ppc_fp0_regnum)
293*11efff7fSkettenis || (i >= tdep->ppc_fp0_regnum + ppc_num_fprs)))
294b725ae77Skettenis {
295b725ae77Skettenis /* printf("write valid reg %d\n", bdm_regno); */
296b725ae77Skettenis ocd_write_bdm_registers (bdm_regno, deprecated_registers + DEPRECATED_REGISTER_BYTE (i), 4);
297b725ae77Skettenis }
298b725ae77Skettenis /*
299b725ae77Skettenis else if (i == gdbarch_tdep (current_gdbarch)->ppc_mq_regnum)
300b725ae77Skettenis printf("don't write invalid reg %d (PPC_MQ_REGNUM)\n", bdm_regno);
301b725ae77Skettenis else
302b725ae77Skettenis printf("don't write invalid reg %d\n", bdm_regno);
303b725ae77Skettenis */
304b725ae77Skettenis }
305b725ae77Skettenis }
306b725ae77Skettenis
307b725ae77Skettenis /* Define the target subroutine names */
308b725ae77Skettenis
309b725ae77Skettenis struct target_ops bdm_ppc_ops;
310b725ae77Skettenis
311b725ae77Skettenis static void
init_bdm_ppc_ops(void)312b725ae77Skettenis init_bdm_ppc_ops (void)
313b725ae77Skettenis {
314b725ae77Skettenis bdm_ppc_ops.to_shortname = "ocd";
315b725ae77Skettenis bdm_ppc_ops.to_longname = "Remote target with On-Chip Debugging";
316b725ae77Skettenis bdm_ppc_ops.to_doc = "Use a remote target with On-Chip Debugging. To use a target box;\n\
317b725ae77Skettenis specify the serial device it is connected to (e.g. /dev/ttya). To use\n\
318b725ae77Skettenis a wiggler, specify wiggler and then the port it is connected to\n\
319b725ae77Skettenis (e.g. wiggler lpt1)."; /* to_doc */
320b725ae77Skettenis bdm_ppc_ops.to_open = bdm_ppc_open;
321b725ae77Skettenis bdm_ppc_ops.to_close = ocd_close;
322b725ae77Skettenis bdm_ppc_ops.to_detach = ocd_detach;
323b725ae77Skettenis bdm_ppc_ops.to_resume = ocd_resume;
324b725ae77Skettenis bdm_ppc_ops.to_wait = bdm_ppc_wait;
325b725ae77Skettenis bdm_ppc_ops.to_fetch_registers = bdm_ppc_fetch_registers;
326b725ae77Skettenis bdm_ppc_ops.to_store_registers = bdm_ppc_store_registers;
327b725ae77Skettenis bdm_ppc_ops.to_prepare_to_store = ocd_prepare_to_store;
328*11efff7fSkettenis bdm_ppc_ops.deprecated_xfer_memory = ocd_xfer_memory;
329b725ae77Skettenis bdm_ppc_ops.to_files_info = ocd_files_info;
330b725ae77Skettenis bdm_ppc_ops.to_insert_breakpoint = ocd_insert_breakpoint;
331b725ae77Skettenis bdm_ppc_ops.to_remove_breakpoint = ocd_remove_breakpoint;
332b725ae77Skettenis bdm_ppc_ops.to_kill = ocd_kill;
333b725ae77Skettenis bdm_ppc_ops.to_load = ocd_load;
334b725ae77Skettenis bdm_ppc_ops.to_create_inferior = ocd_create_inferior;
335b725ae77Skettenis bdm_ppc_ops.to_mourn_inferior = ocd_mourn;
336b725ae77Skettenis bdm_ppc_ops.to_thread_alive = ocd_thread_alive;
337b725ae77Skettenis bdm_ppc_ops.to_stop = ocd_stop;
338b725ae77Skettenis bdm_ppc_ops.to_stratum = process_stratum;
339b725ae77Skettenis bdm_ppc_ops.to_has_all_memory = 1;
340b725ae77Skettenis bdm_ppc_ops.to_has_memory = 1;
341b725ae77Skettenis bdm_ppc_ops.to_has_stack = 1;
342b725ae77Skettenis bdm_ppc_ops.to_has_registers = 1;
343b725ae77Skettenis bdm_ppc_ops.to_has_execution = 1;
344b725ae77Skettenis bdm_ppc_ops.to_magic = OPS_MAGIC;
345b725ae77Skettenis } /* init_bdm_ppc_ops */
346b725ae77Skettenis
347b725ae77Skettenis extern initialize_file_ftype _initialize_bdm_ppc; /* -Wmissing-prototypes */
348b725ae77Skettenis
349b725ae77Skettenis void
_initialize_bdm_ppc(void)350b725ae77Skettenis _initialize_bdm_ppc (void)
351b725ae77Skettenis {
352b725ae77Skettenis init_bdm_ppc_ops ();
353b725ae77Skettenis add_target (&bdm_ppc_ops);
354b725ae77Skettenis }
355