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