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