gdb/sparc64-tdep.c - gdb
Global variables defined
Functions defined
Macros defined
Source code
- #include "defs.h"
- #include "arch-utils.h"
- #include "dwarf2-frame.h"
- #include "floatformat.h"
- #include "frame.h"
- #include "frame-base.h"
- #include "frame-unwind.h"
- #include "gdbcore.h"
- #include "gdbtypes.h"
- #include "inferior.h"
- #include "symtab.h"
- #include "objfiles.h"
- #include "osabi.h"
- #include "regcache.h"
- #include "target.h"
- #include "value.h"
- #include "sparc64-tdep.h"
- static int
- sparc64_integral_or_pointer_p (const struct type *type)
- {
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_INT:
- case TYPE_CODE_BOOL:
- case TYPE_CODE_CHAR:
- case TYPE_CODE_ENUM:
- case TYPE_CODE_RANGE:
- {
- int len = TYPE_LENGTH (type);
- gdb_assert (len == 1 || len == 2 || len == 4 || len == 8);
- }
- return 1;
- case TYPE_CODE_PTR:
- case TYPE_CODE_REF:
- {
- int len = TYPE_LENGTH (type);
- gdb_assert (len == 8);
- }
- return 1;
- default:
- break;
- }
- return 0;
- }
- static int
- sparc64_floating_p (const struct type *type)
- {
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_FLT:
- {
- int len = TYPE_LENGTH (type);
- gdb_assert (len == 4 || len == 8 || len == 16);
- }
- return 1;
- default:
- break;
- }
- return 0;
- }
- static int
- sparc64_complex_floating_p (const struct type *type)
- {
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_COMPLEX:
- {
- int len = TYPE_LENGTH (type);
- gdb_assert (len == 8 || len == 16 || len == 32);
- }
- return 1;
- default:
- break;
- }
- return 0;
- }
- static int
- sparc64_structure_or_union_p (const struct type *type)
- {
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_UNION:
- case TYPE_CODE_ARRAY:
- return 1;
- default:
- break;
- }
- return 0;
- }
- static struct type *
- sparc64_pstate_type (struct gdbarch *gdbarch)
- {
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- if (!tdep->sparc64_pstate_type)
- {
- struct type *type;
- type = arch_flags_type (gdbarch, "builtin_type_sparc64_pstate", 8);
- append_flags_type_flag (type, 0, "AG");
- append_flags_type_flag (type, 1, "IE");
- append_flags_type_flag (type, 2, "PRIV");
- append_flags_type_flag (type, 3, "AM");
- append_flags_type_flag (type, 4, "PEF");
- append_flags_type_flag (type, 5, "RED");
- append_flags_type_flag (type, 8, "TLE");
- append_flags_type_flag (type, 9, "CLE");
- append_flags_type_flag (type, 10, "PID0");
- append_flags_type_flag (type, 11, "PID1");
- tdep->sparc64_pstate_type = type;
- }
- return tdep->sparc64_pstate_type;
- }
- static struct type *
- sparc64_fsr_type (struct gdbarch *gdbarch)
- {
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- if (!tdep->sparc64_fsr_type)
- {
- struct type *type;
- type = arch_flags_type (gdbarch, "builtin_type_sparc64_fsr", 8);
- append_flags_type_flag (type, 0, "NXA");
- append_flags_type_flag (type, 1, "DZA");
- append_flags_type_flag (type, 2, "UFA");
- append_flags_type_flag (type, 3, "OFA");
- append_flags_type_flag (type, 4, "NVA");
- append_flags_type_flag (type, 5, "NXC");
- append_flags_type_flag (type, 6, "DZC");
- append_flags_type_flag (type, 7, "UFC");
- append_flags_type_flag (type, 8, "OFC");
- append_flags_type_flag (type, 9, "NVC");
- append_flags_type_flag (type, 22, "NS");
- append_flags_type_flag (type, 23, "NXM");
- append_flags_type_flag (type, 24, "DZM");
- append_flags_type_flag (type, 25, "UFM");
- append_flags_type_flag (type, 26, "OFM");
- append_flags_type_flag (type, 27, "NVM");
- tdep->sparc64_fsr_type = type;
- }
- return tdep->sparc64_fsr_type;
- }
- static struct type *
- sparc64_fprs_type (struct gdbarch *gdbarch)
- {
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- if (!tdep->sparc64_fprs_type)
- {
- struct type *type;
- type = arch_flags_type (gdbarch, "builtin_type_sparc64_fprs", 8);
- append_flags_type_flag (type, 0, "DL");
- append_flags_type_flag (type, 1, "DU");
- append_flags_type_flag (type, 2, "FEF");
- tdep->sparc64_fprs_type = type;
- }
- return tdep->sparc64_fprs_type;
- }
- static const char *sparc64_register_names[] =
- {
- "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
- "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
- "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
- "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7",
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
- "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
- "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
- "pc", "npc",
- FIXME
- "state",
- "fsr",
- "fprs",
- "y",
- };
- #define SPARC64_NUM_REGS ARRAY_SIZE (sparc64_register_names)
- static const char *sparc64_pseudo_register_names[] =
- {
- "cwp", "pstate", "asi", "ccr",
- "d0", "d2", "d4", "d6", "d8", "d10", "d12", "d14",
- "d16", "d18", "d20", "d22", "d24", "d26", "d28", "d30",
- "d32", "d34", "d36", "d38", "d40", "d42", "d44", "d46",
- "d48", "d50", "d52", "d54", "d56", "d58", "d60", "d62",
- "q0", "q4", "q8", "q12", "q16", "q20", "q24", "q28",
- "q32", "q36", "q40", "q44", "q48", "q52", "q56", "q60",
- };
- #define SPARC64_NUM_PSEUDO_REGS ARRAY_SIZE (sparc64_pseudo_register_names)
- static const char *
- sparc64_register_name (struct gdbarch *gdbarch, int regnum)
- {
- if (regnum >= 0 && regnum < SPARC64_NUM_REGS)
- return sparc64_register_names[regnum];
- if (regnum >= SPARC64_NUM_REGS
- && regnum < SPARC64_NUM_REGS + SPARC64_NUM_PSEUDO_REGS)
- return sparc64_pseudo_register_names[regnum - SPARC64_NUM_REGS];
- return NULL;
- }
- static struct type *
- sparc64_register_type (struct gdbarch *gdbarch, int regnum)
- {
-
- if (regnum == SPARC_SP_REGNUM || regnum == SPARC_FP_REGNUM)
- return builtin_type (gdbarch)->builtin_data_ptr;
- if (regnum >= SPARC_G0_REGNUM && regnum <= SPARC_I7_REGNUM)
- return builtin_type (gdbarch)->builtin_int64;
- if (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM)
- return builtin_type (gdbarch)->builtin_float;
- if (regnum >= SPARC64_F32_REGNUM && regnum <= SPARC64_F62_REGNUM)
- return builtin_type (gdbarch)->builtin_double;
- if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM)
- return builtin_type (gdbarch)->builtin_func_ptr;
-
- if (regnum == SPARC64_STATE_REGNUM)
- return builtin_type (gdbarch)->builtin_int64;
- if (regnum == SPARC64_FSR_REGNUM)
- return sparc64_fsr_type (gdbarch);
- if (regnum == SPARC64_FPRS_REGNUM)
- return sparc64_fprs_type (gdbarch);
-
- if (regnum == SPARC64_Y_REGNUM)
- return builtin_type (gdbarch)->builtin_int64;
-
- if (regnum == SPARC64_CWP_REGNUM)
- return builtin_type (gdbarch)->builtin_int64;
- if (regnum == SPARC64_PSTATE_REGNUM)
- return sparc64_pstate_type (gdbarch);
- if (regnum == SPARC64_ASI_REGNUM)
- return builtin_type (gdbarch)->builtin_int64;
- if (regnum == SPARC64_CCR_REGNUM)
- return builtin_type (gdbarch)->builtin_int64;
- if (regnum >= SPARC64_D0_REGNUM && regnum <= SPARC64_D62_REGNUM)
- return builtin_type (gdbarch)->builtin_double;
- if (regnum >= SPARC64_Q0_REGNUM && regnum <= SPARC64_Q60_REGNUM)
- return builtin_type (gdbarch)->builtin_long_double;
- internal_error (__FILE__, __LINE__, _("invalid regnum"));
- }
- static enum register_status
- sparc64_pseudo_register_read (struct gdbarch *gdbarch,
- struct regcache *regcache,
- int regnum, gdb_byte *buf)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- enum register_status status;
- gdb_assert (regnum >= SPARC64_NUM_REGS);
- if (regnum >= SPARC64_D0_REGNUM && regnum <= SPARC64_D30_REGNUM)
- {
- regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC64_D0_REGNUM);
- status = regcache_raw_read (regcache, regnum, buf);
- if (status == REG_VALID)
- status = regcache_raw_read (regcache, regnum + 1, buf + 4);
- return status;
- }
- else if (regnum >= SPARC64_D32_REGNUM && regnum <= SPARC64_D62_REGNUM)
- {
- regnum = SPARC64_F32_REGNUM + (regnum - SPARC64_D32_REGNUM);
- return regcache_raw_read (regcache, regnum, buf);
- }
- else if (regnum >= SPARC64_Q0_REGNUM && regnum <= SPARC64_Q28_REGNUM)
- {
- regnum = SPARC_F0_REGNUM + 4 * (regnum - SPARC64_Q0_REGNUM);
- status = regcache_raw_read (regcache, regnum, buf);
- if (status == REG_VALID)
- status = regcache_raw_read (regcache, regnum + 1, buf + 4);
- if (status == REG_VALID)
- status = regcache_raw_read (regcache, regnum + 2, buf + 8);
- if (status == REG_VALID)
- status = regcache_raw_read (regcache, regnum + 3, buf + 12);
- return status;
- }
- else if (regnum >= SPARC64_Q32_REGNUM && regnum <= SPARC64_Q60_REGNUM)
- {
- regnum = SPARC64_F32_REGNUM + 2 * (regnum - SPARC64_Q32_REGNUM);
- status = regcache_raw_read (regcache, regnum, buf);
- if (status == REG_VALID)
- status = regcache_raw_read (regcache, regnum + 1, buf + 8);
- return status;
- }
- else if (regnum == SPARC64_CWP_REGNUM
- || regnum == SPARC64_PSTATE_REGNUM
- || regnum == SPARC64_ASI_REGNUM
- || regnum == SPARC64_CCR_REGNUM)
- {
- ULONGEST state;
- status = regcache_raw_read_unsigned (regcache, SPARC64_STATE_REGNUM, &state);
- if (status != REG_VALID)
- return status;
- switch (regnum)
- {
- case SPARC64_CWP_REGNUM:
- state = (state >> 0) & ((1 << 5) - 1);
- break;
- case SPARC64_PSTATE_REGNUM:
- state = (state >> 8) & ((1 << 12) - 1);
- break;
- case SPARC64_ASI_REGNUM:
- state = (state >> 24) & ((1 << 8) - 1);
- break;
- case SPARC64_CCR_REGNUM:
- state = (state >> 32) & ((1 << 8) - 1);
- break;
- }
- store_unsigned_integer (buf, 8, byte_order, state);
- }
- return REG_VALID;
- }
- static void
- sparc64_pseudo_register_write (struct gdbarch *gdbarch,
- struct regcache *regcache,
- int regnum, const gdb_byte *buf)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- gdb_assert (regnum >= SPARC64_NUM_REGS);
- if (regnum >= SPARC64_D0_REGNUM && regnum <= SPARC64_D30_REGNUM)
- {
- regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC64_D0_REGNUM);
- regcache_raw_write (regcache, regnum, buf);
- regcache_raw_write (regcache, regnum + 1, buf + 4);
- }
- else if (regnum >= SPARC64_D32_REGNUM && regnum <= SPARC64_D62_REGNUM)
- {
- regnum = SPARC64_F32_REGNUM + (regnum - SPARC64_D32_REGNUM);
- regcache_raw_write (regcache, regnum, buf);
- }
- else if (regnum >= SPARC64_Q0_REGNUM && regnum <= SPARC64_Q28_REGNUM)
- {
- regnum = SPARC_F0_REGNUM + 4 * (regnum - SPARC64_Q0_REGNUM);
- regcache_raw_write (regcache, regnum, buf);
- regcache_raw_write (regcache, regnum + 1, buf + 4);
- regcache_raw_write (regcache, regnum + 2, buf + 8);
- regcache_raw_write (regcache, regnum + 3, buf + 12);
- }
- else if (regnum >= SPARC64_Q32_REGNUM && regnum <= SPARC64_Q60_REGNUM)
- {
- regnum = SPARC64_F32_REGNUM + 2 * (regnum - SPARC64_Q32_REGNUM);
- regcache_raw_write (regcache, regnum, buf);
- regcache_raw_write (regcache, regnum + 1, buf + 8);
- }
- else if (regnum == SPARC64_CWP_REGNUM
- || regnum == SPARC64_PSTATE_REGNUM
- || regnum == SPARC64_ASI_REGNUM
- || regnum == SPARC64_CCR_REGNUM)
- {
- ULONGEST state, bits;
- regcache_raw_read_unsigned (regcache, SPARC64_STATE_REGNUM, &state);
- bits = extract_unsigned_integer (buf, 8, byte_order);
- switch (regnum)
- {
- case SPARC64_CWP_REGNUM:
- state |= ((bits & ((1 << 5) - 1)) << 0);
- break;
- case SPARC64_PSTATE_REGNUM:
- state |= ((bits & ((1 << 12) - 1)) << 8);
- break;
- case SPARC64_ASI_REGNUM:
- state |= ((bits & ((1 << 8) - 1)) << 24);
- break;
- case SPARC64_CCR_REGNUM:
- state |= ((bits & ((1 << 8) - 1)) << 32);
- break;
- }
- regcache_raw_write_unsigned (regcache, SPARC64_STATE_REGNUM, state);
- }
- }
- static CORE_ADDR
- sparc64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
- {
- struct symtab_and_line sal;
- CORE_ADDR func_start, func_end;
- struct sparc_frame_cache cache;
-
- if (find_pc_partial_function (start_pc, NULL, &func_start, &func_end))
- {
- sal = find_pc_line (func_start, 0);
- if (sal.end < func_end
- && start_pc <= sal.end)
- return sal.end;
- }
- return sparc_analyze_prologue (gdbarch, start_pc, 0xffffffffffffffffULL,
- &cache);
- }
- static struct sparc_frame_cache *
- sparc64_frame_cache (struct frame_info *this_frame, void **this_cache)
- {
- return sparc_frame_cache (this_frame, this_cache);
- }
- static void
- sparc64_frame_this_id (struct frame_info *this_frame, void **this_cache,
- struct frame_id *this_id)
- {
- struct sparc_frame_cache *cache =
- sparc64_frame_cache (this_frame, this_cache);
-
- if (cache->base == 0)
- return;
- (*this_id) = frame_id_build (cache->base, cache->pc);
- }
- static struct value *
- sparc64_frame_prev_register (struct frame_info *this_frame, void **this_cache,
- int regnum)
- {
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- struct sparc_frame_cache *cache =
- sparc64_frame_cache (this_frame, this_cache);
- if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM)
- {
- CORE_ADDR pc = (regnum == SPARC64_NPC_REGNUM) ? 4 : 0;
- regnum =
- (cache->copied_regs_mask & 0x80) ? SPARC_I7_REGNUM : SPARC_O7_REGNUM;
- pc += get_frame_register_unsigned (this_frame, regnum) + 8;
- return frame_unwind_got_constant (this_frame, regnum, pc);
- }
-
- {
- ULONGEST wcookie = sparc_fetch_wcookie (gdbarch);
- if (wcookie != 0 && !cache->frameless_p && regnum == SPARC_I7_REGNUM)
- {
- CORE_ADDR addr = cache->base + (regnum - SPARC_L0_REGNUM) * 8;
- ULONGEST i7;
-
- i7 = get_frame_memory_unsigned (this_frame, addr, 8);
- return frame_unwind_got_constant (this_frame, regnum, i7 ^ wcookie);
- }
- }
-
- if (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM
- && (cache->saved_regs_mask & (1 << (regnum - SPARC_L0_REGNUM))))
- {
- CORE_ADDR addr = cache->base + (regnum - SPARC_L0_REGNUM) * 8;
- return frame_unwind_got_memory (this_frame, regnum, addr);
- }
-
- if (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM
- && (cache->copied_regs_mask & (1 << (regnum - SPARC_O0_REGNUM))))
- regnum += (SPARC_I0_REGNUM - SPARC_O0_REGNUM);
- return frame_unwind_got_register (this_frame, regnum, regnum);
- }
- static const struct frame_unwind sparc64_frame_unwind =
- {
- NORMAL_FRAME,
- default_frame_unwind_stop_reason,
- sparc64_frame_this_id,
- sparc64_frame_prev_register,
- NULL,
- default_frame_sniffer
- };
- static CORE_ADDR
- sparc64_frame_base_address (struct frame_info *this_frame, void **this_cache)
- {
- struct sparc_frame_cache *cache =
- sparc64_frame_cache (this_frame, this_cache);
- return cache->base;
- }
- static const struct frame_base sparc64_frame_base =
- {
- &sparc64_frame_unwind,
- sparc64_frame_base_address,
- sparc64_frame_base_address,
- sparc64_frame_base_address
- };
- static int
- sparc64_16_byte_align_p (struct type *type)
- {
- if (sparc64_floating_p (type) && TYPE_LENGTH (type) == 16)
- return 1;
- if (sparc64_structure_or_union_p (type))
- {
- int i;
- for (i = 0; i < TYPE_NFIELDS (type); i++)
- {
- struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i));
- if (sparc64_16_byte_align_p (subtype))
- return 1;
- }
- }
- return 0;
- }
- static void
- sparc64_store_floating_fields (struct regcache *regcache, struct type *type,
- const gdb_byte *valbuf, int element, int bitpos)
- {
- int len = TYPE_LENGTH (type);
- gdb_assert (element < 16);
- if (sparc64_floating_p (type)
- || (sparc64_complex_floating_p (type) && len <= 16))
- {
- int regnum;
- if (len == 16)
- {
- gdb_assert (bitpos == 0);
- gdb_assert ((element % 2) == 0);
- regnum = SPARC64_Q0_REGNUM + element / 2;
- regcache_cooked_write (regcache, regnum, valbuf);
- }
- else if (len == 8)
- {
- gdb_assert (bitpos == 0 || bitpos == 64);
- regnum = SPARC64_D0_REGNUM + element + bitpos / 64;
- regcache_cooked_write (regcache, regnum, valbuf + (bitpos / 8));
- }
- else
- {
- gdb_assert (len == 4);
- gdb_assert (bitpos % 32 == 0 && bitpos >= 0 && bitpos < 128);
- regnum = SPARC_F0_REGNUM + element * 2 + bitpos / 32;
- regcache_cooked_write (regcache, regnum, valbuf + (bitpos / 8));
- }
- }
- else if (sparc64_structure_or_union_p (type))
- {
- int i;
- for (i = 0; i < TYPE_NFIELDS (type); i++)
- {
- struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i));
- int subpos = bitpos + TYPE_FIELD_BITPOS (type, i);
- sparc64_store_floating_fields (regcache, subtype, valbuf,
- element, subpos);
- }
-
- if (TYPE_NFIELDS (type) == 1)
- {
- struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, 0));
- if (sparc64_floating_p (subtype) && TYPE_LENGTH (subtype) == 4)
- regcache_cooked_write (regcache, SPARC_F1_REGNUM, valbuf);
- }
- }
- }
- static void
- sparc64_extract_floating_fields (struct regcache *regcache, struct type *type,
- gdb_byte *valbuf, int bitpos)
- {
- if (sparc64_floating_p (type))
- {
- int len = TYPE_LENGTH (type);
- int regnum;
- if (len == 16)
- {
- gdb_assert (bitpos == 0 || bitpos == 128);
- regnum = SPARC64_Q0_REGNUM + bitpos / 128;
- regcache_cooked_read (regcache, regnum, valbuf + (bitpos / 8));
- }
- else if (len == 8)
- {
- gdb_assert (bitpos % 64 == 0 && bitpos >= 0 && bitpos < 256);
- regnum = SPARC64_D0_REGNUM + bitpos / 64;
- regcache_cooked_read (regcache, regnum, valbuf + (bitpos / 8));
- }
- else
- {
- gdb_assert (len == 4);
- gdb_assert (bitpos % 32 == 0 && bitpos >= 0 && bitpos < 256);
- regnum = SPARC_F0_REGNUM + bitpos / 32;
- regcache_cooked_read (regcache, regnum, valbuf + (bitpos / 8));
- }
- }
- else if (sparc64_structure_or_union_p (type))
- {
- int i;
- for (i = 0; i < TYPE_NFIELDS (type); i++)
- {
- struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i));
- int subpos = bitpos + TYPE_FIELD_BITPOS (type, i);
- sparc64_extract_floating_fields (regcache, subtype, valbuf, subpos);
- }
- }
- }
- static CORE_ADDR
- sparc64_store_arguments (struct regcache *regcache, int nargs,
- struct value **args, CORE_ADDR sp,
- int struct_return, CORE_ADDR struct_addr)
- {
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
-
- int num_elements = 0;
- int element = 0;
- int i;
-
- sp += BIAS;
-
- if (struct_return)
- num_elements++;
- for (i = 0; i < nargs; i++)
- {
- struct type *type = value_type (args[i]);
- int len = TYPE_LENGTH (type);
- if (sparc64_structure_or_union_p (type)
- || (sparc64_complex_floating_p (type) && len == 32))
- {
-
- if (len <= 16)
- {
- if (num_elements % 2 && sparc64_16_byte_align_p (type))
- num_elements++;
- num_elements += ((len + 7) / 8);
- }
- else
- {
-
- sp -= len;
-
- sp &= ~0xf;
- write_memory (sp, value_contents (args[i]), len);
- args[i] = value_from_pointer (lookup_pointer_type (type), sp);
- num_elements++;
- }
- }
- else if (sparc64_floating_p (type) || sparc64_complex_floating_p (type))
- {
-
- if (len == 16)
- {
-
- num_elements += 2;
-
- if ((num_elements % 2) && sparc64_16_byte_align_p (type))
- num_elements++;
- }
- else
- num_elements++;
- }
- else
- {
-
- gdb_assert (sparc64_integral_or_pointer_p (type));
-
- if (len < 8)
- args[i] = value_cast (builtin_type (gdbarch)->builtin_int64,
- args[i]);
- num_elements++;
- }
- }
-
- sp -= num_elements * 8;
-
- sp &= ~0xf;
-
- if (struct_return)
- {
- regcache_cooked_write_unsigned (regcache, SPARC_O0_REGNUM, struct_addr);
- element++;
- }
- for (i = 0; i < nargs; i++)
- {
- const gdb_byte *valbuf = value_contents (args[i]);
- struct type *type = value_type (args[i]);
- int len = TYPE_LENGTH (type);
- int regnum = -1;
- gdb_byte buf[16];
- if (sparc64_structure_or_union_p (type)
- || (sparc64_complex_floating_p (type) && len == 32))
- {
-
- gdb_assert (len <= 16);
- memset (buf, 0, sizeof (buf));
- valbuf = memcpy (buf, valbuf, len);
- if (element % 2 && sparc64_16_byte_align_p (type))
- element++;
- if (element < 6)
- {
- regnum = SPARC_O0_REGNUM + element;
- if (len > 8 && element < 5)
- regcache_cooked_write (regcache, regnum + 1, valbuf + 8);
- }
- if (element < 16)
- sparc64_store_floating_fields (regcache, type, valbuf, element, 0);
- }
- else if (sparc64_complex_floating_p (type))
- {
-
- if (element < 16)
- {
- regnum = SPARC64_D0_REGNUM + element;
- if (len == 16)
- {
- if (regnum < SPARC64_D30_REGNUM)
- regcache_cooked_write (regcache, regnum + 1, valbuf + 8);
- if (regnum < SPARC64_D10_REGNUM)
- regcache_cooked_write (regcache,
- SPARC_O0_REGNUM + element + 1,
- valbuf + 8);
- }
- }
- }
- else if (sparc64_floating_p (type))
- {
-
- if (len == 16)
- {
- if (element % 2)
- element++;
- if (element < 16)
- regnum = SPARC64_Q0_REGNUM + element / 2;
- }
- else if (len == 8)
- {
- if (element < 16)
- regnum = SPARC64_D0_REGNUM + element;
- }
- else if (len == 4)
- {
-
- memset (buf, 0, 4);
- memcpy (buf + 4, valbuf, 4);
- valbuf = buf;
- len = 8;
- if (element < 16)
- regnum = SPARC64_D0_REGNUM + element;
- }
- }
- else
- {
-
- gdb_assert (len == 8);
- if (element < 6)
- regnum = SPARC_O0_REGNUM + element;
- }
- if (regnum != -1)
- {
- regcache_cooked_write (regcache, regnum, valbuf);
-
- if (regnum >= SPARC64_D0_REGNUM && regnum <= SPARC64_D10_REGNUM)
- {
- gdb_assert (element < 6);
- regnum = SPARC_O0_REGNUM + element;
- regcache_cooked_write (regcache, regnum, valbuf);
- }
- else if (regnum >= SPARC64_Q0_REGNUM && regnum <= SPARC64_Q8_REGNUM)
- {
- gdb_assert (element < 5);
- regnum = SPARC_O0_REGNUM + element;
- regcache_cooked_write (regcache, regnum, valbuf);
- regcache_cooked_write (regcache, regnum + 1, valbuf + 8);
- }
- }
-
- write_memory (sp + element * 8, valbuf, len);
- element += ((len + 7) / 8);
- }
- gdb_assert (element == num_elements);
-
- sp -= BIAS;
- return sp;
- }
- static CORE_ADDR
- sparc64_frame_align (struct gdbarch *gdbarch, CORE_ADDR address)
- {
-
- return address & ~0xf;
- }
- static CORE_ADDR
- sparc64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
- struct regcache *regcache, CORE_ADDR bp_addr,
- int nargs, struct value **args, CORE_ADDR sp,
- int struct_return, CORE_ADDR struct_addr)
- {
-
- regcache_cooked_write_unsigned (regcache, SPARC_O7_REGNUM, bp_addr - 8);
-
- sp = sparc64_store_arguments (regcache, nargs, args, sp,
- struct_return, struct_addr);
-
- sp -= 16 * 8;
-
- gdb_assert ((sp + BIAS) % 16 == 0);
-
- regcache_cooked_write_unsigned (regcache, SPARC_SP_REGNUM, sp);
- return sp + BIAS;
- }
- static void
- sparc64_extract_return_value (struct type *type, struct regcache *regcache,
- gdb_byte *valbuf)
- {
- int len = TYPE_LENGTH (type);
- gdb_byte buf[32];
- int i;
- if (sparc64_structure_or_union_p (type))
- {
-
- gdb_assert (len <= 32);
- for (i = 0; i < ((len + 7) / 8); i++)
- regcache_cooked_read (regcache, SPARC_O0_REGNUM + i, buf + i * 8);
- if (TYPE_CODE (type) != TYPE_CODE_UNION)
- sparc64_extract_floating_fields (regcache, type, buf, 0);
- memcpy (valbuf, buf, len);
- }
- else if (sparc64_floating_p (type) || sparc64_complex_floating_p (type))
- {
-
- for (i = 0; i < len / 4; i++)
- regcache_cooked_read (regcache, SPARC_F0_REGNUM + i, buf + i * 4);
- memcpy (valbuf, buf, len);
- }
- else if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
- {
-
- gdb_assert (len <= 32);
- for (i = 0; i < ((len + 7) / 8); i++)
- regcache_cooked_read (regcache, SPARC_O0_REGNUM + i, buf + i * 8);
- memcpy (valbuf, buf, len);
- }
- else
- {
-
- gdb_assert (sparc64_integral_or_pointer_p (type));
-
- regcache_cooked_read (regcache, SPARC_O0_REGNUM, buf);
- memcpy (valbuf, buf + 8 - len, len);
- }
- }
- static void
- sparc64_store_return_value (struct type *type, struct regcache *regcache,
- const gdb_byte *valbuf)
- {
- int len = TYPE_LENGTH (type);
- gdb_byte buf[16];
- int i;
- if (sparc64_structure_or_union_p (type))
- {
-
- gdb_assert (len <= 32);
-
- memset (buf, 0, sizeof (buf));
- memcpy (buf, valbuf, len);
- for (i = 0; i < ((len + 7) / 8); i++)
- regcache_cooked_write (regcache, SPARC_O0_REGNUM + i, buf + i * 8);
- if (TYPE_CODE (type) != TYPE_CODE_UNION)
- sparc64_store_floating_fields (regcache, type, buf, 0, 0);
- }
- else if (sparc64_floating_p (type) || sparc64_complex_floating_p (type))
- {
-
- memcpy (buf, valbuf, len);
- for (i = 0; i < len / 4; i++)
- regcache_cooked_write (regcache, SPARC_F0_REGNUM + i, buf + i * 4);
- }
- else if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
- {
-
- gdb_assert (len <= 32);
- memset (buf, 0, sizeof (buf));
- memcpy (buf, valbuf, len);
- for (i = 0; i < ((len + 7) / 8); i++)
- regcache_cooked_write (regcache, SPARC_O0_REGNUM + i, buf + i * 8);
- }
- else
- {
-
- gdb_assert (sparc64_integral_or_pointer_p (type));
-
- memset (buf, 0, 8);
- memcpy (buf + 8 - len, valbuf, len);
- regcache_cooked_write (regcache, SPARC_O0_REGNUM, buf);
- }
- }
- static enum return_value_convention
- sparc64_return_value (struct gdbarch *gdbarch, struct value *function,
- struct type *type, struct regcache *regcache,
- gdb_byte *readbuf, const gdb_byte *writebuf)
- {
- if (TYPE_LENGTH (type) > 32)
- return RETURN_VALUE_STRUCT_CONVENTION;
- if (readbuf)
- sparc64_extract_return_value (type, regcache, readbuf);
- if (writebuf)
- sparc64_store_return_value (type, regcache, writebuf);
- return RETURN_VALUE_REGISTER_CONVENTION;
- }
- static void
- sparc64_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
- struct dwarf2_frame_state_reg *reg,
- struct frame_info *this_frame)
- {
- switch (regnum)
- {
- case SPARC_G0_REGNUM:
-
- reg->how = DWARF2_FRAME_REG_SAME_VALUE;
- break;
- case SPARC_SP_REGNUM:
- reg->how = DWARF2_FRAME_REG_CFA;
- break;
- case SPARC64_PC_REGNUM:
- reg->how = DWARF2_FRAME_REG_RA_OFFSET;
- reg->loc.offset = 8;
- break;
- case SPARC64_NPC_REGNUM:
- reg->how = DWARF2_FRAME_REG_RA_OFFSET;
- reg->loc.offset = 12;
- break;
- }
- }
- void
- sparc64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
- {
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- tdep->pc_regnum = SPARC64_PC_REGNUM;
- tdep->npc_regnum = SPARC64_NPC_REGNUM;
-
- set_gdbarch_long_bit (gdbarch, 64);
- set_gdbarch_long_long_bit (gdbarch, 64);
- set_gdbarch_ptr_bit (gdbarch, 64);
- set_gdbarch_num_regs (gdbarch, SPARC64_NUM_REGS);
- set_gdbarch_register_name (gdbarch, sparc64_register_name);
- set_gdbarch_register_type (gdbarch, sparc64_register_type);
- set_gdbarch_num_pseudo_regs (gdbarch, SPARC64_NUM_PSEUDO_REGS);
- set_gdbarch_pseudo_register_read (gdbarch, sparc64_pseudo_register_read);
- set_gdbarch_pseudo_register_write (gdbarch, sparc64_pseudo_register_write);
-
- set_gdbarch_pc_regnum (gdbarch, SPARC64_PC_REGNUM);
-
- set_gdbarch_frame_align (gdbarch, sparc64_frame_align);
- set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
- set_gdbarch_push_dummy_code (gdbarch, NULL);
- set_gdbarch_push_dummy_call (gdbarch, sparc64_push_dummy_call);
- set_gdbarch_return_value (gdbarch, sparc64_return_value);
- set_gdbarch_stabs_argument_has_addr
- (gdbarch, default_stabs_argument_has_addr);
- set_gdbarch_skip_prologue (gdbarch, sparc64_skip_prologue);
- set_gdbarch_in_function_epilogue_p (gdbarch, sparc_in_function_epilogue_p);
-
- dwarf2_frame_set_init_reg (gdbarch, sparc64_dwarf2_frame_init_reg);
- FIXME
- frame_unwind_append_unwinder (gdbarch, &sparc64_frame_unwind);
- frame_base_set_default (gdbarch, &sparc64_frame_base);
- }
- #define TSTATE_CWP 0x000000000000001fULL
- #define TSTATE_ICC 0x0000000f00000000ULL
- #define TSTATE_XCC 0x000000f000000000ULL
- #define PSR_S 0x00000080
- #define PSR_ICC 0x00f00000
- #define PSR_VERS 0x0f000000
- #define PSR_IMPL 0xf0000000
- #define PSR_V8PLUS 0xff000000
- #define PSR_XCC 0x000f0000
- void
- sparc64_supply_gregset (const struct sparc_gregmap *gregmap,
- struct regcache *regcache,
- int regnum, const void *gregs)
- {
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- int sparc32 = (gdbarch_ptr_bit (gdbarch) == 32);
- const gdb_byte *regs = gregs;
- gdb_byte zero[8] = { 0 };
- int i;
- if (sparc32)
- {
- if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
- {
- int offset = gregmap->r_tstate_offset;
- ULONGEST tstate, psr;
- gdb_byte buf[4];
- tstate = extract_unsigned_integer (regs + offset, 8, byte_order);
- psr = ((tstate & TSTATE_CWP) | PSR_S | ((tstate & TSTATE_ICC) >> 12)
- | ((tstate & TSTATE_XCC) >> 20) | PSR_V8PLUS);
- store_unsigned_integer (buf, 4, byte_order, psr);
- regcache_raw_supply (regcache, SPARC32_PSR_REGNUM, buf);
- }
- if (regnum == SPARC32_PC_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, SPARC32_PC_REGNUM,
- regs + gregmap->r_pc_offset + 4);
- if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, SPARC32_NPC_REGNUM,
- regs + gregmap->r_npc_offset + 4);
- if (regnum == SPARC32_Y_REGNUM || regnum == -1)
- {
- int offset = gregmap->r_y_offset + 8 - gregmap->r_y_size;
- regcache_raw_supply (regcache, SPARC32_Y_REGNUM, regs + offset);
- }
- }
- else
- {
- if (regnum == SPARC64_STATE_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, SPARC64_STATE_REGNUM,
- regs + gregmap->r_tstate_offset);
- if (regnum == SPARC64_PC_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, SPARC64_PC_REGNUM,
- regs + gregmap->r_pc_offset);
- if (regnum == SPARC64_NPC_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, SPARC64_NPC_REGNUM,
- regs + gregmap->r_npc_offset);
- if (regnum == SPARC64_Y_REGNUM || regnum == -1)
- {
- gdb_byte buf[8];
- memset (buf, 0, 8);
- memcpy (buf + 8 - gregmap->r_y_size,
- regs + gregmap->r_y_offset, gregmap->r_y_size);
- regcache_raw_supply (regcache, SPARC64_Y_REGNUM, buf);
- }
- if ((regnum == SPARC64_FPRS_REGNUM || regnum == -1)
- && gregmap->r_fprs_offset != -1)
- regcache_raw_supply (regcache, SPARC64_FPRS_REGNUM,
- regs + gregmap->r_fprs_offset);
- }
- if (regnum == SPARC_G0_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, SPARC_G0_REGNUM, &zero);
- if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
- {
- int offset = gregmap->r_g1_offset;
- if (sparc32)
- offset += 4;
- for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
- {
- if (regnum == i || regnum == -1)
- regcache_raw_supply (regcache, i, regs + offset);
- offset += 8;
- }
- }
- if ((regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM) || regnum == -1)
- {
-
- if (gregmap->r_l0_offset == -1)
- {
- ULONGEST sp;
- regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
- sparc_supply_rwindow (regcache, sp, regnum);
- }
- else
- {
- int offset = gregmap->r_l0_offset;
- if (sparc32)
- offset += 4;
- for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
- {
- if (regnum == i || regnum == -1)
- regcache_raw_supply (regcache, i, regs + offset);
- offset += 8;
- }
- }
- }
- }
- void
- sparc64_collect_gregset (const struct sparc_gregmap *gregmap,
- const struct regcache *regcache,
- int regnum, void *gregs)
- {
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- int sparc32 = (gdbarch_ptr_bit (gdbarch) == 32);
- gdb_byte *regs = gregs;
- int i;
- if (sparc32)
- {
- if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
- {
- int offset = gregmap->r_tstate_offset;
- ULONGEST tstate, psr;
- gdb_byte buf[8];
- tstate = extract_unsigned_integer (regs + offset, 8, byte_order);
- regcache_raw_collect (regcache, SPARC32_PSR_REGNUM, buf);
- psr = extract_unsigned_integer (buf, 4, byte_order);
- tstate |= (psr & PSR_ICC) << 12;
- if ((psr & (PSR_VERS | PSR_IMPL)) == PSR_V8PLUS)
- tstate |= (psr & PSR_XCC) << 20;
- store_unsigned_integer (buf, 8, byte_order, tstate);
- memcpy (regs + offset, buf, 8);
- }
- if (regnum == SPARC32_PC_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, SPARC32_PC_REGNUM,
- regs + gregmap->r_pc_offset + 4);
- if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, SPARC32_NPC_REGNUM,
- regs + gregmap->r_npc_offset + 4);
- if (regnum == SPARC32_Y_REGNUM || regnum == -1)
- {
- int offset = gregmap->r_y_offset + 8 - gregmap->r_y_size;
- regcache_raw_collect (regcache, SPARC32_Y_REGNUM, regs + offset);
- }
- }
- else
- {
- if (regnum == SPARC64_STATE_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, SPARC64_STATE_REGNUM,
- regs + gregmap->r_tstate_offset);
- if (regnum == SPARC64_PC_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, SPARC64_PC_REGNUM,
- regs + gregmap->r_pc_offset);
- if (regnum == SPARC64_NPC_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, SPARC64_NPC_REGNUM,
- regs + gregmap->r_npc_offset);
- if (regnum == SPARC64_Y_REGNUM || regnum == -1)
- {
- gdb_byte buf[8];
- regcache_raw_collect (regcache, SPARC64_Y_REGNUM, buf);
- memcpy (regs + gregmap->r_y_offset,
- buf + 8 - gregmap->r_y_size, gregmap->r_y_size);
- }
- if ((regnum == SPARC64_FPRS_REGNUM || regnum == -1)
- && gregmap->r_fprs_offset != -1)
- regcache_raw_collect (regcache, SPARC64_FPRS_REGNUM,
- regs + gregmap->r_fprs_offset);
- }
- if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
- {
- int offset = gregmap->r_g1_offset;
- if (sparc32)
- offset += 4;
-
- for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
- {
- if (regnum == i || regnum == -1)
- regcache_raw_collect (regcache, i, regs + offset);
- offset += 8;
- }
- }
- if ((regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM) || regnum == -1)
- {
-
- if (gregmap->r_l0_offset != -1)
- {
- int offset = gregmap->r_l0_offset;
- if (sparc32)
- offset += 4;
- for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
- {
- if (regnum == i || regnum == -1)
- regcache_raw_collect (regcache, i, regs + offset);
- offset += 8;
- }
- }
- }
- }
- void
- sparc64_supply_fpregset (const struct sparc_fpregmap *fpregmap,
- struct regcache *regcache,
- int regnum, const void *fpregs)
- {
- int sparc32 = (gdbarch_ptr_bit (get_regcache_arch (regcache)) == 32);
- const gdb_byte *regs = fpregs;
- int i;
- for (i = 0; i < 32; i++)
- {
- if (regnum == (SPARC_F0_REGNUM + i) || regnum == -1)
- regcache_raw_supply (regcache, SPARC_F0_REGNUM + i,
- regs + fpregmap->r_f0_offset + (i * 4));
- }
- if (sparc32)
- {
- if (regnum == SPARC32_FSR_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, SPARC32_FSR_REGNUM,
- regs + fpregmap->r_fsr_offset);
- }
- else
- {
- for (i = 0; i < 16; i++)
- {
- if (regnum == (SPARC64_F32_REGNUM + i) || regnum == -1)
- regcache_raw_supply (regcache, SPARC64_F32_REGNUM + i,
- (regs + fpregmap->r_f0_offset
- + (32 * 4) + (i * 8)));
- }
- if (regnum == SPARC64_FSR_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, SPARC64_FSR_REGNUM,
- regs + fpregmap->r_fsr_offset);
- }
- }
- void
- sparc64_collect_fpregset (const struct sparc_fpregmap *fpregmap,
- const struct regcache *regcache,
- int regnum, void *fpregs)
- {
- int sparc32 = (gdbarch_ptr_bit (get_regcache_arch (regcache)) == 32);
- gdb_byte *regs = fpregs;
- int i;
- for (i = 0; i < 32; i++)
- {
- if (regnum == (SPARC_F0_REGNUM + i) || regnum == -1)
- regcache_raw_collect (regcache, SPARC_F0_REGNUM + i,
- regs + fpregmap->r_f0_offset + (i * 4));
- }
- if (sparc32)
- {
- if (regnum == SPARC32_FSR_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, SPARC32_FSR_REGNUM,
- regs + fpregmap->r_fsr_offset);
- }
- else
- {
- for (i = 0; i < 16; i++)
- {
- if (regnum == (SPARC64_F32_REGNUM + i) || regnum == -1)
- regcache_raw_collect (regcache, SPARC64_F32_REGNUM + i,
- (regs + fpregmap->r_f0_offset
- + (32 * 4) + (i * 8)));
- }
- if (regnum == SPARC64_FSR_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, SPARC64_FSR_REGNUM,
- regs + fpregmap->r_fsr_offset);
- }
- }
- const struct sparc_fpregmap sparc64_bsd_fpregmap =
- {
- 0 * 8,
- 32 * 8,
- };