diff options
-rw-r--r-- | gdb/ChangeLog | 26 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/doc/gdb.texinfo | 38 | ||||
-rw-r--r-- | gdb/spu-linux-nat.c | 3 | ||||
-rw-r--r-- | gdb/spu-tdep.c | 619 | ||||
-rw-r--r-- | gdb/spu-tdep.h | 9 | ||||
-rw-r--r-- | gdb/target.h | 2 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/spu-info.c | 236 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/spu-info.exp | 243 |
10 files changed, 1185 insertions, 3 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ddd98ad..0d16e47 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,31 @@ 2007-06-12 Ulrich Weigand <uweigand@de.ibm.com> + * target.h (enum target_object): Add TARGET_OBJECT_SPU. + * spu-linux-nat.c (spu_xfer_partial): Handle TARGET_OBJECT_SPU. + + * spu-tdep.h (SPU_NUM_PSEUDO_REGS): Add 5 pseudo registers. + (enum spu_regnum): Add SPU_FPSCR_REGNUM, SPU_SRR0_REGNUM, + SPU_LSLR_REGNUM, SPU_DECR_REGNUM, SPU_DECR_STATUS_REGNUM. + * spu-tdep.c (infospucmdlist): New variable. + (spu_register_name): Handle additional pseudo registers. + (spu_register_type): Likewise. + (spu_pseudo_register_read): Likewise. + (spu_pseudo_register_write): Likewise. + (spu_pseudo_register_read_spu): New function. + (spu_pseudo_register_write_spu): Likewise. + (info_spu_event_command): New function. + (info_spu_signal_command): Likewise. + (info_spu_mailbox_list): Likewise. + (info_spu_mailbox_command): Likewise. + (spu_mfc_get_bitfield): Likewise. + (info_spu_dma_cmdlist): Likewise. + (info_spu_dma_command): Likewise. + (info_spu_proxydma_command): Likewise. + (info_spu_command): Likewise. + (_initialize_spu_tdep): Install "info spu" commands. + +2007-06-12 Ulrich Weigand <uweigand@de.ibm.com> + * spu-linux-nat.c (spu_proc_xfer_spu): Do not return failure when accessing non-seekable spufs files. diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 38c3b85..7a73f3b 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,9 @@ +2007-06-12 Ulrich Weigand <uweigand@de.ibm.com> + Markus Deuling <deuling@de.ibm.com> + + * gdb.texinfo (Architectures): Add new SPU section to document + Cell Broadband Engine SPU architecture specific commands. + 2007-06-09 Vladimir Prus <vladimir@codesourcery.com> * gdb.texinfo (GDB/MI Variable Objects): Editorial diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 7c04b2b..0641386 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -15100,6 +15100,7 @@ all uses of @value{GDBN} with the architecture, both native and cross. * Alpha:: * MIPS:: * HPPA:: HP PA architecture +* SPU:: Cell Broadband Engine SPU architecture @end menu @node i386 @@ -15280,6 +15281,43 @@ given @var{address}. @end table +@node SPU +@subsection Cell Broadband Engine SPU architecture +@cindex Cell Broadband Engine +@cindex SPU + +When @value{GDBN} is debugging the Cell Broadband Engine SPU architecture, +it provides the following special commands: + +@table @code +@item info spu event +@kindex info spu +Display SPU event facility status. Shows current event mask +and pending event status. + +@item info spu signal +Display SPU signal notification facility status. Shows pending +signal-control word and signal notification mode of both signal +notification channels. + +@item info spu mailbox +Display SPU mailbox facility status. Shows all pending entries, +in order of processing, in each of the SPU Write Outbound, +SPU Write Outbound Interrupt, and SPU Read Inbound mailboxes. + +@item info spu dma +Display MFC DMA status. Shows all pending commands in the MFC +DMA queue. For each entry, opcode, tag, class IDs, effective +and local store addresses and transfer size are shown. + +@item info spu proxydma +Display MFC Proxy-DMA status. Shows all pending commands in the MFC +Proxy-DMA queue. For each entry, opcode, tag, class IDs, effective +and local store addresses and transfer size are shown. + +@end table + + @node Controlling GDB @chapter Controlling @value{GDBN} diff --git a/gdb/spu-linux-nat.c b/gdb/spu-linux-nat.c index 21a7c5d..3a03f22 100644 --- a/gdb/spu-linux-nat.c +++ b/gdb/spu-linux-nat.c @@ -535,6 +535,9 @@ spu_xfer_partial (struct target_ops *ops, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, LONGEST len) { + if (object == TARGET_OBJECT_SPU) + return spu_proc_xfer_spu (annex, readbuf, writebuf, offset, len); + if (object == TARGET_OBJECT_MEMORY) { int fd; diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c index 305201a..8872084 100644 --- a/gdb/spu-tdep.c +++ b/gdb/spu-tdep.c @@ -49,6 +49,9 @@ /* SPU-specific vector type. */ struct type *spu_builtin_type_vec128; +/* The list of available "info spu " commands. */ +static struct cmd_list_element *infospucmdlist = NULL; + /* Registers. */ static const char * @@ -72,7 +75,7 @@ spu_register_name (int reg_nr) "r104", "r105", "r106", "r107", "r108", "r109", "r110", "r111", "r112", "r113", "r114", "r115", "r116", "r117", "r118", "r119", "r120", "r121", "r122", "r123", "r124", "r125", "r126", "r127", - "id", "pc", "sp" + "id", "pc", "sp", "fpscr", "srr0", "lslr", "decr", "decr_status" }; if (reg_nr < 0) @@ -100,6 +103,21 @@ spu_register_type (struct gdbarch *gdbarch, int reg_nr) case SPU_SP_REGNUM: return builtin_type_void_data_ptr; + case SPU_FPSCR_REGNUM: + return builtin_type_uint128; + + case SPU_SRR0_REGNUM: + return builtin_type_uint32; + + case SPU_LSLR_REGNUM: + return builtin_type_uint32; + + case SPU_DECR_REGNUM: + return builtin_type_uint32; + + case SPU_DECR_STATUS_REGNUM: + return builtin_type_uint32; + default: internal_error (__FILE__, __LINE__, "invalid regnum"); } @@ -108,10 +126,29 @@ spu_register_type (struct gdbarch *gdbarch, int reg_nr) /* Pseudo registers for preferred slots - stack pointer. */ static void +spu_pseudo_register_read_spu (struct regcache *regcache, const char *regname, + gdb_byte *buf) +{ + 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); + memset (reg, 0, sizeof reg); + target_read (¤t_target, TARGET_OBJECT_SPU, annex, + reg, 0, sizeof reg); + + store_unsigned_integer (buf, 4, strtoulst (reg, NULL, 16)); +} + +static void spu_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int regnum, gdb_byte *buf) { gdb_byte reg[16]; + char annex[32]; + ULONGEST id; switch (regnum) { @@ -120,16 +157,56 @@ spu_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, memcpy (buf, reg, 4); break; + case SPU_FPSCR_REGNUM: + regcache_raw_read_unsigned (regcache, SPU_ID_REGNUM, &id); + xsnprintf (annex, sizeof annex, "%d/fpcr", (int) id); + target_read (¤t_target, TARGET_OBJECT_SPU, annex, buf, 0, 16); + break; + + case SPU_SRR0_REGNUM: + spu_pseudo_register_read_spu (regcache, "srr0", buf); + break; + + case SPU_LSLR_REGNUM: + spu_pseudo_register_read_spu (regcache, "lslr", buf); + break; + + case SPU_DECR_REGNUM: + spu_pseudo_register_read_spu (regcache, "decr", buf); + break; + + case SPU_DECR_STATUS_REGNUM: + spu_pseudo_register_read_spu (regcache, "decr_status", buf); + break; + default: internal_error (__FILE__, __LINE__, _("invalid regnum")); } } static void +spu_pseudo_register_write_spu (struct regcache *regcache, const char *regname, + const gdb_byte *buf) +{ + 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)); + target_write (¤t_target, TARGET_OBJECT_SPU, annex, + reg, 0, strlen (reg)); +} + +static void spu_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, int regnum, const gdb_byte *buf) { gdb_byte reg[16]; + char annex[32]; + ULONGEST id; switch (regnum) { @@ -139,6 +216,28 @@ spu_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, regcache_raw_write (regcache, SPU_RAW_SP_REGNUM, reg); break; + case SPU_FPSCR_REGNUM: + regcache_raw_read_unsigned (regcache, SPU_ID_REGNUM, &id); + xsnprintf (annex, sizeof annex, "%d/fpcr", (int) id); + target_write (¤t_target, TARGET_OBJECT_SPU, annex, buf, 0, 16); + break; + + case SPU_SRR0_REGNUM: + spu_pseudo_register_write_spu (regcache, "srr0", buf); + break; + + case SPU_LSLR_REGNUM: + spu_pseudo_register_write_spu (regcache, "lslr", buf); + break; + + case SPU_DECR_REGNUM: + spu_pseudo_register_write_spu (regcache, "decr", buf); + break; + + case SPU_DECR_STATUS_REGNUM: + spu_pseudo_register_write_spu (regcache, "decr_status", buf); + break; + default: internal_error (__FILE__, __LINE__, _("invalid regnum")); } @@ -1318,6 +1417,502 @@ spu_overlay_new_objfile (struct objfile *objfile) } +/* "info spu" commands. */ + +static void +info_spu_event_command (char *args, int from_tty) +{ + struct frame_info *frame = get_selected_frame (NULL); + ULONGEST event_status = 0; + ULONGEST event_mask = 0; + struct cleanup *chain; + gdb_byte buf[100]; + char annex[32]; + LONGEST len; + int rc, id; + + 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); + if (len <= 0) + error (_("Could not read event_status.")); + 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); + if (len <= 0) + error (_("Could not read event_mask.")); + event_mask = strtoulst (buf, NULL, 16); + + chain = make_cleanup_ui_out_tuple_begin_end (uiout, "SPUInfoEvent"); + + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_fmt (uiout, "event_status", + "0x%s", phex_nz (event_status, 4)); + ui_out_field_fmt (uiout, "event_mask", + "0x%s", phex_nz (event_mask, 4)); + } + else + { + printf_filtered (_("Event Status 0x%s\n"), phex (event_status, 4)); + printf_filtered (_("Event Mask 0x%s\n"), phex (event_mask, 4)); + } + + do_cleanups (chain); +} + +static void +info_spu_signal_command (char *args, int from_tty) +{ + struct frame_info *frame = get_selected_frame (NULL); + ULONGEST signal1 = 0; + ULONGEST signal1_type = 0; + int signal1_pending = 0; + ULONGEST signal2 = 0; + ULONGEST signal2_type = 0; + int signal2_pending = 0; + struct cleanup *chain; + char annex[32]; + gdb_byte buf[100]; + LONGEST len; + int rc, id; + + id = get_frame_register_unsigned (frame, SPU_ID_REGNUM); + + xsnprintf (annex, sizeof annex, "%d/signal1", id); + len = target_read (¤t_target, TARGET_OBJECT_SPU, annex, buf, 0, 4); + if (len < 0) + error (_("Could not read signal1.")); + else if (len == 4) + { + signal1 = extract_unsigned_integer (buf, 4); + signal1_pending = 1; + } + + xsnprintf (annex, sizeof annex, "%d/signal1_type", id); + len = target_read (¤t_target, TARGET_OBJECT_SPU, annex, + buf, 0, sizeof buf); + if (len <= 0) + error (_("Could not read signal1_type.")); + signal1_type = strtoulst (buf, NULL, 16); + + xsnprintf (annex, sizeof annex, "%d/signal2", id); + len = target_read (¤t_target, TARGET_OBJECT_SPU, annex, buf, 0, 4); + if (len < 0) + error (_("Could not read signal2.")); + else if (len == 4) + { + signal2 = extract_unsigned_integer (buf, 4); + signal2_pending = 1; + } + + xsnprintf (annex, sizeof annex, "%d/signal2_type", id); + len = target_read (¤t_target, TARGET_OBJECT_SPU, annex, + buf, 0, sizeof buf); + if (len <= 0) + error (_("Could not read signal2_type.")); + signal2_type = strtoulst (buf, NULL, 16); + + chain = make_cleanup_ui_out_tuple_begin_end (uiout, "SPUInfoSignal"); + + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_int (uiout, "signal1_pending", signal1_pending); + ui_out_field_fmt (uiout, "signal1", "0x%s", phex_nz (signal1, 4)); + ui_out_field_int (uiout, "signal1_type", signal1_type); + ui_out_field_int (uiout, "signal2_pending", signal2_pending); + ui_out_field_fmt (uiout, "signal2", "0x%s", phex_nz (signal2, 4)); + ui_out_field_int (uiout, "signal2_type", signal2_type); + } + else + { + if (signal1_pending) + printf_filtered (_("Signal 1 control word 0x%s "), phex (signal1, 4)); + else + printf_filtered (_("Signal 1 not pending ")); + + if (signal1_type) + printf_filtered (_("(Type Overwrite)\n")); + else + printf_filtered (_("(Type Or)\n")); + + if (signal2_pending) + printf_filtered (_("Signal 2 control word 0x%s "), phex (signal2, 4)); + else + printf_filtered (_("Signal 2 not pending ")); + + if (signal2_type) + printf_filtered (_("(Type Overwrite)\n")); + else + printf_filtered (_("(Type Or)\n")); + } + + do_cleanups (chain); +} + +static void +info_spu_mailbox_list (gdb_byte *buf, int nr, + const char *field, const char *msg) +{ + struct cleanup *chain; + int i; + + if (nr <= 0) + return; + + chain = make_cleanup_ui_out_table_begin_end (uiout, 1, nr, "mbox"); + + ui_out_table_header (uiout, 32, ui_left, field, msg); + ui_out_table_body (uiout); + + for (i = 0; i < nr; i++) + { + 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); + ui_out_field_fmt (uiout, field, "0x%s", phex (val, 4)); + do_cleanups (val_chain); + + if (!ui_out_is_mi_like_p (uiout)) + printf_filtered ("\n"); + } + + do_cleanups (chain); +} + +static void +info_spu_mailbox_command (char *args, int from_tty) +{ + struct frame_info *frame = get_selected_frame (NULL); + struct cleanup *chain; + char annex[32]; + gdb_byte buf[1024]; + LONGEST len; + int i, id; + + id = get_frame_register_unsigned (frame, SPU_ID_REGNUM); + + chain = make_cleanup_ui_out_tuple_begin_end (uiout, "SPUInfoMailbox"); + + xsnprintf (annex, sizeof annex, "%d/mbox_info", id); + len = target_read (¤t_target, TARGET_OBJECT_SPU, annex, + buf, 0, sizeof buf); + if (len < 0) + error (_("Could not read mbox_info.")); + + info_spu_mailbox_list (buf, len / 4, "mbox", "SPU Outbound Mailbox"); + + xsnprintf (annex, sizeof annex, "%d/ibox_info", id); + len = target_read (¤t_target, TARGET_OBJECT_SPU, annex, + buf, 0, sizeof buf); + if (len < 0) + error (_("Could not read ibox_info.")); + + info_spu_mailbox_list (buf, len / 4, "ibox", "SPU Outbound Interrupt Mailbox"); + + xsnprintf (annex, sizeof annex, "%d/wbox_info", id); + len = target_read (¤t_target, TARGET_OBJECT_SPU, annex, + buf, 0, sizeof buf); + if (len < 0) + error (_("Could not read wbox_info.")); + + info_spu_mailbox_list (buf, len / 4, "wbox", "SPU Inbound Mailbox"); + + do_cleanups (chain); +} + +static ULONGEST +spu_mfc_get_bitfield (ULONGEST word, int first, int last) +{ + ULONGEST mask = ~(~(ULONGEST)0 << (last - first + 1)); + return (word >> (63 - last)) & mask; +} + +static void +info_spu_dma_cmdlist (gdb_byte *buf, int nr) +{ + static char *spu_mfc_opcode[256] = + { + /* 00 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + /* 10 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + /* 20 */ "put", "putb", "putf", NULL, "putl", "putlb", "putlf", NULL, + "puts", "putbs", "putfs", NULL, NULL, NULL, NULL, NULL, + /* 30 */ "putr", "putrb", "putrf", NULL, "putrl", "putrlb", "putrlf", NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + /* 40 */ "get", "getb", "getf", NULL, "getl", "getlb", "getlf", NULL, + "gets", "getbs", "getfs", NULL, NULL, NULL, NULL, NULL, + /* 50 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + /* 60 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + /* 70 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + /* 80 */ "sdcrt", "sdcrtst", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, "sdcrz", NULL, NULL, NULL, "sdcrst", NULL, "sdcrf", + /* 90 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + /* a0 */ "sndsig", "sndsigb", "sndsigf", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + /* b0 */ "putlluc", NULL, NULL, NULL, "putllc", NULL, NULL, NULL, + "putqlluc", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + /* c0 */ "barrier", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "mfceieio", NULL, NULL, NULL, "mfcsync", NULL, NULL, NULL, + /* d0 */ "getllar", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + /* e0 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + /* f0 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + }; + + struct cleanup *chain; + int i; + + chain = make_cleanup_ui_out_table_begin_end (uiout, 10, nr, "dma_cmd"); + + ui_out_table_header (uiout, 7, ui_left, "opcode", "Opcode"); + ui_out_table_header (uiout, 3, ui_left, "tag", "Tag"); + ui_out_table_header (uiout, 3, ui_left, "tid", "TId"); + ui_out_table_header (uiout, 3, ui_left, "rid", "RId"); + ui_out_table_header (uiout, 18, ui_left, "ea", "EA"); + ui_out_table_header (uiout, 7, ui_left, "lsa", "LSA"); + ui_out_table_header (uiout, 7, ui_left, "size", "Size"); + ui_out_table_header (uiout, 7, ui_left, "lstaddr", "LstAddr"); + ui_out_table_header (uiout, 7, ui_left, "lstsize", "LstSize"); + ui_out_table_header (uiout, 1, ui_left, "error_p", "E"); + + ui_out_table_body (uiout); + + for (i = 0; i < nr; i++) + { + struct cleanup *cmd_chain; + 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; + int list_valid_p, noop_valid_p, qw_valid_p, ea_valid_p, cmd_error_p; + + /* 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); + + list_lsa = spu_mfc_get_bitfield (mfc_cq_dw0, 0, 14); + list_size = spu_mfc_get_bitfield (mfc_cq_dw0, 15, 26); + mfc_cmd_opcode = spu_mfc_get_bitfield (mfc_cq_dw0, 27, 34); + mfc_cmd_tag = spu_mfc_get_bitfield (mfc_cq_dw0, 35, 39); + list_valid_p = spu_mfc_get_bitfield (mfc_cq_dw0, 40, 40); + rclass_id = spu_mfc_get_bitfield (mfc_cq_dw0, 41, 43); + tclass_id = spu_mfc_get_bitfield (mfc_cq_dw0, 44, 46); + + mfc_ea = spu_mfc_get_bitfield (mfc_cq_dw1, 0, 51) << 12 + | spu_mfc_get_bitfield (mfc_cq_dw2, 25, 36); + + mfc_lsa = spu_mfc_get_bitfield (mfc_cq_dw2, 0, 13); + mfc_size = spu_mfc_get_bitfield (mfc_cq_dw2, 14, 24); + noop_valid_p = spu_mfc_get_bitfield (mfc_cq_dw2, 37, 37); + qw_valid_p = spu_mfc_get_bitfield (mfc_cq_dw2, 38, 38); + ea_valid_p = spu_mfc_get_bitfield (mfc_cq_dw2, 39, 39); + cmd_error_p = spu_mfc_get_bitfield (mfc_cq_dw2, 40, 40); + + cmd_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "cmd"); + + if (spu_mfc_opcode[mfc_cmd_opcode]) + ui_out_field_string (uiout, "opcode", spu_mfc_opcode[mfc_cmd_opcode]); + else + ui_out_field_int (uiout, "opcode", mfc_cmd_opcode); + + ui_out_field_int (uiout, "tag", mfc_cmd_tag); + ui_out_field_int (uiout, "tid", tclass_id); + ui_out_field_int (uiout, "rid", rclass_id); + + if (ea_valid_p) + ui_out_field_fmt (uiout, "ea", "0x%s", phex (mfc_ea, 8)); + else + ui_out_field_skip (uiout, "ea"); + + ui_out_field_fmt (uiout, "lsa", "0x%05x", mfc_lsa << 4); + if (qw_valid_p) + ui_out_field_fmt (uiout, "size", "0x%05x", mfc_size << 4); + else + ui_out_field_fmt (uiout, "size", "0x%05x", mfc_size); + + if (list_valid_p) + { + ui_out_field_fmt (uiout, "lstaddr", "0x%05x", list_lsa << 3); + ui_out_field_fmt (uiout, "lstsize", "0x%05x", list_size << 3); + } + else + { + ui_out_field_skip (uiout, "lstaddr"); + ui_out_field_skip (uiout, "lstsize"); + } + + if (cmd_error_p) + ui_out_field_string (uiout, "error_p", "*"); + else + ui_out_field_skip (uiout, "error_p"); + + do_cleanups (cmd_chain); + + if (!ui_out_is_mi_like_p (uiout)) + printf_filtered ("\n"); + } + + do_cleanups (chain); +} + +static void +info_spu_dma_command (char *args, int from_tty) +{ + struct frame_info *frame = get_selected_frame (NULL); + ULONGEST dma_info_type; + ULONGEST dma_info_mask; + ULONGEST dma_info_status; + ULONGEST dma_info_stall_and_notify; + ULONGEST dma_info_atomic_command_status; + struct cleanup *chain; + char annex[32]; + gdb_byte buf[1024]; + LONGEST len; + int i, id; + + id = get_frame_register_unsigned (frame, SPU_ID_REGNUM); + + xsnprintf (annex, sizeof annex, "%d/dma_info", id); + len = target_read (¤t_target, TARGET_OBJECT_SPU, annex, + buf, 0, 40 + 16 * 32); + 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); + + chain = make_cleanup_ui_out_tuple_begin_end (uiout, "SPUInfoDMA"); + + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_fmt (uiout, "dma_info_type", "0x%s", + phex_nz (dma_info_type, 4)); + ui_out_field_fmt (uiout, "dma_info_mask", "0x%s", + phex_nz (dma_info_mask, 4)); + ui_out_field_fmt (uiout, "dma_info_status", "0x%s", + phex_nz (dma_info_status, 4)); + ui_out_field_fmt (uiout, "dma_info_stall_and_notify", "0x%s", + phex_nz (dma_info_stall_and_notify, 4)); + ui_out_field_fmt (uiout, "dma_info_atomic_command_status", "0x%s", + phex_nz (dma_info_atomic_command_status, 4)); + } + else + { + const char *query_msg; + + 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; + } + + printf_filtered (_("Tag-Group Status 0x%s\n"), + phex (dma_info_status, 4)); + printf_filtered (_("Tag-Group Mask 0x%s (%s)\n"), + phex (dma_info_mask, 4), query_msg); + printf_filtered (_("Stall-and-Notify 0x%s\n"), + phex (dma_info_stall_and_notify, 4)); + printf_filtered (_("Atomic Cmd Status 0x%s\n"), + phex (dma_info_atomic_command_status, 4)); + printf_filtered ("\n"); + } + + info_spu_dma_cmdlist (buf + 40, 16); + do_cleanups (chain); +} + +static void +info_spu_proxydma_command (char *args, int from_tty) +{ + struct frame_info *frame = get_selected_frame (NULL); + ULONGEST dma_info_type; + ULONGEST dma_info_mask; + ULONGEST dma_info_status; + struct cleanup *chain; + char annex[32]; + gdb_byte buf[1024]; + LONGEST len; + int i, id; + + id = get_frame_register_unsigned (frame, SPU_ID_REGNUM); + + xsnprintf (annex, sizeof annex, "%d/proxydma_info", id); + len = target_read (¤t_target, TARGET_OBJECT_SPU, annex, + buf, 0, 24 + 8 * 32); + 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); + + chain = make_cleanup_ui_out_tuple_begin_end (uiout, "SPUInfoProxyDMA"); + + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_fmt (uiout, "proxydma_info_type", "0x%s", + phex_nz (dma_info_type, 4)); + ui_out_field_fmt (uiout, "proxydma_info_mask", "0x%s", + phex_nz (dma_info_mask, 4)); + ui_out_field_fmt (uiout, "proxydma_info_status", "0x%s", + phex_nz (dma_info_status, 4)); + } + else + { + const char *query_msg; + + 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; + } + + printf_filtered (_("Tag-Group Status 0x%s\n"), + phex (dma_info_status, 4)); + printf_filtered (_("Tag-Group Mask 0x%s (%s)\n"), + phex (dma_info_mask, 4), query_msg); + printf_filtered ("\n"); + } + + info_spu_dma_cmdlist (buf + 24, 8); + do_cleanups (chain); +} + +static void +info_spu_command (char *args, int from_tty) +{ + printf_unfiltered (_("\"info spu\" must be followed by the name of an SPU facility.\n")); + help_list (infospucmdlist, "info spu ", -1, gdb_stdout); +} + + /* Set up gdbarch struct. */ static struct gdbarch * @@ -1430,4 +2025,26 @@ _initialize_spu_tdep (void) /* Add ourselves to objfile event chain. */ observer_attach_new_objfile (spu_overlay_new_objfile); spu_overlay_data = register_objfile_data (); + + /* Add root prefix command for all "info spu" commands. */ + add_prefix_cmd ("spu", class_info, info_spu_command, + _("Various SPU specific commands."), + &infospucmdlist, "info spu ", 0, &infolist); + + /* Add various "info spu" commands. */ + add_cmd ("event", class_info, info_spu_event_command, + _("Display SPU event facility status.\n"), + &infospucmdlist); + add_cmd ("signal", class_info, info_spu_signal_command, + _("Display SPU signal notification facility status.\n"), + &infospucmdlist); + add_cmd ("mailbox", class_info, info_spu_mailbox_command, + _("Display SPU mailbox facility status.\n"), + &infospucmdlist); + add_cmd ("dma", class_info, info_spu_dma_command, + _("Display MFC DMA status.\n"), + &infospucmdlist); + add_cmd ("proxydma", class_info, info_spu_proxydma_command, + _("Display MFC Proxy-DMA status.\n"), + &infospucmdlist); } diff --git a/gdb/spu-tdep.h b/gdb/spu-tdep.h index 7d0df18..d573608 100644 --- a/gdb/spu-tdep.h +++ b/gdb/spu-tdep.h @@ -23,7 +23,7 @@ /* Number of registers. */ #define SPU_NUM_REGS 130 -#define SPU_NUM_PSEUDO_REGS 1 +#define SPU_NUM_PSEUDO_REGS 6 #define SPU_NUM_GPRS 128 /* Register numbers of various important registers. */ @@ -41,7 +41,12 @@ enum spu_regnum /* Special registers. */ SPU_ID_REGNUM = 128, /* SPU ID register. */ SPU_PC_REGNUM = 129, /* Next program counter. */ - SPU_SP_REGNUM = 130 /* Stack pointer (preferred slot). */ + SPU_SP_REGNUM = 130, /* Stack pointer (preferred slot). */ + SPU_FPSCR_REGNUM = 131, /* Floating point status/control register. */ + SPU_SRR0_REGNUM = 132, /* SRR0 register. */ + SPU_LSLR_REGNUM = 133, /* Local store limit register. */ + SPU_DECR_REGNUM = 134, /* Decrementer value. */ + SPU_DECR_STATUS_REGNUM = 135 /* Decrementer status. */ }; /* Local store. */ diff --git a/gdb/target.h b/gdb/target.h index 24db136..7cde49b 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -189,6 +189,8 @@ enum target_object { /* AVR target specific transfer. See "avr-tdep.c" and "remote.c". */ TARGET_OBJECT_AVR, + /* SPU target specific transfer. See "spu-tdep.c". */ + TARGET_OBJECT_SPU, /* Transfer up-to LEN bytes of memory starting at OFFSET. */ TARGET_OBJECT_MEMORY, /* Memory, avoiding GDB's data cache and trusting the executable. diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 80d31af..c953e57 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2007-06-12 Ulrich Weigand <Ulrich.Weigand@de.ibm.com> + Markus Deuling <deuling@de.ibm.com> + + * gdb.arch/spu-info.exp: New testcase. + * gdb.arch/spu-info.c: New file. + 2007-06-05 Daniel Jacobowitz <dan@codesourcery.com> * gdb.arch/thumb-prologue.c: Record the breakpoint address in diff --git a/gdb/testsuite/gdb.arch/spu-info.c b/gdb/testsuite/gdb.arch/spu-info.c new file mode 100644 index 0000000..1fc83ec --- /dev/null +++ b/gdb/testsuite/gdb.arch/spu-info.c @@ -0,0 +1,236 @@ +/* Copyright 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + This file is part of the gdb testsuite. + + Contributed by Markus Deuling <deuling@de.ibm.com>. + Tests for 'info spu' commands. */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <spu_mfcio.h> + + +/* PPE-assisted call interface. */ +void +send_to_ppe (unsigned int signalcode, unsigned int opcode, void *data) +{ + __vector unsigned int stopfunc = + { + signalcode, /* stop */ + (opcode << 24) | (unsigned int) data, + 0x4020007f, /* nop */ + 0x35000000 /* bi $0 */ + }; + + void (*f) (void) = (void *) &stopfunc; + asm ("sync"); + f (); +} + +/* PPE-assisted call to mmap from SPU. */ +unsigned long long +mmap_ea (unsigned long long start, size_t length, + int prot, int flags, int fd, off_t offset) +{ + struct mmap_args + { + unsigned long long start __attribute__ ((aligned (16))); + size_t length __attribute__ ((aligned (16))); + int prot __attribute__ ((aligned (16))); + int flags __attribute__ ((aligned (16))); + int fd __attribute__ ((aligned (16))); + off_t offset __attribute__ ((aligned (16))); + } args; + + args.start = start; + args.length = length; + args.prot = prot; + args.flags = flags; + args.fd = fd; + args.offset = offset; + + send_to_ppe (0x2101, 11, &args); + return args.start; +} + +/* This works only in a Linux environment with <= 1024 open + file descriptors for one process. Result is the file + descriptor for the current context if available. */ +int +find_context_fd (void) +{ + int dir_fd = -1; + int i; + + for (i = 0; i < 1024; i++) + { + struct stat stat; + + if (fstat (i, &stat) < 0) + break; + if (S_ISDIR (stat.st_mode)) + dir_fd = dir_fd == -1 ? i : -2; + } + return dir_fd < 0 ? -1 : dir_fd; +} + +/* Open the context file and return the file handler. */ +int +open_context_file (int context_fd, char *name, int flags) +{ + char buf[128]; + + if (context_fd < 0) + return -1; + + sprintf (buf, "/proc/self/fd/%d/%s", context_fd, name); + return open (buf, flags); +} + + +int +do_event_test () +{ + spu_write_event_mask (MFC_MULTI_SRC_SYNC_EVENT); /* 0x1000 */ /* Marker Event */ + spu_write_event_mask (MFC_PRIV_ATTN_EVENT); /* 0x0800 */ + spu_write_event_mask (MFC_LLR_LOST_EVENT); /* 0x0400 */ + spu_write_event_mask (MFC_SIGNAL_NOTIFY_1_EVENT); /* 0x0200 */ + spu_write_event_mask (MFC_SIGNAL_NOTIFY_2_EVENT); /* 0x0100 */ + spu_write_event_mask (MFC_OUT_MBOX_AVAILABLE_EVENT); /* 0x0080 */ + spu_write_event_mask (MFC_OUT_INTR_MBOX_AVAILABLE_EVENT); /* 0x0040 */ + spu_write_event_mask (MFC_DECREMENTER_EVENT); /* 0x0020 */ + spu_write_event_mask (MFC_IN_MBOX_AVAILABLE_EVENT); /* 0x0010 */ + spu_write_event_mask (MFC_COMMAND_QUEUE_AVAILABLE_EVENT); /* 0x0008 */ + spu_write_event_mask (MFC_LIST_STALL_NOTIFY_EVENT); /* 0x0002 */ + spu_write_event_mask (MFC_TAG_STATUS_UPDATE_EVENT); /* 0x0001 */ + + return 0; +} + +int +do_dma_test () +{ + #define MAP_FAILED (-1ULL) + #define PROT_READ 0x1 + #define MAP_PRIVATE 0x002 + #define BSIZE 128 + static char buf[BSIZE] __attribute__ ((aligned (128))); + char *file = "/var/tmp/tmp_buf"; + struct stat fdstat; + int fd, cnt; + unsigned long long src; + + /* Create a file and fill it with some bytes. */ + fd = open (file, O_CREAT | O_RDWR | O_TRUNC, 0777); + if (fd == -1) + return -1; + memset ((void *)buf, '1', BSIZE); + write (fd, buf, BSIZE); + write (fd, buf, BSIZE); + memset ((void *)buf, 0, BSIZE); + + if (fstat (fd, &fdstat) != 0 + || !fdstat.st_size) + return -2; + + src = mmap_ea(0ULL, fdstat.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (src == MAP_FAILED) + return -3; + + /* Copy some data via DMA. */ + mfc_get (&buf, src, BSIZE, 5, 0, 0); /* Marker DMA */ + mfc_write_tag_mask (1<<5); /* Marker DMAWait */ + spu_mfcstat (MFC_TAG_UPDATE_ALL); + + /* Close the file. */ + close (fd); + + return cnt; +} + +int +do_mailbox_test () +{ + /* Write to SPU Outbound Mailbox. */ + if (spu_stat_out_mbox ()) /* Marker Mbox */ + spu_write_out_mbox (0x12345678); + + /* Write to SPU Outbound Interrupt Mailbox. */ + if (spu_stat_out_intr_mbox ()) + spu_write_out_intr_mbox (0x12345678); + + return 0; /* Marker MboxEnd */ +} + +int +do_signal_test () +{ + struct stat fdstat; + int context_fd = find_context_fd (); + int ret, buf, fd; + + buf = 23; /* Marker Signal */ + /* Write to signal1. */ + fd = open_context_file (context_fd, "signal1", O_RDWR); + if (fstat (fd, &fdstat) != 0) + return -1; + ret = write (fd, buf, sizeof (int)); + close (fd); /* Marker Signal1 */ + + /* Write to signal2. */ + fd = open_context_file (context_fd, "signal2", O_RDWR); + if (fstat (fd, &fdstat) != 0) + return -1; + ret = write (fd, buf, sizeof (int)); + close (fd); /* Marker Signal2 */ + + /* Read signal1. */ + if (spu_stat_signal1 ()) + ret = spu_read_signal1 (); + + /* Read signal2. */ + if (spu_stat_signal2 ()) + ret = spu_read_signal2 (); /* Marker SignalRead */ + + return 0; +} + +int +main (unsigned long long speid, unsigned long long argp, + unsigned long long envp) +{ + int res; + + /* info spu event */ + res = do_event_test (); + + /* info spu dma */ + res = do_dma_test (); + + /* info spu mailbox */ + res = do_mailbox_test (); + + /* info spu signal */ + res = do_signal_test (); + + return 0; +} + diff --git a/gdb/testsuite/gdb.arch/spu-info.exp b/gdb/testsuite/gdb.arch/spu-info.exp new file mode 100644 index 0000000..61e997a --- /dev/null +++ b/gdb/testsuite/gdb.arch/spu-info.exp @@ -0,0 +1,243 @@ +# Copyright 2007 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# +# This file is part of the gdb testsuite. +# +# Contributed by Markus Deuling <deuling@de.ibm.com>. +# Tests for 'info spu' commands. + +set prms_id 0 +set bug_id 0 + +if { ![istarget "spu-*-elf"] } then { + verbose "Skipping SPU-only testcase" + return +} + +set testfile "spu-info" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +set sources ${srcdir}/${subdir}/${srcfile} + +if { [gdb_compile $sources ${binfile} executable { debug }] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# Continue to MARKER +proc c_to { marker } { + global srcfile + set line [gdb_get_line_number $marker] + gdb_test "break $line" \ + "Breakpoint.*at.*file.*$srcfile.*line $line.*" \ + "break $line" + gdb_test "continue" \ + "Continuing.*Breakpoint.*at.*$srcfile.*$line.*" \ + "continue to $line" +} + + + +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +# Check the help. +gdb_test "info spu" \ + ".*info spu.* must be followed by the name of an SPU facility.*" \ + "info spu" +gdb_test "help info spu" \ + "Various SPU specific commands.*List of info spu subcommands.*" \ + "help info spu" + +gdb_test "help info spu dma" \ + "Display MFC DMA status." \ + "help info spu dma" +gdb_test "help info spu event" \ + "Display SPU event facility status." \ + "help info spu event" +gdb_test "help info spu mailbox" \ + "Display SPU mailbox facility status." \ + "help info spu mailbox" +gdb_test "help info spu proxydma" \ + "Display MFC Proxy-DMA status." \ + "help info spu proxydma" +gdb_test "help info spu signal" \ + "Display SPU signal notification facility status." \ + "help info spu signal" + + +# architecture should be spu:256K. +gdb_test "show architecture" \ + "The target architecture is set automatically.*currently spu:256K.*" \ + "architecture = spu256K" + +# 'info spu event'. +gdb_test "info spu event" \ + "Event Status.*Event Mask.*" \ + "info spu event" + +# 'info spu signal'. +gdb_test "info spu signal" \ + "Signal 1 not pending.*\(Type.*\).*Signal 2 not pending.*\(Type.*\).*" \ + "info spu signal" + +# 'info spu mailbox'. +gdb_test "info spu mailbox" \ + "SPU Outbound Mailbox.*SPU Outbound Interrupt Mailbox.*" \ + "info spu mailbox" + +# 'info spu dma'. +gdb_test "info spu dma" \ + "Tag-Group Status.*Tag-Group Mask.*Stall-and-Notify .*Atomic Cmd Status.*Opcode.*Tag.*TId.*RId.*EA.*LSA.*Size.*LstAddr.*LstSize.*E.*" \ + "info spu dma" + +# 'info spu proxydma'. +gdb_test "info spu proxydma" \ + "Tag-Group Status.*Tag-Group Mask.*Opcode.*Tag.*TId.*RId.*EA.*LSA.*Size.*LstAddr.*LstSize.*E.*" \ + "info spu proxydma" + +# Event tests. +c_to "Marker Event" +gdb_test "info spu event" \ + "Event Status 0x00000000.*Event Mask 0x00000000.*" \ + "empty event status" + +# MFC_MULTI_SRC_SYNC_EVENT. +gdb_test "next" "" "next" +gdb_test "info spu event" \ + "Event Status 0x00000000.*Event Mask 0x00001000.*" \ + "event mask 0x1000" +# MFC_PRIV_ATTN_EVENT. +gdb_test "next" "" "next" +gdb_test "info spu event" \ + "Event Status 0x00000000.*Event Mask 0x00000800.*" \ + "event mask 0x0800" +# MFC_LLR_LOST_EVENT. +gdb_test "next" "" "next" +gdb_test "info spu event" \ + "Event Status 0x00000000.*Event Mask 0x00000400.*" \ + "event mask 0x0400" +# MFC_SIGNAL_NOTIFY_1_EVENT. +gdb_test "next" "" "next" +gdb_test "info spu event" \ + "Event Status 0x00000000.*Event Mask 0x00000200.*" \ + "event mask 0x0200" +# MFC_SIGNAL_NOTIFY_2_EVENT. +gdb_test "next" "" "next" +gdb_test "info spu event" \ + "Event Status 0x00000000.*Event Mask 0x00000100.*" \ + "event mask 0x0100" +# MFC_OUT_MBOX_AVAILABLE_EVENT. +gdb_test "next" "" "next" +gdb_test "info spu event" \ + "Event Status 0x00000000.*Event Mask 0x00000080.*" \ + "event mask 0x0080" +# MFC_OUT_INTR_MBOX_AVAILABLE_EVENT. +gdb_test "next" "" "next" +gdb_test "info spu event" \ + "Event Status 0x00000000.*Event Mask 0x00000040.*" \ + "event mask 0x0040" +# MFC_DECREMENTER_EVENT. +gdb_test "next" "" "next" +gdb_test "info spu event" \ + "Event Status 0x00000000.*Event Mask 0x00000020.*" \ + "event mask 0x0020" +# MFC_IN_MBOX_AVAILABLE_EVENT. +gdb_test "next" "" "next" +gdb_test "info spu event" \ + "Event Status 0x00000000.*Event Mask 0x00000010.*" \ + "event mask 0x0010" +# MFC_COMMAND_QUEUE_AVAILABLE_EVENT. +gdb_test "next" "" "next" +gdb_test "info spu event" \ + "Event Status 0x00000000.*Event Mask 0x00000008.*" \ + "event mask 0x0008" +# MFC_LIST_STALL_NOTIFY_EVENT. +gdb_test "next" "" "next" +gdb_test "info spu event" \ + "Event Status 0x00000000.*Event Mask 0x00000002.*" \ + "event mask 0x0002" +# MFC_TAG_STATUS_UPDATE_EVENT. +gdb_test "next" "" "next" +gdb_test "info spu event" \ + "Event Status 0x00000000.*Event Mask 0x00000001.*" \ + "event mask 0x0001" + + +# DMA tests. +# 'info spu dma' should be empty. +c_to "Marker DMA" +gdb_test "info spu dma" \ + "Tag-Group Status.*0x00000000.*Tag-Group Mask.*0x00000000.*Stall-and-Notify.*0x00000000.*Atomic Cmd Status.*0x00000000.*Opcode.*Tag.*TId.*RId.*EA.*LSA.*Size.*LstAddr.*LstSize.*E.*0.*0.*0.*0.*0x00000 0x00000.*" \ + "info spu dma (empty)" + +# 'info spu dma' should be filled with some data. +c_to "Marker DMAWait" +gdb_test "next" "" "next" +gdb_test "info spu dma" \ + "Tag-Group Status.*0x00000000.*Tag-Group Mask.*0x00000020.*Stall-and-Notify.*0x00000000.*Atomic Cmd Status.*0x00000000.*Opcode.*Tag.*TId.*RId.*EA.*LSA.*Size.*LstAddr.*LstSize.*E.*getl.*putllc.*get.*mfcsync.*get.*0.*0.*0.*0.*0x00000 0x00000.*" \ + "info spu dma (non-empty)" +gdb_test "finish" "" "finish" + +# Mailbox Test +# 'info spu mailbox' should be empty. +c_to "Marker Mbox" +gdb_test "info spu mailbox" \ + "SPU Outbound Mailbox.*0xc0000000.*SPU Outbound Interrupt Mailbox.*0xc0000000.*" \ + "info spu mailbox" + +# 'info spu mailbox' should now contain data. +c_to "Marker MboxEnd" +gdb_test "info spu mailbox" \ + "SPU Outbound Mailbox.*0x12345678.*SPU Outbound Interrupt Mailbox.*0x12345678.*" \ + "info spu mailbox" + +# Signal Test +# 'info spu signal'. +c_to "Marker Signal" +gdb_test "info spu signal" \ + "Signal 1 not pending.*\(Type.*\).*Signal 2 not pending.*\(Type.*\).*" \ + "info spu signal" + +# 'info spu signal' with signal1 pending. +c_to "Marker Signal1" +gdb_test "info spu signal" \ + "Signal 1 control word 0x801c0800.*Signal 2 not pending.*\(Type.*\).*" \ + "info spu signal" + +# 'info spu signal' with signal1 and signal2 pending. +c_to "Marker Signal2" +gdb_test "info spu signal" \ + "Signal 1 control word 0x801c0800.*Signal 2 control word 0x801c0800.*" \ + "info spu signal" + +# Read signal1. Only signal2 is pending. +c_to "Marker SignalRead" +gdb_test "info spu signal" \ + "Signal 1 not pending.*Signal 2 control word 0x801c0800.*" \ + "info spu signal" + + +gdb_exit + +return 0 |