| 1 | /* Remote target communications for the Macraigor Systems BDM Wiggler |
| 2 | talking to a Motorola PPC 505. |
| 3 | Copyright 1996, 1997 Free Software Foundation, Inc. |
| 4 | |
| 5 | This file is part of GDB. |
| 6 | |
| 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. |
| 11 | |
| 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. |
| 16 | |
| 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. */ |
| 20 | |
| 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" |
| 38 | |
| 39 | static void bdm_ppc_open PARAMS ((char *name, int from_tty)); |
| 40 | |
| 41 | static int bdm_ppc_wait PARAMS ((int pid, |
| 42 | struct target_waitstatus *target_status)); |
| 43 | |
| 44 | static void bdm_ppc_fetch_registers PARAMS ((int regno)); |
| 45 | |
| 46 | static void bdm_ppc_store_registers PARAMS ((int regno)); |
| 47 | |
| 48 | extern struct target_ops bdm_ppc_ops; /* Forward decl */ |
| 49 | \f |
| 50 | /* Open a connection to a remote debugger. |
| 51 | NAME is the filename used for communication. */ |
| 52 | |
| 53 | static void |
| 54 | bdm_ppc_open (name, from_tty) |
| 55 | char *name; |
| 56 | int from_tty; |
| 57 | { |
| 58 | ocd_open (name, from_tty, OCD_TARGET_MOTO_PPC, &bdm_ppc_ops); |
| 59 | } |
| 60 | |
| 61 | /* Wait until the remote machine stops, then return, |
| 62 | storing status in STATUS just as `wait' would. |
| 63 | Returns "pid" (though it's not clear what, if anything, that |
| 64 | means in the case of this target). */ |
| 65 | |
| 66 | static int |
| 67 | bdm_ppc_wait (pid, target_status) |
| 68 | int pid; |
| 69 | struct target_waitstatus *target_status; |
| 70 | { |
| 71 | int stop_reason; |
| 72 | |
| 73 | target_status->kind = TARGET_WAITKIND_STOPPED; |
| 74 | |
| 75 | stop_reason = ocd_wait (); |
| 76 | |
| 77 | if (stop_reason) |
| 78 | { |
| 79 | target_status->value.sig = TARGET_SIGNAL_INT; |
| 80 | return inferior_pid; |
| 81 | } |
| 82 | |
| 83 | target_status->value.sig = TARGET_SIGNAL_TRAP; /* XXX for now */ |
| 84 | |
| 85 | { |
| 86 | unsigned long ecr, der; |
| 87 | |
| 88 | ecr = ocd_read_bdm_register (148); /* Read the exception cause register */ |
| 89 | der = ocd_read_bdm_register (149); /* Read the debug enables register */ |
| 90 | fprintf_unfiltered (gdb_stdout, "ecr = 0x%x, der = 0x%x\n", ecr, der); |
| 91 | } |
| 92 | |
| 93 | return inferior_pid; |
| 94 | } |
| 95 | \f |
| 96 | static int bdm_regmap[] = {BDM_REGMAP}; |
| 97 | |
| 98 | /* Read the remote registers into regs. |
| 99 | |
| 100 | The Wiggler uses the following codes to access the registers: |
| 101 | |
| 102 | 0 -> 1023 SPR 0 -> 1023 |
| 103 | 0 - SPR 0 - MQ |
| 104 | 1 - SPR 1 - XER |
| 105 | 8 - SPR 8 - LR |
| 106 | 9 - SPR 9 - CTR (known as cnt in GDB) |
| 107 | 26 - SPR 26 - SRR0 - pc |
| 108 | 1024 -> 2047 DCR 0 -> DCR 1023 (IBM PPC 4xx only) |
| 109 | 2048 -> 2079 R0 -> R31 |
| 110 | 2080 -> 2143 FP0 -> FP31 (64 bit regs) |
| 111 | 2144 CR (known as cnd in GDB) |
| 112 | 2145 FPCSR |
| 113 | 2146 MSR (known as ps in GDB) |
| 114 | */ |
| 115 | |
| 116 | static void |
| 117 | bdm_ppc_fetch_registers (regno) |
| 118 | int regno; |
| 119 | { |
| 120 | int i; |
| 121 | unsigned char *regs; |
| 122 | int first_regno, last_regno; |
| 123 | int first_bdm_regno, last_bdm_regno; |
| 124 | int reglen; |
| 125 | |
| 126 | if (regno == -1) |
| 127 | { |
| 128 | first_regno = 0; |
| 129 | last_regno = NUM_REGS - 1; |
| 130 | |
| 131 | first_bdm_regno = 0; |
| 132 | last_bdm_regno = BDM_NUM_REGS - 1; |
| 133 | } |
| 134 | else |
| 135 | { |
| 136 | first_regno = regno; |
| 137 | last_regno = regno; |
| 138 | |
| 139 | first_bdm_regno = bdm_regmap [regno]; |
| 140 | last_bdm_regno = bdm_regmap [regno]; |
| 141 | } |
| 142 | |
| 143 | if (first_bdm_regno == -1) |
| 144 | { |
| 145 | supply_register (first_regno, NULL); |
| 146 | return; /* Unsupported register */ |
| 147 | } |
| 148 | |
| 149 | regs = ocd_read_bdm_registers (first_bdm_regno, last_bdm_regno, ®len); |
| 150 | |
| 151 | for (i = first_regno; i <= last_regno; i++) |
| 152 | { |
| 153 | int bdm_regno, regoffset; |
| 154 | |
| 155 | bdm_regno = bdm_regmap [i]; |
| 156 | if (bdm_regno != -1) |
| 157 | { |
| 158 | regoffset = bdm_regno - first_bdm_regno; |
| 159 | |
| 160 | if (regoffset >= reglen / 4) |
| 161 | continue; |
| 162 | |
| 163 | supply_register (i, regs + 4 * regoffset); |
| 164 | } |
| 165 | else |
| 166 | supply_register (i, NULL); /* Unsupported register */ |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | /* Store register REGNO, or all registers if REGNO == -1, from the contents |
| 171 | of REGISTERS. FIXME: ignores errors. */ |
| 172 | |
| 173 | static void |
| 174 | bdm_ppc_store_registers (regno) |
| 175 | int regno; |
| 176 | { |
| 177 | int i; |
| 178 | int first_regno, last_regno; |
| 179 | int first_bdm_regno, last_bdm_regno; |
| 180 | |
| 181 | if (regno == -1) |
| 182 | { |
| 183 | first_regno = 0; |
| 184 | last_regno = NUM_REGS - 1; |
| 185 | |
| 186 | first_bdm_regno = 0; |
| 187 | last_bdm_regno = BDM_NUM_REGS - 1; |
| 188 | } |
| 189 | else |
| 190 | { |
| 191 | first_regno = regno; |
| 192 | last_regno = regno; |
| 193 | |
| 194 | first_bdm_regno = bdm_regmap [regno]; |
| 195 | last_bdm_regno = bdm_regmap [regno]; |
| 196 | } |
| 197 | |
| 198 | if (first_bdm_regno == -1) |
| 199 | return; /* Unsupported register */ |
| 200 | |
| 201 | for (i = first_regno; i <= last_regno; i++) |
| 202 | { |
| 203 | int bdm_regno; |
| 204 | |
| 205 | bdm_regno = bdm_regmap [i]; |
| 206 | |
| 207 | ocd_write_bdm_registers (bdm_regno, registers + REGISTER_BYTE (i), 4); |
| 208 | } |
| 209 | } |
| 210 | \f |
| 211 | /* Define the target subroutine names */ |
| 212 | |
| 213 | struct target_ops bdm_ppc_ops = { |
| 214 | "ocd", /* to_shortname */ |
| 215 | "", /* to_longname */ |
| 216 | "", /* to_doc */ |
| 217 | bdm_ppc_open, /* to_open */ |
| 218 | ocd_close, /* to_close */ |
| 219 | NULL, /* to_attach */ |
| 220 | ocd_detach, /* to_detach */ |
| 221 | ocd_resume, /* to_resume */ |
| 222 | bdm_ppc_wait, /* to_wait */ |
| 223 | bdm_ppc_fetch_registers, /* to_fetch_registers */ |
| 224 | bdm_ppc_store_registers, /* to_store_registers */ |
| 225 | ocd_prepare_to_store, /* to_prepare_to_store */ |
| 226 | ocd_xfer_memory, /* to_xfer_memory */ |
| 227 | ocd_files_info, /* to_files_info */ |
| 228 | memory_insert_breakpoint, /* to_insert_breakpoint */ |
| 229 | memory_remove_breakpoint, /* to_remove_breakpoint */ |
| 230 | NULL, /* to_terminal_init */ |
| 231 | NULL, /* to_terminal_inferior */ |
| 232 | NULL, /* to_terminal_ours_for_output */ |
| 233 | NULL, /* to_terminal_ours */ |
| 234 | NULL, /* to_terminal_info */ |
| 235 | ocd_kill, /* to_kill */ |
| 236 | ocd_load, /* to_load */ |
| 237 | NULL, /* to_lookup_symbol */ |
| 238 | ocd_create_inferior, /* to_create_inferior */ |
| 239 | ocd_mourn, /* to_mourn_inferior */ |
| 240 | 0, /* to_can_run */ |
| 241 | 0, /* to_notice_signals */ |
| 242 | ocd_thread_alive, /* to_thread_alive */ |
| 243 | ocd_stop, /* to_stop */ |
| 244 | process_stratum, /* to_stratum */ |
| 245 | NULL, /* to_next */ |
| 246 | 1, /* to_has_all_memory */ |
| 247 | 1, /* to_has_memory */ |
| 248 | 1, /* to_has_stack */ |
| 249 | 1, /* to_has_registers */ |
| 250 | 1, /* to_has_execution */ |
| 251 | NULL, /* sections */ |
| 252 | NULL, /* sections_end */ |
| 253 | OPS_MAGIC /* to_magic */ |
| 254 | }; |
| 255 | |
| 256 | void |
| 257 | _initialize_bdm_ppc () |
| 258 | { |
| 259 | add_target (&bdm_ppc_ops); |
| 260 | } |