1162298Simp/* $FreeBSD$ */ 2162298Simp 3162298Simp /* Native-dependent code for BSD Unix running on ARM's, for GDB. 4162298Simp Copyright 1988, 1989, 1991, 1992, 1994, 1996, 1999, 2002 5162298Simp Free Software Foundation, Inc. 6162298Simp 7162298Simp This file is part of GDB. 8162298Simp 9162298Simp This program is free software; you can redistribute it and/or modify 10162298Simp it under the terms of the GNU General Public License as published by 11162298Simp the Free Software Foundation; either version 2 of the License, or 12162298Simp (at your option) any later version. 13162298Simp 14162298Simp This program is distributed in the hope that it will be useful, 15162298Simp but WITHOUT ANY WARRANTY; without even the implied warranty of 16162298Simp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17162298Simp GNU General Public License for more details. 18162298Simp 19162298Simp You should have received a copy of the GNU General Public License 20162298Simp along with this program; if not, write to the Free Software 21162298Simp Foundation, Inc., 59 Temple Place - Suite 330, 22162298Simp Boston, MA 02111-1307, USA. */ 23162298Simp 24162298Simp#include "defs.h" 25162298Simp 26162298Simp#ifndef FETCH_INFERIOR_REGISTERS 27162298Simp#ifndef CROSS_DEBUGGER 28162298Simp#error Not FETCH_INFERIOR_REGISTERS 29162298Simp#endif 30162298Simp#endif /* !FETCH_INFERIOR_REGISTERS */ 31162298Simp 32162298Simp#include "arm-tdep.h" 33162298Simp 34162298Simp#include <sys/types.h> 35225190Scognet#ifndef CROSS_DEBUGGER 36162298Simp#include <sys/ptrace.h> 37162298Simp#include <machine/reg.h> 38162298Simp#include <machine/frame.h> 39162298Simp#endif 40162298Simp#include "inferior.h" 41162298Simp#include "regcache.h" 42162298Simp#include "gdbcore.h" 43162298Simp 44162298Simpextern int arm_apcs_32; 45162298Simp 46162298Simp#ifdef CROSS_DEBUGGER 47162298Simpstruct reg { 48162298Simp unsigned int r[13]; 49162298Simp unsigned int r_sp; 50162298Simp unsigned int r_lr; 51162298Simp unsigned int r_pc; 52162298Simp unsigned int r_cpsr; 53162298Simp}; 54162298Simp 55162298Simptypedef struct fp_extended_precision { 56162298Simp u_int32_t fp_exponent; 57162298Simp u_int32_t fp_mantissa_hi; 58162298Simp u_int32_t fp_mantissa_lo; 59162298Simp} fp_extended_precision_t; 60162298Simp 61162298Simptypedef struct fp_extended_precision fp_reg_t; 62162298Simp 63162298Simpstruct fpreg { 64162298Simp unsigned int fpr_fpsr; 65162298Simp fp_reg_t fpr[8]; 66162298Simp}; 67162298Simp#endif 68162298Simp 69162298Simpvoid 70162298Simpsupply_gregset (struct reg *gregset) 71162298Simp{ 72162298Simp int regno; 73162298Simp CORE_ADDR r_pc; 74162298Simp 75162298Simp /* Integer registers. */ 76162298Simp for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) 77162298Simp supply_register (regno, (char *) &gregset->r[regno]); 78162298Simp 79162298Simp supply_register (ARM_SP_REGNUM, (char *) &gregset->r_sp); 80162298Simp supply_register (ARM_LR_REGNUM, (char *) &gregset->r_lr); 81173705Scognet supply_register (ARM_PC_REGNUM, (char *) &gregset->r_pc); 82162298Simp 83162298Simp if (arm_apcs_32) 84162298Simp supply_register (ARM_PS_REGNUM, (char *) &gregset->r_cpsr); 85162298Simp else 86162298Simp supply_register (ARM_PS_REGNUM, (char *) &gregset->r_pc); 87162298Simp} 88162298Simp 89173705Scognet/* Fill register REGNO (if it is a general-purpose register) in 90173705Scognet *GREGSETPS with the value in GDB's register array. If REGNO is -1, 91173705Scognet do this for all registers. */ 92173705Scognet 93162298Simpvoid 94173705Scognetfill_gregset (struct reg *gregset, int regno) 95173705Scognet{ 96173705Scognet int i; 97173705Scognet 98173705Scognet for (i = ARM_A1_REGNUM; i < ARM_SP_REGNUM; i++) 99173705Scognet if ((regno == -1 || regno == i)) 100173705Scognet regcache_collect (i, &gregset->r[i]); 101173705Scognet if (regno == -1 || regno == ARM_SP_REGNUM) 102173705Scognet regcache_collect (ARM_SP_REGNUM, &gregset->r_sp); 103173705Scognet if (regno == -1 || regno == ARM_LR_REGNUM) 104173705Scognet regcache_collect (ARM_LR_REGNUM, &gregset->r_lr); 105173705Scognet if (regno == -1 || regno == ARM_PC_REGNUM) 106173705Scognet regcache_collect (ARM_PC_REGNUM, &gregset->r_pc); 107173705Scognet if (regno == -1 || regno == ARM_PS_REGNUM) 108173705Scognet regcache_collect (ARM_PS_REGNUM, &gregset->r_cpsr); 109173705Scognet} 110173705Scognet 111173705Scognetvoid 112162298Simpsupply_fpregset (struct fpreg *fparegset) 113162298Simp{ 114162298Simp int regno; 115162298Simp 116162298Simp for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++) 117162298Simp supply_register 118162298Simp (regno, (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]); 119162298Simp 120162298Simp supply_register (ARM_FPS_REGNUM, (char *) &fparegset->fpr_fpsr); 121162298Simp} 122162298Simp 123173705Scognetvoid 124173705Scognetfill_fpregset (struct fpreg *fparegset, int regno) 125173705Scognet{ 126173705Scognet int i; 127173705Scognet 128173705Scognet for (i = ARM_F0_REGNUM; i <= ARM_F7_REGNUM; i++) 129173705Scognet if (regno == -1 || regno == i) 130173705Scognet regcache_raw_supply(current_regcache, i, 131173705Scognet &fparegset->fpr[i - ARM_F0_REGNUM]); 132173705Scognet if (regno == -1 || regno == ARM_FPS_REGNUM) 133173705Scognet regcache_raw_supply(current_regcache, ARM_FPS_REGNUM, 134173705Scognet &fparegset->fpr_fpsr); 135173705Scognet} 136173705Scognet 137162298Simpstatic void 138162298Simpfetch_register (int regno) 139162298Simp{ 140162298Simp struct reg inferior_registers; 141162298Simp#ifndef CROSS_DEBUGGER 142162298Simp int ret; 143162298Simp 144162298Simp ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid), 145162298Simp (PTRACE_ARG3_TYPE) &inferior_registers, 0); 146162298Simp 147162298Simp if (ret < 0) 148162298Simp { 149162298Simp warning ("unable to fetch general register"); 150162298Simp return; 151162298Simp } 152162298Simp#endif 153162298Simp 154162298Simp switch (regno) 155162298Simp { 156162298Simp case ARM_SP_REGNUM: 157162298Simp supply_register (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); 158162298Simp break; 159162298Simp 160162298Simp case ARM_LR_REGNUM: 161162298Simp supply_register (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); 162162298Simp break; 163162298Simp 164162298Simp case ARM_PC_REGNUM: 165162298Simp /* This is ok: we're running native... */ 166162298Simp inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc); 167162298Simp supply_register (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc); 168162298Simp break; 169162298Simp 170162298Simp case ARM_PS_REGNUM: 171162298Simp if (arm_apcs_32) 172162298Simp supply_register (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr); 173162298Simp else 174162298Simp supply_register (ARM_PS_REGNUM, (char *) &inferior_registers.r_pc); 175162298Simp break; 176162298Simp 177162298Simp default: 178162298Simp supply_register (regno, (char *) &inferior_registers.r[regno]); 179162298Simp break; 180162298Simp } 181162298Simp} 182162298Simp 183162298Simpstatic void 184162298Simpfetch_regs (void) 185162298Simp{ 186162298Simp struct reg inferior_registers; 187162298Simp#ifndef CROSS_DEBUGGER 188162298Simp int ret; 189162298Simp#endif 190162298Simp int regno; 191162298Simp 192162298Simp#ifndef CROSS_DEBUGGER 193162298Simp ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid), 194162298Simp (PTRACE_ARG3_TYPE) &inferior_registers, 0); 195162298Simp 196162298Simp if (ret < 0) 197162298Simp { 198162298Simp warning ("unable to fetch general registers"); 199162298Simp return; 200162298Simp } 201162298Simp#endif 202162298Simp 203162298Simp supply_gregset (&inferior_registers); 204162298Simp} 205162298Simp 206162298Simpstatic void 207162298Simpfetch_fp_register (int regno) 208162298Simp{ 209162298Simp struct fpreg inferior_fp_registers; 210162298Simp#ifndef CROSS_DEBUGGER 211162298Simp int ret; 212162298Simp 213162298Simp ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), 214162298Simp (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0); 215162298Simp 216162298Simp if (ret < 0) 217162298Simp { 218162298Simp warning ("unable to fetch floating-point register"); 219162298Simp return; 220162298Simp } 221162298Simp#endif 222162298Simp 223162298Simp switch (regno) 224162298Simp { 225162298Simp case ARM_FPS_REGNUM: 226162298Simp supply_register (ARM_FPS_REGNUM, 227162298Simp (char *) &inferior_fp_registers.fpr_fpsr); 228162298Simp break; 229162298Simp 230162298Simp default: 231162298Simp supply_register 232162298Simp (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); 233162298Simp break; 234162298Simp } 235162298Simp} 236162298Simp 237162298Simpstatic void 238162298Simpfetch_fp_regs (void) 239162298Simp{ 240162298Simp struct fpreg inferior_fp_registers; 241162298Simp#ifndef CROSS_DEBUGGER 242162298Simp int ret; 243162298Simp#endif 244162298Simp int regno; 245162298Simp 246162298Simp#ifndef CROSS_DEBUGGER 247162298Simp ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), 248162298Simp (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0); 249162298Simp 250162298Simp if (ret < 0) 251162298Simp { 252162298Simp warning ("unable to fetch general registers"); 253162298Simp return; 254162298Simp } 255162298Simp#endif 256162298Simp 257162298Simp supply_fpregset (&inferior_fp_registers); 258162298Simp} 259162298Simp 260162298Simpvoid 261162298Simpfetch_inferior_registers (int regno) 262162298Simp{ 263162298Simp if (regno >= 0) 264162298Simp { 265162298Simp if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM) 266162298Simp fetch_register (regno); 267162298Simp else 268162298Simp fetch_fp_register (regno); 269162298Simp } 270162298Simp else 271162298Simp { 272162298Simp fetch_regs (); 273162298Simp fetch_fp_regs (); 274162298Simp } 275162298Simp} 276162298Simp 277162298Simp 278162298Simpstatic void 279162298Simpstore_register (int regno) 280162298Simp{ 281162298Simp struct reg inferior_registers; 282162298Simp#ifndef CROSS_DEBUGGER 283162298Simp int ret; 284162298Simp 285162298Simp ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid), 286162298Simp (PTRACE_ARG3_TYPE) &inferior_registers, 0); 287162298Simp 288162298Simp if (ret < 0) 289162298Simp { 290162298Simp warning ("unable to fetch general registers"); 291162298Simp return; 292162298Simp } 293162298Simp#endif 294162298Simp 295162298Simp switch (regno) 296162298Simp { 297162298Simp case ARM_SP_REGNUM: 298162298Simp regcache_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); 299162298Simp break; 300162298Simp 301162298Simp case ARM_LR_REGNUM: 302162298Simp regcache_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); 303162298Simp break; 304162298Simp 305162298Simp case ARM_PC_REGNUM: 306162298Simp if (arm_apcs_32) 307162298Simp regcache_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc); 308162298Simp else 309162298Simp { 310162298Simp unsigned pc_val; 311162298Simp 312162298Simp regcache_collect (ARM_PC_REGNUM, (char *) &pc_val); 313162298Simp 314162298Simp pc_val = ADDR_BITS_REMOVE (pc_val); 315162298Simp inferior_registers.r_pc 316162298Simp ^= ADDR_BITS_REMOVE (inferior_registers.r_pc); 317162298Simp inferior_registers.r_pc |= pc_val; 318162298Simp } 319162298Simp break; 320162298Simp 321162298Simp case ARM_PS_REGNUM: 322162298Simp if (arm_apcs_32) 323162298Simp regcache_collect (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr); 324162298Simp else 325162298Simp { 326162298Simp unsigned psr_val; 327162298Simp 328162298Simp regcache_collect (ARM_PS_REGNUM, (char *) &psr_val); 329162298Simp 330162298Simp psr_val ^= ADDR_BITS_REMOVE (psr_val); 331162298Simp inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc); 332162298Simp inferior_registers.r_pc |= psr_val; 333162298Simp } 334162298Simp break; 335162298Simp 336162298Simp default: 337162298Simp regcache_collect (regno, (char *) &inferior_registers.r[regno]); 338162298Simp break; 339162298Simp } 340162298Simp 341162298Simp#ifndef CROSS_DEBUGGER 342162298Simp ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid), 343162298Simp (PTRACE_ARG3_TYPE) &inferior_registers, 0); 344162298Simp 345162298Simp if (ret < 0) 346162298Simp warning ("unable to write register %d to inferior", regno); 347162298Simp#endif 348162298Simp} 349162298Simp 350162298Simpstatic void 351162298Simpstore_regs (void) 352162298Simp{ 353162298Simp struct reg inferior_registers; 354162298Simp int ret; 355162298Simp int regno; 356162298Simp 357162298Simp 358162298Simp for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) 359162298Simp regcache_collect (regno, (char *) &inferior_registers.r[regno]); 360162298Simp 361162298Simp regcache_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); 362162298Simp regcache_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); 363162298Simp 364162298Simp if (arm_apcs_32) 365162298Simp { 366162298Simp regcache_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc); 367162298Simp regcache_collect (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr); 368162298Simp } 369162298Simp else 370162298Simp { 371162298Simp unsigned pc_val; 372162298Simp unsigned psr_val; 373162298Simp 374162298Simp regcache_collect (ARM_PC_REGNUM, (char *) &pc_val); 375162298Simp regcache_collect (ARM_PS_REGNUM, (char *) &psr_val); 376162298Simp 377162298Simp pc_val = ADDR_BITS_REMOVE (pc_val); 378162298Simp psr_val ^= ADDR_BITS_REMOVE (psr_val); 379162298Simp 380162298Simp inferior_registers.r_pc = pc_val | psr_val; 381162298Simp } 382162298Simp 383162298Simp#ifndef CROSS_DEBUGGER 384162298Simp ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid), 385162298Simp (PTRACE_ARG3_TYPE) &inferior_registers, 0); 386162298Simp 387162298Simp if (ret < 0) 388162298Simp warning ("unable to store general registers"); 389162298Simp#endif 390162298Simp} 391162298Simp 392162298Simpstatic void 393162298Simpstore_fp_register (int regno) 394162298Simp{ 395162298Simp struct fpreg inferior_fp_registers; 396162298Simp#ifndef CROSS_DEBUGGER 397162298Simp int ret; 398162298Simp 399162298Simp ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), 400162298Simp (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0); 401162298Simp 402162298Simp if (ret < 0) 403162298Simp { 404162298Simp warning ("unable to fetch floating-point registers"); 405162298Simp return; 406162298Simp } 407162298Simp#endif 408162298Simp 409162298Simp switch (regno) 410162298Simp { 411162298Simp case ARM_FPS_REGNUM: 412162298Simp regcache_collect (ARM_FPS_REGNUM, 413162298Simp (char *) &inferior_fp_registers.fpr_fpsr); 414162298Simp break; 415162298Simp 416162298Simp default: 417162298Simp regcache_collect 418162298Simp (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); 419162298Simp break; 420162298Simp } 421162298Simp 422162298Simp#ifndef CROSS_DEBUGGER 423162298Simp ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid), 424162298Simp (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0); 425162298Simp 426162298Simp if (ret < 0) 427162298Simp warning ("unable to write register %d to inferior", regno); 428162298Simp#endif 429162298Simp} 430162298Simp 431162298Simpstatic void 432162298Simpstore_fp_regs (void) 433162298Simp{ 434162298Simp struct fpreg inferior_fp_registers; 435162298Simp int ret; 436162298Simp int regno; 437162298Simp 438162298Simp 439162298Simp for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++) 440162298Simp regcache_collect 441162298Simp (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); 442162298Simp 443162298Simp regcache_collect (ARM_FPS_REGNUM, (char *) &inferior_fp_registers.fpr_fpsr); 444162298Simp 445162298Simp#ifndef CROSS_DEBUGGER 446162298Simp ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid), 447162298Simp (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0); 448162298Simp 449162298Simp if (ret < 0) 450162298Simp warning ("unable to store floating-point registers"); 451162298Simp#endif 452162298Simp} 453162298Simp 454162298Simpvoid 455162298Simpstore_inferior_registers (int regno) 456162298Simp{ 457162298Simp if (regno >= 0) 458162298Simp { 459162298Simp if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM) 460162298Simp store_register (regno); 461162298Simp else 462162298Simp store_fp_register (regno); 463162298Simp } 464162298Simp else 465162298Simp { 466162298Simp store_regs (); 467162298Simp store_fp_regs (); 468162298Simp } 469162298Simp} 470162298Simp 471162298Simp 472162298Simpstruct md_core 473162298Simp{ 474162298Simp struct reg intreg; 475162298Simp struct fpreg freg; 476162298Simp}; 477162298Simp 478162298Simpstatic void 479162298Simpfetch_core_registers (char *core_reg_sect, unsigned core_reg_size, 480162298Simp int which, CORE_ADDR ignore) 481162298Simp{ 482162298Simp struct md_core *core_reg = (struct md_core *) core_reg_sect; 483162298Simp int regno; 484162298Simp CORE_ADDR r_pc; 485162298Simp 486162298Simp supply_gregset (&core_reg->intreg); 487162298Simp supply_fpregset (&core_reg->freg); 488162298Simp} 489162298Simp 490162298Simpstatic void 491162298Simpfetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size, 492162298Simp int which, CORE_ADDR ignore) 493162298Simp{ 494162298Simp struct reg gregset; 495162298Simp struct fpreg fparegset; 496162298Simp 497162298Simp switch (which) 498162298Simp { 499162298Simp case 0: /* Integer registers. */ 500162298Simp if (core_reg_size != sizeof (struct reg)) 501162298Simp warning ("wrong size of register set in core file"); 502162298Simp else 503162298Simp { 504162298Simp /* The memcpy may be unnecessary, but we can't really be sure 505162298Simp of the alignment of the data in the core file. */ 506162298Simp memcpy (&gregset, core_reg_sect, sizeof (gregset)); 507162298Simp supply_gregset (&gregset); 508162298Simp } 509162298Simp break; 510162298Simp 511162298Simp case 2: 512162298Simp if (core_reg_size != sizeof (struct fpreg)) 513162298Simp warning ("wrong size of FPA register set in core file"); 514162298Simp else 515162298Simp { 516162298Simp /* The memcpy may be unnecessary, but we can't really be sure 517162298Simp of the alignment of the data in the core file. */ 518162298Simp memcpy (&fparegset, core_reg_sect, sizeof (fparegset)); 519162298Simp supply_fpregset (&fparegset); 520162298Simp } 521162298Simp break; 522162298Simp 523162298Simp default: 524162298Simp /* Don't know what kind of register request this is; just ignore it. */ 525162298Simp break; 526162298Simp } 527162298Simp} 528162298Simp 529162298Simpstatic struct core_fns arm_freebsd_core_fns = 530162298Simp{ 531162298Simp bfd_target_unknown_flavour, /* core_flovour. */ 532162298Simp default_check_format, /* check_format. */ 533162298Simp default_core_sniffer, /* core_sniffer. */ 534162298Simp fetch_core_registers, /* core_read_registers. */ 535162298Simp NULL 536162298Simp}; 537162298Simp 538162298Simpstatic struct core_fns arm_freebsd_elfcore_fns = 539162298Simp{ 540162298Simp bfd_target_elf_flavour, /* core_flovour. */ 541162298Simp default_check_format, /* check_format. */ 542162298Simp default_core_sniffer, /* core_sniffer. */ 543162298Simp fetch_elfcore_registers, /* core_read_registers. */ 544162298Simp NULL 545162298Simp}; 546162298Simp 547162298Simpvoid 548162298Simp_initialize_arm_fbsdnat (void) 549162298Simp{ 550162298Simp add_core_fns (&arm_freebsd_core_fns); 551162298Simp add_core_fns (&arm_freebsd_elfcore_fns); 552162298Simp} 553