1238104Sdes/* Remote target communications for the Macraigor Systems BDM Wiggler 2238104Sdes talking to a Motorola PPC 8xx ADS board 3238104Sdes Copyright 1996, 1997, 1998, 1999, 2000, 2001 4238104Sdes Free Software Foundation, Inc. 5238104Sdes 6238104Sdes This file is part of GDB. 7238104Sdes 8238104Sdes This program is free software; you can redistribute it and/or modify 9238104Sdes it under the terms of the GNU General Public License as published by 10238104Sdes the Free Software Foundation; either version 2 of the License, or 11238104Sdes (at your option) any later version. 12238104Sdes 13238104Sdes This program is distributed in the hope that it will be useful, 14238104Sdes but WITHOUT ANY WARRANTY; without even the implied warranty of 15238104Sdes MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16238104Sdes GNU General Public License for more details. 17238104Sdes 18238104Sdes You should have received a copy of the GNU General Public License 19238104Sdes along with this program; if not, write to the Free Software 20238104Sdes Foundation, Inc., 59 Temple Place - Suite 330, 21238104Sdes Boston, MA 02111-1307, USA. */ 22238104Sdes 23238104Sdes#include "defs.h" 24238104Sdes#include "gdbcore.h" 25238104Sdes#include "gdb_string.h" 26238104Sdes#include <fcntl.h> 27238104Sdes#include "frame.h" 28238104Sdes#include "inferior.h" 29238104Sdes#include "bfd.h" 30238104Sdes#include "symfile.h" 31238104Sdes#include "target.h" 32238104Sdes#include "gdbcmd.h" 33238104Sdes#include "objfiles.h" 34238104Sdes#include "gdb-stabs.h" 35238104Sdes#include <sys/types.h> 36238104Sdes#include "serial.h" 37238104Sdes#include "ocd.h" 38238104Sdes#include "ppc-tdep.h" 39238104Sdes#include "regcache.h" 40238104Sdes 41238104Sdesstatic void bdm_ppc_open (char *name, int from_tty); 42238104Sdes 43238104Sdesstatic ptid_t bdm_ppc_wait (ptid_t ptid, 44238104Sdes struct target_waitstatus *target_status); 45238104Sdes 46238104Sdesstatic void bdm_ppc_fetch_registers (int regno); 47238104Sdes 48238104Sdesstatic void bdm_ppc_store_registers (int regno); 49238104Sdes 50238104Sdesextern struct target_ops bdm_ppc_ops; /* Forward decl */ 51238104Sdes 52238104Sdes/*#define BDM_NUM_REGS 71 */ 53238104Sdes#define BDM_NUM_REGS 24 54238104Sdes 55238104Sdes#define BDM_REGMAP \ 56238104Sdes 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, /* r0-r7 */ \ 57238104Sdes 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, /* r8-r15 */ \ 58238104Sdes 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, /* r16-r23 */ \ 59238104Sdes 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, /* r24-r31 */ \ 60238104Sdes\ 61238104Sdes 2080, 2082, 2084, 2086, 2088, 2090, 2092, 2094, /* fp0->fp8 */ \ 62238104Sdes 2096, 2098, 2100, 2102, 2104, 2106, 2108, 2110, /* fp0->fp8 */ \ 63238104Sdes 2112, 2114, 2116, 2118, 2120, 2122, 2124, 2126, /* fp0->fp8 */ \ 64238104Sdes 2128, 2130, 2132, 2134, 2136, 2138, 2140, 2142, /* fp0->fp8 */ \ 65238104Sdes\ 66238104Sdes 26, /* pc (SRR0 (SPR 26)) */ \ 67238104Sdes 2146, /* ps (MSR) */ \ 68238104Sdes 2144, /* cnd (CR) */ \ 69238104Sdes 8, /* lr (SPR 8) */ \ 70238104Sdes 9, /* cnt (CTR (SPR 9)) */ \ 71238104Sdes 1, /* xer (SPR 1) */ \ 72238104Sdes 0, /* mq (SPR 0) */ 73238104Sdes 74238104Sdes 75238104Sdeschar nowatchdog[4] = 76238104Sdes{0xff, 0xff, 0xff, 0x88}; 77238104Sdes 78238104Sdes/* Open a connection to a remote debugger. 79238104Sdes NAME is the filename used for communication. */ 80238104Sdes 81238104Sdesstatic void 82238104Sdesbdm_ppc_open (char *name, int from_tty) 83238104Sdes{ 84238104Sdes CORE_ADDR watchdogaddr = 0xff000004; 85238104Sdes 86238104Sdes ocd_open (name, from_tty, OCD_TARGET_MOTO_PPC, &bdm_ppc_ops); 87238104Sdes 88238104Sdes /* We want interrupts to drop us into debugging mode. */ 89238104Sdes /* Modify the DER register to accomplish this. */ 90238104Sdes ocd_write_bdm_register (149, 0x20024000); 91238104Sdes 92238104Sdes /* Disable watchdog timer on the board */ 93238104Sdes ocd_write_bytes (watchdogaddr, nowatchdog, 4); 94238104Sdes} 95238104Sdes 96238104Sdes/* Wait until the remote machine stops, then return, 97238104Sdes storing status in STATUS just as `wait' would. 98238104Sdes Returns "pid" (though it's not clear what, if anything, that 99238104Sdes means in the case of this target). */ 100238104Sdes 101238104Sdesstatic ptid_t 102238104Sdesbdm_ppc_wait (ptid_t ptid, struct target_waitstatus *target_status) 103238104Sdes{ 104 int stop_reason; 105 106 target_status->kind = TARGET_WAITKIND_STOPPED; 107 108 stop_reason = ocd_wait (); 109 110 if (stop_reason) 111 { 112 target_status->value.sig = TARGET_SIGNAL_INT; 113 return inferior_ptid; 114 } 115 116 target_status->value.sig = TARGET_SIGNAL_TRAP; /* XXX for now */ 117 118#if 0 119 { 120 unsigned long ecr, der; 121 122 ecr = ocd_read_bdm_register (148); /* Read the exception cause register */ 123 der = ocd_read_bdm_register (149); /* Read the debug enables register */ 124 fprintf_unfiltered (gdb_stdout, "ecr = 0x%x, der = 0x%x\n", ecr, der); 125 } 126#endif 127 128 return inferior_ptid; 129} 130 131static int bdm_regmap[] = 132{BDM_REGMAP}; 133 134/* Read the remote registers into regs. 135 Fetch register REGNO, or all registers if REGNO == -1 136 137 The Wiggler uses the following codes to access the registers: 138 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) 151 */ 152 153static void 154bdm_ppc_fetch_registers (int regno) 155{ 156 int i; 157 unsigned char *regs, *beginregs, *endregs, *almostregs; 158 unsigned char midregs[32]; 159 unsigned char mqreg[1]; 160 int first_regno, last_regno; 161 int first_bdm_regno, last_bdm_regno; 162 int reglen, beginreglen, endreglen; 163 164#if 1 165 for (i = 0; i < (FPLAST_REGNUM - FP0_REGNUM + 1); i++) 166 { 167 midregs[i] = -1; 168 } 169 mqreg[0] = -1; 170#endif 171 172 if (regno == -1) 173 { 174 first_regno = 0; 175 last_regno = NUM_REGS - 1; 176 177 first_bdm_regno = 0; 178 last_bdm_regno = BDM_NUM_REGS - 1; 179 } 180 else 181 { 182 first_regno = regno; 183 last_regno = regno; 184 185 first_bdm_regno = bdm_regmap[regno]; 186 last_bdm_regno = bdm_regmap[regno]; 187 } 188 189 if (first_bdm_regno == -1) 190 { 191 supply_register (first_regno, NULL); 192 return; /* Unsupported register */ 193 } 194 195#if 1 196 /* Can't ask for floating point regs on ppc 8xx, also need to 197 avoid asking for the mq register. */ 198 if (first_regno == last_regno) /* only want one reg */ 199 { 200/* printf("Asking for register %d\n", first_regno); */ 201 202 /* if asking for an invalid register */ 203 if ((first_regno == gdbarch_tdep (current_gdbarch)->ppc_mq_regnum) 204 || (first_regno == gdbarch_tdep (current_gdbarch)->ppc_fpscr_regnum) 205 || ((first_regno >= FP0_REGNUM) && (first_regno <= FPLAST_REGNUM))) 206 { 207/* printf("invalid reg request!\n"); */ 208 supply_register (first_regno, NULL); 209 return; /* Unsupported register */ 210 } 211 else 212 { 213 regs = ocd_read_bdm_registers (first_bdm_regno, 214 last_bdm_regno, ®len); 215 } 216 } 217 else 218 /* want all regs */ 219 { 220/* printf("Asking for registers %d to %d\n", first_regno, last_regno); */ 221 beginregs = ocd_read_bdm_registers (first_bdm_regno, 222 FP0_REGNUM - 1, &beginreglen); 223 endregs = (strcat (midregs, 224 ocd_read_bdm_registers (FPLAST_REGNUM + 1, 225 last_bdm_regno - 1, &endreglen))); 226 almostregs = (strcat (beginregs, endregs)); 227 regs = (strcat (almostregs, mqreg)); 228 reglen = beginreglen + 32 + endreglen + 1; 229 } 230 231#endif 232#if 0 233 regs = ocd_read_bdm_registers (first_bdm_regno, last_bdm_regno, ®len); 234#endif 235 236 for (i = first_regno; i <= last_regno; i++) 237 { 238 int bdm_regno, regoffset; 239 240 bdm_regno = bdm_regmap[i]; 241 if (bdm_regno != -1) 242 { 243 regoffset = bdm_regno - first_bdm_regno; 244 245 if (regoffset >= reglen / 4) 246 continue; 247 248 supply_register (i, regs + 4 * regoffset); 249 } 250 else 251 supply_register (i, NULL); /* Unsupported register */ 252 } 253} 254 255/* Store register REGNO, or all registers if REGNO == -1, from the contents 256 of REGISTERS. FIXME: ignores errors. */ 257 258static void 259bdm_ppc_store_registers (int regno) 260{ 261 int i; 262 int first_regno, last_regno; 263 int first_bdm_regno, last_bdm_regno; 264 265 if (regno == -1) 266 { 267 first_regno = 0; 268 last_regno = NUM_REGS - 1; 269 270 first_bdm_regno = 0; 271 last_bdm_regno = BDM_NUM_REGS - 1; 272 } 273 else 274 { 275 first_regno = regno; 276 last_regno = regno; 277 278 first_bdm_regno = bdm_regmap[regno]; 279 last_bdm_regno = bdm_regmap[regno]; 280 } 281 282 if (first_bdm_regno == -1) 283 return; /* Unsupported register */ 284 285 for (i = first_regno; i <= last_regno; i++) 286 { 287 int bdm_regno; 288 289 bdm_regno = bdm_regmap[i]; 290 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 != gdbarch_tdep (current_gdbarch)->ppc_mq_regnum) 294 && (i != gdbarch_tdep (current_gdbarch)->ppc_fpscr_regnum) 295 && ((i < FP0_REGNUM) || (i > FPLAST_REGNUM))) 296 { 297/* printf("write valid reg %d\n", bdm_regno); */ 298 ocd_write_bdm_registers (bdm_regno, deprecated_registers + DEPRECATED_REGISTER_BYTE (i), 4); 299 } 300/* 301 else if (i == gdbarch_tdep (current_gdbarch)->ppc_mq_regnum) 302 printf("don't write invalid reg %d (PPC_MQ_REGNUM)\n", bdm_regno); 303 else 304 printf("don't write invalid reg %d\n", bdm_regno); 305 */ 306 } 307} 308 309/* Define the target subroutine names */ 310 311struct target_ops bdm_ppc_ops; 312 313static void 314init_bdm_ppc_ops (void) 315{ 316 bdm_ppc_ops.to_shortname = "ocd"; 317 bdm_ppc_ops.to_longname = "Remote target with On-Chip Debugging"; 318 bdm_ppc_ops.to_doc = "Use a remote target with On-Chip Debugging. To use a target box;\n\ 319specify the serial device it is connected to (e.g. /dev/ttya). To use\n\ 320a wiggler, specify wiggler and then the port it is connected to\n\ 321(e.g. wiggler lpt1)."; /* to_doc */ 322 bdm_ppc_ops.to_open = bdm_ppc_open; 323 bdm_ppc_ops.to_close = ocd_close; 324 bdm_ppc_ops.to_detach = ocd_detach; 325 bdm_ppc_ops.to_resume = ocd_resume; 326 bdm_ppc_ops.to_wait = bdm_ppc_wait; 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_kill = ocd_kill; 335 bdm_ppc_ops.to_load = ocd_load; 336 bdm_ppc_ops.to_create_inferior = ocd_create_inferior; 337 bdm_ppc_ops.to_mourn_inferior = ocd_mourn; 338 bdm_ppc_ops.to_thread_alive = ocd_thread_alive; 339 bdm_ppc_ops.to_stop = ocd_stop; 340 bdm_ppc_ops.to_stratum = process_stratum; 341 bdm_ppc_ops.to_has_all_memory = 1; 342 bdm_ppc_ops.to_has_memory = 1; 343 bdm_ppc_ops.to_has_stack = 1; 344 bdm_ppc_ops.to_has_registers = 1; 345 bdm_ppc_ops.to_has_execution = 1; 346 bdm_ppc_ops.to_magic = OPS_MAGIC; 347} /* init_bdm_ppc_ops */ 348 349extern initialize_file_ftype _initialize_bdm_ppc; /* -Wmissing-prototypes */ 350 351void 352_initialize_bdm_ppc (void) 353{ 354 init_bdm_ppc_ops (); 355 add_target (&bdm_ppc_ops); 356} 357