xref: /openbsd/gnu/usr.bin/binutils/gdb/ppc-bdm.c (revision 11efff7f)
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, &reglen);
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, &reglen);
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