summaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.arch/spu-info.c
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2007-06-12 14:35:26 +0000
committerUlrich Weigand <uweigand@de.ibm.com>2007-06-12 14:35:26 +0000
commit23d964e7b6625bec3822bcb9613f65362b9b3026 (patch)
treec9c8d4a9f98b11ad39dc14dddc8f41374747fc33 /gdb/testsuite/gdb.arch/spu-info.c
parent374c1d382bcb2271b3a39ee369717f255ca0777a (diff)
downloadbinutils-gdb-23d964e7b6625bec3822bcb9613f65362b9b3026.tar.gz
* 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. testsuite/ChangeLog: * gdb.arch/spu-info.exp: New testcase. * gdb.arch/spu-info.c: New file. doc/ChangeLog: * gdb.texinfo (Architectures): Add new SPU section to document Cell Broadband Engine SPU architecture specific commands.
Diffstat (limited to 'gdb/testsuite/gdb.arch/spu-info.c')
-rw-r--r--gdb/testsuite/gdb.arch/spu-info.c236
1 files changed, 236 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.arch/spu-info.c b/gdb/testsuite/gdb.arch/spu-info.c
new file mode 100644
index 00000000000..1fc83ec076c
--- /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;
+}
+