1130803Smarcel/* Native support for MIPS running SVR4, for GDB. 2130803Smarcel Copyright 1994, 1995, 2000, 2001 Free Software Foundation, Inc. 3130803Smarcel 4130803Smarcel This file is part of GDB. 5130803Smarcel 6130803Smarcel This program is free software; you can redistribute it and/or modify 7130803Smarcel it under the terms of the GNU General Public License as published by 8130803Smarcel the Free Software Foundation; either version 2 of the License, or 9130803Smarcel (at your option) any later version. 10130803Smarcel 11130803Smarcel This program is distributed in the hope that it will be useful, 12130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 13130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14130803Smarcel GNU General Public License for more details. 15130803Smarcel 16130803Smarcel You should have received a copy of the GNU General Public License 17130803Smarcel along with this program; if not, write to the Free Software 18130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 19130803Smarcel Boston, MA 02111-1307, USA. */ 20130803Smarcel 21130803Smarcel#include "defs.h" 22130803Smarcel#include "inferior.h" 23130803Smarcel#include "gdbcore.h" 24130803Smarcel#include "target.h" 25130803Smarcel#include "regcache.h" 26130803Smarcel 27130803Smarcel#include <sys/time.h> 28130803Smarcel#include <sys/procfs.h> 29130803Smarcel#include <setjmp.h> /* For JB_XXX. */ 30130803Smarcel 31130803Smarcel/* Prototypes for supply_gregset etc. */ 32130803Smarcel#include "gregset.h" 33130803Smarcel 34130803Smarcel/* Size of elements in jmpbuf */ 35130803Smarcel 36130803Smarcel#define JB_ELEMENT_SIZE 4 37130803Smarcel 38130803Smarcel/* 39130803Smarcel * See the comment in m68k-tdep.c regarding the utility of these functions. 40130803Smarcel * 41130803Smarcel * These definitions are from the MIPS SVR4 ABI, so they may work for 42130803Smarcel * any MIPS SVR4 target. 43130803Smarcel */ 44130803Smarcel 45130803Smarcelvoid 46130803Smarcelsupply_gregset (gregset_t *gregsetp) 47130803Smarcel{ 48130803Smarcel int regi; 49130803Smarcel greg_t *regp = &(*gregsetp)[0]; 50130803Smarcel char zerobuf[MAX_REGISTER_SIZE]; 51130803Smarcel memset (zerobuf, 0, MAX_REGISTER_SIZE); 52130803Smarcel 53130803Smarcel for (regi = 0; regi <= CXT_RA; regi++) 54130803Smarcel supply_register (regi, (char *) (regp + regi)); 55130803Smarcel 56130803Smarcel supply_register (mips_regnum (current_gdbarch)->pc, 57130803Smarcel (char *) (regp + CXT_EPC)); 58130803Smarcel supply_register (mips_regnum (current_gdbarch)->hi, 59130803Smarcel (char *) (regp + CXT_MDHI)); 60130803Smarcel supply_register (mips_regnum (current_gdbarch)->lo, 61130803Smarcel (char *) (regp + CXT_MDLO)); 62130803Smarcel supply_register (mips_regnum (current_gdbarch)->cause, 63130803Smarcel (char *) (regp + CXT_CAUSE)); 64130803Smarcel 65130803Smarcel /* Fill inaccessible registers with zero. */ 66130803Smarcel supply_register (PS_REGNUM, zerobuf); 67130803Smarcel supply_register (mips_regnum (current_gdbarch)->badvaddr, zerobuf); 68130803Smarcel supply_register (DEPRECATED_FP_REGNUM, zerobuf); 69130803Smarcel supply_register (UNUSED_REGNUM, zerobuf); 70130803Smarcel for (regi = FIRST_EMBED_REGNUM; regi <= LAST_EMBED_REGNUM; regi++) 71130803Smarcel supply_register (regi, zerobuf); 72130803Smarcel} 73130803Smarcel 74130803Smarcelvoid 75130803Smarcelfill_gregset (gregset_t *gregsetp, int regno) 76130803Smarcel{ 77130803Smarcel int regi; 78130803Smarcel greg_t *regp = &(*gregsetp)[0]; 79130803Smarcel 80130803Smarcel for (regi = 0; regi <= 32; regi++) 81130803Smarcel if ((regno == -1) || (regno == regi)) 82130803Smarcel *(regp + regi) = *(greg_t *) & deprecated_registers[DEPRECATED_REGISTER_BYTE (regi)]; 83130803Smarcel 84130803Smarcel if ((regno == -1) || (regno == mips_regnum (current_gdbarch)->pc)) 85130803Smarcel *(regp + CXT_EPC) = *(greg_t *) & deprecated_registers[DEPRECATED_REGISTER_BYTE (mips_regnum (current_gdbarch)->pc)]; 86130803Smarcel 87130803Smarcel if ((regno == -1) || (regno == mips_regnum (current_gdbarch)->cause)) 88130803Smarcel *(regp + CXT_CAUSE) = *(greg_t *) & deprecated_registers[DEPRECATED_REGISTER_BYTE (mips_regnum (current_gdbarch)->cause)]; 89130803Smarcel 90130803Smarcel if ((regno == -1) || (regno == mips_regnum (current_gdbarch)->hi)) 91130803Smarcel *(regp + CXT_MDHI) = *(greg_t *) & deprecated_registers[DEPRECATED_REGISTER_BYTE (mips_regnum (current_gdbarch)->hi)]; 92130803Smarcel 93130803Smarcel if ((regno == -1) || (regno == mips_regnum (current_gdbarch)->lo)) 94130803Smarcel *(regp + CXT_MDLO) = *(greg_t *) & deprecated_registers[DEPRECATED_REGISTER_BYTE (mips_regnum (current_gdbarch)->lo)]; 95130803Smarcel} 96130803Smarcel 97130803Smarcel/* 98130803Smarcel * Now we do the same thing for floating-point registers. 99130803Smarcel * We don't bother to condition on FP0 regnum since any 100130803Smarcel * reasonable MIPS configuration has an R3010 in it. 101130803Smarcel * 102130803Smarcel * Again, see the comments in m68k-tdep.c. 103130803Smarcel */ 104130803Smarcel 105130803Smarcelvoid 106130803Smarcelsupply_fpregset (fpregset_t *fpregsetp) 107130803Smarcel{ 108130803Smarcel int regi; 109130803Smarcel char zerobuf[MAX_REGISTER_SIZE]; 110130803Smarcel memset (zerobuf, 0, MAX_REGISTER_SIZE); 111130803Smarcel 112130803Smarcel for (regi = 0; regi < 32; regi++) 113130803Smarcel supply_register (mips_regnum (current_gdbarch)->fp0 + regi, 114130803Smarcel (char *) &fpregsetp->fp_r.fp_regs[regi]); 115130803Smarcel 116130803Smarcel supply_register (mips_regnum (current_gdbarch)->fp_control_status, 117130803Smarcel (char *) &fpregsetp->fp_csr); 118130803Smarcel 119130803Smarcel /* FIXME: how can we supply FCRIR? The ABI doesn't tell us. */ 120130803Smarcel supply_register (mips_regnum (current_gdbarch)->fp_implementation_revision, 121130803Smarcel zerobuf); 122130803Smarcel} 123130803Smarcel 124130803Smarcelvoid 125130803Smarcelfill_fpregset (fpregset_t *fpregsetp, int regno) 126130803Smarcel{ 127130803Smarcel int regi; 128130803Smarcel char *from, *to; 129130803Smarcel 130130803Smarcel for (regi = mips_regnum (current_gdbarch)->fp0; 131130803Smarcel regi < mips_regnum (current_gdbarch)->fp0 + 32; regi++) 132130803Smarcel { 133130803Smarcel if ((regno == -1) || (regno == regi)) 134130803Smarcel { 135130803Smarcel from = (char *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regi)]; 136130803Smarcel to = (char *) &(fpregsetp->fp_r.fp_regs[regi - mips_regnum (current_gdbarch)->fp0]); 137130803Smarcel memcpy (to, from, DEPRECATED_REGISTER_RAW_SIZE (regi)); 138130803Smarcel } 139130803Smarcel } 140130803Smarcel 141130803Smarcel if ((regno == -1) 142130803Smarcel || (regno == mips_regnum (current_gdbarch)->fp_control_status)) 143130803Smarcel fpregsetp->fp_csr = *(unsigned *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (mips_regnum (current_gdbarch)->fp_control_status)]; 144130803Smarcel} 145130803Smarcel 146130803Smarcel 147130803Smarcel/* Figure out where the longjmp will land. 148130803Smarcel We expect the first arg to be a pointer to the jmp_buf structure from which 149130803Smarcel we extract the pc (_JB_PC) that we will land at. The pc is copied into PC. 150130803Smarcel This routine returns true on success. */ 151130803Smarcel 152130803Smarcelint 153130803Smarcelget_longjmp_target (CORE_ADDR *pc) 154130803Smarcel{ 155130803Smarcel char *buf; 156130803Smarcel CORE_ADDR jb_addr; 157130803Smarcel 158130803Smarcel buf = alloca (TARGET_PTR_BIT / TARGET_CHAR_BIT); 159130803Smarcel jb_addr = read_register (A0_REGNUM); 160130803Smarcel 161130803Smarcel if (target_read_memory (jb_addr + _JB_PC * JB_ELEMENT_SIZE, buf, 162130803Smarcel TARGET_PTR_BIT / TARGET_CHAR_BIT)) 163130803Smarcel return 0; 164130803Smarcel 165130803Smarcel *pc = extract_unsigned_integer (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT); 166130803Smarcel 167130803Smarcel return 1; 168130803Smarcel} 169