1130803Smarcel/* Target-dependent code for FreeBSD/sparc64. 2130803Smarcel 3130803Smarcel Copyright 2003, 2004 Free Software Foundation, Inc. 4130803Smarcel 5130803Smarcel This file is part of GDB. 6130803Smarcel 7130803Smarcel This program is free software; you can redistribute it and/or modify 8130803Smarcel it under the terms of the GNU General Public License as published by 9130803Smarcel the Free Software Foundation; either version 2 of the License, or 10130803Smarcel (at your option) any later version. 11130803Smarcel 12130803Smarcel This program is distributed in the hope that it will be useful, 13130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 14130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15130803Smarcel GNU General Public License for more details. 16130803Smarcel 17130803Smarcel You should have received a copy of the GNU General Public License 18130803Smarcel along with this program; if not, write to the Free Software 19130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 20130803Smarcel Boston, MA 02111-1307, USA. */ 21130803Smarcel 22130803Smarcel#include "defs.h" 23130803Smarcel#include "frame.h" 24130803Smarcel#include "frame-unwind.h" 25130803Smarcel#include "gdbcore.h" 26130803Smarcel#include "osabi.h" 27130803Smarcel#include "regcache.h" 28130803Smarcel#include "regset.h" 29130803Smarcel#include "target.h" 30130803Smarcel#include "trad-frame.h" 31130803Smarcel 32130803Smarcel#include "gdb_assert.h" 33130803Smarcel#include "gdb_string.h" 34130803Smarcel 35130803Smarcel#include "sparc64-tdep.h" 36130803Smarcel 37130803Smarcel/* From <machine/reg.h>. */ 38130803Smarcelconst struct sparc_gregset sparc64fbsd_gregset = 39130803Smarcel{ 40130803Smarcel 26 * 8, /* "tstate" */ 41130803Smarcel 25 * 8, /* %pc */ 42130803Smarcel 24 * 8, /* %npc */ 43130803Smarcel 28 * 8, /* %y */ 44130803Smarcel 16 * 8, /* %fprs */ 45130803Smarcel -1, 46130803Smarcel 1 * 8, /* %g1 */ 47130803Smarcel -1, /* %l0 */ 48130803Smarcel 8 /* sizeof (%y) */ 49130803Smarcel}; 50130803Smarcel 51130803Smarcel 52130803Smarcelstatic void 53130803Smarcelsparc64fbsd_supply_gregset (const struct regset *regset, 54130803Smarcel struct regcache *regcache, 55130803Smarcel int regnum, const void *gregs, size_t len) 56130803Smarcel{ 57130803Smarcel sparc64_supply_gregset (regset->descr, regcache, regnum, gregs); 58130803Smarcel} 59130803Smarcel 60130803Smarcelstatic void 61130803Smarcelsparc64fbsd_supply_fpregset (const struct regset *regset, 62130803Smarcel struct regcache *regcache, 63130803Smarcel int regnum, const void *fpregs, size_t len) 64130803Smarcel{ 65130803Smarcel sparc64_supply_fpregset (regcache, regnum, fpregs); 66130803Smarcel} 67224686Smarius 68224686Smariusvoid 69224686Smariussupply_gregset (const void *gregs) 70224686Smarius{ 71224686Smarius sparc64_supply_gregset (&sparc64fbsd_gregset, current_regcache, -1, gregs); 72224686Smarius} 73224686Smarius 74224686Smariusvoid 75224686Smariussupply_fpregset (const void *fpregs) 76224686Smarius{ 77224686Smarius sparc64_supply_fpregset (current_regcache, -1, fpregs); 78224686Smarius} 79224686Smarius 80224686Smariusvoid 81224686Smariusfill_gregset (void *gregs, int regnum) 82224686Smarius{ 83224686Smarius sparc64_collect_gregset (&sparc64fbsd_gregset, current_regcache, regnum, 84224686Smarius gregs); 85224686Smarius} 86224686Smarius 87224686Smariusvoid 88224686Smariusfill_fpregset (void *fpregs, int regnum) 89224686Smarius{ 90224686Smarius sparc64_collect_fpregset (current_regcache, regnum, fpregs); 91224686Smarius} 92130803Smarcel 93130803Smarcel 94130803Smarcel/* Signal trampolines. */ 95130803Smarcel 96130803Smarcelstatic int 97130803Smarcelsparc64fbsd_pc_in_sigtramp (CORE_ADDR pc, char *name) 98130803Smarcel{ 99130803Smarcel return (name && strcmp (name, "__sigtramp") == 0); 100130803Smarcel} 101130803Smarcel 102130803Smarcelstatic struct sparc_frame_cache * 103130803Smarcelsparc64fbsd_sigtramp_frame_cache (struct frame_info *next_frame, 104130803Smarcel void **this_cache) 105130803Smarcel{ 106130803Smarcel struct sparc_frame_cache *cache; 107130803Smarcel CORE_ADDR addr, mcontext_addr, sp; 108130803Smarcel LONGEST fprs; 109130803Smarcel int regnum; 110130803Smarcel 111130803Smarcel if (*this_cache) 112130803Smarcel return *this_cache; 113130803Smarcel 114130803Smarcel cache = sparc_frame_cache (next_frame, this_cache); 115130803Smarcel gdb_assert (cache == *this_cache); 116130803Smarcel 117130803Smarcel cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); 118130803Smarcel 119130803Smarcel /* The third argument is a pointer to an instance of `ucontext_t', 120130803Smarcel which has a member `uc_mcontext' that contains the saved 121130803Smarcel registers. */ 122130803Smarcel addr = frame_unwind_register_unsigned (next_frame, SPARC_O2_REGNUM); 123130803Smarcel mcontext_addr = addr + 64; 124130803Smarcel 125130803Smarcel /* The following registers travel in the `mc_local' slots of 126130803Smarcel `mcontext_t'. */ 127130803Smarcel addr = mcontext_addr + 16 * 8; 128130803Smarcel cache->saved_regs[SPARC64_FPRS_REGNUM].addr = addr + 0 * 8; 129130803Smarcel cache->saved_regs[SPARC64_FSR_REGNUM].addr = addr + 1 * 8; 130130803Smarcel 131130803Smarcel /* The following registers travel in the `mc_in' slots of 132130803Smarcel `mcontext_t'. */ 133130803Smarcel addr = mcontext_addr + 24 * 8; 134130803Smarcel cache->saved_regs[SPARC64_NPC_REGNUM].addr = addr + 0 * 8; 135130803Smarcel cache->saved_regs[SPARC64_PC_REGNUM].addr = addr + 1 * 8; 136130803Smarcel cache->saved_regs[SPARC64_STATE_REGNUM].addr = addr + 2 * 8; 137130803Smarcel cache->saved_regs[SPARC64_Y_REGNUM].addr = addr + 4 * 8; 138130803Smarcel 139130803Smarcel /* The `global' and `out' registers travel in the `mc_global' and 140130803Smarcel `mc_out' slots of `mcontext_t', except for %g0. Since %g0 is 141130803Smarcel always zero, keep the identity encoding. */ 142130803Smarcel for (regnum = SPARC_G1_REGNUM, addr = mcontext_addr + 8; 143130803Smarcel regnum <= SPARC_O7_REGNUM; regnum++, addr += 8) 144130803Smarcel cache->saved_regs[regnum].addr = addr; 145130803Smarcel 146130803Smarcel /* The `local' and `in' registers have been saved in the register 147130803Smarcel save area. */ 148130803Smarcel addr = cache->saved_regs[SPARC_SP_REGNUM].addr; 149130803Smarcel sp = get_frame_memory_unsigned (next_frame, addr, 8); 150130803Smarcel for (regnum = SPARC_L0_REGNUM, addr = sp + BIAS; 151130803Smarcel regnum <= SPARC_I7_REGNUM; regnum++, addr += 8) 152130803Smarcel cache->saved_regs[regnum].addr = addr; 153130803Smarcel 154130803Smarcel /* The floating-point registers are only saved if the FEF bit in 155130803Smarcel %fprs has been set. */ 156130803Smarcel 157130803Smarcel#define FPRS_FEF (1 << 2) 158130803Smarcel 159130803Smarcel addr = cache->saved_regs[SPARC64_FPRS_REGNUM].addr; 160130803Smarcel fprs = get_frame_memory_unsigned (next_frame, addr, 8); 161130803Smarcel if (fprs & FPRS_FEF) 162130803Smarcel { 163130803Smarcel for (regnum = SPARC_F0_REGNUM, addr = mcontext_addr + 32 * 8; 164130803Smarcel regnum <= SPARC_F31_REGNUM; regnum++, addr += 4) 165130803Smarcel cache->saved_regs[regnum].addr = addr; 166130803Smarcel 167130803Smarcel for (regnum = SPARC64_F32_REGNUM; 168130803Smarcel regnum <= SPARC64_F62_REGNUM; regnum++, addr += 8) 169130803Smarcel cache->saved_regs[regnum].addr = addr; 170130803Smarcel } 171130803Smarcel 172130803Smarcel return cache; 173130803Smarcel} 174130803Smarcel 175130803Smarcelstatic void 176130803Smarcelsparc64fbsd_sigtramp_frame_this_id (struct frame_info *next_frame, 177130803Smarcel void **this_cache, 178130803Smarcel struct frame_id *this_id) 179130803Smarcel{ 180130803Smarcel struct sparc_frame_cache *cache = 181130803Smarcel sparc64fbsd_sigtramp_frame_cache (next_frame, this_cache); 182130803Smarcel 183130803Smarcel (*this_id) = frame_id_build (cache->base, cache->pc); 184130803Smarcel} 185130803Smarcel 186130803Smarcelstatic void 187130803Smarcelsparc64fbsd_sigtramp_frame_prev_register (struct frame_info *next_frame, 188130803Smarcel void **this_cache, 189130803Smarcel int regnum, int *optimizedp, 190130803Smarcel enum lval_type *lvalp, 191130803Smarcel CORE_ADDR *addrp, 192130803Smarcel int *realnump, void *valuep) 193130803Smarcel{ 194130803Smarcel struct sparc_frame_cache *cache = 195130803Smarcel sparc64fbsd_sigtramp_frame_cache (next_frame, this_cache); 196130803Smarcel 197130803Smarcel trad_frame_prev_register (next_frame, cache->saved_regs, regnum, 198130803Smarcel optimizedp, lvalp, addrp, realnump, valuep); 199130803Smarcel} 200130803Smarcel 201130803Smarcelstatic const struct frame_unwind sparc64fbsd_sigtramp_frame_unwind = 202130803Smarcel{ 203130803Smarcel SIGTRAMP_FRAME, 204130803Smarcel sparc64fbsd_sigtramp_frame_this_id, 205130803Smarcel sparc64fbsd_sigtramp_frame_prev_register 206130803Smarcel}; 207130803Smarcel 208130803Smarcelstatic const struct frame_unwind * 209130803Smarcelsparc64fbsd_sigtramp_frame_sniffer (struct frame_info *next_frame) 210130803Smarcel{ 211130803Smarcel CORE_ADDR pc = frame_pc_unwind (next_frame); 212130803Smarcel char *name; 213130803Smarcel 214130803Smarcel find_pc_partial_function (pc, &name, NULL, NULL); 215130803Smarcel if (sparc64fbsd_pc_in_sigtramp (pc, name)) 216130803Smarcel return &sparc64fbsd_sigtramp_frame_unwind; 217130803Smarcel 218130803Smarcel return NULL; 219130803Smarcel} 220130803Smarcel 221130803Smarcel 222130803Smarcelstatic void 223130803Smarcelsparc64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 224130803Smarcel{ 225130803Smarcel struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 226130803Smarcel 227130803Smarcel tdep->gregset = XMALLOC (struct regset); 228130803Smarcel tdep->gregset->descr = &sparc64fbsd_gregset; 229130803Smarcel tdep->gregset->supply_regset = sparc64fbsd_supply_gregset; 230130803Smarcel tdep->sizeof_gregset = 256; 231130803Smarcel 232130803Smarcel tdep->fpregset = XMALLOC (struct regset); 233130803Smarcel tdep->fpregset->supply_regset = sparc64fbsd_supply_fpregset; 234130803Smarcel tdep->sizeof_fpregset = 272; 235130803Smarcel 236130803Smarcel set_gdbarch_pc_in_sigtramp (gdbarch, sparc64fbsd_pc_in_sigtramp); 237130803Smarcel frame_unwind_append_sniffer (gdbarch, sparc64fbsd_sigtramp_frame_sniffer); 238130803Smarcel 239130803Smarcel sparc64_init_abi (info, gdbarch); 240130803Smarcel} 241130803Smarcel 242130803Smarcel/* Provide a prototype to silence -Wmissing-prototypes. */ 243130803Smarcelvoid _initialize_sparc64fbsd_tdep (void); 244130803Smarcel 245130803Smarcelvoid 246130803Smarcel_initialize_sparc64fbsd_tdep (void) 247130803Smarcel{ 248130803Smarcel gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, 249130803Smarcel GDB_OSABI_FREEBSD_ELF, sparc64fbsd_init_abi); 250130803Smarcel} 251