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