* Fixing typo that caused infinite loop upon PKE MPG.
[binutils-gdb.git] / gdb / ppc-bdm.c
blob6731e9a16ddb2cb53b215652e7e1c3728220fd66
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.
5 This file is part of GDB.
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.
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.
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. */
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"
39 static void bdm_ppc_open PARAMS ((char *name, int from_tty));
41 static int bdm_ppc_wait PARAMS ((int pid,
42 struct target_waitstatus *target_status));
44 static void bdm_ppc_fetch_registers PARAMS ((int regno));
46 static void bdm_ppc_store_registers PARAMS ((int regno));
48 extern struct target_ops bdm_ppc_ops; /* Forward decl */
50 /*#define BDM_NUM_REGS 71*/
51 #define BDM_NUM_REGS 24
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 */ \
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 */ \
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) */ \
70 0, /* mq (SPR 0) */
73 char nowatchdog[4] = {0xff,0xff,0xff,0x88};
75 /* Open a connection to a remote debugger.
76 NAME is the filename used for communication. */
78 static void
79 bdm_ppc_open (name, from_tty)
80 char *name;
81 int from_tty;
83 CORE_ADDR watchdogaddr = 0xff000004;
85 ocd_open (name, from_tty, OCD_TARGET_MOTO_PPC, &bdm_ppc_ops);
87 /* We want interrupts to drop us into debugging mode. */
88 /* Modify the DER register to accomplish this. */
89 ocd_write_bdm_register (149, 0x20024000);
91 /* Disable watchdog timer on the board */
92 ocd_write_bytes (watchdogaddr, nowatchdog, 4);
95 /* Wait until the remote machine stops, then return,
96 storing status in STATUS just as `wait' would.
97 Returns "pid" (though it's not clear what, if anything, that
98 means in the case of this target). */
100 static int
101 bdm_ppc_wait (pid, target_status)
102 int pid;
103 struct target_waitstatus *target_status;
105 int stop_reason;
107 target_status->kind = TARGET_WAITKIND_STOPPED;
109 stop_reason = ocd_wait ();
111 if (stop_reason)
113 target_status->value.sig = TARGET_SIGNAL_INT;
114 return inferior_pid;
117 target_status->value.sig = TARGET_SIGNAL_TRAP; /* XXX for now */
119 #if 0
121 unsigned long ecr, der;
123 ecr = ocd_read_bdm_register (148); /* Read the exception cause register */
124 der = ocd_read_bdm_register (149); /* Read the debug enables register */
125 fprintf_unfiltered (gdb_stdout, "ecr = 0x%x, der = 0x%x\n", ecr, der);
127 #endif
129 return inferior_pid;
132 static int bdm_regmap[] = {BDM_REGMAP};
134 /* Read the remote registers into regs.
135 Fetch register REGNO, or all registers if REGNO == -1
137 The Wiggler uses the following codes to access the registers:
139 0 -> 1023 SPR 0 -> 1023
140 0 - SPR 0 - MQ
141 1 - SPR 1 - XER
142 8 - SPR 8 - LR
143 9 - SPR 9 - CTR (known as cnt in GDB)
144 26 - SPR 26 - SRR0 - pc
145 1024 -> 2047 DCR 0 -> DCR 1023 (IBM PPC 4xx only)
146 2048 -> 2079 R0 -> R31
147 2080 -> 2143 FP0 -> FP31 (64 bit regs) (IBM PPC 5xx only)
148 2144 CR (known as cnd in GDB)
149 2145 FPCSR
150 2146 MSR (known as ps in GDB)
153 static void
154 bdm_ppc_fetch_registers (regno)
155 int regno;
157 int i;
158 unsigned char *regs, *beginregs, *endregs, *almostregs;
159 unsigned char midregs[32];
160 unsigned char mqreg[1];
161 int first_regno, last_regno;
162 int first_bdm_regno, last_bdm_regno;
163 int reglen, beginreglen, endreglen;
165 #if 1
166 for (i = 0; i < (FPLAST_REGNUM - FP0_REGNUM + 1); i++)
168 midregs[i] = -1;
170 mqreg[0] = -1;
171 #endif
173 if (regno == -1)
175 first_regno = 0;
176 last_regno = NUM_REGS - 1;
178 first_bdm_regno = 0;
179 last_bdm_regno = BDM_NUM_REGS - 1;
181 else
183 first_regno = regno;
184 last_regno = regno;
186 first_bdm_regno = bdm_regmap [regno];
187 last_bdm_regno = bdm_regmap [regno];
190 if (first_bdm_regno == -1)
192 supply_register (first_regno, NULL);
193 return; /* Unsupported register */
196 #if 1
197 /* Can't ask for floating point regs on ppc 8xx, also need to
198 avoid asking for the mq register. */
199 if (first_regno == last_regno) /* only want one reg */
201 /* printf("Asking for register %d\n", first_regno); */
203 /* if asking for an invalid register */
204 if ((first_regno == MQ_REGNUM) ||
205 ((first_regno >= FP0_REGNUM) && (first_regno <= FPLAST_REGNUM)))
207 /* printf("invalid reg request!\n"); */
208 supply_register (first_regno, NULL);
209 return; /* Unsupported register */
211 else
213 regs = ocd_read_bdm_registers (first_bdm_regno,
214 last_bdm_regno, &reglen);
217 else /* want all regs */
219 /* printf("Asking for registers %d to %d\n", first_regno, last_regno); */
220 beginregs = ocd_read_bdm_registers (first_bdm_regno,
221 FP0_REGNUM - 1, &beginreglen);
222 endregs = (strcat (midregs,
223 ocd_read_bdm_registers (FPLAST_REGNUM + 1,
224 last_bdm_regno - 1, &endreglen)));
225 almostregs = (strcat (beginregs, endregs));
226 regs = (strcat (almostregs, mqreg));
227 reglen = beginreglen + 32 + endreglen + 1;
230 #endif
231 #if 0
232 regs = ocd_read_bdm_registers (first_bdm_regno, last_bdm_regno, &reglen);
233 #endif
235 for (i = first_regno; i <= last_regno; i++)
237 int bdm_regno, regoffset;
239 bdm_regno = bdm_regmap [i];
240 if (bdm_regno != -1)
242 regoffset = bdm_regno - first_bdm_regno;
244 if (regoffset >= reglen / 4)
245 continue;
247 supply_register (i, regs + 4 * regoffset);
249 else
250 supply_register (i, NULL); /* Unsupported register */
254 /* Store register REGNO, or all registers if REGNO == -1, from the contents
255 of REGISTERS. FIXME: ignores errors. */
257 static void
258 bdm_ppc_store_registers (regno)
259 int regno;
261 int i;
262 int first_regno, last_regno;
263 int first_bdm_regno, last_bdm_regno;
265 if (regno == -1)
267 first_regno = 0;
268 last_regno = NUM_REGS - 1;
270 first_bdm_regno = 0;
271 last_bdm_regno = BDM_NUM_REGS - 1;
273 else
275 first_regno = regno;
276 last_regno = regno;
278 first_bdm_regno = bdm_regmap [regno];
279 last_bdm_regno = bdm_regmap [regno];
282 if (first_bdm_regno == -1)
283 return; /* Unsupported register */
285 for (i = first_regno; i <= last_regno; i++)
287 int bdm_regno;
289 bdm_regno = bdm_regmap [i];
291 /* only attempt to write if it's a valid ppc 8xx register */
292 /* (need to avoid FP regs and MQ reg) */
293 if ((i != MQ_REGNUM) && ((i < FP0_REGNUM) || (i > FPLAST_REGNUM)))
295 /* printf("write valid reg %d\n", bdm_regno); */
296 ocd_write_bdm_registers (bdm_regno, registers + REGISTER_BYTE (i), 4);
299 else if (i == MQ_REGNUM)
300 printf("don't write invalid reg %d (MQ_REGNUM)\n", bdm_regno);
301 else
302 printf("don't write invalid reg %d\n", bdm_regno);
307 /* Define the target subroutine names */
309 struct target_ops bdm_ppc_ops = {
310 "ocd", /* to_shortname */
311 "Remote target with On-Chip Debugging", /* to_longname */
312 "Use a remote target with On-Chip Debugging. To use a target box,\n\
313 specify the serial device it is connected to (e.g. /dev/ttya). To use\n\
314 a wiggler, specify wiggler and then the port it is connected to\n\
315 (e.g. wiggler lpt1).", /* to_doc */
316 bdm_ppc_open, /* to_open */
317 ocd_close, /* to_close */
318 NULL, /* to_attach */
319 ocd_detach, /* to_detach */
320 ocd_resume, /* to_resume */
321 bdm_ppc_wait, /* to_wait */
322 bdm_ppc_fetch_registers, /* to_fetch_registers */
323 bdm_ppc_store_registers, /* to_store_registers */
324 ocd_prepare_to_store, /* to_prepare_to_store */
325 ocd_xfer_memory, /* to_xfer_memory */
326 ocd_files_info, /* to_files_info */
327 ocd_insert_breakpoint, /* to_insert_breakpoint */
328 ocd_remove_breakpoint, /* to_remove_breakpoint */
329 NULL, /* to_terminal_init */
330 NULL, /* to_terminal_inferior */
331 NULL, /* to_terminal_ours_for_output */
332 NULL, /* to_terminal_ours */
333 NULL, /* to_terminal_info */
334 ocd_kill, /* to_kill */
335 ocd_load, /* to_load */
336 NULL, /* to_lookup_symbol */
337 ocd_create_inferior, /* to_create_inferior */
338 ocd_mourn, /* to_mourn_inferior */
339 0, /* to_can_run */
340 0, /* to_notice_signals */
341 ocd_thread_alive, /* to_thread_alive */
342 ocd_stop, /* to_stop */
343 process_stratum, /* to_stratum */
344 NULL, /* to_next */
345 1, /* to_has_all_memory */
346 1, /* to_has_memory */
347 1, /* to_has_stack */
348 1, /* to_has_registers */
349 1, /* to_has_execution */
350 NULL, /* sections */
351 NULL, /* sections_end */
352 OPS_MAGIC /* to_magic */
355 void
356 _initialize_bdm_ppc ()
358 add_target (&bdm_ppc_ops);