146283Sdfr/* Remote target communications for the Macraigor Systems BDM Wiggler 246283Sdfr talking to a Motorola PPC 8xx ADS board 398944Sobrien Copyright 1996, 1997, 1998, 1999, 2000, 2001 498944Sobrien Free Software Foundation, Inc. 546283Sdfr 698944Sobrien This file is part of GDB. 746283Sdfr 898944Sobrien This program is free software; you can redistribute it and/or modify 998944Sobrien it under the terms of the GNU General Public License as published by 1098944Sobrien the Free Software Foundation; either version 2 of the License, or 1198944Sobrien (at your option) any later version. 1246283Sdfr 1398944Sobrien This program is distributed in the hope that it will be useful, 1498944Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1598944Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1698944Sobrien GNU General Public License for more details. 1746283Sdfr 1898944Sobrien You should have received a copy of the GNU General Public License 1998944Sobrien along with this program; if not, write to the Free Software 2098944Sobrien Foundation, Inc., 59 Temple Place - Suite 330, 2198944Sobrien Boston, MA 02111-1307, USA. */ 2246283Sdfr 2346283Sdfr#include "defs.h" 2446283Sdfr#include "gdbcore.h" 2546283Sdfr#include "gdb_string.h" 2646283Sdfr#include <fcntl.h> 2746283Sdfr#include "frame.h" 2846283Sdfr#include "inferior.h" 2946283Sdfr#include "bfd.h" 3046283Sdfr#include "symfile.h" 3146283Sdfr#include "target.h" 3246283Sdfr#include "gdbcmd.h" 3346283Sdfr#include "objfiles.h" 3446283Sdfr#include "gdb-stabs.h" 3546283Sdfr#include <sys/types.h> 3646283Sdfr#include "serial.h" 3746283Sdfr#include "ocd.h" 3898944Sobrien#include "ppc-tdep.h" 3998944Sobrien#include "regcache.h" 4046283Sdfr 4198944Sobrienstatic void bdm_ppc_open (char *name, int from_tty); 4246283Sdfr 4398944Sobrienstatic ptid_t bdm_ppc_wait (ptid_t ptid, 4498944Sobrien struct target_waitstatus *target_status); 4546283Sdfr 4698944Sobrienstatic void bdm_ppc_fetch_registers (int regno); 4746283Sdfr 4898944Sobrienstatic void bdm_ppc_store_registers (int regno); 4946283Sdfr 5046283Sdfrextern struct target_ops bdm_ppc_ops; /* Forward decl */ 5146283Sdfr 5298944Sobrien/*#define BDM_NUM_REGS 71 */ 5346283Sdfr#define BDM_NUM_REGS 24 5446283Sdfr 5546283Sdfr#define BDM_REGMAP \ 5646283Sdfr 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, /* r0-r7 */ \ 5746283Sdfr 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, /* r8-r15 */ \ 5846283Sdfr 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, /* r16-r23 */ \ 5946283Sdfr 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, /* r24-r31 */ \ 6046283Sdfr\ 6146283Sdfr 2080, 2082, 2084, 2086, 2088, 2090, 2092, 2094, /* fp0->fp8 */ \ 6246283Sdfr 2096, 2098, 2100, 2102, 2104, 2106, 2108, 2110, /* fp0->fp8 */ \ 6346283Sdfr 2112, 2114, 2116, 2118, 2120, 2122, 2124, 2126, /* fp0->fp8 */ \ 6446283Sdfr 2128, 2130, 2132, 2134, 2136, 2138, 2140, 2142, /* fp0->fp8 */ \ 6546283Sdfr\ 6646283Sdfr 26, /* pc (SRR0 (SPR 26)) */ \ 6746283Sdfr 2146, /* ps (MSR) */ \ 6846283Sdfr 2144, /* cnd (CR) */ \ 6946283Sdfr 8, /* lr (SPR 8) */ \ 7046283Sdfr 9, /* cnt (CTR (SPR 9)) */ \ 7146283Sdfr 1, /* xer (SPR 1) */ \ 7298944Sobrien 0, /* mq (SPR 0) */ 7346283Sdfr 7446283Sdfr 7598944Sobrienchar nowatchdog[4] = 7698944Sobrien{0xff, 0xff, 0xff, 0x88}; 7798944Sobrien 7846283Sdfr/* Open a connection to a remote debugger. 7946283Sdfr NAME is the filename used for communication. */ 8046283Sdfr 8146283Sdfrstatic void 8298944Sobrienbdm_ppc_open (char *name, int from_tty) 8346283Sdfr{ 8446283Sdfr CORE_ADDR watchdogaddr = 0xff000004; 8546283Sdfr 8646283Sdfr ocd_open (name, from_tty, OCD_TARGET_MOTO_PPC, &bdm_ppc_ops); 8746283Sdfr 8846283Sdfr /* We want interrupts to drop us into debugging mode. */ 8946283Sdfr /* Modify the DER register to accomplish this. */ 9046283Sdfr ocd_write_bdm_register (149, 0x20024000); 9146283Sdfr 9246283Sdfr /* Disable watchdog timer on the board */ 9346283Sdfr ocd_write_bytes (watchdogaddr, nowatchdog, 4); 9446283Sdfr} 9546283Sdfr 9646283Sdfr/* Wait until the remote machine stops, then return, 9746283Sdfr storing status in STATUS just as `wait' would. 9846283Sdfr Returns "pid" (though it's not clear what, if anything, that 9946283Sdfr means in the case of this target). */ 10046283Sdfr 10198944Sobrienstatic ptid_t 10298944Sobrienbdm_ppc_wait (ptid_t ptid, struct target_waitstatus *target_status) 10346283Sdfr{ 10446283Sdfr int stop_reason; 10546283Sdfr 10646283Sdfr target_status->kind = TARGET_WAITKIND_STOPPED; 10746283Sdfr 10846283Sdfr stop_reason = ocd_wait (); 10946283Sdfr 11046283Sdfr if (stop_reason) 11146283Sdfr { 11246283Sdfr target_status->value.sig = TARGET_SIGNAL_INT; 11398944Sobrien return inferior_ptid; 11446283Sdfr } 11546283Sdfr 11698944Sobrien target_status->value.sig = TARGET_SIGNAL_TRAP; /* XXX for now */ 11746283Sdfr 11846283Sdfr#if 0 11946283Sdfr { 12046283Sdfr unsigned long ecr, der; 12146283Sdfr 12298944Sobrien ecr = ocd_read_bdm_register (148); /* Read the exception cause register */ 12398944Sobrien der = ocd_read_bdm_register (149); /* Read the debug enables register */ 12446283Sdfr fprintf_unfiltered (gdb_stdout, "ecr = 0x%x, der = 0x%x\n", ecr, der); 12546283Sdfr } 12646283Sdfr#endif 12746283Sdfr 12898944Sobrien return inferior_ptid; 12946283Sdfr} 13046283Sdfr 13198944Sobrienstatic int bdm_regmap[] = 13298944Sobrien{BDM_REGMAP}; 13346283Sdfr 13446283Sdfr/* Read the remote registers into regs. 13546283Sdfr Fetch register REGNO, or all registers if REGNO == -1 13646283Sdfr 13746283Sdfr The Wiggler uses the following codes to access the registers: 13846283Sdfr 13998944Sobrien 0 -> 1023 SPR 0 -> 1023 14098944Sobrien 0 - SPR 0 - MQ 14198944Sobrien 1 - SPR 1 - XER 14298944Sobrien 8 - SPR 8 - LR 14398944Sobrien 9 - SPR 9 - CTR (known as cnt in GDB) 14498944Sobrien 26 - SPR 26 - SRR0 - pc 14598944Sobrien 1024 -> 2047 DCR 0 -> DCR 1023 (IBM PPC 4xx only) 14698944Sobrien 2048 -> 2079 R0 -> R31 14798944Sobrien 2080 -> 2143 FP0 -> FP31 (64 bit regs) (IBM PPC 5xx only) 14898944Sobrien 2144 CR (known as cnd in GDB) 14998944Sobrien 2145 FPCSR 15098944Sobrien 2146 MSR (known as ps in GDB) 15146283Sdfr */ 15246283Sdfr 15346283Sdfrstatic void 15498944Sobrienbdm_ppc_fetch_registers (int regno) 15546283Sdfr{ 15646283Sdfr int i; 15746283Sdfr unsigned char *regs, *beginregs, *endregs, *almostregs; 15846283Sdfr unsigned char midregs[32]; 15946283Sdfr unsigned char mqreg[1]; 16046283Sdfr int first_regno, last_regno; 16146283Sdfr int first_bdm_regno, last_bdm_regno; 16246283Sdfr int reglen, beginreglen, endreglen; 16346283Sdfr 16446283Sdfr#if 1 16546283Sdfr for (i = 0; i < (FPLAST_REGNUM - FP0_REGNUM + 1); i++) 16646283Sdfr { 16746283Sdfr midregs[i] = -1; 16846283Sdfr } 16946283Sdfr mqreg[0] = -1; 17046283Sdfr#endif 17146283Sdfr 17246283Sdfr if (regno == -1) 17346283Sdfr { 17446283Sdfr first_regno = 0; 17546283Sdfr last_regno = NUM_REGS - 1; 17646283Sdfr 17746283Sdfr first_bdm_regno = 0; 17846283Sdfr last_bdm_regno = BDM_NUM_REGS - 1; 17946283Sdfr } 18046283Sdfr else 18146283Sdfr { 18246283Sdfr first_regno = regno; 18346283Sdfr last_regno = regno; 18446283Sdfr 18598944Sobrien first_bdm_regno = bdm_regmap[regno]; 18698944Sobrien last_bdm_regno = bdm_regmap[regno]; 18746283Sdfr } 18846283Sdfr 18946283Sdfr if (first_bdm_regno == -1) 19046283Sdfr { 19146283Sdfr supply_register (first_regno, NULL); 19246283Sdfr return; /* Unsupported register */ 19346283Sdfr } 19446283Sdfr 19546283Sdfr#if 1 19646283Sdfr /* Can't ask for floating point regs on ppc 8xx, also need to 19746283Sdfr avoid asking for the mq register. */ 19846283Sdfr if (first_regno == last_regno) /* only want one reg */ 19946283Sdfr { 20046283Sdfr/* printf("Asking for register %d\n", first_regno); */ 20146283Sdfr 20246283Sdfr /* if asking for an invalid register */ 20398944Sobrien if ((first_regno == gdbarch_tdep (current_gdbarch)->ppc_mq_regnum) 204130803Smarcel || (first_regno == gdbarch_tdep (current_gdbarch)->ppc_fpscr_regnum) 20598944Sobrien || ((first_regno >= FP0_REGNUM) && (first_regno <= FPLAST_REGNUM))) 20646283Sdfr { 20746283Sdfr/* printf("invalid reg request!\n"); */ 20898944Sobrien supply_register (first_regno, NULL); 20998944Sobrien return; /* Unsupported register */ 21098944Sobrien } 21146283Sdfr else 21246283Sdfr { 21398944Sobrien regs = ocd_read_bdm_registers (first_bdm_regno, 21498944Sobrien last_bdm_regno, ®len); 21598944Sobrien } 21646283Sdfr } 21798944Sobrien else 21898944Sobrien /* want all regs */ 21946283Sdfr { 22046283Sdfr/* printf("Asking for registers %d to %d\n", first_regno, last_regno); */ 22146283Sdfr beginregs = ocd_read_bdm_registers (first_bdm_regno, 22298944Sobrien FP0_REGNUM - 1, &beginreglen); 22398944Sobrien endregs = (strcat (midregs, 22498944Sobrien ocd_read_bdm_registers (FPLAST_REGNUM + 1, 22598944Sobrien last_bdm_regno - 1, &endreglen))); 22646283Sdfr almostregs = (strcat (beginregs, endregs)); 22746283Sdfr regs = (strcat (almostregs, mqreg)); 22846283Sdfr reglen = beginreglen + 32 + endreglen + 1; 22946283Sdfr } 23046283Sdfr 23146283Sdfr#endif 23246283Sdfr#if 0 23346283Sdfr regs = ocd_read_bdm_registers (first_bdm_regno, last_bdm_regno, ®len); 23446283Sdfr#endif 23546283Sdfr 23646283Sdfr for (i = first_regno; i <= last_regno; i++) 23746283Sdfr { 23846283Sdfr int bdm_regno, regoffset; 23946283Sdfr 24098944Sobrien bdm_regno = bdm_regmap[i]; 24146283Sdfr if (bdm_regno != -1) 24246283Sdfr { 24346283Sdfr regoffset = bdm_regno - first_bdm_regno; 24446283Sdfr 24546283Sdfr if (regoffset >= reglen / 4) 24646283Sdfr continue; 24746283Sdfr 24846283Sdfr supply_register (i, regs + 4 * regoffset); 24946283Sdfr } 25046283Sdfr else 25198944Sobrien supply_register (i, NULL); /* Unsupported register */ 25246283Sdfr } 25346283Sdfr} 25446283Sdfr 25546283Sdfr/* Store register REGNO, or all registers if REGNO == -1, from the contents 25646283Sdfr of REGISTERS. FIXME: ignores errors. */ 25746283Sdfr 25846283Sdfrstatic void 25998944Sobrienbdm_ppc_store_registers (int regno) 26046283Sdfr{ 26146283Sdfr int i; 26246283Sdfr int first_regno, last_regno; 26346283Sdfr int first_bdm_regno, last_bdm_regno; 26446283Sdfr 26546283Sdfr if (regno == -1) 26646283Sdfr { 26746283Sdfr first_regno = 0; 26846283Sdfr last_regno = NUM_REGS - 1; 26946283Sdfr 27046283Sdfr first_bdm_regno = 0; 27146283Sdfr last_bdm_regno = BDM_NUM_REGS - 1; 27246283Sdfr } 27346283Sdfr else 27446283Sdfr { 27546283Sdfr first_regno = regno; 27646283Sdfr last_regno = regno; 27746283Sdfr 27898944Sobrien first_bdm_regno = bdm_regmap[regno]; 27998944Sobrien last_bdm_regno = bdm_regmap[regno]; 28046283Sdfr } 28146283Sdfr 28246283Sdfr if (first_bdm_regno == -1) 28346283Sdfr return; /* Unsupported register */ 28446283Sdfr 28546283Sdfr for (i = first_regno; i <= last_regno; i++) 28646283Sdfr { 28746283Sdfr int bdm_regno; 28846283Sdfr 28998944Sobrien bdm_regno = bdm_regmap[i]; 29046283Sdfr 29146283Sdfr /* only attempt to write if it's a valid ppc 8xx register */ 29246283Sdfr /* (need to avoid FP regs and MQ reg) */ 293130803Smarcel if ((i != gdbarch_tdep (current_gdbarch)->ppc_mq_regnum) 294130803Smarcel && (i != gdbarch_tdep (current_gdbarch)->ppc_fpscr_regnum) 295130803Smarcel && ((i < FP0_REGNUM) || (i > FPLAST_REGNUM))) 29646283Sdfr { 29746283Sdfr/* printf("write valid reg %d\n", bdm_regno); */ 298130803Smarcel ocd_write_bdm_registers (bdm_regno, deprecated_registers + DEPRECATED_REGISTER_BYTE (i), 4); 29998944Sobrien } 30046283Sdfr/* 30198944Sobrien else if (i == gdbarch_tdep (current_gdbarch)->ppc_mq_regnum) 30298944Sobrien printf("don't write invalid reg %d (PPC_MQ_REGNUM)\n", bdm_regno); 30398944Sobrien else 30498944Sobrien printf("don't write invalid reg %d\n", bdm_regno); 30598944Sobrien */ 30646283Sdfr } 30746283Sdfr} 30846283Sdfr 30946283Sdfr/* Define the target subroutine names */ 31046283Sdfr 31198944Sobrienstruct target_ops bdm_ppc_ops; 31246283Sdfr 31398944Sobrienstatic void 31498944Sobrieninit_bdm_ppc_ops (void) 31546283Sdfr{ 31698944Sobrien bdm_ppc_ops.to_shortname = "ocd"; 31798944Sobrien bdm_ppc_ops.to_longname = "Remote target with On-Chip Debugging"; 31898944Sobrien bdm_ppc_ops.to_doc = "Use a remote target with On-Chip Debugging. To use a target box;\n\ 31946283Sdfrspecify the serial device it is connected to (e.g. /dev/ttya). To use\n\ 32046283Sdfra wiggler, specify wiggler and then the port it is connected to\n\ 32198944Sobrien(e.g. wiggler lpt1)."; /* to_doc */ 32298944Sobrien bdm_ppc_ops.to_open = bdm_ppc_open; 32398944Sobrien bdm_ppc_ops.to_close = ocd_close; 32498944Sobrien bdm_ppc_ops.to_detach = ocd_detach; 32598944Sobrien bdm_ppc_ops.to_resume = ocd_resume; 32698944Sobrien bdm_ppc_ops.to_wait = bdm_ppc_wait; 32798944Sobrien bdm_ppc_ops.to_fetch_registers = bdm_ppc_fetch_registers; 32898944Sobrien bdm_ppc_ops.to_store_registers = bdm_ppc_store_registers; 32998944Sobrien bdm_ppc_ops.to_prepare_to_store = ocd_prepare_to_store; 33098944Sobrien bdm_ppc_ops.to_xfer_memory = ocd_xfer_memory; 33198944Sobrien bdm_ppc_ops.to_files_info = ocd_files_info; 33298944Sobrien bdm_ppc_ops.to_insert_breakpoint = ocd_insert_breakpoint; 33398944Sobrien bdm_ppc_ops.to_remove_breakpoint = ocd_remove_breakpoint; 33498944Sobrien bdm_ppc_ops.to_kill = ocd_kill; 33598944Sobrien bdm_ppc_ops.to_load = ocd_load; 33698944Sobrien bdm_ppc_ops.to_create_inferior = ocd_create_inferior; 33798944Sobrien bdm_ppc_ops.to_mourn_inferior = ocd_mourn; 33898944Sobrien bdm_ppc_ops.to_thread_alive = ocd_thread_alive; 33998944Sobrien bdm_ppc_ops.to_stop = ocd_stop; 34098944Sobrien bdm_ppc_ops.to_stratum = process_stratum; 34198944Sobrien bdm_ppc_ops.to_has_all_memory = 1; 34298944Sobrien bdm_ppc_ops.to_has_memory = 1; 34398944Sobrien bdm_ppc_ops.to_has_stack = 1; 34498944Sobrien bdm_ppc_ops.to_has_registers = 1; 34598944Sobrien bdm_ppc_ops.to_has_execution = 1; 34698944Sobrien bdm_ppc_ops.to_magic = OPS_MAGIC; 34798944Sobrien} /* init_bdm_ppc_ops */ 34846283Sdfr 349130803Smarcelextern initialize_file_ftype _initialize_bdm_ppc; /* -Wmissing-prototypes */ 350130803Smarcel 35146283Sdfrvoid 35298944Sobrien_initialize_bdm_ppc (void) 35346283Sdfr{ 35498944Sobrien init_bdm_ppc_ops (); 35546283Sdfr add_target (&bdm_ppc_ops); 35646283Sdfr} 357