1/*
2 * Copyright (c) 2004 Marcel Moolenaar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "defs.h"
28#include "gdb_string.h"
29#include "regcache.h"
30#include "regset.h"
31#include "solib-svr4.h"
32#include "value.h"
33
34#include "ia64-tdep.h"
35
36#define FPREG_SUPPLIES(r) ((r) >= IA64_FR0_REGNUM && (r) <= IA64_FR127_REGNUM)
37#define GREG_SUPPLIES(r)  (!FPREG_SUPPLIES(r))
38
39static int reg_offset[462] = {
40    -1,   96,  248,  256,  152,  160,  168,  176,       /* Regs 0-7. */
41   264,  272,  280,  288,    0,   64,  296,  304,       /* Regs 8-15. */
42   312,  320,  328,  336,  344,  352,  360,  368,       /* Regs 16-23. */
43   376,  384,  392,  400,  408,  416,  424,  432,       /* Regs 24-31. */
44    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 32-39. */
45    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 40-47. */
46    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 48-55. */
47    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 56-63. */
48    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 64-71. */
49    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 72-79. */
50    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 80-87. */
51    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 88-95. */
52    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 96-103. */
53    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 104-111. */
54    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 112-119. */
55    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 120-127. */
56    -1,   -1,    0,   16,   32,   48,  320,  336,       /* Regs 128-135. */
57   352,  368,  384,  400,  416,  432,  448,  464,       /* Regs 136-143. */
58    64,   80,   96,  112,  128,  144,  160,  176,       /* Regs 144-151. */
59   192,  208,  224,  240,  256,  272,  288,  304,       /* Regs 152-159. */
60   480,  496,  512,  528,  544,  560,  576,  592,       /* Regs 160-167. */
61   608,  624,  640,  656,  672,  688,  704,  720,       /* Regs 168-175. */
62   736,  752,  768,  784,  800,  816,  832,  848,       /* Regs 176-183. */
63   864,  880,  896,  912,  928,  944,  960,  976,       /* Regs 184-191. */
64   992, 1008, 1024, 1040, 1056, 1072, 1088, 1104,       /* Regs 192-199. */
65  1120, 1136, 1152, 1168, 1184, 1200, 1216, 1232,       /* Regs 200-207. */
66  1248, 1264, 1280, 1296, 1312, 1328, 1344, 1360,       /* Regs 208-215. */
67  1376, 1392, 1408, 1424, 1440, 1456, 1472, 1488,       /* Regs 216-223. */
68  1504, 1520, 1536, 1552, 1568, 1584, 1600, 1616,       /* Regs 224-231. */
69  1632, 1648, 1664, 1680, 1696, 1712, 1728, 1744,       /* Regs 232-239. */
70  1760, 1776, 1792, 1808, 1824, 1840, 1856, 1872,       /* Regs 240-247. */
71  1888, 1904, 1920, 1936, 1952, 1968, 1984, 2000,       /* Regs 248-255. */
72    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 256-263. */
73    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 264-271. */
74    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 272-279. */
75    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 280-287. */
76    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 288-295. */
77    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 296-303. */
78    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 304-311. */
79    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 312-319. */
80    16,  184,  192,  200,  208,  216,  440,  448,       /* Regs 320-327. */
81    -1,   -1,   24,  120,   88,  112,   -1,   -1,       /* Regs 328-335. */
82    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 336-343. */
83    -1,   -1,   -1,   -1,   -1,   -1,   72,  104,       /* Regs 344-351. */
84    40,   48,   -1,   -1,   -1,   -1,   -1,  464,       /* Regs 352-359. */
85   472,   -1,   -1,   -1,   -1,   -1,  456,   -1,       /* Regs 360-367. */
86    -1,   -1,    8,   -1,   -1,   -1,   80,   -1,       /* Regs 368-375. */
87    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 376-383. */
88    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 384-391. */
89    -1,   -1,   -1,   -1,   -1,   -1,   32,  224,       /* Regs 392-399. */
90    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 400-407. */
91    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 408-415. */
92    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 416-423. */
93    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 424-431. */
94    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 432-439. */
95    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 440-447. */
96    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,       /* Regs 448-455. */
97    -1,   -1,   -1,   -1,   -1,   -1
98};
99
100static void
101ia64_fbsd_regcache_collect (struct regcache *regcache, int regno,
102			    void *regs)
103{
104  int ofs;
105
106  if (regno < 0 || regno >= NUM_REGS)
107    return;
108
109  ofs = reg_offset[regno];
110  if (regno == IA64_BSP_REGNUM)
111    {
112      uint64_t bsp, bspstore;
113      regcache_raw_collect (regcache, regno, &bsp);
114      regcache_raw_collect (regcache, IA64_BSPSTORE_REGNUM, &bspstore);
115      *(uint64_t *)((char *)regs + ofs) = bsp - bspstore;
116    }
117  else
118    {
119      if (ofs >= 0)
120	regcache_raw_collect (regcache, regno, (char*)regs + ofs);
121    }
122}
123
124static void
125ia64_fbsd_regcache_supply (struct regcache *regcache, int regno,
126			   const void *regs)
127{
128  int ofs;
129
130  if (regno < 0 || regno >= NUM_REGS)
131    return;
132
133  ofs = reg_offset[regno];
134  if (regno == IA64_BSP_REGNUM)
135    {
136      /* BSP is synthesized. It's not actually present in struct reg,
137	 but can be derived from bspstore and ndirty. The offset of
138	 IA64_BSP_REGNUM in the reg_offset array above is that of the
139	 ndirty field in struct reg. */
140      uint64_t bsp;
141      bsp = *((uint64_t*)((char *)regs + ofs));		/* ndirty */
142      bsp += *((uint64_t*)((char *)regs + reg_offset[IA64_BSPSTORE_REGNUM]));
143      regcache_raw_supply (regcache, regno, &bsp);
144    }
145  else
146    {
147      if (ofs < 0)
148	regcache_raw_supply (regcache, regno, NULL);
149      else
150	regcache_raw_supply (regcache, regno, (char *)regs + ofs);
151    }
152}
153
154void
155fill_fpregset (void *fpregs, int regno)
156{
157  if (regno == -1)
158    {
159      for (regno = 0; regno < NUM_REGS; regno++)
160	{
161	  if (FPREG_SUPPLIES(regno))
162	    ia64_fbsd_regcache_collect (current_regcache, regno, fpregs);
163	}
164    }
165  else
166    {
167      if (FPREG_SUPPLIES(regno))
168	ia64_fbsd_regcache_collect (current_regcache, regno, fpregs);
169    }
170}
171
172void
173fill_gregset (void *gregs, int regno)
174{
175  if (regno == -1)
176    {
177      for (regno = 0; regno < NUM_REGS; regno++)
178	{
179	  if (GREG_SUPPLIES(regno))
180	    ia64_fbsd_regcache_collect (current_regcache, regno, gregs);
181	}
182    }
183  else
184    {
185      if (GREG_SUPPLIES(regno))
186	ia64_fbsd_regcache_collect (current_regcache, regno, gregs);
187    }
188}
189
190void
191supply_fpregset (const void *fpregs)
192{
193  int regno;
194
195  for (regno = 0; regno < NUM_REGS; regno++)
196    {
197      if (FPREG_SUPPLIES(regno))
198	ia64_fbsd_regcache_supply (current_regcache, regno, fpregs);
199    }
200}
201
202void
203supply_gregset (const void *gregs)
204{
205  int regno;
206
207  for (regno = 0; regno < NUM_REGS; regno++)
208    {
209      if (GREG_SUPPLIES(regno))
210	ia64_fbsd_regcache_supply (current_regcache, regno, gregs);
211    }
212}
213
214static void
215ia64_fbsd_supply_gregset (const struct regset *regset,
216			  struct regcache *regcache, int regno,
217			  const void *gregs, size_t len)
218{
219  if (regno == -1)
220    {
221      for (regno = 0; regno < NUM_REGS; regno++)
222	{
223	  if (GREG_SUPPLIES(regno))
224	    ia64_fbsd_regcache_supply (regcache, regno, gregs);
225	}
226    }
227  else
228    if (GREG_SUPPLIES(regno))
229      ia64_fbsd_regcache_supply (regcache, regno, gregs);
230}
231
232static void
233ia64_fbsd_supply_fpregset (const struct regset *regset,
234			   struct regcache *regcache, int regno,
235			   const void *fpregs, size_t len)
236{
237  if (regno == -1)
238    {
239      for (regno = 0; regno < NUM_REGS; regno++)
240	{
241	  if (FPREG_SUPPLIES(regno))
242	    ia64_fbsd_regcache_supply (regcache, regno, fpregs);
243	}
244    }
245  else
246    if (FPREG_SUPPLIES(regno))
247      ia64_fbsd_regcache_supply (regcache, regno, fpregs);
248}
249
250static struct regset gregset = { NULL, ia64_fbsd_supply_gregset };
251static struct regset fpregset = { NULL, ia64_fbsd_supply_fpregset };
252
253static const struct regset *
254ia64_fbsd_regset_from_core_section (struct gdbarch *gdbarch,
255				    const char *sect_name, size_t sect_size)
256{
257  if (strcmp (sect_name, ".reg") == 0)
258    return (&gregset);
259  if (strcmp (sect_name, ".reg2") == 0)
260    return (&fpregset);
261  return (NULL);
262}
263
264static int
265ia64_fbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
266{
267  uint64_t gwpage = 5ULL << 61;
268  return (pc >= gwpage && pc < (gwpage + 8192)) ? 1 : 0;
269}
270
271static void
272ia64_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
273{
274  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
275
276  set_gdbarch_pc_in_sigtramp (gdbarch, ia64_fbsd_pc_in_sigtramp);
277  set_gdbarch_regset_from_core_section (gdbarch,
278                                        ia64_fbsd_regset_from_core_section);
279  set_solib_svr4_fetch_link_map_offsets (gdbarch,
280					 svr4_lp64_fetch_link_map_offsets);
281  tdep->find_global_pointer = ia64_generic_find_global_pointer;
282}
283
284void
285_initialize_ia64_fbsd_tdep (void)
286{
287  gdbarch_register_osabi (bfd_arch_ia64, 0ul, GDB_OSABI_FREEBSD_ELF,
288                          ia64_fbsd_init_abi);
289}
290