1130812Smarcel/* Low level Alpha interface, for GDB when running native.
2130812Smarcel   Copyright 1993, 1995, 1996, 1998, 1999, 2000, 2001, 2003
3130812Smarcel   Free Software Foundation, Inc.
4130812Smarcel
5130812Smarcel   This file is part of GDB.
6130812Smarcel
7130812Smarcel   This program is free software; you can redistribute it and/or modify
8130812Smarcel   it under the terms of the GNU General Public License as published by
9130812Smarcel   the Free Software Foundation; either version 2 of the License, or
10130812Smarcel   (at your option) any later version.
11130812Smarcel
12130812Smarcel   This program is distributed in the hope that it will be useful,
13130812Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
14130812Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15130812Smarcel   GNU General Public License for more details.
16130812Smarcel
17130812Smarcel   You should have received a copy of the GNU General Public License
18130812Smarcel   along with this program; if not, write to the Free Software
19130812Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
20130812Smarcel   Boston, MA 02111-1307, USA.  */
21130812Smarcel
22130812Smarcel#include "defs.h"
23130812Smarcel#include "gdb_string.h"
24130812Smarcel#include "inferior.h"
25130812Smarcel#include "gdbcore.h"
26130812Smarcel#include "target.h"
27130812Smarcel#include "regcache.h"
28130812Smarcel
29130812Smarcel#include "alpha-tdep.h"
30130812Smarcel
31130812Smarcel#include <sys/ptrace.h>
32130812Smarcel#ifdef __linux__
33130812Smarcel#include <asm/reg.h>
34130812Smarcel#include <alpha/ptrace.h>
35130812Smarcel#else
36130812Smarcel#include <alpha/coreregs.h>
37130812Smarcel#endif
38130812Smarcel#include <sys/user.h>
39130812Smarcel
40130812Smarcel/* Prototypes for local functions. */
41130812Smarcel
42130812Smarcelstatic void fetch_osf_core_registers (char *, unsigned, int, CORE_ADDR);
43130812Smarcelstatic void fetch_elf_core_registers (char *, unsigned, int, CORE_ADDR);
44130812Smarcel
45130812Smarcel/* Extract the register values out of the core file and store
46130812Smarcel   them where `read_register' will find them.
47130812Smarcel
48130812Smarcel   CORE_REG_SECT points to the register values themselves, read into memory.
49130812Smarcel   CORE_REG_SIZE is the size of that area.
50130812Smarcel   WHICH says which set of registers we are handling (0 = int, 2 = float
51130812Smarcel   on machines where they are discontiguous).
52130812Smarcel   REG_ADDR is the offset from u.u_ar0 to the register values relative to
53130812Smarcel   core_reg_sect.  This is used with old-fashioned core files to
54130812Smarcel   locate the registers in a large upage-plus-stack ".reg" section.
55130812Smarcel   Original upage address X is at location core_reg_sect+x+reg_addr.
56130812Smarcel */
57130812Smarcel
58130812Smarcelstatic void
59130812Smarcelfetch_osf_core_registers (char *core_reg_sect, unsigned core_reg_size,
60130812Smarcel			  int which, CORE_ADDR reg_addr)
61130812Smarcel{
62130812Smarcel  int regno;
63130812Smarcel  int addr;
64130812Smarcel  int bad_reg = -1;
65130812Smarcel
66130812Smarcel  /* Table to map a gdb regnum to an index in the core register
67130812Smarcel     section.  The floating point register values are garbage in
68130812Smarcel     OSF/1.2 core files.  OSF5 uses different names for the register
69130812Smarcel     enum list, need to handle two cases.  The actual values are the
70130812Smarcel     same.  */
71130812Smarcel  static int const core_reg_mapping[ALPHA_NUM_REGS] =
72130812Smarcel  {
73130812Smarcel#ifdef NCF_REGS
74130812Smarcel#define EFL NCF_REGS
75130812Smarcel    CF_V0, CF_T0, CF_T1, CF_T2, CF_T3, CF_T4, CF_T5, CF_T6,
76130812Smarcel    CF_T7, CF_S0, CF_S1, CF_S2, CF_S3, CF_S4, CF_S5, CF_S6,
77130812Smarcel    CF_A0, CF_A1, CF_A2, CF_A3, CF_A4, CF_A5, CF_T8, CF_T9,
78130812Smarcel    CF_T10, CF_T11, CF_RA, CF_T12, CF_AT, CF_GP, CF_SP, -1,
79130812Smarcel    EFL + 0, EFL + 1, EFL + 2, EFL + 3, EFL + 4, EFL + 5, EFL + 6, EFL + 7,
80130812Smarcel    EFL + 8, EFL + 9, EFL + 10, EFL + 11, EFL + 12, EFL + 13, EFL + 14, EFL + 15,
81130812Smarcel    EFL + 16, EFL + 17, EFL + 18, EFL + 19, EFL + 20, EFL + 21, EFL + 22, EFL + 23,
82130812Smarcel    EFL + 24, EFL + 25, EFL + 26, EFL + 27, EFL + 28, EFL + 29, EFL + 30, EFL + 31,
83130812Smarcel    CF_PC, -1
84130812Smarcel#else
85130812Smarcel#define EFL (EF_SIZE / 8)
86130812Smarcel    EF_V0, EF_T0, EF_T1, EF_T2, EF_T3, EF_T4, EF_T5, EF_T6,
87130812Smarcel    EF_T7, EF_S0, EF_S1, EF_S2, EF_S3, EF_S4, EF_S5, EF_S6,
88130812Smarcel    EF_A0, EF_A1, EF_A2, EF_A3, EF_A4, EF_A5, EF_T8, EF_T9,
89130812Smarcel    EF_T10, EF_T11, EF_RA, EF_T12, EF_AT, EF_GP, EF_SP, -1,
90130812Smarcel    EFL + 0, EFL + 1, EFL + 2, EFL + 3, EFL + 4, EFL + 5, EFL + 6, EFL + 7,
91130812Smarcel    EFL + 8, EFL + 9, EFL + 10, EFL + 11, EFL + 12, EFL + 13, EFL + 14, EFL + 15,
92130812Smarcel    EFL + 16, EFL + 17, EFL + 18, EFL + 19, EFL + 20, EFL + 21, EFL + 22, EFL + 23,
93130812Smarcel    EFL + 24, EFL + 25, EFL + 26, EFL + 27, EFL + 28, EFL + 29, EFL + 30, EFL + 31,
94130812Smarcel    EF_PC, -1
95130812Smarcel#endif
96130812Smarcel  };
97130812Smarcel
98130812Smarcel  for (regno = 0; regno < ALPHA_NUM_REGS; regno++)
99130812Smarcel    {
100130812Smarcel      if (CANNOT_FETCH_REGISTER (regno))
101130812Smarcel	{
102130812Smarcel	  supply_register (regno, NULL);
103130812Smarcel	  continue;
104130812Smarcel	}
105130812Smarcel      addr = 8 * core_reg_mapping[regno];
106130812Smarcel      if (addr < 0 || addr >= core_reg_size)
107130812Smarcel	{
108130812Smarcel	  /* ??? UNIQUE is a new addition.  Don't generate an error.  */
109130812Smarcel	  if (regno == ALPHA_UNIQUE_REGNUM)
110130812Smarcel	    {
111130812Smarcel	      supply_register (regno, NULL);
112130812Smarcel	      continue;
113130812Smarcel	    }
114130812Smarcel	  if (bad_reg < 0)
115130812Smarcel	    bad_reg = regno;
116130812Smarcel	}
117130812Smarcel      else
118130812Smarcel	{
119130812Smarcel	  supply_register (regno, core_reg_sect + addr);
120130812Smarcel	}
121130812Smarcel    }
122130812Smarcel  if (bad_reg >= 0)
123130812Smarcel    {
124130812Smarcel      error ("Register %s not found in core file.", REGISTER_NAME (bad_reg));
125130812Smarcel    }
126130812Smarcel}
127130812Smarcel
128130812Smarcelstatic void
129130812Smarcelfetch_elf_core_registers (char *core_reg_sect, unsigned core_reg_size,
130130812Smarcel			  int which, CORE_ADDR reg_addr)
131130812Smarcel{
132130812Smarcel  if (core_reg_size < 32 * 8)
133130812Smarcel    {
134130812Smarcel      error ("Core file register section too small (%u bytes).", core_reg_size);
135130812Smarcel      return;
136130812Smarcel    }
137130812Smarcel
138130812Smarcel  switch (which)
139130812Smarcel    {
140130812Smarcel    case 0: /* integer registers */
141130812Smarcel      /* PC is in slot 32; UNIQUE is in slot 33, if present.  */
142130812Smarcel      alpha_supply_int_regs (-1, core_reg_sect, core_reg_sect + 31*8,
143130812Smarcel			     (core_reg_size >= 33 * 8
144130812Smarcel			      ? core_reg_sect + 32*8 : NULL));
145130812Smarcel      break;
146130812Smarcel
147130812Smarcel    case 2: /* floating-point registers */
148130812Smarcel      /* FPCR is in slot 32.  */
149130812Smarcel      alpha_supply_fp_regs (-1, core_reg_sect, core_reg_sect + 31*8);
150130812Smarcel      break;
151130812Smarcel
152130812Smarcel    default:
153130812Smarcel      break;
154130812Smarcel    }
155130812Smarcel}
156130812Smarcel
157130812Smarcel
158130812Smarcel/* Map gdb internal register number to a ptrace ``address''.
159130812Smarcel   These ``addresses'' are defined in <sys/ptrace.h>, with
160130812Smarcel   the exception of ALPHA_UNIQUE_PTRACE_ADDR.  */
161130812Smarcel
162130812Smarcel#ifndef ALPHA_UNIQUE_PTRACE_ADDR
163130812Smarcel#define ALPHA_UNIQUE_PTRACE_ADDR 0
164130812Smarcel#endif
165130812Smarcel
166130812SmarcelCORE_ADDR
167130812Smarcelregister_addr (int regno, CORE_ADDR blockend)
168130812Smarcel{
169130812Smarcel  if (regno == PC_REGNUM)
170130812Smarcel    return PC;
171130812Smarcel  if (regno == ALPHA_UNIQUE_REGNUM)
172130812Smarcel    return ALPHA_UNIQUE_PTRACE_ADDR;
173130812Smarcel  if (regno < FP0_REGNUM)
174130812Smarcel    return GPR_BASE + regno;
175130812Smarcel  else
176130812Smarcel    return FPR_BASE + regno - FP0_REGNUM;
177130812Smarcel}
178130812Smarcel
179130812Smarcelint
180130812Smarcelkernel_u_size (void)
181130812Smarcel{
182130812Smarcel  return (sizeof (struct user));
183130812Smarcel}
184130812Smarcel
185130812Smarcel#if defined(USE_PROC_FS) || defined(HAVE_GREGSET_T)
186130812Smarcel#include <sys/procfs.h>
187130812Smarcel
188130812Smarcel/* Prototypes for supply_gregset etc. */
189130812Smarcel#include "gregset.h"
190130812Smarcel
191130812Smarcel/* Locate the UNIQUE value within the gregset_t.  */
192130812Smarcel#ifndef ALPHA_REGSET_UNIQUE
193130812Smarcel#define ALPHA_REGSET_UNIQUE(ptr) NULL
194130812Smarcel#endif
195130812Smarcel
196130812Smarcel/*
197130812Smarcel * See the comment in m68k-tdep.c regarding the utility of these functions.
198130812Smarcel */
199130812Smarcel
200130812Smarcelvoid
201130812Smarcelsupply_gregset (gdb_gregset_t *gregsetp)
202130812Smarcel{
203130812Smarcel  long *regp = ALPHA_REGSET_BASE (gregsetp);
204130812Smarcel  void *unique = ALPHA_REGSET_UNIQUE (gregsetp);
205130812Smarcel
206130812Smarcel  /* PC is in slot 32.  */
207130812Smarcel  alpha_supply_int_regs (-1, regp, regp + 31, unique);
208130812Smarcel}
209130812Smarcel
210130812Smarcelvoid
211130812Smarcelfill_gregset (gdb_gregset_t *gregsetp, int regno)
212130812Smarcel{
213130812Smarcel  long *regp = ALPHA_REGSET_BASE (gregsetp);
214130812Smarcel  void *unique = ALPHA_REGSET_UNIQUE (gregsetp);
215130812Smarcel
216130812Smarcel  /* PC is in slot 32.  */
217130812Smarcel  alpha_fill_int_regs (regno, regp, regp + 31, unique);
218130812Smarcel}
219130812Smarcel
220130812Smarcel/*
221130812Smarcel * Now we do the same thing for floating-point registers.
222130812Smarcel * Again, see the comments in m68k-tdep.c.
223130812Smarcel */
224130812Smarcel
225130812Smarcelvoid
226130812Smarcelsupply_fpregset (gdb_fpregset_t *fpregsetp)
227130812Smarcel{
228130812Smarcel  long *regp = ALPHA_REGSET_BASE (fpregsetp);
229130812Smarcel
230130812Smarcel  /* FPCR is in slot 32.  */
231130812Smarcel  alpha_supply_fp_regs (-1, regp, regp + 31);
232130812Smarcel}
233130812Smarcel
234130812Smarcelvoid
235130812Smarcelfill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
236130812Smarcel{
237130812Smarcel  long *regp = ALPHA_REGSET_BASE (fpregsetp);
238130812Smarcel
239130812Smarcel  /* FPCR is in slot 32.  */
240130812Smarcel  alpha_fill_fp_regs (regno, regp, regp + 31);
241130812Smarcel}
242130812Smarcel#endif
243130812Smarcel
244130812Smarcel
245130812Smarcel/* Register that we are able to handle alpha core file formats. */
246130812Smarcel
247130812Smarcelstatic struct core_fns alpha_osf_core_fns =
248130812Smarcel{
249130812Smarcel  /* This really is bfd_target_unknown_flavour.  */
250130812Smarcel
251130812Smarcel  bfd_target_unknown_flavour,		/* core_flavour */
252130812Smarcel  default_check_format,			/* check_format */
253130812Smarcel  default_core_sniffer,			/* core_sniffer */
254130812Smarcel  fetch_osf_core_registers,		/* core_read_registers */
255130812Smarcel  NULL					/* next */
256130812Smarcel};
257130812Smarcel
258130812Smarcelstatic struct core_fns alpha_elf_core_fns =
259130812Smarcel{
260130812Smarcel  bfd_target_elf_flavour,		/* core_flavour */
261130812Smarcel  default_check_format,			/* check_format */
262130812Smarcel  default_core_sniffer,			/* core_sniffer */
263130812Smarcel  fetch_elf_core_registers,		/* core_read_registers */
264130812Smarcel  NULL					/* next */
265130812Smarcel};
266130812Smarcel
267130812Smarcelvoid
268130812Smarcel_initialize_core_alpha (void)
269130812Smarcel{
270130812Smarcel  add_core_fns (&alpha_osf_core_fns);
271130812Smarcel  add_core_fns (&alpha_elf_core_fns);
272130812Smarcel}
273