198944Sobrien/* Target-dependent code for the IA-64 for GDB, the GNU debugger.
298944Sobrien
3130803Smarcel   Copyright 1999, 2000, 2001, 2002, 2003, 2004 Free Software
4130803Smarcel   Foundation, Inc.
598944Sobrien
698944Sobrien   This file is part of GDB.
798944Sobrien
898944Sobrien   This program is free software; you can redistribute it and/or modify
998944Sobrien   it under the terms of the GNU General Public License as published by
1098944Sobrien   the Free Software Foundation; either version 2 of the License, or
1198944Sobrien   (at your option) any later version.
1298944Sobrien
1398944Sobrien   This program is distributed in the hope that it will be useful,
1498944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1598944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1698944Sobrien   GNU General Public License for more details.
1798944Sobrien
1898944Sobrien   You should have received a copy of the GNU General Public License
1998944Sobrien   along with this program; if not, write to the Free Software
2098944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
2198944Sobrien   Boston, MA 02111-1307, USA.  */
2298944Sobrien
2398944Sobrien#include "defs.h"
2498944Sobrien#include "inferior.h"
2598944Sobrien#include "gdbcore.h"
2698944Sobrien#include "arch-utils.h"
2798944Sobrien#include "floatformat.h"
2898944Sobrien#include "regcache.h"
29130803Smarcel#include "reggroups.h"
30130803Smarcel#include "frame.h"
31130803Smarcel#include "frame-base.h"
32130803Smarcel#include "frame-unwind.h"
3398944Sobrien#include "doublest.h"
3498944Sobrien#include "value.h"
35130803Smarcel#include "gdb_assert.h"
3698944Sobrien#include "objfiles.h"
3798944Sobrien#include "elf/common.h"		/* for DT_PLTGOT value */
3898944Sobrien#include "elf-bfd.h"
39130803Smarcel#include "elf.h"                /* for PT_IA64_UNWIND value */
40130803Smarcel#include "dis-asm.h"
41130803Smarcel#include "ia64-tdep.h"
4298944Sobrien
43130803Smarcel#ifdef HAVE_LIBUNWIND_IA64_H
44130803Smarcel#include "libunwind-frame.h"
45130803Smarcel#include "libunwind-ia64.h"
46130803Smarcel#endif
47130803Smarcel
4898944Sobrien/* An enumeration of the different IA-64 instruction types.  */
4998944Sobrien
5098944Sobrientypedef enum instruction_type
5198944Sobrien{
5298944Sobrien  A,			/* Integer ALU ;    I-unit or M-unit */
5398944Sobrien  I,			/* Non-ALU integer; I-unit */
5498944Sobrien  M,			/* Memory ;         M-unit */
5598944Sobrien  F,			/* Floating-point ; F-unit */
5698944Sobrien  B,			/* Branch ;         B-unit */
5798944Sobrien  L,			/* Extended (L+X) ; I-unit */
5898944Sobrien  X,			/* Extended (L+X) ; I-unit */
5998944Sobrien  undefined		/* undefined or reserved */
6098944Sobrien} instruction_type;
6198944Sobrien
6298944Sobrien/* We represent IA-64 PC addresses as the value of the instruction
6398944Sobrien   pointer or'd with some bit combination in the low nibble which
6498944Sobrien   represents the slot number in the bundle addressed by the
6598944Sobrien   instruction pointer.  The problem is that the Linux kernel
6698944Sobrien   multiplies its slot numbers (for exceptions) by one while the
6798944Sobrien   disassembler multiplies its slot numbers by 6.  In addition, I've
6898944Sobrien   heard it said that the simulator uses 1 as the multiplier.
6998944Sobrien
7098944Sobrien   I've fixed the disassembler so that the bytes_per_line field will
7198944Sobrien   be the slot multiplier.  If bytes_per_line comes in as zero, it
7298944Sobrien   is set to six (which is how it was set up initially). -- objdump
7398944Sobrien   displays pretty disassembly dumps with this value.  For our purposes,
7498944Sobrien   we'll set bytes_per_line to SLOT_MULTIPLIER. This is okay since we
7598944Sobrien   never want to also display the raw bytes the way objdump does. */
7698944Sobrien
7798944Sobrien#define SLOT_MULTIPLIER 1
7898944Sobrien
7998944Sobrien/* Length in bytes of an instruction bundle */
8098944Sobrien
8198944Sobrien#define BUNDLE_LEN 16
8298944Sobrien
8398944Sobrienstatic gdbarch_init_ftype ia64_gdbarch_init;
8498944Sobrien
8598944Sobrienstatic gdbarch_register_name_ftype ia64_register_name;
86130803Smarcelstatic gdbarch_register_type_ftype ia64_register_type;
8798944Sobrienstatic gdbarch_breakpoint_from_pc_ftype ia64_breakpoint_from_pc;
8898944Sobrienstatic gdbarch_skip_prologue_ftype ia64_skip_prologue;
8998944Sobrienstatic gdbarch_extract_return_value_ftype ia64_extract_return_value;
9098944Sobrienstatic gdbarch_use_struct_convention_ftype ia64_use_struct_convention;
9198944Sobrienstatic struct type *is_float_or_hfa_type (struct type *t);
9298944Sobrien
93130803Smarcelstatic struct type *builtin_type_ia64_ext;
9498944Sobrien
95130803Smarcel#define NUM_IA64_RAW_REGS 462
96130803Smarcel
9798944Sobrienstatic int sp_regnum = IA64_GR12_REGNUM;
9898944Sobrienstatic int fp_regnum = IA64_VFP_REGNUM;
9998944Sobrienstatic int lr_regnum = IA64_VRAP_REGNUM;
10098944Sobrien
101130803Smarcel/* NOTE: we treat the register stack registers r32-r127 as pseudo-registers because
102130803Smarcel   they may not be accessible via the ptrace register get/set interfaces.  */
103130803Smarcelenum pseudo_regs { FIRST_PSEUDO_REGNUM = NUM_IA64_RAW_REGS, VBOF_REGNUM = IA64_NAT127_REGNUM + 1, V32_REGNUM,
104130803Smarcel		   V127_REGNUM = V32_REGNUM + 95,
105130803Smarcel		   VP0_REGNUM, VP16_REGNUM = VP0_REGNUM + 16, VP63_REGNUM = VP0_REGNUM + 63, LAST_PSEUDO_REGNUM };
10698944Sobrien
10798944Sobrien/* Array of register names; There should be ia64_num_regs strings in
10898944Sobrien   the initializer.  */
10998944Sobrien
11098944Sobrienstatic char *ia64_register_names[] =
11198944Sobrien{ "r0",   "r1",   "r2",   "r3",   "r4",   "r5",   "r6",   "r7",
11298944Sobrien  "r8",   "r9",   "r10",  "r11",  "r12",  "r13",  "r14",  "r15",
11398944Sobrien  "r16",  "r17",  "r18",  "r19",  "r20",  "r21",  "r22",  "r23",
11498944Sobrien  "r24",  "r25",  "r26",  "r27",  "r28",  "r29",  "r30",  "r31",
115130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
116130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
117130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
118130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
119130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
120130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
121130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
122130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
123130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
124130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
125130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
126130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
12798944Sobrien
12898944Sobrien  "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7",
12998944Sobrien  "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15",
13098944Sobrien  "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",
13198944Sobrien  "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",
13298944Sobrien  "f32",  "f33",  "f34",  "f35",  "f36",  "f37",  "f38",  "f39",
13398944Sobrien  "f40",  "f41",  "f42",  "f43",  "f44",  "f45",  "f46",  "f47",
13498944Sobrien  "f48",  "f49",  "f50",  "f51",  "f52",  "f53",  "f54",  "f55",
13598944Sobrien  "f56",  "f57",  "f58",  "f59",  "f60",  "f61",  "f62",  "f63",
13698944Sobrien  "f64",  "f65",  "f66",  "f67",  "f68",  "f69",  "f70",  "f71",
13798944Sobrien  "f72",  "f73",  "f74",  "f75",  "f76",  "f77",  "f78",  "f79",
13898944Sobrien  "f80",  "f81",  "f82",  "f83",  "f84",  "f85",  "f86",  "f87",
13998944Sobrien  "f88",  "f89",  "f90",  "f91",  "f92",  "f93",  "f94",  "f95",
14098944Sobrien  "f96",  "f97",  "f98",  "f99",  "f100", "f101", "f102", "f103",
14198944Sobrien  "f104", "f105", "f106", "f107", "f108", "f109", "f110", "f111",
14298944Sobrien  "f112", "f113", "f114", "f115", "f116", "f117", "f118", "f119",
14398944Sobrien  "f120", "f121", "f122", "f123", "f124", "f125", "f126", "f127",
14498944Sobrien
145130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
146130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
147130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
148130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
149130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
150130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
151130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
152130803Smarcel  "",     "",     "",     "",     "",     "",     "",     "",
15398944Sobrien
15498944Sobrien  "b0",   "b1",   "b2",   "b3",   "b4",   "b5",   "b6",   "b7",
15598944Sobrien
15698944Sobrien  "vfp", "vrap",
15798944Sobrien
15898944Sobrien  "pr", "ip", "psr", "cfm",
15998944Sobrien
16098944Sobrien  "kr0",   "kr1",   "kr2",   "kr3",   "kr4",   "kr5",   "kr6",   "kr7",
16198944Sobrien  "", "", "", "", "", "", "", "",
16298944Sobrien  "rsc", "bsp", "bspstore", "rnat",
16398944Sobrien  "", "fcr", "", "",
16498944Sobrien  "eflag", "csd", "ssd", "cflg", "fsr", "fir", "fdr",  "",
16598944Sobrien  "ccv", "", "", "", "unat", "", "", "",
16698944Sobrien  "fpsr", "", "", "", "itc",
16798944Sobrien  "", "", "", "", "", "", "", "", "", "",
16898944Sobrien  "", "", "", "", "", "", "", "", "",
16998944Sobrien  "pfs", "lc", "ec",
17098944Sobrien  "", "", "", "", "", "", "", "", "", "",
17198944Sobrien  "", "", "", "", "", "", "", "", "", "",
17298944Sobrien  "", "", "", "", "", "", "", "", "", "",
17398944Sobrien  "", "", "", "", "", "", "", "", "", "",
17498944Sobrien  "", "", "", "", "", "", "", "", "", "",
17598944Sobrien  "", "", "", "", "", "", "", "", "", "",
17698944Sobrien  "",
17798944Sobrien  "nat0",  "nat1",  "nat2",  "nat3",  "nat4",  "nat5",  "nat6",  "nat7",
17898944Sobrien  "nat8",  "nat9",  "nat10", "nat11", "nat12", "nat13", "nat14", "nat15",
17998944Sobrien  "nat16", "nat17", "nat18", "nat19", "nat20", "nat21", "nat22", "nat23",
18098944Sobrien  "nat24", "nat25", "nat26", "nat27", "nat28", "nat29", "nat30", "nat31",
18198944Sobrien  "nat32", "nat33", "nat34", "nat35", "nat36", "nat37", "nat38", "nat39",
18298944Sobrien  "nat40", "nat41", "nat42", "nat43", "nat44", "nat45", "nat46", "nat47",
18398944Sobrien  "nat48", "nat49", "nat50", "nat51", "nat52", "nat53", "nat54", "nat55",
18498944Sobrien  "nat56", "nat57", "nat58", "nat59", "nat60", "nat61", "nat62", "nat63",
18598944Sobrien  "nat64", "nat65", "nat66", "nat67", "nat68", "nat69", "nat70", "nat71",
18698944Sobrien  "nat72", "nat73", "nat74", "nat75", "nat76", "nat77", "nat78", "nat79",
18798944Sobrien  "nat80", "nat81", "nat82", "nat83", "nat84", "nat85", "nat86", "nat87",
18898944Sobrien  "nat88", "nat89", "nat90", "nat91", "nat92", "nat93", "nat94", "nat95",
18998944Sobrien  "nat96", "nat97", "nat98", "nat99", "nat100","nat101","nat102","nat103",
19098944Sobrien  "nat104","nat105","nat106","nat107","nat108","nat109","nat110","nat111",
19198944Sobrien  "nat112","nat113","nat114","nat115","nat116","nat117","nat118","nat119",
19298944Sobrien  "nat120","nat121","nat122","nat123","nat124","nat125","nat126","nat127",
193130803Smarcel
194130803Smarcel  "bof",
195130803Smarcel
196130803Smarcel  "r32",  "r33",  "r34",  "r35",  "r36",  "r37",  "r38",  "r39",
197130803Smarcel  "r40",  "r41",  "r42",  "r43",  "r44",  "r45",  "r46",  "r47",
198130803Smarcel  "r48",  "r49",  "r50",  "r51",  "r52",  "r53",  "r54",  "r55",
199130803Smarcel  "r56",  "r57",  "r58",  "r59",  "r60",  "r61",  "r62",  "r63",
200130803Smarcel  "r64",  "r65",  "r66",  "r67",  "r68",  "r69",  "r70",  "r71",
201130803Smarcel  "r72",  "r73",  "r74",  "r75",  "r76",  "r77",  "r78",  "r79",
202130803Smarcel  "r80",  "r81",  "r82",  "r83",  "r84",  "r85",  "r86",  "r87",
203130803Smarcel  "r88",  "r89",  "r90",  "r91",  "r92",  "r93",  "r94",  "r95",
204130803Smarcel  "r96",  "r97",  "r98",  "r99",  "r100", "r101", "r102", "r103",
205130803Smarcel  "r104", "r105", "r106", "r107", "r108", "r109", "r110", "r111",
206130803Smarcel  "r112", "r113", "r114", "r115", "r116", "r117", "r118", "r119",
207130803Smarcel  "r120", "r121", "r122", "r123", "r124", "r125", "r126", "r127",
208130803Smarcel
209130803Smarcel  "p0",   "p1",   "p2",   "p3",   "p4",   "p5",   "p6",   "p7",
210130803Smarcel  "p8",   "p9",   "p10",  "p11",  "p12",  "p13",  "p14",  "p15",
211130803Smarcel  "p16",  "p17",  "p18",  "p19",  "p20",  "p21",  "p22",  "p23",
212130803Smarcel  "p24",  "p25",  "p26",  "p27",  "p28",  "p29",  "p30",  "p31",
213130803Smarcel  "p32",  "p33",  "p34",  "p35",  "p36",  "p37",  "p38",  "p39",
214130803Smarcel  "p40",  "p41",  "p42",  "p43",  "p44",  "p45",  "p46",  "p47",
215130803Smarcel  "p48",  "p49",  "p50",  "p51",  "p52",  "p53",  "p54",  "p55",
216130803Smarcel  "p56",  "p57",  "p58",  "p59",  "p60",  "p61",  "p62",  "p63",
21798944Sobrien};
21898944Sobrien
219130803Smarcelstruct ia64_frame_cache
220130803Smarcel{
221130803Smarcel  CORE_ADDR base;       /* frame pointer base for frame */
222130803Smarcel  CORE_ADDR pc;		/* function start pc for frame */
223130803Smarcel  CORE_ADDR saved_sp;	/* stack pointer for frame */
224130803Smarcel  CORE_ADDR bsp;	/* points at r32 for the current frame */
225130803Smarcel  CORE_ADDR cfm;	/* cfm value for current frame */
226130803Smarcel  CORE_ADDR prev_cfm;   /* cfm value for previous frame */
227130803Smarcel  int   frameless;
228130803Smarcel  int   sof;		/* Size of frame  (decoded from cfm value) */
229130803Smarcel  int	sol;		/* Size of locals (decoded from cfm value) */
230130803Smarcel  int	sor;		/* Number of rotating registers. (decoded from cfm value) */
231130803Smarcel  CORE_ADDR after_prologue;
232130803Smarcel  /* Address of first instruction after the last
233130803Smarcel     prologue instruction;  Note that there may
234130803Smarcel     be instructions from the function's body
235130803Smarcel     intermingled with the prologue. */
236130803Smarcel  int mem_stack_frame_size;
237130803Smarcel  /* Size of the memory stack frame (may be zero),
238130803Smarcel     or -1 if it has not been determined yet. */
239130803Smarcel  int	fp_reg;		/* Register number (if any) used a frame pointer
24098944Sobrien			   for this frame.  0 if no register is being used
24198944Sobrien			   as the frame pointer. */
242130803Smarcel
243130803Smarcel  /* Saved registers.  */
244130803Smarcel  CORE_ADDR saved_regs[NUM_IA64_RAW_REGS];
24598944Sobrien
246130803Smarcel};
247130803Smarcel
24898944Sobrienint
249130803Smarcelia64_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
250130803Smarcel			  struct reggroup *group)
25198944Sobrien{
252130803Smarcel  int vector_p;
253130803Smarcel  int float_p;
254130803Smarcel  int raw_p;
255130803Smarcel  if (group == all_reggroup)
256130803Smarcel    return 1;
257130803Smarcel  vector_p = TYPE_VECTOR (register_type (gdbarch, regnum));
258130803Smarcel  float_p = TYPE_CODE (register_type (gdbarch, regnum)) == TYPE_CODE_FLT;
259130803Smarcel  raw_p = regnum < NUM_IA64_RAW_REGS;
260130803Smarcel  if (group == float_reggroup)
261130803Smarcel    return float_p;
262130803Smarcel  if (group == vector_reggroup)
263130803Smarcel    return vector_p;
264130803Smarcel  if (group == general_reggroup)
265130803Smarcel    return (!vector_p && !float_p);
266130803Smarcel  if (group == save_reggroup || group == restore_reggroup)
267130803Smarcel    return raw_p;
268130803Smarcel  return 0;
26998944Sobrien}
27098944Sobrien
271130803Smarcelstatic const char *
272130803Smarcelia64_register_name (int reg)
27398944Sobrien{
274130803Smarcel  return ia64_register_names[reg];
27598944Sobrien}
27698944Sobrien
27798944Sobrienstruct type *
278130803Smarcelia64_register_type (struct gdbarch *arch, int reg)
27998944Sobrien{
28098944Sobrien  if (reg >= IA64_FR0_REGNUM && reg <= IA64_FR127_REGNUM)
281130803Smarcel    return builtin_type_ia64_ext;
28298944Sobrien  else
28398944Sobrien    return builtin_type_long;
28498944Sobrien}
28598944Sobrien
286130803Smarcelstatic int
287130803Smarcelia64_dwarf_reg_to_regnum (int reg)
28898944Sobrien{
289130803Smarcel  if (reg >= IA64_GR32_REGNUM && reg <= IA64_GR127_REGNUM)
290130803Smarcel    return V32_REGNUM + (reg - IA64_GR32_REGNUM);
291130803Smarcel  return reg;
29298944Sobrien}
29398944Sobrien
294130803Smarcelstatic int
295130803Smarcelfloatformat_valid (const struct floatformat *fmt, const char *from)
296130803Smarcel{
297130803Smarcel  return 1;
298130803Smarcel}
29998944Sobrien
300130803Smarcelconst struct floatformat floatformat_ia64_ext =
30198944Sobrien{
302130803Smarcel  floatformat_little, 82, 0, 1, 17, 65535, 0x1ffff, 18, 64,
303130803Smarcel  floatformat_intbit_yes, "floatformat_ia64_ext", floatformat_valid
304130803Smarcel};
30598944Sobrien
30698944Sobrien
30798944Sobrien/* Extract ``len'' bits from an instruction bundle starting at
30898944Sobrien   bit ``from''.  */
30998944Sobrien
31098944Sobrienstatic long long
31198944Sobrienextract_bit_field (char *bundle, int from, int len)
31298944Sobrien{
31398944Sobrien  long long result = 0LL;
31498944Sobrien  int to = from + len;
31598944Sobrien  int from_byte = from / 8;
31698944Sobrien  int to_byte = to / 8;
31798944Sobrien  unsigned char *b = (unsigned char *) bundle;
31898944Sobrien  unsigned char c;
31998944Sobrien  int lshift;
32098944Sobrien  int i;
32198944Sobrien
32298944Sobrien  c = b[from_byte];
32398944Sobrien  if (from_byte == to_byte)
32498944Sobrien    c = ((unsigned char) (c << (8 - to % 8))) >> (8 - to % 8);
32598944Sobrien  result = c >> (from % 8);
32698944Sobrien  lshift = 8 - (from % 8);
32798944Sobrien
32898944Sobrien  for (i = from_byte+1; i < to_byte; i++)
32998944Sobrien    {
33098944Sobrien      result |= ((long long) b[i]) << lshift;
33198944Sobrien      lshift += 8;
33298944Sobrien    }
33398944Sobrien
33498944Sobrien  if (from_byte < to_byte && (to % 8 != 0))
33598944Sobrien    {
33698944Sobrien      c = b[to_byte];
33798944Sobrien      c = ((unsigned char) (c << (8 - to % 8))) >> (8 - to % 8);
33898944Sobrien      result |= ((long long) c) << lshift;
33998944Sobrien    }
34098944Sobrien
34198944Sobrien  return result;
34298944Sobrien}
34398944Sobrien
34498944Sobrien/* Replace the specified bits in an instruction bundle */
34598944Sobrien
34698944Sobrienstatic void
34798944Sobrienreplace_bit_field (char *bundle, long long val, int from, int len)
34898944Sobrien{
34998944Sobrien  int to = from + len;
35098944Sobrien  int from_byte = from / 8;
35198944Sobrien  int to_byte = to / 8;
35298944Sobrien  unsigned char *b = (unsigned char *) bundle;
35398944Sobrien  unsigned char c;
35498944Sobrien
35598944Sobrien  if (from_byte == to_byte)
35698944Sobrien    {
35798944Sobrien      unsigned char left, right;
35898944Sobrien      c = b[from_byte];
35998944Sobrien      left = (c >> (to % 8)) << (to % 8);
36098944Sobrien      right = ((unsigned char) (c << (8 - from % 8))) >> (8 - from % 8);
36198944Sobrien      c = (unsigned char) (val & 0xff);
36298944Sobrien      c = (unsigned char) (c << (from % 8 + 8 - to % 8)) >> (8 - to % 8);
36398944Sobrien      c |= right | left;
36498944Sobrien      b[from_byte] = c;
36598944Sobrien    }
36698944Sobrien  else
36798944Sobrien    {
36898944Sobrien      int i;
36998944Sobrien      c = b[from_byte];
37098944Sobrien      c = ((unsigned char) (c << (8 - from % 8))) >> (8 - from % 8);
37198944Sobrien      c = c | (val << (from % 8));
37298944Sobrien      b[from_byte] = c;
37398944Sobrien      val >>= 8 - from % 8;
37498944Sobrien
37598944Sobrien      for (i = from_byte+1; i < to_byte; i++)
37698944Sobrien	{
37798944Sobrien	  c = val & 0xff;
37898944Sobrien	  val >>= 8;
37998944Sobrien	  b[i] = c;
38098944Sobrien	}
38198944Sobrien
38298944Sobrien      if (to % 8 != 0)
38398944Sobrien	{
38498944Sobrien	  unsigned char cv = (unsigned char) val;
38598944Sobrien	  c = b[to_byte];
38698944Sobrien	  c = c >> (to % 8) << (to % 8);
38798944Sobrien	  c |= ((unsigned char) (cv << (8 - to % 8))) >> (8 - to % 8);
38898944Sobrien	  b[to_byte] = c;
38998944Sobrien	}
39098944Sobrien    }
39198944Sobrien}
39298944Sobrien
39398944Sobrien/* Return the contents of slot N (for N = 0, 1, or 2) in
39498944Sobrien   and instruction bundle */
39598944Sobrien
39698944Sobrienstatic long long
39798944SobrienslotN_contents (char *bundle, int slotnum)
39898944Sobrien{
39998944Sobrien  return extract_bit_field (bundle, 5+41*slotnum, 41);
40098944Sobrien}
40198944Sobrien
40298944Sobrien/* Store an instruction in an instruction bundle */
40398944Sobrien
40498944Sobrienstatic void
40598944Sobrienreplace_slotN_contents (char *bundle, long long instr, int slotnum)
40698944Sobrien{
40798944Sobrien  replace_bit_field (bundle, instr, 5+41*slotnum, 41);
40898944Sobrien}
40998944Sobrien
41098944Sobrienstatic enum instruction_type template_encoding_table[32][3] =
41198944Sobrien{
41298944Sobrien  { M, I, I },				/* 00 */
41398944Sobrien  { M, I, I },				/* 01 */
41498944Sobrien  { M, I, I },				/* 02 */
41598944Sobrien  { M, I, I },				/* 03 */
41698944Sobrien  { M, L, X },				/* 04 */
41798944Sobrien  { M, L, X },				/* 05 */
41898944Sobrien  { undefined, undefined, undefined },  /* 06 */
41998944Sobrien  { undefined, undefined, undefined },  /* 07 */
42098944Sobrien  { M, M, I },				/* 08 */
42198944Sobrien  { M, M, I },				/* 09 */
42298944Sobrien  { M, M, I },				/* 0A */
42398944Sobrien  { M, M, I },				/* 0B */
42498944Sobrien  { M, F, I },				/* 0C */
42598944Sobrien  { M, F, I },				/* 0D */
42698944Sobrien  { M, M, F },				/* 0E */
42798944Sobrien  { M, M, F },				/* 0F */
42898944Sobrien  { M, I, B },				/* 10 */
42998944Sobrien  { M, I, B },				/* 11 */
43098944Sobrien  { M, B, B },				/* 12 */
43198944Sobrien  { M, B, B },				/* 13 */
43298944Sobrien  { undefined, undefined, undefined },  /* 14 */
43398944Sobrien  { undefined, undefined, undefined },  /* 15 */
43498944Sobrien  { B, B, B },				/* 16 */
43598944Sobrien  { B, B, B },				/* 17 */
43698944Sobrien  { M, M, B },				/* 18 */
43798944Sobrien  { M, M, B },				/* 19 */
43898944Sobrien  { undefined, undefined, undefined },  /* 1A */
43998944Sobrien  { undefined, undefined, undefined },  /* 1B */
44098944Sobrien  { M, F, B },				/* 1C */
44198944Sobrien  { M, F, B },				/* 1D */
44298944Sobrien  { undefined, undefined, undefined },  /* 1E */
44398944Sobrien  { undefined, undefined, undefined },  /* 1F */
44498944Sobrien};
44598944Sobrien
44698944Sobrien/* Fetch and (partially) decode an instruction at ADDR and return the
44798944Sobrien   address of the next instruction to fetch.  */
44898944Sobrien
44998944Sobrienstatic CORE_ADDR
45098944Sobrienfetch_instruction (CORE_ADDR addr, instruction_type *it, long long *instr)
45198944Sobrien{
45298944Sobrien  char bundle[BUNDLE_LEN];
45398944Sobrien  int slotnum = (int) (addr & 0x0f) / SLOT_MULTIPLIER;
45498944Sobrien  long long template;
45598944Sobrien  int val;
45698944Sobrien
45798944Sobrien  /* Warn about slot numbers greater than 2.  We used to generate
45898944Sobrien     an error here on the assumption that the user entered an invalid
45998944Sobrien     address.  But, sometimes GDB itself requests an invalid address.
46098944Sobrien     This can (easily) happen when execution stops in a function for
46198944Sobrien     which there are no symbols.  The prologue scanner will attempt to
46298944Sobrien     find the beginning of the function - if the nearest symbol
46398944Sobrien     happens to not be aligned on a bundle boundary (16 bytes), the
46498944Sobrien     resulting starting address will cause GDB to think that the slot
46598944Sobrien     number is too large.
46698944Sobrien
46798944Sobrien     So we warn about it and set the slot number to zero.  It is
46898944Sobrien     not necessarily a fatal condition, particularly if debugging
46998944Sobrien     at the assembly language level.  */
47098944Sobrien  if (slotnum > 2)
47198944Sobrien    {
47298944Sobrien      warning ("Can't fetch instructions for slot numbers greater than 2.\n"
47398944Sobrien	       "Using slot 0 instead");
47498944Sobrien      slotnum = 0;
47598944Sobrien    }
47698944Sobrien
47798944Sobrien  addr &= ~0x0f;
47898944Sobrien
47998944Sobrien  val = target_read_memory (addr, bundle, BUNDLE_LEN);
48098944Sobrien
48198944Sobrien  if (val != 0)
48298944Sobrien    return 0;
48398944Sobrien
48498944Sobrien  *instr = slotN_contents (bundle, slotnum);
48598944Sobrien  template = extract_bit_field (bundle, 0, 5);
48698944Sobrien  *it = template_encoding_table[(int)template][slotnum];
48798944Sobrien
48898944Sobrien  if (slotnum == 2 || (slotnum == 1 && *it == L))
48998944Sobrien    addr += 16;
49098944Sobrien  else
49198944Sobrien    addr += (slotnum + 1) * SLOT_MULTIPLIER;
49298944Sobrien
49398944Sobrien  return addr;
49498944Sobrien}
49598944Sobrien
49698944Sobrien/* There are 5 different break instructions (break.i, break.b,
49798944Sobrien   break.m, break.f, and break.x), but they all have the same
49898944Sobrien   encoding.  (The five bit template in the low five bits of the
49998944Sobrien   instruction bundle distinguishes one from another.)
50098944Sobrien
50198944Sobrien   The runtime architecture manual specifies that break instructions
50298944Sobrien   used for debugging purposes must have the upper two bits of the 21
50398944Sobrien   bit immediate set to a 0 and a 1 respectively.  A breakpoint
50498944Sobrien   instruction encodes the most significant bit of its 21 bit
50598944Sobrien   immediate at bit 36 of the 41 bit instruction.  The penultimate msb
50698944Sobrien   is at bit 25 which leads to the pattern below.
50798944Sobrien
50898944Sobrien   Originally, I had this set up to do, e.g, a "break.i 0x80000"  But
50998944Sobrien   it turns out that 0x80000 was used as the syscall break in the early
51098944Sobrien   simulators.  So I changed the pattern slightly to do "break.i 0x080001"
51198944Sobrien   instead.  But that didn't work either (I later found out that this
51298944Sobrien   pattern was used by the simulator that I was using.)  So I ended up
51398944Sobrien   using the pattern seen below. */
51498944Sobrien
51598944Sobrien#if 0
516130803Smarcel#define IA64_BREAKPOINT 0x00002000040LL
51798944Sobrien#endif
518130803Smarcel#define IA64_BREAKPOINT 0x00003333300LL
51998944Sobrien
52098944Sobrienstatic int
52198944Sobrienia64_memory_insert_breakpoint (CORE_ADDR addr, char *contents_cache)
52298944Sobrien{
52398944Sobrien  char bundle[BUNDLE_LEN];
52498944Sobrien  int slotnum = (int) (addr & 0x0f) / SLOT_MULTIPLIER;
52598944Sobrien  long long instr;
52698944Sobrien  int val;
527130803Smarcel  int template;
52898944Sobrien
52998944Sobrien  if (slotnum > 2)
53098944Sobrien    error("Can't insert breakpoint for slot numbers greater than 2.");
53198944Sobrien
53298944Sobrien  addr &= ~0x0f;
53398944Sobrien
53498944Sobrien  val = target_read_memory (addr, bundle, BUNDLE_LEN);
535130803Smarcel
536130803Smarcel  /* Check for L type instruction in 2nd slot, if present then
537130803Smarcel     bump up the slot number to the 3rd slot */
538130803Smarcel  template = extract_bit_field (bundle, 0, 5);
539130803Smarcel  if (slotnum == 1 && template_encoding_table[template][1] == L)
540130803Smarcel    {
541130803Smarcel      slotnum = 2;
542130803Smarcel    }
543130803Smarcel
54498944Sobrien  instr = slotN_contents (bundle, slotnum);
54598944Sobrien  memcpy(contents_cache, &instr, sizeof(instr));
546130803Smarcel  replace_slotN_contents (bundle, IA64_BREAKPOINT, slotnum);
54798944Sobrien  if (val == 0)
54898944Sobrien    target_write_memory (addr, bundle, BUNDLE_LEN);
54998944Sobrien
55098944Sobrien  return val;
55198944Sobrien}
55298944Sobrien
55398944Sobrienstatic int
55498944Sobrienia64_memory_remove_breakpoint (CORE_ADDR addr, char *contents_cache)
55598944Sobrien{
55698944Sobrien  char bundle[BUNDLE_LEN];
55798944Sobrien  int slotnum = (addr & 0x0f) / SLOT_MULTIPLIER;
55898944Sobrien  long long instr;
55998944Sobrien  int val;
560130803Smarcel  int template;
56198944Sobrien
56298944Sobrien  addr &= ~0x0f;
56398944Sobrien
56498944Sobrien  val = target_read_memory (addr, bundle, BUNDLE_LEN);
565130803Smarcel
566130803Smarcel  /* Check for L type instruction in 2nd slot, if present then
567130803Smarcel     bump up the slot number to the 3rd slot */
568130803Smarcel  template = extract_bit_field (bundle, 0, 5);
569130803Smarcel  if (slotnum == 1 && template_encoding_table[template][1] == L)
570130803Smarcel    {
571130803Smarcel      slotnum = 2;
572130803Smarcel    }
573130803Smarcel
57498944Sobrien  memcpy (&instr, contents_cache, sizeof instr);
57598944Sobrien  replace_slotN_contents (bundle, instr, slotnum);
57698944Sobrien  if (val == 0)
57798944Sobrien    target_write_memory (addr, bundle, BUNDLE_LEN);
57898944Sobrien
57998944Sobrien  return val;
58098944Sobrien}
58198944Sobrien
58298944Sobrien/* We don't really want to use this, but remote.c needs to call it in order
58398944Sobrien   to figure out if Z-packets are supported or not.  Oh, well. */
584130803Smarcelconst unsigned char *
58598944Sobrienia64_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
58698944Sobrien{
58798944Sobrien  static unsigned char breakpoint[] =
58898944Sobrien    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
58998944Sobrien  *lenptr = sizeof (breakpoint);
59098944Sobrien#if 0
59198944Sobrien  *pcptr &= ~0x0f;
59298944Sobrien#endif
59398944Sobrien  return breakpoint;
59498944Sobrien}
59598944Sobrien
596130803Smarcelstatic CORE_ADDR
59798944Sobrienia64_read_pc (ptid_t ptid)
59898944Sobrien{
59998944Sobrien  CORE_ADDR psr_value = read_register_pid (IA64_PSR_REGNUM, ptid);
60098944Sobrien  CORE_ADDR pc_value   = read_register_pid (IA64_IP_REGNUM, ptid);
60198944Sobrien  int slot_num = (psr_value >> 41) & 3;
60298944Sobrien
60398944Sobrien  return pc_value | (slot_num * SLOT_MULTIPLIER);
60498944Sobrien}
60598944Sobrien
60698944Sobrienvoid
60798944Sobrienia64_write_pc (CORE_ADDR new_pc, ptid_t ptid)
60898944Sobrien{
60998944Sobrien  int slot_num = (int) (new_pc & 0xf) / SLOT_MULTIPLIER;
61098944Sobrien  CORE_ADDR psr_value = read_register_pid (IA64_PSR_REGNUM, ptid);
61198944Sobrien  psr_value &= ~(3LL << 41);
61298944Sobrien  psr_value |= (CORE_ADDR)(slot_num & 0x3) << 41;
61398944Sobrien
61498944Sobrien  new_pc &= ~0xfLL;
61598944Sobrien
61698944Sobrien  write_register_pid (IA64_PSR_REGNUM, psr_value, ptid);
61798944Sobrien  write_register_pid (IA64_IP_REGNUM, new_pc, ptid);
61898944Sobrien}
61998944Sobrien
62098944Sobrien#define IS_NaT_COLLECTION_ADDR(addr) ((((addr) >> 3) & 0x3f) == 0x3f)
62198944Sobrien
62298944Sobrien/* Returns the address of the slot that's NSLOTS slots away from
62398944Sobrien   the address ADDR. NSLOTS may be positive or negative. */
62498944Sobrienstatic CORE_ADDR
62598944Sobrienrse_address_add(CORE_ADDR addr, int nslots)
62698944Sobrien{
62798944Sobrien  CORE_ADDR new_addr;
62898944Sobrien  int mandatory_nat_slots = nslots / 63;
62998944Sobrien  int direction = nslots < 0 ? -1 : 1;
63098944Sobrien
63198944Sobrien  new_addr = addr + 8 * (nslots + mandatory_nat_slots);
63298944Sobrien
63398944Sobrien  if ((new_addr >> 9)  != ((addr + 8 * 64 * mandatory_nat_slots) >> 9))
63498944Sobrien    new_addr += 8 * direction;
63598944Sobrien
63698944Sobrien  if (IS_NaT_COLLECTION_ADDR(new_addr))
63798944Sobrien    new_addr += 8 * direction;
63898944Sobrien
63998944Sobrien  return new_addr;
64098944Sobrien}
64198944Sobrien
642130803Smarcelstatic void
643134800Smarcelia64_read_reg (CORE_ADDR addr, void *buf, int len)
644134800Smarcel{
645134800Smarcel  ULONGEST bspstore;
646134800Smarcel  regcache_cooked_read_unsigned (current_regcache, IA64_BSPSTORE_REGNUM,
647134800Smarcel				 &bspstore);
648134800Smarcel  if (addr >= bspstore)
649134800Smarcel    {
650134800Smarcel      ULONGEST bsp;
651134800Smarcel      regcache_cooked_read_unsigned (current_regcache, IA64_BSP_REGNUM,
652134800Smarcel				     &bsp);
653134800Smarcel      if (addr < bsp)
654134800Smarcel	{
655134800Smarcel	  target_read_partial (&current_target, TARGET_OBJECT_DIRTY,
656134800Smarcel			       (void*)&bspstore, buf, addr - bspstore, len);
657134800Smarcel	  return;
658134800Smarcel	}
659134800Smarcel    }
660134800Smarcel  read_memory (addr, buf, len);
661134800Smarcel}
662134800Smarcel
663134800Smarcelstatic void
664134800Smarcelia64_write_reg (CORE_ADDR addr, void *buf, int len)
665134800Smarcel{
666134800Smarcel  ULONGEST bspstore;
667134800Smarcel  regcache_cooked_read_unsigned (current_regcache, IA64_BSPSTORE_REGNUM,
668134800Smarcel				 &bspstore);
669134800Smarcel  if (addr >= bspstore)
670134800Smarcel    {
671134800Smarcel      ULONGEST bsp;
672134800Smarcel      regcache_cooked_read_unsigned (current_regcache, IA64_BSP_REGNUM,
673134800Smarcel				     &bsp);
674134800Smarcel      if (addr < bsp)
675134800Smarcel	{
676134800Smarcel	  target_write_partial (&current_target, TARGET_OBJECT_DIRTY,
677134800Smarcel				(void*)&bspstore, buf, addr - bspstore, len);
678134800Smarcel	  return;
679134800Smarcel	}
680134800Smarcel    }
681134800Smarcel  write_memory (addr, buf, len);
682134800Smarcel}
683134800Smarcel
684134800Smarcelstatic void
685130803Smarcelia64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
686130803Smarcel                           int regnum, void *buf)
687130803Smarcel{
688130803Smarcel  if (regnum >= V32_REGNUM && regnum <= V127_REGNUM)
689130803Smarcel    {
690130803Smarcel      ULONGEST bsp;
691130803Smarcel      ULONGEST cfm;
692130803Smarcel      CORE_ADDR reg;
693130803Smarcel      regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp);
694130803Smarcel      regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
69598944Sobrien
696130803Smarcel      /* The bsp points at the end of the register frame so we
697130803Smarcel	 subtract the size of frame from it to get start of register frame.  */
698130803Smarcel      bsp = rse_address_add (bsp, -(cfm & 0x7f));
699130803Smarcel
700134800Smarcel      if ((cfm & 0x7f) > regnum - V32_REGNUM)
701130803Smarcel	{
702134800Smarcel	  ULONGEST addr = rse_address_add (bsp, (regnum - V32_REGNUM));
703134800Smarcel	  ia64_read_reg (addr, buf, register_size (current_gdbarch, regnum));
704130803Smarcel	}
705130803Smarcel      else
706130803Smarcel	store_unsigned_integer (buf, register_size (current_gdbarch, regnum), 0);
707130803Smarcel    }
708130803Smarcel  else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT31_REGNUM)
709130803Smarcel    {
710130803Smarcel      ULONGEST unatN_val;
711130803Smarcel      ULONGEST unat;
712130803Smarcel      regcache_cooked_read_unsigned (regcache, IA64_UNAT_REGNUM, &unat);
713130803Smarcel      unatN_val = (unat & (1LL << (regnum - IA64_NAT0_REGNUM))) != 0;
714130803Smarcel      store_unsigned_integer (buf, register_size (current_gdbarch, regnum), unatN_val);
715130803Smarcel    }
716130803Smarcel  else if (IA64_NAT32_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM)
717130803Smarcel    {
718130803Smarcel      ULONGEST natN_val = 0;
719130803Smarcel      ULONGEST bsp;
720130803Smarcel      ULONGEST cfm;
721130803Smarcel      CORE_ADDR gr_addr = 0;
722130803Smarcel      regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp);
723130803Smarcel      regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
72498944Sobrien
725130803Smarcel      /* The bsp points at the end of the register frame so we
726130803Smarcel	 subtract the size of frame from it to get start of register frame.  */
727130803Smarcel      bsp = rse_address_add (bsp, -(cfm & 0x7f));
728130803Smarcel
729130803Smarcel      if ((cfm & 0x7f) > regnum - V32_REGNUM)
730130803Smarcel	gr_addr = rse_address_add (bsp, (regnum - V32_REGNUM));
731130803Smarcel
732130803Smarcel      if (gr_addr != 0)
733130803Smarcel	{
734130803Smarcel	  /* Compute address of nat collection bits.  */
735130803Smarcel	  CORE_ADDR nat_addr = gr_addr | 0x1f8;
736130803Smarcel	  CORE_ADDR nat_collection;
737130803Smarcel	  int nat_bit;
738130803Smarcel	  /* If our nat collection address is bigger than bsp, we have to get
739130803Smarcel	     the nat collection from rnat.  Otherwise, we fetch the nat
740130803Smarcel	     collection from the computed address.  */
741130803Smarcel	  if (nat_addr >= bsp)
742130803Smarcel	    regcache_cooked_read_unsigned (regcache, IA64_RNAT_REGNUM, &nat_collection);
743130803Smarcel	  else
744131082Smarcel	    {
745134800Smarcel	      uint64_t tmp;
746134800Smarcel	      ia64_read_reg (nat_addr, &tmp, sizeof(tmp));
747134800Smarcel	      nat_collection = tmp;
748131082Smarcel	    }
749130803Smarcel	  nat_bit = (gr_addr >> 3) & 0x3f;
750130803Smarcel	  natN_val = (nat_collection >> nat_bit) & 1;
751130803Smarcel	}
752130803Smarcel
753130803Smarcel      store_unsigned_integer (buf, register_size (current_gdbarch, regnum), natN_val);
754130803Smarcel    }
755130803Smarcel  else if (regnum == VBOF_REGNUM)
756130803Smarcel    {
757130803Smarcel      /* A virtual register frame start is provided for user convenience.
758130803Smarcel         It can be calculated as the bsp - sof (sizeof frame). */
759130803Smarcel      ULONGEST bsp, vbsp;
760130803Smarcel      ULONGEST cfm;
761130803Smarcel      CORE_ADDR reg;
762130803Smarcel      regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp);
763130803Smarcel      regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
76498944Sobrien
765130803Smarcel      /* The bsp points at the end of the register frame so we
766130803Smarcel	 subtract the size of frame from it to get beginning of frame.  */
767130803Smarcel      vbsp = rse_address_add (bsp, -(cfm & 0x7f));
768130803Smarcel      store_unsigned_integer (buf, register_size (current_gdbarch, regnum), vbsp);
769130803Smarcel    }
770130803Smarcel  else if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM)
77198944Sobrien    {
772130803Smarcel      ULONGEST pr;
773130803Smarcel      ULONGEST cfm;
774130803Smarcel      ULONGEST prN_val;
775130803Smarcel      CORE_ADDR reg;
776130803Smarcel      regcache_cooked_read_unsigned (regcache, IA64_PR_REGNUM, &pr);
777130803Smarcel      regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
778130803Smarcel
779130803Smarcel      if (VP16_REGNUM <= regnum && regnum <= VP63_REGNUM)
780130803Smarcel	{
781130803Smarcel	  /* Fetch predicate register rename base from current frame
782130803Smarcel	     marker for this frame. */
783130803Smarcel	  int rrb_pr = (cfm >> 32) & 0x3f;
784130803Smarcel
785130803Smarcel	  /* Adjust the register number to account for register rotation. */
786130803Smarcel	  regnum = VP16_REGNUM
787130803Smarcel	         + ((regnum - VP16_REGNUM) + rrb_pr) % 48;
788130803Smarcel	}
789130803Smarcel      prN_val = (pr & (1LL << (regnum - VP0_REGNUM))) != 0;
790130803Smarcel      store_unsigned_integer (buf, register_size (current_gdbarch, regnum), prN_val);
79198944Sobrien    }
792130803Smarcel  else
793130803Smarcel    memset (buf, 0, register_size (current_gdbarch, regnum));
79498944Sobrien}
79598944Sobrien
796130803Smarcelstatic void
797130803Smarcelia64_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
798130803Smarcel			    int regnum, const void *buf)
79998944Sobrien{
800130803Smarcel  if (regnum >= V32_REGNUM && regnum <= V127_REGNUM)
80198944Sobrien    {
802130803Smarcel      ULONGEST bsp;
803130803Smarcel      ULONGEST cfm;
804130803Smarcel      CORE_ADDR reg;
805130803Smarcel      regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp);
806130803Smarcel      regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
80798944Sobrien
808130803Smarcel      bsp = rse_address_add (bsp, -(cfm & 0x7f));
809130803Smarcel
810130803Smarcel      if ((cfm & 0x7f) > regnum - V32_REGNUM)
811130803Smarcel	{
812134800Smarcel	  ULONGEST addr = rse_address_add (bsp, (regnum - V32_REGNUM));
813134800Smarcel	  ia64_write_reg (addr, (void *)buf, 8);
814130803Smarcel	}
81598944Sobrien    }
816130803Smarcel  else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT31_REGNUM)
817130803Smarcel    {
818130803Smarcel      ULONGEST unatN_val, unat, unatN_mask;
819130803Smarcel      regcache_cooked_read_unsigned (regcache, IA64_UNAT_REGNUM, &unat);
820130803Smarcel      unatN_val = extract_unsigned_integer (buf, register_size (current_gdbarch, regnum));
821130803Smarcel      unatN_mask = (1LL << (regnum - IA64_NAT0_REGNUM));
822130803Smarcel      if (unatN_val == 0)
823130803Smarcel	unat &= ~unatN_mask;
824130803Smarcel      else if (unatN_val == 1)
825130803Smarcel	unat |= unatN_mask;
826130803Smarcel      regcache_cooked_write_unsigned (regcache, IA64_UNAT_REGNUM, unat);
827130803Smarcel    }
828130803Smarcel  else if (IA64_NAT32_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM)
829130803Smarcel    {
830130803Smarcel      ULONGEST natN_val;
831130803Smarcel      ULONGEST bsp;
832130803Smarcel      ULONGEST cfm;
833130803Smarcel      CORE_ADDR gr_addr = 0;
834130803Smarcel      regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp);
835130803Smarcel      regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
836130803Smarcel
837130803Smarcel      /* The bsp points at the end of the register frame so we
838130803Smarcel	 subtract the size of frame from it to get start of register frame.  */
839130803Smarcel      bsp = rse_address_add (bsp, -(cfm & 0x7f));
840130803Smarcel
841130803Smarcel      if ((cfm & 0x7f) > regnum - V32_REGNUM)
842130803Smarcel	gr_addr = rse_address_add (bsp, (regnum - V32_REGNUM));
843130803Smarcel
844130803Smarcel      natN_val = extract_unsigned_integer (buf, register_size (current_gdbarch, regnum));
845130803Smarcel
846130803Smarcel      if (gr_addr != 0 && (natN_val == 0 || natN_val == 1))
847130803Smarcel	{
848130803Smarcel	  /* Compute address of nat collection bits.  */
849130803Smarcel	  CORE_ADDR nat_addr = gr_addr | 0x1f8;
850130803Smarcel	  CORE_ADDR nat_collection;
851130803Smarcel	  int natN_bit = (gr_addr >> 3) & 0x3f;
852130803Smarcel	  ULONGEST natN_mask = (1LL << natN_bit);
853130803Smarcel	  /* If our nat collection address is bigger than bsp, we have to get
854130803Smarcel	     the nat collection from rnat.  Otherwise, we fetch the nat
855130803Smarcel	     collection from the computed address.  */
856130803Smarcel	  if (nat_addr >= bsp)
857130803Smarcel	    {
858130803Smarcel	      regcache_cooked_read_unsigned (regcache, IA64_RNAT_REGNUM, &nat_collection);
859130803Smarcel	      if (natN_val)
860130803Smarcel		nat_collection |= natN_mask;
861130803Smarcel	      else
862130803Smarcel		nat_collection &= ~natN_mask;
863130803Smarcel	      regcache_cooked_write_unsigned (regcache, IA64_RNAT_REGNUM, nat_collection);
864130803Smarcel	    }
865130803Smarcel	  else
866130803Smarcel	    {
867134800Smarcel	      uint64_t tmp;
868134800Smarcel	      ia64_read_reg (nat_addr, &tmp, sizeof(tmp));
869134800Smarcel	      nat_collection = tmp;
870130803Smarcel	      if (natN_val)
871130803Smarcel		nat_collection |= natN_mask;
872130803Smarcel	      else
873130803Smarcel		nat_collection &= ~natN_mask;
874134800Smarcel	      tmp = nat_collection;
875134800Smarcel	      ia64_write_reg (nat_addr, &tmp, sizeof(tmp));
876130803Smarcel	    }
877130803Smarcel	}
878130803Smarcel    }
879130803Smarcel  else if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM)
880130803Smarcel    {
881130803Smarcel      ULONGEST pr;
882130803Smarcel      ULONGEST cfm;
883130803Smarcel      ULONGEST prN_val;
884130803Smarcel      ULONGEST prN_mask;
885130803Smarcel
886130803Smarcel      regcache_cooked_read_unsigned (regcache, IA64_PR_REGNUM, &pr);
887130803Smarcel      regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
888130803Smarcel
889130803Smarcel      if (VP16_REGNUM <= regnum && regnum <= VP63_REGNUM)
890130803Smarcel	{
891130803Smarcel	  /* Fetch predicate register rename base from current frame
892130803Smarcel	     marker for this frame. */
893130803Smarcel	  int rrb_pr = (cfm >> 32) & 0x3f;
894130803Smarcel
895130803Smarcel	  /* Adjust the register number to account for register rotation. */
896130803Smarcel	  regnum = VP16_REGNUM
897130803Smarcel	         + ((regnum - VP16_REGNUM) + rrb_pr) % 48;
898130803Smarcel	}
899130803Smarcel      prN_val = extract_unsigned_integer (buf, register_size (current_gdbarch, regnum));
900130803Smarcel      prN_mask = (1LL << (regnum - VP0_REGNUM));
901130803Smarcel      if (prN_val == 0)
902130803Smarcel	pr &= ~prN_mask;
903130803Smarcel      else if (prN_val == 1)
904130803Smarcel	pr |= prN_mask;
905130803Smarcel      regcache_cooked_write_unsigned (regcache, IA64_PR_REGNUM, pr);
906130803Smarcel    }
90798944Sobrien}
90898944Sobrien
909130803Smarcel/* The ia64 needs to convert between various ieee floating-point formats
910130803Smarcel   and the special ia64 floating point register format.  */
911130803Smarcel
912130803Smarcelstatic int
913130803Smarcelia64_convert_register_p (int regno, struct type *type)
914130803Smarcel{
915130803Smarcel  return (regno >= IA64_FR0_REGNUM && regno <= IA64_FR127_REGNUM);
916130803Smarcel}
917130803Smarcel
918130803Smarcelstatic void
919130803Smarcelia64_register_to_value (struct frame_info *frame, int regnum,
920130803Smarcel                         struct type *valtype, void *out)
921130803Smarcel{
922130803Smarcel  char in[MAX_REGISTER_SIZE];
923130803Smarcel  frame_register_read (frame, regnum, in);
924130803Smarcel  convert_typed_floating (in, builtin_type_ia64_ext, out, valtype);
925130803Smarcel}
926130803Smarcel
927130803Smarcelstatic void
928130803Smarcelia64_value_to_register (struct frame_info *frame, int regnum,
929130803Smarcel                         struct type *valtype, const void *in)
930130803Smarcel{
931130803Smarcel  char out[MAX_REGISTER_SIZE];
932130803Smarcel  convert_typed_floating (in, valtype, out, builtin_type_ia64_ext);
933130803Smarcel  put_frame_register (frame, regnum, out);
934130803Smarcel}
935130803Smarcel
936130803Smarcel
93798944Sobrien/* Limit the number of skipped non-prologue instructions since examining
93898944Sobrien   of the prologue is expensive.  */
939130803Smarcelstatic int max_skip_non_prologue_insns = 40;
94098944Sobrien
94198944Sobrien/* Given PC representing the starting address of a function, and
94298944Sobrien   LIM_PC which is the (sloppy) limit to which to scan when looking
94398944Sobrien   for a prologue, attempt to further refine this limit by using
94498944Sobrien   the line data in the symbol table.  If successful, a better guess
94598944Sobrien   on where the prologue ends is returned, otherwise the previous
94698944Sobrien   value of lim_pc is returned.  TRUST_LIMIT is a pointer to a flag
94798944Sobrien   which will be set to indicate whether the returned limit may be
94898944Sobrien   used with no further scanning in the event that the function is
94998944Sobrien   frameless.  */
95098944Sobrien
951130803Smarcel/* FIXME: cagney/2004-02-14: This function and logic have largely been
952130803Smarcel   superseded by skip_prologue_using_sal.  */
953130803Smarcel
95498944Sobrienstatic CORE_ADDR
95598944Sobrienrefine_prologue_limit (CORE_ADDR pc, CORE_ADDR lim_pc, int *trust_limit)
95698944Sobrien{
95798944Sobrien  struct symtab_and_line prologue_sal;
95898944Sobrien  CORE_ADDR start_pc = pc;
95998944Sobrien
96098944Sobrien  /* Start off not trusting the limit.  */
96198944Sobrien  *trust_limit = 0;
96298944Sobrien
96398944Sobrien  prologue_sal = find_pc_line (pc, 0);
96498944Sobrien  if (prologue_sal.line != 0)
96598944Sobrien    {
96698944Sobrien      int i;
96798944Sobrien      CORE_ADDR addr = prologue_sal.end;
96898944Sobrien
96998944Sobrien      /* Handle the case in which compiler's optimizer/scheduler
97098944Sobrien         has moved instructions into the prologue.  We scan ahead
97198944Sobrien	 in the function looking for address ranges whose corresponding
97298944Sobrien	 line number is less than or equal to the first one that we
97398944Sobrien	 found for the function.  (It can be less than when the
97498944Sobrien	 scheduler puts a body instruction before the first prologue
97598944Sobrien	 instruction.)  */
97698944Sobrien      for (i = 2 * max_skip_non_prologue_insns;
97798944Sobrien           i > 0 && (lim_pc == 0 || addr < lim_pc);
97898944Sobrien	   i--)
97998944Sobrien        {
98098944Sobrien	  struct symtab_and_line sal;
98198944Sobrien
98298944Sobrien	  sal = find_pc_line (addr, 0);
98398944Sobrien	  if (sal.line == 0)
98498944Sobrien	    break;
98598944Sobrien	  if (sal.line <= prologue_sal.line
98698944Sobrien	      && sal.symtab == prologue_sal.symtab)
98798944Sobrien	    {
98898944Sobrien	      prologue_sal = sal;
98998944Sobrien	    }
99098944Sobrien	  addr = sal.end;
99198944Sobrien	}
99298944Sobrien
99398944Sobrien      if (lim_pc == 0 || prologue_sal.end < lim_pc)
99498944Sobrien	{
99598944Sobrien	  lim_pc = prologue_sal.end;
99698944Sobrien	  if (start_pc == get_pc_function_start (lim_pc))
99798944Sobrien	    *trust_limit = 1;
99898944Sobrien	}
99998944Sobrien    }
100098944Sobrien  return lim_pc;
100198944Sobrien}
100298944Sobrien
100398944Sobrien#define isScratch(_regnum_) ((_regnum_) == 2 || (_regnum_) == 3 \
100498944Sobrien  || (8 <= (_regnum_) && (_regnum_) <= 11) \
100598944Sobrien  || (14 <= (_regnum_) && (_regnum_) <= 31))
100698944Sobrien#define imm9(_instr_) \
100798944Sobrien  ( ((((_instr_) & 0x01000000000LL) ? -1 : 0) << 8) \
100898944Sobrien   | (((_instr_) & 0x00008000000LL) >> 20) \
100998944Sobrien   | (((_instr_) & 0x00000001fc0LL) >> 6))
101098944Sobrien
1011130803Smarcel/* Allocate and initialize a frame cache.  */
1012130803Smarcel
1013130803Smarcelstatic struct ia64_frame_cache *
1014130803Smarcelia64_alloc_frame_cache (void)
1015130803Smarcel{
1016130803Smarcel  struct ia64_frame_cache *cache;
1017130803Smarcel  int i;
1018130803Smarcel
1019130803Smarcel  cache = FRAME_OBSTACK_ZALLOC (struct ia64_frame_cache);
1020130803Smarcel
1021130803Smarcel  /* Base address.  */
1022130803Smarcel  cache->base = 0;
1023130803Smarcel  cache->pc = 0;
1024130803Smarcel  cache->cfm = 0;
1025130803Smarcel  cache->prev_cfm = 0;
1026130803Smarcel  cache->sof = 0;
1027130803Smarcel  cache->sol = 0;
1028130803Smarcel  cache->sor = 0;
1029130803Smarcel  cache->bsp = 0;
1030130803Smarcel  cache->fp_reg = 0;
1031130803Smarcel  cache->frameless = 1;
1032130803Smarcel
1033130803Smarcel  for (i = 0; i < NUM_IA64_RAW_REGS; i++)
1034130803Smarcel    cache->saved_regs[i] = 0;
1035130803Smarcel
1036130803Smarcel  return cache;
1037130803Smarcel}
1038130803Smarcel
103998944Sobrienstatic CORE_ADDR
1040130803Smarcelexamine_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct frame_info *next_frame, struct ia64_frame_cache *cache)
104198944Sobrien{
104298944Sobrien  CORE_ADDR next_pc;
104398944Sobrien  CORE_ADDR last_prologue_pc = pc;
104498944Sobrien  instruction_type it;
104598944Sobrien  long long instr;
104698944Sobrien  int cfm_reg  = 0;
104798944Sobrien  int ret_reg  = 0;
104898944Sobrien  int fp_reg   = 0;
104998944Sobrien  int unat_save_reg = 0;
105098944Sobrien  int pr_save_reg = 0;
105198944Sobrien  int mem_stack_frame_size = 0;
105298944Sobrien  int spill_reg   = 0;
105398944Sobrien  CORE_ADDR spill_addr = 0;
105498944Sobrien  char instores[8];
105598944Sobrien  char infpstores[8];
1056130803Smarcel  char reg_contents[256];
105798944Sobrien  int trust_limit;
1058130803Smarcel  int frameless = 1;
1059130803Smarcel  int i;
1060130803Smarcel  CORE_ADDR addr;
1061130803Smarcel  char buf[8];
1062130803Smarcel  CORE_ADDR bof, sor, sol, sof, cfm, rrb_gr;
106398944Sobrien
106498944Sobrien  memset (instores, 0, sizeof instores);
106598944Sobrien  memset (infpstores, 0, sizeof infpstores);
1066130803Smarcel  memset (reg_contents, 0, sizeof reg_contents);
106798944Sobrien
1068130803Smarcel  if (cache->after_prologue != 0
1069130803Smarcel      && cache->after_prologue <= lim_pc)
1070130803Smarcel    return cache->after_prologue;
107198944Sobrien
107298944Sobrien  lim_pc = refine_prologue_limit (pc, lim_pc, &trust_limit);
1073130803Smarcel  next_pc = fetch_instruction (pc, &it, &instr);
107498944Sobrien
1075130803Smarcel  /* We want to check if we have a recognizable function start before we
1076130803Smarcel     look ahead for a prologue.  */
107798944Sobrien  if (pc < lim_pc && next_pc
107898944Sobrien      && it == M && ((instr & 0x1ee0000003fLL) == 0x02c00000000LL))
107998944Sobrien    {
1080130803Smarcel      /* alloc - start of a regular function.  */
108198944Sobrien      int sor = (int) ((instr & 0x00078000000LL) >> 27);
108298944Sobrien      int sol = (int) ((instr & 0x00007f00000LL) >> 20);
108398944Sobrien      int sof = (int) ((instr & 0x000000fe000LL) >> 13);
108498944Sobrien      int rN = (int) ((instr & 0x00000001fc0LL) >> 6);
1085130803Smarcel
1086130803Smarcel      /* Verify that the current cfm matches what we think is the
1087130803Smarcel	 function start.  If we have somehow jumped within a function,
1088130803Smarcel	 we do not want to interpret the prologue and calculate the
1089130803Smarcel	 addresses of various registers such as the return address.
1090130803Smarcel	 We will instead treat the frame as frameless. */
1091130803Smarcel      if (!next_frame ||
1092130803Smarcel	  (sof == (cache->cfm & 0x7f) &&
1093130803Smarcel	   sol == ((cache->cfm >> 7) & 0x7f)))
1094130803Smarcel	frameless = 0;
1095130803Smarcel
109698944Sobrien      cfm_reg = rN;
109798944Sobrien      last_prologue_pc = next_pc;
109898944Sobrien      pc = next_pc;
109998944Sobrien    }
110098944Sobrien  else
110198944Sobrien    {
1102130803Smarcel      /* Look for a leaf routine.  */
1103130803Smarcel      if (pc < lim_pc && next_pc
1104130803Smarcel	  && (it == I || it == M)
1105130803Smarcel          && ((instr & 0x1ee00000000LL) == 0x10800000000LL))
1106130803Smarcel	{
1107130803Smarcel	  /* adds rN = imm14, rM   (or mov rN, rM  when imm14 is 0) */
1108130803Smarcel	  int imm = (int) ((((instr & 0x01000000000LL) ? -1 : 0) << 13)
1109130803Smarcel	                   | ((instr & 0x001f8000000LL) >> 20)
1110130803Smarcel		           | ((instr & 0x000000fe000LL) >> 13));
1111130803Smarcel	  int rM = (int) ((instr & 0x00007f00000LL) >> 20);
1112130803Smarcel	  int rN = (int) ((instr & 0x00000001fc0LL) >> 6);
1113130803Smarcel	  int qp = (int) (instr & 0x0000000003fLL);
1114130803Smarcel	  if (qp == 0 && rN == 2 && imm == 0 && rM == 12 && fp_reg == 0)
1115130803Smarcel	    {
1116130803Smarcel	      /* mov r2, r12 - beginning of leaf routine */
1117130803Smarcel	      fp_reg = rN;
1118130803Smarcel	      last_prologue_pc = next_pc;
1119130803Smarcel	    }
1120130803Smarcel	}
1121130803Smarcel
1122130803Smarcel      /* If we don't recognize a regular function or leaf routine, we are
1123130803Smarcel	 done.  */
1124130803Smarcel      if (!fp_reg)
1125130803Smarcel	{
1126130803Smarcel	  pc = lim_pc;
1127130803Smarcel	  if (trust_limit)
1128130803Smarcel	    last_prologue_pc = lim_pc;
1129130803Smarcel	}
113098944Sobrien    }
113198944Sobrien
113298944Sobrien  /* Loop, looking for prologue instructions, keeping track of
113398944Sobrien     where preserved registers were spilled. */
113498944Sobrien  while (pc < lim_pc)
113598944Sobrien    {
113698944Sobrien      next_pc = fetch_instruction (pc, &it, &instr);
113798944Sobrien      if (next_pc == 0)
113898944Sobrien	break;
113998944Sobrien
1140130803Smarcel      if (it == B && ((instr & 0x1e1f800003f) != 0x04000000000))
114198944Sobrien	{
1142130803Smarcel	  /* Exit loop upon hitting a non-nop branch instruction. */
1143130803Smarcel	  if (trust_limit)
1144130803Smarcel	    lim_pc = pc;
114598944Sobrien	  break;
114698944Sobrien	}
1147130803Smarcel      else if (((instr & 0x3fLL) != 0LL) &&
1148130803Smarcel	       (frameless || ret_reg != 0))
1149130803Smarcel	{
1150130803Smarcel	  /* Exit loop upon hitting a predicated instruction if
1151130803Smarcel	     we already have the return register or if we are frameless.  */
1152130803Smarcel	  if (trust_limit)
1153130803Smarcel	    lim_pc = pc;
1154130803Smarcel	  break;
1155130803Smarcel	}
115698944Sobrien      else if (it == I && ((instr & 0x1eff8000000LL) == 0x00188000000LL))
115798944Sobrien        {
115898944Sobrien	  /* Move from BR */
115998944Sobrien	  int b2 = (int) ((instr & 0x0000000e000LL) >> 13);
116098944Sobrien	  int rN = (int) ((instr & 0x00000001fc0LL) >> 6);
116198944Sobrien	  int qp = (int) (instr & 0x0000000003f);
116298944Sobrien
116398944Sobrien	  if (qp == 0 && b2 == 0 && rN >= 32 && ret_reg == 0)
116498944Sobrien	    {
116598944Sobrien	      ret_reg = rN;
116698944Sobrien	      last_prologue_pc = next_pc;
116798944Sobrien	    }
116898944Sobrien	}
116998944Sobrien      else if ((it == I || it == M)
117098944Sobrien          && ((instr & 0x1ee00000000LL) == 0x10800000000LL))
117198944Sobrien	{
117298944Sobrien	  /* adds rN = imm14, rM   (or mov rN, rM  when imm14 is 0) */
117398944Sobrien	  int imm = (int) ((((instr & 0x01000000000LL) ? -1 : 0) << 13)
117498944Sobrien	                   | ((instr & 0x001f8000000LL) >> 20)
117598944Sobrien		           | ((instr & 0x000000fe000LL) >> 13));
117698944Sobrien	  int rM = (int) ((instr & 0x00007f00000LL) >> 20);
117798944Sobrien	  int rN = (int) ((instr & 0x00000001fc0LL) >> 6);
117898944Sobrien	  int qp = (int) (instr & 0x0000000003fLL);
117998944Sobrien
118098944Sobrien	  if (qp == 0 && rN >= 32 && imm == 0 && rM == 12 && fp_reg == 0)
118198944Sobrien	    {
118298944Sobrien	      /* mov rN, r12 */
118398944Sobrien	      fp_reg = rN;
118498944Sobrien	      last_prologue_pc = next_pc;
118598944Sobrien	    }
118698944Sobrien	  else if (qp == 0 && rN == 12 && rM == 12)
118798944Sobrien	    {
118898944Sobrien	      /* adds r12, -mem_stack_frame_size, r12 */
118998944Sobrien	      mem_stack_frame_size -= imm;
119098944Sobrien	      last_prologue_pc = next_pc;
119198944Sobrien	    }
119298944Sobrien	  else if (qp == 0 && rN == 2
119398944Sobrien	        && ((rM == fp_reg && fp_reg != 0) || rM == 12))
119498944Sobrien	    {
1195130803Smarcel	      char buf[MAX_REGISTER_SIZE];
1196130803Smarcel	      CORE_ADDR saved_sp = 0;
119798944Sobrien	      /* adds r2, spilloffset, rFramePointer
119898944Sobrien	           or
119998944Sobrien		 adds r2, spilloffset, r12
120098944Sobrien
120198944Sobrien	         Get ready for stf.spill or st8.spill instructions.
120298944Sobrien		 The address to start spilling at is loaded into r2.
120398944Sobrien		 FIXME:  Why r2?  That's what gcc currently uses; it
120498944Sobrien		 could well be different for other compilers.  */
120598944Sobrien
120698944Sobrien	      /* Hmm... whether or not this will work will depend on
120798944Sobrien	         where the pc is.  If it's still early in the prologue
120898944Sobrien		 this'll be wrong.  FIXME */
1209130803Smarcel	      if (next_frame)
1210130803Smarcel		{
1211130803Smarcel		  frame_unwind_register (next_frame, sp_regnum, buf);
1212130803Smarcel		  saved_sp = extract_unsigned_integer (buf, 8);
1213130803Smarcel		}
1214130803Smarcel	      spill_addr  = saved_sp
121598944Sobrien	                  + (rM == 12 ? 0 : mem_stack_frame_size)
121698944Sobrien			  + imm;
121798944Sobrien	      spill_reg   = rN;
121898944Sobrien	      last_prologue_pc = next_pc;
121998944Sobrien	    }
1220130803Smarcel	  else if (qp == 0 && rM >= 32 && rM < 40 && !instores[rM] &&
1221130803Smarcel		   rN < 256 && imm == 0)
1222130803Smarcel	    {
1223130803Smarcel	      /* mov rN, rM where rM is an input register */
1224130803Smarcel	      reg_contents[rN] = rM;
1225130803Smarcel	      last_prologue_pc = next_pc;
1226130803Smarcel	    }
1227130803Smarcel	  else if (frameless && qp == 0 && rN == fp_reg && imm == 0 &&
1228130803Smarcel		   rM == 2)
1229130803Smarcel	    {
1230130803Smarcel	      /* mov r12, r2 */
1231130803Smarcel	      last_prologue_pc = next_pc;
1232130803Smarcel	      break;
1233130803Smarcel	    }
123498944Sobrien	}
123598944Sobrien      else if (it == M
123698944Sobrien            && (   ((instr & 0x1efc0000000LL) == 0x0eec0000000LL)
123798944Sobrien                || ((instr & 0x1ffc8000000LL) == 0x0cec0000000LL) ))
123898944Sobrien	{
123998944Sobrien	  /* stf.spill [rN] = fM, imm9
124098944Sobrien	     or
124198944Sobrien	     stf.spill [rN] = fM  */
124298944Sobrien
124398944Sobrien	  int imm = imm9(instr);
124498944Sobrien	  int rN = (int) ((instr & 0x00007f00000LL) >> 20);
124598944Sobrien	  int fM = (int) ((instr & 0x000000fe000LL) >> 13);
124698944Sobrien	  int qp = (int) (instr & 0x0000000003fLL);
124798944Sobrien	  if (qp == 0 && rN == spill_reg && spill_addr != 0
124898944Sobrien	      && ((2 <= fM && fM <= 5) || (16 <= fM && fM <= 31)))
124998944Sobrien	    {
1250130803Smarcel	      cache->saved_regs[IA64_FR0_REGNUM + fM] = spill_addr;
125198944Sobrien
125298944Sobrien              if ((instr & 0x1efc0000000) == 0x0eec0000000)
125398944Sobrien		spill_addr += imm;
125498944Sobrien	      else
125598944Sobrien		spill_addr = 0;		/* last one; must be done */
125698944Sobrien	      last_prologue_pc = next_pc;
125798944Sobrien	    }
125898944Sobrien	}
125998944Sobrien      else if ((it == M && ((instr & 0x1eff8000000LL) == 0x02110000000LL))
126098944Sobrien            || (it == I && ((instr & 0x1eff8000000LL) == 0x00050000000LL)) )
126198944Sobrien	{
126298944Sobrien	  /* mov.m rN = arM
126398944Sobrien	       or
126498944Sobrien	     mov.i rN = arM */
126598944Sobrien
126698944Sobrien	  int arM = (int) ((instr & 0x00007f00000LL) >> 20);
126798944Sobrien	  int rN  = (int) ((instr & 0x00000001fc0LL) >> 6);
126898944Sobrien	  int qp  = (int) (instr & 0x0000000003fLL);
126998944Sobrien	  if (qp == 0 && isScratch (rN) && arM == 36 /* ar.unat */)
127098944Sobrien	    {
127198944Sobrien	      /* We have something like "mov.m r3 = ar.unat".  Remember the
127298944Sobrien		 r3 (or whatever) and watch for a store of this register... */
127398944Sobrien	      unat_save_reg = rN;
127498944Sobrien	      last_prologue_pc = next_pc;
127598944Sobrien	    }
127698944Sobrien	}
127798944Sobrien      else if (it == I && ((instr & 0x1eff8000000LL) == 0x00198000000LL))
127898944Sobrien	{
127998944Sobrien	  /* mov rN = pr */
128098944Sobrien	  int rN  = (int) ((instr & 0x00000001fc0LL) >> 6);
128198944Sobrien	  int qp  = (int) (instr & 0x0000000003fLL);
128298944Sobrien	  if (qp == 0 && isScratch (rN))
128398944Sobrien	    {
128498944Sobrien	      pr_save_reg = rN;
128598944Sobrien	      last_prologue_pc = next_pc;
128698944Sobrien	    }
128798944Sobrien	}
128898944Sobrien      else if (it == M
128998944Sobrien            && (   ((instr & 0x1ffc8000000LL) == 0x08cc0000000LL)
129098944Sobrien	        || ((instr & 0x1efc0000000LL) == 0x0acc0000000LL)))
129198944Sobrien	{
129298944Sobrien	  /* st8 [rN] = rM
129398944Sobrien	      or
129498944Sobrien	     st8 [rN] = rM, imm9 */
129598944Sobrien	  int rN = (int) ((instr & 0x00007f00000LL) >> 20);
129698944Sobrien	  int rM = (int) ((instr & 0x000000fe000LL) >> 13);
129798944Sobrien	  int qp = (int) (instr & 0x0000000003fLL);
1298130803Smarcel	  int indirect = rM < 256 ? reg_contents[rM] : 0;
129998944Sobrien	  if (qp == 0 && rN == spill_reg && spill_addr != 0
130098944Sobrien	      && (rM == unat_save_reg || rM == pr_save_reg))
130198944Sobrien	    {
130298944Sobrien	      /* We've found a spill of either the UNAT register or the PR
130398944Sobrien	         register.  (Well, not exactly; what we've actually found is
130498944Sobrien		 a spill of the register that UNAT or PR was moved to).
130598944Sobrien		 Record that fact and move on... */
130698944Sobrien	      if (rM == unat_save_reg)
130798944Sobrien		{
130898944Sobrien		  /* Track UNAT register */
1309130803Smarcel		  cache->saved_regs[IA64_UNAT_REGNUM] = spill_addr;
131098944Sobrien		  unat_save_reg = 0;
131198944Sobrien		}
131298944Sobrien	      else
131398944Sobrien	        {
131498944Sobrien		  /* Track PR register */
1315130803Smarcel		  cache->saved_regs[IA64_PR_REGNUM] = spill_addr;
131698944Sobrien		  pr_save_reg = 0;
131798944Sobrien		}
131898944Sobrien	      if ((instr & 0x1efc0000000LL) == 0x0acc0000000LL)
131998944Sobrien		/* st8 [rN] = rM, imm9 */
132098944Sobrien		spill_addr += imm9(instr);
132198944Sobrien	      else
132298944Sobrien		spill_addr = 0;		/* must be done spilling */
132398944Sobrien	      last_prologue_pc = next_pc;
132498944Sobrien	    }
132598944Sobrien	  else if (qp == 0 && 32 <= rM && rM < 40 && !instores[rM-32])
132698944Sobrien	    {
132798944Sobrien	      /* Allow up to one store of each input register. */
132898944Sobrien	      instores[rM-32] = 1;
132998944Sobrien	      last_prologue_pc = next_pc;
133098944Sobrien	    }
1331130803Smarcel	  else if (qp == 0 && 32 <= indirect && indirect < 40 &&
1332130803Smarcel		   !instores[indirect-32])
1333130803Smarcel	    {
1334130803Smarcel	      /* Allow an indirect store of an input register.  */
1335130803Smarcel	      instores[indirect-32] = 1;
1336130803Smarcel	      last_prologue_pc = next_pc;
1337130803Smarcel	    }
133898944Sobrien	}
133998944Sobrien      else if (it == M && ((instr & 0x1ff08000000LL) == 0x08c00000000LL))
134098944Sobrien	{
134198944Sobrien	  /* One of
134298944Sobrien	       st1 [rN] = rM
134398944Sobrien	       st2 [rN] = rM
134498944Sobrien	       st4 [rN] = rM
134598944Sobrien	       st8 [rN] = rM
134698944Sobrien	     Note that the st8 case is handled in the clause above.
134798944Sobrien
134898944Sobrien	     Advance over stores of input registers. One store per input
134998944Sobrien	     register is permitted. */
135098944Sobrien	  int rM = (int) ((instr & 0x000000fe000LL) >> 13);
135198944Sobrien	  int qp = (int) (instr & 0x0000000003fLL);
1352130803Smarcel	  int indirect = rM < 256 ? reg_contents[rM] : 0;
135398944Sobrien	  if (qp == 0 && 32 <= rM && rM < 40 && !instores[rM-32])
135498944Sobrien	    {
135598944Sobrien	      instores[rM-32] = 1;
135698944Sobrien	      last_prologue_pc = next_pc;
135798944Sobrien	    }
1358130803Smarcel	  else if (qp == 0 && 32 <= indirect && indirect < 40 &&
1359130803Smarcel		   !instores[indirect-32])
1360130803Smarcel	    {
1361130803Smarcel	      /* Allow an indirect store of an input register.  */
1362130803Smarcel	      instores[indirect-32] = 1;
1363130803Smarcel	      last_prologue_pc = next_pc;
1364130803Smarcel	    }
136598944Sobrien	}
136698944Sobrien      else if (it == M && ((instr & 0x1ff88000000LL) == 0x0cc80000000LL))
136798944Sobrien        {
136898944Sobrien	  /* Either
136998944Sobrien	       stfs [rN] = fM
137098944Sobrien	     or
137198944Sobrien	       stfd [rN] = fM
137298944Sobrien
137398944Sobrien	     Advance over stores of floating point input registers.  Again
137498944Sobrien	     one store per register is permitted */
137598944Sobrien	  int fM = (int) ((instr & 0x000000fe000LL) >> 13);
137698944Sobrien	  int qp = (int) (instr & 0x0000000003fLL);
137798944Sobrien	  if (qp == 0 && 8 <= fM && fM < 16 && !infpstores[fM - 8])
137898944Sobrien	    {
137998944Sobrien	      infpstores[fM-8] = 1;
138098944Sobrien	      last_prologue_pc = next_pc;
138198944Sobrien	    }
138298944Sobrien	}
138398944Sobrien      else if (it == M
138498944Sobrien            && (   ((instr & 0x1ffc8000000LL) == 0x08ec0000000LL)
138598944Sobrien	        || ((instr & 0x1efc0000000LL) == 0x0aec0000000LL)))
138698944Sobrien	{
138798944Sobrien	  /* st8.spill [rN] = rM
138898944Sobrien	       or
138998944Sobrien	     st8.spill [rN] = rM, imm9 */
139098944Sobrien	  int rN = (int) ((instr & 0x00007f00000LL) >> 20);
139198944Sobrien	  int rM = (int) ((instr & 0x000000fe000LL) >> 13);
139298944Sobrien	  int qp = (int) (instr & 0x0000000003fLL);
139398944Sobrien	  if (qp == 0 && rN == spill_reg && 4 <= rM && rM <= 7)
139498944Sobrien	    {
139598944Sobrien	      /* We've found a spill of one of the preserved general purpose
139698944Sobrien	         regs.  Record the spill address and advance the spill
139798944Sobrien		 register if appropriate. */
1398130803Smarcel	      cache->saved_regs[IA64_GR0_REGNUM + rM] = spill_addr;
139998944Sobrien	      if ((instr & 0x1efc0000000LL) == 0x0aec0000000LL)
140098944Sobrien	        /* st8.spill [rN] = rM, imm9 */
140198944Sobrien		spill_addr += imm9(instr);
140298944Sobrien	      else
140398944Sobrien		spill_addr = 0;		/* Done spilling */
140498944Sobrien	      last_prologue_pc = next_pc;
140598944Sobrien	    }
140698944Sobrien	}
140798944Sobrien
140898944Sobrien      pc = next_pc;
140998944Sobrien    }
141098944Sobrien
1411130803Smarcel  /* If not frameless and we aren't called by skip_prologue, then we need to calculate
1412130803Smarcel     registers for the previous frame which will be needed later.  */
141398944Sobrien
1414130803Smarcel  if (!frameless && next_frame)
1415130803Smarcel    {
1416130803Smarcel      /* Extract the size of the rotating portion of the stack
1417130803Smarcel	 frame and the register rename base from the current
1418130803Smarcel	 frame marker. */
1419130803Smarcel      cfm = cache->cfm;
1420130803Smarcel      sor = cache->sor;
1421130803Smarcel      sof = cache->sof;
1422130803Smarcel      sol = cache->sol;
1423130803Smarcel      rrb_gr = (cfm >> 18) & 0x7f;
142498944Sobrien
1425130803Smarcel      /* Find the bof (beginning of frame).  */
1426130803Smarcel      bof = rse_address_add (cache->bsp, -sof);
1427130803Smarcel
1428130803Smarcel      for (i = 0, addr = bof;
1429130803Smarcel	   i < sof;
1430130803Smarcel	   i++, addr += 8)
1431130803Smarcel	{
1432130803Smarcel	  if (IS_NaT_COLLECTION_ADDR (addr))
1433130803Smarcel	    {
1434130803Smarcel	      addr += 8;
1435130803Smarcel	    }
1436130803Smarcel	  if (i+32 == cfm_reg)
1437130803Smarcel	    cache->saved_regs[IA64_CFM_REGNUM] = addr;
1438130803Smarcel	  if (i+32 == ret_reg)
1439130803Smarcel	    cache->saved_regs[IA64_VRAP_REGNUM] = addr;
1440130803Smarcel	  if (i+32 == fp_reg)
1441130803Smarcel	    cache->saved_regs[IA64_VFP_REGNUM] = addr;
1442130803Smarcel	}
144398944Sobrien
1444130803Smarcel      /* For the previous argument registers we require the previous bof.
1445130803Smarcel	 If we can't find the previous cfm, then we can do nothing.  */
1446130803Smarcel      cfm = 0;
1447130803Smarcel      if (cache->saved_regs[IA64_CFM_REGNUM] != 0)
1448130803Smarcel	{
1449134800Smarcel	  uint64_t tmp;
1450134800Smarcel	  ia64_read_reg (cache->saved_regs[IA64_CFM_REGNUM], &tmp, sizeof(tmp));
1451134800Smarcel	  cfm = tmp;
1452130803Smarcel	}
1453130803Smarcel      else if (cfm_reg != 0)
1454130803Smarcel	{
1455130803Smarcel	  frame_unwind_register (next_frame, cfm_reg, buf);
1456130803Smarcel	  cfm = extract_unsigned_integer (buf, 8);
1457130803Smarcel	}
1458130803Smarcel      cache->prev_cfm = cfm;
1459130803Smarcel
1460130803Smarcel      if (cfm != 0)
1461130803Smarcel	{
1462130803Smarcel	  sor = ((cfm >> 14) & 0xf) * 8;
1463130803Smarcel	  sof = (cfm & 0x7f);
1464130803Smarcel	  sol = (cfm >> 7) & 0x7f;
1465130803Smarcel	  rrb_gr = (cfm >> 18) & 0x7f;
146698944Sobrien
1467130803Smarcel	  /* The previous bof only requires subtraction of the sol (size of locals)
1468130803Smarcel	     due to the overlap between output and input of subsequent frames.  */
1469130803Smarcel	  bof = rse_address_add (bof, -sol);
1470130803Smarcel
1471130803Smarcel	  for (i = 0, addr = bof;
1472130803Smarcel	       i < sof;
1473130803Smarcel	       i++, addr += 8)
1474130803Smarcel	    {
1475130803Smarcel	      if (IS_NaT_COLLECTION_ADDR (addr))
1476130803Smarcel		{
1477130803Smarcel		  addr += 8;
1478130803Smarcel		}
1479130803Smarcel	      if (i < sor)
1480130803Smarcel		cache->saved_regs[IA64_GR32_REGNUM + ((i + (sor - rrb_gr)) % sor)]
1481130803Smarcel		  = addr;
1482130803Smarcel	      else
1483130803Smarcel		cache->saved_regs[IA64_GR32_REGNUM + i] = addr;
1484130803Smarcel	    }
1485130803Smarcel
1486130803Smarcel	}
1487130803Smarcel    }
1488130803Smarcel
1489130803Smarcel  /* Try and trust the lim_pc value whenever possible.  */
1490130803Smarcel  if (trust_limit && lim_pc >= last_prologue_pc)
1491130803Smarcel    last_prologue_pc = lim_pc;
1492130803Smarcel
1493130803Smarcel  cache->frameless = frameless;
1494130803Smarcel  cache->after_prologue = last_prologue_pc;
1495130803Smarcel  cache->mem_stack_frame_size = mem_stack_frame_size;
1496130803Smarcel  cache->fp_reg = fp_reg;
1497130803Smarcel
149898944Sobrien  return last_prologue_pc;
149998944Sobrien}
150098944Sobrien
150198944SobrienCORE_ADDR
150298944Sobrienia64_skip_prologue (CORE_ADDR pc)
150398944Sobrien{
1504130803Smarcel  struct ia64_frame_cache cache;
1505130803Smarcel  cache.base = 0;
1506130803Smarcel  cache.after_prologue = 0;
1507130803Smarcel  cache.cfm = 0;
1508130803Smarcel  cache.bsp = 0;
1509130803Smarcel
1510130803Smarcel  /* Call examine_prologue with - as third argument since we don't have a next frame pointer to send.  */
1511130803Smarcel  return examine_prologue (pc, pc+1024, 0, &cache);
151298944Sobrien}
151398944Sobrien
1514130803Smarcel
1515130803Smarcel/* Normal frames.  */
1516130803Smarcel
1517130803Smarcelstatic struct ia64_frame_cache *
1518130803Smarcelia64_frame_cache (struct frame_info *next_frame, void **this_cache)
151998944Sobrien{
1520130803Smarcel  struct ia64_frame_cache *cache;
1521130803Smarcel  char buf[8];
1522130803Smarcel  CORE_ADDR cfm, sof, sol, bsp, psr;
1523130803Smarcel  int i;
152498944Sobrien
1525130803Smarcel  if (*this_cache)
1526130803Smarcel    return *this_cache;
152798944Sobrien
1528130803Smarcel  cache = ia64_alloc_frame_cache ();
1529130803Smarcel  *this_cache = cache;
153098944Sobrien
1531130803Smarcel  frame_unwind_register (next_frame, sp_regnum, buf);
1532130803Smarcel  cache->saved_sp = extract_unsigned_integer (buf, 8);
153398944Sobrien
1534130803Smarcel  /* We always want the bsp to point to the end of frame.
1535130803Smarcel     This way, we can always get the beginning of frame (bof)
1536130803Smarcel     by subtracting frame size.  */
1537130803Smarcel  frame_unwind_register (next_frame, IA64_BSP_REGNUM, buf);
1538130803Smarcel  cache->bsp = extract_unsigned_integer (buf, 8);
1539130803Smarcel
1540130803Smarcel  frame_unwind_register (next_frame, IA64_PSR_REGNUM, buf);
1541130803Smarcel  psr = extract_unsigned_integer (buf, 8);
1542130803Smarcel
1543130803Smarcel  frame_unwind_register (next_frame, IA64_CFM_REGNUM, buf);
1544130803Smarcel  cfm = extract_unsigned_integer (buf, 8);
1545130803Smarcel
1546130803Smarcel  cache->sof = (cfm & 0x7f);
1547130803Smarcel  cache->sol = (cfm >> 7) & 0x7f;
1548130803Smarcel  cache->sor = ((cfm >> 14) & 0xf) * 8;
1549130803Smarcel
1550130803Smarcel  cache->cfm = cfm;
1551130803Smarcel
1552130803Smarcel  cache->pc = frame_func_unwind (next_frame);
1553130803Smarcel
1554130803Smarcel  if (cache->pc != 0)
1555130803Smarcel    examine_prologue (cache->pc, frame_pc_unwind (next_frame), next_frame, cache);
1556130803Smarcel
1557130803Smarcel  cache->base = cache->saved_sp + cache->mem_stack_frame_size;
1558130803Smarcel
1559130803Smarcel  return cache;
156098944Sobrien}
156198944Sobrien
1562130803Smarcelstatic void
1563130803Smarcelia64_frame_this_id (struct frame_info *next_frame, void **this_cache,
1564130803Smarcel		    struct frame_id *this_id)
156598944Sobrien{
1566130803Smarcel  struct ia64_frame_cache *cache =
1567130803Smarcel    ia64_frame_cache (next_frame, this_cache);
156898944Sobrien
1569130803Smarcel  /* This marks the outermost frame.  */
1570130803Smarcel  if (cache->base == 0)
1571130803Smarcel    return;
157298944Sobrien
1573130803Smarcel  (*this_id) = frame_id_build_special (cache->base, cache->pc, cache->bsp);
1574130803Smarcel  if (gdbarch_debug >= 1)
1575130803Smarcel    fprintf_unfiltered (gdb_stdlog,
1576130803Smarcel			"regular frame id: code 0x%s, stack 0x%s, special 0x%s, next_frame %p\n",
1577130803Smarcel			paddr_nz (this_id->code_addr),
1578130803Smarcel			paddr_nz (this_id->stack_addr),
1579130803Smarcel			paddr_nz (cache->bsp), next_frame);
1580130803Smarcel}
158198944Sobrien
1582130803Smarcelstatic void
1583130803Smarcelia64_frame_prev_register (struct frame_info *next_frame, void **this_cache,
1584130803Smarcel			  int regnum, int *optimizedp,
1585130803Smarcel			  enum lval_type *lvalp, CORE_ADDR *addrp,
1586130803Smarcel			  int *realnump, void *valuep)
1587130803Smarcel{
1588130803Smarcel  struct ia64_frame_cache *cache =
1589130803Smarcel    ia64_frame_cache (next_frame, this_cache);
1590130803Smarcel  char dummy_valp[MAX_REGISTER_SIZE];
1591130803Smarcel  char buf[8];
159298944Sobrien
1593130803Smarcel  gdb_assert (regnum >= 0);
159498944Sobrien
1595130803Smarcel  if (!target_has_registers)
1596130803Smarcel    error ("No registers.");
159798944Sobrien
1598130803Smarcel  *optimizedp = 0;
1599130803Smarcel  *addrp = 0;
1600130803Smarcel  *lvalp = not_lval;
1601130803Smarcel  *realnump = -1;
1602130803Smarcel
1603130803Smarcel  /* Rather than check each time if valuep is non-null, supply a dummy buffer
1604130803Smarcel     when valuep is not supplied.  */
1605130803Smarcel  if (!valuep)
1606130803Smarcel    valuep = dummy_valp;
1607130803Smarcel
1608130803Smarcel  memset (valuep, 0, register_size (current_gdbarch, regnum));
1609130803Smarcel
1610130803Smarcel  if (regnum == SP_REGNUM)
161198944Sobrien    {
161298944Sobrien      /* Handle SP values for all frames but the topmost. */
1613130803Smarcel      store_unsigned_integer (valuep, register_size (current_gdbarch, regnum),
1614130803Smarcel			      cache->base);
161598944Sobrien    }
161698944Sobrien  else if (regnum == IA64_BSP_REGNUM)
161798944Sobrien    {
1618130803Smarcel      char cfm_valuep[MAX_REGISTER_SIZE];
1619130803Smarcel      int  cfm_optim;
1620130803Smarcel      int  cfm_realnum;
1621130803Smarcel      enum lval_type cfm_lval;
1622130803Smarcel      CORE_ADDR cfm_addr;
1623130803Smarcel      CORE_ADDR bsp, prev_cfm, prev_bsp;
1624130803Smarcel
1625130803Smarcel      /* We want to calculate the previous bsp as the end of the previous register stack frame.
1626130803Smarcel	 This corresponds to what the hardware bsp register will be if we pop the frame
1627130803Smarcel	 back which is why we might have been called.  We know the beginning of the current
1628130803Smarcel	 frame is cache->bsp - cache->sof.  This value in the previous frame points to
1629130803Smarcel	 the start of the output registers.  We can calculate the end of that frame by adding
1630130803Smarcel	 the size of output (sof (size of frame) - sol (size of locals)).  */
1631130803Smarcel      ia64_frame_prev_register (next_frame, this_cache, IA64_CFM_REGNUM,
1632130803Smarcel				&cfm_optim, &cfm_lval, &cfm_addr, &cfm_realnum, cfm_valuep);
1633130803Smarcel      prev_cfm = extract_unsigned_integer (cfm_valuep, 8);
1634130803Smarcel
1635130803Smarcel      bsp = rse_address_add (cache->bsp, -(cache->sof));
1636130803Smarcel      prev_bsp = rse_address_add (bsp, (prev_cfm & 0x7f) - ((prev_cfm >> 7) & 0x7f));
1637130803Smarcel
1638130803Smarcel      store_unsigned_integer (valuep, register_size (current_gdbarch, regnum),
1639130803Smarcel			      prev_bsp);
164098944Sobrien    }
1641130803Smarcel  else if (regnum == IA64_CFM_REGNUM)
1642130803Smarcel    {
1643130803Smarcel      CORE_ADDR addr = cache->saved_regs[IA64_CFM_REGNUM];
1644130803Smarcel
1645130803Smarcel      if (addr != 0)
1646130803Smarcel	{
1647130803Smarcel	  *lvalp = lval_memory;
1648130803Smarcel	  *addrp = addr;
1649134800Smarcel	  ia64_read_reg (addr, valuep, register_size (current_gdbarch, regnum));
1650130803Smarcel	}
1651130803Smarcel      else if (cache->prev_cfm)
1652130803Smarcel	store_unsigned_integer (valuep, register_size (current_gdbarch, regnum), cache->prev_cfm);
1653130803Smarcel      else if (cache->frameless)
1654130803Smarcel	{
1655130803Smarcel	  CORE_ADDR cfm = 0;
1656130803Smarcel	  frame_unwind_register (next_frame, IA64_PFS_REGNUM, valuep);
1657130803Smarcel	}
1658130803Smarcel    }
165998944Sobrien  else if (regnum == IA64_VFP_REGNUM)
166098944Sobrien    {
166198944Sobrien      /* If the function in question uses an automatic register (r32-r127)
166298944Sobrien         for the frame pointer, it'll be found by ia64_find_saved_register()
166398944Sobrien	 above.  If the function lacks one of these frame pointers, we can
1664130803Smarcel	 still provide a value since we know the size of the frame.  */
1665130803Smarcel      CORE_ADDR vfp = cache->base;
1666130803Smarcel      store_unsigned_integer (valuep, register_size (current_gdbarch, IA64_VFP_REGNUM), vfp);
166798944Sobrien    }
1668130803Smarcel  else if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM)
166998944Sobrien    {
1670130803Smarcel      char pr_valuep[MAX_REGISTER_SIZE];
167198944Sobrien      int  pr_optim;
1672130803Smarcel      int  pr_realnum;
167398944Sobrien      enum lval_type pr_lval;
167498944Sobrien      CORE_ADDR pr_addr;
1675130803Smarcel      ULONGEST prN_val;
1676130803Smarcel      ia64_frame_prev_register (next_frame, this_cache, IA64_PR_REGNUM,
1677130803Smarcel				&pr_optim, &pr_lval, &pr_addr, &pr_realnum, pr_valuep);
1678130803Smarcel      if (VP16_REGNUM <= regnum && regnum <= VP63_REGNUM)
167998944Sobrien	{
168098944Sobrien	  /* Fetch predicate register rename base from current frame
1681130803Smarcel	     marker for this frame.  */
1682130803Smarcel	  int rrb_pr = (cache->cfm >> 32) & 0x3f;
168398944Sobrien
1684130803Smarcel	  /* Adjust the register number to account for register rotation.  */
1685130803Smarcel	  regnum = VP16_REGNUM
1686130803Smarcel	         + ((regnum - VP16_REGNUM) + rrb_pr) % 48;
168798944Sobrien	}
1688130803Smarcel      prN_val = extract_bit_field ((unsigned char *) pr_valuep,
1689130803Smarcel                                   regnum - VP0_REGNUM, 1);
1690130803Smarcel      store_unsigned_integer (valuep, register_size (current_gdbarch, regnum), prN_val);
169198944Sobrien    }
169298944Sobrien  else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT31_REGNUM)
169398944Sobrien    {
1694130803Smarcel      char unat_valuep[MAX_REGISTER_SIZE];
169598944Sobrien      int  unat_optim;
1696130803Smarcel      int  unat_realnum;
169798944Sobrien      enum lval_type unat_lval;
169898944Sobrien      CORE_ADDR unat_addr;
1699130803Smarcel      ULONGEST unatN_val;
1700130803Smarcel      ia64_frame_prev_register (next_frame, this_cache, IA64_UNAT_REGNUM,
1701130803Smarcel				&unat_optim, &unat_lval, &unat_addr, &unat_realnum, unat_valuep);
1702130803Smarcel      unatN_val = extract_bit_field ((unsigned char *) unat_valuep,
170398944Sobrien                                   regnum - IA64_NAT0_REGNUM, 1);
1704130803Smarcel      store_unsigned_integer (valuep, register_size (current_gdbarch, regnum),
170598944Sobrien                              unatN_val);
170698944Sobrien    }
170798944Sobrien  else if (IA64_NAT32_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM)
170898944Sobrien    {
170998944Sobrien      int natval = 0;
171098944Sobrien      /* Find address of general register corresponding to nat bit we're
1711130803Smarcel         interested in.  */
1712130803Smarcel      CORE_ADDR gr_addr;
171398944Sobrien
1714130803Smarcel      gr_addr = cache->saved_regs[regnum - IA64_NAT0_REGNUM
1715130803Smarcel				  + IA64_GR0_REGNUM];
1716130803Smarcel      if (gr_addr != 0)
171798944Sobrien	{
1718130803Smarcel	  /* Compute address of nat collection bits.  */
171998944Sobrien	  CORE_ADDR nat_addr = gr_addr | 0x1f8;
1720130803Smarcel	  CORE_ADDR bsp;
172198944Sobrien	  CORE_ADDR nat_collection;
172298944Sobrien	  int nat_bit;
172398944Sobrien	  /* If our nat collection address is bigger than bsp, we have to get
172498944Sobrien	     the nat collection from rnat.  Otherwise, we fetch the nat
1725130803Smarcel	     collection from the computed address.  */
1726130803Smarcel	  frame_unwind_register (next_frame, IA64_BSP_REGNUM, buf);
1727130803Smarcel	  bsp = extract_unsigned_integer (buf, 8);
172898944Sobrien	  if (nat_addr >= bsp)
1729130803Smarcel	    {
1730130803Smarcel	      frame_unwind_register (next_frame, IA64_RNAT_REGNUM, buf);
1731130803Smarcel	      nat_collection = extract_unsigned_integer (buf, 8);
1732130803Smarcel	    }
173398944Sobrien	  else
1734134800Smarcel	    {
1735134800Smarcel	      uint64_t tmp;
1736134800Smarcel	      ia64_read_reg (nat_addr, &tmp, sizeof(tmp));
1737134800Smarcel	      nat_collection = tmp;
1738134800Smarcel	    }
173998944Sobrien	  nat_bit = (gr_addr >> 3) & 0x3f;
174098944Sobrien	  natval = (nat_collection >> nat_bit) & 1;
174198944Sobrien	}
1742130803Smarcel
1743130803Smarcel      store_unsigned_integer (valuep, register_size (current_gdbarch, regnum), natval);
174498944Sobrien    }
174598944Sobrien  else if (regnum == IA64_IP_REGNUM)
174698944Sobrien    {
1747130803Smarcel      CORE_ADDR pc = 0;
1748130803Smarcel      CORE_ADDR addr = cache->saved_regs[IA64_VRAP_REGNUM];
1749130803Smarcel
1750130803Smarcel      if (addr != 0)
1751130803Smarcel	{
1752130803Smarcel	  *lvalp = lval_memory;
1753130803Smarcel	  *addrp = addr;
1754134800Smarcel	  ia64_read_reg (addr, buf, register_size (current_gdbarch, IA64_IP_REGNUM));
1755130803Smarcel	  pc = extract_unsigned_integer (buf, 8);
175698944Sobrien	}
1757130803Smarcel      else if (cache->frameless)
1758130803Smarcel	{
1759130803Smarcel	  frame_unwind_register (next_frame, IA64_BR0_REGNUM, buf);
1760130803Smarcel	  pc = extract_unsigned_integer (buf, 8);
1761130803Smarcel	}
1762130803Smarcel      pc &= ~0xf;
1763130803Smarcel      store_unsigned_integer (valuep, 8, pc);
176498944Sobrien    }
1765130803Smarcel  else if (regnum == IA64_PSR_REGNUM)
176698944Sobrien    {
1767130803Smarcel      /* We don't know how to get the complete previous PSR, but we need it for
1768130803Smarcel	 the slot information when we unwind the pc (pc is formed of IP register
1769130803Smarcel	 plus slot information from PSR).  To get the previous slot information,
1770130803Smarcel	 we mask it off the return address.  */
1771130803Smarcel      ULONGEST slot_num = 0;
1772130803Smarcel      CORE_ADDR pc= 0;
1773130803Smarcel      CORE_ADDR psr = 0;
1774130803Smarcel      CORE_ADDR addr = cache->saved_regs[IA64_VRAP_REGNUM];
1775130803Smarcel
1776130803Smarcel      frame_unwind_register (next_frame, IA64_PSR_REGNUM, buf);
1777130803Smarcel      psr = extract_unsigned_integer (buf, 8);
1778130803Smarcel
1779130803Smarcel      if (addr != 0)
178098944Sobrien	{
1781130803Smarcel	  *lvalp = lval_memory;
1782130803Smarcel	  *addrp = addr;
1783134800Smarcel	  ia64_read_reg (addr, buf, register_size (current_gdbarch, IA64_IP_REGNUM));
1784130803Smarcel	  pc = extract_unsigned_integer (buf, 8);
178598944Sobrien	}
1786130803Smarcel      else if (cache->frameless)
1787130803Smarcel	{
1788130803Smarcel	  CORE_ADDR pc;
1789130803Smarcel	  frame_unwind_register (next_frame, IA64_BR0_REGNUM, buf);
1790130803Smarcel	  pc = extract_unsigned_integer (buf, 8);
1791130803Smarcel	}
1792130803Smarcel      psr &= ~(3LL << 41);
1793130803Smarcel      slot_num = pc & 0x3LL;
1794130803Smarcel      psr |= (CORE_ADDR)slot_num << 41;
1795130803Smarcel      store_unsigned_integer (valuep, 8, psr);
1796130803Smarcel    }
1797130803Smarcel  else if (regnum == IA64_BR0_REGNUM)
1798130803Smarcel    {
1799130803Smarcel      CORE_ADDR br0 = 0;
1800130803Smarcel      CORE_ADDR addr = cache->saved_regs[IA64_BR0_REGNUM];
180198944Sobrien      if (addr != 0)
180298944Sobrien	{
1803130803Smarcel	  *lvalp = lval_memory;
1804130803Smarcel	  *addrp = addr;
1805134800Smarcel	  ia64_read_reg (addr, buf, register_size (current_gdbarch, IA64_BR0_REGNUM));
1806130803Smarcel	  br0 = extract_unsigned_integer (buf, 8);
180798944Sobrien	}
1808130803Smarcel      store_unsigned_integer (valuep, 8, br0);
1809130803Smarcel    }
1810130803Smarcel else if ((regnum >= IA64_GR32_REGNUM && regnum <= IA64_GR127_REGNUM) ||
1811130803Smarcel	   (regnum >= V32_REGNUM && regnum <= V127_REGNUM))
1812130803Smarcel    {
1813130803Smarcel      CORE_ADDR addr = 0;
1814130803Smarcel      if (regnum >= V32_REGNUM)
1815130803Smarcel	regnum = IA64_GR32_REGNUM + (regnum - V32_REGNUM);
1816130803Smarcel      addr = cache->saved_regs[regnum];
1817130803Smarcel      if (addr != 0)
1818130803Smarcel	{
1819130803Smarcel	  *lvalp = lval_memory;
1820130803Smarcel	  *addrp = addr;
1821134800Smarcel	  ia64_read_reg (addr, valuep, register_size (current_gdbarch, regnum));
1822130803Smarcel	}
1823130803Smarcel      else if (cache->frameless)
182498944Sobrien        {
1825130803Smarcel	  char r_valuep[MAX_REGISTER_SIZE];
1826130803Smarcel	  int  r_optim;
1827130803Smarcel	  int  r_realnum;
1828130803Smarcel	  enum lval_type r_lval;
1829130803Smarcel	  CORE_ADDR r_addr;
1830130803Smarcel	  CORE_ADDR prev_cfm, prev_bsp, prev_bof;
1831130803Smarcel	  CORE_ADDR addr = 0;
1832132685Smarcel
1833130803Smarcel	  if (regnum >= V32_REGNUM)
1834130803Smarcel	    regnum = IA64_GR32_REGNUM + (regnum - V32_REGNUM);
1835130803Smarcel	  ia64_frame_prev_register (next_frame, this_cache, IA64_CFM_REGNUM,
1836130803Smarcel				    &r_optim, &r_lval, &r_addr, &r_realnum, r_valuep);
1837130803Smarcel	  prev_cfm = extract_unsigned_integer (r_valuep, 8);
1838130803Smarcel	  ia64_frame_prev_register (next_frame, this_cache, IA64_BSP_REGNUM,
1839130803Smarcel				    &r_optim, &r_lval, &r_addr, &r_realnum, r_valuep);
1840130803Smarcel	  prev_bsp = extract_unsigned_integer (r_valuep, 8);
1841130803Smarcel	  prev_bof = rse_address_add (prev_bsp, -(prev_cfm & 0x7f));
1842130803Smarcel
1843130803Smarcel	  addr = rse_address_add (prev_bof, (regnum - IA64_GR32_REGNUM));
1844134800Smarcel	  *lvalp = lval_memory;
1845134800Smarcel	  *addrp = addr;
1846134800Smarcel	  ia64_read_reg (addr, valuep, register_size (current_gdbarch, regnum));
184798944Sobrien        }
184898944Sobrien    }
184998944Sobrien  else
185098944Sobrien    {
1851130803Smarcel      CORE_ADDR addr = 0;
185298944Sobrien      if (IA64_FR32_REGNUM <= regnum && regnum <= IA64_FR127_REGNUM)
185398944Sobrien	{
185498944Sobrien	  /* Fetch floating point register rename base from current
1855130803Smarcel	     frame marker for this frame.  */
1856130803Smarcel	  int rrb_fr = (cache->cfm >> 25) & 0x7f;
185798944Sobrien
185898944Sobrien	  /* Adjust the floating point register number to account for
1859130803Smarcel	     register rotation.  */
186098944Sobrien	  regnum = IA64_FR32_REGNUM
186198944Sobrien	         + ((regnum - IA64_FR32_REGNUM) + rrb_fr) % 96;
186298944Sobrien	}
186398944Sobrien
1864130803Smarcel      /* If we have stored a memory address, access the register.  */
1865130803Smarcel      addr = cache->saved_regs[regnum];
1866130803Smarcel      if (addr != 0)
1867130803Smarcel	{
1868130803Smarcel	  *lvalp = lval_memory;
1869130803Smarcel	  *addrp = addr;
1870134800Smarcel	  ia64_read_reg (addr, valuep, register_size (current_gdbarch, regnum));
1871130803Smarcel	}
1872130803Smarcel      /* Otherwise, punt and get the current value of the register.  */
1873130803Smarcel      else
1874130803Smarcel	frame_unwind_register (next_frame, regnum, valuep);
187598944Sobrien    }
1876130803Smarcel
1877130803Smarcel  if (gdbarch_debug >= 1)
1878130803Smarcel    fprintf_unfiltered (gdb_stdlog,
1879130803Smarcel			"regular prev register <%d> <%s> is 0x%s\n", regnum,
1880130803Smarcel			(((unsigned) regnum <= IA64_NAT127_REGNUM)
1881130803Smarcel			 ? ia64_register_names[regnum] : "r??"),
1882130803Smarcel			paddr_nz (extract_unsigned_integer (valuep, 8)));
188398944Sobrien}
1884130803Smarcel
1885130803Smarcelstatic const struct frame_unwind ia64_frame_unwind =
1886130803Smarcel{
1887130803Smarcel  NORMAL_FRAME,
1888130803Smarcel  &ia64_frame_this_id,
1889130803Smarcel  &ia64_frame_prev_register
1890130803Smarcel};
189198944Sobrien
1892130803Smarcelstatic const struct frame_unwind *
1893130803Smarcelia64_frame_sniffer (struct frame_info *next_frame)
189498944Sobrien{
1895130803Smarcel  return &ia64_frame_unwind;
1896130803Smarcel}
189798944Sobrien
1898130803Smarcel/* Signal trampolines.  */
189998944Sobrien
1900130803Smarcelstatic void
1901130803Smarcelia64_sigtramp_frame_init_saved_regs (struct ia64_frame_cache *cache)
1902130803Smarcel{
1903130803Smarcel  if (SIGCONTEXT_REGISTER_ADDRESS)
1904130803Smarcel    {
1905130803Smarcel      int regno;
1906130803Smarcel
1907130803Smarcel      cache->saved_regs[IA64_VRAP_REGNUM] =
1908130803Smarcel	SIGCONTEXT_REGISTER_ADDRESS (cache->base, IA64_IP_REGNUM);
1909130803Smarcel      cache->saved_regs[IA64_CFM_REGNUM] =
1910130803Smarcel	SIGCONTEXT_REGISTER_ADDRESS (cache->base, IA64_CFM_REGNUM);
1911130803Smarcel      cache->saved_regs[IA64_PSR_REGNUM] =
1912130803Smarcel	SIGCONTEXT_REGISTER_ADDRESS (cache->base, IA64_PSR_REGNUM);
1913130803Smarcel      cache->saved_regs[IA64_BSP_REGNUM] =
1914130803Smarcel	SIGCONTEXT_REGISTER_ADDRESS (cache->base, IA64_BSP_REGNUM);
1915130803Smarcel      cache->saved_regs[IA64_RNAT_REGNUM] =
1916130803Smarcel	SIGCONTEXT_REGISTER_ADDRESS (cache->base, IA64_RNAT_REGNUM);
1917130803Smarcel      cache->saved_regs[IA64_CCV_REGNUM] =
1918130803Smarcel	SIGCONTEXT_REGISTER_ADDRESS (cache->base, IA64_CCV_REGNUM);
1919130803Smarcel      cache->saved_regs[IA64_UNAT_REGNUM] =
1920130803Smarcel	SIGCONTEXT_REGISTER_ADDRESS (cache->base, IA64_UNAT_REGNUM);
1921130803Smarcel      cache->saved_regs[IA64_FPSR_REGNUM] =
1922130803Smarcel	SIGCONTEXT_REGISTER_ADDRESS (cache->base, IA64_FPSR_REGNUM);
1923130803Smarcel      cache->saved_regs[IA64_PFS_REGNUM] =
1924130803Smarcel	SIGCONTEXT_REGISTER_ADDRESS (cache->base, IA64_PFS_REGNUM);
1925130803Smarcel      cache->saved_regs[IA64_LC_REGNUM] =
1926130803Smarcel	SIGCONTEXT_REGISTER_ADDRESS (cache->base, IA64_LC_REGNUM);
1927130803Smarcel      for (regno = IA64_GR1_REGNUM; regno <= IA64_GR31_REGNUM; regno++)
1928130803Smarcel	cache->saved_regs[regno] =
1929130803Smarcel	  SIGCONTEXT_REGISTER_ADDRESS (cache->base, regno);
1930130803Smarcel      for (regno = IA64_BR0_REGNUM; regno <= IA64_BR7_REGNUM; regno++)
1931130803Smarcel	cache->saved_regs[regno] =
1932130803Smarcel	  SIGCONTEXT_REGISTER_ADDRESS (cache->base, regno);
1933130803Smarcel      for (regno = IA64_FR2_REGNUM; regno <= IA64_FR31_REGNUM; regno++)
1934130803Smarcel	cache->saved_regs[regno] =
1935130803Smarcel	  SIGCONTEXT_REGISTER_ADDRESS (cache->base, regno);
1936130803Smarcel    }
193798944Sobrien}
193898944Sobrien
1939130803Smarcelstatic struct ia64_frame_cache *
1940130803Smarcelia64_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache)
194198944Sobrien{
1942130803Smarcel  struct ia64_frame_cache *cache;
1943130803Smarcel  CORE_ADDR addr;
1944130803Smarcel  char buf[8];
1945130803Smarcel  int i;
194698944Sobrien
1947130803Smarcel  if (*this_cache)
1948130803Smarcel    return *this_cache;
1949130803Smarcel
1950130803Smarcel  cache = ia64_alloc_frame_cache ();
1951130803Smarcel
1952130803Smarcel  frame_unwind_register (next_frame, sp_regnum, buf);
1953130803Smarcel  /* Note that frame size is hard-coded below.  We cannot calculate it
1954130803Smarcel     via prologue examination.  */
1955130803Smarcel  cache->base = extract_unsigned_integer (buf, 8) + 16;
1956130803Smarcel
1957130803Smarcel  frame_unwind_register (next_frame, IA64_BSP_REGNUM, buf);
1958130803Smarcel  cache->bsp = extract_unsigned_integer (buf, 8);
1959130803Smarcel
1960130803Smarcel  frame_unwind_register (next_frame, IA64_CFM_REGNUM, buf);
1961130803Smarcel  cache->cfm = extract_unsigned_integer (buf, 8);
1962130803Smarcel  cache->sof = cache->cfm & 0x7f;
1963130803Smarcel
1964130803Smarcel  ia64_sigtramp_frame_init_saved_regs (cache);
1965130803Smarcel
1966130803Smarcel  *this_cache = cache;
1967130803Smarcel  return cache;
1968130803Smarcel}
1969130803Smarcel
1970130803Smarcelstatic void
1971130803Smarcelia64_sigtramp_frame_this_id (struct frame_info *next_frame,
1972130803Smarcel			       void **this_cache, struct frame_id *this_id)
1973130803Smarcel{
1974130803Smarcel  struct ia64_frame_cache *cache =
1975130803Smarcel    ia64_sigtramp_frame_cache (next_frame, this_cache);
1976130803Smarcel
1977130803Smarcel  (*this_id) = frame_id_build_special (cache->base, frame_pc_unwind (next_frame), cache->bsp);
1978130803Smarcel  if (gdbarch_debug >= 1)
1979130803Smarcel    fprintf_unfiltered (gdb_stdlog,
1980130803Smarcel			"sigtramp frame id: code 0x%s, stack 0x%s, special 0x%s, next_frame %p\n",
1981130803Smarcel			paddr_nz (this_id->code_addr),
1982130803Smarcel			paddr_nz (this_id->stack_addr),
1983130803Smarcel			paddr_nz (cache->bsp), next_frame);
1984130803Smarcel}
1985130803Smarcel
1986130803Smarcelstatic void
1987130803Smarcelia64_sigtramp_frame_prev_register (struct frame_info *next_frame,
1988130803Smarcel				   void **this_cache,
1989130803Smarcel				   int regnum, int *optimizedp,
1990130803Smarcel				   enum lval_type *lvalp, CORE_ADDR *addrp,
1991130803Smarcel				   int *realnump, void *valuep)
1992130803Smarcel{
1993130803Smarcel  char dummy_valp[MAX_REGISTER_SIZE];
1994130803Smarcel  char buf[MAX_REGISTER_SIZE];
1995130803Smarcel
1996130803Smarcel  struct ia64_frame_cache *cache =
1997130803Smarcel    ia64_sigtramp_frame_cache (next_frame, this_cache);
1998130803Smarcel
1999130803Smarcel  gdb_assert (regnum >= 0);
2000130803Smarcel
2001130803Smarcel  if (!target_has_registers)
2002130803Smarcel    error ("No registers.");
2003130803Smarcel
2004130803Smarcel  *optimizedp = 0;
2005130803Smarcel  *addrp = 0;
2006130803Smarcel  *lvalp = not_lval;
2007130803Smarcel  *realnump = -1;
2008130803Smarcel
2009130803Smarcel  /* Rather than check each time if valuep is non-null, supply a dummy buffer
2010130803Smarcel     when valuep is not supplied.  */
2011130803Smarcel  if (!valuep)
2012130803Smarcel    valuep = dummy_valp;
2013130803Smarcel
2014130803Smarcel  memset (valuep, 0, register_size (current_gdbarch, regnum));
2015130803Smarcel
2016130803Smarcel  if (regnum == IA64_IP_REGNUM)
201798944Sobrien    {
2018130803Smarcel      CORE_ADDR pc = 0;
2019130803Smarcel      CORE_ADDR addr = cache->saved_regs[IA64_VRAP_REGNUM];
202098944Sobrien
2021130803Smarcel      if (addr != 0)
202298944Sobrien	{
2023130803Smarcel	  *lvalp = lval_memory;
2024130803Smarcel	  *addrp = addr;
2025134800Smarcel	  ia64_read_reg (addr, buf, register_size (current_gdbarch, IA64_IP_REGNUM));
2026130803Smarcel	  pc = extract_unsigned_integer (buf, 8);
202798944Sobrien	}
2028130803Smarcel      pc &= ~0xf;
2029130803Smarcel      store_unsigned_integer (valuep, 8, pc);
203098944Sobrien    }
2031130803Smarcel else if ((regnum >= IA64_GR32_REGNUM && regnum <= IA64_GR127_REGNUM) ||
2032130803Smarcel	   (regnum >= V32_REGNUM && regnum <= V127_REGNUM))
2033130803Smarcel    {
2034130803Smarcel      CORE_ADDR addr = 0;
2035130803Smarcel      if (regnum >= V32_REGNUM)
2036130803Smarcel	regnum = IA64_GR32_REGNUM + (regnum - V32_REGNUM);
2037130803Smarcel      addr = cache->saved_regs[regnum];
2038130803Smarcel      if (addr != 0)
2039130803Smarcel	{
2040130803Smarcel	  *lvalp = lval_memory;
2041130803Smarcel	  *addrp = addr;
2042134800Smarcel	  ia64_read_reg (addr, valuep, register_size (current_gdbarch, regnum));
2043130803Smarcel	}
2044130803Smarcel    }
204598944Sobrien  else
2046130803Smarcel    {
2047130803Smarcel      /* All other registers not listed above.  */
2048130803Smarcel      CORE_ADDR addr = cache->saved_regs[regnum];
2049130803Smarcel      if (addr != 0)
2050130803Smarcel	{
2051130803Smarcel	  *lvalp = lval_memory;
2052130803Smarcel	  *addrp = addr;
2053134800Smarcel	  ia64_read_reg (addr, valuep, register_size (current_gdbarch, regnum));
2054130803Smarcel	}
2055130803Smarcel    }
2056130803Smarcel
2057130803Smarcel  if (gdbarch_debug >= 1)
2058130803Smarcel    fprintf_unfiltered (gdb_stdlog,
2059130803Smarcel			"sigtramp prev register <%s> is 0x%s\n",
2060130803Smarcel			(((unsigned) regnum <= IA64_NAT127_REGNUM)
2061130803Smarcel			 ? ia64_register_names[regnum] : "r??"),
2062130803Smarcel			paddr_nz (extract_unsigned_integer (valuep, 8)));
206398944Sobrien}
206498944Sobrien
2065130803Smarcelstatic const struct frame_unwind ia64_sigtramp_frame_unwind =
2066130803Smarcel{
2067130803Smarcel  SIGTRAMP_FRAME,
2068130803Smarcel  ia64_sigtramp_frame_this_id,
2069130803Smarcel  ia64_sigtramp_frame_prev_register
2070130803Smarcel};
207198944Sobrien
2072130803Smarcelstatic const struct frame_unwind *
2073130803Smarcelia64_sigtramp_frame_sniffer (struct frame_info *next_frame)
207498944Sobrien{
2075130803Smarcel  char *name;
2076130803Smarcel  CORE_ADDR pc = frame_pc_unwind (next_frame);
2077130803Smarcel
2078130803Smarcel  find_pc_partial_function (pc, &name, NULL, NULL);
2079130803Smarcel  if (PC_IN_SIGTRAMP (pc, name))
2080130803Smarcel    return &ia64_sigtramp_frame_unwind;
2081130803Smarcel
2082130803Smarcel  return NULL;
208398944Sobrien}
2084130803Smarcel
208598944Sobrien
2086130803Smarcelstatic CORE_ADDR
2087130803Smarcelia64_frame_base_address (struct frame_info *next_frame, void **this_cache)
208898944Sobrien{
2089130803Smarcel  struct ia64_frame_cache *cache =
2090130803Smarcel    ia64_frame_cache (next_frame, this_cache);
2091130803Smarcel
2092130803Smarcel  return cache->base;
209398944Sobrien}
209498944Sobrien
2095130803Smarcelstatic const struct frame_base ia64_frame_base =
209698944Sobrien{
2097130803Smarcel  &ia64_frame_unwind,
2098130803Smarcel  ia64_frame_base_address,
2099130803Smarcel  ia64_frame_base_address,
2100130803Smarcel  ia64_frame_base_address
2101130803Smarcel};
2102130803Smarcel
2103130803Smarcel#ifdef HAVE_LIBUNWIND_IA64_H
2104130803Smarcel
2105130803Smarcelstruct ia64_unwind_table_entry
2106130803Smarcel  {
2107130803Smarcel    unw_word_t start_offset;
2108130803Smarcel    unw_word_t end_offset;
2109130803Smarcel    unw_word_t info_offset;
2110130803Smarcel  };
2111130803Smarcel
2112130803Smarcelstatic __inline__ uint64_t
2113130803Smarcelia64_rse_slot_num (uint64_t addr)
2114130803Smarcel{
2115130803Smarcel  return (addr >> 3) & 0x3f;
211698944Sobrien}
211798944Sobrien
2118130803Smarcel/* Skip over a designated number of registers in the backing
2119130803Smarcel   store, remembering every 64th position is for NAT.  */
2120130803Smarcelstatic __inline__ uint64_t
2121130803Smarcelia64_rse_skip_regs (uint64_t addr, long num_regs)
212298944Sobrien{
2123130803Smarcel  long delta = ia64_rse_slot_num(addr) + num_regs;
2124130803Smarcel
2125130803Smarcel  if (num_regs < 0)
2126130803Smarcel    delta -= 0x3e;
2127130803Smarcel  return addr + ((num_regs + delta/0x3f) << 3);
212898944Sobrien}
2129130803Smarcel
2130130803Smarcel/* Gdb libunwind-frame callback function to convert from an ia64 gdb register
2131130803Smarcel   number to a libunwind register number.  */
2132130803Smarcelstatic int
2133130803Smarcelia64_gdb2uw_regnum (int regnum)
2134130803Smarcel{
2135130803Smarcel  if (regnum == sp_regnum)
2136130803Smarcel    return UNW_IA64_SP;
2137130803Smarcel  else if (regnum == IA64_BSP_REGNUM)
2138130803Smarcel    return UNW_IA64_BSP;
2139130803Smarcel  else if ((unsigned) (regnum - IA64_GR0_REGNUM) < 128)
2140130803Smarcel    return UNW_IA64_GR + (regnum - IA64_GR0_REGNUM);
2141130803Smarcel  else if ((unsigned) (regnum - V32_REGNUM) < 95)
2142130803Smarcel    return UNW_IA64_GR + 32 + (regnum - V32_REGNUM);
2143130803Smarcel  else if ((unsigned) (regnum - IA64_FR0_REGNUM) < 128)
2144130803Smarcel    return UNW_IA64_FR + (regnum - IA64_FR0_REGNUM);
2145130803Smarcel  else if ((unsigned) (regnum - IA64_PR0_REGNUM) < 64)
2146130803Smarcel    return -1;
2147130803Smarcel  else if ((unsigned) (regnum - IA64_BR0_REGNUM) < 8)
2148130803Smarcel    return UNW_IA64_BR + (regnum - IA64_BR0_REGNUM);
2149130803Smarcel  else if (regnum == IA64_PR_REGNUM)
2150130803Smarcel    return UNW_IA64_PR;
2151130803Smarcel  else if (regnum == IA64_IP_REGNUM)
2152130803Smarcel    return UNW_REG_IP;
2153130803Smarcel  else if (regnum == IA64_CFM_REGNUM)
2154130803Smarcel    return UNW_IA64_CFM;
2155130803Smarcel  else if ((unsigned) (regnum - IA64_AR0_REGNUM) < 128)
2156130803Smarcel    return UNW_IA64_AR + (regnum - IA64_AR0_REGNUM);
2157130803Smarcel  else if ((unsigned) (regnum - IA64_NAT0_REGNUM) < 128)
2158130803Smarcel    return UNW_IA64_NAT + (regnum - IA64_NAT0_REGNUM);
2159130803Smarcel  else
2160130803Smarcel    return -1;
2161130803Smarcel}
2162130803Smarcel
2163130803Smarcel/* Gdb libunwind-frame callback function to convert from a libunwind register
2164130803Smarcel   number to a ia64 gdb register number.  */
2165130803Smarcelstatic int
2166130803Smarcelia64_uw2gdb_regnum (int uw_regnum)
2167130803Smarcel{
2168130803Smarcel  if (uw_regnum == UNW_IA64_SP)
2169130803Smarcel    return sp_regnum;
2170130803Smarcel  else if (uw_regnum == UNW_IA64_BSP)
2171130803Smarcel    return IA64_BSP_REGNUM;
2172130803Smarcel  else if ((unsigned) (uw_regnum - UNW_IA64_GR) < 32)
2173130803Smarcel    return IA64_GR0_REGNUM + (uw_regnum - UNW_IA64_GR);
2174130803Smarcel  else if ((unsigned) (uw_regnum - UNW_IA64_GR) < 128)
2175130803Smarcel    return V32_REGNUM + (uw_regnum - (IA64_GR0_REGNUM + 32));
2176130803Smarcel  else if ((unsigned) (uw_regnum - UNW_IA64_FR) < 128)
2177130803Smarcel    return IA64_FR0_REGNUM + (uw_regnum - UNW_IA64_FR);
2178130803Smarcel  else if ((unsigned) (uw_regnum - UNW_IA64_BR) < 8)
2179130803Smarcel    return IA64_BR0_REGNUM + (uw_regnum - UNW_IA64_BR);
2180130803Smarcel  else if (uw_regnum == UNW_IA64_PR)
2181130803Smarcel    return IA64_PR_REGNUM;
2182130803Smarcel  else if (uw_regnum == UNW_REG_IP)
2183130803Smarcel    return IA64_IP_REGNUM;
2184130803Smarcel  else if (uw_regnum == UNW_IA64_CFM)
2185130803Smarcel    return IA64_CFM_REGNUM;
2186130803Smarcel  else if ((unsigned) (uw_regnum - UNW_IA64_AR) < 128)
2187130803Smarcel    return IA64_AR0_REGNUM + (uw_regnum - UNW_IA64_AR);
2188130803Smarcel  else if ((unsigned) (uw_regnum - UNW_IA64_NAT) < 128)
2189130803Smarcel    return IA64_NAT0_REGNUM + (uw_regnum - UNW_IA64_NAT);
2190130803Smarcel  else
2191130803Smarcel    return -1;
2192130803Smarcel}
219398944Sobrien
2194130803Smarcel/* Gdb libunwind-frame callback function to reveal if register is a float
2195130803Smarcel   register or not.  */
2196130803Smarcelstatic int
2197130803Smarcelia64_is_fpreg (int uw_regnum)
219898944Sobrien{
2199130803Smarcel  return unw_is_fpreg (uw_regnum);
220098944Sobrien}
2201130803Smarcel
2202130803Smarcel/* Libunwind callback accessor function for general registers.  */
2203130803Smarcelstatic int
2204130803Smarcelia64_access_reg (unw_addr_space_t as, unw_regnum_t uw_regnum, unw_word_t *val,
2205130803Smarcel		 int write, void *arg)
2206130803Smarcel{
2207130803Smarcel  int regnum = ia64_uw2gdb_regnum (uw_regnum);
2208130803Smarcel  unw_word_t bsp, sof, sol, cfm, psr, ip;
2209130803Smarcel  struct frame_info *next_frame = arg;
2210130803Smarcel  long new_sof, old_sof;
2211130803Smarcel  char buf[MAX_REGISTER_SIZE];
2212130803Smarcel
2213130803Smarcel  if (write)
2214130803Smarcel    {
2215130803Smarcel      if (regnum < 0)
2216130803Smarcel	/* ignore writes to pseudo-registers such as UNW_IA64_PROC_STARTI.  */
2217130803Smarcel	return 0;
2218130803Smarcel
2219130803Smarcel      switch (uw_regnum)
2220130803Smarcel	{
2221130803Smarcel	case UNW_REG_IP:
2222130803Smarcel	  ia64_write_pc (*val, inferior_ptid);
2223130803Smarcel	  break;
222498944Sobrien
2225130803Smarcel	case UNW_IA64_AR_BSPSTORE:
2226130803Smarcel	  write_register (IA64_BSP_REGNUM, *val);
2227130803Smarcel	  break;
2228130803Smarcel
2229130803Smarcel	case UNW_IA64_AR_BSP:
2230130803Smarcel	case UNW_IA64_BSP:
2231130803Smarcel	  /* Account for the fact that ptrace() expects bsp to point
2232130803Smarcel	     after the current register frame.  */
2233130803Smarcel	  cfm = read_register (IA64_CFM_REGNUM);
2234130803Smarcel	  sof = (cfm & 0x7f);
2235130803Smarcel	  bsp = ia64_rse_skip_regs (*val, sof);
2236130803Smarcel	  write_register (IA64_BSP_REGNUM, bsp);
2237130803Smarcel	  break;
2238130803Smarcel
2239130803Smarcel	case UNW_IA64_CFM:
2240130803Smarcel	  /* If we change CFM, we need to adjust ptrace's notion of
2241130803Smarcel	     bsp accordingly, so that the real bsp remains
2242130803Smarcel	     unchanged.  */
2243130803Smarcel	  bsp = read_register (IA64_BSP_REGNUM);
2244130803Smarcel	  cfm = read_register (IA64_CFM_REGNUM);
2245130803Smarcel	  old_sof = (cfm & 0x7f);
2246130803Smarcel	  new_sof = (*val & 0x7f);
2247130803Smarcel	  if (old_sof != new_sof)
2248130803Smarcel	    {
2249130803Smarcel	      bsp = ia64_rse_skip_regs (bsp, -old_sof + new_sof);
2250130803Smarcel	      write_register (IA64_BSP_REGNUM, bsp);
2251130803Smarcel	    }
2252130803Smarcel	  write_register (IA64_CFM_REGNUM, *val);
2253130803Smarcel	  break;
2254130803Smarcel
2255130803Smarcel	default:
2256130803Smarcel	  write_register (regnum, *val);
2257130803Smarcel	  break;
2258130803Smarcel	}
2259130803Smarcel      if (gdbarch_debug >= 1)
2260130803Smarcel	fprintf_unfiltered (gdb_stdlog,
2261130803Smarcel			    "  access_reg: to cache: %4s=0x%s\n",
2262130803Smarcel			    (((unsigned) regnum <= IA64_NAT127_REGNUM)
2263130803Smarcel			     ? ia64_register_names[regnum] : "r??"),
2264130803Smarcel			    paddr_nz (*val));
2265130803Smarcel    }
2266130803Smarcel  else
2267130803Smarcel    {
2268130803Smarcel      switch (uw_regnum)
2269130803Smarcel	{
2270130803Smarcel	case UNW_REG_IP:
2271130803Smarcel	  /* Libunwind expects to see the pc value which means the slot number
2272130803Smarcel	     from the psr must be merged with the ip word address.  */
2273130803Smarcel	  frame_unwind_register (next_frame, IA64_IP_REGNUM, buf);
2274130803Smarcel	  ip = extract_unsigned_integer (buf, 8);
2275130803Smarcel	  frame_unwind_register (next_frame, IA64_PSR_REGNUM, buf);
2276130803Smarcel	  psr = extract_unsigned_integer (buf, 8);
2277130803Smarcel	  *val = ip | ((psr >> 41) & 0x3);
2278130803Smarcel	  break;
2279130803Smarcel
2280130803Smarcel	case UNW_IA64_AR_BSP:
2281130803Smarcel	  /* Libunwind expects to see the beginning of the current register
2282130803Smarcel	     frame so we must account for the fact that ptrace() will return a value
2283130803Smarcel	     for bsp that points *after* the current register frame.  */
2284130803Smarcel	  frame_unwind_register (next_frame, IA64_BSP_REGNUM, buf);
2285130803Smarcel	  bsp = extract_unsigned_integer (buf, 8);
2286130803Smarcel	  frame_unwind_register (next_frame, IA64_CFM_REGNUM, buf);
2287130803Smarcel	  cfm = extract_unsigned_integer (buf, 8);
2288130803Smarcel	  sof = (cfm & 0x7f);
2289130803Smarcel	  *val = ia64_rse_skip_regs (bsp, -sof);
2290130803Smarcel	  break;
2291130803Smarcel
2292130803Smarcel	case UNW_IA64_AR_BSPSTORE:
2293130803Smarcel	  /* Libunwind wants bspstore to be after the current register frame.
2294130803Smarcel	     This is what ptrace() and gdb treats as the regular bsp value.  */
2295130803Smarcel	  frame_unwind_register (next_frame, IA64_BSP_REGNUM, buf);
2296130803Smarcel	  *val = extract_unsigned_integer (buf, 8);
2297130803Smarcel	  break;
2298130803Smarcel
2299130803Smarcel	default:
2300130803Smarcel	  /* For all other registers, just unwind the value directly.  */
2301130803Smarcel	  frame_unwind_register (next_frame, regnum, buf);
2302130803Smarcel	  *val = extract_unsigned_integer (buf, 8);
2303130803Smarcel	  break;
2304130803Smarcel	}
2305130803Smarcel
2306130803Smarcel      if (gdbarch_debug >= 1)
2307130803Smarcel	fprintf_unfiltered (gdb_stdlog,
2308130803Smarcel			    "  access_reg: from cache: %4s=0x%s\n",
2309130803Smarcel			    (((unsigned) regnum <= IA64_NAT127_REGNUM)
2310130803Smarcel			     ? ia64_register_names[regnum] : "r??"),
2311130803Smarcel			    paddr_nz (*val));
2312130803Smarcel    }
2313130803Smarcel  return 0;
2314130803Smarcel}
2315130803Smarcel
2316130803Smarcel/* Libunwind callback accessor function for floating-point registers.  */
2317130803Smarcelstatic int
2318130803Smarcelia64_access_fpreg (unw_addr_space_t as, unw_regnum_t uw_regnum, unw_fpreg_t *val,
2319130803Smarcel		   int write, void *arg)
232098944Sobrien{
2321130803Smarcel  int regnum = ia64_uw2gdb_regnum (uw_regnum);
2322130803Smarcel
2323130803Smarcel  if (write)
2324130803Smarcel    regcache_cooked_write (current_regcache, regnum, (char *) val);
2325130803Smarcel  else
2326130803Smarcel    regcache_cooked_read (current_regcache, regnum, (char *) val);
2327130803Smarcel  return 0;
232898944Sobrien}
232998944Sobrien
2330130803Smarcel/* Libunwind callback accessor function for accessing memory.  */
2331130803Smarcelstatic int
2332130803Smarcelia64_access_mem (unw_addr_space_t as,
2333130803Smarcel		 unw_word_t addr, unw_word_t *val,
2334130803Smarcel		 int write, void *arg)
233598944Sobrien{
2336130803Smarcel  /* XXX do we need to normalize byte-order here?  */
2337130803Smarcel  if (write)
2338130803Smarcel    return target_write_memory (addr, (char *) val, sizeof (unw_word_t));
2339130803Smarcel  else
2340130803Smarcel    return target_read_memory (addr, (char *) val, sizeof (unw_word_t));
2341130803Smarcel}
234298944Sobrien
2343130803Smarcel/* Call low-level function to access the kernel unwind table.  */
2344130803Smarcelstatic int
2345130803Smarcelgetunwind_table (void *buf, size_t len)
2346130803Smarcel{
2347130803Smarcel  LONGEST x;
2348130803Smarcel  x = target_read_partial (&current_target, TARGET_OBJECT_UNWIND_TABLE, NULL,
2349130803Smarcel			   buf, 0, len);
235098944Sobrien
2351130803Smarcel  return (int)x;
2352130803Smarcel}
2353130803Smarcel
2354130803Smarcel/* Get the kernel unwind table.  */
2355130803Smarcelstatic int
2356130803Smarcelget_kernel_table (unw_word_t ip, unw_dyn_info_t *di)
2357130803Smarcel{
2358130803Smarcel  size_t size;
2359130803Smarcel  struct ia64_table_entry
2360130803Smarcel  {
2361130803Smarcel    uint64_t start_offset;
2362130803Smarcel    uint64_t end_offset;
2363130803Smarcel    uint64_t info_offset;
2364130803Smarcel  };
2365130803Smarcel  static struct ia64_table_entry *ktab = NULL, *etab;
2366130803Smarcel
2367130803Smarcel  if (!ktab)
236898944Sobrien    {
2369130803Smarcel      size = getunwind_table (NULL, 0);
2370130803Smarcel      if ((int)size < 0)
2371130803Smarcel	return -UNW_ENOINFO;
2372130803Smarcel      ktab = xmalloc (size);
2373130803Smarcel      getunwind_table (ktab, size);
2374130803Smarcel
2375130803Smarcel      /* Determine length of kernel's unwind table and relocate
2376130803Smarcel	 it's entries.  */
2377130803Smarcel      for (etab = ktab; etab->start_offset; ++etab)
2378130803Smarcel	etab->info_offset += (uint64_t) ktab;
2379130803Smarcel    }
2380130803Smarcel
2381130803Smarcel  if (ip < ktab[0].start_offset || ip >= etab[-1].end_offset)
2382130803Smarcel    return -UNW_ENOINFO;
2383130803Smarcel
2384130803Smarcel  di->format = UNW_INFO_FORMAT_TABLE;
2385130803Smarcel  di->gp = 0;
2386130803Smarcel  di->start_ip = ktab[0].start_offset;
2387130803Smarcel  di->end_ip = etab[-1].end_offset;
2388130803Smarcel  di->u.ti.name_ptr = (unw_word_t) "<kernel>";
2389130803Smarcel  di->u.ti.segbase = 0;
2390130803Smarcel  di->u.ti.table_len = ((char *) etab - (char *) ktab) / sizeof (unw_word_t);
2391130803Smarcel  di->u.ti.table_data = (unw_word_t *) ktab;
2392130803Smarcel
2393130803Smarcel  if (gdbarch_debug >= 1)
2394130803Smarcel    fprintf_unfiltered (gdb_stdlog, "get_kernel_table: found table `%s': "
2395130803Smarcel			"segbase=0x%s, length=%s, gp=0x%s\n",
2396130803Smarcel			(char *) di->u.ti.name_ptr,
2397130803Smarcel			paddr_nz (di->u.ti.segbase),
2398130803Smarcel			paddr_u (di->u.ti.table_len),
2399130803Smarcel			paddr_nz (di->gp));
2400130803Smarcel  return 0;
2401130803Smarcel}
240298944Sobrien
2403130803Smarcel/* Find the unwind table entry for a specified address.  */
2404130803Smarcelstatic int
2405130803Smarcelia64_find_unwind_table (struct objfile *objfile, unw_word_t ip,
2406130803Smarcel			unw_dyn_info_t *dip, void **buf)
2407130803Smarcel{
2408130803Smarcel  Elf_Internal_Phdr *phdr, *p_text = NULL, *p_unwind = NULL;
2409130803Smarcel  Elf_Internal_Ehdr *ehdr;
2410130803Smarcel  unw_word_t segbase = 0;
2411130803Smarcel  CORE_ADDR load_base;
2412130803Smarcel  bfd *bfd;
2413130803Smarcel  int i;
2414130803Smarcel
2415130803Smarcel  bfd = objfile->obfd;
2416130803Smarcel
2417130803Smarcel  ehdr = elf_tdata (bfd)->elf_header;
2418130803Smarcel  phdr = elf_tdata (bfd)->phdr;
2419130803Smarcel
2420130803Smarcel  load_base = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
2421130803Smarcel
2422130803Smarcel  for (i = 0; i < ehdr->e_phnum; ++i)
242398944Sobrien    {
2424130803Smarcel      switch (phdr[i].p_type)
2425130803Smarcel	{
2426130803Smarcel	case PT_LOAD:
2427130803Smarcel	  if ((unw_word_t) (ip - load_base - phdr[i].p_vaddr)
2428130803Smarcel	      < phdr[i].p_memsz)
2429130803Smarcel	    p_text = phdr + i;
2430130803Smarcel	  break;
2431130803Smarcel
2432130803Smarcel	case PT_IA_64_UNWIND:
2433130803Smarcel	  p_unwind = phdr + i;
2434130803Smarcel	  break;
2435130803Smarcel
2436130803Smarcel	default:
2437130803Smarcel	  break;
2438130803Smarcel	}
243998944Sobrien    }
2440130803Smarcel
2441130803Smarcel  if (!p_text || !p_unwind
2442130803Smarcel      /* Verify that the segment that contains the IP also contains
2443130803Smarcel	 the static unwind table.  If not, we are dealing with
2444130803Smarcel	 runtime-generated code, for which we have no info here.  */
2445130803Smarcel      || (p_unwind->p_vaddr - p_text->p_vaddr) >= p_text->p_memsz)
2446130803Smarcel    return -UNW_ENOINFO;
2447130803Smarcel
2448130803Smarcel  segbase = p_text->p_vaddr + load_base;
2449130803Smarcel
2450130803Smarcel  dip->start_ip = segbase;
2451130803Smarcel  dip->end_ip = dip->start_ip + p_text->p_memsz;
2452130803Smarcel  dip->gp = FIND_GLOBAL_POINTER (ip);
2453130803Smarcel  dip->format = UNW_INFO_FORMAT_REMOTE_TABLE;
2454130803Smarcel  dip->u.rti.name_ptr = (unw_word_t) bfd_get_filename (bfd);
2455130803Smarcel  dip->u.rti.segbase = segbase;
2456130803Smarcel  dip->u.rti.table_len = p_unwind->p_memsz / sizeof (unw_word_t);
2457130803Smarcel  dip->u.rti.table_data = p_unwind->p_vaddr + load_base;
2458130803Smarcel
2459130803Smarcel  return 0;
2460130803Smarcel}
2461130803Smarcel
2462130803Smarcel/* Libunwind callback accessor function to acquire procedure unwind-info.  */
2463130803Smarcelstatic int
2464130803Smarcelia64_find_proc_info_x (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
2465130803Smarcel		       int need_unwind_info, void *arg)
2466130803Smarcel{
2467130803Smarcel  struct obj_section *sec = find_pc_section (ip);
2468130803Smarcel  unw_dyn_info_t di;
2469130803Smarcel  int ret;
2470130803Smarcel  void *buf = NULL;
2471130803Smarcel
2472130803Smarcel  if (!sec)
247398944Sobrien    {
2474130803Smarcel      /* XXX This only works if the host and the target architecture are
2475130803Smarcel	 both ia64 and if the have (more or less) the same kernel
2476130803Smarcel	 version.  */
2477130803Smarcel      if (get_kernel_table (ip, &di) < 0)
2478130803Smarcel	return -UNW_ENOINFO;
2479130803Smarcel
2480130803Smarcel      if (gdbarch_debug >= 1)
2481130803Smarcel	fprintf_unfiltered (gdb_stdlog, "ia64_find_proc_info_x: 0x%s -> "
2482130803Smarcel			    "(name=`%s',segbase=0x%s,start=0x%s,end=0x%s,gp=0x%s,"
2483130803Smarcel			    "length=%s,data=0x%s)\n",
2484130803Smarcel			    paddr_nz (ip), (char *)di.u.ti.name_ptr,
2485130803Smarcel			    paddr_nz (di.u.ti.segbase),
2486130803Smarcel			    paddr_nz (di.start_ip), paddr_nz (di.end_ip),
2487130803Smarcel			    paddr_nz (di.gp),
2488130803Smarcel			    paddr_u (di.u.ti.table_len),
2489130803Smarcel			    paddr_nz ((CORE_ADDR)di.u.ti.table_data));
249098944Sobrien    }
249198944Sobrien  else
249298944Sobrien    {
2493130803Smarcel      ret = ia64_find_unwind_table (sec->objfile, ip, &di, &buf);
2494130803Smarcel      if (ret < 0)
2495130803Smarcel	return ret;
249698944Sobrien
2497130803Smarcel      if (gdbarch_debug >= 1)
2498130803Smarcel	fprintf_unfiltered (gdb_stdlog, "ia64_find_proc_info_x: 0x%s -> "
2499130803Smarcel			    "(name=`%s',segbase=0x%s,start=0x%s,end=0x%s,gp=0x%s,"
2500130803Smarcel			    "length=%s,data=0x%s)\n",
2501130803Smarcel			    paddr_nz (ip), (char *)di.u.rti.name_ptr,
2502130803Smarcel			    paddr_nz (di.u.rti.segbase),
2503130803Smarcel			    paddr_nz (di.start_ip), paddr_nz (di.end_ip),
2504130803Smarcel			    paddr_nz (di.gp),
2505130803Smarcel			    paddr_u (di.u.rti.table_len),
2506130803Smarcel			    paddr_nz (di.u.rti.table_data));
2507130803Smarcel    }
250898944Sobrien
2509130803Smarcel  ret = libunwind_search_unwind_table (&as, ip, &di, pi, need_unwind_info,
2510130803Smarcel				       arg);
251198944Sobrien
2512130803Smarcel  /* We no longer need the dyn info storage so free it.  */
2513130803Smarcel  xfree (buf);
2514130803Smarcel
2515130803Smarcel  return ret;
2516130803Smarcel}
2517130803Smarcel
2518130803Smarcel/* Libunwind callback accessor function for cleanup.  */
2519130803Smarcelstatic void
2520130803Smarcelia64_put_unwind_info (unw_addr_space_t as,
2521130803Smarcel		      unw_proc_info_t *pip, void *arg)
2522130803Smarcel{
2523130803Smarcel  /* Nothing required for now.  */
2524130803Smarcel}
2525130803Smarcel
2526130803Smarcel/* Libunwind callback accessor function to get head of the dynamic
2527130803Smarcel   unwind-info registration list.  */
2528130803Smarcelstatic int
2529130803Smarcelia64_get_dyn_info_list (unw_addr_space_t as,
2530130803Smarcel			unw_word_t *dilap, void *arg)
2531130803Smarcel{
2532130803Smarcel  struct obj_section *text_sec;
2533130803Smarcel  struct objfile *objfile;
2534130803Smarcel  unw_word_t ip, addr;
2535130803Smarcel  unw_dyn_info_t di;
2536130803Smarcel  int ret;
2537130803Smarcel
2538130803Smarcel  if (!libunwind_is_initialized ())
2539130803Smarcel    return -UNW_ENOINFO;
2540130803Smarcel
2541130803Smarcel  for (objfile = object_files; objfile; objfile = objfile->next)
2542130803Smarcel    {
2543130803Smarcel      void *buf = NULL;
2544130803Smarcel
2545130803Smarcel      text_sec = objfile->sections + SECT_OFF_TEXT (objfile);
2546130803Smarcel      ip = text_sec->addr;
2547130803Smarcel      ret = ia64_find_unwind_table (objfile, ip, &di, &buf);
2548130803Smarcel      if (ret >= 0)
2549130803Smarcel	{
2550130803Smarcel	  addr = libunwind_find_dyn_list (as, &di, arg);
2551130803Smarcel	  /* We no longer need the dyn info storage so free it.  */
2552130803Smarcel	  xfree (buf);
2553130803Smarcel
2554130803Smarcel	  if (addr)
2555130803Smarcel	    {
2556130803Smarcel	      if (gdbarch_debug >= 1)
2557130803Smarcel		fprintf_unfiltered (gdb_stdlog,
2558130803Smarcel				    "dynamic unwind table in objfile %s "
2559130803Smarcel				    "at 0x%s (gp=0x%s)\n",
2560130803Smarcel				    bfd_get_filename (objfile->obfd),
2561130803Smarcel				    paddr_nz (addr), paddr_nz (di.gp));
2562130803Smarcel	      *dilap = addr;
2563130803Smarcel	      return 0;
2564130803Smarcel	    }
2565130803Smarcel	}
256698944Sobrien    }
2567130803Smarcel  return -UNW_ENOINFO;
2568130803Smarcel}
2569130803Smarcel
2570130803Smarcel
2571130803Smarcel/* Frame interface functions for libunwind.  */
2572130803Smarcel
2573130803Smarcelstatic void
2574130803Smarcelia64_libunwind_frame_this_id (struct frame_info *next_frame, void **this_cache,
2575130803Smarcel		      struct frame_id *this_id)
2576130803Smarcel{
2577130803Smarcel  char buf[8];
2578130803Smarcel  CORE_ADDR bsp;
2579130803Smarcel  struct frame_id id;
2580130803Smarcel
2581130803Smarcel  libunwind_frame_this_id (next_frame, this_cache, &id);
2582130803Smarcel
2583130803Smarcel  /* We must add the bsp as the special address for frame comparison purposes.  */
2584130803Smarcel  frame_unwind_register (next_frame, IA64_BSP_REGNUM, buf);
2585130803Smarcel  bsp = extract_unsigned_integer (buf, 8);
2586130803Smarcel
2587130803Smarcel  (*this_id) = frame_id_build_special (id.stack_addr, id.code_addr, bsp);
2588130803Smarcel
2589130803Smarcel  if (gdbarch_debug >= 1)
2590130803Smarcel    fprintf_unfiltered (gdb_stdlog,
2591130803Smarcel			"libunwind frame id: code 0x%s, stack 0x%s, special 0x%s, next_frame %p\n",
2592130803Smarcel			paddr_nz (id.code_addr), paddr_nz (id.stack_addr),
2593130803Smarcel			paddr_nz (bsp), next_frame);
2594130803Smarcel}
2595130803Smarcel
2596130803Smarcelstatic void
2597130803Smarcelia64_libunwind_frame_prev_register (struct frame_info *next_frame,
2598130803Smarcel				    void **this_cache,
2599130803Smarcel				    int regnum, int *optimizedp,
2600130803Smarcel				    enum lval_type *lvalp, CORE_ADDR *addrp,
2601130803Smarcel				    int *realnump, void *valuep)
2602130803Smarcel{
2603130803Smarcel  int reg = regnum;
2604130803Smarcel
2605130803Smarcel  if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM)
2606130803Smarcel    reg = IA64_PR_REGNUM;
2607130803Smarcel  else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM)
2608130803Smarcel    reg = IA64_UNAT_REGNUM;
2609130803Smarcel
2610130803Smarcel  /* Let libunwind do most of the work.  */
2611130803Smarcel  libunwind_frame_prev_register (next_frame, this_cache, reg,
2612130803Smarcel				 optimizedp, lvalp, addrp, realnump, valuep);
2613130803Smarcel
2614130803Smarcel  if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM)
2615130803Smarcel    {
2616130803Smarcel      ULONGEST prN_val;
2617130803Smarcel
2618130803Smarcel      if (VP16_REGNUM <= regnum && regnum <= VP63_REGNUM)
2619130803Smarcel	{
2620130803Smarcel	  int rrb_pr = 0;
2621130803Smarcel	  ULONGEST cfm;
2622130803Smarcel	  unsigned char buf[MAX_REGISTER_SIZE];
2623130803Smarcel
2624130803Smarcel	  /* Fetch predicate register rename base from current frame
2625130803Smarcel	     marker for this frame.  */
2626130803Smarcel	  frame_unwind_register (next_frame, IA64_CFM_REGNUM, buf);
2627130803Smarcel	  cfm = extract_unsigned_integer (buf, 8);
2628130803Smarcel	  rrb_pr = (cfm >> 32) & 0x3f;
2629130803Smarcel
2630130803Smarcel	  /* Adjust the register number to account for register rotation.  */
2631130803Smarcel	  regnum = VP16_REGNUM
2632130803Smarcel	    + ((regnum - VP16_REGNUM) + rrb_pr) % 48;
2633130803Smarcel	}
2634130803Smarcel      prN_val = extract_bit_field ((unsigned char *) valuep,
2635130803Smarcel				   regnum - VP0_REGNUM, 1);
2636130803Smarcel      store_unsigned_integer (valuep, register_size (current_gdbarch, regnum), prN_val);
2637130803Smarcel    }
2638130803Smarcel  else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM)
2639130803Smarcel    {
2640130803Smarcel      ULONGEST unatN_val;
2641130803Smarcel
2642130803Smarcel      unatN_val = extract_bit_field ((unsigned char *) valuep,
2643130803Smarcel                                   regnum - IA64_NAT0_REGNUM, 1);
2644130803Smarcel      store_unsigned_integer (valuep, register_size (current_gdbarch, regnum),
2645130803Smarcel                              unatN_val);
2646130803Smarcel    }
2647130803Smarcel  else if (regnum == IA64_BSP_REGNUM)
2648130803Smarcel    {
2649130803Smarcel      char cfm_valuep[MAX_REGISTER_SIZE];
2650130803Smarcel      int  cfm_optim;
2651130803Smarcel      int  cfm_realnum;
2652130803Smarcel      enum lval_type cfm_lval;
2653130803Smarcel      CORE_ADDR cfm_addr;
2654130803Smarcel      CORE_ADDR bsp, prev_cfm, prev_bsp;
2655130803Smarcel
2656130803Smarcel      /* We want to calculate the previous bsp as the end of the previous register stack frame.
2657130803Smarcel	 This corresponds to what the hardware bsp register will be if we pop the frame
2658130803Smarcel	 back which is why we might have been called.  We know that libunwind will pass us back
2659130803Smarcel	 the beginning of the current frame so we should just add sof to it. */
2660130803Smarcel      prev_bsp = extract_unsigned_integer (valuep, 8);
2661130803Smarcel      libunwind_frame_prev_register (next_frame, this_cache, IA64_CFM_REGNUM,
2662130803Smarcel				     &cfm_optim, &cfm_lval, &cfm_addr, &cfm_realnum, cfm_valuep);
2663130803Smarcel      prev_cfm = extract_unsigned_integer (cfm_valuep, 8);
2664130803Smarcel      prev_bsp = rse_address_add (prev_bsp, (prev_cfm & 0x7f));
2665130803Smarcel
2666130803Smarcel      store_unsigned_integer (valuep, register_size (current_gdbarch, regnum),
2667130803Smarcel			      prev_bsp);
2668130803Smarcel    }
2669130803Smarcel
2670130803Smarcel  if (gdbarch_debug >= 1)
2671130803Smarcel    fprintf_unfiltered (gdb_stdlog,
2672130803Smarcel			"libunwind prev register <%s> is 0x%s\n",
2673130803Smarcel			(((unsigned) regnum <= IA64_NAT127_REGNUM)
2674130803Smarcel			 ? ia64_register_names[regnum] : "r??"),
2675130803Smarcel			paddr_nz (extract_unsigned_integer (valuep, 8)));
2676130803Smarcel}
2677130803Smarcel
2678130803Smarcelstatic const struct frame_unwind ia64_libunwind_frame_unwind =
2679130803Smarcel{
2680130803Smarcel  NORMAL_FRAME,
2681130803Smarcel  ia64_libunwind_frame_this_id,
2682130803Smarcel  ia64_libunwind_frame_prev_register
2683130803Smarcel};
2684130803Smarcel
2685130803Smarcelstatic const struct frame_unwind *
2686130803Smarcelia64_libunwind_frame_sniffer (struct frame_info *next_frame)
2687130803Smarcel{
2688130803Smarcel  if (libunwind_is_initialized () && libunwind_frame_sniffer (next_frame))
2689130803Smarcel    return &ia64_libunwind_frame_unwind;
2690130803Smarcel
2691130803Smarcel  return NULL;
2692130803Smarcel}
2693130803Smarcel
2694130803Smarcel/* Set of libunwind callback acccessor functions.  */
2695130803Smarcelstatic unw_accessors_t ia64_unw_accessors =
2696130803Smarcel{
2697130803Smarcel  ia64_find_proc_info_x,
2698130803Smarcel  ia64_put_unwind_info,
2699130803Smarcel  ia64_get_dyn_info_list,
2700130803Smarcel  ia64_access_mem,
2701130803Smarcel  ia64_access_reg,
2702130803Smarcel  ia64_access_fpreg,
2703130803Smarcel  /* resume */
2704130803Smarcel  /* get_proc_name */
2705130803Smarcel};
2706130803Smarcel
2707130803Smarcel/* Set of ia64 gdb libunwind-frame callbacks and data for generic libunwind-frame code to use.  */
2708130803Smarcelstatic struct libunwind_descr ia64_libunwind_descr =
2709130803Smarcel{
2710130803Smarcel  ia64_gdb2uw_regnum,
2711130803Smarcel  ia64_uw2gdb_regnum,
2712130803Smarcel  ia64_is_fpreg,
2713130803Smarcel  &ia64_unw_accessors,
2714130803Smarcel};
2715130803Smarcel
2716130803Smarcel#endif /* HAVE_LIBUNWIND_IA64_H  */
2717130803Smarcel
2718130803Smarcel/* Should we use DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS instead of
2719130803Smarcel   EXTRACT_RETURN_VALUE?  GCC_P is true if compiled with gcc and TYPE
2720130803Smarcel   is the type (which is known to be struct, union or array).  */
2721130803Smarcelint
2722130803Smarcelia64_use_struct_convention (int gcc_p, struct type *type)
2723130803Smarcel{
2724130803Smarcel  struct type *float_elt_type;
2725130803Smarcel
2726130803Smarcel  /* HFAs are structures (or arrays) consisting entirely of floating
2727130803Smarcel     point values of the same length.  Up to 8 of these are returned
2728130803Smarcel     in registers.  Don't use the struct convention when this is the
2729130803Smarcel     case.  */
2730130803Smarcel  float_elt_type = is_float_or_hfa_type (type);
2731130803Smarcel  if (float_elt_type != NULL
2732130803Smarcel      && TYPE_LENGTH (type) / TYPE_LENGTH (float_elt_type) <= 8)
2733130803Smarcel    return 0;
2734130803Smarcel
2735130803Smarcel  /* Other structs of length 32 or less are returned in r8-r11.
2736130803Smarcel     Don't use the struct convention for those either.  */
2737130803Smarcel  return TYPE_LENGTH (type) > 32;
2738130803Smarcel}
2739130803Smarcel
2740130803Smarcelvoid
2741130803Smarcelia64_extract_return_value (struct type *type, struct regcache *regcache, void *valbuf)
2742130803Smarcel{
2743130803Smarcel  struct type *float_elt_type;
2744130803Smarcel
2745130803Smarcel  float_elt_type = is_float_or_hfa_type (type);
2746130803Smarcel  if (float_elt_type != NULL)
2747130803Smarcel    {
2748130803Smarcel      char from[MAX_REGISTER_SIZE];
2749130803Smarcel      int offset = 0;
2750130803Smarcel      int regnum = IA64_FR8_REGNUM;
2751130803Smarcel      int n = TYPE_LENGTH (type) / TYPE_LENGTH (float_elt_type);
2752130803Smarcel
2753130803Smarcel      while (n-- > 0)
2754130803Smarcel	{
2755130803Smarcel	  regcache_cooked_read (regcache, regnum, from);
2756130803Smarcel	  convert_typed_floating (from, builtin_type_ia64_ext,
2757130803Smarcel				  (char *)valbuf + offset, float_elt_type);
2758130803Smarcel	  offset += TYPE_LENGTH (float_elt_type);
2759130803Smarcel	  regnum++;
2760130803Smarcel	}
2761130803Smarcel    }
276298944Sobrien  else
2763130803Smarcel    {
2764130803Smarcel      ULONGEST val;
2765130803Smarcel      int offset = 0;
2766130803Smarcel      int regnum = IA64_GR8_REGNUM;
2767130803Smarcel      int reglen = TYPE_LENGTH (ia64_register_type (NULL, IA64_GR8_REGNUM));
2768130803Smarcel      int n = TYPE_LENGTH (type) / reglen;
2769130803Smarcel      int m = TYPE_LENGTH (type) % reglen;
277098944Sobrien
2771130803Smarcel      while (n-- > 0)
2772130803Smarcel	{
2773130803Smarcel	  ULONGEST val;
2774130803Smarcel	  regcache_cooked_read_unsigned (regcache, regnum, &val);
2775130803Smarcel	  memcpy ((char *)valbuf + offset, &val, reglen);
2776130803Smarcel	  offset += reglen;
2777130803Smarcel	  regnum++;
2778130803Smarcel	}
2779130803Smarcel
2780130803Smarcel      if (m)
2781130803Smarcel	{
2782130803Smarcel          regcache_cooked_read_unsigned (regcache, regnum, &val);
2783130803Smarcel	  memcpy ((char *)valbuf + offset, &val, m);
2784130803Smarcel	}
2785130803Smarcel    }
278698944Sobrien}
278798944Sobrien
2788130803SmarcelCORE_ADDR
2789130803Smarcelia64_extract_struct_value_address (struct regcache *regcache)
2790130803Smarcel{
2791130803Smarcel  error ("ia64_extract_struct_value_address called and cannot get struct value address");
2792130803Smarcel  return 0;
2793130803Smarcel}
2794130803Smarcel
2795130803Smarcel
279698944Sobrienstatic int
279798944Sobrienis_float_or_hfa_type_recurse (struct type *t, struct type **etp)
279898944Sobrien{
279998944Sobrien  switch (TYPE_CODE (t))
280098944Sobrien    {
280198944Sobrien    case TYPE_CODE_FLT:
280298944Sobrien      if (*etp)
280398944Sobrien	return TYPE_LENGTH (*etp) == TYPE_LENGTH (t);
280498944Sobrien      else
280598944Sobrien	{
280698944Sobrien	  *etp = t;
280798944Sobrien	  return 1;
280898944Sobrien	}
280998944Sobrien      break;
281098944Sobrien    case TYPE_CODE_ARRAY:
281198944Sobrien      return
281298944Sobrien	is_float_or_hfa_type_recurse (check_typedef (TYPE_TARGET_TYPE (t)),
281398944Sobrien				      etp);
281498944Sobrien      break;
281598944Sobrien    case TYPE_CODE_STRUCT:
281698944Sobrien      {
281798944Sobrien	int i;
281898944Sobrien
281998944Sobrien	for (i = 0; i < TYPE_NFIELDS (t); i++)
282098944Sobrien	  if (!is_float_or_hfa_type_recurse
282198944Sobrien	      (check_typedef (TYPE_FIELD_TYPE (t, i)), etp))
282298944Sobrien	    return 0;
282398944Sobrien	return 1;
282498944Sobrien      }
282598944Sobrien      break;
282698944Sobrien    default:
282798944Sobrien      return 0;
282898944Sobrien      break;
282998944Sobrien    }
283098944Sobrien}
283198944Sobrien
283298944Sobrien/* Determine if the given type is one of the floating point types or
283398944Sobrien   and HFA (which is a struct, array, or combination thereof whose
2834130803Smarcel   bottom-most elements are all of the same floating point type).  */
283598944Sobrien
283698944Sobrienstatic struct type *
283798944Sobrienis_float_or_hfa_type (struct type *t)
283898944Sobrien{
283998944Sobrien  struct type *et = 0;
284098944Sobrien
284198944Sobrien  return is_float_or_hfa_type_recurse (t, &et) ? et : 0;
284298944Sobrien}
284398944Sobrien
284498944Sobrien
284598944Sobrien/* Return 1 if the alignment of T is such that the next even slot
284698944Sobrien   should be used.  Return 0, if the next available slot should
284798944Sobrien   be used.  (See section 8.5.1 of the IA-64 Software Conventions
2848130803Smarcel   and Runtime manual).  */
284998944Sobrien
285098944Sobrienstatic int
285198944Sobrienslot_alignment_is_next_even (struct type *t)
285298944Sobrien{
285398944Sobrien  switch (TYPE_CODE (t))
285498944Sobrien    {
285598944Sobrien    case TYPE_CODE_INT:
285698944Sobrien    case TYPE_CODE_FLT:
285798944Sobrien      if (TYPE_LENGTH (t) > 8)
285898944Sobrien	return 1;
285998944Sobrien      else
286098944Sobrien	return 0;
286198944Sobrien    case TYPE_CODE_ARRAY:
286298944Sobrien      return
286398944Sobrien	slot_alignment_is_next_even (check_typedef (TYPE_TARGET_TYPE (t)));
286498944Sobrien    case TYPE_CODE_STRUCT:
286598944Sobrien      {
286698944Sobrien	int i;
286798944Sobrien
286898944Sobrien	for (i = 0; i < TYPE_NFIELDS (t); i++)
286998944Sobrien	  if (slot_alignment_is_next_even
287098944Sobrien	      (check_typedef (TYPE_FIELD_TYPE (t, i))))
287198944Sobrien	    return 1;
287298944Sobrien	return 0;
287398944Sobrien      }
287498944Sobrien    default:
287598944Sobrien      return 0;
287698944Sobrien    }
287798944Sobrien}
287898944Sobrien
287998944Sobrien/* Attempt to find (and return) the global pointer for the given
288098944Sobrien   function.
288198944Sobrien
288298944Sobrien   This is a rather nasty bit of code searchs for the .dynamic section
288398944Sobrien   in the objfile corresponding to the pc of the function we're trying
288498944Sobrien   to call.  Once it finds the addresses at which the .dynamic section
288598944Sobrien   lives in the child process, it scans the Elf64_Dyn entries for a
288698944Sobrien   DT_PLTGOT tag.  If it finds one of these, the corresponding
288798944Sobrien   d_un.d_ptr value is the global pointer.  */
288898944Sobrien
2889131082SmarcelCORE_ADDR
2890131082Smarcelia64_generic_find_global_pointer (CORE_ADDR faddr)
289198944Sobrien{
289298944Sobrien  struct obj_section *faddr_sect;
289398944Sobrien
289498944Sobrien  faddr_sect = find_pc_section (faddr);
289598944Sobrien  if (faddr_sect != NULL)
289698944Sobrien    {
289798944Sobrien      struct obj_section *osect;
289898944Sobrien
289998944Sobrien      ALL_OBJFILE_OSECTIONS (faddr_sect->objfile, osect)
290098944Sobrien	{
290198944Sobrien	  if (strcmp (osect->the_bfd_section->name, ".dynamic") == 0)
290298944Sobrien	    break;
290398944Sobrien	}
290498944Sobrien
290598944Sobrien      if (osect < faddr_sect->objfile->sections_end)
290698944Sobrien	{
290798944Sobrien	  CORE_ADDR addr;
290898944Sobrien
290998944Sobrien	  addr = osect->addr;
291098944Sobrien	  while (addr < osect->endaddr)
291198944Sobrien	    {
291298944Sobrien	      int status;
291398944Sobrien	      LONGEST tag;
291498944Sobrien	      char buf[8];
291598944Sobrien
291698944Sobrien	      status = target_read_memory (addr, buf, sizeof (buf));
291798944Sobrien	      if (status != 0)
291898944Sobrien		break;
291998944Sobrien	      tag = extract_signed_integer (buf, sizeof (buf));
292098944Sobrien
292198944Sobrien	      if (tag == DT_PLTGOT)
292298944Sobrien		{
292398944Sobrien		  CORE_ADDR global_pointer;
292498944Sobrien
292598944Sobrien		  status = target_read_memory (addr + 8, buf, sizeof (buf));
292698944Sobrien		  if (status != 0)
292798944Sobrien		    break;
2928130803Smarcel		  global_pointer = extract_unsigned_integer (buf, sizeof (buf));
292998944Sobrien
293098944Sobrien		  /* The payoff... */
293198944Sobrien		  return global_pointer;
293298944Sobrien		}
293398944Sobrien
293498944Sobrien	      if (tag == DT_NULL)
293598944Sobrien		break;
293698944Sobrien
293798944Sobrien	      addr += 16;
293898944Sobrien	    }
293998944Sobrien	}
294098944Sobrien    }
294198944Sobrien  return 0;
294298944Sobrien}
294398944Sobrien
294498944Sobrien/* Given a function's address, attempt to find (and return) the
294598944Sobrien   corresponding (canonical) function descriptor.  Return 0 if
2946130803Smarcel   not found.  */
294798944Sobrienstatic CORE_ADDR
294898944Sobrienfind_extant_func_descr (CORE_ADDR faddr)
294998944Sobrien{
295098944Sobrien  struct obj_section *faddr_sect;
295198944Sobrien
2952130803Smarcel  /* Return early if faddr is already a function descriptor.  */
295398944Sobrien  faddr_sect = find_pc_section (faddr);
295498944Sobrien  if (faddr_sect && strcmp (faddr_sect->the_bfd_section->name, ".opd") == 0)
295598944Sobrien    return faddr;
295698944Sobrien
295798944Sobrien  if (faddr_sect != NULL)
295898944Sobrien    {
295998944Sobrien      struct obj_section *osect;
296098944Sobrien      ALL_OBJFILE_OSECTIONS (faddr_sect->objfile, osect)
296198944Sobrien	{
296298944Sobrien	  if (strcmp (osect->the_bfd_section->name, ".opd") == 0)
296398944Sobrien	    break;
296498944Sobrien	}
296598944Sobrien
296698944Sobrien      if (osect < faddr_sect->objfile->sections_end)
296798944Sobrien	{
296898944Sobrien	  CORE_ADDR addr;
296998944Sobrien
297098944Sobrien	  addr = osect->addr;
297198944Sobrien	  while (addr < osect->endaddr)
297298944Sobrien	    {
297398944Sobrien	      int status;
297498944Sobrien	      LONGEST faddr2;
297598944Sobrien	      char buf[8];
297698944Sobrien
297798944Sobrien	      status = target_read_memory (addr, buf, sizeof (buf));
297898944Sobrien	      if (status != 0)
297998944Sobrien		break;
298098944Sobrien	      faddr2 = extract_signed_integer (buf, sizeof (buf));
298198944Sobrien
298298944Sobrien	      if (faddr == faddr2)
298398944Sobrien		return addr;
298498944Sobrien
298598944Sobrien	      addr += 16;
298698944Sobrien	    }
298798944Sobrien	}
298898944Sobrien    }
298998944Sobrien  return 0;
299098944Sobrien}
299198944Sobrien
299298944Sobrien/* Attempt to find a function descriptor corresponding to the
299398944Sobrien   given address.  If none is found, construct one on the
2994130803Smarcel   stack using the address at fdaptr.  */
299598944Sobrien
299698944Sobrienstatic CORE_ADDR
299798944Sobrienfind_func_descr (CORE_ADDR faddr, CORE_ADDR *fdaptr)
299898944Sobrien{
299998944Sobrien  CORE_ADDR fdesc;
300098944Sobrien
300198944Sobrien  fdesc = find_extant_func_descr (faddr);
300298944Sobrien
300398944Sobrien  if (fdesc == 0)
300498944Sobrien    {
300598944Sobrien      CORE_ADDR global_pointer;
300698944Sobrien      char buf[16];
300798944Sobrien
300898944Sobrien      fdesc = *fdaptr;
300998944Sobrien      *fdaptr += 16;
301098944Sobrien
301198944Sobrien      global_pointer = FIND_GLOBAL_POINTER (faddr);
301298944Sobrien
301398944Sobrien      if (global_pointer == 0)
301498944Sobrien	global_pointer = read_register (IA64_GR1_REGNUM);
301598944Sobrien
3016130803Smarcel      store_unsigned_integer (buf, 8, faddr);
3017130803Smarcel      store_unsigned_integer (buf + 8, 8, global_pointer);
301898944Sobrien
301998944Sobrien      write_memory (fdesc, buf, 16);
302098944Sobrien    }
302198944Sobrien
302298944Sobrien  return fdesc;
302398944Sobrien}
302498944Sobrien
3025130803Smarcel/* Use the following routine when printing out function pointers
3026130803Smarcel   so the user can see the function address rather than just the
3027130803Smarcel   function descriptor.  */
3028130803Smarcelstatic CORE_ADDR
3029130803Smarcelia64_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr,
3030130803Smarcel				 struct target_ops *targ)
303198944Sobrien{
3032130803Smarcel  struct obj_section *s;
3033130803Smarcel
3034130803Smarcel  s = find_pc_section (addr);
3035130803Smarcel
3036130803Smarcel  /* check if ADDR points to a function descriptor.  */
3037130803Smarcel  if (s && strcmp (s->the_bfd_section->name, ".opd") == 0)
3038130803Smarcel    return read_memory_unsigned_integer (addr, 8);
3039130803Smarcel
3040130803Smarcel  return addr;
3041130803Smarcel}
3042130803Smarcel
3043130803Smarcelstatic CORE_ADDR
3044130803Smarcelia64_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
3045130803Smarcel{
3046130803Smarcel  return sp & ~0xfLL;
3047130803Smarcel}
3048130803Smarcel
3049130803Smarcelstatic CORE_ADDR
3050130803Smarcelia64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
3051130803Smarcel		      struct regcache *regcache, CORE_ADDR bp_addr,
3052130803Smarcel		      int nargs, struct value **args, CORE_ADDR sp,
3053130803Smarcel		      int struct_return, CORE_ADDR struct_addr)
3054130803Smarcel{
305598944Sobrien  int argno;
305698944Sobrien  struct value *arg;
305798944Sobrien  struct type *type;
305898944Sobrien  int len, argoffset;
305998944Sobrien  int nslots, rseslots, memslots, slotnum, nfuncargs;
306098944Sobrien  int floatreg;
3061130803Smarcel  CORE_ADDR bsp, cfm, pfs, new_bsp, funcdescaddr, pc, global_pointer;
306298944Sobrien
306398944Sobrien  nslots = 0;
306498944Sobrien  nfuncargs = 0;
3065130803Smarcel  /* Count the number of slots needed for the arguments.  */
306698944Sobrien  for (argno = 0; argno < nargs; argno++)
306798944Sobrien    {
306898944Sobrien      arg = args[argno];
306998944Sobrien      type = check_typedef (VALUE_TYPE (arg));
307098944Sobrien      len = TYPE_LENGTH (type);
307198944Sobrien
307298944Sobrien      if ((nslots & 1) && slot_alignment_is_next_even (type))
307398944Sobrien	nslots++;
307498944Sobrien
307598944Sobrien      if (TYPE_CODE (type) == TYPE_CODE_FUNC)
307698944Sobrien	nfuncargs++;
307798944Sobrien
307898944Sobrien      nslots += (len + 7) / 8;
307998944Sobrien    }
308098944Sobrien
3081130803Smarcel  /* Divvy up the slots between the RSE and the memory stack.  */
308298944Sobrien  rseslots = (nslots > 8) ? 8 : nslots;
308398944Sobrien  memslots = nslots - rseslots;
308498944Sobrien
3085130803Smarcel  /* Allocate a new RSE frame.  */
308698944Sobrien  cfm = read_register (IA64_CFM_REGNUM);
308798944Sobrien
308898944Sobrien  bsp = read_register (IA64_BSP_REGNUM);
308998944Sobrien  new_bsp = rse_address_add (bsp, rseslots);
309098944Sobrien  write_register (IA64_BSP_REGNUM, new_bsp);
309198944Sobrien
309298944Sobrien  pfs = read_register (IA64_PFS_REGNUM);
309398944Sobrien  pfs &= 0xc000000000000000LL;
309498944Sobrien  pfs |= (cfm & 0xffffffffffffLL);
309598944Sobrien  write_register (IA64_PFS_REGNUM, pfs);
309698944Sobrien
309798944Sobrien  cfm &= 0xc000000000000000LL;
309898944Sobrien  cfm |= rseslots;
309998944Sobrien  write_register (IA64_CFM_REGNUM, cfm);
310098944Sobrien
310198944Sobrien  /* We will attempt to find function descriptors in the .opd segment,
310298944Sobrien     but if we can't we'll construct them ourselves.  That being the
3103130803Smarcel     case, we'll need to reserve space on the stack for them.  */
310498944Sobrien  funcdescaddr = sp - nfuncargs * 16;
310598944Sobrien  funcdescaddr &= ~0xfLL;
310698944Sobrien
310798944Sobrien  /* Adjust the stack pointer to it's new value.  The calling conventions
310898944Sobrien     require us to have 16 bytes of scratch, plus whatever space is
3109130803Smarcel     necessary for the memory slots and our function descriptors.  */
311098944Sobrien  sp = sp - 16 - (memslots + nfuncargs) * 8;
3111130803Smarcel  sp &= ~0xfLL;				/* Maintain 16 byte alignment.  */
311298944Sobrien
311398944Sobrien  /* Place the arguments where they belong.  The arguments will be
311498944Sobrien     either placed in the RSE backing store or on the memory stack.
311598944Sobrien     In addition, floating point arguments or HFAs are placed in
3116130803Smarcel     floating point registers.  */
311798944Sobrien  slotnum = 0;
311898944Sobrien  floatreg = IA64_FR8_REGNUM;
311998944Sobrien  for (argno = 0; argno < nargs; argno++)
312098944Sobrien    {
312198944Sobrien      struct type *float_elt_type;
312298944Sobrien
312398944Sobrien      arg = args[argno];
312498944Sobrien      type = check_typedef (VALUE_TYPE (arg));
312598944Sobrien      len = TYPE_LENGTH (type);
312698944Sobrien
3127130803Smarcel      /* Special handling for function parameters.  */
312898944Sobrien      if (len == 8
312998944Sobrien          && TYPE_CODE (type) == TYPE_CODE_PTR
313098944Sobrien	  && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC)
313198944Sobrien	{
313298944Sobrien	  char val_buf[8];
313398944Sobrien
3134130803Smarcel	  store_unsigned_integer (val_buf, 8,
3135130803Smarcel				  find_func_descr (extract_unsigned_integer (VALUE_CONTENTS (arg), 8),
3136130803Smarcel						   &funcdescaddr));
313798944Sobrien	  if (slotnum < rseslots)
313898944Sobrien	    write_memory (rse_address_add (bsp, slotnum), val_buf, 8);
313998944Sobrien	  else
314098944Sobrien	    write_memory (sp + 16 + 8 * (slotnum - rseslots), val_buf, 8);
314198944Sobrien	  slotnum++;
314298944Sobrien	  continue;
314398944Sobrien	}
314498944Sobrien
3145130803Smarcel      /* Normal slots.  */
314698944Sobrien
314798944Sobrien      /* Skip odd slot if necessary...  */
314898944Sobrien      if ((slotnum & 1) && slot_alignment_is_next_even (type))
314998944Sobrien	slotnum++;
315098944Sobrien
315198944Sobrien      argoffset = 0;
315298944Sobrien      while (len > 0)
315398944Sobrien	{
315498944Sobrien	  char val_buf[8];
315598944Sobrien
315698944Sobrien	  memset (val_buf, 0, 8);
315798944Sobrien	  memcpy (val_buf, VALUE_CONTENTS (arg) + argoffset, (len > 8) ? 8 : len);
315898944Sobrien
315998944Sobrien	  if (slotnum < rseslots)
316098944Sobrien	    write_memory (rse_address_add (bsp, slotnum), val_buf, 8);
316198944Sobrien	  else
316298944Sobrien	    write_memory (sp + 16 + 8 * (slotnum - rseslots), val_buf, 8);
316398944Sobrien
316498944Sobrien	  argoffset += 8;
316598944Sobrien	  len -= 8;
316698944Sobrien	  slotnum++;
316798944Sobrien	}
316898944Sobrien
3169130803Smarcel      /* Handle floating point types (including HFAs).  */
317098944Sobrien      float_elt_type = is_float_or_hfa_type (type);
317198944Sobrien      if (float_elt_type != NULL)
317298944Sobrien	{
317398944Sobrien	  argoffset = 0;
317498944Sobrien	  len = TYPE_LENGTH (type);
317598944Sobrien	  while (len > 0 && floatreg < IA64_FR16_REGNUM)
317698944Sobrien	    {
3177130803Smarcel	      char to[MAX_REGISTER_SIZE];
3178130803Smarcel	      convert_typed_floating (VALUE_CONTENTS (arg) + argoffset, float_elt_type,
3179130803Smarcel				      to, builtin_type_ia64_ext);
3180130803Smarcel	      regcache_cooked_write (regcache, floatreg, (void *)to);
318198944Sobrien	      floatreg++;
318298944Sobrien	      argoffset += TYPE_LENGTH (float_elt_type);
318398944Sobrien	      len -= TYPE_LENGTH (float_elt_type);
318498944Sobrien	    }
318598944Sobrien	}
318698944Sobrien    }
318798944Sobrien
3188130803Smarcel  /* Store the struct return value in r8 if necessary.  */
318998944Sobrien  if (struct_return)
319098944Sobrien    {
3191130803Smarcel      regcache_cooked_write_unsigned (regcache, IA64_GR8_REGNUM, (ULONGEST)struct_addr);
319298944Sobrien    }
319398944Sobrien
3194130803Smarcel  global_pointer = FIND_GLOBAL_POINTER (func_addr);
319598944Sobrien
3196130803Smarcel  if (global_pointer != 0)
3197130803Smarcel    write_register (IA64_GR1_REGNUM, global_pointer);
319898944Sobrien
3199130803Smarcel  write_register (IA64_BR0_REGNUM, bp_addr);
320098944Sobrien
3201130803Smarcel  write_register (sp_regnum, sp);
320298944Sobrien
320398944Sobrien  return sp;
320498944Sobrien}
320598944Sobrien
3206130803Smarcelstatic struct frame_id
3207130803Smarcelia64_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
320898944Sobrien{
3209130803Smarcel  char buf[8];
3210130803Smarcel  CORE_ADDR sp, bsp;
321198944Sobrien
3212130803Smarcel  frame_unwind_register (next_frame, sp_regnum, buf);
3213130803Smarcel  sp = extract_unsigned_integer (buf, 8);
321498944Sobrien
3215130803Smarcel  frame_unwind_register (next_frame, IA64_BSP_REGNUM, buf);
3216130803Smarcel  bsp = extract_unsigned_integer (buf, 8);
3217130803Smarcel
3218130803Smarcel  if (gdbarch_debug >= 1)
3219130803Smarcel    fprintf_unfiltered (gdb_stdlog,
3220130803Smarcel			"dummy frame id: code 0x%s, stack 0x%s, special 0x%s\n",
3221130803Smarcel			paddr_nz (frame_pc_unwind (next_frame)),
3222130803Smarcel			paddr_nz (sp), paddr_nz (bsp));
3223130803Smarcel
3224130803Smarcel  return frame_id_build_special (sp, frame_pc_unwind (next_frame), bsp);
322598944Sobrien}
322698944Sobrien
3227130803Smarcelstatic CORE_ADDR
3228130803Smarcelia64_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
322998944Sobrien{
3230130803Smarcel  char buf[8];
3231130803Smarcel  CORE_ADDR ip, psr, pc;
323298944Sobrien
3233130803Smarcel  frame_unwind_register (next_frame, IA64_IP_REGNUM, buf);
3234130803Smarcel  ip = extract_unsigned_integer (buf, 8);
3235130803Smarcel  frame_unwind_register (next_frame, IA64_PSR_REGNUM, buf);
3236130803Smarcel  psr = extract_unsigned_integer (buf, 8);
3237130803Smarcel
3238130803Smarcel  pc = (ip & ~0xf) | ((psr >> 41) & 3);
3239130803Smarcel  return pc;
324098944Sobrien}
324198944Sobrien
324298944Sobrienstatic void
3243130803Smarcelia64_store_return_value (struct type *type, struct regcache *regcache, const void *valbuf)
324498944Sobrien{
3245130803Smarcel  if (TYPE_CODE (type) == TYPE_CODE_FLT)
324698944Sobrien    {
3247130803Smarcel      char to[MAX_REGISTER_SIZE];
3248130803Smarcel      convert_typed_floating (valbuf, type, to, builtin_type_ia64_ext);
3249130803Smarcel      regcache_cooked_write (regcache, IA64_FR8_REGNUM, (void *)to);
3250130803Smarcel      target_store_registers (IA64_FR8_REGNUM);
325198944Sobrien    }
325298944Sobrien  else
3253130803Smarcel    regcache_cooked_write (regcache, IA64_GR8_REGNUM, valbuf);
325498944Sobrien}
325598944Sobrien
325698944Sobrienstatic void
3257130803Smarcelia64_remote_translate_xfer_address (struct gdbarch *gdbarch,
3258130803Smarcel				    struct regcache *regcache,
3259130803Smarcel				    CORE_ADDR memaddr, int nr_bytes,
326098944Sobrien				    CORE_ADDR *targ_addr, int *targ_len)
326198944Sobrien{
326298944Sobrien  *targ_addr = memaddr;
326398944Sobrien  *targ_len  = nr_bytes;
326498944Sobrien}
326598944Sobrien
3266130803Smarcelstatic int
3267130803Smarcelia64_print_insn (bfd_vma memaddr, struct disassemble_info *info)
326898944Sobrien{
3269130803Smarcel  info->bytes_per_line = SLOT_MULTIPLIER;
3270130803Smarcel  return print_insn_ia64 (memaddr, info);
327198944Sobrien}
327298944Sobrien
327398944Sobrienstatic struct gdbarch *
327498944Sobrienia64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
327598944Sobrien{
327698944Sobrien  struct gdbarch *gdbarch;
327798944Sobrien  struct gdbarch_tdep *tdep;
327898944Sobrien
3279130803Smarcel  /* If there is already a candidate, use it.  */
3280130803Smarcel  arches = gdbarch_list_lookup_by_info (arches, &info);
3281130803Smarcel  if (arches != NULL)
3282130803Smarcel    return arches->gdbarch;
328398944Sobrien
328498944Sobrien  tdep = xmalloc (sizeof (struct gdbarch_tdep));
328598944Sobrien  gdbarch = gdbarch_alloc (&info, tdep);
3286131082Smarcel  tdep->osabi = info.osabi;
3287131082Smarcel  tdep->sigcontext_register_address = NULL;
3288131082Smarcel  tdep->find_global_pointer = ia64_generic_find_global_pointer;
328998944Sobrien
3290130803Smarcel  /* Define the ia64 floating-point format to gdb.  */
3291130803Smarcel  builtin_type_ia64_ext =
3292130803Smarcel    init_type (TYPE_CODE_FLT, 128 / 8,
3293130803Smarcel               0, "builtin_type_ia64_ext", NULL);
3294130803Smarcel  TYPE_FLOATFORMAT (builtin_type_ia64_ext) = &floatformat_ia64_ext;
3295130803Smarcel
3296130803Smarcel  /* According to the ia64 specs, instructions that store long double
3297130803Smarcel     floats in memory use a long-double format different than that
3298130803Smarcel     used in the floating registers.  The memory format matches the
3299130803Smarcel     x86 extended float format which is 80 bits.  An OS may choose to
3300130803Smarcel     use this format (e.g. GNU/Linux) or choose to use a different
3301130803Smarcel     format for storing long doubles (e.g. HPUX).  In the latter case,
3302130803Smarcel     the setting of the format may be moved/overridden in an
3303130803Smarcel     OS-specific tdep file.  */
3304130803Smarcel  set_gdbarch_long_double_format (gdbarch, &floatformat_i387_ext);
3305130803Smarcel
330698944Sobrien  set_gdbarch_short_bit (gdbarch, 16);
330798944Sobrien  set_gdbarch_int_bit (gdbarch, 32);
330898944Sobrien  set_gdbarch_long_bit (gdbarch, 64);
330998944Sobrien  set_gdbarch_long_long_bit (gdbarch, 64);
331098944Sobrien  set_gdbarch_float_bit (gdbarch, 32);
331198944Sobrien  set_gdbarch_double_bit (gdbarch, 64);
3312130803Smarcel  set_gdbarch_long_double_bit (gdbarch, 128);
331398944Sobrien  set_gdbarch_ptr_bit (gdbarch, 64);
331498944Sobrien
3315130803Smarcel  set_gdbarch_num_regs (gdbarch, NUM_IA64_RAW_REGS);
3316130803Smarcel  set_gdbarch_num_pseudo_regs (gdbarch, LAST_PSEUDO_REGNUM - FIRST_PSEUDO_REGNUM);
331798944Sobrien  set_gdbarch_sp_regnum (gdbarch, sp_regnum);
331898944Sobrien  set_gdbarch_fp0_regnum (gdbarch, IA64_FR0_REGNUM);
331998944Sobrien
332098944Sobrien  set_gdbarch_register_name (gdbarch, ia64_register_name);
3321130803Smarcel  /* FIXME:  Following interface should not be needed, however, without it recurse.exp
3322130803Smarcel     gets a number of extra failures.  */
3323130803Smarcel  set_gdbarch_deprecated_register_size (gdbarch, 8);
3324130803Smarcel  set_gdbarch_register_type (gdbarch, ia64_register_type);
332598944Sobrien
3326130803Smarcel  set_gdbarch_pseudo_register_read (gdbarch, ia64_pseudo_register_read);
3327130803Smarcel  set_gdbarch_pseudo_register_write (gdbarch, ia64_pseudo_register_write);
3328130803Smarcel  set_gdbarch_dwarf2_reg_to_regnum (gdbarch, ia64_dwarf_reg_to_regnum);
3329130803Smarcel  set_gdbarch_register_reggroup_p (gdbarch, ia64_register_reggroup_p);
3330130803Smarcel  set_gdbarch_convert_register_p (gdbarch, ia64_convert_register_p);
3331130803Smarcel  set_gdbarch_register_to_value (gdbarch, ia64_register_to_value);
3332130803Smarcel  set_gdbarch_value_to_register (gdbarch, ia64_value_to_register);
3333130803Smarcel
333498944Sobrien  set_gdbarch_skip_prologue (gdbarch, ia64_skip_prologue);
333598944Sobrien
333698944Sobrien  set_gdbarch_use_struct_convention (gdbarch, ia64_use_struct_convention);
333798944Sobrien  set_gdbarch_extract_return_value (gdbarch, ia64_extract_return_value);
333898944Sobrien
333998944Sobrien  set_gdbarch_store_return_value (gdbarch, ia64_store_return_value);
3340130803Smarcel  set_gdbarch_deprecated_extract_struct_value_address (gdbarch, ia64_extract_struct_value_address);
334198944Sobrien
334298944Sobrien  set_gdbarch_memory_insert_breakpoint (gdbarch, ia64_memory_insert_breakpoint);
334398944Sobrien  set_gdbarch_memory_remove_breakpoint (gdbarch, ia64_memory_remove_breakpoint);
334498944Sobrien  set_gdbarch_breakpoint_from_pc (gdbarch, ia64_breakpoint_from_pc);
334598944Sobrien  set_gdbarch_read_pc (gdbarch, ia64_read_pc);
3346131082Smarcel  set_gdbarch_write_pc (gdbarch, ia64_write_pc);
334798944Sobrien
334898944Sobrien  /* Settings for calling functions in the inferior.  */
3349130803Smarcel  set_gdbarch_push_dummy_call (gdbarch, ia64_push_dummy_call);
3350130803Smarcel  set_gdbarch_frame_align (gdbarch, ia64_frame_align);
3351130803Smarcel  set_gdbarch_unwind_dummy_id (gdbarch, ia64_unwind_dummy_id);
335298944Sobrien
3353130803Smarcel  set_gdbarch_unwind_pc (gdbarch, ia64_unwind_pc);
3354130803Smarcel  frame_unwind_append_sniffer (gdbarch, ia64_sigtramp_frame_sniffer);
3355130803Smarcel#ifdef HAVE_LIBUNWIND_IA64_H
3356130803Smarcel  frame_unwind_append_sniffer (gdbarch, ia64_libunwind_frame_sniffer);
3357130803Smarcel  libunwind_frame_set_descr (gdbarch, &ia64_libunwind_descr);
3358130803Smarcel#endif
3359130803Smarcel  frame_unwind_append_sniffer (gdbarch, ia64_frame_sniffer);
3360130803Smarcel  frame_base_set_default (gdbarch, &ia64_frame_base);
336198944Sobrien
336298944Sobrien  /* Settings that should be unnecessary.  */
336398944Sobrien  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
336498944Sobrien
336598944Sobrien  set_gdbarch_remote_translate_xfer_address (
336698944Sobrien    gdbarch, ia64_remote_translate_xfer_address);
336798944Sobrien
3368130803Smarcel  set_gdbarch_print_insn (gdbarch, ia64_print_insn);
3369130803Smarcel  set_gdbarch_convert_from_func_ptr_addr (gdbarch, ia64_convert_from_func_ptr_addr);
3370130803Smarcel
3371131082Smarcel  gdbarch_init_osabi (info, gdbarch);
3372131082Smarcel
337398944Sobrien  return gdbarch;
337498944Sobrien}
337598944Sobrien
3376130803Smarcelextern initialize_file_ftype _initialize_ia64_tdep; /* -Wmissing-prototypes */
3377130803Smarcel
337898944Sobrienvoid
337998944Sobrien_initialize_ia64_tdep (void)
338098944Sobrien{
338198944Sobrien  register_gdbarch_init (bfd_arch_ia64, ia64_gdbarch_init);
338298944Sobrien}
3383