/* SPU target-dependent code for GDB, the GNU debugger.
- Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
Based on a port by Sid Manning <sid@us.ibm.com>.
if (!tdep->spu_builtin_type_vec128)
{
+ const struct builtin_type *bt = builtin_type (gdbarch);
struct type *t;
- t = init_composite_type ("__spu_builtin_type_vec128", TYPE_CODE_UNION);
- append_composite_type_field (t, "uint128", builtin_type_int128);
+ t = arch_composite_type (gdbarch,
+ "__spu_builtin_type_vec128", TYPE_CODE_UNION);
+ append_composite_type_field (t, "uint128", bt->builtin_int128);
append_composite_type_field (t, "v2_int64",
- init_vector_type (builtin_type_int64, 2));
+ init_vector_type (bt->builtin_int64, 2));
append_composite_type_field (t, "v4_int32",
- init_vector_type (builtin_type_int32, 4));
+ init_vector_type (bt->builtin_int32, 4));
append_composite_type_field (t, "v8_int16",
- init_vector_type (builtin_type_int16, 8));
+ init_vector_type (bt->builtin_int16, 8));
append_composite_type_field (t, "v16_int8",
- init_vector_type (builtin_type_int8, 16));
+ init_vector_type (bt->builtin_int8, 16));
append_composite_type_field (t, "v2_double",
- init_vector_type (builtin_type_double, 2));
+ init_vector_type (bt->builtin_double, 2));
append_composite_type_field (t, "v4_float",
- init_vector_type (builtin_type_float, 4));
+ init_vector_type (bt->builtin_float, 4));
- TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
+ TYPE_VECTOR (t) = 1;
TYPE_NAME (t) = "spu_builtin_type_vec128";
tdep->spu_builtin_type_vec128 = t;
/* Registers. */
static const char *
-spu_register_name (int reg_nr)
+spu_register_name (struct gdbarch *gdbarch, int reg_nr)
{
static char *register_names[] =
{
switch (reg_nr)
{
case SPU_ID_REGNUM:
- return builtin_type_uint32;
+ return builtin_type (gdbarch)->builtin_uint32;
case SPU_PC_REGNUM:
- return builtin_type_void_func_ptr;
+ return builtin_type (gdbarch)->builtin_func_ptr;
case SPU_SP_REGNUM:
- return builtin_type_void_data_ptr;
+ return builtin_type (gdbarch)->builtin_data_ptr;
case SPU_FPSCR_REGNUM:
- return builtin_type_uint128;
+ return builtin_type (gdbarch)->builtin_uint128;
case SPU_SRR0_REGNUM:
- return builtin_type_uint32;
+ return builtin_type (gdbarch)->builtin_uint32;
case SPU_LSLR_REGNUM:
- return builtin_type_uint32;
+ return builtin_type (gdbarch)->builtin_uint32;
case SPU_DECR_REGNUM:
- return builtin_type_uint32;
+ return builtin_type (gdbarch)->builtin_uint32;
case SPU_DECR_STATUS_REGNUM:
- return builtin_type_uint32;
+ return builtin_type (gdbarch)->builtin_uint32;
default:
internal_error (__FILE__, __LINE__, "invalid regnum");
spu_pseudo_register_read_spu (struct regcache *regcache, const char *regname,
gdb_byte *buf)
{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte reg[32];
char annex[32];
ULONGEST id;
target_read (¤t_target, TARGET_OBJECT_SPU, annex,
reg, 0, sizeof reg);
- store_unsigned_integer (buf, 4, strtoulst (reg, NULL, 16));
+ store_unsigned_integer (buf, 4, byte_order, strtoulst (reg, NULL, 16));
}
static void
spu_pseudo_register_write_spu (struct regcache *regcache, const char *regname,
const gdb_byte *buf)
{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte reg[32];
char annex[32];
ULONGEST id;
regcache_raw_read_unsigned (regcache, SPU_ID_REGNUM, &id);
xsnprintf (annex, sizeof annex, "%d/%s", (int) id, regname);
xsnprintf (reg, sizeof reg, "0x%s",
- phex_nz (extract_unsigned_integer (buf, 4), 4));
+ phex_nz (extract_unsigned_integer (buf, 4, byte_order), 4));
target_write (¤t_target, TARGET_OBJECT_SPU, annex,
reg, 0, strlen (reg));
}
return default_register_reggroup_p (gdbarch, regnum, group);
}
+/* Address conversion. */
+
+static CORE_ADDR
+spu_pointer_to_address (struct gdbarch *gdbarch,
+ struct type *type, const gdb_byte *buf)
+{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ ULONGEST addr
+ = extract_unsigned_integer (buf, TYPE_LENGTH (type), byte_order);
+ ULONGEST lslr = SPU_LS_SIZE - 1; /* Hard-wired LS size. */
+
+ if (target_has_registers && target_has_stack && target_has_memory)
+ lslr = get_frame_register_unsigned (get_selected_frame (NULL),
+ SPU_LSLR_REGNUM);
+
+ return addr & lslr;
+}
+
+static CORE_ADDR
+spu_integer_to_address (struct gdbarch *gdbarch,
+ struct type *type, const gdb_byte *buf)
+{
+ ULONGEST addr = unpack_long (type, buf);
+ ULONGEST lslr = SPU_LS_SIZE - 1; /* Hard-wired LS size. */
+
+ if (target_has_registers && target_has_stack && target_has_memory)
+ lslr = get_frame_register_unsigned (get_selected_frame (NULL),
+ SPU_LSLR_REGNUM);
+
+ return addr & lslr;
+}
+
/* Decoding SPU instructions. */
};
static CORE_ADDR
-spu_analyze_prologue (CORE_ADDR start_pc, CORE_ADDR end_pc,
+spu_analyze_prologue (struct gdbarch *gdbarch,
+ CORE_ADDR start_pc, CORE_ADDR end_pc,
struct spu_prologue_data *data)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int found_sp = 0;
int found_fp = 0;
int found_lr = 0;
if (target_read_memory (pc, buf, 4))
break;
- insn = extract_unsigned_integer (buf, 4);
+ insn = extract_unsigned_integer (buf, 4, byte_order);
/* AI is the typical instruction to set up a stack frame.
It is also used to initialize the frame pointer. */
/* Return the first instruction after the prologue starting at PC. */
static CORE_ADDR
-spu_skip_prologue (CORE_ADDR pc)
+spu_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
struct spu_prologue_data data;
- return spu_analyze_prologue (pc, (CORE_ADDR)-1, &data);
+ return spu_analyze_prologue (gdbarch, pc, (CORE_ADDR)-1, &data);
}
/* Return the frame pointer in use at address PC. */
static void
-spu_virtual_frame_pointer (CORE_ADDR pc, int *reg, LONGEST *offset)
+spu_virtual_frame_pointer (struct gdbarch *gdbarch, CORE_ADDR pc,
+ int *reg, LONGEST *offset)
{
struct spu_prologue_data data;
- spu_analyze_prologue (pc, (CORE_ADDR)-1, &data);
+ spu_analyze_prologue (gdbarch, pc, (CORE_ADDR)-1, &data);
if (data.size != -1 && data.cfa_reg != -1)
{
static int
spu_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR scan_pc, func_start, func_end, epilogue_start, epilogue_end;
bfd_byte buf[4];
unsigned int insn;
{
if (target_read_memory (scan_pc, buf, 4))
return 0;
- insn = extract_unsigned_integer (buf, 4);
+ insn = extract_unsigned_integer (buf, 4, byte_order);
if (is_branch (insn, &immed, &ra))
{
{
if (target_read_memory (scan_pc, buf, 4))
return 0;
- insn = extract_unsigned_integer (buf, 4);
+ insn = extract_unsigned_integer (buf, 4, byte_order);
if (is_branch (insn, &immed, &ra))
return 0;
};
static struct spu_unwind_cache *
-spu_frame_unwind_cache (struct frame_info *next_frame,
+spu_frame_unwind_cache (struct frame_info *this_frame,
void **this_prologue_cache)
{
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
struct spu_unwind_cache *info;
struct spu_prologue_data data;
gdb_byte buf[16];
info = FRAME_OBSTACK_ZALLOC (struct spu_unwind_cache);
*this_prologue_cache = info;
- info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+ info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
info->frame_base = 0;
info->local_base = 0;
/* Find the start of the current function, and analyze its prologue. */
- info->func = frame_func_unwind (next_frame, NORMAL_FRAME);
+ info->func = get_frame_func (this_frame);
if (info->func == 0)
{
/* Fall back to using the current PC as frame ID. */
- info->func = frame_pc_unwind (next_frame);
+ info->func = get_frame_pc (this_frame);
data.size = -1;
}
else
- spu_analyze_prologue (info->func, frame_pc_unwind (next_frame), &data);
-
+ spu_analyze_prologue (gdbarch, info->func, get_frame_pc (this_frame),
+ &data);
/* If successful, use prologue analysis data. */
if (data.size != -1 && data.cfa_reg != -1)
int i;
/* Determine CFA via unwound CFA_REG plus CFA_OFFSET. */
- frame_unwind_register (next_frame, data.cfa_reg, buf);
- cfa = extract_unsigned_integer (buf, 4) + data.cfa_offset;
+ get_frame_register (this_frame, data.cfa_reg, buf);
+ cfa = extract_unsigned_integer (buf, 4, byte_order) + data.cfa_offset;
/* Call-saved register slots. */
for (i = 0; i < SPU_NUM_GPRS; i++)
/* Otherwise, fall back to reading the backchain link. */
else
{
- CORE_ADDR reg, backchain;
+ CORE_ADDR reg;
+ LONGEST backchain;
+ int status;
/* Get the backchain. */
- reg = frame_unwind_register_unsigned (next_frame, SPU_SP_REGNUM);
- backchain = read_memory_unsigned_integer (reg, 4);
+ reg = get_frame_register_unsigned (this_frame, SPU_SP_REGNUM);
+ status = safe_read_memory_integer (reg, 4, byte_order, &backchain);
/* A zero backchain terminates the frame chain. Also, sanity
check against the local store size limit. */
- if (backchain != 0 && backchain < SPU_LS_SIZE)
+ if (status && backchain > 0 && backchain < SPU_LS_SIZE)
{
/* Assume the link register is saved into its slot. */
if (backchain + 16 < SPU_LS_SIZE)
}
}
+ /* If we didn't find a frame, we cannot determine SP / return address. */
+ if (info->frame_base == 0)
+ return info;
+
/* The previous SP is equal to the CFA. */
trad_frame_set_value (info->saved_regs, SPU_SP_REGNUM, info->frame_base);
if (trad_frame_addr_p (info->saved_regs, SPU_LR_REGNUM))
target_read_memory (info->saved_regs[SPU_LR_REGNUM].addr, buf, 16);
else
- frame_unwind_register (next_frame, SPU_LR_REGNUM, buf);
+ get_frame_register (this_frame, SPU_LR_REGNUM, buf);
/* Normally, the return address is contained in the slot 0 of the
link register, and slots 1-3 are zero. For an overlay return,
slot 1 contains the partition number of the overlay section to
be returned to, and slot 2 contains the return address within
that section. Return the latter address in that case. */
- if (extract_unsigned_integer (buf + 8, 4) != 0)
+ if (extract_unsigned_integer (buf + 8, 4, byte_order) != 0)
trad_frame_set_value (info->saved_regs, SPU_PC_REGNUM,
- extract_unsigned_integer (buf + 8, 4));
+ extract_unsigned_integer (buf + 8, 4, byte_order));
else
trad_frame_set_value (info->saved_regs, SPU_PC_REGNUM,
- extract_unsigned_integer (buf, 4));
+ extract_unsigned_integer (buf, 4, byte_order));
return info;
}
static void
-spu_frame_this_id (struct frame_info *next_frame,
+spu_frame_this_id (struct frame_info *this_frame,
void **this_prologue_cache, struct frame_id *this_id)
{
struct spu_unwind_cache *info =
- spu_frame_unwind_cache (next_frame, this_prologue_cache);
+ spu_frame_unwind_cache (this_frame, this_prologue_cache);
if (info->frame_base == 0)
return;
*this_id = frame_id_build (info->frame_base, info->func);
}
-static void
-spu_frame_prev_register (struct frame_info *next_frame,
- void **this_prologue_cache,
- int regnum, int *optimizedp,
- enum lval_type *lvalp, CORE_ADDR * addrp,
- int *realnump, gdb_byte *bufferp)
+static struct value *
+spu_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache, int regnum)
{
struct spu_unwind_cache *info
- = spu_frame_unwind_cache (next_frame, this_prologue_cache);
+ = spu_frame_unwind_cache (this_frame, this_prologue_cache);
/* Special-case the stack pointer. */
if (regnum == SPU_RAW_SP_REGNUM)
regnum = SPU_SP_REGNUM;
- trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
- optimizedp, lvalp, addrp, realnump, bufferp);
+ return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
}
static const struct frame_unwind spu_frame_unwind = {
NORMAL_FRAME,
spu_frame_this_id,
- spu_frame_prev_register
+ spu_frame_prev_register,
+ NULL,
+ default_frame_sniffer
};
-const struct frame_unwind *
-spu_frame_sniffer (struct frame_info *next_frame)
-{
- return &spu_frame_unwind;
-}
-
static CORE_ADDR
-spu_frame_base_address (struct frame_info *next_frame, void **this_cache)
+spu_frame_base_address (struct frame_info *this_frame, void **this_cache)
{
struct spu_unwind_cache *info
- = spu_frame_unwind_cache (next_frame, this_cache);
+ = spu_frame_unwind_cache (this_frame, this_cache);
return info->local_base;
}
return sp & ~15;
}
+static CORE_ADDR
+spu_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp, CORE_ADDR funaddr,
+ struct value **args, int nargs, struct type *value_type,
+ CORE_ADDR *real_pc, CORE_ADDR *bp_addr,
+ struct regcache *regcache)
+{
+ /* Allocate space sufficient for a breakpoint, keeping the stack aligned. */
+ sp = (sp - 4) & ~15;
+ /* Store the address of that breakpoint */
+ *bp_addr = sp;
+ /* The call starts at the callee's entry point. */
+ *real_pc = funaddr;
+
+ return sp;
+}
+
static int
spu_scalar_value_p (struct type *type)
{
int nargs, struct value **args, CORE_ADDR sp,
int struct_return, CORE_ADDR struct_addr)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ CORE_ADDR sp_delta;
int i;
int regnum = SPU_ARG1_REGNUM;
int stack_arg = -1;
/* Set the return address. */
memset (buf, 0, sizeof buf);
- store_unsigned_integer (buf, 4, bp_addr);
+ store_unsigned_integer (buf, 4, byte_order, bp_addr);
regcache_cooked_write (regcache, SPU_LR_REGNUM, buf);
/* If STRUCT_RETURN is true, then the struct return address (in
if (struct_return)
{
memset (buf, 0, sizeof buf);
- store_unsigned_integer (buf, 4, struct_addr);
+ store_unsigned_integer (buf, 4, byte_order, struct_addr);
regcache_cooked_write (regcache, regnum++, buf);
}
regcache_cooked_read (regcache, SPU_RAW_SP_REGNUM, buf);
target_write_memory (sp, buf, 16);
- /* Finally, update the SP register. */
- regcache_cooked_write_unsigned (regcache, SPU_SP_REGNUM, sp);
+ /* Finally, update all slots of the SP register. */
+ sp_delta = sp - extract_unsigned_integer (buf, 4, byte_order);
+ for (i = 0; i < 4; i++)
+ {
+ CORE_ADDR sp_slot = extract_unsigned_integer (buf + 4*i, 4, byte_order);
+ store_unsigned_integer (buf + 4*i, 4, byte_order, sp_slot + sp_delta);
+ }
+ regcache_cooked_write (regcache, SPU_RAW_SP_REGNUM, buf);
return sp;
}
static struct frame_id
-spu_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+spu_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
{
- return frame_id_build (spu_unwind_sp (gdbarch, next_frame),
- spu_unwind_pc (gdbarch, next_frame));
+ CORE_ADDR pc = get_frame_register_unsigned (this_frame, SPU_PC_REGNUM);
+ CORE_ADDR sp = get_frame_register_unsigned (this_frame, SPU_SP_REGNUM);
+ return frame_id_build (sp, pc & -4);
}
/* Function return value access. */
static enum return_value_convention
-spu_return_value (struct gdbarch *gdbarch, struct type *type,
- struct regcache *regcache, gdb_byte *out, const gdb_byte *in)
+spu_return_value (struct gdbarch *gdbarch, struct type *func_type,
+ struct type *type, struct regcache *regcache,
+ gdb_byte *out, const gdb_byte *in)
{
enum return_value_convention rvc;
/* Breakpoints. */
static const gdb_byte *
-spu_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
+spu_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR * pcptr, int *lenptr)
{
static const gdb_byte breakpoint[] = { 0x00, 0x00, 0x3f, 0xff };
/* Software single-stepping support. */
-int
+static int
spu_software_single_step (struct frame_info *frame)
{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR pc, next_pc;
unsigned int insn;
int offset, reg;
if (target_read_memory (pc, buf, 4))
return 1;
- insn = extract_unsigned_integer (buf, 4);
+ insn = extract_unsigned_integer (buf, 4, byte_order);
/* Next sequential instruction is at PC + 4, except if the current
instruction is a PPE-assisted call, in which case it is at PC + 8.
else
next_pc = (pc + 4) & (SPU_LS_SIZE - 1);
- insert_single_step_breakpoint (next_pc);
+ insert_single_step_breakpoint (gdbarch, next_pc);
if (is_branch (insn, &offset, ®))
{
else if (reg != -1)
{
get_frame_register_bytes (frame, reg, 0, 4, buf);
- target += extract_unsigned_integer (buf, 4) & -4;
+ target += extract_unsigned_integer (buf, 4, byte_order) & -4;
}
target = target & (SPU_LS_SIZE - 1);
if (target != next_pc)
- insert_single_step_breakpoint (target);
+ insert_single_step_breakpoint (gdbarch, target);
}
return 1;
}
+
+/* Longjmp support. */
+
+static int
+spu_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ gdb_byte buf[4];
+ CORE_ADDR jb_addr;
+
+ /* Jump buffer is pointed to by the argument register $r3. */
+ get_frame_register_bytes (frame, SPU_ARG1_REGNUM, 0, 4, buf);
+ jb_addr = extract_unsigned_integer (buf, 4, byte_order);
+ if (target_read_memory (jb_addr, buf, 4))
+ return 0;
+
+ *pc = extract_unsigned_integer (buf, 4, byte_order);
+ return 1;
+}
+
+
/* Target overlays for the SPU overlay manager.
See the documentation of simple_overlay_update for how the
static struct spu_overlay_table *
spu_get_overlay_table (struct objfile *objfile)
{
+ enum bfd_endian byte_order = bfd_big_endian (objfile->obfd)?
+ BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
struct minimal_symbol *ovly_table_msym, *ovly_buf_table_msym;
CORE_ADDR ovly_table_base, ovly_buf_table_base;
unsigned ovly_table_size, ovly_buf_table_size;
for (i = 0; i < ovly_table_size / 16; i++)
{
- CORE_ADDR vma = extract_unsigned_integer (ovly_table + 16*i + 0, 4);
- CORE_ADDR size = extract_unsigned_integer (ovly_table + 16*i + 4, 4);
- CORE_ADDR pos = extract_unsigned_integer (ovly_table + 16*i + 8, 4);
- CORE_ADDR buf = extract_unsigned_integer (ovly_table + 16*i + 12, 4);
+ CORE_ADDR vma = extract_unsigned_integer (ovly_table + 16*i + 0,
+ 4, byte_order);
+ CORE_ADDR size = extract_unsigned_integer (ovly_table + 16*i + 4,
+ 4, byte_order);
+ CORE_ADDR pos = extract_unsigned_integer (ovly_table + 16*i + 8,
+ 4, byte_order);
+ CORE_ADDR buf = extract_unsigned_integer (ovly_table + 16*i + 12,
+ 4, byte_order);
if (buf == 0 || (buf - 1) * 4 >= ovly_buf_table_size)
continue;
static void
spu_overlay_update_osect (struct obj_section *osect)
{
+ enum bfd_endian byte_order = bfd_big_endian (osect->objfile->obfd)?
+ BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
struct spu_overlay_table *ovly_table;
CORE_ADDR val;
if (ovly_table->mapped_ptr == 0)
return;
- val = read_memory_unsigned_integer (ovly_table->mapped_ptr, 4);
+ val = read_memory_unsigned_integer (ovly_table->mapped_ptr, 4, byte_order);
osect->ovly_mapped = (val == ovly_table->mapped_val);
}
struct objfile *objfile;
ALL_OBJSECTIONS (objfile, osect)
- if (section_is_overlay (osect->the_bfd_section))
+ if (section_is_overlay (osect))
spu_overlay_update_osect (osect);
}
}
if (!objfile || objfile_data (objfile, spu_overlay_data) != NULL)
return;
+ /* Consider only SPU objfiles. */
+ if (bfd_get_arch (objfile->obfd) != bfd_arch_spu)
+ return;
+
/* Check if this objfile has overlays. */
ovly_table = spu_get_overlay_table (objfile);
if (!ovly_table)
LONGEST len;
int rc, id;
+ if (gdbarch_bfd_arch_info (get_frame_arch (frame))->arch != bfd_arch_spu)
+ error (_("\"info spu\" is only supported on the SPU architecture."));
+
id = get_frame_register_unsigned (frame, SPU_ID_REGNUM);
xsnprintf (annex, sizeof annex, "%d/event_status", id);
len = target_read (¤t_target, TARGET_OBJECT_SPU, annex,
- buf, 0, sizeof buf);
+ buf, 0, (sizeof (buf) - 1));
if (len <= 0)
error (_("Could not read event_status."));
+ buf[len] = '\0';
event_status = strtoulst (buf, NULL, 16);
xsnprintf (annex, sizeof annex, "%d/event_mask", id);
len = target_read (¤t_target, TARGET_OBJECT_SPU, annex,
- buf, 0, sizeof buf);
+ buf, 0, (sizeof (buf) - 1));
if (len <= 0)
error (_("Could not read event_mask."));
+ buf[len] = '\0';
event_mask = strtoulst (buf, NULL, 16);
chain = make_cleanup_ui_out_tuple_begin_end (uiout, "SPUInfoEvent");
info_spu_signal_command (char *args, int from_tty)
{
struct frame_info *frame = get_selected_frame (NULL);
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
ULONGEST signal1 = 0;
ULONGEST signal1_type = 0;
int signal1_pending = 0;
LONGEST len;
int rc, id;
+ if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu)
+ error (_("\"info spu\" is only supported on the SPU architecture."));
+
id = get_frame_register_unsigned (frame, SPU_ID_REGNUM);
xsnprintf (annex, sizeof annex, "%d/signal1", id);
error (_("Could not read signal1."));
else if (len == 4)
{
- signal1 = extract_unsigned_integer (buf, 4);
+ signal1 = extract_unsigned_integer (buf, 4, byte_order);
signal1_pending = 1;
}
xsnprintf (annex, sizeof annex, "%d/signal1_type", id);
len = target_read (¤t_target, TARGET_OBJECT_SPU, annex,
- buf, 0, sizeof buf);
+ buf, 0, (sizeof (buf) - 1));
if (len <= 0)
error (_("Could not read signal1_type."));
+ buf[len] = '\0';
signal1_type = strtoulst (buf, NULL, 16);
xsnprintf (annex, sizeof annex, "%d/signal2", id);
error (_("Could not read signal2."));
else if (len == 4)
{
- signal2 = extract_unsigned_integer (buf, 4);
+ signal2 = extract_unsigned_integer (buf, 4, byte_order);
signal2_pending = 1;
}
xsnprintf (annex, sizeof annex, "%d/signal2_type", id);
len = target_read (¤t_target, TARGET_OBJECT_SPU, annex,
- buf, 0, sizeof buf);
+ buf, 0, (sizeof (buf) - 1));
if (len <= 0)
error (_("Could not read signal2_type."));
+ buf[len] = '\0';
signal2_type = strtoulst (buf, NULL, 16);
chain = make_cleanup_ui_out_tuple_begin_end (uiout, "SPUInfoSignal");
printf_filtered (_("Signal 1 not pending "));
if (signal1_type)
- printf_filtered (_("(Type Overwrite)\n"));
- else
printf_filtered (_("(Type Or)\n"));
+ else
+ printf_filtered (_("(Type Overwrite)\n"));
if (signal2_pending)
printf_filtered (_("Signal 2 control word 0x%s "), phex (signal2, 4));
printf_filtered (_("Signal 2 not pending "));
if (signal2_type)
- printf_filtered (_("(Type Overwrite)\n"));
- else
printf_filtered (_("(Type Or)\n"));
+ else
+ printf_filtered (_("(Type Overwrite)\n"));
}
do_cleanups (chain);
}
static void
-info_spu_mailbox_list (gdb_byte *buf, int nr,
+info_spu_mailbox_list (gdb_byte *buf, int nr, enum bfd_endian byte_order,
const char *field, const char *msg)
{
struct cleanup *chain;
struct cleanup *val_chain;
ULONGEST val;
val_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "mbox");
- val = extract_unsigned_integer (buf + 4*i, 4);
+ val = extract_unsigned_integer (buf + 4*i, 4, byte_order);
ui_out_field_fmt (uiout, field, "0x%s", phex (val, 4));
do_cleanups (val_chain);
info_spu_mailbox_command (char *args, int from_tty)
{
struct frame_info *frame = get_selected_frame (NULL);
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
struct cleanup *chain;
char annex[32];
gdb_byte buf[1024];
LONGEST len;
int i, id;
+ if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu)
+ error (_("\"info spu\" is only supported on the SPU architecture."));
+
id = get_frame_register_unsigned (frame, SPU_ID_REGNUM);
chain = make_cleanup_ui_out_tuple_begin_end (uiout, "SPUInfoMailbox");
if (len < 0)
error (_("Could not read mbox_info."));
- info_spu_mailbox_list (buf, len / 4, "mbox", "SPU Outbound Mailbox");
+ info_spu_mailbox_list (buf, len / 4, byte_order,
+ "mbox", "SPU Outbound Mailbox");
xsnprintf (annex, sizeof annex, "%d/ibox_info", id);
len = target_read (¤t_target, TARGET_OBJECT_SPU, annex,
if (len < 0)
error (_("Could not read ibox_info."));
- info_spu_mailbox_list (buf, len / 4, "ibox", "SPU Outbound Interrupt Mailbox");
+ info_spu_mailbox_list (buf, len / 4, byte_order,
+ "ibox", "SPU Outbound Interrupt Mailbox");
xsnprintf (annex, sizeof annex, "%d/wbox_info", id);
len = target_read (¤t_target, TARGET_OBJECT_SPU, annex,
if (len < 0)
error (_("Could not read wbox_info."));
- info_spu_mailbox_list (buf, len / 4, "wbox", "SPU Inbound Mailbox");
+ info_spu_mailbox_list (buf, len / 4, byte_order,
+ "wbox", "SPU Inbound Mailbox");
do_cleanups (chain);
}
}
static void
-info_spu_dma_cmdlist (gdb_byte *buf, int nr)
+info_spu_dma_cmdlist (gdb_byte *buf, int nr, enum bfd_endian byte_order)
{
static char *spu_mfc_opcode[256] =
{
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
+ int *seq = alloca (nr * sizeof (int));
+ int done = 0;
struct cleanup *chain;
- int i;
+ int i, j;
+
+
+ /* Determine sequence in which to display (valid) entries. */
+ for (i = 0; i < nr; i++)
+ {
+ /* Search for the first valid entry all of whose
+ dependencies are met. */
+ for (j = 0; j < nr; j++)
+ {
+ ULONGEST mfc_cq_dw3;
+ ULONGEST dependencies;
+
+ if (done & (1 << (nr - 1 - j)))
+ continue;
+
+ mfc_cq_dw3
+ = extract_unsigned_integer (buf + 32*j + 24,8, byte_order);
+ if (!spu_mfc_get_bitfield (mfc_cq_dw3, 16, 16))
+ continue;
+
+ dependencies = spu_mfc_get_bitfield (mfc_cq_dw3, 0, nr - 1);
+ if ((dependencies & done) != dependencies)
+ continue;
+
+ seq[i] = j;
+ done |= 1 << (nr - 1 - j);
+ break;
+ }
+
+ if (j == nr)
+ break;
+ }
+
+ nr = i;
+
chain = make_cleanup_ui_out_table_begin_end (uiout, 10, nr, "dma_cmd");
ULONGEST mfc_cq_dw0;
ULONGEST mfc_cq_dw1;
ULONGEST mfc_cq_dw2;
- ULONGEST mfc_cq_dw3;
int mfc_cmd_opcode, mfc_cmd_tag, rclass_id, tclass_id;
int lsa, size, list_lsa, list_size, mfc_lsa, mfc_size;
ULONGEST mfc_ea;
/* Decode contents of MFC Command Queue Context Save/Restore Registers.
See "Cell Broadband Engine Registers V1.3", section 3.3.2.1. */
- mfc_cq_dw0 = extract_unsigned_integer (buf + 32*i, 8);
- mfc_cq_dw1 = extract_unsigned_integer (buf + 32*i + 8, 8);
- mfc_cq_dw2 = extract_unsigned_integer (buf + 32*i + 16, 8);
- mfc_cq_dw3 = extract_unsigned_integer (buf + 32*i + 24, 8);
+ mfc_cq_dw0
+ = extract_unsigned_integer (buf + 32*seq[i], 8, byte_order);
+ mfc_cq_dw1
+ = extract_unsigned_integer (buf + 32*seq[i] + 8, 8, byte_order);
+ mfc_cq_dw2
+ = extract_unsigned_integer (buf + 32*seq[i] + 16, 8, byte_order);
list_lsa = spu_mfc_get_bitfield (mfc_cq_dw0, 0, 14);
list_size = spu_mfc_get_bitfield (mfc_cq_dw0, 15, 26);
info_spu_dma_command (char *args, int from_tty)
{
struct frame_info *frame = get_selected_frame (NULL);
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
ULONGEST dma_info_type;
ULONGEST dma_info_mask;
ULONGEST dma_info_status;
LONGEST len;
int i, id;
+ if (gdbarch_bfd_arch_info (get_frame_arch (frame))->arch != bfd_arch_spu)
+ error (_("\"info spu\" is only supported on the SPU architecture."));
+
id = get_frame_register_unsigned (frame, SPU_ID_REGNUM);
xsnprintf (annex, sizeof annex, "%d/dma_info", id);
if (len <= 0)
error (_("Could not read dma_info."));
- dma_info_type = extract_unsigned_integer (buf, 8);
- dma_info_mask = extract_unsigned_integer (buf + 8, 8);
- dma_info_status = extract_unsigned_integer (buf + 16, 8);
- dma_info_stall_and_notify = extract_unsigned_integer (buf + 24, 8);
- dma_info_atomic_command_status = extract_unsigned_integer (buf + 32, 8);
+ dma_info_type
+ = extract_unsigned_integer (buf, 8, byte_order);
+ dma_info_mask
+ = extract_unsigned_integer (buf + 8, 8, byte_order);
+ dma_info_status
+ = extract_unsigned_integer (buf + 16, 8, byte_order);
+ dma_info_stall_and_notify
+ = extract_unsigned_integer (buf + 24, 8, byte_order);
+ dma_info_atomic_command_status
+ = extract_unsigned_integer (buf + 32, 8, byte_order);
chain = make_cleanup_ui_out_tuple_begin_end (uiout, "SPUInfoDMA");
}
else
{
- const char *query_msg;
+ const char *query_msg = _("no query pending");
- switch (dma_info_type)
- {
- case 0: query_msg = _("no query pending"); break;
- case 1: query_msg = _("'any' query pending"); break;
- case 2: query_msg = _("'all' query pending"); break;
- default: query_msg = _("undefined query type"); break;
- }
+ if (dma_info_type & 4)
+ switch (dma_info_type & 3)
+ {
+ case 1: query_msg = _("'any' query pending"); break;
+ case 2: query_msg = _("'all' query pending"); break;
+ default: query_msg = _("undefined query type"); break;
+ }
printf_filtered (_("Tag-Group Status 0x%s\n"),
phex (dma_info_status, 4));
printf_filtered ("\n");
}
- info_spu_dma_cmdlist (buf + 40, 16);
+ info_spu_dma_cmdlist (buf + 40, 16, byte_order);
do_cleanups (chain);
}
info_spu_proxydma_command (char *args, int from_tty)
{
struct frame_info *frame = get_selected_frame (NULL);
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
ULONGEST dma_info_type;
ULONGEST dma_info_mask;
ULONGEST dma_info_status;
LONGEST len;
int i, id;
+ if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu)
+ error (_("\"info spu\" is only supported on the SPU architecture."));
+
id = get_frame_register_unsigned (frame, SPU_ID_REGNUM);
xsnprintf (annex, sizeof annex, "%d/proxydma_info", id);
if (len <= 0)
error (_("Could not read proxydma_info."));
- dma_info_type = extract_unsigned_integer (buf, 8);
- dma_info_mask = extract_unsigned_integer (buf + 8, 8);
- dma_info_status = extract_unsigned_integer (buf + 16, 8);
+ dma_info_type = extract_unsigned_integer (buf, 8, byte_order);
+ dma_info_mask = extract_unsigned_integer (buf + 8, 8, byte_order);
+ dma_info_status = extract_unsigned_integer (buf + 16, 8, byte_order);
chain = make_cleanup_ui_out_tuple_begin_end (uiout, "SPUInfoProxyDMA");
{
const char *query_msg;
- switch (dma_info_type)
+ switch (dma_info_type & 3)
{
case 0: query_msg = _("no query pending"); break;
case 1: query_msg = _("'any' query pending"); break;
printf_filtered ("\n");
}
- info_spu_dma_cmdlist (buf + 24, 8);
+ info_spu_dma_cmdlist (buf + 24, 8, byte_order);
do_cleanups (chain);
}
set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
+ /* Address conversion. */
+ set_gdbarch_pointer_to_address (gdbarch, spu_pointer_to_address);
+ set_gdbarch_integer_to_address (gdbarch, spu_integer_to_address);
+
/* Inferior function calls. */
set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
set_gdbarch_frame_align (gdbarch, spu_frame_align);
+ set_gdbarch_frame_red_zone_size (gdbarch, 2000);
+ set_gdbarch_push_dummy_code (gdbarch, spu_push_dummy_code);
set_gdbarch_push_dummy_call (gdbarch, spu_push_dummy_call);
- set_gdbarch_unwind_dummy_id (gdbarch, spu_unwind_dummy_id);
+ set_gdbarch_dummy_id (gdbarch, spu_dummy_id);
set_gdbarch_return_value (gdbarch, spu_return_value);
/* Frame handling. */
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
- frame_unwind_append_sniffer (gdbarch, spu_frame_sniffer);
+ frame_unwind_append_unwinder (gdbarch, &spu_frame_unwind);
frame_base_set_default (gdbarch, &spu_frame_base);
set_gdbarch_unwind_pc (gdbarch, spu_unwind_pc);
set_gdbarch_unwind_sp (gdbarch, spu_unwind_sp);
set_gdbarch_breakpoint_from_pc (gdbarch, spu_breakpoint_from_pc);
set_gdbarch_cannot_step_breakpoint (gdbarch, 1);
set_gdbarch_software_single_step (gdbarch, spu_software_single_step);
+ set_gdbarch_get_longjmp_target (gdbarch, spu_get_longjmp_target);
/* Overlays. */
set_gdbarch_overlay_update (gdbarch, spu_overlay_update);
return gdbarch;
}
+/* Provide a prototype to silence -Wmissing-prototypes. */
+extern initialize_file_ftype _initialize_spu_tdep;
+
void
_initialize_spu_tdep (void)
{