| /* Target-dependent code for the IA-64 for GDB, the GNU debugger. | 
 |  | 
 |    Copyright (C) 1999-2023 Free Software Foundation, Inc. | 
 |  | 
 |    This file is part of GDB. | 
 |  | 
 |    This program is free software; you can redistribute it and/or modify | 
 |    it under the terms of the GNU General Public License as published by | 
 |    the Free Software Foundation; either version 3 of the License, or | 
 |    (at your option) any later version. | 
 |  | 
 |    This program is distributed in the hope that it will be useful, | 
 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |    GNU General Public License for more details. | 
 |  | 
 |    You should have received a copy of the GNU General Public License | 
 |    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
 |  | 
 | #include "defs.h" | 
 | #include "inferior.h" | 
 | #include "gdbcore.h" | 
 | #include "arch-utils.h" | 
 | #include "floatformat.h" | 
 | #include "gdbtypes.h" | 
 | #include "regcache.h" | 
 | #include "reggroups.h" | 
 | #include "frame.h" | 
 | #include "frame-base.h" | 
 | #include "frame-unwind.h" | 
 | #include "target-float.h" | 
 | #include "value.h" | 
 | #include "objfiles.h" | 
 | #include "elf/common.h"		/* for DT_PLTGOT value */ | 
 | #include "elf-bfd.h" | 
 | #include "dis-asm.h" | 
 | #include "infcall.h" | 
 | #include "osabi.h" | 
 | #include "ia64-tdep.h" | 
 | #include "cp-abi.h" | 
 |  | 
 | #ifdef HAVE_LIBUNWIND_IA64_H | 
 | #include "elf/ia64.h"           /* for PT_IA_64_UNWIND value */ | 
 | #include "ia64-libunwind-tdep.h" | 
 |  | 
 | /* Note: KERNEL_START is supposed to be an address which is not going | 
 | 	 to ever contain any valid unwind info.  For ia64 linux, the choice | 
 | 	 of 0xc000000000000000 is fairly safe since that's uncached space. | 
 |   | 
 | 	 We use KERNEL_START as follows: after obtaining the kernel's | 
 | 	 unwind table via getunwind(), we project its unwind data into | 
 | 	 address-range KERNEL_START-(KERNEL_START+ktab_size) and then | 
 | 	 when ia64_access_mem() sees a memory access to this | 
 | 	 address-range, we redirect it to ktab instead. | 
 |  | 
 | 	 None of this hackery is needed with a modern kernel/libcs | 
 | 	 which uses the kernel virtual DSO to provide access to the | 
 | 	 kernel's unwind info.  In that case, ktab_size remains 0 and | 
 | 	 hence the value of KERNEL_START doesn't matter.  */ | 
 |  | 
 | #define KERNEL_START 0xc000000000000000ULL | 
 |  | 
 | static size_t ktab_size = 0; | 
 | struct ia64_table_entry | 
 |   { | 
 |     uint64_t start_offset; | 
 |     uint64_t end_offset; | 
 |     uint64_t info_offset; | 
 |   }; | 
 |  | 
 | static struct ia64_table_entry *ktab = NULL; | 
 | static gdb::optional<gdb::byte_vector> ktab_buf; | 
 |  | 
 | #endif | 
 |  | 
 | /* An enumeration of the different IA-64 instruction types.  */ | 
 |  | 
 | enum ia64_instruction_type | 
 | { | 
 |   A,			/* Integer ALU ;    I-unit or M-unit */ | 
 |   I,			/* Non-ALU integer; I-unit */ | 
 |   M,			/* Memory ;         M-unit */ | 
 |   F,			/* Floating-point ; F-unit */ | 
 |   B,			/* Branch ;         B-unit */ | 
 |   L,			/* Extended (L+X) ; I-unit */ | 
 |   X,			/* Extended (L+X) ; I-unit */ | 
 |   undefined		/* undefined or reserved */ | 
 | }; | 
 |  | 
 | /* We represent IA-64 PC addresses as the value of the instruction | 
 |    pointer or'd with some bit combination in the low nibble which | 
 |    represents the slot number in the bundle addressed by the | 
 |    instruction pointer.  The problem is that the Linux kernel | 
 |    multiplies its slot numbers (for exceptions) by one while the | 
 |    disassembler multiplies its slot numbers by 6.  In addition, I've | 
 |    heard it said that the simulator uses 1 as the multiplier. | 
 |     | 
 |    I've fixed the disassembler so that the bytes_per_line field will | 
 |    be the slot multiplier.  If bytes_per_line comes in as zero, it | 
 |    is set to six (which is how it was set up initially). -- objdump | 
 |    displays pretty disassembly dumps with this value.  For our purposes, | 
 |    we'll set bytes_per_line to SLOT_MULTIPLIER. This is okay since we | 
 |    never want to also display the raw bytes the way objdump does.  */ | 
 |  | 
 | #define SLOT_MULTIPLIER 1 | 
 |  | 
 | /* Length in bytes of an instruction bundle.  */ | 
 |  | 
 | #define BUNDLE_LEN 16 | 
 |  | 
 | /* See the saved memory layout comment for ia64_memory_insert_breakpoint.  */ | 
 |  | 
 | #if BREAKPOINT_MAX < BUNDLE_LEN - 2 | 
 | # error "BREAKPOINT_MAX < BUNDLE_LEN - 2" | 
 | #endif | 
 |  | 
 | static gdbarch_init_ftype ia64_gdbarch_init; | 
 |  | 
 | static gdbarch_register_name_ftype ia64_register_name; | 
 | static gdbarch_register_type_ftype ia64_register_type; | 
 | static gdbarch_breakpoint_from_pc_ftype ia64_breakpoint_from_pc; | 
 | static gdbarch_skip_prologue_ftype ia64_skip_prologue; | 
 | static struct type *is_float_or_hfa_type (struct type *t); | 
 | static CORE_ADDR ia64_find_global_pointer (struct gdbarch *gdbarch, | 
 | 					   CORE_ADDR faddr); | 
 |  | 
 | #define NUM_IA64_RAW_REGS 462 | 
 |  | 
 | /* Big enough to hold a FP register in bytes.  */ | 
 | #define IA64_FP_REGISTER_SIZE 16 | 
 |  | 
 | static int sp_regnum = IA64_GR12_REGNUM; | 
 |  | 
 | /* NOTE: we treat the register stack registers r32-r127 as | 
 |    pseudo-registers because they may not be accessible via the ptrace | 
 |    register get/set interfaces.  */ | 
 |  | 
 | enum pseudo_regs { FIRST_PSEUDO_REGNUM = NUM_IA64_RAW_REGS, | 
 | 		   VBOF_REGNUM = IA64_NAT127_REGNUM + 1, V32_REGNUM,  | 
 | 		   V127_REGNUM = V32_REGNUM + 95,  | 
 | 		   VP0_REGNUM, VP16_REGNUM = VP0_REGNUM + 16, | 
 | 		   VP63_REGNUM = VP0_REGNUM + 63, LAST_PSEUDO_REGNUM }; | 
 |  | 
 | /* Array of register names; There should be ia64_num_regs strings in | 
 |    the initializer.  */ | 
 |  | 
 | static const char * const ia64_register_names[] = | 
 | { "r0",   "r1",   "r2",   "r3",   "r4",   "r5",   "r6",   "r7", | 
 |   "r8",   "r9",   "r10",  "r11",  "r12",  "r13",  "r14",  "r15", | 
 |   "r16",  "r17",  "r18",  "r19",  "r20",  "r21",  "r22",  "r23", | 
 |   "r24",  "r25",  "r26",  "r27",  "r28",  "r29",  "r30",  "r31", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |  | 
 |   "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7", | 
 |   "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15", | 
 |   "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23", | 
 |   "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31", | 
 |   "f32",  "f33",  "f34",  "f35",  "f36",  "f37",  "f38",  "f39", | 
 |   "f40",  "f41",  "f42",  "f43",  "f44",  "f45",  "f46",  "f47", | 
 |   "f48",  "f49",  "f50",  "f51",  "f52",  "f53",  "f54",  "f55", | 
 |   "f56",  "f57",  "f58",  "f59",  "f60",  "f61",  "f62",  "f63", | 
 |   "f64",  "f65",  "f66",  "f67",  "f68",  "f69",  "f70",  "f71", | 
 |   "f72",  "f73",  "f74",  "f75",  "f76",  "f77",  "f78",  "f79", | 
 |   "f80",  "f81",  "f82",  "f83",  "f84",  "f85",  "f86",  "f87", | 
 |   "f88",  "f89",  "f90",  "f91",  "f92",  "f93",  "f94",  "f95", | 
 |   "f96",  "f97",  "f98",  "f99",  "f100", "f101", "f102", "f103", | 
 |   "f104", "f105", "f106", "f107", "f108", "f109", "f110", "f111", | 
 |   "f112", "f113", "f114", "f115", "f116", "f117", "f118", "f119", | 
 |   "f120", "f121", "f122", "f123", "f124", "f125", "f126", "f127", | 
 |  | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |   "",     "",     "",     "",     "",     "",     "",     "", | 
 |  | 
 |   "b0",   "b1",   "b2",   "b3",   "b4",   "b5",   "b6",   "b7", | 
 |  | 
 |   "vfp", "vrap", | 
 |  | 
 |   "pr", "ip", "psr", "cfm", | 
 |  | 
 |   "kr0",   "kr1",   "kr2",   "kr3",   "kr4",   "kr5",   "kr6",   "kr7", | 
 |   "", "", "", "", "", "", "", "", | 
 |   "rsc", "bsp", "bspstore", "rnat", | 
 |   "", "fcr", "", "", | 
 |   "eflag", "csd", "ssd", "cflg", "fsr", "fir", "fdr",  "", | 
 |   "ccv", "", "", "", "unat", "", "", "", | 
 |   "fpsr", "", "", "", "itc", | 
 |   "", "", "", "", "", "", "", "", "", "", | 
 |   "", "", "", "", "", "", "", "", "", | 
 |   "pfs", "lc", "ec", | 
 |   "", "", "", "", "", "", "", "", "", "", | 
 |   "", "", "", "", "", "", "", "", "", "", | 
 |   "", "", "", "", "", "", "", "", "", "", | 
 |   "", "", "", "", "", "", "", "", "", "", | 
 |   "", "", "", "", "", "", "", "", "", "", | 
 |   "", "", "", "", "", "", "", "", "", "", | 
 |   "", | 
 |   "nat0",  "nat1",  "nat2",  "nat3",  "nat4",  "nat5",  "nat6",  "nat7", | 
 |   "nat8",  "nat9",  "nat10", "nat11", "nat12", "nat13", "nat14", "nat15", | 
 |   "nat16", "nat17", "nat18", "nat19", "nat20", "nat21", "nat22", "nat23", | 
 |   "nat24", "nat25", "nat26", "nat27", "nat28", "nat29", "nat30", "nat31", | 
 |   "nat32", "nat33", "nat34", "nat35", "nat36", "nat37", "nat38", "nat39", | 
 |   "nat40", "nat41", "nat42", "nat43", "nat44", "nat45", "nat46", "nat47", | 
 |   "nat48", "nat49", "nat50", "nat51", "nat52", "nat53", "nat54", "nat55", | 
 |   "nat56", "nat57", "nat58", "nat59", "nat60", "nat61", "nat62", "nat63", | 
 |   "nat64", "nat65", "nat66", "nat67", "nat68", "nat69", "nat70", "nat71", | 
 |   "nat72", "nat73", "nat74", "nat75", "nat76", "nat77", "nat78", "nat79", | 
 |   "nat80", "nat81", "nat82", "nat83", "nat84", "nat85", "nat86", "nat87", | 
 |   "nat88", "nat89", "nat90", "nat91", "nat92", "nat93", "nat94", "nat95", | 
 |   "nat96", "nat97", "nat98", "nat99", "nat100","nat101","nat102","nat103", | 
 |   "nat104","nat105","nat106","nat107","nat108","nat109","nat110","nat111", | 
 |   "nat112","nat113","nat114","nat115","nat116","nat117","nat118","nat119", | 
 |   "nat120","nat121","nat122","nat123","nat124","nat125","nat126","nat127", | 
 |  | 
 |   "bof", | 
 |    | 
 |   "r32",  "r33",  "r34",  "r35",  "r36",  "r37",  "r38",  "r39",    | 
 |   "r40",  "r41",  "r42",  "r43",  "r44",  "r45",  "r46",  "r47", | 
 |   "r48",  "r49",  "r50",  "r51",  "r52",  "r53",  "r54",  "r55", | 
 |   "r56",  "r57",  "r58",  "r59",  "r60",  "r61",  "r62",  "r63", | 
 |   "r64",  "r65",  "r66",  "r67",  "r68",  "r69",  "r70",  "r71", | 
 |   "r72",  "r73",  "r74",  "r75",  "r76",  "r77",  "r78",  "r79", | 
 |   "r80",  "r81",  "r82",  "r83",  "r84",  "r85",  "r86",  "r87", | 
 |   "r88",  "r89",  "r90",  "r91",  "r92",  "r93",  "r94",  "r95", | 
 |   "r96",  "r97",  "r98",  "r99",  "r100", "r101", "r102", "r103", | 
 |   "r104", "r105", "r106", "r107", "r108", "r109", "r110", "r111", | 
 |   "r112", "r113", "r114", "r115", "r116", "r117", "r118", "r119", | 
 |   "r120", "r121", "r122", "r123", "r124", "r125", "r126", "r127", | 
 |  | 
 |   "p0",   "p1",   "p2",   "p3",   "p4",   "p5",   "p6",   "p7", | 
 |   "p8",   "p9",   "p10",  "p11",  "p12",  "p13",  "p14",  "p15", | 
 |   "p16",  "p17",  "p18",  "p19",  "p20",  "p21",  "p22",  "p23", | 
 |   "p24",  "p25",  "p26",  "p27",  "p28",  "p29",  "p30",  "p31", | 
 |   "p32",  "p33",  "p34",  "p35",  "p36",  "p37",  "p38",  "p39", | 
 |   "p40",  "p41",  "p42",  "p43",  "p44",  "p45",  "p46",  "p47", | 
 |   "p48",  "p49",  "p50",  "p51",  "p52",  "p53",  "p54",  "p55", | 
 |   "p56",  "p57",  "p58",  "p59",  "p60",  "p61",  "p62",  "p63", | 
 | }; | 
 |  | 
 | struct ia64_frame_cache | 
 | { | 
 |   CORE_ADDR base;       /* frame pointer base for frame */ | 
 |   CORE_ADDR pc;		/* function start pc for frame */ | 
 |   CORE_ADDR saved_sp;	/* stack pointer for frame */ | 
 |   CORE_ADDR bsp;	/* points at r32 for the current frame */ | 
 |   CORE_ADDR cfm;	/* cfm value for current frame */ | 
 |   CORE_ADDR prev_cfm;   /* cfm value for previous frame */ | 
 |   int   frameless; | 
 |   int   sof;		/* Size of frame  (decoded from cfm value).  */ | 
 |   int	sol;		/* Size of locals (decoded from cfm value).  */ | 
 |   int	sor;		/* Number of rotating registers (decoded from | 
 | 			   cfm value).  */ | 
 |   CORE_ADDR after_prologue; | 
 |   /* Address of first instruction after the last | 
 |      prologue instruction;  Note that there may | 
 |      be instructions from the function's body | 
 |      intermingled with the prologue.  */ | 
 |   int mem_stack_frame_size; | 
 |   /* Size of the memory stack frame (may be zero), | 
 |      or -1 if it has not been determined yet.  */ | 
 |   int	fp_reg;		/* Register number (if any) used a frame pointer | 
 | 			   for this frame.  0 if no register is being used | 
 | 			   as the frame pointer.  */ | 
 |    | 
 |   /* Saved registers.  */ | 
 |   CORE_ADDR saved_regs[NUM_IA64_RAW_REGS]; | 
 |  | 
 | }; | 
 |  | 
 | static int | 
 | floatformat_valid (const struct floatformat *fmt, const void *from) | 
 | { | 
 |   return 1; | 
 | } | 
 |  | 
 | static const struct floatformat floatformat_ia64_ext_little = | 
 | { | 
 |   floatformat_little, 82, 0, 1, 17, 65535, 0x1ffff, 18, 64, | 
 |   floatformat_intbit_yes, "floatformat_ia64_ext_little", floatformat_valid, NULL | 
 | }; | 
 |  | 
 | static const struct floatformat floatformat_ia64_ext_big = | 
 | { | 
 |   floatformat_big, 82, 46, 47, 17, 65535, 0x1ffff, 64, 64, | 
 |   floatformat_intbit_yes, "floatformat_ia64_ext_big", floatformat_valid | 
 | }; | 
 |  | 
 | static const struct floatformat *floatformats_ia64_ext[2] = | 
 | { | 
 |   &floatformat_ia64_ext_big, | 
 |   &floatformat_ia64_ext_little | 
 | }; | 
 |  | 
 | static struct type * | 
 | ia64_ext_type (struct gdbarch *gdbarch) | 
 | { | 
 |   ia64_gdbarch_tdep *tdep = gdbarch_tdep<ia64_gdbarch_tdep> (gdbarch); | 
 |  | 
 |   if (!tdep->ia64_ext_type) | 
 |     { | 
 |       type_allocator alloc (gdbarch); | 
 |       tdep->ia64_ext_type | 
 | 	= init_float_type (alloc, 128, "builtin_type_ia64_ext", | 
 | 			   floatformats_ia64_ext); | 
 |     } | 
 |  | 
 |   return tdep->ia64_ext_type; | 
 | } | 
 |  | 
 | static int | 
 | ia64_register_reggroup_p (struct gdbarch *gdbarch, int regnum, | 
 | 			  const struct reggroup *group) | 
 | { | 
 |   int vector_p; | 
 |   int float_p; | 
 |   int raw_p; | 
 |   if (group == all_reggroup) | 
 |     return 1; | 
 |   vector_p = register_type (gdbarch, regnum)->is_vector (); | 
 |   float_p = register_type (gdbarch, regnum)->code () == TYPE_CODE_FLT; | 
 |   raw_p = regnum < NUM_IA64_RAW_REGS; | 
 |   if (group == float_reggroup) | 
 |     return float_p; | 
 |   if (group == vector_reggroup) | 
 |     return vector_p; | 
 |   if (group == general_reggroup) | 
 |     return (!vector_p && !float_p); | 
 |   if (group == save_reggroup || group == restore_reggroup) | 
 |     return raw_p;  | 
 |   return 0; | 
 | } | 
 |  | 
 | static const char * | 
 | ia64_register_name (struct gdbarch *gdbarch, int reg) | 
 | { | 
 |   return ia64_register_names[reg]; | 
 | } | 
 |  | 
 | struct type * | 
 | ia64_register_type (struct gdbarch *arch, int reg) | 
 | { | 
 |   if (reg >= IA64_FR0_REGNUM && reg <= IA64_FR127_REGNUM) | 
 |     return ia64_ext_type (arch); | 
 |   else | 
 |     return builtin_type (arch)->builtin_long; | 
 | } | 
 |  | 
 | static int | 
 | ia64_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) | 
 | { | 
 |   if (reg >= IA64_GR32_REGNUM && reg <= IA64_GR127_REGNUM) | 
 |     return V32_REGNUM + (reg - IA64_GR32_REGNUM); | 
 |   return reg; | 
 | } | 
 |  | 
 |  | 
 | /* Extract ``len'' bits from an instruction bundle starting at | 
 |    bit ``from''.  */ | 
 |  | 
 | static long long | 
 | extract_bit_field (const gdb_byte *bundle, int from, int len) | 
 | { | 
 |   long long result = 0LL; | 
 |   int to = from + len; | 
 |   int from_byte = from / 8; | 
 |   int to_byte = to / 8; | 
 |   unsigned char *b = (unsigned char *) bundle; | 
 |   unsigned char c; | 
 |   int lshift; | 
 |   int i; | 
 |  | 
 |   c = b[from_byte]; | 
 |   if (from_byte == to_byte) | 
 |     c = ((unsigned char) (c << (8 - to % 8))) >> (8 - to % 8); | 
 |   result = c >> (from % 8); | 
 |   lshift = 8 - (from % 8); | 
 |  | 
 |   for (i = from_byte+1; i < to_byte; i++) | 
 |     { | 
 |       result |= ((long long) b[i]) << lshift; | 
 |       lshift += 8; | 
 |     } | 
 |  | 
 |   if (from_byte < to_byte && (to % 8 != 0)) | 
 |     { | 
 |       c = b[to_byte]; | 
 |       c = ((unsigned char) (c << (8 - to % 8))) >> (8 - to % 8); | 
 |       result |= ((long long) c) << lshift; | 
 |     } | 
 |  | 
 |   return result; | 
 | } | 
 |  | 
 | /* Replace the specified bits in an instruction bundle.  */ | 
 |  | 
 | static void | 
 | replace_bit_field (gdb_byte *bundle, long long val, int from, int len) | 
 | { | 
 |   int to = from + len; | 
 |   int from_byte = from / 8; | 
 |   int to_byte = to / 8; | 
 |   unsigned char *b = (unsigned char *) bundle; | 
 |   unsigned char c; | 
 |  | 
 |   if (from_byte == to_byte) | 
 |     { | 
 |       unsigned char left, right; | 
 |       c = b[from_byte]; | 
 |       left = (c >> (to % 8)) << (to % 8); | 
 |       right = ((unsigned char) (c << (8 - from % 8))) >> (8 - from % 8); | 
 |       c = (unsigned char) (val & 0xff); | 
 |       c = (unsigned char) (c << (from % 8 + 8 - to % 8)) >> (8 - to % 8); | 
 |       c |= right | left; | 
 |       b[from_byte] = c; | 
 |     } | 
 |   else | 
 |     { | 
 |       int i; | 
 |       c = b[from_byte]; | 
 |       c = ((unsigned char) (c << (8 - from % 8))) >> (8 - from % 8); | 
 |       c = c | (val << (from % 8)); | 
 |       b[from_byte] = c; | 
 |       val >>= 8 - from % 8; | 
 |  | 
 |       for (i = from_byte+1; i < to_byte; i++) | 
 | 	{ | 
 | 	  c = val & 0xff; | 
 | 	  val >>= 8; | 
 | 	  b[i] = c; | 
 | 	} | 
 |  | 
 |       if (to % 8 != 0) | 
 | 	{ | 
 | 	  unsigned char cv = (unsigned char) val; | 
 | 	  c = b[to_byte]; | 
 | 	  c = c >> (to % 8) << (to % 8); | 
 | 	  c |= ((unsigned char) (cv << (8 - to % 8))) >> (8 - to % 8); | 
 | 	  b[to_byte] = c; | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | /* Return the contents of slot N (for N = 0, 1, or 2) in | 
 |    and instruction bundle.  */ | 
 |  | 
 | static long long | 
 | slotN_contents (gdb_byte *bundle, int slotnum) | 
 | { | 
 |   return extract_bit_field (bundle, 5+41*slotnum, 41); | 
 | } | 
 |  | 
 | /* Store an instruction in an instruction bundle.  */ | 
 |  | 
 | static void | 
 | replace_slotN_contents (gdb_byte *bundle, long long instr, int slotnum) | 
 | { | 
 |   replace_bit_field (bundle, instr, 5+41*slotnum, 41); | 
 | } | 
 |  | 
 | static const enum ia64_instruction_type template_encoding_table[32][3] = | 
 | { | 
 |   { M, I, I },				/* 00 */ | 
 |   { M, I, I },				/* 01 */ | 
 |   { M, I, I },				/* 02 */ | 
 |   { M, I, I },				/* 03 */ | 
 |   { M, L, X },				/* 04 */ | 
 |   { M, L, X },				/* 05 */ | 
 |   { undefined, undefined, undefined },  /* 06 */ | 
 |   { undefined, undefined, undefined },  /* 07 */ | 
 |   { M, M, I },				/* 08 */ | 
 |   { M, M, I },				/* 09 */ | 
 |   { M, M, I },				/* 0A */ | 
 |   { M, M, I },				/* 0B */ | 
 |   { M, F, I },				/* 0C */ | 
 |   { M, F, I },				/* 0D */ | 
 |   { M, M, F },				/* 0E */ | 
 |   { M, M, F },				/* 0F */ | 
 |   { M, I, B },				/* 10 */ | 
 |   { M, I, B },				/* 11 */ | 
 |   { M, B, B },				/* 12 */ | 
 |   { M, B, B },				/* 13 */ | 
 |   { undefined, undefined, undefined },  /* 14 */ | 
 |   { undefined, undefined, undefined },  /* 15 */ | 
 |   { B, B, B },				/* 16 */ | 
 |   { B, B, B },				/* 17 */ | 
 |   { M, M, B },				/* 18 */ | 
 |   { M, M, B },				/* 19 */ | 
 |   { undefined, undefined, undefined },  /* 1A */ | 
 |   { undefined, undefined, undefined },  /* 1B */ | 
 |   { M, F, B },				/* 1C */ | 
 |   { M, F, B },				/* 1D */ | 
 |   { undefined, undefined, undefined },  /* 1E */ | 
 |   { undefined, undefined, undefined },  /* 1F */ | 
 | }; | 
 |  | 
 | /* Fetch and (partially) decode an instruction at ADDR and return the | 
 |    address of the next instruction to fetch.  */ | 
 |  | 
 | static CORE_ADDR | 
 | fetch_instruction (CORE_ADDR addr, ia64_instruction_type *it, long long *instr) | 
 | { | 
 |   gdb_byte bundle[BUNDLE_LEN]; | 
 |   int slotnum = (int) (addr & 0x0f) / SLOT_MULTIPLIER; | 
 |   long long templ; | 
 |   int val; | 
 |  | 
 |   /* Warn about slot numbers greater than 2.  We used to generate | 
 |      an error here on the assumption that the user entered an invalid | 
 |      address.  But, sometimes GDB itself requests an invalid address. | 
 |      This can (easily) happen when execution stops in a function for | 
 |      which there are no symbols.  The prologue scanner will attempt to | 
 |      find the beginning of the function - if the nearest symbol | 
 |      happens to not be aligned on a bundle boundary (16 bytes), the | 
 |      resulting starting address will cause GDB to think that the slot | 
 |      number is too large. | 
 |  | 
 |      So we warn about it and set the slot number to zero.  It is | 
 |      not necessarily a fatal condition, particularly if debugging | 
 |      at the assembly language level.  */ | 
 |   if (slotnum > 2) | 
 |     { | 
 |       warning (_("Can't fetch instructions for slot numbers greater than 2.\n" | 
 | 	       "Using slot 0 instead")); | 
 |       slotnum = 0; | 
 |     } | 
 |  | 
 |   addr &= ~0x0f; | 
 |  | 
 |   val = target_read_memory (addr, bundle, BUNDLE_LEN); | 
 |  | 
 |   if (val != 0) | 
 |     return 0; | 
 |  | 
 |   *instr = slotN_contents (bundle, slotnum); | 
 |   templ = extract_bit_field (bundle, 0, 5); | 
 |   *it = template_encoding_table[(int)templ][slotnum]; | 
 |  | 
 |   if (slotnum == 2 || (slotnum == 1 && *it == L)) | 
 |     addr += 16; | 
 |   else | 
 |     addr += (slotnum + 1) * SLOT_MULTIPLIER; | 
 |  | 
 |   return addr; | 
 | } | 
 |  | 
 | /* There are 5 different break instructions (break.i, break.b, | 
 |    break.m, break.f, and break.x), but they all have the same | 
 |    encoding.  (The five bit template in the low five bits of the | 
 |    instruction bundle distinguishes one from another.) | 
 |     | 
 |    The runtime architecture manual specifies that break instructions | 
 |    used for debugging purposes must have the upper two bits of the 21 | 
 |    bit immediate set to a 0 and a 1 respectively.  A breakpoint | 
 |    instruction encodes the most significant bit of its 21 bit | 
 |    immediate at bit 36 of the 41 bit instruction.  The penultimate msb | 
 |    is at bit 25 which leads to the pattern below.   | 
 |     | 
 |    Originally, I had this set up to do, e.g, a "break.i 0x80000"  But | 
 |    it turns out that 0x80000 was used as the syscall break in the early | 
 |    simulators.  So I changed the pattern slightly to do "break.i 0x080001" | 
 |    instead.  But that didn't work either (I later found out that this | 
 |    pattern was used by the simulator that I was using.)  So I ended up | 
 |    using the pattern seen below. | 
 |  | 
 |    SHADOW_CONTENTS has byte-based addressing (PLACED_ADDRESS and SHADOW_LEN) | 
 |    while we need bit-based addressing as the instructions length is 41 bits and | 
 |    we must not modify/corrupt the adjacent slots in the same bundle. | 
 |    Fortunately we may store larger memory incl. the adjacent bits with the | 
 |    original memory content (not the possibly already stored breakpoints there). | 
 |    We need to be careful in ia64_memory_remove_breakpoint to always restore | 
 |    only the specific bits of this instruction ignoring any adjacent stored | 
 |    bits. | 
 |  | 
 |    We use the original addressing with the low nibble in the range <0..2> which | 
 |    gets incorrectly interpreted by generic non-ia64 breakpoint_restore_shadows | 
 |    as the direct byte offset of SHADOW_CONTENTS.  We store whole BUNDLE_LEN | 
 |    bytes just without these two possibly skipped bytes to not to exceed to the | 
 |    next bundle. | 
 |  | 
 |    If we would like to store the whole bundle to SHADOW_CONTENTS we would have | 
 |    to store already the base address (`address & ~0x0f') into PLACED_ADDRESS. | 
 |    In such case there is no other place where to store | 
 |    SLOTNUM (`adress & 0x0f', value in the range <0..2>).  We need to know | 
 |    SLOTNUM in ia64_memory_remove_breakpoint. | 
 |  | 
 |    There is one special case where we need to be extra careful: | 
 |    L-X instructions, which are instructions that occupy 2 slots | 
 |    (The L part is always in slot 1, and the X part is always in | 
 |    slot 2).  We must refuse to insert breakpoints for an address | 
 |    that points at slot 2 of a bundle where an L-X instruction is | 
 |    present, since there is logically no instruction at that address. | 
 |    However, to make things more interesting, the opcode of L-X | 
 |    instructions is located in slot 2.  This means that, to insert | 
 |    a breakpoint at an address that points to slot 1, we actually | 
 |    need to write the breakpoint in slot 2!  Slot 1 is actually | 
 |    the extended operand, so writing the breakpoint there would not | 
 |    have the desired effect.  Another side-effect of this issue | 
 |    is that we need to make sure that the shadow contents buffer | 
 |    does save byte 15 of our instruction bundle (this is the tail | 
 |    end of slot 2, which wouldn't be saved if we were to insert | 
 |    the breakpoint in slot 1). | 
 |     | 
 |    ia64 16-byte bundle layout: | 
 |    | 5 bits | slot 0 with 41 bits | slot 1 with 41 bits | slot 2 with 41 bits | | 
 |     | 
 |    The current addressing used by the code below: | 
 |    original PC   placed_address   placed_size             required    covered | 
 | 				  == bp_tgt->shadow_len   reqd \subset covered | 
 |    0xABCDE0      0xABCDE0         0x10                    <0x0...0x5> <0x0..0xF> | 
 |    0xABCDE1      0xABCDE1         0xF                     <0x5...0xA> <0x1..0xF> | 
 |    0xABCDE2      0xABCDE2         0xE                     <0xA...0xF> <0x2..0xF> | 
 |  | 
 |    L-X instructions are treated a little specially, as explained above: | 
 |    0xABCDE1      0xABCDE1         0xF                     <0xA...0xF> <0x1..0xF> | 
 |  | 
 |    `objdump -d' and some other tools show a bit unjustified offsets: | 
 |    original PC   byte where starts the instruction   objdump offset | 
 |    0xABCDE0      0xABCDE0                            0xABCDE0 | 
 |    0xABCDE1      0xABCDE5                            0xABCDE6 | 
 |    0xABCDE2      0xABCDEA                            0xABCDEC | 
 |    */ | 
 |  | 
 | #define IA64_BREAKPOINT 0x00003333300LL | 
 |  | 
 | static int | 
 | ia64_memory_insert_breakpoint (struct gdbarch *gdbarch, | 
 | 			       struct bp_target_info *bp_tgt) | 
 | { | 
 |   CORE_ADDR addr = bp_tgt->placed_address = bp_tgt->reqstd_address; | 
 |   gdb_byte bundle[BUNDLE_LEN]; | 
 |   int slotnum = (int) (addr & 0x0f) / SLOT_MULTIPLIER, shadow_slotnum; | 
 |   long long instr_breakpoint; | 
 |   int val; | 
 |   int templ; | 
 |  | 
 |   if (slotnum > 2) | 
 |     error (_("Can't insert breakpoint for slot numbers greater than 2.")); | 
 |  | 
 |   addr &= ~0x0f; | 
 |  | 
 |   /* Enable the automatic memory restoration from breakpoints while | 
 |      we read our instruction bundle for the purpose of SHADOW_CONTENTS. | 
 |      Otherwise, we could possibly store into the shadow parts of the adjacent | 
 |      placed breakpoints.  It is due to our SHADOW_CONTENTS overlapping the real | 
 |      breakpoint instruction bits region.  */ | 
 |   scoped_restore restore_memory_0 | 
 |     = make_scoped_restore_show_memory_breakpoints (0); | 
 |   val = target_read_memory (addr, bundle, BUNDLE_LEN); | 
 |   if (val != 0) | 
 |     return val; | 
 |  | 
 |   /* SHADOW_SLOTNUM saves the original slot number as expected by the caller | 
 |      for addressing the SHADOW_CONTENTS placement.  */ | 
 |   shadow_slotnum = slotnum; | 
 |  | 
 |   /* Always cover the last byte of the bundle in case we are inserting | 
 |      a breakpoint on an L-X instruction.  */ | 
 |   bp_tgt->shadow_len = BUNDLE_LEN - shadow_slotnum; | 
 |  | 
 |   templ = extract_bit_field (bundle, 0, 5); | 
 |   if (template_encoding_table[templ][slotnum] == X) | 
 |     { | 
 |       /* X unit types can only be used in slot 2, and are actually | 
 | 	 part of a 2-slot L-X instruction.  We cannot break at this | 
 | 	 address, as this is the second half of an instruction that | 
 | 	 lives in slot 1 of that bundle.  */ | 
 |       gdb_assert (slotnum == 2); | 
 |       error (_("Can't insert breakpoint for non-existing slot X")); | 
 |     } | 
 |   if (template_encoding_table[templ][slotnum] == L) | 
 |     { | 
 |       /* L unit types can only be used in slot 1.  But the associated | 
 | 	 opcode for that instruction is in slot 2, so bump the slot number | 
 | 	 accordingly.  */ | 
 |       gdb_assert (slotnum == 1); | 
 |       slotnum = 2; | 
 |     } | 
 |  | 
 |   /* Store the whole bundle, except for the initial skipped bytes by the slot | 
 |      number interpreted as bytes offset in PLACED_ADDRESS.  */ | 
 |   memcpy (bp_tgt->shadow_contents, bundle + shadow_slotnum, | 
 | 	  bp_tgt->shadow_len); | 
 |  | 
 |   /* Re-read the same bundle as above except that, this time, read it in order | 
 |      to compute the new bundle inside which we will be inserting the | 
 |      breakpoint.  Therefore, disable the automatic memory restoration from | 
 |      breakpoints while we read our instruction bundle.  Otherwise, the general | 
 |      restoration mechanism kicks in and we would possibly remove parts of the | 
 |      adjacent placed breakpoints.  It is due to our SHADOW_CONTENTS overlapping | 
 |      the real breakpoint instruction bits region.  */ | 
 |   scoped_restore restore_memory_1 | 
 |     = make_scoped_restore_show_memory_breakpoints (1); | 
 |   val = target_read_memory (addr, bundle, BUNDLE_LEN); | 
 |   if (val != 0) | 
 |     return val; | 
 |  | 
 |   /* Breakpoints already present in the code will get detected and not get | 
 |      reinserted by bp_loc_is_permanent.  Multiple breakpoints at the same | 
 |      location cannot induce the internal error as they are optimized into | 
 |      a single instance by update_global_location_list.  */ | 
 |   instr_breakpoint = slotN_contents (bundle, slotnum); | 
 |   if (instr_breakpoint == IA64_BREAKPOINT) | 
 |     internal_error (_("Address %s already contains a breakpoint."), | 
 | 		    paddress (gdbarch, bp_tgt->placed_address)); | 
 |   replace_slotN_contents (bundle, IA64_BREAKPOINT, slotnum); | 
 |  | 
 |   val = target_write_memory (addr + shadow_slotnum, bundle + shadow_slotnum, | 
 | 			     bp_tgt->shadow_len); | 
 |  | 
 |   return val; | 
 | } | 
 |  | 
 | static int | 
 | ia64_memory_remove_breakpoint (struct gdbarch *gdbarch, | 
 | 			       struct bp_target_info *bp_tgt) | 
 | { | 
 |   CORE_ADDR addr = bp_tgt->placed_address; | 
 |   gdb_byte bundle_mem[BUNDLE_LEN], bundle_saved[BUNDLE_LEN]; | 
 |   int slotnum = (addr & 0x0f) / SLOT_MULTIPLIER, shadow_slotnum; | 
 |   long long instr_breakpoint, instr_saved; | 
 |   int val; | 
 |   int templ; | 
 |  | 
 |   addr &= ~0x0f; | 
 |  | 
 |   /* Disable the automatic memory restoration from breakpoints while | 
 |      we read our instruction bundle.  Otherwise, the general restoration | 
 |      mechanism kicks in and we would possibly remove parts of the adjacent | 
 |      placed breakpoints.  It is due to our SHADOW_CONTENTS overlapping the real | 
 |      breakpoint instruction bits region.  */ | 
 |   scoped_restore restore_memory_1 | 
 |     = make_scoped_restore_show_memory_breakpoints (1); | 
 |   val = target_read_memory (addr, bundle_mem, BUNDLE_LEN); | 
 |   if (val != 0) | 
 |     return val; | 
 |  | 
 |   /* SHADOW_SLOTNUM saves the original slot number as expected by the caller | 
 |      for addressing the SHADOW_CONTENTS placement.  */ | 
 |   shadow_slotnum = slotnum; | 
 |  | 
 |   templ = extract_bit_field (bundle_mem, 0, 5); | 
 |   if (template_encoding_table[templ][slotnum] == X) | 
 |     { | 
 |       /* X unit types can only be used in slot 2, and are actually | 
 | 	 part of a 2-slot L-X instruction.  We refuse to insert | 
 | 	 breakpoints at this address, so there should be no reason | 
 | 	 for us attempting to remove one there, except if the program's | 
 | 	 code somehow got modified in memory.  */ | 
 |       gdb_assert (slotnum == 2); | 
 |       warning (_("Cannot remove breakpoint at address %s from non-existing " | 
 | 		 "X-type slot, memory has changed underneath"), | 
 | 	       paddress (gdbarch, bp_tgt->placed_address)); | 
 |       return -1; | 
 |     } | 
 |   if (template_encoding_table[templ][slotnum] == L) | 
 |     { | 
 |       /* L unit types can only be used in slot 1.  But the breakpoint | 
 | 	 was actually saved using slot 2, so update the slot number | 
 | 	 accordingly.  */ | 
 |       gdb_assert (slotnum == 1); | 
 |       slotnum = 2; | 
 |     } | 
 |  | 
 |   gdb_assert (bp_tgt->shadow_len == BUNDLE_LEN - shadow_slotnum); | 
 |  | 
 |   instr_breakpoint = slotN_contents (bundle_mem, slotnum); | 
 |   if (instr_breakpoint != IA64_BREAKPOINT) | 
 |     { | 
 |       warning (_("Cannot remove breakpoint at address %s, " | 
 | 		 "no break instruction at such address."), | 
 | 	       paddress (gdbarch, bp_tgt->placed_address)); | 
 |       return -1; | 
 |     } | 
 |  | 
 |   /* Extract the original saved instruction from SLOTNUM normalizing its | 
 |      bit-shift for INSTR_SAVED.  */ | 
 |   memcpy (bundle_saved, bundle_mem, BUNDLE_LEN); | 
 |   memcpy (bundle_saved + shadow_slotnum, bp_tgt->shadow_contents, | 
 | 	  bp_tgt->shadow_len); | 
 |   instr_saved = slotN_contents (bundle_saved, slotnum); | 
 |  | 
 |   /* In BUNDLE_MEM, be careful to modify only the bits belonging to SLOTNUM | 
 |      and not any of the other ones that are stored in SHADOW_CONTENTS.  */ | 
 |   replace_slotN_contents (bundle_mem, instr_saved, slotnum); | 
 |   val = target_write_raw_memory (addr, bundle_mem, BUNDLE_LEN); | 
 |  | 
 |   return val; | 
 | } | 
 |  | 
 | /* Implement the breakpoint_kind_from_pc gdbarch method.  */ | 
 |  | 
 | static int | 
 | ia64_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr) | 
 | { | 
 |   /* A place holder of gdbarch method breakpoint_kind_from_pc.   */ | 
 |   return 0; | 
 | } | 
 |  | 
 | /* As gdbarch_breakpoint_from_pc ranges have byte granularity and ia64 | 
 |    instruction slots ranges are bit-granular (41 bits) we have to provide an | 
 |    extended range as described for ia64_memory_insert_breakpoint.  We also take | 
 |    care of preserving the `break' instruction 21-bit (or 62-bit) parameter to | 
 |    make a match for permanent breakpoints.  */ | 
 |  | 
 | static const gdb_byte * | 
 | ia64_breakpoint_from_pc (struct gdbarch *gdbarch, | 
 | 			 CORE_ADDR *pcptr, int *lenptr) | 
 | { | 
 |   CORE_ADDR addr = *pcptr; | 
 |   static gdb_byte bundle[BUNDLE_LEN]; | 
 |   int slotnum = (int) (*pcptr & 0x0f) / SLOT_MULTIPLIER, shadow_slotnum; | 
 |   long long instr_fetched; | 
 |   int val; | 
 |   int templ; | 
 |  | 
 |   if (slotnum > 2) | 
 |     error (_("Can't insert breakpoint for slot numbers greater than 2.")); | 
 |  | 
 |   addr &= ~0x0f; | 
 |  | 
 |   /* Enable the automatic memory restoration from breakpoints while | 
 |      we read our instruction bundle to match bp_loc_is_permanent.  */ | 
 |   { | 
 |     scoped_restore restore_memory_0 | 
 |       = make_scoped_restore_show_memory_breakpoints (0); | 
 |     val = target_read_memory (addr, bundle, BUNDLE_LEN); | 
 |   } | 
 |  | 
 |   /* The memory might be unreachable.  This can happen, for instance, | 
 |      when the user inserts a breakpoint at an invalid address.  */ | 
 |   if (val != 0) | 
 |     return NULL; | 
 |  | 
 |   /* SHADOW_SLOTNUM saves the original slot number as expected by the caller | 
 |      for addressing the SHADOW_CONTENTS placement.  */ | 
 |   shadow_slotnum = slotnum; | 
 |  | 
 |   /* Cover always the last byte of the bundle for the L-X slot case.  */ | 
 |   *lenptr = BUNDLE_LEN - shadow_slotnum; | 
 |  | 
 |   /* Check for L type instruction in slot 1, if present then bump up the slot | 
 |      number to the slot 2.  */ | 
 |   templ = extract_bit_field (bundle, 0, 5); | 
 |   if (template_encoding_table[templ][slotnum] == X) | 
 |     { | 
 |       gdb_assert (slotnum == 2); | 
 |       error (_("Can't insert breakpoint for non-existing slot X")); | 
 |     } | 
 |   if (template_encoding_table[templ][slotnum] == L) | 
 |     { | 
 |       gdb_assert (slotnum == 1); | 
 |       slotnum = 2; | 
 |     } | 
 |  | 
 |   /* A break instruction has its all its opcode bits cleared except for | 
 |      the parameter value.  For L+X slot pair we are at the X slot (slot 2) so | 
 |      we should not touch the L slot - the upper 41 bits of the parameter.  */ | 
 |   instr_fetched = slotN_contents (bundle, slotnum); | 
 |   instr_fetched &= 0x1003ffffc0LL; | 
 |   replace_slotN_contents (bundle, instr_fetched, slotnum); | 
 |  | 
 |   return bundle + shadow_slotnum; | 
 | } | 
 |  | 
 | static CORE_ADDR | 
 | ia64_read_pc (readable_regcache *regcache) | 
 | { | 
 |   ULONGEST psr_value, pc_value; | 
 |   int slot_num; | 
 |  | 
 |   regcache->cooked_read (IA64_PSR_REGNUM, &psr_value); | 
 |   regcache->cooked_read (IA64_IP_REGNUM, &pc_value); | 
 |   slot_num = (psr_value >> 41) & 3; | 
 |  | 
 |   return pc_value | (slot_num * SLOT_MULTIPLIER); | 
 | } | 
 |  | 
 | void | 
 | ia64_write_pc (struct regcache *regcache, CORE_ADDR new_pc) | 
 | { | 
 |   int slot_num = (int) (new_pc & 0xf) / SLOT_MULTIPLIER; | 
 |   ULONGEST psr_value; | 
 |  | 
 |   regcache_cooked_read_unsigned (regcache, IA64_PSR_REGNUM, &psr_value); | 
 |   psr_value &= ~(3LL << 41); | 
 |   psr_value |= (ULONGEST)(slot_num & 0x3) << 41; | 
 |  | 
 |   new_pc &= ~0xfLL; | 
 |  | 
 |   regcache_cooked_write_unsigned (regcache, IA64_PSR_REGNUM, psr_value); | 
 |   regcache_cooked_write_unsigned (regcache, IA64_IP_REGNUM, new_pc); | 
 | } | 
 |  | 
 | #define IS_NaT_COLLECTION_ADDR(addr) ((((addr) >> 3) & 0x3f) == 0x3f) | 
 |  | 
 | /* Returns the address of the slot that's NSLOTS slots away from | 
 |    the address ADDR.  NSLOTS may be positive or negative.  */ | 
 | static CORE_ADDR | 
 | rse_address_add(CORE_ADDR addr, int nslots) | 
 | { | 
 |   CORE_ADDR new_addr; | 
 |   int mandatory_nat_slots = nslots / 63; | 
 |   int direction = nslots < 0 ? -1 : 1; | 
 |  | 
 |   new_addr = addr + 8 * (nslots + mandatory_nat_slots); | 
 |  | 
 |   if ((new_addr >> 9)  != ((addr + 8 * 64 * mandatory_nat_slots) >> 9)) | 
 |     new_addr += 8 * direction; | 
 |  | 
 |   if (IS_NaT_COLLECTION_ADDR(new_addr)) | 
 |     new_addr += 8 * direction; | 
 |  | 
 |   return new_addr; | 
 | } | 
 |  | 
 | static enum register_status | 
 | ia64_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache, | 
 | 			   int regnum, gdb_byte *buf) | 
 | { | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   enum register_status status; | 
 |  | 
 |   if (regnum >= V32_REGNUM && regnum <= V127_REGNUM) | 
 |     { | 
 | #ifdef HAVE_LIBUNWIND_IA64_H | 
 |       /* First try and use the libunwind special reg accessor, | 
 | 	 otherwise fallback to standard logic.  */ | 
 |       if (!libunwind_is_initialized () | 
 | 	  || libunwind_get_reg_special (gdbarch, regcache, regnum, buf) != 0) | 
 | #endif | 
 | 	{ | 
 | 	  /* The fallback position is to assume that r32-r127 are | 
 | 	     found sequentially in memory starting at $bof.  This | 
 | 	     isn't always true, but without libunwind, this is the | 
 | 	     best we can do.  */ | 
 | 	  ULONGEST cfm; | 
 | 	  ULONGEST bsp; | 
 | 	  CORE_ADDR reg; | 
 |  | 
 | 	  status = regcache->cooked_read (IA64_BSP_REGNUM, &bsp); | 
 | 	  if (status != REG_VALID) | 
 | 	    return status; | 
 |  | 
 | 	  status = regcache->cooked_read (IA64_CFM_REGNUM, &cfm); | 
 | 	  if (status != REG_VALID) | 
 | 	    return status; | 
 |  | 
 | 	  /* The bsp points at the end of the register frame so we | 
 | 	     subtract the size of frame from it to get start of | 
 | 	     register frame.  */ | 
 | 	  bsp = rse_address_add (bsp, -(cfm & 0x7f)); | 
 | 	   | 
 | 	  if ((cfm & 0x7f) > regnum - V32_REGNUM)  | 
 | 	    { | 
 | 	      ULONGEST reg_addr = rse_address_add (bsp, (regnum - V32_REGNUM)); | 
 | 	      reg = read_memory_integer ((CORE_ADDR)reg_addr, 8, byte_order); | 
 | 	      store_unsigned_integer (buf, register_size (gdbarch, regnum), | 
 | 				      byte_order, reg); | 
 | 	    } | 
 | 	  else | 
 | 	    store_unsigned_integer (buf, register_size (gdbarch, regnum), | 
 | 				    byte_order, 0); | 
 | 	} | 
 |     } | 
 |   else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT31_REGNUM) | 
 |     { | 
 |       ULONGEST unatN_val; | 
 |       ULONGEST unat; | 
 |  | 
 |       status = regcache->cooked_read (IA64_UNAT_REGNUM, &unat); | 
 |       if (status != REG_VALID) | 
 | 	return status; | 
 |       unatN_val = (unat & (1LL << (regnum - IA64_NAT0_REGNUM))) != 0; | 
 |       store_unsigned_integer (buf, register_size (gdbarch, regnum), | 
 | 			      byte_order, unatN_val); | 
 |     } | 
 |   else if (IA64_NAT32_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM) | 
 |     { | 
 |       ULONGEST natN_val = 0; | 
 |       ULONGEST bsp; | 
 |       ULONGEST cfm; | 
 |       CORE_ADDR gr_addr = 0; | 
 |  | 
 |       status = regcache->cooked_read (IA64_BSP_REGNUM, &bsp); | 
 |       if (status != REG_VALID) | 
 | 	return status; | 
 |  | 
 |       status = regcache->cooked_read (IA64_CFM_REGNUM, &cfm); | 
 |       if (status != REG_VALID) | 
 | 	return status; | 
 |  | 
 |       /* The bsp points at the end of the register frame so we | 
 | 	 subtract the size of frame from it to get start of register frame.  */ | 
 |       bsp = rse_address_add (bsp, -(cfm & 0x7f)); | 
 |   | 
 |       if ((cfm & 0x7f) > regnum - V32_REGNUM)  | 
 | 	gr_addr = rse_address_add (bsp, (regnum - V32_REGNUM)); | 
 |        | 
 |       if (gr_addr != 0) | 
 | 	{ | 
 | 	  /* Compute address of nat collection bits.  */ | 
 | 	  CORE_ADDR nat_addr = gr_addr | 0x1f8; | 
 | 	  ULONGEST nat_collection; | 
 | 	  int nat_bit; | 
 | 	  /* If our nat collection address is bigger than bsp, we have to get | 
 | 	     the nat collection from rnat.  Otherwise, we fetch the nat | 
 | 	     collection from the computed address.  */ | 
 | 	  if (nat_addr >= bsp) | 
 | 	    regcache->cooked_read (IA64_RNAT_REGNUM, &nat_collection); | 
 | 	  else | 
 | 	    nat_collection = read_memory_integer (nat_addr, 8, byte_order); | 
 | 	  nat_bit = (gr_addr >> 3) & 0x3f; | 
 | 	  natN_val = (nat_collection >> nat_bit) & 1; | 
 | 	} | 
 |        | 
 |       store_unsigned_integer (buf, register_size (gdbarch, regnum), | 
 | 			      byte_order, natN_val); | 
 |     } | 
 |   else if (regnum == VBOF_REGNUM) | 
 |     { | 
 |       /* A virtual register frame start is provided for user convenience. | 
 | 	 It can be calculated as the bsp - sof (sizeof frame).  */ | 
 |       ULONGEST bsp, vbsp; | 
 |       ULONGEST cfm; | 
 |  | 
 |       status = regcache->cooked_read (IA64_BSP_REGNUM, &bsp); | 
 |       if (status != REG_VALID) | 
 | 	return status; | 
 |       status = regcache->cooked_read (IA64_CFM_REGNUM, &cfm); | 
 |       if (status != REG_VALID) | 
 | 	return status; | 
 |  | 
 |       /* The bsp points at the end of the register frame so we | 
 | 	 subtract the size of frame from it to get beginning of frame.  */ | 
 |       vbsp = rse_address_add (bsp, -(cfm & 0x7f)); | 
 |       store_unsigned_integer (buf, register_size (gdbarch, regnum), | 
 | 			      byte_order, vbsp); | 
 |     } | 
 |   else if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM) | 
 |     { | 
 |       ULONGEST pr; | 
 |       ULONGEST cfm; | 
 |       ULONGEST prN_val; | 
 |  | 
 |       status = regcache->cooked_read (IA64_PR_REGNUM, &pr); | 
 |       if (status != REG_VALID) | 
 | 	return status; | 
 |       status = regcache->cooked_read (IA64_CFM_REGNUM, &cfm); | 
 |       if (status != REG_VALID) | 
 | 	return status; | 
 |  | 
 |       if (VP16_REGNUM <= regnum && regnum <= VP63_REGNUM) | 
 | 	{ | 
 | 	  /* Fetch predicate register rename base from current frame | 
 | 	     marker for this frame.  */ | 
 | 	  int rrb_pr = (cfm >> 32) & 0x3f; | 
 |  | 
 | 	  /* Adjust the register number to account for register rotation.  */ | 
 | 	  regnum = VP16_REGNUM  | 
 | 		 + ((regnum - VP16_REGNUM) + rrb_pr) % 48; | 
 | 	} | 
 |       prN_val = (pr & (1LL << (regnum - VP0_REGNUM))) != 0; | 
 |       store_unsigned_integer (buf, register_size (gdbarch, regnum), | 
 | 			      byte_order, prN_val); | 
 |     } | 
 |   else | 
 |     memset (buf, 0, register_size (gdbarch, regnum)); | 
 |  | 
 |   return REG_VALID; | 
 | } | 
 |  | 
 | static void | 
 | ia64_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, | 
 | 			    int regnum, const gdb_byte *buf) | 
 | { | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |  | 
 |   if (regnum >= V32_REGNUM && regnum <= V127_REGNUM) | 
 |     { | 
 |       ULONGEST bsp; | 
 |       ULONGEST cfm; | 
 |       regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp); | 
 |       regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm); | 
 |  | 
 |       bsp = rse_address_add (bsp, -(cfm & 0x7f)); | 
 |   | 
 |       if ((cfm & 0x7f) > regnum - V32_REGNUM)  | 
 | 	{ | 
 | 	  ULONGEST reg_addr = rse_address_add (bsp, (regnum - V32_REGNUM)); | 
 | 	  write_memory (reg_addr, buf, 8); | 
 | 	} | 
 |     } | 
 |   else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT31_REGNUM) | 
 |     { | 
 |       ULONGEST unatN_val, unat, unatN_mask; | 
 |       regcache_cooked_read_unsigned (regcache, IA64_UNAT_REGNUM, &unat); | 
 |       unatN_val = extract_unsigned_integer (buf, register_size (gdbarch, | 
 | 								regnum), | 
 | 					    byte_order); | 
 |       unatN_mask = (1LL << (regnum - IA64_NAT0_REGNUM)); | 
 |       if (unatN_val == 0) | 
 | 	unat &= ~unatN_mask; | 
 |       else if (unatN_val == 1) | 
 | 	unat |= unatN_mask; | 
 |       regcache_cooked_write_unsigned (regcache, IA64_UNAT_REGNUM, unat); | 
 |     } | 
 |   else if (IA64_NAT32_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM) | 
 |     { | 
 |       ULONGEST natN_val; | 
 |       ULONGEST bsp; | 
 |       ULONGEST cfm; | 
 |       CORE_ADDR gr_addr = 0; | 
 |       regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp); | 
 |       regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm); | 
 |  | 
 |       /* The bsp points at the end of the register frame so we | 
 | 	 subtract the size of frame from it to get start of register frame.  */ | 
 |       bsp = rse_address_add (bsp, -(cfm & 0x7f)); | 
 |   | 
 |       if ((cfm & 0x7f) > regnum - V32_REGNUM)  | 
 | 	gr_addr = rse_address_add (bsp, (regnum - V32_REGNUM)); | 
 |        | 
 |       natN_val = extract_unsigned_integer (buf, register_size (gdbarch, | 
 | 							       regnum), | 
 | 					   byte_order); | 
 |  | 
 |       if (gr_addr != 0 && (natN_val == 0 || natN_val == 1)) | 
 | 	{ | 
 | 	  /* Compute address of nat collection bits.  */ | 
 | 	  CORE_ADDR nat_addr = gr_addr | 0x1f8; | 
 | 	  CORE_ADDR nat_collection; | 
 | 	  int natN_bit = (gr_addr >> 3) & 0x3f; | 
 | 	  ULONGEST natN_mask = (1LL << natN_bit); | 
 | 	  /* If our nat collection address is bigger than bsp, we have to get | 
 | 	     the nat collection from rnat.  Otherwise, we fetch the nat | 
 | 	     collection from the computed address.  */ | 
 | 	  if (nat_addr >= bsp) | 
 | 	    { | 
 | 	      regcache_cooked_read_unsigned (regcache, | 
 | 					     IA64_RNAT_REGNUM, | 
 | 					     &nat_collection); | 
 | 	      if (natN_val) | 
 | 		nat_collection |= natN_mask; | 
 | 	      else | 
 | 		nat_collection &= ~natN_mask; | 
 | 	      regcache_cooked_write_unsigned (regcache, IA64_RNAT_REGNUM, | 
 | 					      nat_collection); | 
 | 	    } | 
 | 	  else | 
 | 	    { | 
 | 	      gdb_byte nat_buf[8]; | 
 | 	      nat_collection = read_memory_integer (nat_addr, 8, byte_order); | 
 | 	      if (natN_val) | 
 | 		nat_collection |= natN_mask; | 
 | 	      else | 
 | 		nat_collection &= ~natN_mask; | 
 | 	      store_unsigned_integer (nat_buf, register_size (gdbarch, regnum), | 
 | 				      byte_order, nat_collection); | 
 | 	      write_memory (nat_addr, nat_buf, 8); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |   else if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM) | 
 |     { | 
 |       ULONGEST pr; | 
 |       ULONGEST cfm; | 
 |       ULONGEST prN_val; | 
 |       ULONGEST prN_mask; | 
 |  | 
 |       regcache_cooked_read_unsigned (regcache, IA64_PR_REGNUM, &pr); | 
 |       regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm); | 
 |  | 
 |       if (VP16_REGNUM <= regnum && regnum <= VP63_REGNUM) | 
 | 	{ | 
 | 	  /* Fetch predicate register rename base from current frame | 
 | 	     marker for this frame.  */ | 
 | 	  int rrb_pr = (cfm >> 32) & 0x3f; | 
 |  | 
 | 	  /* Adjust the register number to account for register rotation.  */ | 
 | 	  regnum = VP16_REGNUM  | 
 | 		 + ((regnum - VP16_REGNUM) + rrb_pr) % 48; | 
 | 	} | 
 |       prN_val = extract_unsigned_integer (buf, register_size (gdbarch, regnum), | 
 | 					  byte_order); | 
 |       prN_mask = (1LL << (regnum - VP0_REGNUM)); | 
 |       if (prN_val == 0) | 
 | 	pr &= ~prN_mask; | 
 |       else if (prN_val == 1) | 
 | 	pr |= prN_mask; | 
 |       regcache_cooked_write_unsigned (regcache, IA64_PR_REGNUM, pr); | 
 |     } | 
 | } | 
 |  | 
 | /* The ia64 needs to convert between various ieee floating-point formats | 
 |    and the special ia64 floating point register format.  */ | 
 |  | 
 | static int | 
 | ia64_convert_register_p (struct gdbarch *gdbarch, int regno, struct type *type) | 
 | { | 
 |   return (regno >= IA64_FR0_REGNUM && regno <= IA64_FR127_REGNUM | 
 | 	  && type->code () == TYPE_CODE_FLT | 
 | 	  && type != ia64_ext_type (gdbarch)); | 
 | } | 
 |  | 
 | static int | 
 | ia64_register_to_value (frame_info_ptr frame, int regnum, | 
 | 			struct type *valtype, gdb_byte *out, | 
 | 			int *optimizedp, int *unavailablep) | 
 | { | 
 |   struct gdbarch *gdbarch = get_frame_arch (frame); | 
 |   gdb_byte in[IA64_FP_REGISTER_SIZE]; | 
 |  | 
 |   /* Convert to TYPE.  */ | 
 |   if (!get_frame_register_bytes (frame, regnum, 0, | 
 | 				 gdb::make_array_view (in, | 
 | 						       register_size (gdbarch, | 
 | 								      regnum)), | 
 | 				 optimizedp, unavailablep)) | 
 |     return 0; | 
 |  | 
 |   target_float_convert (in, ia64_ext_type (gdbarch), out, valtype); | 
 |   *optimizedp = *unavailablep = 0; | 
 |   return 1; | 
 | } | 
 |  | 
 | static void | 
 | ia64_value_to_register (frame_info_ptr frame, int regnum, | 
 | 			 struct type *valtype, const gdb_byte *in) | 
 | { | 
 |   struct gdbarch *gdbarch = get_frame_arch (frame); | 
 |   gdb_byte out[IA64_FP_REGISTER_SIZE]; | 
 |   target_float_convert (in, valtype, out, ia64_ext_type (gdbarch)); | 
 |   put_frame_register (frame, regnum, out); | 
 | } | 
 |  | 
 |  | 
 | /* Limit the number of skipped non-prologue instructions since examining | 
 |    of the prologue is expensive.  */ | 
 | static int max_skip_non_prologue_insns = 40; | 
 |  | 
 | /* Given PC representing the starting address of a function, and | 
 |    LIM_PC which is the (sloppy) limit to which to scan when looking | 
 |    for a prologue, attempt to further refine this limit by using | 
 |    the line data in the symbol table.  If successful, a better guess | 
 |    on where the prologue ends is returned, otherwise the previous | 
 |    value of lim_pc is returned.  TRUST_LIMIT is a pointer to a flag | 
 |    which will be set to indicate whether the returned limit may be | 
 |    used with no further scanning in the event that the function is | 
 |    frameless.  */ | 
 |  | 
 | /* FIXME: cagney/2004-02-14: This function and logic have largely been | 
 |    superseded by skip_prologue_using_sal.  */ | 
 |  | 
 | static CORE_ADDR | 
 | refine_prologue_limit (CORE_ADDR pc, CORE_ADDR lim_pc, int *trust_limit) | 
 | { | 
 |   struct symtab_and_line prologue_sal; | 
 |   CORE_ADDR start_pc = pc; | 
 |   CORE_ADDR end_pc; | 
 |  | 
 |   /* The prologue can not possibly go past the function end itself, | 
 |      so we can already adjust LIM_PC accordingly.  */ | 
 |   if (find_pc_partial_function (pc, NULL, NULL, &end_pc) && end_pc < lim_pc) | 
 |     lim_pc = end_pc; | 
 |  | 
 |   /* Start off not trusting the limit.  */ | 
 |   *trust_limit = 0; | 
 |  | 
 |   prologue_sal = find_pc_line (pc, 0); | 
 |   if (prologue_sal.line != 0) | 
 |     { | 
 |       int i; | 
 |       CORE_ADDR addr = prologue_sal.end; | 
 |  | 
 |       /* Handle the case in which compiler's optimizer/scheduler | 
 | 	 has moved instructions into the prologue.  We scan ahead | 
 | 	 in the function looking for address ranges whose corresponding | 
 | 	 line number is less than or equal to the first one that we | 
 | 	 found for the function.  (It can be less than when the | 
 | 	 scheduler puts a body instruction before the first prologue | 
 | 	 instruction.)  */ | 
 |       for (i = 2 * max_skip_non_prologue_insns;  | 
 | 	   i > 0 && (lim_pc == 0 || addr < lim_pc); | 
 | 	   i--) | 
 | 	{ | 
 | 	  struct symtab_and_line sal; | 
 |  | 
 | 	  sal = find_pc_line (addr, 0); | 
 | 	  if (sal.line == 0) | 
 | 	    break; | 
 | 	  if (sal.line <= prologue_sal.line  | 
 | 	      && sal.symtab == prologue_sal.symtab) | 
 | 	    { | 
 | 	      prologue_sal = sal; | 
 | 	    } | 
 | 	  addr = sal.end; | 
 | 	} | 
 |  | 
 |       if (lim_pc == 0 || prologue_sal.end < lim_pc) | 
 | 	{ | 
 | 	  lim_pc = prologue_sal.end; | 
 | 	  if (start_pc == get_pc_function_start (lim_pc)) | 
 | 	    *trust_limit = 1; | 
 | 	} | 
 |     } | 
 |   return lim_pc; | 
 | } | 
 |  | 
 | #define isScratch(_regnum_) ((_regnum_) == 2 || (_regnum_) == 3 \ | 
 |   || (8 <= (_regnum_) && (_regnum_) <= 11) \ | 
 |   || (14 <= (_regnum_) && (_regnum_) <= 31)) | 
 | #define imm9(_instr_) \ | 
 |   ( ((((_instr_) & 0x01000000000LL) ? -1 : 0) << 8) \ | 
 |    | (((_instr_) & 0x00008000000LL) >> 20) \ | 
 |    | (((_instr_) & 0x00000001fc0LL) >> 6)) | 
 |  | 
 | /* Allocate and initialize a frame cache.  */ | 
 |  | 
 | static struct ia64_frame_cache * | 
 | ia64_alloc_frame_cache (void) | 
 | { | 
 |   struct ia64_frame_cache *cache; | 
 |   int i; | 
 |  | 
 |   cache = FRAME_OBSTACK_ZALLOC (struct ia64_frame_cache); | 
 |  | 
 |   /* Base address.  */ | 
 |   cache->base = 0; | 
 |   cache->pc = 0; | 
 |   cache->cfm = 0; | 
 |   cache->prev_cfm = 0; | 
 |   cache->sof = 0; | 
 |   cache->sol = 0; | 
 |   cache->sor = 0; | 
 |   cache->bsp = 0; | 
 |   cache->fp_reg = 0; | 
 |   cache->frameless = 1; | 
 |  | 
 |   for (i = 0; i < NUM_IA64_RAW_REGS; i++) | 
 |     cache->saved_regs[i] = 0; | 
 |  | 
 |   return cache; | 
 | } | 
 |  | 
 | static CORE_ADDR | 
 | examine_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, | 
 | 		  frame_info_ptr this_frame, | 
 | 		  struct ia64_frame_cache *cache) | 
 | { | 
 |   CORE_ADDR next_pc; | 
 |   CORE_ADDR last_prologue_pc = pc; | 
 |   ia64_instruction_type it; | 
 |   long long instr; | 
 |   int cfm_reg  = 0; | 
 |   int ret_reg  = 0; | 
 |   int fp_reg   = 0; | 
 |   int unat_save_reg = 0; | 
 |   int pr_save_reg = 0; | 
 |   int mem_stack_frame_size = 0; | 
 |   int spill_reg   = 0; | 
 |   CORE_ADDR spill_addr = 0; | 
 |   char instores[8]; | 
 |   char infpstores[8]; | 
 |   char reg_contents[256]; | 
 |   int trust_limit; | 
 |   int frameless = 1; | 
 |   int i; | 
 |   CORE_ADDR addr; | 
 |   gdb_byte buf[8]; | 
 |   CORE_ADDR bof, sor, sol, sof, cfm, rrb_gr; | 
 |  | 
 |   memset (instores, 0, sizeof instores); | 
 |   memset (infpstores, 0, sizeof infpstores); | 
 |   memset (reg_contents, 0, sizeof reg_contents); | 
 |  | 
 |   if (cache->after_prologue != 0 | 
 |       && cache->after_prologue <= lim_pc) | 
 |     return cache->after_prologue; | 
 |  | 
 |   lim_pc = refine_prologue_limit (pc, lim_pc, &trust_limit); | 
 |   next_pc = fetch_instruction (pc, &it, &instr); | 
 |  | 
 |   /* We want to check if we have a recognizable function start before we | 
 |      look ahead for a prologue.  */ | 
 |   if (pc < lim_pc && next_pc  | 
 |       && it == M && ((instr & 0x1ee0000003fLL) == 0x02c00000000LL)) | 
 |     { | 
 |       /* alloc - start of a regular function.  */ | 
 |       int sol_bits = (int) ((instr & 0x00007f00000LL) >> 20); | 
 |       int sof_bits = (int) ((instr & 0x000000fe000LL) >> 13); | 
 |       int rN = (int) ((instr & 0x00000001fc0LL) >> 6); | 
 |  | 
 |       /* Verify that the current cfm matches what we think is the | 
 | 	 function start.  If we have somehow jumped within a function, | 
 | 	 we do not want to interpret the prologue and calculate the | 
 | 	 addresses of various registers such as the return address. | 
 | 	 We will instead treat the frame as frameless.  */ | 
 |       if (!this_frame || | 
 | 	  (sof_bits == (cache->cfm & 0x7f) && | 
 | 	   sol_bits == ((cache->cfm >> 7) & 0x7f))) | 
 | 	frameless = 0; | 
 |  | 
 |       cfm_reg = rN; | 
 |       last_prologue_pc = next_pc; | 
 |       pc = next_pc; | 
 |     } | 
 |   else | 
 |     { | 
 |       /* Look for a leaf routine.  */ | 
 |       if (pc < lim_pc && next_pc | 
 | 	  && (it == I || it == M)  | 
 | 	  && ((instr & 0x1ee00000000LL) == 0x10800000000LL)) | 
 | 	{ | 
 | 	  /* adds rN = imm14, rM   (or mov rN, rM  when imm14 is 0) */ | 
 | 	  int imm = (int) ((((instr & 0x01000000000LL) ? -1 : 0) << 13)  | 
 | 			   | ((instr & 0x001f8000000LL) >> 20) | 
 | 			   | ((instr & 0x000000fe000LL) >> 13)); | 
 | 	  int rM = (int) ((instr & 0x00007f00000LL) >> 20); | 
 | 	  int rN = (int) ((instr & 0x00000001fc0LL) >> 6); | 
 | 	  int qp = (int) (instr & 0x0000000003fLL); | 
 | 	  if (qp == 0 && rN == 2 && imm == 0 && rM == 12 && fp_reg == 0) | 
 | 	    { | 
 | 	      /* mov r2, r12 - beginning of leaf routine.  */ | 
 | 	      fp_reg = rN; | 
 | 	      last_prologue_pc = next_pc; | 
 | 	    } | 
 | 	}  | 
 |  | 
 |       /* If we don't recognize a regular function or leaf routine, we are | 
 | 	 done.  */ | 
 |       if (!fp_reg) | 
 | 	{ | 
 | 	  pc = lim_pc;	 | 
 | 	  if (trust_limit) | 
 | 	    last_prologue_pc = lim_pc; | 
 | 	} | 
 |     } | 
 |  | 
 |   /* Loop, looking for prologue instructions, keeping track of | 
 |      where preserved registers were spilled.  */ | 
 |   while (pc < lim_pc) | 
 |     { | 
 |       next_pc = fetch_instruction (pc, &it, &instr); | 
 |       if (next_pc == 0) | 
 | 	break; | 
 |  | 
 |       if (it == B && ((instr & 0x1e1f800003fLL) != 0x04000000000LL)) | 
 | 	{ | 
 | 	  /* Exit loop upon hitting a non-nop branch instruction.  */  | 
 | 	  if (trust_limit) | 
 | 	    lim_pc = pc; | 
 | 	  break; | 
 | 	} | 
 |       else if (((instr & 0x3fLL) != 0LL) &&  | 
 | 	       (frameless || ret_reg != 0)) | 
 | 	{ | 
 | 	  /* Exit loop upon hitting a predicated instruction if | 
 | 	     we already have the return register or if we are frameless.  */  | 
 | 	  if (trust_limit) | 
 | 	    lim_pc = pc; | 
 | 	  break; | 
 | 	} | 
 |       else if (it == I && ((instr & 0x1eff8000000LL) == 0x00188000000LL)) | 
 | 	{ | 
 | 	  /* Move from BR */ | 
 | 	  int b2 = (int) ((instr & 0x0000000e000LL) >> 13); | 
 | 	  int rN = (int) ((instr & 0x00000001fc0LL) >> 6); | 
 | 	  int qp = (int) (instr & 0x0000000003f); | 
 |  | 
 | 	  if (qp == 0 && b2 == 0 && rN >= 32 && ret_reg == 0) | 
 | 	    { | 
 | 	      ret_reg = rN; | 
 | 	      last_prologue_pc = next_pc; | 
 | 	    } | 
 | 	} | 
 |       else if ((it == I || it == M)  | 
 | 	  && ((instr & 0x1ee00000000LL) == 0x10800000000LL)) | 
 | 	{ | 
 | 	  /* adds rN = imm14, rM   (or mov rN, rM  when imm14 is 0) */ | 
 | 	  int imm = (int) ((((instr & 0x01000000000LL) ? -1 : 0) << 13)  | 
 | 			   | ((instr & 0x001f8000000LL) >> 20) | 
 | 			   | ((instr & 0x000000fe000LL) >> 13)); | 
 | 	  int rM = (int) ((instr & 0x00007f00000LL) >> 20); | 
 | 	  int rN = (int) ((instr & 0x00000001fc0LL) >> 6); | 
 | 	  int qp = (int) (instr & 0x0000000003fLL); | 
 |  | 
 | 	  if (qp == 0 && rN >= 32 && imm == 0 && rM == 12 && fp_reg == 0) | 
 | 	    { | 
 | 	      /* mov rN, r12 */ | 
 | 	      fp_reg = rN; | 
 | 	      last_prologue_pc = next_pc; | 
 | 	    } | 
 | 	  else if (qp == 0 && rN == 12 && rM == 12) | 
 | 	    { | 
 | 	      /* adds r12, -mem_stack_frame_size, r12 */ | 
 | 	      mem_stack_frame_size -= imm; | 
 | 	      last_prologue_pc = next_pc; | 
 | 	    } | 
 | 	  else if (qp == 0 && rN == 2  | 
 | 		&& ((rM == fp_reg && fp_reg != 0) || rM == 12)) | 
 | 	    { | 
 | 	      CORE_ADDR saved_sp = 0; | 
 | 	      /* adds r2, spilloffset, rFramePointer  | 
 | 		   or | 
 | 		 adds r2, spilloffset, r12 | 
 |  | 
 | 		 Get ready for stf.spill or st8.spill instructions. | 
 | 		 The address to start spilling at is loaded into r2. | 
 | 		 FIXME:  Why r2?  That's what gcc currently uses; it | 
 | 		 could well be different for other compilers.  */ | 
 |  | 
 | 	      /* Hmm...  whether or not this will work will depend on | 
 | 		 where the pc is.  If it's still early in the prologue | 
 | 		 this'll be wrong.  FIXME */ | 
 | 	      if (this_frame) | 
 | 		saved_sp = get_frame_register_unsigned (this_frame, | 
 | 							sp_regnum); | 
 | 	      spill_addr  = saved_sp | 
 | 			  + (rM == 12 ? 0 : mem_stack_frame_size)  | 
 | 			  + imm; | 
 | 	      spill_reg   = rN; | 
 | 	      last_prologue_pc = next_pc; | 
 | 	    } | 
 | 	  else if (qp == 0 && rM >= 32 && rM < 40 && !instores[rM-32] &&  | 
 | 		   rN < 256 && imm == 0) | 
 | 	    { | 
 | 	      /* mov rN, rM where rM is an input register.  */ | 
 | 	      reg_contents[rN] = rM; | 
 | 	      last_prologue_pc = next_pc; | 
 | 	    } | 
 | 	  else if (frameless && qp == 0 && rN == fp_reg && imm == 0 &&  | 
 | 		   rM == 2) | 
 | 	    { | 
 | 	      /* mov r12, r2 */ | 
 | 	      last_prologue_pc = next_pc; | 
 | 	      break; | 
 | 	    } | 
 | 	} | 
 |       else if (it == M  | 
 | 	    && (   ((instr & 0x1efc0000000LL) == 0x0eec0000000LL) | 
 | 		|| ((instr & 0x1ffc8000000LL) == 0x0cec0000000LL) )) | 
 | 	{ | 
 | 	  /* stf.spill [rN] = fM, imm9 | 
 | 	     or | 
 | 	     stf.spill [rN] = fM  */ | 
 |  | 
 | 	  int imm = imm9(instr); | 
 | 	  int rN = (int) ((instr & 0x00007f00000LL) >> 20); | 
 | 	  int fM = (int) ((instr & 0x000000fe000LL) >> 13); | 
 | 	  int qp = (int) (instr & 0x0000000003fLL); | 
 | 	  if (qp == 0 && rN == spill_reg && spill_addr != 0 | 
 | 	      && ((2 <= fM && fM <= 5) || (16 <= fM && fM <= 31))) | 
 | 	    { | 
 | 	      cache->saved_regs[IA64_FR0_REGNUM + fM] = spill_addr; | 
 |  | 
 | 	      if ((instr & 0x1efc0000000LL) == 0x0eec0000000LL) | 
 | 		spill_addr += imm; | 
 | 	      else | 
 | 		spill_addr = 0;		/* last one; must be done.  */ | 
 | 	      last_prologue_pc = next_pc; | 
 | 	    } | 
 | 	} | 
 |       else if ((it == M && ((instr & 0x1eff8000000LL) == 0x02110000000LL)) | 
 | 	    || (it == I && ((instr & 0x1eff8000000LL) == 0x00050000000LL)) ) | 
 | 	{ | 
 | 	  /* mov.m rN = arM    | 
 | 	       or  | 
 | 	     mov.i rN = arM */ | 
 |  | 
 | 	  int arM = (int) ((instr & 0x00007f00000LL) >> 20); | 
 | 	  int rN  = (int) ((instr & 0x00000001fc0LL) >> 6); | 
 | 	  int qp  = (int) (instr & 0x0000000003fLL); | 
 | 	  if (qp == 0 && isScratch (rN) && arM == 36 /* ar.unat */) | 
 | 	    { | 
 | 	      /* We have something like "mov.m r3 = ar.unat".  Remember the | 
 | 		 r3 (or whatever) and watch for a store of this register...  */ | 
 | 	      unat_save_reg = rN; | 
 | 	      last_prologue_pc = next_pc; | 
 | 	    } | 
 | 	} | 
 |       else if (it == I && ((instr & 0x1eff8000000LL) == 0x00198000000LL)) | 
 | 	{ | 
 | 	  /* mov rN = pr */ | 
 | 	  int rN  = (int) ((instr & 0x00000001fc0LL) >> 6); | 
 | 	  int qp  = (int) (instr & 0x0000000003fLL); | 
 | 	  if (qp == 0 && isScratch (rN)) | 
 | 	    { | 
 | 	      pr_save_reg = rN; | 
 | 	      last_prologue_pc = next_pc; | 
 | 	    } | 
 | 	} | 
 |       else if (it == M  | 
 | 	    && (   ((instr & 0x1ffc8000000LL) == 0x08cc0000000LL) | 
 | 		|| ((instr & 0x1efc0000000LL) == 0x0acc0000000LL))) | 
 | 	{ | 
 | 	  /* st8 [rN] = rM  | 
 | 	      or | 
 | 	     st8 [rN] = rM, imm9 */ | 
 | 	  int rN = (int) ((instr & 0x00007f00000LL) >> 20); | 
 | 	  int rM = (int) ((instr & 0x000000fe000LL) >> 13); | 
 | 	  int qp = (int) (instr & 0x0000000003fLL); | 
 | 	  int indirect = rM < 256 ? reg_contents[rM] : 0; | 
 | 	  if (qp == 0 && rN == spill_reg && spill_addr != 0 | 
 | 	      && (rM == unat_save_reg || rM == pr_save_reg)) | 
 | 	    { | 
 | 	      /* We've found a spill of either the UNAT register or the PR | 
 | 		 register.  (Well, not exactly; what we've actually found is | 
 | 		 a spill of the register that UNAT or PR was moved to). | 
 | 		 Record that fact and move on...  */ | 
 | 	      if (rM == unat_save_reg) | 
 | 		{ | 
 | 		  /* Track UNAT register.  */ | 
 | 		  cache->saved_regs[IA64_UNAT_REGNUM] = spill_addr; | 
 | 		  unat_save_reg = 0; | 
 | 		} | 
 | 	      else | 
 | 		{ | 
 | 		  /* Track PR register.  */ | 
 | 		  cache->saved_regs[IA64_PR_REGNUM] = spill_addr; | 
 | 		  pr_save_reg = 0; | 
 | 		} | 
 | 	      if ((instr & 0x1efc0000000LL) == 0x0acc0000000LL) | 
 | 		/* st8 [rN] = rM, imm9 */ | 
 | 		spill_addr += imm9(instr); | 
 | 	      else | 
 | 		spill_addr = 0;		/* Must be done spilling.  */ | 
 | 	      last_prologue_pc = next_pc; | 
 | 	    } | 
 | 	  else if (qp == 0 && 32 <= rM && rM < 40 && !instores[rM-32]) | 
 | 	    { | 
 | 	      /* Allow up to one store of each input register.  */ | 
 | 	      instores[rM-32] = 1; | 
 | 	      last_prologue_pc = next_pc; | 
 | 	    } | 
 | 	  else if (qp == 0 && 32 <= indirect && indirect < 40 &&  | 
 | 		   !instores[indirect-32]) | 
 | 	    { | 
 | 	      /* Allow an indirect store of an input register.  */ | 
 | 	      instores[indirect-32] = 1; | 
 | 	      last_prologue_pc = next_pc; | 
 | 	    } | 
 | 	} | 
 |       else if (it == M && ((instr & 0x1ff08000000LL) == 0x08c00000000LL)) | 
 | 	{ | 
 | 	  /* One of | 
 | 	       st1 [rN] = rM | 
 | 	       st2 [rN] = rM | 
 | 	       st4 [rN] = rM | 
 | 	       st8 [rN] = rM | 
 | 	     Note that the st8 case is handled in the clause above. | 
 | 	      | 
 | 	     Advance over stores of input registers.  One store per input | 
 | 	     register is permitted.  */ | 
 | 	  int rM = (int) ((instr & 0x000000fe000LL) >> 13); | 
 | 	  int qp = (int) (instr & 0x0000000003fLL); | 
 | 	  int indirect = rM < 256 ? reg_contents[rM] : 0; | 
 | 	  if (qp == 0 && 32 <= rM && rM < 40 && !instores[rM-32]) | 
 | 	    { | 
 | 	      instores[rM-32] = 1; | 
 | 	      last_prologue_pc = next_pc; | 
 | 	    } | 
 | 	  else if (qp == 0 && 32 <= indirect && indirect < 40 &&  | 
 | 		   !instores[indirect-32]) | 
 | 	    { | 
 | 	      /* Allow an indirect store of an input register.  */ | 
 | 	      instores[indirect-32] = 1; | 
 | 	      last_prologue_pc = next_pc; | 
 | 	    } | 
 | 	} | 
 |       else if (it == M && ((instr & 0x1ff88000000LL) == 0x0cc80000000LL)) | 
 | 	{ | 
 | 	  /* Either | 
 | 	       stfs [rN] = fM | 
 | 	     or | 
 | 	       stfd [rN] = fM | 
 |  | 
 | 	     Advance over stores of floating point input registers.  Again | 
 | 	     one store per register is permitted.  */ | 
 | 	  int fM = (int) ((instr & 0x000000fe000LL) >> 13); | 
 | 	  int qp = (int) (instr & 0x0000000003fLL); | 
 | 	  if (qp == 0 && 8 <= fM && fM < 16 && !infpstores[fM - 8]) | 
 | 	    { | 
 | 	      infpstores[fM-8] = 1; | 
 | 	      last_prologue_pc = next_pc; | 
 | 	    } | 
 | 	} | 
 |       else if (it == M | 
 | 	    && (   ((instr & 0x1ffc8000000LL) == 0x08ec0000000LL) | 
 | 		|| ((instr & 0x1efc0000000LL) == 0x0aec0000000LL))) | 
 | 	{ | 
 | 	  /* st8.spill [rN] = rM | 
 | 	       or | 
 | 	     st8.spill [rN] = rM, imm9 */ | 
 | 	  int rN = (int) ((instr & 0x00007f00000LL) >> 20); | 
 | 	  int rM = (int) ((instr & 0x000000fe000LL) >> 13); | 
 | 	  int qp = (int) (instr & 0x0000000003fLL); | 
 | 	  if (qp == 0 && rN == spill_reg && 4 <= rM && rM <= 7) | 
 | 	    { | 
 | 	      /* We've found a spill of one of the preserved general purpose | 
 | 		 regs.  Record the spill address and advance the spill | 
 | 		 register if appropriate.  */ | 
 | 	      cache->saved_regs[IA64_GR0_REGNUM + rM] = spill_addr; | 
 | 	      if ((instr & 0x1efc0000000LL) == 0x0aec0000000LL) | 
 | 		/* st8.spill [rN] = rM, imm9 */ | 
 | 		spill_addr += imm9(instr); | 
 | 	      else | 
 | 		spill_addr = 0;		/* Done spilling.  */ | 
 | 	      last_prologue_pc = next_pc; | 
 | 	    } | 
 | 	} | 
 |  | 
 |       pc = next_pc; | 
 |     } | 
 |  | 
 |   /* If not frameless and we aren't called by skip_prologue, then we need | 
 |      to calculate registers for the previous frame which will be needed | 
 |      later.  */ | 
 |  | 
 |   if (!frameless && this_frame) | 
 |     { | 
 |       struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 |       enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |  | 
 |       /* Extract the size of the rotating portion of the stack | 
 | 	 frame and the register rename base from the current | 
 | 	 frame marker.  */ | 
 |       cfm = cache->cfm; | 
 |       sor = cache->sor; | 
 |       sof = cache->sof; | 
 |       sol = cache->sol; | 
 |       rrb_gr = (cfm >> 18) & 0x7f; | 
 |  | 
 |       /* Find the bof (beginning of frame).  */ | 
 |       bof = rse_address_add (cache->bsp, -sof); | 
 |        | 
 |       for (i = 0, addr = bof; | 
 | 	   i < sof; | 
 | 	   i++, addr += 8) | 
 | 	{ | 
 | 	  if (IS_NaT_COLLECTION_ADDR (addr)) | 
 | 	    { | 
 | 	      addr += 8; | 
 | 	    } | 
 | 	  if (i+32 == cfm_reg) | 
 | 	    cache->saved_regs[IA64_CFM_REGNUM] = addr; | 
 | 	  if (i+32 == ret_reg) | 
 | 	    cache->saved_regs[IA64_VRAP_REGNUM] = addr; | 
 | 	  if (i+32 == fp_reg) | 
 | 	    cache->saved_regs[IA64_VFP_REGNUM] = addr; | 
 | 	} | 
 |  | 
 |       /* For the previous argument registers we require the previous bof. | 
 | 	 If we can't find the previous cfm, then we can do nothing.  */ | 
 |       cfm = 0; | 
 |       if (cache->saved_regs[IA64_CFM_REGNUM] != 0) | 
 | 	{ | 
 | 	  cfm = read_memory_integer (cache->saved_regs[IA64_CFM_REGNUM], | 
 | 				     8, byte_order); | 
 | 	} | 
 |       else if (cfm_reg != 0) | 
 | 	{ | 
 | 	  get_frame_register (this_frame, cfm_reg, buf); | 
 | 	  cfm = extract_unsigned_integer (buf, 8, byte_order); | 
 | 	} | 
 |       cache->prev_cfm = cfm; | 
 |        | 
 |       if (cfm != 0) | 
 | 	{ | 
 | 	  sor = ((cfm >> 14) & 0xf) * 8; | 
 | 	  sof = (cfm & 0x7f); | 
 | 	  sol = (cfm >> 7) & 0x7f; | 
 | 	  rrb_gr = (cfm >> 18) & 0x7f; | 
 |  | 
 | 	  /* The previous bof only requires subtraction of the sol (size of | 
 | 	     locals) due to the overlap between output and input of | 
 | 	     subsequent frames.  */ | 
 | 	  bof = rse_address_add (bof, -sol); | 
 | 	   | 
 | 	  for (i = 0, addr = bof; | 
 | 	       i < sof; | 
 | 	       i++, addr += 8) | 
 | 	    { | 
 | 	      if (IS_NaT_COLLECTION_ADDR (addr)) | 
 | 		{ | 
 | 		  addr += 8; | 
 | 		} | 
 | 	      if (i < sor) | 
 | 		cache->saved_regs[IA64_GR32_REGNUM | 
 | 				  + ((i + (sor - rrb_gr)) % sor)]  | 
 | 		  = addr; | 
 | 	      else | 
 | 		cache->saved_regs[IA64_GR32_REGNUM + i] = addr; | 
 | 	    } | 
 | 	   | 
 | 	} | 
 |     } | 
 |        | 
 |   /* Try and trust the lim_pc value whenever possible.  */ | 
 |   if (trust_limit && lim_pc >= last_prologue_pc) | 
 |     last_prologue_pc = lim_pc; | 
 |  | 
 |   cache->frameless = frameless; | 
 |   cache->after_prologue = last_prologue_pc; | 
 |   cache->mem_stack_frame_size = mem_stack_frame_size; | 
 |   cache->fp_reg = fp_reg; | 
 |  | 
 |   return last_prologue_pc; | 
 | } | 
 |  | 
 | CORE_ADDR | 
 | ia64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) | 
 | { | 
 |   struct ia64_frame_cache cache; | 
 |   cache.base = 0; | 
 |   cache.after_prologue = 0; | 
 |   cache.cfm = 0; | 
 |   cache.bsp = 0; | 
 |  | 
 |   /* Call examine_prologue with - as third argument since we don't | 
 |      have a next frame pointer to send.  */ | 
 |   return examine_prologue (pc, pc+1024, 0, &cache); | 
 | } | 
 |  | 
 |  | 
 | /* Normal frames.  */ | 
 |  | 
 | static struct ia64_frame_cache * | 
 | ia64_frame_cache (frame_info_ptr this_frame, void **this_cache) | 
 | { | 
 |   struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   struct ia64_frame_cache *cache; | 
 |   gdb_byte buf[8]; | 
 |   CORE_ADDR cfm; | 
 |  | 
 |   if (*this_cache) | 
 |     return (struct ia64_frame_cache *) *this_cache; | 
 |  | 
 |   cache = ia64_alloc_frame_cache (); | 
 |   *this_cache = cache; | 
 |  | 
 |   get_frame_register (this_frame, sp_regnum, buf); | 
 |   cache->saved_sp = extract_unsigned_integer (buf, 8, byte_order); | 
 |  | 
 |   /* We always want the bsp to point to the end of frame. | 
 |      This way, we can always get the beginning of frame (bof) | 
 |      by subtracting frame size.  */ | 
 |   get_frame_register (this_frame, IA64_BSP_REGNUM, buf); | 
 |   cache->bsp = extract_unsigned_integer (buf, 8, byte_order); | 
 |    | 
 |   get_frame_register (this_frame, IA64_PSR_REGNUM, buf); | 
 |  | 
 |   get_frame_register (this_frame, IA64_CFM_REGNUM, buf); | 
 |   cfm = extract_unsigned_integer (buf, 8, byte_order); | 
 |  | 
 |   cache->sof = (cfm & 0x7f); | 
 |   cache->sol = (cfm >> 7) & 0x7f; | 
 |   cache->sor = ((cfm >> 14) & 0xf) * 8; | 
 |  | 
 |   cache->cfm = cfm; | 
 |  | 
 |   cache->pc = get_frame_func (this_frame); | 
 |  | 
 |   if (cache->pc != 0) | 
 |     examine_prologue (cache->pc, get_frame_pc (this_frame), this_frame, cache); | 
 |    | 
 |   cache->base = cache->saved_sp + cache->mem_stack_frame_size; | 
 |  | 
 |   return cache; | 
 | } | 
 |  | 
 | static void | 
 | ia64_frame_this_id (frame_info_ptr this_frame, void **this_cache, | 
 | 		    struct frame_id *this_id) | 
 | { | 
 |   struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 |   struct ia64_frame_cache *cache = | 
 |     ia64_frame_cache (this_frame, this_cache); | 
 |  | 
 |   /* If outermost frame, mark with null frame id.  */ | 
 |   if (cache->base != 0) | 
 |     (*this_id) = frame_id_build_special (cache->base, cache->pc, cache->bsp); | 
 |   if (gdbarch_debug >= 1) | 
 |     gdb_printf (gdb_stdlog, | 
 | 		"regular frame id: code %s, stack %s, " | 
 | 		"special %s, this_frame %s\n", | 
 | 		paddress (gdbarch, this_id->code_addr), | 
 | 		paddress (gdbarch, this_id->stack_addr), | 
 | 		paddress (gdbarch, cache->bsp), | 
 | 		host_address_to_string (this_frame.get ())); | 
 | } | 
 |  | 
 | static struct value * | 
 | ia64_frame_prev_register (frame_info_ptr this_frame, void **this_cache, | 
 | 			  int regnum) | 
 | { | 
 |   struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   struct ia64_frame_cache *cache = ia64_frame_cache (this_frame, this_cache); | 
 |   gdb_byte buf[8]; | 
 |  | 
 |   gdb_assert (regnum >= 0); | 
 |  | 
 |   if (!target_has_registers ()) | 
 |     error (_("No registers.")); | 
 |  | 
 |   if (regnum == gdbarch_sp_regnum (gdbarch)) | 
 |     return frame_unwind_got_constant (this_frame, regnum, cache->base); | 
 |  | 
 |   else if (regnum == IA64_BSP_REGNUM) | 
 |     { | 
 |       struct value *val; | 
 |       CORE_ADDR prev_cfm, bsp, prev_bsp; | 
 |  | 
 |       /* We want to calculate the previous bsp as the end of the previous | 
 | 	 register stack frame.  This corresponds to what the hardware bsp | 
 | 	 register will be if we pop the frame back which is why we might | 
 | 	 have been called.  We know the beginning of the current frame is | 
 | 	 cache->bsp - cache->sof.  This value in the previous frame points | 
 | 	 to the start of the output registers.  We can calculate the end of | 
 | 	 that frame by adding the size of output: | 
 | 	    (sof (size of frame) - sol (size of locals)).  */ | 
 |       val = ia64_frame_prev_register (this_frame, this_cache, IA64_CFM_REGNUM); | 
 |       prev_cfm = extract_unsigned_integer (val->contents_all ().data (), | 
 | 					   8, byte_order); | 
 |       bsp = rse_address_add (cache->bsp, -(cache->sof)); | 
 |       prev_bsp = | 
 | 	rse_address_add (bsp, (prev_cfm & 0x7f) - ((prev_cfm >> 7) & 0x7f)); | 
 |  | 
 |       return frame_unwind_got_constant (this_frame, regnum, prev_bsp); | 
 |     } | 
 |  | 
 |   else if (regnum == IA64_CFM_REGNUM) | 
 |     { | 
 |       CORE_ADDR addr = cache->saved_regs[IA64_CFM_REGNUM]; | 
 |        | 
 |       if (addr != 0) | 
 | 	return frame_unwind_got_memory (this_frame, regnum, addr); | 
 |  | 
 |       if (cache->prev_cfm) | 
 | 	return frame_unwind_got_constant (this_frame, regnum, cache->prev_cfm); | 
 |  | 
 |       if (cache->frameless) | 
 | 	return frame_unwind_got_register (this_frame, IA64_PFS_REGNUM, | 
 | 					  IA64_PFS_REGNUM); | 
 |       return frame_unwind_got_register (this_frame, regnum, 0); | 
 |     } | 
 |  | 
 |   else if (regnum == IA64_VFP_REGNUM) | 
 |     { | 
 |       /* If the function in question uses an automatic register (r32-r127) | 
 | 	 for the frame pointer, it'll be found by ia64_find_saved_register() | 
 | 	 above.  If the function lacks one of these frame pointers, we can | 
 | 	 still provide a value since we know the size of the frame.  */ | 
 |       return frame_unwind_got_constant (this_frame, regnum, cache->base); | 
 |     } | 
 |  | 
 |   else if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM) | 
 |     { | 
 |       struct value *pr_val; | 
 |       ULONGEST prN; | 
 |        | 
 |       pr_val = ia64_frame_prev_register (this_frame, this_cache, | 
 | 					 IA64_PR_REGNUM); | 
 |       if (VP16_REGNUM <= regnum && regnum <= VP63_REGNUM) | 
 | 	{ | 
 | 	  /* Fetch predicate register rename base from current frame | 
 | 	     marker for this frame.  */ | 
 | 	  int rrb_pr = (cache->cfm >> 32) & 0x3f; | 
 |  | 
 | 	  /* Adjust the register number to account for register rotation.  */ | 
 | 	  regnum = VP16_REGNUM + ((regnum - VP16_REGNUM) + rrb_pr) % 48; | 
 | 	} | 
 |       prN = extract_bit_field (pr_val->contents_all ().data (), | 
 | 			       regnum - VP0_REGNUM, 1); | 
 |       return frame_unwind_got_constant (this_frame, regnum, prN); | 
 |     } | 
 |  | 
 |   else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT31_REGNUM) | 
 |     { | 
 |       struct value *unat_val; | 
 |       ULONGEST unatN; | 
 |       unat_val = ia64_frame_prev_register (this_frame, this_cache, | 
 | 					   IA64_UNAT_REGNUM); | 
 |       unatN = extract_bit_field (unat_val->contents_all ().data (), | 
 | 				 regnum - IA64_NAT0_REGNUM, 1); | 
 |       return frame_unwind_got_constant (this_frame, regnum, unatN); | 
 |     } | 
 |  | 
 |   else if (IA64_NAT32_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM) | 
 |     { | 
 |       int natval = 0; | 
 |       /* Find address of general register corresponding to nat bit we're | 
 | 	 interested in.  */ | 
 |       CORE_ADDR gr_addr; | 
 |  | 
 |       gr_addr = cache->saved_regs[regnum - IA64_NAT0_REGNUM + IA64_GR0_REGNUM]; | 
 |  | 
 |       if (gr_addr != 0) | 
 | 	{ | 
 | 	  /* Compute address of nat collection bits.  */ | 
 | 	  CORE_ADDR nat_addr = gr_addr | 0x1f8; | 
 | 	  CORE_ADDR bsp; | 
 | 	  CORE_ADDR nat_collection; | 
 | 	  int nat_bit; | 
 |  | 
 | 	  /* If our nat collection address is bigger than bsp, we have to get | 
 | 	     the nat collection from rnat.  Otherwise, we fetch the nat | 
 | 	     collection from the computed address.  */ | 
 | 	  get_frame_register (this_frame, IA64_BSP_REGNUM, buf); | 
 | 	  bsp = extract_unsigned_integer (buf, 8, byte_order); | 
 | 	  if (nat_addr >= bsp) | 
 | 	    { | 
 | 	      get_frame_register (this_frame, IA64_RNAT_REGNUM, buf); | 
 | 	      nat_collection = extract_unsigned_integer (buf, 8, byte_order); | 
 | 	    } | 
 | 	  else | 
 | 	    nat_collection = read_memory_integer (nat_addr, 8, byte_order); | 
 | 	  nat_bit = (gr_addr >> 3) & 0x3f; | 
 | 	  natval = (nat_collection >> nat_bit) & 1; | 
 | 	} | 
 |  | 
 |       return frame_unwind_got_constant (this_frame, regnum, natval); | 
 |     } | 
 |  | 
 |   else if (regnum == IA64_IP_REGNUM) | 
 |     { | 
 |       CORE_ADDR pc = 0; | 
 |       CORE_ADDR addr = cache->saved_regs[IA64_VRAP_REGNUM]; | 
 |  | 
 |       if (addr != 0) | 
 | 	{ | 
 | 	  read_memory (addr, buf, register_size (gdbarch, IA64_IP_REGNUM)); | 
 | 	  pc = extract_unsigned_integer (buf, 8, byte_order); | 
 | 	} | 
 |       else if (cache->frameless) | 
 | 	{ | 
 | 	  get_frame_register (this_frame, IA64_BR0_REGNUM, buf); | 
 | 	  pc = extract_unsigned_integer (buf, 8, byte_order); | 
 | 	} | 
 |       pc &= ~0xf; | 
 |       return frame_unwind_got_constant (this_frame, regnum, pc); | 
 |     } | 
 |  | 
 |   else if (regnum == IA64_PSR_REGNUM) | 
 |     { | 
 |       /* We don't know how to get the complete previous PSR, but we need it | 
 | 	 for the slot information when we unwind the pc (pc is formed of IP | 
 | 	 register plus slot information from PSR).  To get the previous | 
 | 	 slot information, we mask it off the return address.  */ | 
 |       ULONGEST slot_num = 0; | 
 |       CORE_ADDR pc = 0; | 
 |       CORE_ADDR psr = 0; | 
 |       CORE_ADDR addr = cache->saved_regs[IA64_VRAP_REGNUM]; | 
 |  | 
 |       get_frame_register (this_frame, IA64_PSR_REGNUM, buf); | 
 |       psr = extract_unsigned_integer (buf, 8, byte_order); | 
 |  | 
 |       if (addr != 0) | 
 | 	{ | 
 | 	  read_memory (addr, buf, register_size (gdbarch, IA64_IP_REGNUM)); | 
 | 	  pc = extract_unsigned_integer (buf, 8, byte_order); | 
 | 	} | 
 |       else if (cache->frameless) | 
 | 	{ | 
 | 	  get_frame_register (this_frame, IA64_BR0_REGNUM, buf); | 
 | 	  pc = extract_unsigned_integer (buf, 8, byte_order); | 
 | 	} | 
 |       psr &= ~(3LL << 41); | 
 |       slot_num = pc & 0x3LL; | 
 |       psr |= (CORE_ADDR)slot_num << 41; | 
 |       return frame_unwind_got_constant (this_frame, regnum, psr); | 
 |     } | 
 |  | 
 |   else if (regnum == IA64_BR0_REGNUM) | 
 |     { | 
 |       CORE_ADDR addr = cache->saved_regs[IA64_BR0_REGNUM]; | 
 |  | 
 |       if (addr != 0) | 
 | 	return frame_unwind_got_memory (this_frame, regnum, addr); | 
 |  | 
 |       return frame_unwind_got_constant (this_frame, regnum, 0); | 
 |     } | 
 |  | 
 |   else if ((regnum >= IA64_GR32_REGNUM && regnum <= IA64_GR127_REGNUM) | 
 | 	   || (regnum >= V32_REGNUM && regnum <= V127_REGNUM)) | 
 |     { | 
 |       CORE_ADDR addr = 0; | 
 |  | 
 |       if (regnum >= V32_REGNUM) | 
 | 	regnum = IA64_GR32_REGNUM + (regnum - V32_REGNUM); | 
 |       addr = cache->saved_regs[regnum]; | 
 |       if (addr != 0) | 
 | 	return frame_unwind_got_memory (this_frame, regnum, addr); | 
 |  | 
 |       if (cache->frameless) | 
 | 	{ | 
 | 	  struct value *reg_val; | 
 | 	  CORE_ADDR prev_cfm, prev_bsp, prev_bof; | 
 |  | 
 | 	  /* FIXME: brobecker/2008-05-01: Doesn't this seem redundant | 
 | 	     with the same code above?  */ | 
 | 	  if (regnum >= V32_REGNUM) | 
 | 	    regnum = IA64_GR32_REGNUM + (regnum - V32_REGNUM); | 
 | 	  reg_val = ia64_frame_prev_register (this_frame, this_cache, | 
 | 					      IA64_CFM_REGNUM); | 
 | 	  prev_cfm = extract_unsigned_integer | 
 | 	    (reg_val->contents_all ().data (), 8, byte_order); | 
 | 	  reg_val = ia64_frame_prev_register (this_frame, this_cache, | 
 | 					      IA64_BSP_REGNUM); | 
 | 	  prev_bsp = extract_unsigned_integer | 
 | 	    (reg_val->contents_all ().data (), 8, byte_order); | 
 | 	  prev_bof = rse_address_add (prev_bsp, -(prev_cfm & 0x7f)); | 
 |  | 
 | 	  addr = rse_address_add (prev_bof, (regnum - IA64_GR32_REGNUM)); | 
 | 	  return frame_unwind_got_memory (this_frame, regnum, addr); | 
 | 	} | 
 |        | 
 |       return frame_unwind_got_constant (this_frame, regnum, 0); | 
 |     } | 
 |  | 
 |   else /* All other registers.  */ | 
 |     { | 
 |       CORE_ADDR addr = 0; | 
 |  | 
 |       if (IA64_FR32_REGNUM <= regnum && regnum <= IA64_FR127_REGNUM) | 
 | 	{ | 
 | 	  /* Fetch floating point register rename base from current | 
 | 	     frame marker for this frame.  */ | 
 | 	  int rrb_fr = (cache->cfm >> 25) & 0x7f; | 
 |  | 
 | 	  /* Adjust the floating point register number to account for | 
 | 	     register rotation.  */ | 
 | 	  regnum = IA64_FR32_REGNUM | 
 | 		 + ((regnum - IA64_FR32_REGNUM) + rrb_fr) % 96; | 
 | 	} | 
 |  | 
 |       /* If we have stored a memory address, access the register.  */ | 
 |       addr = cache->saved_regs[regnum]; | 
 |       if (addr != 0) | 
 | 	return frame_unwind_got_memory (this_frame, regnum, addr); | 
 |       /* Otherwise, punt and get the current value of the register.  */ | 
 |       else  | 
 | 	return frame_unwind_got_register (this_frame, regnum, regnum); | 
 |     } | 
 | } | 
 |   | 
 | static const struct frame_unwind ia64_frame_unwind = | 
 | { | 
 |   "ia64 prologue", | 
 |   NORMAL_FRAME, | 
 |   default_frame_unwind_stop_reason, | 
 |   &ia64_frame_this_id, | 
 |   &ia64_frame_prev_register, | 
 |   NULL, | 
 |   default_frame_sniffer | 
 | }; | 
 |  | 
 | /* Signal trampolines.  */ | 
 |  | 
 | static void | 
 | ia64_sigtramp_frame_init_saved_regs (frame_info_ptr this_frame, | 
 | 				     struct ia64_frame_cache *cache) | 
 | { | 
 |   struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 |   ia64_gdbarch_tdep *tdep = gdbarch_tdep<ia64_gdbarch_tdep> (gdbarch); | 
 |  | 
 |   if (tdep->sigcontext_register_address) | 
 |     { | 
 |       int regno; | 
 |  | 
 |       cache->saved_regs[IA64_VRAP_REGNUM] | 
 | 	= tdep->sigcontext_register_address (gdbarch, cache->base, | 
 | 					     IA64_IP_REGNUM); | 
 |       cache->saved_regs[IA64_CFM_REGNUM] | 
 | 	= tdep->sigcontext_register_address (gdbarch, cache->base, | 
 | 					     IA64_CFM_REGNUM); | 
 |       cache->saved_regs[IA64_PSR_REGNUM] | 
 | 	= tdep->sigcontext_register_address (gdbarch, cache->base, | 
 | 					     IA64_PSR_REGNUM); | 
 |       cache->saved_regs[IA64_BSP_REGNUM] | 
 | 	= tdep->sigcontext_register_address (gdbarch, cache->base, | 
 | 					     IA64_BSP_REGNUM); | 
 |       cache->saved_regs[IA64_RNAT_REGNUM] | 
 | 	= tdep->sigcontext_register_address (gdbarch, cache->base, | 
 | 					     IA64_RNAT_REGNUM); | 
 |       cache->saved_regs[IA64_CCV_REGNUM] | 
 | 	= tdep->sigcontext_register_address (gdbarch, cache->base, | 
 | 					     IA64_CCV_REGNUM); | 
 |       cache->saved_regs[IA64_UNAT_REGNUM] | 
 | 	= tdep->sigcontext_register_address (gdbarch, cache->base, | 
 | 					     IA64_UNAT_REGNUM); | 
 |       cache->saved_regs[IA64_FPSR_REGNUM] | 
 | 	= tdep->sigcontext_register_address (gdbarch, cache->base, | 
 | 					     IA64_FPSR_REGNUM); | 
 |       cache->saved_regs[IA64_PFS_REGNUM] | 
 | 	= tdep->sigcontext_register_address (gdbarch, cache->base, | 
 | 					     IA64_PFS_REGNUM); | 
 |       cache->saved_regs[IA64_LC_REGNUM] | 
 | 	= tdep->sigcontext_register_address (gdbarch, cache->base, | 
 | 					     IA64_LC_REGNUM); | 
 |  | 
 |       for (regno = IA64_GR1_REGNUM; regno <= IA64_GR31_REGNUM; regno++) | 
 | 	cache->saved_regs[regno] = | 
 | 	  tdep->sigcontext_register_address (gdbarch, cache->base, regno); | 
 |       for (regno = IA64_BR0_REGNUM; regno <= IA64_BR7_REGNUM; regno++) | 
 | 	cache->saved_regs[regno] = | 
 | 	  tdep->sigcontext_register_address (gdbarch, cache->base, regno); | 
 |       for (regno = IA64_FR2_REGNUM; regno <= IA64_FR31_REGNUM; regno++) | 
 | 	cache->saved_regs[regno] = | 
 | 	  tdep->sigcontext_register_address (gdbarch, cache->base, regno); | 
 |     } | 
 | } | 
 |  | 
 | static struct ia64_frame_cache * | 
 | ia64_sigtramp_frame_cache (frame_info_ptr this_frame, void **this_cache) | 
 | { | 
 |   struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   struct ia64_frame_cache *cache; | 
 |   gdb_byte buf[8]; | 
 |  | 
 |   if (*this_cache) | 
 |     return (struct ia64_frame_cache *) *this_cache; | 
 |  | 
 |   cache = ia64_alloc_frame_cache (); | 
 |  | 
 |   get_frame_register (this_frame, sp_regnum, buf); | 
 |   /* Note that frame size is hard-coded below.  We cannot calculate it | 
 |      via prologue examination.  */ | 
 |   cache->base = extract_unsigned_integer (buf, 8, byte_order) + 16; | 
 |  | 
 |   get_frame_register (this_frame, IA64_BSP_REGNUM, buf); | 
 |   cache->bsp = extract_unsigned_integer (buf, 8, byte_order); | 
 |  | 
 |   get_frame_register (this_frame, IA64_CFM_REGNUM, buf); | 
 |   cache->cfm = extract_unsigned_integer (buf, 8, byte_order); | 
 |   cache->sof = cache->cfm & 0x7f; | 
 |  | 
 |   ia64_sigtramp_frame_init_saved_regs (this_frame, cache); | 
 |  | 
 |   *this_cache = cache; | 
 |   return cache; | 
 | } | 
 |  | 
 | static void | 
 | ia64_sigtramp_frame_this_id (frame_info_ptr this_frame, | 
 | 			     void **this_cache, struct frame_id *this_id) | 
 | { | 
 |   struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 |   struct ia64_frame_cache *cache = | 
 |     ia64_sigtramp_frame_cache (this_frame, this_cache); | 
 |  | 
 |   (*this_id) = frame_id_build_special (cache->base, | 
 | 				       get_frame_pc (this_frame), | 
 | 				       cache->bsp); | 
 |   if (gdbarch_debug >= 1) | 
 |     gdb_printf (gdb_stdlog, | 
 | 		"sigtramp frame id: code %s, stack %s, " | 
 | 		"special %s, this_frame %s\n", | 
 | 		paddress (gdbarch, this_id->code_addr), | 
 | 		paddress (gdbarch, this_id->stack_addr), | 
 | 		paddress (gdbarch, cache->bsp), | 
 | 		host_address_to_string (this_frame.get ())); | 
 | } | 
 |  | 
 | static struct value * | 
 | ia64_sigtramp_frame_prev_register (frame_info_ptr this_frame, | 
 | 				   void **this_cache, int regnum) | 
 | { | 
 |   struct ia64_frame_cache *cache = | 
 |     ia64_sigtramp_frame_cache (this_frame, this_cache); | 
 |  | 
 |   gdb_assert (regnum >= 0); | 
 |  | 
 |   if (!target_has_registers ()) | 
 |     error (_("No registers.")); | 
 |  | 
 |   if (regnum == IA64_IP_REGNUM) | 
 |     { | 
 |       CORE_ADDR pc = 0; | 
 |       CORE_ADDR addr = cache->saved_regs[IA64_VRAP_REGNUM]; | 
 |  | 
 |       if (addr != 0) | 
 | 	{ | 
 | 	  struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 | 	  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 | 	  pc = read_memory_unsigned_integer (addr, 8, byte_order); | 
 | 	} | 
 |       pc &= ~0xf; | 
 |       return frame_unwind_got_constant (this_frame, regnum, pc); | 
 |     } | 
 |  | 
 |   else if ((regnum >= IA64_GR32_REGNUM && regnum <= IA64_GR127_REGNUM) | 
 | 	   || (regnum >= V32_REGNUM && regnum <= V127_REGNUM)) | 
 |     { | 
 |       CORE_ADDR addr = 0; | 
 |  | 
 |       if (regnum >= V32_REGNUM) | 
 | 	regnum = IA64_GR32_REGNUM + (regnum - V32_REGNUM); | 
 |       addr = cache->saved_regs[regnum]; | 
 |       if (addr != 0) | 
 | 	return frame_unwind_got_memory (this_frame, regnum, addr); | 
 |  | 
 |       return frame_unwind_got_constant (this_frame, regnum, 0); | 
 |     } | 
 |  | 
 |   else  /* All other registers not listed above.  */ | 
 |     { | 
 |       CORE_ADDR addr = cache->saved_regs[regnum]; | 
 |  | 
 |       if (addr != 0) | 
 | 	return frame_unwind_got_memory (this_frame, regnum, addr); | 
 |  | 
 |       return frame_unwind_got_constant (this_frame, regnum, 0); | 
 |     } | 
 | } | 
 |  | 
 | static int | 
 | ia64_sigtramp_frame_sniffer (const struct frame_unwind *self, | 
 | 			     frame_info_ptr this_frame, | 
 | 			     void **this_cache) | 
 | { | 
 |   gdbarch *arch = get_frame_arch (this_frame); | 
 |   ia64_gdbarch_tdep *tdep = gdbarch_tdep<ia64_gdbarch_tdep> (arch); | 
 |   if (tdep->pc_in_sigtramp) | 
 |     { | 
 |       CORE_ADDR pc = get_frame_pc (this_frame); | 
 |  | 
 |       if (tdep->pc_in_sigtramp (pc)) | 
 | 	return 1; | 
 |     } | 
 |  | 
 |   return 0; | 
 | } | 
 |  | 
 | static const struct frame_unwind ia64_sigtramp_frame_unwind = | 
 | { | 
 |   "ia64 sigtramp", | 
 |   SIGTRAMP_FRAME, | 
 |   default_frame_unwind_stop_reason, | 
 |   ia64_sigtramp_frame_this_id, | 
 |   ia64_sigtramp_frame_prev_register, | 
 |   NULL, | 
 |   ia64_sigtramp_frame_sniffer | 
 | }; | 
 |  | 
 |  | 
 |  | 
 | static CORE_ADDR | 
 | ia64_frame_base_address (frame_info_ptr this_frame, void **this_cache) | 
 | { | 
 |   struct ia64_frame_cache *cache = ia64_frame_cache (this_frame, this_cache); | 
 |  | 
 |   return cache->base; | 
 | } | 
 |  | 
 | static const struct frame_base ia64_frame_base = | 
 | { | 
 |   &ia64_frame_unwind, | 
 |   ia64_frame_base_address, | 
 |   ia64_frame_base_address, | 
 |   ia64_frame_base_address | 
 | }; | 
 |  | 
 | #ifdef HAVE_LIBUNWIND_IA64_H | 
 |  | 
 | struct ia64_unwind_table_entry | 
 |   { | 
 |     unw_word_t start_offset; | 
 |     unw_word_t end_offset; | 
 |     unw_word_t info_offset; | 
 |   }; | 
 |  | 
 | static __inline__ uint64_t | 
 | ia64_rse_slot_num (uint64_t addr) | 
 | { | 
 |   return (addr >> 3) & 0x3f; | 
 | } | 
 |  | 
 | /* Skip over a designated number of registers in the backing | 
 |    store, remembering every 64th position is for NAT.  */ | 
 | static __inline__ uint64_t | 
 | ia64_rse_skip_regs (uint64_t addr, long num_regs) | 
 | { | 
 |   long delta = ia64_rse_slot_num(addr) + num_regs; | 
 |  | 
 |   if (num_regs < 0) | 
 |     delta -= 0x3e; | 
 |   return addr + ((num_regs + delta/0x3f) << 3); | 
 | } | 
 |    | 
 | /* Gdb ia64-libunwind-tdep callback function to convert from an ia64 gdb | 
 |    register number to a libunwind register number.  */ | 
 | static int | 
 | ia64_gdb2uw_regnum (int regnum) | 
 | { | 
 |   if (regnum == sp_regnum) | 
 |     return UNW_IA64_SP; | 
 |   else if (regnum == IA64_BSP_REGNUM) | 
 |     return UNW_IA64_BSP; | 
 |   else if ((unsigned) (regnum - IA64_GR0_REGNUM) < 128) | 
 |     return UNW_IA64_GR + (regnum - IA64_GR0_REGNUM); | 
 |   else if ((unsigned) (regnum - V32_REGNUM) < 95) | 
 |     return UNW_IA64_GR + 32 + (regnum - V32_REGNUM); | 
 |   else if ((unsigned) (regnum - IA64_FR0_REGNUM) < 128) | 
 |     return UNW_IA64_FR + (regnum - IA64_FR0_REGNUM); | 
 |   else if ((unsigned) (regnum - IA64_PR0_REGNUM) < 64) | 
 |     return -1; | 
 |   else if ((unsigned) (regnum - IA64_BR0_REGNUM) < 8) | 
 |     return UNW_IA64_BR + (regnum - IA64_BR0_REGNUM); | 
 |   else if (regnum == IA64_PR_REGNUM) | 
 |     return UNW_IA64_PR; | 
 |   else if (regnum == IA64_IP_REGNUM) | 
 |     return UNW_REG_IP; | 
 |   else if (regnum == IA64_CFM_REGNUM) | 
 |     return UNW_IA64_CFM; | 
 |   else if ((unsigned) (regnum - IA64_AR0_REGNUM) < 128) | 
 |     return UNW_IA64_AR + (regnum - IA64_AR0_REGNUM); | 
 |   else if ((unsigned) (regnum - IA64_NAT0_REGNUM) < 128) | 
 |     return UNW_IA64_NAT + (regnum - IA64_NAT0_REGNUM); | 
 |   else | 
 |     return -1; | 
 | } | 
 |    | 
 | /* Gdb ia64-libunwind-tdep callback function to convert from a libunwind | 
 |    register number to a ia64 gdb register number.  */ | 
 | static int | 
 | ia64_uw2gdb_regnum (int uw_regnum) | 
 | { | 
 |   if (uw_regnum == UNW_IA64_SP) | 
 |     return sp_regnum; | 
 |   else if (uw_regnum == UNW_IA64_BSP) | 
 |     return IA64_BSP_REGNUM; | 
 |   else if ((unsigned) (uw_regnum - UNW_IA64_GR) < 32) | 
 |     return IA64_GR0_REGNUM + (uw_regnum - UNW_IA64_GR); | 
 |   else if ((unsigned) (uw_regnum - UNW_IA64_GR) < 128) | 
 |     return V32_REGNUM + (uw_regnum - (IA64_GR0_REGNUM + 32)); | 
 |   else if ((unsigned) (uw_regnum - UNW_IA64_FR) < 128) | 
 |     return IA64_FR0_REGNUM + (uw_regnum - UNW_IA64_FR); | 
 |   else if ((unsigned) (uw_regnum - UNW_IA64_BR) < 8) | 
 |     return IA64_BR0_REGNUM + (uw_regnum - UNW_IA64_BR); | 
 |   else if (uw_regnum == UNW_IA64_PR) | 
 |     return IA64_PR_REGNUM; | 
 |   else if (uw_regnum == UNW_REG_IP) | 
 |     return IA64_IP_REGNUM; | 
 |   else if (uw_regnum == UNW_IA64_CFM) | 
 |     return IA64_CFM_REGNUM; | 
 |   else if ((unsigned) (uw_regnum - UNW_IA64_AR) < 128) | 
 |     return IA64_AR0_REGNUM + (uw_regnum - UNW_IA64_AR); | 
 |   else if ((unsigned) (uw_regnum - UNW_IA64_NAT) < 128) | 
 |     return IA64_NAT0_REGNUM + (uw_regnum - UNW_IA64_NAT); | 
 |   else | 
 |     return -1; | 
 | } | 
 |  | 
 | /* Gdb ia64-libunwind-tdep callback function to reveal if register is | 
 |    a float register or not.  */ | 
 | static int | 
 | ia64_is_fpreg (int uw_regnum) | 
 | { | 
 |   return unw_is_fpreg (uw_regnum); | 
 | } | 
 |  | 
 | /* Libunwind callback accessor function for general registers.  */ | 
 | static int | 
 | ia64_access_reg (unw_addr_space_t as, unw_regnum_t uw_regnum, unw_word_t *val,  | 
 | 		 int write, void *arg) | 
 | { | 
 |   int regnum = ia64_uw2gdb_regnum (uw_regnum); | 
 |   unw_word_t bsp, sof, cfm, psr, ip; | 
 |   struct frame_info *this_frame = (frame_info *) arg; | 
 |   struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 |   ia64_gdbarch_tdep *tdep = gdbarch_tdep<ia64_gdbarch_tdep> (gdbarch); | 
 |    | 
 |   /* We never call any libunwind routines that need to write registers.  */ | 
 |   gdb_assert (!write); | 
 |  | 
 |   switch (uw_regnum) | 
 |     { | 
 |       case UNW_REG_IP: | 
 | 	/* Libunwind expects to see the pc value which means the slot number | 
 | 	   from the psr must be merged with the ip word address.  */ | 
 | 	ip = get_frame_register_unsigned (this_frame, IA64_IP_REGNUM); | 
 | 	psr = get_frame_register_unsigned (this_frame, IA64_PSR_REGNUM); | 
 | 	*val = ip | ((psr >> 41) & 0x3); | 
 | 	break; | 
 |   | 
 |       case UNW_IA64_AR_BSP: | 
 | 	/* Libunwind expects to see the beginning of the current | 
 | 	   register frame so we must account for the fact that | 
 | 	   ptrace() will return a value for bsp that points *after* | 
 | 	   the current register frame.  */ | 
 | 	bsp = get_frame_register_unsigned (this_frame, IA64_BSP_REGNUM); | 
 | 	cfm = get_frame_register_unsigned (this_frame, IA64_CFM_REGNUM); | 
 | 	sof = tdep->size_of_register_frame (this_frame, cfm); | 
 | 	*val = ia64_rse_skip_regs (bsp, -sof); | 
 | 	break; | 
 |  | 
 |       case UNW_IA64_AR_BSPSTORE: | 
 | 	/* Libunwind wants bspstore to be after the current register frame. | 
 | 	   This is what ptrace() and gdb treats as the regular bsp value.  */ | 
 | 	*val = get_frame_register_unsigned (this_frame, IA64_BSP_REGNUM); | 
 | 	break; | 
 |  | 
 |       default: | 
 | 	/* For all other registers, just unwind the value directly.  */ | 
 | 	*val = get_frame_register_unsigned (this_frame, regnum); | 
 | 	break; | 
 |     } | 
 |        | 
 |   if (gdbarch_debug >= 1) | 
 |     gdb_printf (gdb_stdlog,  | 
 | 		"  access_reg: from cache: %4s=%s\n", | 
 | 		(((unsigned) regnum <= IA64_NAT127_REGNUM) | 
 | 		 ? ia64_register_names[regnum] : "r??"),  | 
 | 		paddress (gdbarch, *val)); | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Libunwind callback accessor function for floating-point registers.  */ | 
 | static int | 
 | ia64_access_fpreg (unw_addr_space_t as, unw_regnum_t uw_regnum, | 
 | 		   unw_fpreg_t *val, int write, void *arg) | 
 | { | 
 |   int regnum = ia64_uw2gdb_regnum (uw_regnum); | 
 |   frame_info_ptr this_frame = (frame_info_ptr) arg; | 
 |    | 
 |   /* We never call any libunwind routines that need to write registers.  */ | 
 |   gdb_assert (!write); | 
 |  | 
 |   get_frame_register (this_frame, regnum, (gdb_byte *) val); | 
 |  | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Libunwind callback accessor function for top-level rse registers.  */ | 
 | static int | 
 | ia64_access_rse_reg (unw_addr_space_t as, unw_regnum_t uw_regnum, | 
 | 		     unw_word_t *val, int write, void *arg) | 
 | { | 
 |   int regnum = ia64_uw2gdb_regnum (uw_regnum); | 
 |   unw_word_t bsp, sof, cfm, psr, ip; | 
 |   struct regcache *regcache = (struct regcache *) arg; | 
 |   struct gdbarch *gdbarch = regcache->arch (); | 
 |    | 
 |   /* We never call any libunwind routines that need to write registers.  */ | 
 |   gdb_assert (!write); | 
 |  | 
 |   switch (uw_regnum) | 
 |     { | 
 |       case UNW_REG_IP: | 
 | 	/* Libunwind expects to see the pc value which means the slot number | 
 | 	   from the psr must be merged with the ip word address.  */ | 
 | 	regcache_cooked_read_unsigned (regcache, IA64_IP_REGNUM, &ip); | 
 | 	regcache_cooked_read_unsigned (regcache, IA64_PSR_REGNUM, &psr); | 
 | 	*val = ip | ((psr >> 41) & 0x3); | 
 | 	break; | 
 | 	   | 
 |       case UNW_IA64_AR_BSP: | 
 | 	/* Libunwind expects to see the beginning of the current | 
 | 	   register frame so we must account for the fact that | 
 | 	   ptrace() will return a value for bsp that points *after* | 
 | 	   the current register frame.  */ | 
 | 	regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp); | 
 | 	regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm); | 
 | 	sof = (cfm & 0x7f); | 
 | 	*val = ia64_rse_skip_regs (bsp, -sof); | 
 | 	break; | 
 | 	   | 
 |       case UNW_IA64_AR_BSPSTORE: | 
 | 	/* Libunwind wants bspstore to be after the current register frame. | 
 | 	   This is what ptrace() and gdb treats as the regular bsp value.  */ | 
 | 	regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, val); | 
 | 	break; | 
 |  | 
 |       default: | 
 | 	/* For all other registers, just unwind the value directly.  */ | 
 | 	regcache_cooked_read_unsigned (regcache, regnum, val); | 
 | 	break; | 
 |     } | 
 |        | 
 |   if (gdbarch_debug >= 1) | 
 |     gdb_printf (gdb_stdlog,  | 
 | 		"  access_rse_reg: from cache: %4s=%s\n", | 
 | 		(((unsigned) regnum <= IA64_NAT127_REGNUM) | 
 | 		 ? ia64_register_names[regnum] : "r??"),  | 
 | 		paddress (gdbarch, *val)); | 
 |  | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Libunwind callback accessor function for top-level fp registers.  */ | 
 | static int | 
 | ia64_access_rse_fpreg (unw_addr_space_t as, unw_regnum_t uw_regnum, | 
 | 		       unw_fpreg_t *val, int write, void *arg) | 
 | { | 
 |   int regnum = ia64_uw2gdb_regnum (uw_regnum); | 
 |   struct regcache *regcache = (struct regcache *) arg; | 
 |    | 
 |   /* We never call any libunwind routines that need to write registers.  */ | 
 |   gdb_assert (!write); | 
 |  | 
 |   regcache->cooked_read (regnum, (gdb_byte *) val); | 
 |  | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Libunwind callback accessor function for accessing memory.  */ | 
 | static int | 
 | ia64_access_mem (unw_addr_space_t as, | 
 | 		 unw_word_t addr, unw_word_t *val, | 
 | 		 int write, void *arg) | 
 | { | 
 |   if (addr - KERNEL_START < ktab_size) | 
 |     { | 
 |       unw_word_t *laddr = (unw_word_t*) ((char *) ktab | 
 | 			  + (addr - KERNEL_START)); | 
 | 		 | 
 |       if (write) | 
 | 	*laddr = *val;  | 
 |       else  | 
 | 	*val = *laddr; | 
 |       return 0; | 
 |     } | 
 |  | 
 |   /* XXX do we need to normalize byte-order here?  */ | 
 |   if (write) | 
 |     return target_write_memory (addr, (gdb_byte *) val, sizeof (unw_word_t)); | 
 |   else | 
 |     return target_read_memory (addr, (gdb_byte *) val, sizeof (unw_word_t)); | 
 | } | 
 |  | 
 | /* Call low-level function to access the kernel unwind table.  */ | 
 | static gdb::optional<gdb::byte_vector> | 
 | getunwind_table () | 
 | { | 
 |   /* FIXME drow/2005-09-10: This code used to call | 
 |      ia64_linux_xfer_unwind_table directly to fetch the unwind table | 
 |      for the currently running ia64-linux kernel.  That data should | 
 |      come from the core file and be accessed via the auxv vector; if | 
 |      we want to preserve fall back to the running kernel's table, then | 
 |      we should find a way to override the corefile layer's | 
 |      xfer_partial method.  */ | 
 |  | 
 |   return target_read_alloc (current_inferior ()->top_target (), | 
 | 			    TARGET_OBJECT_UNWIND_TABLE, NULL); | 
 | } | 
 |  | 
 | /* Get the kernel unwind table.  */				  | 
 | static int | 
 | get_kernel_table (unw_word_t ip, unw_dyn_info_t *di) | 
 | { | 
 |   static struct ia64_table_entry *etab; | 
 |  | 
 |   if (!ktab)  | 
 |     { | 
 |       ktab_buf = getunwind_table (); | 
 |       if (!ktab_buf) | 
 | 	return -UNW_ENOINFO; | 
 |  | 
 |       ktab = (struct ia64_table_entry *) ktab_buf->data (); | 
 |       ktab_size = ktab_buf->size (); | 
 |  | 
 |       for (etab = ktab; etab->start_offset; ++etab) | 
 | 	etab->info_offset += KERNEL_START; | 
 |     } | 
 |    | 
 |   if (ip < ktab[0].start_offset || ip >= etab[-1].end_offset) | 
 |     return -UNW_ENOINFO; | 
 |    | 
 |   di->format = UNW_INFO_FORMAT_TABLE; | 
 |   di->gp = 0; | 
 |   di->start_ip = ktab[0].start_offset; | 
 |   di->end_ip = etab[-1].end_offset; | 
 |   di->u.ti.name_ptr = (unw_word_t) "<kernel>"; | 
 |   di->u.ti.segbase = 0; | 
 |   di->u.ti.table_len = ((char *) etab - (char *) ktab) / sizeof (unw_word_t); | 
 |   di->u.ti.table_data = (unw_word_t *) ktab; | 
 |    | 
 |   if (gdbarch_debug >= 1) | 
 |     gdb_printf (gdb_stdlog, "get_kernel_table: found table `%s': " | 
 | 		"segbase=%s, length=%s, gp=%s\n", | 
 | 		(char *) di->u.ti.name_ptr,  | 
 | 		hex_string (di->u.ti.segbase), | 
 | 		pulongest (di->u.ti.table_len),  | 
 | 		hex_string (di->gp)); | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Find the unwind table entry for a specified address.  */ | 
 | static int | 
 | ia64_find_unwind_table (struct objfile *objfile, unw_word_t ip, | 
 | 			unw_dyn_info_t *dip, void **buf) | 
 | { | 
 |   Elf_Internal_Phdr *phdr, *p_text = NULL, *p_unwind = NULL; | 
 |   Elf_Internal_Ehdr *ehdr; | 
 |   unw_word_t segbase = 0; | 
 |   CORE_ADDR load_base; | 
 |   bfd *bfd; | 
 |   int i; | 
 |  | 
 |   bfd = objfile->obfd; | 
 |    | 
 |   ehdr = elf_tdata (bfd)->elf_header; | 
 |   phdr = elf_tdata (bfd)->phdr; | 
 |  | 
 |   load_base = objfile->text_section_offset (); | 
 |  | 
 |   for (i = 0; i < ehdr->e_phnum; ++i) | 
 |     { | 
 |       switch (phdr[i].p_type) | 
 | 	{ | 
 | 	case PT_LOAD: | 
 | 	  if ((unw_word_t) (ip - load_base - phdr[i].p_vaddr) | 
 | 	      < phdr[i].p_memsz) | 
 | 	    p_text = phdr + i; | 
 | 	  break; | 
 |  | 
 | 	case PT_IA_64_UNWIND: | 
 | 	  p_unwind = phdr + i; | 
 | 	  break; | 
 |  | 
 | 	default: | 
 | 	  break; | 
 | 	} | 
 |     } | 
 |  | 
 |   if (!p_text || !p_unwind) | 
 |     return -UNW_ENOINFO; | 
 |  | 
 |   /* Verify that the segment that contains the IP also contains | 
 |      the static unwind table.  If not, we may be in the Linux kernel's | 
 |      DSO gate page in which case the unwind table is another segment. | 
 |      Otherwise, we are dealing with runtime-generated code, for which we  | 
 |      have no info here.  */ | 
 |   segbase = p_text->p_vaddr + load_base; | 
 |  | 
 |   if ((p_unwind->p_vaddr - p_text->p_vaddr) >= p_text->p_memsz) | 
 |     { | 
 |       int ok = 0; | 
 |       for (i = 0; i < ehdr->e_phnum; ++i) | 
 | 	{ | 
 | 	  if (phdr[i].p_type == PT_LOAD | 
 | 	      && (p_unwind->p_vaddr - phdr[i].p_vaddr) < phdr[i].p_memsz) | 
 | 	    { | 
 | 	      ok = 1; | 
 | 	      /* Get the segbase from the section containing the | 
 | 		 libunwind table.  */ | 
 | 	      segbase = phdr[i].p_vaddr + load_base; | 
 | 	    } | 
 | 	} | 
 |       if (!ok) | 
 | 	return -UNW_ENOINFO; | 
 |     } | 
 |  | 
 |   dip->start_ip = p_text->p_vaddr + load_base; | 
 |   dip->end_ip = dip->start_ip + p_text->p_memsz; | 
 |   dip->gp = ia64_find_global_pointer (objfile->arch (), ip); | 
 |   dip->format = UNW_INFO_FORMAT_REMOTE_TABLE; | 
 |   dip->u.rti.name_ptr = (unw_word_t) bfd_get_filename (bfd); | 
 |   dip->u.rti.segbase = segbase; | 
 |   dip->u.rti.table_len = p_unwind->p_memsz / sizeof (unw_word_t); | 
 |   dip->u.rti.table_data = p_unwind->p_vaddr + load_base; | 
 |  | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Libunwind callback accessor function to acquire procedure unwind-info.  */ | 
 | static int | 
 | ia64_find_proc_info_x (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, | 
 | 		       int need_unwind_info, void *arg) | 
 | { | 
 |   struct obj_section *sec = find_pc_section (ip); | 
 |   unw_dyn_info_t di; | 
 |   int ret; | 
 |   void *buf = NULL; | 
 |  | 
 |   if (!sec) | 
 |     { | 
 |       /* XXX This only works if the host and the target architecture are | 
 | 	 both ia64 and if the have (more or less) the same kernel | 
 | 	 version.  */ | 
 |       if (get_kernel_table (ip, &di) < 0) | 
 | 	return -UNW_ENOINFO; | 
 |  | 
 |       if (gdbarch_debug >= 1) | 
 | 	gdb_printf (gdb_stdlog, "ia64_find_proc_info_x: %s -> " | 
 | 		    "(name=`%s',segbase=%s,start=%s,end=%s,gp=%s," | 
 | 		    "length=%s,data=%s)\n", | 
 | 		    hex_string (ip), (char *)di.u.ti.name_ptr, | 
 | 		    hex_string (di.u.ti.segbase), | 
 | 		    hex_string (di.start_ip), hex_string (di.end_ip), | 
 | 		    hex_string (di.gp), | 
 | 		    pulongest (di.u.ti.table_len),  | 
 | 		    hex_string ((CORE_ADDR)di.u.ti.table_data)); | 
 |     } | 
 |   else | 
 |     { | 
 |       ret = ia64_find_unwind_table (sec->objfile, ip, &di, &buf); | 
 |       if (ret < 0) | 
 | 	return ret; | 
 |  | 
 |       if (gdbarch_debug >= 1) | 
 | 	gdb_printf (gdb_stdlog, "ia64_find_proc_info_x: %s -> " | 
 | 		    "(name=`%s',segbase=%s,start=%s,end=%s,gp=%s," | 
 | 		    "length=%s,data=%s)\n", | 
 | 		    hex_string (ip), (char *)di.u.rti.name_ptr, | 
 | 		    hex_string (di.u.rti.segbase), | 
 | 		    hex_string (di.start_ip), hex_string (di.end_ip), | 
 | 		    hex_string (di.gp), | 
 | 		    pulongest (di.u.rti.table_len),  | 
 | 		    hex_string (di.u.rti.table_data)); | 
 |     } | 
 |  | 
 |   ret = libunwind_search_unwind_table (&as, ip, &di, pi, need_unwind_info, | 
 | 				       arg); | 
 |  | 
 |   /* We no longer need the dyn info storage so free it.  */ | 
 |   xfree (buf); | 
 |  | 
 |   return ret; | 
 | } | 
 |  | 
 | /* Libunwind callback accessor function for cleanup.  */ | 
 | static void | 
 | ia64_put_unwind_info (unw_addr_space_t as, | 
 | 		      unw_proc_info_t *pip, void *arg) | 
 | { | 
 |   /* Nothing required for now.  */ | 
 | } | 
 |  | 
 | /* Libunwind callback accessor function to get head of the dynamic  | 
 |    unwind-info registration list.  */  | 
 | static int | 
 | ia64_get_dyn_info_list (unw_addr_space_t as, | 
 | 			unw_word_t *dilap, void *arg) | 
 | { | 
 |   struct obj_section *text_sec; | 
 |   unw_word_t ip, addr; | 
 |   unw_dyn_info_t di; | 
 |   int ret; | 
 |  | 
 |   if (!libunwind_is_initialized ()) | 
 |     return -UNW_ENOINFO; | 
 |  | 
 |   for (objfile *objfile : current_program_space->objfiles ()) | 
 |     { | 
 |       void *buf = NULL; | 
 |  | 
 |       text_sec = objfile->sections + SECT_OFF_TEXT (objfile); | 
 |       ip = text_sec->addr (); | 
 |       ret = ia64_find_unwind_table (objfile, ip, &di, &buf); | 
 |       if (ret >= 0) | 
 | 	{ | 
 | 	  addr = libunwind_find_dyn_list (as, &di, arg); | 
 | 	  /* We no longer need the dyn info storage so free it.  */ | 
 | 	  xfree (buf); | 
 |  | 
 | 	  if (addr) | 
 | 	    { | 
 | 	      if (gdbarch_debug >= 1) | 
 | 		gdb_printf (gdb_stdlog, | 
 | 			    "dynamic unwind table in objfile %s " | 
 | 			    "at %s (gp=%s)\n", | 
 | 			    bfd_get_filename (objfile->obfd), | 
 | 			    hex_string (addr), hex_string (di.gp)); | 
 | 	      *dilap = addr; | 
 | 	      return 0; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |   return -UNW_ENOINFO; | 
 | } | 
 |  | 
 |  | 
 | /* Frame interface functions for libunwind.  */ | 
 |  | 
 | static void | 
 | ia64_libunwind_frame_this_id (frame_info_ptr this_frame, void **this_cache, | 
 | 			      struct frame_id *this_id) | 
 | { | 
 |   struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   struct frame_id id = outer_frame_id; | 
 |   gdb_byte buf[8]; | 
 |   CORE_ADDR bsp; | 
 |  | 
 |   libunwind_frame_this_id (this_frame, this_cache, &id); | 
 |   if (id == outer_frame_id) | 
 |     { | 
 |       (*this_id) = outer_frame_id; | 
 |       return; | 
 |     } | 
 |  | 
 |   /* We must add the bsp as the special address for frame comparison  | 
 |      purposes.  */ | 
 |   get_frame_register (this_frame, IA64_BSP_REGNUM, buf); | 
 |   bsp = extract_unsigned_integer (buf, 8, byte_order); | 
 |  | 
 |   (*this_id) = frame_id_build_special (id.stack_addr, id.code_addr, bsp); | 
 |  | 
 |   if (gdbarch_debug >= 1) | 
 |     gdb_printf (gdb_stdlog, | 
 | 		"libunwind frame id: code %s, stack %s, " | 
 | 		"special %s, this_frame %s\n", | 
 | 		paddress (gdbarch, id.code_addr), | 
 | 		paddress (gdbarch, id.stack_addr), | 
 | 		paddress (gdbarch, bsp), | 
 | 		host_address_to_string (this_frame)); | 
 | } | 
 |  | 
 | static struct value * | 
 | ia64_libunwind_frame_prev_register (frame_info_ptr this_frame, | 
 | 				    void **this_cache, int regnum) | 
 | { | 
 |   int reg = regnum; | 
 |   struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   struct value *val; | 
 |  | 
 |   if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM) | 
 |     reg = IA64_PR_REGNUM; | 
 |   else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM) | 
 |     reg = IA64_UNAT_REGNUM; | 
 |  | 
 |   /* Let libunwind do most of the work.  */ | 
 |   val = libunwind_frame_prev_register (this_frame, this_cache, reg); | 
 |  | 
 |   if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM) | 
 |     { | 
 |       ULONGEST prN_val; | 
 |  | 
 |       if (VP16_REGNUM <= regnum && regnum <= VP63_REGNUM) | 
 | 	{ | 
 | 	  int rrb_pr = 0; | 
 | 	  ULONGEST cfm; | 
 |  | 
 | 	  /* Fetch predicate register rename base from current frame | 
 | 	     marker for this frame.  */ | 
 | 	  cfm = get_frame_register_unsigned (this_frame, IA64_CFM_REGNUM); | 
 | 	  rrb_pr = (cfm >> 32) & 0x3f; | 
 | 	   | 
 | 	  /* Adjust the register number to account for register rotation.  */ | 
 | 	  regnum = VP16_REGNUM + ((regnum - VP16_REGNUM) + rrb_pr) % 48; | 
 | 	} | 
 |       prN_val = extract_bit_field (val->contents_all ().data (), | 
 | 				   regnum - VP0_REGNUM, 1); | 
 |       return frame_unwind_got_constant (this_frame, regnum, prN_val); | 
 |     } | 
 |  | 
 |   else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM) | 
 |     { | 
 |       ULONGEST unatN_val; | 
 |  | 
 |       unatN_val = extract_bit_field (val->contents_all ().data (), | 
 | 				     regnum - IA64_NAT0_REGNUM, 1); | 
 |       return frame_unwind_got_constant (this_frame, regnum, unatN_val); | 
 |     } | 
 |  | 
 |   else if (regnum == IA64_BSP_REGNUM) | 
 |     { | 
 |       struct value *cfm_val; | 
 |       CORE_ADDR prev_bsp, prev_cfm; | 
 |  | 
 |       /* We want to calculate the previous bsp as the end of the previous | 
 | 	 register stack frame.  This corresponds to what the hardware bsp | 
 | 	 register will be if we pop the frame back which is why we might | 
 | 	 have been called.  We know that libunwind will pass us back the | 
 | 	 beginning of the current frame so we should just add sof to it.  */ | 
 |       prev_bsp = extract_unsigned_integer (val->contents_all ().data (), | 
 | 					   8, byte_order); | 
 |       cfm_val = libunwind_frame_prev_register (this_frame, this_cache, | 
 | 					       IA64_CFM_REGNUM); | 
 |       prev_cfm = extract_unsigned_integer (cfm_val->contents_all ().data (), | 
 | 					   8, byte_order); | 
 |       prev_bsp = rse_address_add (prev_bsp, (prev_cfm & 0x7f)); | 
 |  | 
 |       return frame_unwind_got_constant (this_frame, regnum, prev_bsp); | 
 |     } | 
 |   else | 
 |     return val; | 
 | } | 
 |  | 
 | static int | 
 | ia64_libunwind_frame_sniffer (const struct frame_unwind *self, | 
 | 			      frame_info_ptr this_frame, | 
 | 			      void **this_cache) | 
 | { | 
 |   if (libunwind_is_initialized () | 
 |       && libunwind_frame_sniffer (self, this_frame, this_cache)) | 
 |     return 1; | 
 |  | 
 |   return 0; | 
 | } | 
 |  | 
 | static const struct frame_unwind ia64_libunwind_frame_unwind = | 
 | { | 
 |   "ia64 libunwind", | 
 |   NORMAL_FRAME, | 
 |   default_frame_unwind_stop_reason, | 
 |   ia64_libunwind_frame_this_id, | 
 |   ia64_libunwind_frame_prev_register, | 
 |   NULL, | 
 |   ia64_libunwind_frame_sniffer, | 
 |   libunwind_frame_dealloc_cache | 
 | }; | 
 |  | 
 | static void | 
 | ia64_libunwind_sigtramp_frame_this_id (frame_info_ptr this_frame, | 
 | 				       void **this_cache, | 
 | 				       struct frame_id *this_id) | 
 | { | 
 |   struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   gdb_byte buf[8]; | 
 |   CORE_ADDR bsp; | 
 |   struct frame_id id = outer_frame_id; | 
 |  | 
 |   libunwind_frame_this_id (this_frame, this_cache, &id); | 
 |   if (id == outer_frame_id) | 
 |     { | 
 |       (*this_id) = outer_frame_id; | 
 |       return; | 
 |     } | 
 |  | 
 |   /* We must add the bsp as the special address for frame comparison  | 
 |      purposes.  */ | 
 |   get_frame_register (this_frame, IA64_BSP_REGNUM, buf); | 
 |   bsp = extract_unsigned_integer (buf, 8, byte_order); | 
 |  | 
 |   /* For a sigtramp frame, we don't make the check for previous ip being 0.  */ | 
 |   (*this_id) = frame_id_build_special (id.stack_addr, id.code_addr, bsp); | 
 |  | 
 |   if (gdbarch_debug >= 1) | 
 |     gdb_printf (gdb_stdlog, | 
 | 		"libunwind sigtramp frame id: code %s, " | 
 | 		"stack %s, special %s, this_frame %s\n", | 
 | 		paddress (gdbarch, id.code_addr), | 
 | 		paddress (gdbarch, id.stack_addr), | 
 | 		paddress (gdbarch, bsp), | 
 | 		host_address_to_string (this_frame)); | 
 | } | 
 |  | 
 | static struct value * | 
 | ia64_libunwind_sigtramp_frame_prev_register (frame_info_ptr this_frame, | 
 | 					     void **this_cache, int regnum) | 
 | { | 
 |   struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   struct value *prev_ip_val; | 
 |   CORE_ADDR prev_ip; | 
 |  | 
 |   /* If the previous frame pc value is 0, then we want to use the SIGCONTEXT | 
 |      method of getting previous registers.  */ | 
 |   prev_ip_val = libunwind_frame_prev_register (this_frame, this_cache, | 
 | 					       IA64_IP_REGNUM); | 
 |   prev_ip = extract_unsigned_integer (prev_ip_val->contents_all ().data (), | 
 | 				      8, byte_order); | 
 |  | 
 |   if (prev_ip == 0) | 
 |     { | 
 |       void *tmp_cache = NULL; | 
 |       return ia64_sigtramp_frame_prev_register (this_frame, &tmp_cache, | 
 | 						regnum); | 
 |     } | 
 |   else | 
 |     return ia64_libunwind_frame_prev_register (this_frame, this_cache, regnum); | 
 | } | 
 |  | 
 | static int | 
 | ia64_libunwind_sigtramp_frame_sniffer (const struct frame_unwind *self, | 
 | 				       frame_info_ptr this_frame, | 
 | 				       void **this_cache) | 
 | { | 
 |   if (libunwind_is_initialized ()) | 
 |     { | 
 |       if (libunwind_sigtramp_frame_sniffer (self, this_frame, this_cache)) | 
 | 	return 1; | 
 |       return 0; | 
 |     } | 
 |   else | 
 |     return ia64_sigtramp_frame_sniffer (self, this_frame, this_cache); | 
 | } | 
 |  | 
 | static const struct frame_unwind ia64_libunwind_sigtramp_frame_unwind = | 
 | { | 
 |   "ia64 libunwind sigtramp", | 
 |   SIGTRAMP_FRAME, | 
 |   default_frame_unwind_stop_reason, | 
 |   ia64_libunwind_sigtramp_frame_this_id, | 
 |   ia64_libunwind_sigtramp_frame_prev_register, | 
 |   NULL, | 
 |   ia64_libunwind_sigtramp_frame_sniffer | 
 | }; | 
 |  | 
 | /* Set of libunwind callback acccessor functions.  */ | 
 | unw_accessors_t ia64_unw_accessors = | 
 | { | 
 |   ia64_find_proc_info_x, | 
 |   ia64_put_unwind_info, | 
 |   ia64_get_dyn_info_list, | 
 |   ia64_access_mem, | 
 |   ia64_access_reg, | 
 |   ia64_access_fpreg, | 
 |   /* resume */ | 
 |   /* get_proc_name */ | 
 | }; | 
 |  | 
 | /* Set of special libunwind callback acccessor functions specific for accessing | 
 |    the rse registers.  At the top of the stack, we want libunwind to figure out | 
 |    how to read r32 - r127.  Though usually they are found sequentially in | 
 |    memory starting from $bof, this is not always true.  */ | 
 | unw_accessors_t ia64_unw_rse_accessors = | 
 | { | 
 |   ia64_find_proc_info_x, | 
 |   ia64_put_unwind_info, | 
 |   ia64_get_dyn_info_list, | 
 |   ia64_access_mem, | 
 |   ia64_access_rse_reg, | 
 |   ia64_access_rse_fpreg, | 
 |   /* resume */ | 
 |   /* get_proc_name */ | 
 | }; | 
 |  | 
 | /* Set of ia64-libunwind-tdep gdb callbacks and data for generic | 
 |    ia64-libunwind-tdep code to use.  */ | 
 | struct libunwind_descr ia64_libunwind_descr = | 
 | { | 
 |   ia64_gdb2uw_regnum,  | 
 |   ia64_uw2gdb_regnum,  | 
 |   ia64_is_fpreg,  | 
 |   &ia64_unw_accessors, | 
 |   &ia64_unw_rse_accessors, | 
 | }; | 
 |  | 
 | #endif /* HAVE_LIBUNWIND_IA64_H  */ | 
 |  | 
 | static int | 
 | ia64_use_struct_convention (struct type *type) | 
 | { | 
 |   struct type *float_elt_type; | 
 |  | 
 |   /* Don't use the struct convention for anything but structure, | 
 |      union, or array types.  */ | 
 |   if (!(type->code () == TYPE_CODE_STRUCT | 
 | 	|| type->code () == TYPE_CODE_UNION | 
 | 	|| type->code () == TYPE_CODE_ARRAY)) | 
 |     return 0; | 
 |  | 
 |   /* HFAs are structures (or arrays) consisting entirely of floating | 
 |      point values of the same length.  Up to 8 of these are returned | 
 |      in registers.  Don't use the struct convention when this is the | 
 |      case.  */ | 
 |   float_elt_type = is_float_or_hfa_type (type); | 
 |   if (float_elt_type != NULL | 
 |       && type->length () / float_elt_type->length () <= 8) | 
 |     return 0; | 
 |  | 
 |   /* Other structs of length 32 or less are returned in r8-r11. | 
 |      Don't use the struct convention for those either.  */ | 
 |   return type->length () > 32; | 
 | } | 
 |  | 
 | /* Return non-zero if TYPE is a structure or union type.  */ | 
 |  | 
 | static int | 
 | ia64_struct_type_p (const struct type *type) | 
 | { | 
 |   return (type->code () == TYPE_CODE_STRUCT | 
 | 	  || type->code () == TYPE_CODE_UNION); | 
 | } | 
 |  | 
 | static void | 
 | ia64_extract_return_value (struct type *type, struct regcache *regcache, | 
 | 			   gdb_byte *valbuf) | 
 | { | 
 |   struct gdbarch *gdbarch = regcache->arch (); | 
 |   struct type *float_elt_type; | 
 |  | 
 |   float_elt_type = is_float_or_hfa_type (type); | 
 |   if (float_elt_type != NULL) | 
 |     { | 
 |       gdb_byte from[IA64_FP_REGISTER_SIZE]; | 
 |       int offset = 0; | 
 |       int regnum = IA64_FR8_REGNUM; | 
 |       int n = type->length () / float_elt_type->length (); | 
 |  | 
 |       while (n-- > 0) | 
 | 	{ | 
 | 	  regcache->cooked_read (regnum, from); | 
 | 	  target_float_convert (from, ia64_ext_type (gdbarch), | 
 | 				valbuf + offset, float_elt_type); | 
 | 	  offset += float_elt_type->length (); | 
 | 	  regnum++; | 
 | 	} | 
 |     } | 
 |   else if (!ia64_struct_type_p (type) && type->length () < 8) | 
 |     { | 
 |       /* This is an integral value, and its size is less than 8 bytes. | 
 | 	 These values are LSB-aligned, so extract the relevant bytes, | 
 | 	 and copy them into VALBUF.  */ | 
 |       /* brobecker/2005-12-30: Actually, all integral values are LSB aligned, | 
 | 	 so I suppose we should also add handling here for integral values | 
 | 	 whose size is greater than 8.  But I wasn't able to create such | 
 | 	 a type, neither in C nor in Ada, so not worrying about these yet.  */ | 
 |       enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |       ULONGEST val; | 
 |  | 
 |       regcache_cooked_read_unsigned (regcache, IA64_GR8_REGNUM, &val); | 
 |       store_unsigned_integer (valbuf, type->length (), byte_order, val); | 
 |     } | 
 |   else | 
 |     { | 
 |       ULONGEST val; | 
 |       int offset = 0; | 
 |       int regnum = IA64_GR8_REGNUM; | 
 |       int reglen = register_type (gdbarch, IA64_GR8_REGNUM)->length (); | 
 |       int n = type->length () / reglen; | 
 |       int m = type->length () % reglen; | 
 |  | 
 |       while (n-- > 0) | 
 | 	{ | 
 | 	  ULONGEST regval; | 
 | 	  regcache_cooked_read_unsigned (regcache, regnum, ®val); | 
 | 	  memcpy ((char *)valbuf + offset, ®val, reglen); | 
 | 	  offset += reglen; | 
 | 	  regnum++; | 
 | 	} | 
 |  | 
 |       if (m) | 
 | 	{ | 
 | 	  regcache_cooked_read_unsigned (regcache, regnum, &val); | 
 | 	  memcpy ((char *)valbuf + offset, &val, m); | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | static void | 
 | ia64_store_return_value (struct type *type, struct regcache *regcache,  | 
 | 			 const gdb_byte *valbuf) | 
 | { | 
 |   struct gdbarch *gdbarch = regcache->arch (); | 
 |   struct type *float_elt_type; | 
 |  | 
 |   float_elt_type = is_float_or_hfa_type (type); | 
 |   if (float_elt_type != NULL) | 
 |     { | 
 |       gdb_byte to[IA64_FP_REGISTER_SIZE]; | 
 |       int offset = 0; | 
 |       int regnum = IA64_FR8_REGNUM; | 
 |       int n = type->length () / float_elt_type->length (); | 
 |  | 
 |       while (n-- > 0) | 
 | 	{ | 
 | 	  target_float_convert (valbuf + offset, float_elt_type, | 
 | 				to, ia64_ext_type (gdbarch)); | 
 | 	  regcache->cooked_write (regnum, to); | 
 | 	  offset += float_elt_type->length (); | 
 | 	  regnum++; | 
 | 	} | 
 |     } | 
 |   else | 
 |     { | 
 |       int offset = 0; | 
 |       int regnum = IA64_GR8_REGNUM; | 
 |       int reglen = register_type (gdbarch, IA64_GR8_REGNUM)->length (); | 
 |       int n = type->length () / reglen; | 
 |       int m = type->length () % reglen; | 
 |  | 
 |       while (n-- > 0) | 
 | 	{ | 
 | 	  ULONGEST val; | 
 | 	  memcpy (&val, (char *)valbuf + offset, reglen); | 
 | 	  regcache_cooked_write_unsigned (regcache, regnum, val); | 
 | 	  offset += reglen; | 
 | 	  regnum++; | 
 | 	} | 
 |  | 
 |       if (m) | 
 | 	{ | 
 | 	  ULONGEST val; | 
 | 	  memcpy (&val, (char *)valbuf + offset, m); | 
 | 	  regcache_cooked_write_unsigned (regcache, regnum, val); | 
 | 	} | 
 |     } | 
 | } | 
 |    | 
 | static enum return_value_convention | 
 | ia64_return_value (struct gdbarch *gdbarch, struct value *function, | 
 | 		   struct type *valtype, struct regcache *regcache, | 
 | 		   gdb_byte *readbuf, const gdb_byte *writebuf) | 
 | { | 
 |   int struct_return = ia64_use_struct_convention (valtype); | 
 |  | 
 |   if (writebuf != NULL) | 
 |     { | 
 |       gdb_assert (!struct_return); | 
 |       ia64_store_return_value (valtype, regcache, writebuf); | 
 |     } | 
 |  | 
 |   if (readbuf != NULL) | 
 |     { | 
 |       gdb_assert (!struct_return); | 
 |       ia64_extract_return_value (valtype, regcache, readbuf); | 
 |     } | 
 |  | 
 |   if (struct_return) | 
 |     return RETURN_VALUE_STRUCT_CONVENTION; | 
 |   else | 
 |     return RETURN_VALUE_REGISTER_CONVENTION; | 
 | } | 
 |  | 
 | static int | 
 | is_float_or_hfa_type_recurse (struct type *t, struct type **etp) | 
 | { | 
 |   switch (t->code ()) | 
 |     { | 
 |     case TYPE_CODE_FLT: | 
 |       if (*etp) | 
 | 	return (*etp)->length () == t->length (); | 
 |       else | 
 | 	{ | 
 | 	  *etp = t; | 
 | 	  return 1; | 
 | 	} | 
 |       break; | 
 |     case TYPE_CODE_ARRAY: | 
 |       return | 
 | 	is_float_or_hfa_type_recurse (check_typedef (t->target_type ()), | 
 | 				      etp); | 
 |       break; | 
 |     case TYPE_CODE_STRUCT: | 
 |       { | 
 | 	int i; | 
 |  | 
 | 	for (i = 0; i < t->num_fields (); i++) | 
 | 	  if (!is_float_or_hfa_type_recurse | 
 | 	      (check_typedef (t->field (i).type ()), etp)) | 
 | 	    return 0; | 
 | 	return 1; | 
 |       } | 
 |       break; | 
 |     default: | 
 |       break; | 
 |     } | 
 |  | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Determine if the given type is one of the floating point types or | 
 |    and HFA (which is a struct, array, or combination thereof whose | 
 |    bottom-most elements are all of the same floating point type).  */ | 
 |  | 
 | static struct type * | 
 | is_float_or_hfa_type (struct type *t) | 
 | { | 
 |   struct type *et = 0; | 
 |  | 
 |   return is_float_or_hfa_type_recurse (t, &et) ? et : 0; | 
 | } | 
 |  | 
 |  | 
 | /* Return 1 if the alignment of T is such that the next even slot | 
 |    should be used.  Return 0, if the next available slot should | 
 |    be used.  (See section 8.5.1 of the IA-64 Software Conventions | 
 |    and Runtime manual).  */ | 
 |  | 
 | static int | 
 | slot_alignment_is_next_even (struct type *t) | 
 | { | 
 |   switch (t->code ()) | 
 |     { | 
 |     case TYPE_CODE_INT: | 
 |     case TYPE_CODE_FLT: | 
 |       if (t->length () > 8) | 
 | 	return 1; | 
 |       else | 
 | 	return 0; | 
 |     case TYPE_CODE_ARRAY: | 
 |       return | 
 | 	slot_alignment_is_next_even (check_typedef (t->target_type ())); | 
 |     case TYPE_CODE_STRUCT: | 
 |       { | 
 | 	int i; | 
 |  | 
 | 	for (i = 0; i < t->num_fields (); i++) | 
 | 	  if (slot_alignment_is_next_even | 
 | 	      (check_typedef (t->field (i).type ()))) | 
 | 	    return 1; | 
 | 	return 0; | 
 |       } | 
 |     default: | 
 |       return 0; | 
 |     } | 
 | } | 
 |  | 
 | /* Attempt to find (and return) the global pointer for the given | 
 |    function. | 
 |  | 
 |    This is a rather nasty bit of code searchs for the .dynamic section | 
 |    in the objfile corresponding to the pc of the function we're trying | 
 |    to call.  Once it finds the addresses at which the .dynamic section | 
 |    lives in the child process, it scans the Elf64_Dyn entries for a | 
 |    DT_PLTGOT tag.  If it finds one of these, the corresponding | 
 |    d_un.d_ptr value is the global pointer.  */ | 
 |  | 
 | static CORE_ADDR | 
 | ia64_find_global_pointer_from_dynamic_section (struct gdbarch *gdbarch, | 
 | 					       CORE_ADDR faddr) | 
 | { | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   struct obj_section *faddr_sect; | 
 |       | 
 |   faddr_sect = find_pc_section (faddr); | 
 |   if (faddr_sect != NULL) | 
 |     { | 
 |       for (obj_section *osect : faddr_sect->objfile->sections ()) | 
 | 	{ | 
 | 	  if (strcmp (osect->the_bfd_section->name, ".dynamic") == 0) | 
 | 	    { | 
 | 	      CORE_ADDR addr = osect->addr (); | 
 | 	      CORE_ADDR endaddr = osect->endaddr (); | 
 |  | 
 | 	      while (addr < endaddr) | 
 | 		{ | 
 | 		  int status; | 
 | 		  LONGEST tag; | 
 | 		  gdb_byte buf[8]; | 
 |  | 
 | 		  status = target_read_memory (addr, buf, sizeof (buf)); | 
 | 		  if (status != 0) | 
 | 		    break; | 
 | 		  tag = extract_signed_integer (buf, byte_order); | 
 |  | 
 | 		  if (tag == DT_PLTGOT) | 
 | 		    { | 
 | 		      CORE_ADDR global_pointer; | 
 |  | 
 | 		      status = target_read_memory (addr + 8, buf, | 
 | 						   sizeof (buf)); | 
 | 		      if (status != 0) | 
 | 			break; | 
 | 		      global_pointer | 
 | 			= extract_unsigned_integer (buf, sizeof (buf), | 
 | 						    byte_order); | 
 |  | 
 | 		      /* The payoff...  */ | 
 | 		      return global_pointer; | 
 | 		    } | 
 |  | 
 | 		  if (tag == DT_NULL) | 
 | 		    break; | 
 |  | 
 | 		  addr += 16; | 
 | 		} | 
 |  | 
 | 	      break; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Attempt to find (and return) the global pointer for the given | 
 |    function.  We first try the find_global_pointer_from_solib routine | 
 |    from the gdbarch tdep vector, if provided.  And if that does not | 
 |    work, then we try ia64_find_global_pointer_from_dynamic_section.  */ | 
 |  | 
 | static CORE_ADDR | 
 | ia64_find_global_pointer (struct gdbarch *gdbarch, CORE_ADDR faddr) | 
 | { | 
 |   ia64_gdbarch_tdep *tdep = gdbarch_tdep<ia64_gdbarch_tdep> (gdbarch); | 
 |   CORE_ADDR addr = 0; | 
 |  | 
 |   if (tdep->find_global_pointer_from_solib) | 
 |     addr = tdep->find_global_pointer_from_solib (gdbarch, faddr); | 
 |   if (addr == 0) | 
 |     addr = ia64_find_global_pointer_from_dynamic_section (gdbarch, faddr); | 
 |   return addr; | 
 | } | 
 |  | 
 | /* Given a function's address, attempt to find (and return) the | 
 |    corresponding (canonical) function descriptor.  Return 0 if | 
 |    not found.  */ | 
 | static CORE_ADDR | 
 | find_extant_func_descr (struct gdbarch *gdbarch, CORE_ADDR faddr) | 
 | { | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   struct obj_section *faddr_sect; | 
 |  | 
 |   /* Return early if faddr is already a function descriptor.  */ | 
 |   faddr_sect = find_pc_section (faddr); | 
 |   if (faddr_sect && strcmp (faddr_sect->the_bfd_section->name, ".opd") == 0) | 
 |     return faddr; | 
 |  | 
 |   if (faddr_sect != NULL) | 
 |     { | 
 |       for (obj_section *osect : faddr_sect->objfile->sections ()) | 
 | 	{ | 
 | 	  if (strcmp (osect->the_bfd_section->name, ".opd") == 0) | 
 | 	    { | 
 | 	      CORE_ADDR addr = osect->addr (); | 
 | 	      CORE_ADDR endaddr = osect->endaddr (); | 
 |  | 
 | 	      while (addr < endaddr) | 
 | 		{ | 
 | 		  int status; | 
 | 		  LONGEST faddr2; | 
 | 		  gdb_byte buf[8]; | 
 |  | 
 | 		  status = target_read_memory (addr, buf, sizeof (buf)); | 
 | 		  if (status != 0) | 
 | 		    break; | 
 | 		  faddr2 = extract_signed_integer (buf, byte_order); | 
 |  | 
 | 		  if (faddr == faddr2) | 
 | 		    return addr; | 
 |  | 
 | 		  addr += 16; | 
 | 		} | 
 |  | 
 | 	      break; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Attempt to find a function descriptor corresponding to the | 
 |    given address.  If none is found, construct one on the | 
 |    stack using the address at fdaptr.  */ | 
 |  | 
 | static CORE_ADDR | 
 | find_func_descr (struct regcache *regcache, CORE_ADDR faddr, CORE_ADDR *fdaptr) | 
 | { | 
 |   struct gdbarch *gdbarch = regcache->arch (); | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   CORE_ADDR fdesc; | 
 |  | 
 |   fdesc = find_extant_func_descr (gdbarch, faddr); | 
 |  | 
 |   if (fdesc == 0) | 
 |     { | 
 |       ULONGEST global_pointer; | 
 |       gdb_byte buf[16]; | 
 |  | 
 |       fdesc = *fdaptr; | 
 |       *fdaptr += 16; | 
 |  | 
 |       global_pointer = ia64_find_global_pointer (gdbarch, faddr); | 
 |  | 
 |       if (global_pointer == 0) | 
 | 	regcache_cooked_read_unsigned (regcache, | 
 | 				       IA64_GR1_REGNUM, &global_pointer); | 
 |  | 
 |       store_unsigned_integer (buf, 8, byte_order, faddr); | 
 |       store_unsigned_integer (buf + 8, 8, byte_order, global_pointer); | 
 |  | 
 |       write_memory (fdesc, buf, 16); | 
 |     } | 
 |  | 
 |   return fdesc;  | 
 | } | 
 |  | 
 | /* Use the following routine when printing out function pointers | 
 |    so the user can see the function address rather than just the | 
 |    function descriptor.  */ | 
 | static CORE_ADDR | 
 | ia64_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr, | 
 | 				 struct target_ops *targ) | 
 | { | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   struct obj_section *s; | 
 |   gdb_byte buf[8]; | 
 |  | 
 |   s = find_pc_section (addr); | 
 |  | 
 |   /* check if ADDR points to a function descriptor.  */ | 
 |   if (s && strcmp (s->the_bfd_section->name, ".opd") == 0) | 
 |     return read_memory_unsigned_integer (addr, 8, byte_order); | 
 |  | 
 |   /* Normally, functions live inside a section that is executable. | 
 |      So, if ADDR points to a non-executable section, then treat it | 
 |      as a function descriptor and return the target address iff | 
 |      the target address itself points to a section that is executable. | 
 |      Check first the memory of the whole length of 8 bytes is readable.  */ | 
 |   if (s && (s->the_bfd_section->flags & SEC_CODE) == 0 | 
 |       && target_read_memory (addr, buf, 8) == 0) | 
 |     { | 
 |       CORE_ADDR pc = extract_unsigned_integer (buf, 8, byte_order); | 
 |       struct obj_section *pc_section = find_pc_section (pc); | 
 |  | 
 |       if (pc_section && (pc_section->the_bfd_section->flags & SEC_CODE)) | 
 | 	return pc; | 
 |     } | 
 |  | 
 |   /* There are also descriptors embedded in vtables.  */ | 
 |   if (s) | 
 |     { | 
 |       struct bound_minimal_symbol minsym; | 
 |  | 
 |       minsym = lookup_minimal_symbol_by_pc (addr); | 
 |  | 
 |       if (minsym.minsym | 
 | 	  && is_vtable_name (minsym.minsym->linkage_name ())) | 
 | 	return read_memory_unsigned_integer (addr, 8, byte_order); | 
 |     } | 
 |  | 
 |   return addr; | 
 | } | 
 |  | 
 | static CORE_ADDR | 
 | ia64_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp) | 
 | { | 
 |   return sp & ~0xfLL; | 
 | } | 
 |  | 
 | /* The default "allocate_new_rse_frame" ia64_infcall_ops routine for ia64.  */ | 
 |  | 
 | static void | 
 | ia64_allocate_new_rse_frame (struct regcache *regcache, ULONGEST bsp, int sof) | 
 | { | 
 |   ULONGEST cfm, pfs, new_bsp; | 
 |  | 
 |   regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm); | 
 |  | 
 |   new_bsp = rse_address_add (bsp, sof); | 
 |   regcache_cooked_write_unsigned (regcache, IA64_BSP_REGNUM, new_bsp); | 
 |  | 
 |   regcache_cooked_read_unsigned (regcache, IA64_PFS_REGNUM, &pfs); | 
 |   pfs &= 0xc000000000000000LL; | 
 |   pfs |= (cfm & 0xffffffffffffLL); | 
 |   regcache_cooked_write_unsigned (regcache, IA64_PFS_REGNUM, pfs); | 
 |  | 
 |   cfm &= 0xc000000000000000LL; | 
 |   cfm |= sof; | 
 |   regcache_cooked_write_unsigned (regcache, IA64_CFM_REGNUM, cfm); | 
 | } | 
 |  | 
 | /* The default "store_argument_in_slot" ia64_infcall_ops routine for | 
 |    ia64.  */ | 
 |  | 
 | static void | 
 | ia64_store_argument_in_slot (struct regcache *regcache, CORE_ADDR bsp, | 
 | 			     int slotnum, gdb_byte *buf) | 
 | { | 
 |   write_memory (rse_address_add (bsp, slotnum), buf, 8); | 
 | } | 
 |  | 
 | /* The default "set_function_addr" ia64_infcall_ops routine for ia64.  */ | 
 |  | 
 | static void | 
 | ia64_set_function_addr (struct regcache *regcache, CORE_ADDR func_addr) | 
 | { | 
 |   /* Nothing needed.  */ | 
 | } | 
 |  | 
 | static CORE_ADDR | 
 | ia64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, | 
 | 		      struct regcache *regcache, CORE_ADDR bp_addr, | 
 | 		      int nargs, struct value **args, CORE_ADDR sp, | 
 | 		      function_call_return_method return_method, | 
 | 		      CORE_ADDR struct_addr) | 
 | { | 
 |   ia64_gdbarch_tdep *tdep = gdbarch_tdep<ia64_gdbarch_tdep> (gdbarch); | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   int argno; | 
 |   struct value *arg; | 
 |   struct type *type; | 
 |   int len, argoffset; | 
 |   int nslots, rseslots, memslots, slotnum, nfuncargs; | 
 |   int floatreg; | 
 |   ULONGEST bsp; | 
 |   CORE_ADDR funcdescaddr, global_pointer; | 
 |   CORE_ADDR func_addr = find_function_addr (function, NULL); | 
 |  | 
 |   nslots = 0; | 
 |   nfuncargs = 0; | 
 |   /* Count the number of slots needed for the arguments.  */ | 
 |   for (argno = 0; argno < nargs; argno++) | 
 |     { | 
 |       arg = args[argno]; | 
 |       type = check_typedef (arg->type ()); | 
 |       len = type->length (); | 
 |  | 
 |       if ((nslots & 1) && slot_alignment_is_next_even (type)) | 
 | 	nslots++; | 
 |  | 
 |       if (type->code () == TYPE_CODE_FUNC) | 
 | 	nfuncargs++; | 
 |  | 
 |       nslots += (len + 7) / 8; | 
 |     } | 
 |  | 
 |   /* Divvy up the slots between the RSE and the memory stack.  */ | 
 |   rseslots = (nslots > 8) ? 8 : nslots; | 
 |   memslots = nslots - rseslots; | 
 |  | 
 |   /* Allocate a new RSE frame.  */ | 
 |   regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp); | 
 |   tdep->infcall_ops.allocate_new_rse_frame (regcache, bsp, rseslots); | 
 |    | 
 |   /* We will attempt to find function descriptors in the .opd segment, | 
 |      but if we can't we'll construct them ourselves.  That being the | 
 |      case, we'll need to reserve space on the stack for them.  */ | 
 |   funcdescaddr = sp - nfuncargs * 16; | 
 |   funcdescaddr &= ~0xfLL; | 
 |  | 
 |   /* Adjust the stack pointer to it's new value.  The calling conventions | 
 |      require us to have 16 bytes of scratch, plus whatever space is | 
 |      necessary for the memory slots and our function descriptors.  */ | 
 |   sp = sp - 16 - (memslots + nfuncargs) * 8; | 
 |   sp &= ~0xfLL;				/* Maintain 16 byte alignment.  */ | 
 |  | 
 |   /* Place the arguments where they belong.  The arguments will be | 
 |      either placed in the RSE backing store or on the memory stack. | 
 |      In addition, floating point arguments or HFAs are placed in | 
 |      floating point registers.  */ | 
 |   slotnum = 0; | 
 |   floatreg = IA64_FR8_REGNUM; | 
 |   for (argno = 0; argno < nargs; argno++) | 
 |     { | 
 |       struct type *float_elt_type; | 
 |  | 
 |       arg = args[argno]; | 
 |       type = check_typedef (arg->type ()); | 
 |       len = type->length (); | 
 |  | 
 |       /* Special handling for function parameters.  */ | 
 |       if (len == 8 | 
 | 	  && type->code () == TYPE_CODE_PTR | 
 | 	  && type->target_type ()->code () == TYPE_CODE_FUNC) | 
 | 	{ | 
 | 	  gdb_byte val_buf[8]; | 
 | 	  ULONGEST faddr = extract_unsigned_integer | 
 | 	    (arg->contents ().data (), 8, byte_order); | 
 | 	  store_unsigned_integer (val_buf, 8, byte_order, | 
 | 				  find_func_descr (regcache, faddr, | 
 | 						   &funcdescaddr)); | 
 | 	  if (slotnum < rseslots) | 
 | 	    tdep->infcall_ops.store_argument_in_slot (regcache, bsp, | 
 | 						      slotnum, val_buf); | 
 | 	  else | 
 | 	    write_memory (sp + 16 + 8 * (slotnum - rseslots), val_buf, 8); | 
 | 	  slotnum++; | 
 | 	  continue; | 
 | 	} | 
 |  | 
 |       /* Normal slots.  */ | 
 |  | 
 |       /* Skip odd slot if necessary...  */ | 
 |       if ((slotnum & 1) && slot_alignment_is_next_even (type)) | 
 | 	slotnum++; | 
 |  | 
 |       argoffset = 0; | 
 |       while (len > 0) | 
 | 	{ | 
 | 	  gdb_byte val_buf[8]; | 
 |  | 
 | 	  memset (val_buf, 0, 8); | 
 | 	  if (!ia64_struct_type_p (type) && len < 8) | 
 | 	    { | 
 | 	      /* Integral types are LSB-aligned, so we have to be careful | 
 | 		 to insert the argument on the correct side of the buffer. | 
 | 		 This is why we use store_unsigned_integer.  */ | 
 | 	      store_unsigned_integer | 
 | 		(val_buf, 8, byte_order, | 
 | 		 extract_unsigned_integer (arg->contents ().data (), len, | 
 | 					   byte_order)); | 
 | 	    } | 
 | 	  else | 
 | 	    { | 
 | 	      /* This is either an 8bit integral type, or an aggregate. | 
 | 		 For 8bit integral type, there is no problem, we just | 
 | 		 copy the value over. | 
 |  | 
 | 		 For aggregates, the only potentially tricky portion | 
 | 		 is to write the last one if it is less than 8 bytes. | 
 | 		 In this case, the data is Byte0-aligned.  Happy news, | 
 | 		 this means that we don't need to differentiate the | 
 | 		 handling of 8byte blocks and less-than-8bytes blocks.  */ | 
 | 	      memcpy (val_buf, arg->contents ().data () + argoffset, | 
 | 		      (len > 8) ? 8 : len); | 
 | 	    } | 
 |  | 
 | 	  if (slotnum < rseslots) | 
 | 	    tdep->infcall_ops.store_argument_in_slot (regcache, bsp, | 
 | 						      slotnum, val_buf); | 
 | 	  else | 
 | 	    write_memory (sp + 16 + 8 * (slotnum - rseslots), val_buf, 8); | 
 |  | 
 | 	  argoffset += 8; | 
 | 	  len -= 8; | 
 | 	  slotnum++; | 
 | 	} | 
 |  | 
 |       /* Handle floating point types (including HFAs).  */ | 
 |       float_elt_type = is_float_or_hfa_type (type); | 
 |       if (float_elt_type != NULL) | 
 | 	{ | 
 | 	  argoffset = 0; | 
 | 	  len = type->length (); | 
 | 	  while (len > 0 && floatreg < IA64_FR16_REGNUM) | 
 | 	    { | 
 | 	      gdb_byte to[IA64_FP_REGISTER_SIZE]; | 
 | 	      target_float_convert (arg->contents ().data () + argoffset, | 
 | 				    float_elt_type, to, | 
 | 				    ia64_ext_type (gdbarch)); | 
 | 	      regcache->cooked_write (floatreg, to); | 
 | 	      floatreg++; | 
 | 	      argoffset += float_elt_type->length (); | 
 | 	      len -= float_elt_type->length (); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |   /* Store the struct return value in r8 if necessary.  */ | 
 |   if (return_method == return_method_struct) | 
 |     regcache_cooked_write_unsigned (regcache, IA64_GR8_REGNUM, | 
 | 				    (ULONGEST) struct_addr); | 
 |  | 
 |   global_pointer = ia64_find_global_pointer (gdbarch, func_addr); | 
 |  | 
 |   if (global_pointer != 0) | 
 |     regcache_cooked_write_unsigned (regcache, IA64_GR1_REGNUM, global_pointer); | 
 |  | 
 |   /* The following is not necessary on HP-UX, because we're using | 
 |      a dummy code sequence pushed on the stack to make the call, and | 
 |      this sequence doesn't need b0 to be set in order for our dummy | 
 |      breakpoint to be hit.  Nonetheless, this doesn't interfere, and | 
 |      it's needed for other OSes, so we do this unconditionaly.  */ | 
 |   regcache_cooked_write_unsigned (regcache, IA64_BR0_REGNUM, bp_addr); | 
 |  | 
 |   regcache_cooked_write_unsigned (regcache, sp_regnum, sp); | 
 |  | 
 |   tdep->infcall_ops.set_function_addr (regcache, func_addr); | 
 |  | 
 |   return sp; | 
 | } | 
 |  | 
 | static const struct ia64_infcall_ops ia64_infcall_ops = | 
 | { | 
 |   ia64_allocate_new_rse_frame, | 
 |   ia64_store_argument_in_slot, | 
 |   ia64_set_function_addr | 
 | }; | 
 |  | 
 | static struct frame_id | 
 | ia64_dummy_id (struct gdbarch *gdbarch, frame_info_ptr this_frame) | 
 | { | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   gdb_byte buf[8]; | 
 |   CORE_ADDR sp, bsp; | 
 |  | 
 |   get_frame_register (this_frame, sp_regnum, buf); | 
 |   sp = extract_unsigned_integer (buf, 8, byte_order); | 
 |  | 
 |   get_frame_register (this_frame, IA64_BSP_REGNUM, buf); | 
 |   bsp = extract_unsigned_integer (buf, 8, byte_order); | 
 |  | 
 |   if (gdbarch_debug >= 1) | 
 |     gdb_printf (gdb_stdlog, | 
 | 		"dummy frame id: code %s, stack %s, special %s\n", | 
 | 		paddress (gdbarch, get_frame_pc (this_frame)), | 
 | 		paddress (gdbarch, sp), paddress (gdbarch, bsp)); | 
 |  | 
 |   return frame_id_build_special (sp, get_frame_pc (this_frame), bsp); | 
 | } | 
 |  | 
 | static CORE_ADDR  | 
 | ia64_unwind_pc (struct gdbarch *gdbarch, frame_info_ptr next_frame) | 
 | { | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   gdb_byte buf[8]; | 
 |   CORE_ADDR ip, psr, pc; | 
 |  | 
 |   frame_unwind_register (next_frame, IA64_IP_REGNUM, buf); | 
 |   ip = extract_unsigned_integer (buf, 8, byte_order); | 
 |   frame_unwind_register (next_frame, IA64_PSR_REGNUM, buf); | 
 |   psr = extract_unsigned_integer (buf, 8, byte_order); | 
 |   | 
 |   pc = (ip & ~0xf) | ((psr >> 41) & 3); | 
 |   return pc; | 
 | } | 
 |  | 
 | static int | 
 | ia64_print_insn (bfd_vma memaddr, struct disassemble_info *info) | 
 | { | 
 |   info->bytes_per_line = SLOT_MULTIPLIER; | 
 |   return default_print_insn (memaddr, info); | 
 | } | 
 |  | 
 | /* The default "size_of_register_frame" gdbarch_tdep routine for ia64.  */ | 
 |  | 
 | static int | 
 | ia64_size_of_register_frame (frame_info_ptr this_frame, ULONGEST cfm) | 
 | { | 
 |   return (cfm & 0x7f); | 
 | } | 
 |  | 
 | static struct gdbarch * | 
 | ia64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | 
 | { | 
 |   /* If there is already a candidate, use it.  */ | 
 |   arches = gdbarch_list_lookup_by_info (arches, &info); | 
 |   if (arches != NULL) | 
 |     return arches->gdbarch; | 
 |  | 
 |   gdbarch *gdbarch | 
 |     = gdbarch_alloc (&info, gdbarch_tdep_up (new ia64_gdbarch_tdep)); | 
 |   ia64_gdbarch_tdep *tdep = gdbarch_tdep<ia64_gdbarch_tdep> (gdbarch); | 
 |  | 
 |   tdep->size_of_register_frame = ia64_size_of_register_frame; | 
 |  | 
 |   /* According to the ia64 specs, instructions that store long double | 
 |      floats in memory use a long-double format different than that | 
 |      used in the floating registers.  The memory format matches the | 
 |      x86 extended float format which is 80 bits.  An OS may choose to | 
 |      use this format (e.g. GNU/Linux) or choose to use a different | 
 |      format for storing long doubles (e.g. HPUX).  In the latter case, | 
 |      the setting of the format may be moved/overridden in an | 
 |      OS-specific tdep file.  */ | 
 |   set_gdbarch_long_double_format (gdbarch, floatformats_i387_ext); | 
 |  | 
 |   set_gdbarch_short_bit (gdbarch, 16); | 
 |   set_gdbarch_int_bit (gdbarch, 32); | 
 |   set_gdbarch_long_bit (gdbarch, 64); | 
 |   set_gdbarch_long_long_bit (gdbarch, 64); | 
 |   set_gdbarch_float_bit (gdbarch, 32); | 
 |   set_gdbarch_double_bit (gdbarch, 64); | 
 |   set_gdbarch_long_double_bit (gdbarch, 128); | 
 |   set_gdbarch_ptr_bit (gdbarch, 64); | 
 |  | 
 |   set_gdbarch_num_regs (gdbarch, NUM_IA64_RAW_REGS); | 
 |   set_gdbarch_num_pseudo_regs (gdbarch, | 
 | 			       LAST_PSEUDO_REGNUM - FIRST_PSEUDO_REGNUM); | 
 |   set_gdbarch_sp_regnum (gdbarch, sp_regnum); | 
 |   set_gdbarch_fp0_regnum (gdbarch, IA64_FR0_REGNUM); | 
 |  | 
 |   set_gdbarch_register_name (gdbarch, ia64_register_name); | 
 |   set_gdbarch_register_type (gdbarch, ia64_register_type); | 
 |  | 
 |   set_gdbarch_pseudo_register_read (gdbarch, ia64_pseudo_register_read); | 
 |   set_gdbarch_pseudo_register_write (gdbarch, ia64_pseudo_register_write); | 
 |   set_gdbarch_dwarf2_reg_to_regnum (gdbarch, ia64_dwarf_reg_to_regnum); | 
 |   set_gdbarch_register_reggroup_p (gdbarch, ia64_register_reggroup_p); | 
 |   set_gdbarch_convert_register_p (gdbarch, ia64_convert_register_p); | 
 |   set_gdbarch_register_to_value (gdbarch, ia64_register_to_value); | 
 |   set_gdbarch_value_to_register (gdbarch, ia64_value_to_register); | 
 |  | 
 |   set_gdbarch_skip_prologue (gdbarch, ia64_skip_prologue); | 
 |  | 
 |   set_gdbarch_return_value (gdbarch, ia64_return_value); | 
 |  | 
 |   set_gdbarch_memory_insert_breakpoint (gdbarch, | 
 | 					ia64_memory_insert_breakpoint); | 
 |   set_gdbarch_memory_remove_breakpoint (gdbarch, | 
 | 					ia64_memory_remove_breakpoint); | 
 |   set_gdbarch_breakpoint_from_pc (gdbarch, ia64_breakpoint_from_pc); | 
 |   set_gdbarch_breakpoint_kind_from_pc (gdbarch, ia64_breakpoint_kind_from_pc); | 
 |   set_gdbarch_read_pc (gdbarch, ia64_read_pc); | 
 |   set_gdbarch_write_pc (gdbarch, ia64_write_pc); | 
 |  | 
 |   /* Settings for calling functions in the inferior.  */ | 
 |   set_gdbarch_push_dummy_call (gdbarch, ia64_push_dummy_call); | 
 |   tdep->infcall_ops = ia64_infcall_ops; | 
 |   set_gdbarch_frame_align (gdbarch, ia64_frame_align); | 
 |   set_gdbarch_dummy_id (gdbarch, ia64_dummy_id); | 
 |  | 
 |   set_gdbarch_unwind_pc (gdbarch, ia64_unwind_pc); | 
 | #ifdef HAVE_LIBUNWIND_IA64_H | 
 |   frame_unwind_append_unwinder (gdbarch, | 
 | 				&ia64_libunwind_sigtramp_frame_unwind); | 
 |   frame_unwind_append_unwinder (gdbarch, &ia64_libunwind_frame_unwind); | 
 |   frame_unwind_append_unwinder (gdbarch, &ia64_sigtramp_frame_unwind); | 
 |   libunwind_frame_set_descr (gdbarch, &ia64_libunwind_descr); | 
 | #else | 
 |   frame_unwind_append_unwinder (gdbarch, &ia64_sigtramp_frame_unwind); | 
 | #endif | 
 |   frame_unwind_append_unwinder (gdbarch, &ia64_frame_unwind); | 
 |   frame_base_set_default (gdbarch, &ia64_frame_base); | 
 |  | 
 |   /* Settings that should be unnecessary.  */ | 
 |   set_gdbarch_inner_than (gdbarch, core_addr_lessthan); | 
 |  | 
 |   set_gdbarch_print_insn (gdbarch, ia64_print_insn); | 
 |   set_gdbarch_convert_from_func_ptr_addr (gdbarch, | 
 | 					  ia64_convert_from_func_ptr_addr); | 
 |  | 
 |   /* The virtual table contains 16-byte descriptors, not pointers to | 
 |      descriptors.  */ | 
 |   set_gdbarch_vtable_function_descriptors (gdbarch, 1); | 
 |  | 
 |   /* Hook in ABI-specific overrides, if they have been registered.  */ | 
 |   gdbarch_init_osabi (info, gdbarch); | 
 |  | 
 |   return gdbarch; | 
 | } | 
 |  | 
 | void _initialize_ia64_tdep (); | 
 | void | 
 | _initialize_ia64_tdep () | 
 | { | 
 |   gdbarch_register (bfd_arch_ia64, ia64_gdbarch_init, NULL); | 
 | } |