1131082Smarcel/*
2131082Smarcel * Copyright (c) 2004 Marcel Moolenaar
3131082Smarcel * All rights reserved.
4131082Smarcel *
5131082Smarcel * Redistribution and use in source and binary forms, with or without
6131082Smarcel * modification, are permitted provided that the following conditions
7131082Smarcel * are met:
8131082Smarcel *
9131082Smarcel * 1. Redistributions of source code must retain the above copyright
10131082Smarcel *    notice, this list of conditions and the following disclaimer.
11131082Smarcel * 2. Redistributions in binary form must reproduce the above copyright
12131082Smarcel *    notice, this list of conditions and the following disclaimer in the
13131082Smarcel *    documentation and/or other materials provided with the distribution.
14131082Smarcel *
15131082Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16131082Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17131082Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18131082Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19131082Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20131082Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21131082Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22131082Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23131082Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24131082Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25131082Smarcel */
26131082Smarcel
27131082Smarcel#include "defs.h"
28131082Smarcel#include "gdb_string.h"
29131082Smarcel#include "regcache.h"
30131082Smarcel#include "regset.h"
31131082Smarcel#include "solib-svr4.h"
32131082Smarcel#include "value.h"
33131082Smarcel
34131082Smarcel#include "ia64-tdep.h"
35131082Smarcel
36131082Smarcel#define FPREG_SUPPLIES(r) ((r) >= IA64_FR0_REGNUM && (r) <= IA64_FR127_REGNUM)
37131082Smarcel#define GREG_SUPPLIES(r)  (!FPREG_SUPPLIES(r))
38131082Smarcel
39131082Smarcelstatic int reg_offset[462] = {
40131082Smarcel    -1,   96,  248,  256,  152,  160,  168,  176,       /* Regs 0-7. */
41131082Smarcel   264,  272,  280,  288,    0,   64,  296,  304,       /* Regs 8-15. */
42131082Smarcel   312,  320,  328,  336,  344,  352,  360,  368,       /* Regs 16-23. */
43131082Smarcel   376,  384,  392,  400,  408,  416,  424,  432,       /* Regs 24-31. */
44131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 32-39. */
45131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 40-47. */
46131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 48-55. */
47131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 56-63. */
48131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 64-71. */
49131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 72-79. */
50131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 80-87. */
51131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 88-95. */
52131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 96-103. */
53131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 104-111. */
54131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 112-119. */
55131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 120-127. */
56131082Smarcel    -1,   -1,    0,   16,   32,   48,  320,  336,       /* Regs 128-135. */
57131082Smarcel   352,  368,  384,  400,  416,  432,  448,  464,       /* Regs 136-143. */
58131082Smarcel    64,   80,   96,  112,  128,  144,  160,  176,       /* Regs 144-151. */
59131082Smarcel   192,  208,  224,  240,  256,  272,  288,  304,       /* Regs 152-159. */
60131082Smarcel   480,  496,  512,  528,  544,  560,  576,  592,       /* Regs 160-167. */
61131082Smarcel   608,  624,  640,  656,  672,  688,  704,  720,       /* Regs 168-175. */
62131082Smarcel   736,  752,  768,  784,  800,  816,  832,  848,       /* Regs 176-183. */
63131082Smarcel   864,  880,  896,  912,  928,  944,  960,  976,       /* Regs 184-191. */
64131082Smarcel   992, 1008, 1024, 1040, 1056, 1072, 1088, 1104,       /* Regs 192-199. */
65131082Smarcel  1120, 1136, 1152, 1168, 1184, 1200, 1216, 1232,       /* Regs 200-207. */
66131082Smarcel  1248, 1264, 1280, 1296, 1312, 1328, 1344, 1360,       /* Regs 208-215. */
67131082Smarcel  1376, 1392, 1408, 1424, 1440, 1456, 1472, 1488,       /* Regs 216-223. */
68131082Smarcel  1504, 1520, 1536, 1552, 1568, 1584, 1600, 1616,       /* Regs 224-231. */
69131082Smarcel  1632, 1648, 1664, 1680, 1696, 1712, 1728, 1744,       /* Regs 232-239. */
70131082Smarcel  1760, 1776, 1792, 1808, 1824, 1840, 1856, 1872,       /* Regs 240-247. */
71131082Smarcel  1888, 1904, 1920, 1936, 1952, 1968, 1984, 2000,       /* Regs 248-255. */
72131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 256-263. */
73131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 264-271. */
74131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 272-279. */
75131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 280-287. */
76131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 288-295. */
77131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 296-303. */
78131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 304-311. */
79131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 312-319. */
80131082Smarcel    16,  184,  192,  200,  208,  216,  440,  448,       /* Regs 320-327. */
81131082Smarcel    -1,   -1,   24,  120,   88,  112,   -1,   -1,       /* Regs 328-335. */
82131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 336-343. */
83131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   72,  104,       /* Regs 344-351. */
84131082Smarcel    40,   48,   -1,   -1,   -1,   -1,   -1,  464,       /* Regs 352-359. */
85131082Smarcel   472,   -1,   -1,   -1,   -1,   -1,  456,   -1,       /* Regs 360-367. */
86131082Smarcel    -1,   -1,    8,   -1,   -1,   -1,   80,   -1,       /* Regs 368-375. */
87131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 376-383. */
88131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 384-391. */
89131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   32,  224,       /* Regs 392-399. */
90131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 400-407. */
91131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 408-415. */
92131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 416-423. */
93131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 424-431. */
94131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 432-439. */
95131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 440-447. */
96131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 448-455. */
97131082Smarcel    -1,   -1,   -1,   -1,   -1,   -1
98131082Smarcel};
99131082Smarcel
100131082Smarcelstatic void
101131082Smarcelia64_fbsd_regcache_collect (struct regcache *regcache, int regno,
102131082Smarcel			    void *regs)
103131082Smarcel{
104131082Smarcel  int ofs;
105131082Smarcel
106131082Smarcel  if (regno < 0 || regno >= NUM_REGS)
107131082Smarcel    return;
108131082Smarcel
109131082Smarcel  ofs = reg_offset[regno];
110132685Smarcel  if (regno == IA64_BSP_REGNUM)
111132685Smarcel    {
112132685Smarcel      uint64_t bsp, bspstore;
113132685Smarcel      regcache_raw_collect (regcache, regno, &bsp);
114132685Smarcel      regcache_raw_collect (regcache, IA64_BSPSTORE_REGNUM, &bspstore);
115132685Smarcel      *(uint64_t *)((char *)regs + ofs) = bsp - bspstore;
116132685Smarcel    }
117132685Smarcel  else
118132685Smarcel    {
119132685Smarcel      if (ofs >= 0)
120132685Smarcel	regcache_raw_collect (regcache, regno, (char*)regs + ofs);
121132685Smarcel    }
122131082Smarcel}
123131082Smarcel
124131082Smarcelstatic void
125131082Smarcelia64_fbsd_regcache_supply (struct regcache *regcache, int regno,
126131082Smarcel			   const void *regs)
127131082Smarcel{
128131082Smarcel  int ofs;
129131082Smarcel
130131082Smarcel  if (regno < 0 || regno >= NUM_REGS)
131131082Smarcel    return;
132131082Smarcel
133131082Smarcel  ofs = reg_offset[regno];
134131082Smarcel  if (regno == IA64_BSP_REGNUM)
135131082Smarcel    {
136131082Smarcel      /* BSP is synthesized. It's not actually present in struct reg,
137131082Smarcel	 but can be derived from bspstore and ndirty. The offset of
138131082Smarcel	 IA64_BSP_REGNUM in the reg_offset array above is that of the
139131082Smarcel	 ndirty field in struct reg. */
140131082Smarcel      uint64_t bsp;
141131082Smarcel      bsp = *((uint64_t*)((char *)regs + ofs));		/* ndirty */
142131082Smarcel      bsp += *((uint64_t*)((char *)regs + reg_offset[IA64_BSPSTORE_REGNUM]));
143131082Smarcel      regcache_raw_supply (regcache, regno, &bsp);
144131082Smarcel    }
145131082Smarcel  else
146131082Smarcel    {
147131082Smarcel      if (ofs < 0)
148131082Smarcel	regcache_raw_supply (regcache, regno, NULL);
149131082Smarcel      else
150131082Smarcel	regcache_raw_supply (regcache, regno, (char *)regs + ofs);
151131082Smarcel    }
152131082Smarcel}
153131082Smarcel
154131082Smarcelvoid
155131082Smarcelfill_fpregset (void *fpregs, int regno)
156131082Smarcel{
157131082Smarcel  if (regno == -1)
158131082Smarcel    {
159131082Smarcel      for (regno = 0; regno < NUM_REGS; regno++)
160131082Smarcel	{
161131082Smarcel	  if (FPREG_SUPPLIES(regno))
162131082Smarcel	    ia64_fbsd_regcache_collect (current_regcache, regno, fpregs);
163131082Smarcel	}
164131082Smarcel    }
165131082Smarcel  else
166131082Smarcel    {
167131082Smarcel      if (FPREG_SUPPLIES(regno))
168131082Smarcel	ia64_fbsd_regcache_collect (current_regcache, regno, fpregs);
169131082Smarcel    }
170131082Smarcel}
171131082Smarcel
172131082Smarcelvoid
173131082Smarcelfill_gregset (void *gregs, int regno)
174131082Smarcel{
175131082Smarcel  if (regno == -1)
176131082Smarcel    {
177131082Smarcel      for (regno = 0; regno < NUM_REGS; regno++)
178131082Smarcel	{
179131082Smarcel	  if (GREG_SUPPLIES(regno))
180131082Smarcel	    ia64_fbsd_regcache_collect (current_regcache, regno, gregs);
181131082Smarcel	}
182131082Smarcel    }
183131082Smarcel  else
184131082Smarcel    {
185131082Smarcel      if (GREG_SUPPLIES(regno))
186131082Smarcel	ia64_fbsd_regcache_collect (current_regcache, regno, gregs);
187131082Smarcel    }
188131082Smarcel}
189131082Smarcel
190131082Smarcelvoid
191132685Smarcelsupply_fpregset (const void *fpregs)
192131082Smarcel{
193132685Smarcel  int regno;
194132685Smarcel
195132685Smarcel  for (regno = 0; regno < NUM_REGS; regno++)
196131082Smarcel    {
197131082Smarcel      if (FPREG_SUPPLIES(regno))
198131082Smarcel	ia64_fbsd_regcache_supply (current_regcache, regno, fpregs);
199131082Smarcel    }
200131082Smarcel}
201131082Smarcel
202131082Smarcelvoid
203132685Smarcelsupply_gregset (const void *gregs)
204131082Smarcel{
205132685Smarcel  int regno;
206132685Smarcel
207132685Smarcel  for (regno = 0; regno < NUM_REGS; regno++)
208131082Smarcel    {
209131082Smarcel      if (GREG_SUPPLIES(regno))
210131082Smarcel	ia64_fbsd_regcache_supply (current_regcache, regno, gregs);
211131082Smarcel    }
212131082Smarcel}
213131082Smarcel
214131082Smarcelstatic void
215131082Smarcelia64_fbsd_supply_gregset (const struct regset *regset,
216131082Smarcel			  struct regcache *regcache, int regno,
217131082Smarcel			  const void *gregs, size_t len)
218131082Smarcel{
219131082Smarcel  if (regno == -1)
220131082Smarcel    {
221131082Smarcel      for (regno = 0; regno < NUM_REGS; regno++)
222131082Smarcel	{
223131082Smarcel	  if (GREG_SUPPLIES(regno))
224131082Smarcel	    ia64_fbsd_regcache_supply (regcache, regno, gregs);
225131082Smarcel	}
226131082Smarcel    }
227131082Smarcel  else
228131082Smarcel    if (GREG_SUPPLIES(regno))
229131082Smarcel      ia64_fbsd_regcache_supply (regcache, regno, gregs);
230131082Smarcel}
231131082Smarcel
232131082Smarcelstatic void
233131082Smarcelia64_fbsd_supply_fpregset (const struct regset *regset,
234131082Smarcel			   struct regcache *regcache, int regno,
235131082Smarcel			   const void *fpregs, size_t len)
236131082Smarcel{
237131082Smarcel  if (regno == -1)
238131082Smarcel    {
239131082Smarcel      for (regno = 0; regno < NUM_REGS; regno++)
240131082Smarcel	{
241131082Smarcel	  if (FPREG_SUPPLIES(regno))
242131082Smarcel	    ia64_fbsd_regcache_supply (regcache, regno, fpregs);
243131082Smarcel	}
244131082Smarcel    }
245131082Smarcel  else
246131082Smarcel    if (FPREG_SUPPLIES(regno))
247131082Smarcel      ia64_fbsd_regcache_supply (regcache, regno, fpregs);
248131082Smarcel}
249131082Smarcel
250131082Smarcelstatic struct regset gregset = { NULL, ia64_fbsd_supply_gregset };
251131082Smarcelstatic struct regset fpregset = { NULL, ia64_fbsd_supply_fpregset };
252131082Smarcel
253131082Smarcelstatic const struct regset *
254131082Smarcelia64_fbsd_regset_from_core_section (struct gdbarch *gdbarch,
255131082Smarcel				    const char *sect_name, size_t sect_size)
256131082Smarcel{
257131082Smarcel  if (strcmp (sect_name, ".reg") == 0)
258131082Smarcel    return (&gregset);
259131082Smarcel  if (strcmp (sect_name, ".reg2") == 0)
260131082Smarcel    return (&fpregset);
261131082Smarcel  return (NULL);
262131082Smarcel}
263131082Smarcel
264131082Smarcelstatic int
265131082Smarcelia64_fbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
266131082Smarcel{
267131082Smarcel  uint64_t gwpage = 5ULL << 61;
268131082Smarcel  return (pc >= gwpage && pc < (gwpage + 8192)) ? 1 : 0;
269131082Smarcel}
270131082Smarcel
271131082Smarcelstatic void
272131082Smarcelia64_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
273131082Smarcel{
274131082Smarcel  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
275131082Smarcel
276131082Smarcel  set_gdbarch_pc_in_sigtramp (gdbarch, ia64_fbsd_pc_in_sigtramp);
277131082Smarcel  set_gdbarch_regset_from_core_section (gdbarch,
278131082Smarcel                                        ia64_fbsd_regset_from_core_section);
279131082Smarcel  set_solib_svr4_fetch_link_map_offsets (gdbarch,
280131082Smarcel					 svr4_lp64_fetch_link_map_offsets);
281131082Smarcel  tdep->find_global_pointer = ia64_generic_find_global_pointer;
282131082Smarcel}
283131082Smarcel
284131082Smarcelvoid
285131082Smarcel_initialize_ia64_fbsd_tdep (void)
286131082Smarcel{
287131082Smarcel  gdbarch_register_osabi (bfd_arch_ia64, 0ul, GDB_OSABI_FREEBSD_ELF,
288131082Smarcel                          ia64_fbsd_init_abi);
289131082Smarcel}
290