1/* Native-dependent code for BSD Unix running on ARM's, for GDB. 2 Copyright 1988, 1989, 1991, 1992, 1994, 1996, 1999, 2002 3 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, 20 Boston, MA 02111-1307, USA. */ 21 22#include "defs.h" 23 24#ifndef FETCH_INFERIOR_REGISTERS 25#error Not FETCH_INFERIOR_REGISTERS 26#endif /* !FETCH_INFERIOR_REGISTERS */ 27 28#include "arm-tdep.h" 29 30#include <sys/types.h> 31#include <sys/ptrace.h> 32#include <machine/reg.h> 33#include <machine/frame.h> 34#include "inferior.h" 35#include "regcache.h" 36#include "gdbcore.h" 37 38extern int arm_apcs_32; 39 40static void 41supply_gregset (struct reg *gregset) 42{ 43 int regno; 44 CORE_ADDR r_pc; 45 46 /* Integer registers. */ 47 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) 48 supply_register (regno, (char *) &gregset->r[regno]); 49 50 supply_register (ARM_SP_REGNUM, (char *) &gregset->r_sp); 51 supply_register (ARM_LR_REGNUM, (char *) &gregset->r_lr); 52 /* This is ok: we're running native... */ 53 r_pc = ADDR_BITS_REMOVE (gregset->r_pc); 54 supply_register (ARM_PC_REGNUM, (char *) &r_pc); 55 56 if (arm_apcs_32) 57 supply_register (ARM_PS_REGNUM, (char *) &gregset->r_cpsr); 58 else 59 supply_register (ARM_PS_REGNUM, (char *) &gregset->r_pc); 60} 61 62static void 63supply_fparegset (struct fpreg *fparegset) 64{ 65 int regno; 66 67 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++) 68 supply_register 69 (regno, (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]); 70 71 supply_register (ARM_FPS_REGNUM, (char *) &fparegset->fpr_fpsr); 72} 73 74static void 75fetch_register (int regno) 76{ 77 struct reg inferior_registers; 78 int ret; 79 80 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid), 81 (PTRACE_ARG3_TYPE) &inferior_registers, 0); 82 83 if (ret < 0) 84 { 85 warning ("unable to fetch general register"); 86 return; 87 } 88 89 switch (regno) 90 { 91 case ARM_SP_REGNUM: 92 supply_register (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); 93 break; 94 95 case ARM_LR_REGNUM: 96 supply_register (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); 97 break; 98 99 case ARM_PC_REGNUM: 100 /* This is ok: we're running native... */ 101 inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc); 102 supply_register (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc); 103 break; 104 105 case ARM_PS_REGNUM: 106 if (arm_apcs_32) 107 supply_register (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr); 108 else 109 supply_register (ARM_PS_REGNUM, (char *) &inferior_registers.r_pc); 110 break; 111 112 default: 113 supply_register (regno, (char *) &inferior_registers.r[regno]); 114 break; 115 } 116} 117 118static void 119fetch_regs (void) 120{ 121 struct reg inferior_registers; 122 int ret; 123 int regno; 124 125 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid), 126 (PTRACE_ARG3_TYPE) &inferior_registers, 0); 127 128 if (ret < 0) 129 { 130 warning ("unable to fetch general registers"); 131 return; 132 } 133 134 supply_gregset (&inferior_registers); 135} 136 137static void 138fetch_fp_register (int regno) 139{ 140 struct fpreg inferior_fp_registers; 141 int ret; 142 143 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), 144 (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0); 145 146 if (ret < 0) 147 { 148 warning ("unable to fetch floating-point register"); 149 return; 150 } 151 152 switch (regno) 153 { 154 case ARM_FPS_REGNUM: 155 supply_register (ARM_FPS_REGNUM, 156 (char *) &inferior_fp_registers.fpr_fpsr); 157 break; 158 159 default: 160 supply_register 161 (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); 162 break; 163 } 164} 165 166static void 167fetch_fp_regs (void) 168{ 169 struct fpreg inferior_fp_registers; 170 int ret; 171 int regno; 172 173 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), 174 (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0); 175 176 if (ret < 0) 177 { 178 warning ("unable to fetch general registers"); 179 return; 180 } 181 182 supply_fparegset (&inferior_fp_registers); 183} 184 185void 186fetch_inferior_registers (int regno) 187{ 188 if (regno >= 0) 189 { 190 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM) 191 fetch_register (regno); 192 else 193 fetch_fp_register (regno); 194 } 195 else 196 { 197 fetch_regs (); 198 fetch_fp_regs (); 199 } 200} 201 202 203static void 204store_register (int regno) 205{ 206 struct reg inferior_registers; 207 int ret; 208 209 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid), 210 (PTRACE_ARG3_TYPE) &inferior_registers, 0); 211 212 if (ret < 0) 213 { 214 warning ("unable to fetch general registers"); 215 return; 216 } 217 218 switch (regno) 219 { 220 case ARM_SP_REGNUM: 221 regcache_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); 222 break; 223 224 case ARM_LR_REGNUM: 225 regcache_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); 226 break; 227 228 case ARM_PC_REGNUM: 229 if (arm_apcs_32) 230 regcache_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc); 231 else 232 { 233 unsigned pc_val; 234 235 regcache_collect (ARM_PC_REGNUM, (char *) &pc_val); 236 237 pc_val = ADDR_BITS_REMOVE (pc_val); 238 inferior_registers.r_pc 239 ^= ADDR_BITS_REMOVE (inferior_registers.r_pc); 240 inferior_registers.r_pc |= pc_val; 241 } 242 break; 243 244 case ARM_PS_REGNUM: 245 if (arm_apcs_32) 246 regcache_collect (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr); 247 else 248 { 249 unsigned psr_val; 250 251 regcache_collect (ARM_PS_REGNUM, (char *) &psr_val); 252 253 psr_val ^= ADDR_BITS_REMOVE (psr_val); 254 inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc); 255 inferior_registers.r_pc |= psr_val; 256 } 257 break; 258 259 default: 260 regcache_collect (regno, (char *) &inferior_registers.r[regno]); 261 break; 262 } 263 264 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid), 265 (PTRACE_ARG3_TYPE) &inferior_registers, 0); 266 267 if (ret < 0) 268 warning ("unable to write register %d to inferior", regno); 269} 270 271static void 272store_regs (void) 273{ 274 struct reg inferior_registers; 275 int ret; 276 int regno; 277 278 279 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) 280 regcache_collect (regno, (char *) &inferior_registers.r[regno]); 281 282 regcache_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); 283 regcache_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); 284 285 if (arm_apcs_32) 286 { 287 regcache_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc); 288 regcache_collect (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr); 289 } 290 else 291 { 292 unsigned pc_val; 293 unsigned psr_val; 294 295 regcache_collect (ARM_PC_REGNUM, (char *) &pc_val); 296 regcache_collect (ARM_PS_REGNUM, (char *) &psr_val); 297 298 pc_val = ADDR_BITS_REMOVE (pc_val); 299 psr_val ^= ADDR_BITS_REMOVE (psr_val); 300 301 inferior_registers.r_pc = pc_val | psr_val; 302 } 303 304 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid), 305 (PTRACE_ARG3_TYPE) &inferior_registers, 0); 306 307 if (ret < 0) 308 warning ("unable to store general registers"); 309} 310 311static void 312store_fp_register (int regno) 313{ 314 struct fpreg inferior_fp_registers; 315 int ret; 316 317 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), 318 (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0); 319 320 if (ret < 0) 321 { 322 warning ("unable to fetch floating-point registers"); 323 return; 324 } 325 326 switch (regno) 327 { 328 case ARM_FPS_REGNUM: 329 regcache_collect (ARM_FPS_REGNUM, 330 (char *) &inferior_fp_registers.fpr_fpsr); 331 break; 332 333 default: 334 regcache_collect 335 (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); 336 break; 337 } 338 339 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid), 340 (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0); 341 342 if (ret < 0) 343 warning ("unable to write register %d to inferior", regno); 344} 345 346static void 347store_fp_regs (void) 348{ 349 struct fpreg inferior_fp_registers; 350 int ret; 351 int regno; 352 353 354 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++) 355 regcache_collect 356 (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); 357 358 regcache_collect (ARM_FPS_REGNUM, (char *) &inferior_fp_registers.fpr_fpsr); 359 360 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid), 361 (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0); 362 363 if (ret < 0) 364 warning ("unable to store floating-point registers"); 365} 366 367void 368store_inferior_registers (int regno) 369{ 370 if (regno >= 0) 371 { 372 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM) 373 store_register (regno); 374 else 375 store_fp_register (regno); 376 } 377 else 378 { 379 store_regs (); 380 store_fp_regs (); 381 } 382} 383 384struct md_core 385{ 386 struct reg intreg; 387 struct fpreg freg; 388}; 389 390static void 391fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, 392 int which, CORE_ADDR ignore) 393{ 394 struct md_core *core_reg = (struct md_core *) core_reg_sect; 395 int regno; 396 CORE_ADDR r_pc; 397 398 supply_gregset (&core_reg->intreg); 399 supply_fparegset (&core_reg->freg); 400} 401 402static void 403fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size, 404 int which, CORE_ADDR ignore) 405{ 406 struct reg gregset; 407 struct fpreg fparegset; 408 409 switch (which) 410 { 411 case 0: /* Integer registers. */ 412 if (core_reg_size != sizeof (struct reg)) 413 warning ("wrong size of register set in core file"); 414 else 415 { 416 /* The memcpy may be unnecessary, but we can't really be sure 417 of the alignment of the data in the core file. */ 418 memcpy (&gregset, core_reg_sect, sizeof (gregset)); 419 supply_gregset (&gregset); 420 } 421 break; 422 423 case 2: 424 if (core_reg_size != sizeof (struct fpreg)) 425 warning ("wrong size of FPA register set in core file"); 426 else 427 { 428 /* The memcpy may be unnecessary, but we can't really be sure 429 of the alignment of the data in the core file. */ 430 memcpy (&fparegset, core_reg_sect, sizeof (fparegset)); 431 supply_fparegset (&fparegset); 432 } 433 break; 434 435 default: 436 /* Don't know what kind of register request this is; just ignore it. */ 437 break; 438 } 439} 440 441static struct core_fns arm_netbsd_core_fns = 442{ 443 bfd_target_unknown_flavour, /* core_flovour. */ 444 default_check_format, /* check_format. */ 445 default_core_sniffer, /* core_sniffer. */ 446 fetch_core_registers, /* core_read_registers. */ 447 NULL 448}; 449 450static struct core_fns arm_netbsd_elfcore_fns = 451{ 452 bfd_target_elf_flavour, /* core_flovour. */ 453 default_check_format, /* check_format. */ 454 default_core_sniffer, /* core_sniffer. */ 455 fetch_elfcore_registers, /* core_read_registers. */ 456 NULL 457}; 458 459void 460_initialize_arm_netbsd_nat (void) 461{ 462 add_core_fns (&arm_netbsd_core_fns); 463 add_core_fns (&arm_netbsd_elfcore_fns); 464} 465