198944Sobrien/* Native-dependent code for BSD Unix running on ARM's, for GDB. 298944Sobrien Copyright 1988, 1989, 1991, 1992, 1994, 1996, 1999, 2002 398944Sobrien Free Software Foundation, Inc. 498944Sobrien 598944Sobrien This file is part of GDB. 698944Sobrien 798944Sobrien This program is free software; you can redistribute it and/or modify 898944Sobrien it under the terms of the GNU General Public License as published by 998944Sobrien the Free Software Foundation; either version 2 of the License, or 1098944Sobrien (at your option) any later version. 1198944Sobrien 1298944Sobrien This program is distributed in the hope that it will be useful, 1398944Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1498944Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1598944Sobrien GNU General Public License for more details. 1698944Sobrien 1798944Sobrien You should have received a copy of the GNU General Public License 1898944Sobrien along with this program; if not, write to the Free Software 1998944Sobrien Foundation, Inc., 59 Temple Place - Suite 330, 2098944Sobrien Boston, MA 02111-1307, USA. */ 2198944Sobrien 2298944Sobrien#include "defs.h" 2398944Sobrien 2498944Sobrien#ifndef FETCH_INFERIOR_REGISTERS 2598944Sobrien#error Not FETCH_INFERIOR_REGISTERS 2698944Sobrien#endif /* !FETCH_INFERIOR_REGISTERS */ 2798944Sobrien 2898944Sobrien#include "arm-tdep.h" 2998944Sobrien 3098944Sobrien#include <sys/types.h> 3198944Sobrien#include <sys/ptrace.h> 3298944Sobrien#include <machine/reg.h> 3398944Sobrien#include <machine/frame.h> 3498944Sobrien#include "inferior.h" 3598944Sobrien#include "regcache.h" 3698944Sobrien#include "gdbcore.h" 3798944Sobrien 3898944Sobrienextern int arm_apcs_32; 3998944Sobrien 4098944Sobrienstatic void 4198944Sobriensupply_gregset (struct reg *gregset) 4298944Sobrien{ 4398944Sobrien int regno; 4498944Sobrien CORE_ADDR r_pc; 4598944Sobrien 4698944Sobrien /* Integer registers. */ 4798944Sobrien for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) 4898944Sobrien supply_register (regno, (char *) &gregset->r[regno]); 4998944Sobrien 5098944Sobrien supply_register (ARM_SP_REGNUM, (char *) &gregset->r_sp); 5198944Sobrien supply_register (ARM_LR_REGNUM, (char *) &gregset->r_lr); 5298944Sobrien /* This is ok: we're running native... */ 5398944Sobrien r_pc = ADDR_BITS_REMOVE (gregset->r_pc); 5498944Sobrien supply_register (ARM_PC_REGNUM, (char *) &r_pc); 5598944Sobrien 5698944Sobrien if (arm_apcs_32) 5798944Sobrien supply_register (ARM_PS_REGNUM, (char *) &gregset->r_cpsr); 5898944Sobrien else 5998944Sobrien supply_register (ARM_PS_REGNUM, (char *) &gregset->r_pc); 6098944Sobrien} 6198944Sobrien 6298944Sobrienstatic void 6398944Sobriensupply_fparegset (struct fpreg *fparegset) 6498944Sobrien{ 6598944Sobrien int regno; 6698944Sobrien 6798944Sobrien for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++) 6898944Sobrien supply_register 6998944Sobrien (regno, (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]); 7098944Sobrien 7198944Sobrien supply_register (ARM_FPS_REGNUM, (char *) &fparegset->fpr_fpsr); 7298944Sobrien} 7398944Sobrien 7498944Sobrienstatic void 7598944Sobrienfetch_register (int regno) 7698944Sobrien{ 7798944Sobrien struct reg inferior_registers; 7898944Sobrien int ret; 7998944Sobrien 8098944Sobrien ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid), 8198944Sobrien (PTRACE_ARG3_TYPE) &inferior_registers, 0); 8298944Sobrien 8398944Sobrien if (ret < 0) 8498944Sobrien { 8598944Sobrien warning ("unable to fetch general register"); 8698944Sobrien return; 8798944Sobrien } 8898944Sobrien 8998944Sobrien switch (regno) 9098944Sobrien { 9198944Sobrien case ARM_SP_REGNUM: 9298944Sobrien supply_register (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); 9398944Sobrien break; 9498944Sobrien 9598944Sobrien case ARM_LR_REGNUM: 9698944Sobrien supply_register (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); 9798944Sobrien break; 9898944Sobrien 9998944Sobrien case ARM_PC_REGNUM: 10098944Sobrien /* This is ok: we're running native... */ 10198944Sobrien inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc); 10298944Sobrien supply_register (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc); 10398944Sobrien break; 10498944Sobrien 10598944Sobrien case ARM_PS_REGNUM: 10698944Sobrien if (arm_apcs_32) 10798944Sobrien supply_register (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr); 10898944Sobrien else 10998944Sobrien supply_register (ARM_PS_REGNUM, (char *) &inferior_registers.r_pc); 11098944Sobrien break; 11198944Sobrien 11298944Sobrien default: 11398944Sobrien supply_register (regno, (char *) &inferior_registers.r[regno]); 11498944Sobrien break; 11598944Sobrien } 11698944Sobrien} 11798944Sobrien 11898944Sobrienstatic void 11998944Sobrienfetch_regs (void) 12098944Sobrien{ 12198944Sobrien struct reg inferior_registers; 12298944Sobrien int ret; 12398944Sobrien int regno; 12498944Sobrien 12598944Sobrien ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid), 12698944Sobrien (PTRACE_ARG3_TYPE) &inferior_registers, 0); 12798944Sobrien 12898944Sobrien if (ret < 0) 12998944Sobrien { 13098944Sobrien warning ("unable to fetch general registers"); 13198944Sobrien return; 13298944Sobrien } 13398944Sobrien 13498944Sobrien supply_gregset (&inferior_registers); 13598944Sobrien} 13698944Sobrien 13798944Sobrienstatic void 13898944Sobrienfetch_fp_register (int regno) 13998944Sobrien{ 14098944Sobrien struct fpreg inferior_fp_registers; 14198944Sobrien int ret; 14298944Sobrien 14398944Sobrien ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), 14498944Sobrien (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0); 14598944Sobrien 14698944Sobrien if (ret < 0) 14798944Sobrien { 14898944Sobrien warning ("unable to fetch floating-point register"); 14998944Sobrien return; 15098944Sobrien } 15198944Sobrien 15298944Sobrien switch (regno) 15398944Sobrien { 15498944Sobrien case ARM_FPS_REGNUM: 15598944Sobrien supply_register (ARM_FPS_REGNUM, 15698944Sobrien (char *) &inferior_fp_registers.fpr_fpsr); 15798944Sobrien break; 15898944Sobrien 15998944Sobrien default: 16098944Sobrien supply_register 16198944Sobrien (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); 16298944Sobrien break; 16398944Sobrien } 16498944Sobrien} 16598944Sobrien 16698944Sobrienstatic void 16798944Sobrienfetch_fp_regs (void) 16898944Sobrien{ 16998944Sobrien struct fpreg inferior_fp_registers; 17098944Sobrien int ret; 17198944Sobrien int regno; 17298944Sobrien 17398944Sobrien ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), 17498944Sobrien (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0); 17598944Sobrien 17698944Sobrien if (ret < 0) 17798944Sobrien { 17898944Sobrien warning ("unable to fetch general registers"); 17998944Sobrien return; 18098944Sobrien } 18198944Sobrien 18298944Sobrien supply_fparegset (&inferior_fp_registers); 18398944Sobrien} 18498944Sobrien 18598944Sobrienvoid 18698944Sobrienfetch_inferior_registers (int regno) 18798944Sobrien{ 18898944Sobrien if (regno >= 0) 18998944Sobrien { 19098944Sobrien if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM) 19198944Sobrien fetch_register (regno); 19298944Sobrien else 19398944Sobrien fetch_fp_register (regno); 19498944Sobrien } 19598944Sobrien else 19698944Sobrien { 19798944Sobrien fetch_regs (); 19898944Sobrien fetch_fp_regs (); 19998944Sobrien } 20098944Sobrien} 20198944Sobrien 20298944Sobrien 20398944Sobrienstatic void 20498944Sobrienstore_register (int regno) 20598944Sobrien{ 20698944Sobrien struct reg inferior_registers; 20798944Sobrien int ret; 20898944Sobrien 20998944Sobrien ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid), 21098944Sobrien (PTRACE_ARG3_TYPE) &inferior_registers, 0); 21198944Sobrien 21298944Sobrien if (ret < 0) 21398944Sobrien { 21498944Sobrien warning ("unable to fetch general registers"); 21598944Sobrien return; 21698944Sobrien } 21798944Sobrien 21898944Sobrien switch (regno) 21998944Sobrien { 22098944Sobrien case ARM_SP_REGNUM: 22198944Sobrien regcache_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); 22298944Sobrien break; 22398944Sobrien 22498944Sobrien case ARM_LR_REGNUM: 22598944Sobrien regcache_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); 22698944Sobrien break; 22798944Sobrien 22898944Sobrien case ARM_PC_REGNUM: 22998944Sobrien if (arm_apcs_32) 23098944Sobrien regcache_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc); 23198944Sobrien else 23298944Sobrien { 23398944Sobrien unsigned pc_val; 23498944Sobrien 23598944Sobrien regcache_collect (ARM_PC_REGNUM, (char *) &pc_val); 23698944Sobrien 23798944Sobrien pc_val = ADDR_BITS_REMOVE (pc_val); 23898944Sobrien inferior_registers.r_pc 23998944Sobrien ^= ADDR_BITS_REMOVE (inferior_registers.r_pc); 24098944Sobrien inferior_registers.r_pc |= pc_val; 24198944Sobrien } 24298944Sobrien break; 24398944Sobrien 24498944Sobrien case ARM_PS_REGNUM: 24598944Sobrien if (arm_apcs_32) 24698944Sobrien regcache_collect (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr); 24798944Sobrien else 24898944Sobrien { 24998944Sobrien unsigned psr_val; 25098944Sobrien 25198944Sobrien regcache_collect (ARM_PS_REGNUM, (char *) &psr_val); 25298944Sobrien 25398944Sobrien psr_val ^= ADDR_BITS_REMOVE (psr_val); 25498944Sobrien inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc); 25598944Sobrien inferior_registers.r_pc |= psr_val; 25698944Sobrien } 25798944Sobrien break; 25898944Sobrien 25998944Sobrien default: 26098944Sobrien regcache_collect (regno, (char *) &inferior_registers.r[regno]); 26198944Sobrien break; 26298944Sobrien } 26398944Sobrien 26498944Sobrien ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid), 26598944Sobrien (PTRACE_ARG3_TYPE) &inferior_registers, 0); 26698944Sobrien 26798944Sobrien if (ret < 0) 26898944Sobrien warning ("unable to write register %d to inferior", regno); 26998944Sobrien} 27098944Sobrien 27198944Sobrienstatic void 27298944Sobrienstore_regs (void) 27398944Sobrien{ 27498944Sobrien struct reg inferior_registers; 27598944Sobrien int ret; 27698944Sobrien int regno; 27798944Sobrien 27898944Sobrien 27998944Sobrien for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) 28098944Sobrien regcache_collect (regno, (char *) &inferior_registers.r[regno]); 28198944Sobrien 28298944Sobrien regcache_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); 28398944Sobrien regcache_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); 28498944Sobrien 28598944Sobrien if (arm_apcs_32) 28698944Sobrien { 28798944Sobrien regcache_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc); 28898944Sobrien regcache_collect (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr); 28998944Sobrien } 29098944Sobrien else 29198944Sobrien { 29298944Sobrien unsigned pc_val; 29398944Sobrien unsigned psr_val; 29498944Sobrien 29598944Sobrien regcache_collect (ARM_PC_REGNUM, (char *) &pc_val); 29698944Sobrien regcache_collect (ARM_PS_REGNUM, (char *) &psr_val); 29798944Sobrien 29898944Sobrien pc_val = ADDR_BITS_REMOVE (pc_val); 29998944Sobrien psr_val ^= ADDR_BITS_REMOVE (psr_val); 30098944Sobrien 30198944Sobrien inferior_registers.r_pc = pc_val | psr_val; 30298944Sobrien } 30398944Sobrien 30498944Sobrien ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid), 30598944Sobrien (PTRACE_ARG3_TYPE) &inferior_registers, 0); 30698944Sobrien 30798944Sobrien if (ret < 0) 30898944Sobrien warning ("unable to store general registers"); 30998944Sobrien} 31098944Sobrien 31198944Sobrienstatic void 31298944Sobrienstore_fp_register (int regno) 31398944Sobrien{ 31498944Sobrien struct fpreg inferior_fp_registers; 31598944Sobrien int ret; 31698944Sobrien 31798944Sobrien ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), 31898944Sobrien (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0); 31998944Sobrien 32098944Sobrien if (ret < 0) 32198944Sobrien { 32298944Sobrien warning ("unable to fetch floating-point registers"); 32398944Sobrien return; 32498944Sobrien } 32598944Sobrien 32698944Sobrien switch (regno) 32798944Sobrien { 32898944Sobrien case ARM_FPS_REGNUM: 32998944Sobrien regcache_collect (ARM_FPS_REGNUM, 33098944Sobrien (char *) &inferior_fp_registers.fpr_fpsr); 33198944Sobrien break; 33298944Sobrien 33398944Sobrien default: 33498944Sobrien regcache_collect 33598944Sobrien (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); 33698944Sobrien break; 33798944Sobrien } 33898944Sobrien 33998944Sobrien ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid), 34098944Sobrien (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0); 34198944Sobrien 34298944Sobrien if (ret < 0) 34398944Sobrien warning ("unable to write register %d to inferior", regno); 34498944Sobrien} 34598944Sobrien 34698944Sobrienstatic void 34798944Sobrienstore_fp_regs (void) 34898944Sobrien{ 34998944Sobrien struct fpreg inferior_fp_registers; 35098944Sobrien int ret; 35198944Sobrien int regno; 35298944Sobrien 35398944Sobrien 35498944Sobrien for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++) 35598944Sobrien regcache_collect 35698944Sobrien (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); 35798944Sobrien 35898944Sobrien regcache_collect (ARM_FPS_REGNUM, (char *) &inferior_fp_registers.fpr_fpsr); 35998944Sobrien 36098944Sobrien ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid), 36198944Sobrien (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0); 36298944Sobrien 36398944Sobrien if (ret < 0) 36498944Sobrien warning ("unable to store floating-point registers"); 36598944Sobrien} 36698944Sobrien 36798944Sobrienvoid 36898944Sobrienstore_inferior_registers (int regno) 36998944Sobrien{ 37098944Sobrien if (regno >= 0) 37198944Sobrien { 37298944Sobrien if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM) 37398944Sobrien store_register (regno); 37498944Sobrien else 37598944Sobrien store_fp_register (regno); 37698944Sobrien } 37798944Sobrien else 37898944Sobrien { 37998944Sobrien store_regs (); 38098944Sobrien store_fp_regs (); 38198944Sobrien } 38298944Sobrien} 38398944Sobrien 38498944Sobrienstruct md_core 38598944Sobrien{ 38698944Sobrien struct reg intreg; 38798944Sobrien struct fpreg freg; 38898944Sobrien}; 38998944Sobrien 39098944Sobrienstatic void 39198944Sobrienfetch_core_registers (char *core_reg_sect, unsigned core_reg_size, 39298944Sobrien int which, CORE_ADDR ignore) 39398944Sobrien{ 39498944Sobrien struct md_core *core_reg = (struct md_core *) core_reg_sect; 39598944Sobrien int regno; 39698944Sobrien CORE_ADDR r_pc; 39798944Sobrien 39898944Sobrien supply_gregset (&core_reg->intreg); 39998944Sobrien supply_fparegset (&core_reg->freg); 40098944Sobrien} 40198944Sobrien 40298944Sobrienstatic void 40398944Sobrienfetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size, 40498944Sobrien int which, CORE_ADDR ignore) 40598944Sobrien{ 40698944Sobrien struct reg gregset; 40798944Sobrien struct fpreg fparegset; 40898944Sobrien 40998944Sobrien switch (which) 41098944Sobrien { 41198944Sobrien case 0: /* Integer registers. */ 41298944Sobrien if (core_reg_size != sizeof (struct reg)) 41398944Sobrien warning ("wrong size of register set in core file"); 41498944Sobrien else 41598944Sobrien { 41698944Sobrien /* The memcpy may be unnecessary, but we can't really be sure 41798944Sobrien of the alignment of the data in the core file. */ 41898944Sobrien memcpy (&gregset, core_reg_sect, sizeof (gregset)); 41998944Sobrien supply_gregset (&gregset); 42098944Sobrien } 42198944Sobrien break; 42298944Sobrien 42398944Sobrien case 2: 42498944Sobrien if (core_reg_size != sizeof (struct fpreg)) 42598944Sobrien warning ("wrong size of FPA register set in core file"); 42698944Sobrien else 42798944Sobrien { 42898944Sobrien /* The memcpy may be unnecessary, but we can't really be sure 42998944Sobrien of the alignment of the data in the core file. */ 43098944Sobrien memcpy (&fparegset, core_reg_sect, sizeof (fparegset)); 43198944Sobrien supply_fparegset (&fparegset); 43298944Sobrien } 43398944Sobrien break; 43498944Sobrien 43598944Sobrien default: 43698944Sobrien /* Don't know what kind of register request this is; just ignore it. */ 43798944Sobrien break; 43898944Sobrien } 43998944Sobrien} 44098944Sobrien 44198944Sobrienstatic struct core_fns arm_netbsd_core_fns = 44298944Sobrien{ 44398944Sobrien bfd_target_unknown_flavour, /* core_flovour. */ 44498944Sobrien default_check_format, /* check_format. */ 44598944Sobrien default_core_sniffer, /* core_sniffer. */ 44698944Sobrien fetch_core_registers, /* core_read_registers. */ 44798944Sobrien NULL 44898944Sobrien}; 44998944Sobrien 45098944Sobrienstatic struct core_fns arm_netbsd_elfcore_fns = 45198944Sobrien{ 45298944Sobrien bfd_target_elf_flavour, /* core_flovour. */ 45398944Sobrien default_check_format, /* check_format. */ 45498944Sobrien default_core_sniffer, /* core_sniffer. */ 45598944Sobrien fetch_elfcore_registers, /* core_read_registers. */ 45698944Sobrien NULL 45798944Sobrien}; 45898944Sobrien 45998944Sobrienvoid 46098944Sobrien_initialize_arm_netbsd_nat (void) 46198944Sobrien{ 46298944Sobrien add_core_fns (&arm_netbsd_core_fns); 46398944Sobrien add_core_fns (&arm_netbsd_elfcore_fns); 46498944Sobrien} 465