1130803Smarcel/* Target-dependent code for UltraSPARC. 2130803Smarcel 3130803Smarcel Copyright 2003, 2004 Free Software Foundation, Inc. 4130803Smarcel 5130803Smarcel This file is part of GDB. 6130803Smarcel 7130803Smarcel This program is free software; you can redistribute it and/or modify 8130803Smarcel it under the terms of the GNU General Public License as published by 9130803Smarcel the Free Software Foundation; either version 2 of the License, or 10130803Smarcel (at your option) any later version. 11130803Smarcel 12130803Smarcel This program is distributed in the hope that it will be useful, 13130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 14130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15130803Smarcel GNU General Public License for more details. 16130803Smarcel 17130803Smarcel You should have received a copy of the GNU General Public License 18130803Smarcel along with this program; if not, write to the Free Software 19130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 20130803Smarcel Boston, MA 02111-1307, USA. */ 21130803Smarcel 22130803Smarcel#include "defs.h" 23130803Smarcel#include "arch-utils.h" 24130803Smarcel#include "floatformat.h" 25130803Smarcel#include "frame.h" 26130803Smarcel#include "frame-base.h" 27130803Smarcel#include "frame-unwind.h" 28130803Smarcel#include "gdbcore.h" 29130803Smarcel#include "gdbtypes.h" 30130803Smarcel#include "inferior.h" 31130803Smarcel#include "symtab.h" 32130803Smarcel#include "objfiles.h" 33130803Smarcel#include "osabi.h" 34130803Smarcel#include "regcache.h" 35130803Smarcel#include "target.h" 36130803Smarcel#include "value.h" 37130803Smarcel 38130803Smarcel#include "gdb_assert.h" 39130803Smarcel#include "gdb_string.h" 40130803Smarcel 41130803Smarcel#include "sparc64-tdep.h" 42130803Smarcel 43130803Smarcel/* This file implements the The SPARC 64-bit ABI as defined by the 44130803Smarcel section "Low-Level System Information" of the SPARC Compliance 45130803Smarcel Definition (SCD) 2.4.1, which is the 64-bit System V psABI for 46130803Smarcel SPARC. */ 47130803Smarcel 48130803Smarcel/* Please use the sparc32_-prefix for 32-bit specific code, the 49130803Smarcel sparc64_-prefix for 64-bit specific code and the sparc_-prefix for 50130803Smarcel code can handle both. */ 51130803Smarcel 52130803Smarcel/* The functions on this page are intended to be used to classify 53130803Smarcel function arguments. */ 54130803Smarcel 55130803Smarcel/* Return the contents if register REGNUM as an address. */ 56130803Smarcel 57130803Smarcelstatic CORE_ADDR 58130803Smarcelsparc_address_from_register (int regnum) 59130803Smarcel{ 60130803Smarcel ULONGEST addr; 61130803Smarcel 62130803Smarcel regcache_cooked_read_unsigned (current_regcache, regnum, &addr); 63130803Smarcel return addr; 64130803Smarcel} 65130803Smarcel 66130803Smarcel/* Check whether TYPE is "Integral or Pointer". */ 67130803Smarcel 68130803Smarcelstatic int 69130803Smarcelsparc64_integral_or_pointer_p (const struct type *type) 70130803Smarcel{ 71130803Smarcel switch (TYPE_CODE (type)) 72130803Smarcel { 73130803Smarcel case TYPE_CODE_INT: 74130803Smarcel case TYPE_CODE_BOOL: 75130803Smarcel case TYPE_CODE_CHAR: 76130803Smarcel case TYPE_CODE_ENUM: 77130803Smarcel case TYPE_CODE_RANGE: 78130803Smarcel { 79130803Smarcel int len = TYPE_LENGTH (type); 80130803Smarcel gdb_assert (len == 1 || len == 2 || len == 4 || len == 8); 81130803Smarcel } 82130803Smarcel return 1; 83130803Smarcel case TYPE_CODE_PTR: 84130803Smarcel case TYPE_CODE_REF: 85130803Smarcel { 86130803Smarcel int len = TYPE_LENGTH (type); 87130803Smarcel gdb_assert (len == 8); 88130803Smarcel } 89130803Smarcel return 1; 90130803Smarcel default: 91130803Smarcel break; 92130803Smarcel } 93130803Smarcel 94130803Smarcel return 0; 95130803Smarcel} 96130803Smarcel 97130803Smarcel/* Check whether TYPE is "Floating". */ 98130803Smarcel 99130803Smarcelstatic int 100130803Smarcelsparc64_floating_p (const struct type *type) 101130803Smarcel{ 102130803Smarcel switch (TYPE_CODE (type)) 103130803Smarcel { 104130803Smarcel case TYPE_CODE_FLT: 105130803Smarcel { 106130803Smarcel int len = TYPE_LENGTH (type); 107130803Smarcel gdb_assert (len == 4 || len == 8 || len == 16); 108130803Smarcel } 109130803Smarcel return 1; 110130803Smarcel default: 111130803Smarcel break; 112130803Smarcel } 113130803Smarcel 114130803Smarcel return 0; 115130803Smarcel} 116130803Smarcel 117130803Smarcel/* Check whether TYPE is "Structure or Union". */ 118130803Smarcel 119130803Smarcelstatic int 120130803Smarcelsparc64_structure_or_union_p (const struct type *type) 121130803Smarcel{ 122130803Smarcel switch (TYPE_CODE (type)) 123130803Smarcel { 124130803Smarcel case TYPE_CODE_STRUCT: 125130803Smarcel case TYPE_CODE_UNION: 126130803Smarcel return 1; 127130803Smarcel default: 128130803Smarcel break; 129130803Smarcel } 130130803Smarcel 131130803Smarcel return 0; 132130803Smarcel} 133130803Smarcel 134130803Smarcel/* Register information. */ 135130803Smarcel 136130803Smarcelstruct sparc64_register_info 137130803Smarcel{ 138130803Smarcel char *name; 139130803Smarcel struct type **type; 140130803Smarcel}; 141130803Smarcel 142130803Smarcelstatic struct sparc64_register_info sparc64_register_info[] = 143130803Smarcel{ 144130803Smarcel { "g0", &builtin_type_int64 }, 145130803Smarcel { "g1", &builtin_type_int64 }, 146130803Smarcel { "g2", &builtin_type_int64 }, 147130803Smarcel { "g3", &builtin_type_int64 }, 148130803Smarcel { "g4", &builtin_type_int64 }, 149130803Smarcel { "g5", &builtin_type_int64 }, 150130803Smarcel { "g6", &builtin_type_int64 }, 151130803Smarcel { "g7", &builtin_type_int64 }, 152130803Smarcel 153130803Smarcel { "o0", &builtin_type_int64 }, 154130803Smarcel { "o1", &builtin_type_int64 }, 155130803Smarcel { "o2", &builtin_type_int64 }, 156130803Smarcel { "o3", &builtin_type_int64 }, 157130803Smarcel { "o4", &builtin_type_int64 }, 158130803Smarcel { "o5", &builtin_type_int64 }, 159130803Smarcel { "sp", &builtin_type_void_data_ptr }, 160130803Smarcel { "o7", &builtin_type_int64 }, 161130803Smarcel 162130803Smarcel { "l0", &builtin_type_int64 }, 163130803Smarcel { "l1", &builtin_type_int64 }, 164130803Smarcel { "l2", &builtin_type_int64 }, 165130803Smarcel { "l3", &builtin_type_int64 }, 166130803Smarcel { "l4", &builtin_type_int64 }, 167130803Smarcel { "l5", &builtin_type_int64 }, 168130803Smarcel { "l6", &builtin_type_int64 }, 169130803Smarcel { "l7", &builtin_type_int64 }, 170130803Smarcel 171130803Smarcel { "i0", &builtin_type_int64 }, 172130803Smarcel { "i1", &builtin_type_int64 }, 173130803Smarcel { "i2", &builtin_type_int64 }, 174130803Smarcel { "i3", &builtin_type_int64 }, 175130803Smarcel { "i4", &builtin_type_int64 }, 176130803Smarcel { "i5", &builtin_type_int64 }, 177130803Smarcel { "fp", &builtin_type_void_data_ptr }, 178130803Smarcel { "i7", &builtin_type_int64 }, 179130803Smarcel 180130803Smarcel { "f0", &builtin_type_float }, 181130803Smarcel { "f1", &builtin_type_float }, 182130803Smarcel { "f2", &builtin_type_float }, 183130803Smarcel { "f3", &builtin_type_float }, 184130803Smarcel { "f4", &builtin_type_float }, 185130803Smarcel { "f5", &builtin_type_float }, 186130803Smarcel { "f6", &builtin_type_float }, 187130803Smarcel { "f7", &builtin_type_float }, 188130803Smarcel { "f8", &builtin_type_float }, 189130803Smarcel { "f9", &builtin_type_float }, 190130803Smarcel { "f10", &builtin_type_float }, 191130803Smarcel { "f11", &builtin_type_float }, 192130803Smarcel { "f12", &builtin_type_float }, 193130803Smarcel { "f13", &builtin_type_float }, 194130803Smarcel { "f14", &builtin_type_float }, 195130803Smarcel { "f15", &builtin_type_float }, 196130803Smarcel { "f16", &builtin_type_float }, 197130803Smarcel { "f17", &builtin_type_float }, 198130803Smarcel { "f18", &builtin_type_float }, 199130803Smarcel { "f19", &builtin_type_float }, 200130803Smarcel { "f20", &builtin_type_float }, 201130803Smarcel { "f21", &builtin_type_float }, 202130803Smarcel { "f22", &builtin_type_float }, 203130803Smarcel { "f23", &builtin_type_float }, 204130803Smarcel { "f24", &builtin_type_float }, 205130803Smarcel { "f25", &builtin_type_float }, 206130803Smarcel { "f26", &builtin_type_float }, 207130803Smarcel { "f27", &builtin_type_float }, 208130803Smarcel { "f28", &builtin_type_float }, 209130803Smarcel { "f29", &builtin_type_float }, 210130803Smarcel { "f30", &builtin_type_float }, 211130803Smarcel { "f31", &builtin_type_float }, 212130803Smarcel { "f32", &builtin_type_double }, 213130803Smarcel { "f34", &builtin_type_double }, 214130803Smarcel { "f36", &builtin_type_double }, 215130803Smarcel { "f38", &builtin_type_double }, 216130803Smarcel { "f40", &builtin_type_double }, 217130803Smarcel { "f42", &builtin_type_double }, 218130803Smarcel { "f44", &builtin_type_double }, 219130803Smarcel { "f46", &builtin_type_double }, 220130803Smarcel { "f48", &builtin_type_double }, 221130803Smarcel { "f50", &builtin_type_double }, 222130803Smarcel { "f52", &builtin_type_double }, 223130803Smarcel { "f54", &builtin_type_double }, 224130803Smarcel { "f56", &builtin_type_double }, 225130803Smarcel { "f58", &builtin_type_double }, 226130803Smarcel { "f60", &builtin_type_double }, 227130803Smarcel { "f62", &builtin_type_double }, 228130803Smarcel 229130803Smarcel { "pc", &builtin_type_void_func_ptr }, 230130803Smarcel { "npc", &builtin_type_void_func_ptr }, 231130803Smarcel 232130803Smarcel /* This raw register contains the contents of %cwp, %pstate, %asi 233130803Smarcel and %ccr as laid out in a %tstate register. */ 234130803Smarcel /* FIXME: Give it a name until we start using register groups. */ 235130803Smarcel { "state", &builtin_type_int64 }, 236130803Smarcel 237130803Smarcel { "fsr", &builtin_type_int64 }, 238130803Smarcel { "fprs", &builtin_type_int64 }, 239130803Smarcel 240130803Smarcel /* "Although Y is a 64-bit register, its high-order 32 bits are 241130803Smarcel reserved and always read as 0." */ 242130803Smarcel { "y", &builtin_type_int64 } 243130803Smarcel}; 244130803Smarcel 245130803Smarcel/* Total number of registers. */ 246130803Smarcel#define SPARC64_NUM_REGS ARRAY_SIZE (sparc64_register_info) 247130803Smarcel 248130803Smarcel/* We provide the aliases %d0..%d62 and %q0..%q60 for the floating 249130803Smarcel registers as "psuedo" registers. */ 250130803Smarcel 251130803Smarcelstatic struct sparc64_register_info sparc64_pseudo_register_info[] = 252130803Smarcel{ 253130803Smarcel { "cwp", &builtin_type_int64 }, 254130803Smarcel { "pstate", &builtin_type_int64 }, 255130803Smarcel { "asi", &builtin_type_int64 }, 256130803Smarcel { "ccr", &builtin_type_int64 }, 257130803Smarcel 258130803Smarcel { "d0", &builtin_type_double }, 259130803Smarcel { "d2", &builtin_type_double }, 260130803Smarcel { "d4", &builtin_type_double }, 261130803Smarcel { "d6", &builtin_type_double }, 262130803Smarcel { "d8", &builtin_type_double }, 263130803Smarcel { "d10", &builtin_type_double }, 264130803Smarcel { "d12", &builtin_type_double }, 265130803Smarcel { "d14", &builtin_type_double }, 266130803Smarcel { "d16", &builtin_type_double }, 267130803Smarcel { "d18", &builtin_type_double }, 268130803Smarcel { "d20", &builtin_type_double }, 269130803Smarcel { "d22", &builtin_type_double }, 270130803Smarcel { "d24", &builtin_type_double }, 271130803Smarcel { "d26", &builtin_type_double }, 272130803Smarcel { "d28", &builtin_type_double }, 273130803Smarcel { "d30", &builtin_type_double }, 274130803Smarcel { "d32", &builtin_type_double }, 275130803Smarcel { "d34", &builtin_type_double }, 276130803Smarcel { "d36", &builtin_type_double }, 277130803Smarcel { "d38", &builtin_type_double }, 278130803Smarcel { "d40", &builtin_type_double }, 279130803Smarcel { "d42", &builtin_type_double }, 280130803Smarcel { "d44", &builtin_type_double }, 281130803Smarcel { "d46", &builtin_type_double }, 282130803Smarcel { "d48", &builtin_type_double }, 283130803Smarcel { "d50", &builtin_type_double }, 284130803Smarcel { "d52", &builtin_type_double }, 285130803Smarcel { "d54", &builtin_type_double }, 286130803Smarcel { "d56", &builtin_type_double }, 287130803Smarcel { "d58", &builtin_type_double }, 288130803Smarcel { "d60", &builtin_type_double }, 289130803Smarcel { "d62", &builtin_type_double }, 290130803Smarcel 291130803Smarcel { "q0", &builtin_type_long_double }, 292130803Smarcel { "q4", &builtin_type_long_double }, 293130803Smarcel { "q8", &builtin_type_long_double }, 294130803Smarcel { "q12", &builtin_type_long_double }, 295130803Smarcel { "q16", &builtin_type_long_double }, 296130803Smarcel { "q20", &builtin_type_long_double }, 297130803Smarcel { "q24", &builtin_type_long_double }, 298130803Smarcel { "q28", &builtin_type_long_double }, 299130803Smarcel { "q32", &builtin_type_long_double }, 300130803Smarcel { "q36", &builtin_type_long_double }, 301130803Smarcel { "q40", &builtin_type_long_double }, 302130803Smarcel { "q44", &builtin_type_long_double }, 303130803Smarcel { "q48", &builtin_type_long_double }, 304130803Smarcel { "q52", &builtin_type_long_double }, 305130803Smarcel { "q56", &builtin_type_long_double }, 306130803Smarcel { "q60", &builtin_type_long_double } 307130803Smarcel}; 308130803Smarcel 309130803Smarcel/* Total number of pseudo registers. */ 310130803Smarcel#define SPARC64_NUM_PSEUDO_REGS ARRAY_SIZE (sparc64_pseudo_register_info) 311130803Smarcel 312130803Smarcel/* Return the name of register REGNUM. */ 313130803Smarcel 314130803Smarcelstatic const char * 315130803Smarcelsparc64_register_name (int regnum) 316130803Smarcel{ 317130803Smarcel if (regnum >= 0 && regnum < SPARC64_NUM_REGS) 318130803Smarcel return sparc64_register_info[regnum].name; 319130803Smarcel 320130803Smarcel if (regnum >= SPARC64_NUM_REGS 321130803Smarcel && regnum < SPARC64_NUM_REGS + SPARC64_NUM_PSEUDO_REGS) 322130803Smarcel return sparc64_pseudo_register_info[regnum - SPARC64_NUM_REGS].name; 323130803Smarcel 324130803Smarcel return NULL; 325130803Smarcel} 326130803Smarcel 327130803Smarcel/* Return the GDB type object for the "standard" data type of data in 328130803Smarcel register REGNUM. */ 329130803Smarcel 330130803Smarcelstatic struct type * 331130803Smarcelsparc64_register_type (struct gdbarch *gdbarch, int regnum) 332130803Smarcel{ 333130803Smarcel if (regnum >= SPARC64_NUM_REGS 334130803Smarcel && regnum < SPARC64_NUM_REGS + SPARC64_NUM_PSEUDO_REGS) 335130803Smarcel return *sparc64_pseudo_register_info[regnum - SPARC64_NUM_REGS].type; 336130803Smarcel 337130803Smarcel gdb_assert (regnum >= 0 && regnum < SPARC64_NUM_REGS); 338130803Smarcel return *sparc64_register_info[regnum].type; 339130803Smarcel} 340130803Smarcel 341130803Smarcelstatic void 342130803Smarcelsparc64_pseudo_register_read (struct gdbarch *gdbarch, 343130803Smarcel struct regcache *regcache, 344130803Smarcel int regnum, void *buf) 345130803Smarcel{ 346130803Smarcel gdb_assert (regnum >= SPARC64_NUM_REGS); 347130803Smarcel 348130803Smarcel if (regnum >= SPARC64_D0_REGNUM && regnum <= SPARC64_D30_REGNUM) 349130803Smarcel { 350130803Smarcel regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC64_D0_REGNUM); 351130803Smarcel regcache_raw_read (regcache, regnum, buf); 352130803Smarcel regcache_raw_read (regcache, regnum + 1, ((char *)buf) + 4); 353130803Smarcel } 354130803Smarcel else if (regnum >= SPARC64_D32_REGNUM && regnum <= SPARC64_D62_REGNUM) 355130803Smarcel { 356130803Smarcel regnum = SPARC64_F32_REGNUM + (regnum - SPARC64_D32_REGNUM); 357130803Smarcel regcache_raw_read (regcache, regnum, buf); 358130803Smarcel } 359130803Smarcel else if (regnum >= SPARC64_Q0_REGNUM && regnum <= SPARC64_Q28_REGNUM) 360130803Smarcel { 361130803Smarcel regnum = SPARC_F0_REGNUM + 4 * (regnum - SPARC64_Q0_REGNUM); 362130803Smarcel regcache_raw_read (regcache, regnum, buf); 363130803Smarcel regcache_raw_read (regcache, regnum + 1, ((char *)buf) + 4); 364130803Smarcel regcache_raw_read (regcache, regnum + 2, ((char *)buf) + 8); 365130803Smarcel regcache_raw_read (regcache, regnum + 3, ((char *)buf) + 12); 366130803Smarcel } 367130803Smarcel else if (regnum >= SPARC64_Q32_REGNUM && regnum <= SPARC64_Q60_REGNUM) 368130803Smarcel { 369130803Smarcel regnum = SPARC64_F32_REGNUM + 2 * (regnum - SPARC64_Q32_REGNUM); 370130803Smarcel regcache_raw_read (regcache, regnum, buf); 371130803Smarcel regcache_raw_read (regcache, regnum + 1, ((char *)buf) + 8); 372130803Smarcel } 373130803Smarcel else if (regnum == SPARC64_CWP_REGNUM 374130803Smarcel || regnum == SPARC64_PSTATE_REGNUM 375130803Smarcel || regnum == SPARC64_ASI_REGNUM 376130803Smarcel || regnum == SPARC64_CCR_REGNUM) 377130803Smarcel { 378130803Smarcel ULONGEST state; 379130803Smarcel 380130803Smarcel regcache_raw_read_unsigned (regcache, SPARC64_STATE_REGNUM, &state); 381130803Smarcel switch (regnum) 382130803Smarcel { 383130803Smarcel case SPARC64_CWP_REGNUM: 384130803Smarcel state = (state >> 0) & ((1 << 5) - 1); 385130803Smarcel break; 386130803Smarcel case SPARC64_PSTATE_REGNUM: 387130803Smarcel state = (state >> 8) & ((1 << 12) - 1); 388130803Smarcel break; 389130803Smarcel case SPARC64_ASI_REGNUM: 390130803Smarcel state = (state >> 24) & ((1 << 8) - 1); 391130803Smarcel break; 392130803Smarcel case SPARC64_CCR_REGNUM: 393130803Smarcel state = (state >> 32) & ((1 << 8) - 1); 394130803Smarcel break; 395130803Smarcel } 396130803Smarcel store_unsigned_integer (buf, 8, state); 397130803Smarcel } 398130803Smarcel} 399130803Smarcel 400130803Smarcelstatic void 401130803Smarcelsparc64_pseudo_register_write (struct gdbarch *gdbarch, 402130803Smarcel struct regcache *regcache, 403130803Smarcel int regnum, const void *buf) 404130803Smarcel{ 405130803Smarcel gdb_assert (regnum >= SPARC64_NUM_REGS); 406130803Smarcel 407130803Smarcel if (regnum >= SPARC64_D0_REGNUM && regnum <= SPARC64_D30_REGNUM) 408130803Smarcel { 409130803Smarcel regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC64_D0_REGNUM); 410130803Smarcel regcache_raw_write (regcache, regnum, buf); 411130803Smarcel regcache_raw_write (regcache, regnum + 1, ((const char *)buf) + 4); 412130803Smarcel } 413130803Smarcel else if (regnum >= SPARC64_D32_REGNUM && regnum <= SPARC64_D62_REGNUM) 414130803Smarcel { 415130803Smarcel regnum = SPARC64_F32_REGNUM + (regnum - SPARC64_D32_REGNUM); 416130803Smarcel regcache_raw_write (regcache, regnum, buf); 417130803Smarcel } 418130803Smarcel else if (regnum >= SPARC64_Q0_REGNUM && regnum <= SPARC64_Q28_REGNUM) 419130803Smarcel { 420130803Smarcel regnum = SPARC_F0_REGNUM + 4 * (regnum - SPARC64_Q0_REGNUM); 421130803Smarcel regcache_raw_write (regcache, regnum, buf); 422130803Smarcel regcache_raw_write (regcache, regnum + 1, ((const char *)buf) + 4); 423130803Smarcel regcache_raw_write (regcache, regnum + 2, ((const char *)buf) + 8); 424130803Smarcel regcache_raw_write (regcache, regnum + 3, ((const char *)buf) + 12); 425130803Smarcel } 426130803Smarcel else if (regnum >= SPARC64_Q32_REGNUM && regnum <= SPARC64_Q60_REGNUM) 427130803Smarcel { 428130803Smarcel regnum = SPARC64_F32_REGNUM + 2 * (regnum - SPARC64_Q32_REGNUM); 429130803Smarcel regcache_raw_write (regcache, regnum, buf); 430130803Smarcel regcache_raw_write (regcache, regnum + 1, ((const char *)buf) + 8); 431130803Smarcel } 432130803Smarcel else if (regnum == SPARC64_CWP_REGNUM 433130803Smarcel || regnum == SPARC64_PSTATE_REGNUM 434130803Smarcel || regnum == SPARC64_ASI_REGNUM 435130803Smarcel || regnum == SPARC64_CCR_REGNUM) 436130803Smarcel { 437130803Smarcel ULONGEST state, bits; 438130803Smarcel 439130803Smarcel regcache_raw_read_unsigned (regcache, SPARC64_STATE_REGNUM, &state); 440130803Smarcel bits = extract_unsigned_integer (buf, 8); 441130803Smarcel switch (regnum) 442130803Smarcel { 443130803Smarcel case SPARC64_CWP_REGNUM: 444130803Smarcel state |= ((bits & ((1 << 5) - 1)) << 0); 445130803Smarcel break; 446130803Smarcel case SPARC64_PSTATE_REGNUM: 447130803Smarcel state |= ((bits & ((1 << 12) - 1)) << 8); 448130803Smarcel break; 449130803Smarcel case SPARC64_ASI_REGNUM: 450130803Smarcel state |= ((bits & ((1 << 8) - 1)) << 24); 451130803Smarcel break; 452130803Smarcel case SPARC64_CCR_REGNUM: 453130803Smarcel state |= ((bits & ((1 << 8) - 1)) << 32); 454130803Smarcel break; 455130803Smarcel } 456130803Smarcel regcache_raw_write_unsigned (regcache, SPARC64_STATE_REGNUM, state); 457130803Smarcel } 458130803Smarcel} 459130803Smarcel 460130803Smarcel 461130803Smarcel/* Return PC of first real instruction of the function starting at 462130803Smarcel START_PC. */ 463130803Smarcel 464130803Smarcelstatic CORE_ADDR 465130803Smarcelsparc64_skip_prologue (CORE_ADDR start_pc) 466130803Smarcel{ 467130803Smarcel struct symtab_and_line sal; 468130803Smarcel CORE_ADDR func_start, func_end; 469130803Smarcel struct sparc_frame_cache cache; 470130803Smarcel 471130803Smarcel /* This is the preferred method, find the end of the prologue by 472130803Smarcel using the debugging information. */ 473130803Smarcel if (find_pc_partial_function (start_pc, NULL, &func_start, &func_end)) 474130803Smarcel { 475130803Smarcel sal = find_pc_line (func_start, 0); 476130803Smarcel 477130803Smarcel if (sal.end < func_end 478130803Smarcel && start_pc <= sal.end) 479130803Smarcel return sal.end; 480130803Smarcel } 481130803Smarcel 482130803Smarcel return sparc_analyze_prologue (start_pc, 0xffffffffffffffffULL, &cache); 483130803Smarcel} 484130803Smarcel 485130803Smarcel/* Normal frames. */ 486130803Smarcel 487130803Smarcelstatic struct sparc_frame_cache * 488130803Smarcelsparc64_frame_cache (struct frame_info *next_frame, void **this_cache) 489130803Smarcel{ 490130803Smarcel return sparc_frame_cache (next_frame, this_cache); 491130803Smarcel} 492130803Smarcel 493130803Smarcelstatic void 494130803Smarcelsparc64_frame_this_id (struct frame_info *next_frame, void **this_cache, 495130803Smarcel struct frame_id *this_id) 496130803Smarcel{ 497130803Smarcel struct sparc_frame_cache *cache = 498130803Smarcel sparc64_frame_cache (next_frame, this_cache); 499130803Smarcel 500130803Smarcel /* This marks the outermost frame. */ 501130803Smarcel if (cache->base == 0) 502130803Smarcel return; 503130803Smarcel 504130803Smarcel (*this_id) = frame_id_build (cache->base, cache->pc); 505130803Smarcel} 506130803Smarcel 507130803Smarcelstatic void 508130803Smarcelsparc64_frame_prev_register (struct frame_info *next_frame, void **this_cache, 509130803Smarcel int regnum, int *optimizedp, 510130803Smarcel enum lval_type *lvalp, CORE_ADDR *addrp, 511130803Smarcel int *realnump, void *valuep) 512130803Smarcel{ 513130803Smarcel struct sparc_frame_cache *cache = 514130803Smarcel sparc64_frame_cache (next_frame, this_cache); 515130803Smarcel 516130803Smarcel if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM) 517130803Smarcel { 518130803Smarcel *optimizedp = 0; 519130803Smarcel *lvalp = not_lval; 520130803Smarcel *addrp = 0; 521130803Smarcel *realnump = -1; 522130803Smarcel if (valuep) 523130803Smarcel { 524130803Smarcel CORE_ADDR pc = (regnum == SPARC64_NPC_REGNUM) ? 4 : 0; 525130803Smarcel 526130803Smarcel regnum = cache->frameless_p ? SPARC_O7_REGNUM : SPARC_I7_REGNUM; 527130803Smarcel pc += frame_unwind_register_unsigned (next_frame, regnum) + 8; 528130803Smarcel store_unsigned_integer (valuep, 8, pc); 529130803Smarcel } 530130803Smarcel return; 531130803Smarcel } 532130803Smarcel 533130803Smarcel /* The previous frame's `local' and `in' registers have been saved 534130803Smarcel in the register save area. */ 535130803Smarcel if (!cache->frameless_p 536130803Smarcel && regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM) 537130803Smarcel { 538130803Smarcel *optimizedp = 0; 539130803Smarcel *lvalp = lval_memory; 540130803Smarcel *addrp = cache->base + BIAS + (regnum - SPARC_L0_REGNUM) * 8; 541130803Smarcel *realnump = -1; 542130803Smarcel if (valuep) 543130803Smarcel { 544130803Smarcel struct gdbarch *gdbarch = get_frame_arch (next_frame); 545130803Smarcel 546130803Smarcel /* Read the value in from memory. */ 547130803Smarcel read_memory (*addrp, valuep, register_size (gdbarch, regnum)); 548130803Smarcel } 549130803Smarcel return; 550130803Smarcel } 551130803Smarcel 552130803Smarcel /* The previous frame's `out' registers are accessable as the 553130803Smarcel current frame's `in' registers. */ 554130803Smarcel if (!cache->frameless_p 555130803Smarcel && regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM) 556130803Smarcel regnum += (SPARC_I0_REGNUM - SPARC_O0_REGNUM); 557130803Smarcel 558130803Smarcel frame_register_unwind (next_frame, regnum, 559130803Smarcel optimizedp, lvalp, addrp, realnump, valuep); 560130803Smarcel} 561130803Smarcel 562130803Smarcelstatic const struct frame_unwind sparc64_frame_unwind = 563130803Smarcel{ 564130803Smarcel NORMAL_FRAME, 565130803Smarcel sparc64_frame_this_id, 566130803Smarcel sparc64_frame_prev_register 567130803Smarcel}; 568130803Smarcel 569130803Smarcelstatic const struct frame_unwind * 570130803Smarcelsparc64_frame_sniffer (struct frame_info *next_frame) 571130803Smarcel{ 572130803Smarcel return &sparc64_frame_unwind; 573130803Smarcel} 574130803Smarcel 575130803Smarcel 576130803Smarcelstatic CORE_ADDR 577130803Smarcelsparc64_frame_base_address (struct frame_info *next_frame, void **this_cache) 578130803Smarcel{ 579130803Smarcel struct sparc_frame_cache *cache = 580130803Smarcel sparc64_frame_cache (next_frame, this_cache); 581130803Smarcel 582130803Smarcel /* ??? Should we take BIAS into account here? */ 583130803Smarcel return cache->base; 584130803Smarcel} 585130803Smarcel 586130803Smarcelstatic const struct frame_base sparc64_frame_base = 587130803Smarcel{ 588130803Smarcel &sparc64_frame_unwind, 589130803Smarcel sparc64_frame_base_address, 590130803Smarcel sparc64_frame_base_address, 591130803Smarcel sparc64_frame_base_address 592130803Smarcel}; 593130803Smarcel 594130803Smarcel/* Check whether TYPE must be 16-byte aligned. */ 595130803Smarcel 596130803Smarcelstatic int 597130803Smarcelsparc64_16_byte_align_p (struct type *type) 598130803Smarcel{ 599130803Smarcel if (sparc64_floating_p (type) && TYPE_LENGTH (type) == 16) 600130803Smarcel return 1; 601130803Smarcel 602130803Smarcel if (sparc64_structure_or_union_p (type)) 603130803Smarcel { 604130803Smarcel int i; 605130803Smarcel 606130803Smarcel for (i = 0; i < TYPE_NFIELDS (type); i++) 607130803Smarcel { 608130803Smarcel struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i)); 609130803Smarcel 610130803Smarcel if (sparc64_16_byte_align_p (subtype)) 611130803Smarcel return 1; 612130803Smarcel } 613130803Smarcel } 614130803Smarcel 615130803Smarcel return 0; 616130803Smarcel} 617130803Smarcel 618130803Smarcel/* Store floating fields of element ELEMENT of an "parameter array" 619130803Smarcel that has type TYPE and is stored at BITPOS in VALBUF in the 620130803Smarcel apropriate registers of REGCACHE. This function can be called 621130803Smarcel recursively and therefore handles floating types in addition to 622130803Smarcel structures. */ 623130803Smarcel 624130803Smarcelstatic void 625130803Smarcelsparc64_store_floating_fields (struct regcache *regcache, struct type *type, 626130803Smarcel char *valbuf, int element, int bitpos) 627130803Smarcel{ 628130803Smarcel gdb_assert (element < 16); 629130803Smarcel 630130803Smarcel if (sparc64_floating_p (type)) 631130803Smarcel { 632130803Smarcel int len = TYPE_LENGTH (type); 633130803Smarcel int regnum; 634130803Smarcel 635130803Smarcel if (len == 16) 636130803Smarcel { 637130803Smarcel gdb_assert (bitpos == 0); 638130803Smarcel gdb_assert ((element % 2) == 0); 639130803Smarcel 640130803Smarcel regnum = SPARC64_Q0_REGNUM + element / 2; 641130803Smarcel regcache_cooked_write (regcache, regnum, valbuf); 642130803Smarcel } 643130803Smarcel else if (len == 8) 644130803Smarcel { 645130803Smarcel gdb_assert (bitpos == 0 || bitpos == 64); 646130803Smarcel 647130803Smarcel regnum = SPARC64_D0_REGNUM + element + bitpos / 64; 648130803Smarcel regcache_cooked_write (regcache, regnum, valbuf + (bitpos / 8)); 649130803Smarcel } 650130803Smarcel else 651130803Smarcel { 652130803Smarcel gdb_assert (len == 4); 653130803Smarcel gdb_assert (bitpos % 32 == 0 && bitpos >= 0 && bitpos < 128); 654130803Smarcel 655130803Smarcel regnum = SPARC_F0_REGNUM + element * 2 + bitpos / 32; 656130803Smarcel regcache_cooked_write (regcache, regnum, valbuf + (bitpos / 8)); 657130803Smarcel } 658130803Smarcel } 659130803Smarcel else if (sparc64_structure_or_union_p (type)) 660130803Smarcel { 661130803Smarcel int i; 662130803Smarcel 663130803Smarcel for (i = 0; i < TYPE_NFIELDS (type); i++) 664130803Smarcel { 665130803Smarcel struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i)); 666130803Smarcel int subpos = bitpos + TYPE_FIELD_BITPOS (type, i); 667130803Smarcel 668130803Smarcel sparc64_store_floating_fields (regcache, subtype, valbuf, 669130803Smarcel element, subpos); 670130803Smarcel } 671130803Smarcel 672130803Smarcel /* GCC has an interesting bug. If TYPE is a structure that has 673130803Smarcel a single `float' member, GCC doesn't treat it as a structure 674130803Smarcel at all, but rather as an ordinary `float' argument. This 675130803Smarcel argument will be stored in %f1, as required by the psABI. 676130803Smarcel However, as a member of a structure the psABI requires it to 677130803Smarcel be stored in %f0. This bug is present in GCC 3.3.2, but 678130803Smarcel probably in older releases to. To appease GCC, if a 679130803Smarcel structure has only a single `float' member, we store its 680130803Smarcel value in %f1 too (we already have stored in %f0). */ 681130803Smarcel if (TYPE_NFIELDS (type) == 1) 682130803Smarcel { 683130803Smarcel struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, 0)); 684130803Smarcel 685130803Smarcel if (sparc64_floating_p (subtype) && TYPE_LENGTH (subtype) == 4) 686130803Smarcel regcache_cooked_write (regcache, SPARC_F1_REGNUM, valbuf); 687130803Smarcel } 688130803Smarcel } 689130803Smarcel} 690130803Smarcel 691130803Smarcel/* Fetch floating fields from a variable of type TYPE from the 692130803Smarcel appropriate registers for BITPOS in REGCACHE and store it at BITPOS 693130803Smarcel in VALBUF. This function can be called recursively and therefore 694130803Smarcel handles floating types in addition to structures. */ 695130803Smarcel 696130803Smarcelstatic void 697130803Smarcelsparc64_extract_floating_fields (struct regcache *regcache, struct type *type, 698130803Smarcel char *valbuf, int bitpos) 699130803Smarcel{ 700130803Smarcel if (sparc64_floating_p (type)) 701130803Smarcel { 702130803Smarcel int len = TYPE_LENGTH (type); 703130803Smarcel int regnum; 704130803Smarcel 705130803Smarcel if (len == 16) 706130803Smarcel { 707130803Smarcel gdb_assert (bitpos == 0 || bitpos == 128); 708130803Smarcel 709130803Smarcel regnum = SPARC64_Q0_REGNUM + bitpos / 128; 710130803Smarcel regcache_cooked_read (regcache, regnum, valbuf + (bitpos / 8)); 711130803Smarcel } 712130803Smarcel else if (len == 8) 713130803Smarcel { 714130803Smarcel gdb_assert (bitpos % 64 == 0 && bitpos >= 0 && bitpos < 256); 715130803Smarcel 716130803Smarcel regnum = SPARC64_D0_REGNUM + bitpos / 64; 717130803Smarcel regcache_cooked_read (regcache, regnum, valbuf + (bitpos / 8)); 718130803Smarcel } 719130803Smarcel else 720130803Smarcel { 721130803Smarcel gdb_assert (len == 4); 722130803Smarcel gdb_assert (bitpos % 32 == 0 && bitpos >= 0 && bitpos < 256); 723130803Smarcel 724130803Smarcel regnum = SPARC_F0_REGNUM + bitpos / 32; 725130803Smarcel regcache_cooked_read (regcache, regnum, valbuf + (bitpos / 8)); 726130803Smarcel } 727130803Smarcel } 728130803Smarcel else if (sparc64_structure_or_union_p (type)) 729130803Smarcel { 730130803Smarcel int i; 731130803Smarcel 732130803Smarcel for (i = 0; i < TYPE_NFIELDS (type); i++) 733130803Smarcel { 734130803Smarcel struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i)); 735130803Smarcel int subpos = bitpos + TYPE_FIELD_BITPOS (type, i); 736130803Smarcel 737130803Smarcel sparc64_extract_floating_fields (regcache, subtype, valbuf, subpos); 738130803Smarcel } 739130803Smarcel } 740130803Smarcel} 741130803Smarcel 742130803Smarcel/* Store the NARGS arguments ARGS and STRUCT_ADDR (if STRUCT_RETURN is 743130803Smarcel non-zero) in REGCACHE and on the stack (starting from address SP). */ 744130803Smarcel 745130803Smarcelstatic CORE_ADDR 746130803Smarcelsparc64_store_arguments (struct regcache *regcache, int nargs, 747130803Smarcel struct value **args, CORE_ADDR sp, 748130803Smarcel int struct_return, CORE_ADDR struct_addr) 749130803Smarcel{ 750130803Smarcel /* Number of extended words in the "parameter array". */ 751130803Smarcel int num_elements = 0; 752130803Smarcel int element = 0; 753130803Smarcel int i; 754130803Smarcel 755130803Smarcel /* Take BIAS into account. */ 756130803Smarcel sp += BIAS; 757130803Smarcel 758130803Smarcel /* First we calculate the number of extended words in the "parameter 759130803Smarcel array". While doing so we also convert some of the arguments. */ 760130803Smarcel 761130803Smarcel if (struct_return) 762130803Smarcel num_elements++; 763130803Smarcel 764130803Smarcel for (i = 0; i < nargs; i++) 765130803Smarcel { 766130803Smarcel struct type *type = VALUE_TYPE (args[i]); 767130803Smarcel int len = TYPE_LENGTH (type); 768130803Smarcel 769130803Smarcel if (sparc64_structure_or_union_p (type)) 770130803Smarcel { 771130803Smarcel /* Structure or Union arguments. */ 772130803Smarcel if (len <= 16) 773130803Smarcel { 774130803Smarcel if (num_elements % 2 && sparc64_16_byte_align_p (type)) 775130803Smarcel num_elements++; 776130803Smarcel num_elements += ((len + 7) / 8); 777130803Smarcel } 778130803Smarcel else 779130803Smarcel { 780130803Smarcel /* The psABI says that "Structures or unions larger than 781130803Smarcel sixteen bytes are copied by the caller and passed 782130803Smarcel indirectly; the caller will pass the address of a 783130803Smarcel correctly aligned structure value. This sixty-four 784130803Smarcel bit address will occupy one word in the parameter 785130803Smarcel array, and may be promoted to an %o register like any 786130803Smarcel other pointer value." Allocate memory for these 787130803Smarcel values on the stack. */ 788130803Smarcel sp -= len; 789130803Smarcel 790130803Smarcel /* Use 16-byte alignment for these values. That's 791130803Smarcel always correct, and wasting a few bytes shouldn't be 792130803Smarcel a problem. */ 793130803Smarcel sp &= ~0xf; 794130803Smarcel 795130803Smarcel write_memory (sp, VALUE_CONTENTS (args[i]), len); 796130803Smarcel args[i] = value_from_pointer (lookup_pointer_type (type), sp); 797130803Smarcel num_elements++; 798130803Smarcel } 799130803Smarcel } 800130803Smarcel else if (sparc64_floating_p (type)) 801130803Smarcel { 802130803Smarcel /* Floating arguments. */ 803130803Smarcel 804130803Smarcel if (len == 16) 805130803Smarcel { 806130803Smarcel /* The psABI says that "Each quad-precision parameter 807130803Smarcel value will be assigned to two extended words in the 808130803Smarcel parameter array. */ 809130803Smarcel num_elements += 2; 810130803Smarcel 811130803Smarcel /* The psABI says that "Long doubles must be 812130803Smarcel quad-aligned, and thus a hole might be introduced 813130803Smarcel into the parameter array to force alignment." Skip 814130803Smarcel an element if necessary. */ 815130803Smarcel if (num_elements % 2) 816130803Smarcel num_elements++; 817130803Smarcel } 818130803Smarcel else 819130803Smarcel num_elements++; 820130803Smarcel } 821130803Smarcel else 822130803Smarcel { 823130803Smarcel /* Integral and pointer arguments. */ 824130803Smarcel gdb_assert (sparc64_integral_or_pointer_p (type)); 825130803Smarcel 826130803Smarcel /* The psABI says that "Each argument value of integral type 827130803Smarcel smaller than an extended word will be widened by the 828130803Smarcel caller to an extended word according to the signed-ness 829130803Smarcel of the argument type." */ 830130803Smarcel if (len < 8) 831130803Smarcel args[i] = value_cast (builtin_type_int64, args[i]); 832130803Smarcel num_elements++; 833130803Smarcel } 834130803Smarcel } 835130803Smarcel 836130803Smarcel /* Allocate the "parameter array". */ 837130803Smarcel sp -= num_elements * 8; 838130803Smarcel 839130803Smarcel /* The psABI says that "Every stack frame must be 16-byte aligned." */ 840130803Smarcel sp &= ~0xf; 841130803Smarcel 842130803Smarcel /* Now we store the arguments in to the "paramater array". Some 843130803Smarcel Integer or Pointer arguments and Structure or Union arguments 844130803Smarcel will be passed in %o registers. Some Floating arguments and 845130803Smarcel floating members of structures are passed in floating-point 846130803Smarcel registers. However, for functions with variable arguments, 847130803Smarcel floating arguments are stored in an %0 register, and for 848130803Smarcel functions without a prototype floating arguments are stored in 849130803Smarcel both a floating-point and an %o registers, or a floating-point 850130803Smarcel register and memory. To simplify the logic here we always pass 851130803Smarcel arguments in memory, an %o register, and a floating-point 852130803Smarcel register if appropriate. This should be no problem since the 853130803Smarcel contents of any unused memory or registers in the "parameter 854130803Smarcel array" are undefined. */ 855130803Smarcel 856130803Smarcel if (struct_return) 857130803Smarcel { 858130803Smarcel regcache_cooked_write_unsigned (regcache, SPARC_O0_REGNUM, struct_addr); 859130803Smarcel element++; 860130803Smarcel } 861130803Smarcel 862130803Smarcel for (i = 0; i < nargs; i++) 863130803Smarcel { 864130803Smarcel char *valbuf = VALUE_CONTENTS (args[i]); 865130803Smarcel struct type *type = VALUE_TYPE (args[i]); 866130803Smarcel int len = TYPE_LENGTH (type); 867130803Smarcel int regnum = -1; 868130803Smarcel char buf[16]; 869130803Smarcel 870130803Smarcel if (sparc64_structure_or_union_p (type)) 871130803Smarcel { 872130803Smarcel /* Structure or Union arguments. */ 873130803Smarcel gdb_assert (len <= 16); 874130803Smarcel memset (buf, 0, sizeof (buf)); 875130803Smarcel valbuf = memcpy (buf, valbuf, len); 876130803Smarcel 877130803Smarcel if (element % 2 && sparc64_16_byte_align_p (type)) 878130803Smarcel element++; 879130803Smarcel 880130803Smarcel if (element < 6) 881130803Smarcel { 882130803Smarcel regnum = SPARC_O0_REGNUM + element; 883130803Smarcel if (len > 8 && element < 5) 884130803Smarcel regcache_cooked_write (regcache, regnum + 1, valbuf + 8); 885130803Smarcel } 886130803Smarcel 887130803Smarcel if (element < 16) 888130803Smarcel sparc64_store_floating_fields (regcache, type, valbuf, element, 0); 889130803Smarcel } 890130803Smarcel else if (sparc64_floating_p (type)) 891130803Smarcel { 892130803Smarcel /* Floating arguments. */ 893130803Smarcel if (len == 16) 894130803Smarcel { 895130803Smarcel if (element % 2) 896130803Smarcel element++; 897130803Smarcel if (element < 16) 898130803Smarcel regnum = SPARC64_Q0_REGNUM + element / 2; 899130803Smarcel } 900130803Smarcel else if (len == 8) 901130803Smarcel { 902130803Smarcel if (element < 16) 903130803Smarcel regnum = SPARC64_D0_REGNUM + element; 904130803Smarcel } 905130803Smarcel else 906130803Smarcel { 907130803Smarcel /* The psABI says "Each single-precision parameter value 908130803Smarcel will be assigned to one extended word in the 909130803Smarcel parameter array, and right-justified within that 910130803Smarcel word; the left half (even floatregister) is 911130803Smarcel undefined." Even though the psABI says that "the 912130803Smarcel left half is undefined", set it to zero here. */ 913130803Smarcel memset (buf, 0, 4); 914130803Smarcel memcpy (buf + 4, valbuf, 4); 915130803Smarcel valbuf = buf; 916130803Smarcel len = 8; 917130803Smarcel if (element < 16) 918130803Smarcel regnum = SPARC64_D0_REGNUM + element; 919130803Smarcel } 920130803Smarcel } 921130803Smarcel else 922130803Smarcel { 923130803Smarcel /* Integral and pointer arguments. */ 924130803Smarcel gdb_assert (len == 8); 925130803Smarcel if (element < 6) 926130803Smarcel regnum = SPARC_O0_REGNUM + element; 927130803Smarcel } 928130803Smarcel 929130803Smarcel if (regnum != -1) 930130803Smarcel { 931130803Smarcel regcache_cooked_write (regcache, regnum, valbuf); 932130803Smarcel 933130803Smarcel /* If we're storing the value in a floating-point register, 934130803Smarcel also store it in the corresponding %0 register(s). */ 935130803Smarcel if (regnum >= SPARC64_D0_REGNUM && regnum <= SPARC64_D10_REGNUM) 936130803Smarcel { 937130803Smarcel gdb_assert (element < 6); 938130803Smarcel regnum = SPARC_O0_REGNUM + element; 939130803Smarcel regcache_cooked_write (regcache, regnum, valbuf); 940130803Smarcel } 941130803Smarcel else if (regnum >= SPARC64_Q0_REGNUM && regnum <= SPARC64_Q8_REGNUM) 942130803Smarcel { 943130803Smarcel gdb_assert (element < 6); 944130803Smarcel regnum = SPARC_O0_REGNUM + element; 945130803Smarcel regcache_cooked_write (regcache, regnum, valbuf); 946130803Smarcel regcache_cooked_write (regcache, regnum + 1, valbuf); 947130803Smarcel } 948130803Smarcel } 949130803Smarcel 950130803Smarcel /* Always store the argument in memeory. */ 951130803Smarcel write_memory (sp + element * 8, valbuf, len); 952130803Smarcel element += ((len + 7) / 8); 953130803Smarcel } 954130803Smarcel 955130803Smarcel gdb_assert (element == num_elements); 956130803Smarcel 957130803Smarcel /* Take BIAS into account. */ 958130803Smarcel sp -= BIAS; 959130803Smarcel return sp; 960130803Smarcel} 961130803Smarcel 962130803Smarcelstatic CORE_ADDR 963130803Smarcelsparc64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr, 964130803Smarcel struct regcache *regcache, CORE_ADDR bp_addr, 965130803Smarcel int nargs, struct value **args, CORE_ADDR sp, 966130803Smarcel int struct_return, CORE_ADDR struct_addr) 967130803Smarcel{ 968130803Smarcel /* Set return address. */ 969130803Smarcel regcache_cooked_write_unsigned (regcache, SPARC_O7_REGNUM, bp_addr - 8); 970130803Smarcel 971130803Smarcel /* Set up function arguments. */ 972130803Smarcel sp = sparc64_store_arguments (regcache, nargs, args, sp, 973130803Smarcel struct_return, struct_addr); 974130803Smarcel 975130803Smarcel /* Allocate the register save area. */ 976130803Smarcel sp -= 16 * 8; 977130803Smarcel 978130803Smarcel /* Stack should be 16-byte aligned at this point. */ 979130803Smarcel gdb_assert ((sp + BIAS) % 16 == 0); 980130803Smarcel 981130803Smarcel /* Finally, update the stack pointer. */ 982130803Smarcel regcache_cooked_write_unsigned (regcache, SPARC_SP_REGNUM, sp); 983130803Smarcel 984130803Smarcel return sp; 985130803Smarcel} 986130803Smarcel 987130803Smarcel 988130803Smarcel/* Extract from an array REGBUF containing the (raw) register state, a 989130803Smarcel function return value of TYPE, and copy that into VALBUF. */ 990130803Smarcel 991130803Smarcelstatic void 992130803Smarcelsparc64_extract_return_value (struct type *type, struct regcache *regcache, 993130803Smarcel void *valbuf) 994130803Smarcel{ 995130803Smarcel int len = TYPE_LENGTH (type); 996130803Smarcel char buf[32]; 997130803Smarcel int i; 998130803Smarcel 999130803Smarcel if (sparc64_structure_or_union_p (type)) 1000130803Smarcel { 1001130803Smarcel /* Structure or Union return values. */ 1002130803Smarcel gdb_assert (len <= 32); 1003130803Smarcel 1004130803Smarcel for (i = 0; i < ((len + 7) / 8); i++) 1005130803Smarcel regcache_cooked_read (regcache, SPARC_O0_REGNUM + i, buf + i * 8); 1006130803Smarcel if (TYPE_CODE (type) != TYPE_CODE_UNION) 1007130803Smarcel sparc64_extract_floating_fields (regcache, type, buf, 0); 1008130803Smarcel memcpy (valbuf, buf, len); 1009130803Smarcel } 1010130803Smarcel else if (sparc64_floating_p (type)) 1011130803Smarcel { 1012130803Smarcel /* Floating return values. */ 1013130803Smarcel for (i = 0; i < len / 4; i++) 1014130803Smarcel regcache_cooked_read (regcache, SPARC_F0_REGNUM + i, buf + i * 4); 1015130803Smarcel memcpy (valbuf, buf, len); 1016130803Smarcel } 1017130803Smarcel else 1018130803Smarcel { 1019130803Smarcel /* Integral and pointer return values. */ 1020130803Smarcel gdb_assert (sparc64_integral_or_pointer_p (type)); 1021130803Smarcel 1022130803Smarcel /* Just stripping off any unused bytes should preserve the 1023130803Smarcel signed-ness just fine. */ 1024130803Smarcel regcache_cooked_read (regcache, SPARC_O0_REGNUM, buf); 1025130803Smarcel memcpy (valbuf, buf + 8 - len, len); 1026130803Smarcel } 1027130803Smarcel} 1028130803Smarcel 1029130803Smarcel/* Write into the appropriate registers a function return value stored 1030130803Smarcel in VALBUF of type TYPE. */ 1031130803Smarcel 1032130803Smarcelstatic void 1033130803Smarcelsparc64_store_return_value (struct type *type, struct regcache *regcache, 1034130803Smarcel const void *valbuf) 1035130803Smarcel{ 1036130803Smarcel int len = TYPE_LENGTH (type); 1037130803Smarcel char buf[16]; 1038130803Smarcel int i; 1039130803Smarcel 1040130803Smarcel if (sparc64_structure_or_union_p (type)) 1041130803Smarcel { 1042130803Smarcel /* Structure or Union return values. */ 1043130803Smarcel gdb_assert (len <= 32); 1044130803Smarcel 1045130803Smarcel /* Simplify matters by storing the complete value (including 1046130803Smarcel floating members) into %o0 and %o1. Floating members are 1047130803Smarcel also store in the appropriate floating-point registers. */ 1048130803Smarcel memset (buf, 0, sizeof (buf)); 1049130803Smarcel memcpy (buf, valbuf, len); 1050130803Smarcel for (i = 0; i < ((len + 7) / 8); i++) 1051130803Smarcel regcache_cooked_write (regcache, SPARC_O0_REGNUM + i, buf + i * 8); 1052130803Smarcel if (TYPE_CODE (type) != TYPE_CODE_UNION) 1053130803Smarcel sparc64_store_floating_fields (regcache, type, buf, 0, 0); 1054130803Smarcel } 1055130803Smarcel else if (sparc64_floating_p (type)) 1056130803Smarcel { 1057130803Smarcel /* Floating return values. */ 1058130803Smarcel memcpy (buf, valbuf, len); 1059130803Smarcel for (i = 0; i < len / 4; i++) 1060130803Smarcel regcache_cooked_write (regcache, SPARC_F0_REGNUM + i, buf + i * 4); 1061130803Smarcel } 1062130803Smarcel else 1063130803Smarcel { 1064130803Smarcel /* Integral and pointer return values. */ 1065130803Smarcel gdb_assert (sparc64_integral_or_pointer_p (type)); 1066130803Smarcel 1067130803Smarcel /* ??? Do we need to do any sign-extension here? */ 1068130803Smarcel memset (buf, 0, 8); 1069130803Smarcel memcpy (buf + 8 - len, valbuf, len); 1070130803Smarcel regcache_cooked_write (regcache, SPARC_O0_REGNUM, buf); 1071130803Smarcel } 1072130803Smarcel} 1073130803Smarcel 1074130803Smarcelstatic enum return_value_convention 1075130803Smarcelsparc64_return_value (struct gdbarch *gdbarch, struct type *type, 1076130803Smarcel struct regcache *regcache, void *readbuf, 1077130803Smarcel const void *writebuf) 1078130803Smarcel{ 1079130803Smarcel if (TYPE_LENGTH (type) > 32) 1080130803Smarcel return RETURN_VALUE_STRUCT_CONVENTION; 1081130803Smarcel 1082130803Smarcel if (readbuf) 1083130803Smarcel sparc64_extract_return_value (type, regcache, readbuf); 1084130803Smarcel if (writebuf) 1085130803Smarcel sparc64_store_return_value (type, regcache, writebuf); 1086130803Smarcel 1087130803Smarcel return RETURN_VALUE_REGISTER_CONVENTION; 1088130803Smarcel} 1089130803Smarcel 1090130803Smarcel 1091130803Smarcelvoid 1092130803Smarcelsparc64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 1093130803Smarcel{ 1094130803Smarcel struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 1095130803Smarcel 1096130803Smarcel tdep->pc_regnum = SPARC64_PC_REGNUM; 1097130803Smarcel tdep->npc_regnum = SPARC64_NPC_REGNUM; 1098130803Smarcel 1099130803Smarcel /* This is what all the fuss is about. */ 1100130803Smarcel set_gdbarch_long_bit (gdbarch, 64); 1101130803Smarcel set_gdbarch_long_long_bit (gdbarch, 64); 1102130803Smarcel set_gdbarch_ptr_bit (gdbarch, 64); 1103130803Smarcel 1104130803Smarcel set_gdbarch_num_regs (gdbarch, SPARC64_NUM_REGS); 1105130803Smarcel set_gdbarch_register_name (gdbarch, sparc64_register_name); 1106130803Smarcel set_gdbarch_register_type (gdbarch, sparc64_register_type); 1107130803Smarcel set_gdbarch_num_pseudo_regs (gdbarch, SPARC64_NUM_PSEUDO_REGS); 1108130803Smarcel set_gdbarch_pseudo_register_read (gdbarch, sparc64_pseudo_register_read); 1109130803Smarcel set_gdbarch_pseudo_register_write (gdbarch, sparc64_pseudo_register_write); 1110130803Smarcel 1111130803Smarcel /* Register numbers of various important registers. */ 1112130803Smarcel set_gdbarch_pc_regnum (gdbarch, SPARC64_PC_REGNUM); /* %pc */ 1113130803Smarcel 1114130803Smarcel /* Call dummy code. */ 1115130803Smarcel set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT); 1116130803Smarcel set_gdbarch_push_dummy_code (gdbarch, NULL); 1117130803Smarcel set_gdbarch_push_dummy_call (gdbarch, sparc64_push_dummy_call); 1118130803Smarcel 1119130803Smarcel set_gdbarch_return_value (gdbarch, sparc64_return_value); 1120130803Smarcel set_gdbarch_stabs_argument_has_addr 1121130803Smarcel (gdbarch, default_stabs_argument_has_addr); 1122130803Smarcel 1123130803Smarcel set_gdbarch_skip_prologue (gdbarch, sparc64_skip_prologue); 1124130803Smarcel 1125130803Smarcel frame_unwind_append_sniffer (gdbarch, sparc64_frame_sniffer); 1126130803Smarcel frame_base_set_default (gdbarch, &sparc64_frame_base); 1127130803Smarcel} 1128130803Smarcel 1129130803Smarcel 1130130803Smarcel/* Helper functions for dealing with register sets. */ 1131130803Smarcel 1132130803Smarcel#define TSTATE_CWP 0x000000000000001fULL 1133130803Smarcel#define TSTATE_ICC 0x0000000f00000000ULL 1134130803Smarcel#define TSTATE_XCC 0x000000f000000000ULL 1135130803Smarcel 1136130803Smarcel#define PSR_S 0x00000080 1137130803Smarcel#define PSR_ICC 0x00f00000 1138130803Smarcel#define PSR_VERS 0x0f000000 1139130803Smarcel#define PSR_IMPL 0xf0000000 1140130803Smarcel#define PSR_V8PLUS 0xff000000 1141130803Smarcel#define PSR_XCC 0x000f0000 1142130803Smarcel 1143130803Smarcelvoid 1144130803Smarcelsparc64_supply_gregset (const struct sparc_gregset *gregset, 1145130803Smarcel struct regcache *regcache, 1146130803Smarcel int regnum, const void *gregs) 1147130803Smarcel{ 1148130803Smarcel int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32); 1149130803Smarcel const char *regs = gregs; 1150130803Smarcel int i; 1151130803Smarcel 1152130803Smarcel if (sparc32) 1153130803Smarcel { 1154130803Smarcel if (regnum == SPARC32_PSR_REGNUM || regnum == -1) 1155130803Smarcel { 1156130803Smarcel int offset = gregset->r_tstate_offset; 1157130803Smarcel ULONGEST tstate, psr; 1158130803Smarcel char buf[4]; 1159130803Smarcel 1160130803Smarcel tstate = extract_unsigned_integer (regs + offset, 8); 1161130803Smarcel psr = ((tstate & TSTATE_CWP) | PSR_S | ((tstate & TSTATE_ICC) >> 12) 1162130803Smarcel | ((tstate & TSTATE_XCC) >> 20) | PSR_V8PLUS); 1163130803Smarcel store_unsigned_integer (buf, 4, psr); 1164130803Smarcel regcache_raw_supply (regcache, SPARC32_PSR_REGNUM, buf); 1165130803Smarcel } 1166130803Smarcel 1167130803Smarcel if (regnum == SPARC32_PC_REGNUM || regnum == -1) 1168130803Smarcel regcache_raw_supply (regcache, SPARC32_PC_REGNUM, 1169130803Smarcel regs + gregset->r_pc_offset + 4); 1170130803Smarcel 1171130803Smarcel if (regnum == SPARC32_NPC_REGNUM || regnum == -1) 1172130803Smarcel regcache_raw_supply (regcache, SPARC32_NPC_REGNUM, 1173130803Smarcel regs + gregset->r_npc_offset + 4); 1174130803Smarcel 1175130803Smarcel if (regnum == SPARC32_Y_REGNUM || regnum == -1) 1176130803Smarcel { 1177130803Smarcel int offset = gregset->r_y_offset + 8 - gregset->r_y_size; 1178130803Smarcel regcache_raw_supply (regcache, SPARC32_Y_REGNUM, regs + offset); 1179130803Smarcel } 1180130803Smarcel } 1181130803Smarcel else 1182130803Smarcel { 1183130803Smarcel if (regnum == SPARC64_STATE_REGNUM || regnum == -1) 1184130803Smarcel regcache_raw_supply (regcache, SPARC64_STATE_REGNUM, 1185130803Smarcel regs + gregset->r_tstate_offset); 1186130803Smarcel 1187130803Smarcel if (regnum == SPARC64_PC_REGNUM || regnum == -1) 1188130803Smarcel regcache_raw_supply (regcache, SPARC64_PC_REGNUM, 1189130803Smarcel regs + gregset->r_pc_offset); 1190130803Smarcel 1191130803Smarcel if (regnum == SPARC64_NPC_REGNUM || regnum == -1) 1192130803Smarcel regcache_raw_supply (regcache, SPARC64_NPC_REGNUM, 1193130803Smarcel regs + gregset->r_npc_offset); 1194130803Smarcel 1195130803Smarcel if (regnum == SPARC64_Y_REGNUM || regnum == -1) 1196130803Smarcel { 1197130803Smarcel char buf[8]; 1198130803Smarcel 1199130803Smarcel memset (buf, 0, 8); 1200130803Smarcel memcpy (buf + 8 - gregset->r_y_size, 1201130803Smarcel regs + gregset->r_y_offset, gregset->r_y_size); 1202130803Smarcel regcache_raw_supply (regcache, SPARC64_Y_REGNUM, buf); 1203130803Smarcel } 1204130803Smarcel 1205130803Smarcel if ((regnum == SPARC64_FPRS_REGNUM || regnum == -1) 1206130803Smarcel && gregset->r_fprs_offset != -1) 1207130803Smarcel regcache_raw_supply (regcache, SPARC64_FPRS_REGNUM, 1208130803Smarcel regs + gregset->r_fprs_offset); 1209130803Smarcel } 1210130803Smarcel 1211130803Smarcel if (regnum == SPARC_G0_REGNUM || regnum == -1) 1212130803Smarcel regcache_raw_supply (regcache, SPARC_G0_REGNUM, NULL); 1213130803Smarcel 1214130803Smarcel if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1) 1215130803Smarcel { 1216130803Smarcel int offset = gregset->r_g1_offset; 1217130803Smarcel 1218130803Smarcel if (sparc32) 1219130803Smarcel offset += 4; 1220130803Smarcel 1221130803Smarcel for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++) 1222130803Smarcel { 1223130803Smarcel if (regnum == i || regnum == -1) 1224130803Smarcel regcache_raw_supply (regcache, i, regs + offset); 1225130803Smarcel offset += 8; 1226130803Smarcel } 1227130803Smarcel } 1228130803Smarcel 1229130803Smarcel if ((regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM) || regnum == -1) 1230130803Smarcel { 1231130803Smarcel /* Not all of the register set variants include Locals and 1232130803Smarcel Inputs. For those that don't, we read them off the stack. */ 1233130803Smarcel if (gregset->r_l0_offset == -1) 1234130803Smarcel { 1235130803Smarcel ULONGEST sp; 1236130803Smarcel 1237130803Smarcel regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp); 1238130803Smarcel sparc_supply_rwindow (regcache, sp, regnum); 1239130803Smarcel } 1240130803Smarcel else 1241130803Smarcel { 1242130803Smarcel int offset = gregset->r_l0_offset; 1243130803Smarcel 1244130803Smarcel if (sparc32) 1245130803Smarcel offset += 4; 1246130803Smarcel 1247130803Smarcel for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++) 1248130803Smarcel { 1249130803Smarcel if (regnum == i || regnum == -1) 1250130803Smarcel regcache_raw_supply (regcache, i, regs + offset); 1251130803Smarcel offset += 8; 1252130803Smarcel } 1253130803Smarcel } 1254130803Smarcel } 1255130803Smarcel} 1256130803Smarcel 1257130803Smarcelvoid 1258130803Smarcelsparc64_collect_gregset (const struct sparc_gregset *gregset, 1259130803Smarcel const struct regcache *regcache, 1260130803Smarcel int regnum, void *gregs) 1261130803Smarcel{ 1262130803Smarcel int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32); 1263130803Smarcel char *regs = gregs; 1264130803Smarcel int i; 1265130803Smarcel 1266130803Smarcel if (sparc32) 1267130803Smarcel { 1268130803Smarcel if (regnum == SPARC32_PSR_REGNUM || regnum == -1) 1269130803Smarcel { 1270130803Smarcel int offset = gregset->r_tstate_offset; 1271130803Smarcel ULONGEST tstate, psr; 1272130803Smarcel char buf[8]; 1273130803Smarcel 1274130803Smarcel tstate = extract_unsigned_integer (regs + offset, 8); 1275130803Smarcel regcache_raw_collect (regcache, SPARC32_PSR_REGNUM, buf); 1276130803Smarcel psr = extract_unsigned_integer (buf, 4); 1277130803Smarcel tstate |= (psr & PSR_ICC) << 12; 1278130803Smarcel if ((psr & (PSR_VERS | PSR_IMPL)) == PSR_V8PLUS) 1279130803Smarcel tstate |= (psr & PSR_XCC) << 20; 1280130803Smarcel store_unsigned_integer (buf, 8, tstate); 1281130803Smarcel memcpy (regs + offset, buf, 8); 1282130803Smarcel } 1283130803Smarcel 1284130803Smarcel if (regnum == SPARC32_PC_REGNUM || regnum == -1) 1285130803Smarcel regcache_raw_collect (regcache, SPARC32_PC_REGNUM, 1286130803Smarcel regs + gregset->r_pc_offset + 4); 1287130803Smarcel 1288130803Smarcel if (regnum == SPARC32_NPC_REGNUM || regnum == -1) 1289130803Smarcel regcache_raw_collect (regcache, SPARC32_NPC_REGNUM, 1290130803Smarcel regs + gregset->r_npc_offset + 4); 1291130803Smarcel 1292130803Smarcel if (regnum == SPARC32_Y_REGNUM || regnum == -1) 1293130803Smarcel { 1294130803Smarcel int offset = gregset->r_y_offset + 8 - gregset->r_y_size; 1295130803Smarcel regcache_raw_collect (regcache, SPARC32_Y_REGNUM, regs + offset); 1296130803Smarcel } 1297130803Smarcel } 1298130803Smarcel else 1299130803Smarcel { 1300130803Smarcel if (regnum == SPARC64_STATE_REGNUM || regnum == -1) 1301130803Smarcel regcache_raw_collect (regcache, SPARC64_STATE_REGNUM, 1302130803Smarcel regs + gregset->r_tstate_offset); 1303130803Smarcel 1304130803Smarcel if (regnum == SPARC64_PC_REGNUM || regnum == -1) 1305130803Smarcel regcache_raw_collect (regcache, SPARC64_PC_REGNUM, 1306130803Smarcel regs + gregset->r_pc_offset); 1307130803Smarcel 1308130803Smarcel if (regnum == SPARC64_NPC_REGNUM || regnum == -1) 1309130803Smarcel regcache_raw_collect (regcache, SPARC64_NPC_REGNUM, 1310130803Smarcel regs + gregset->r_npc_offset); 1311130803Smarcel 1312130803Smarcel if (regnum == SPARC64_Y_REGNUM || regnum == -1) 1313130803Smarcel { 1314130803Smarcel char buf[8]; 1315130803Smarcel 1316130803Smarcel regcache_raw_collect (regcache, SPARC64_Y_REGNUM, buf); 1317130803Smarcel memcpy (regs + gregset->r_y_offset, 1318130803Smarcel buf + 8 - gregset->r_y_size, gregset->r_y_size); 1319130803Smarcel } 1320130803Smarcel 1321130803Smarcel if ((regnum == SPARC64_FPRS_REGNUM || regnum == -1) 1322130803Smarcel && gregset->r_fprs_offset != -1) 1323130803Smarcel regcache_raw_collect (regcache, SPARC64_FPRS_REGNUM, 1324130803Smarcel regs + gregset->r_fprs_offset); 1325130803Smarcel 1326130803Smarcel } 1327130803Smarcel 1328130803Smarcel if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1) 1329130803Smarcel { 1330130803Smarcel int offset = gregset->r_g1_offset; 1331130803Smarcel 1332130803Smarcel if (sparc32) 1333130803Smarcel offset += 4; 1334130803Smarcel 1335130803Smarcel /* %g0 is always zero. */ 1336130803Smarcel for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++) 1337130803Smarcel { 1338130803Smarcel if (regnum == i || regnum == -1) 1339130803Smarcel regcache_raw_collect (regcache, i, regs + offset); 1340130803Smarcel offset += 8; 1341130803Smarcel } 1342130803Smarcel } 1343130803Smarcel 1344130803Smarcel if ((regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM) || regnum == -1) 1345130803Smarcel { 1346130803Smarcel /* Not all of the register set variants include Locals and 1347130803Smarcel Inputs. For those that don't, we read them off the stack. */ 1348130803Smarcel if (gregset->r_l0_offset != -1) 1349130803Smarcel { 1350130803Smarcel int offset = gregset->r_l0_offset; 1351130803Smarcel 1352130803Smarcel if (sparc32) 1353130803Smarcel offset += 4; 1354130803Smarcel 1355130803Smarcel for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++) 1356130803Smarcel { 1357130803Smarcel if (regnum == i || regnum == -1) 1358130803Smarcel regcache_raw_collect (regcache, i, regs + offset); 1359130803Smarcel offset += 8; 1360130803Smarcel } 1361130803Smarcel } 1362130803Smarcel } 1363130803Smarcel} 1364130803Smarcel 1365130803Smarcelvoid 1366130803Smarcelsparc64_supply_fpregset (struct regcache *regcache, 1367130803Smarcel int regnum, const void *fpregs) 1368130803Smarcel{ 1369130803Smarcel int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32); 1370130803Smarcel const char *regs = fpregs; 1371130803Smarcel int i; 1372130803Smarcel 1373130803Smarcel for (i = 0; i < 32; i++) 1374130803Smarcel { 1375130803Smarcel if (regnum == (SPARC_F0_REGNUM + i) || regnum == -1) 1376130803Smarcel regcache_raw_supply (regcache, SPARC_F0_REGNUM + i, regs + (i * 4)); 1377130803Smarcel } 1378130803Smarcel 1379130803Smarcel if (sparc32) 1380130803Smarcel { 1381130803Smarcel if (regnum == SPARC32_FSR_REGNUM || regnum == -1) 1382130803Smarcel regcache_raw_supply (regcache, SPARC32_FSR_REGNUM, 1383130803Smarcel regs + (32 * 4) + (16 * 8) + 4); 1384130803Smarcel } 1385130803Smarcel else 1386130803Smarcel { 1387130803Smarcel for (i = 0; i < 16; i++) 1388130803Smarcel { 1389130803Smarcel if (regnum == (SPARC64_F32_REGNUM + i) || regnum == -1) 1390130803Smarcel regcache_raw_supply (regcache, SPARC64_F32_REGNUM + i, 1391130803Smarcel regs + (32 * 4) + (i * 8)); 1392130803Smarcel } 1393130803Smarcel 1394130803Smarcel if (regnum == SPARC64_FSR_REGNUM || regnum == -1) 1395130803Smarcel regcache_raw_supply (regcache, SPARC64_FSR_REGNUM, 1396130803Smarcel regs + (32 * 4) + (16 * 8)); 1397130803Smarcel } 1398130803Smarcel} 1399130803Smarcel 1400130803Smarcelvoid 1401130803Smarcelsparc64_collect_fpregset (const struct regcache *regcache, 1402130803Smarcel int regnum, void *fpregs) 1403130803Smarcel{ 1404130803Smarcel int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32); 1405130803Smarcel char *regs = fpregs; 1406130803Smarcel int i; 1407130803Smarcel 1408130803Smarcel for (i = 0; i < 32; i++) 1409130803Smarcel { 1410130803Smarcel if (regnum == (SPARC_F0_REGNUM + i) || regnum == -1) 1411130803Smarcel regcache_raw_collect (regcache, SPARC_F0_REGNUM + i, regs + (i * 4)); 1412130803Smarcel } 1413130803Smarcel 1414130803Smarcel if (sparc32) 1415130803Smarcel { 1416130803Smarcel if (regnum == SPARC32_FSR_REGNUM || regnum == -1) 1417130803Smarcel regcache_raw_collect (regcache, SPARC32_FSR_REGNUM, 1418130803Smarcel regs + (32 * 4) + (16 * 8) + 4); 1419130803Smarcel } 1420130803Smarcel else 1421130803Smarcel { 1422130803Smarcel for (i = 0; i < 16; i++) 1423130803Smarcel { 1424130803Smarcel if (regnum == (SPARC64_F32_REGNUM + i) || regnum == -1) 1425130803Smarcel regcache_raw_collect (regcache, SPARC64_F32_REGNUM + i, 1426130803Smarcel regs + (32 * 4) + (i * 8)); 1427130803Smarcel } 1428130803Smarcel 1429130803Smarcel if (regnum == SPARC64_FSR_REGNUM || regnum == -1) 1430130803Smarcel regcache_raw_collect (regcache, SPARC64_FSR_REGNUM, 1431130803Smarcel regs + (32 * 4) + (16 * 8)); 1432130803Smarcel } 1433130803Smarcel} 1434