diff options
author | K. Richard Pixley <rich@cygnus> | 1991-03-28 16:28:29 +0000 |
---|---|---|
committer | K. Richard Pixley <rich@cygnus> | 1991-03-28 16:28:29 +0000 |
commit | dd3b648e8b12ceb7bfce66e7f179b671403aea9c (patch) | |
tree | 91119a0f4943acc9293cd8baba06943621b6e6c7 /gdb/convex-tdep.c | |
parent | bd5635a1e2b38ee8432fcdaa6456079191375277 (diff) | |
download | gdb-dd3b648e8b12ceb7bfce66e7f179b671403aea9c.zip gdb-dd3b648e8b12ceb7bfce66e7f179b671403aea9c.tar.gz gdb-dd3b648e8b12ceb7bfce66e7f179b671403aea9c.tar.bz2 |
Johns release
Diffstat (limited to 'gdb/convex-tdep.c')
-rw-r--r-- | gdb/convex-tdep.c | 934 |
1 files changed, 934 insertions, 0 deletions
diff --git a/gdb/convex-tdep.c b/gdb/convex-tdep.c new file mode 100644 index 0000000..c206e1e --- /dev/null +++ b/gdb/convex-tdep.c @@ -0,0 +1,934 @@ +/* Convex stuff for GDB. + Copyright (C) 1990 Free Software Foundation, Inc. + +This file is part of GDB. + +GDB 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 1, or (at your option) +any later version. + +GDB 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 GDB; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <stdio.h> +#include "defs.h" +#include "param.h" +#include "command.h" +#include "symtab.h" +#include "value.h" +#include "frame.h" +#include "inferior.h" +#include "wait.h" + +#include <signal.h> +#include <fcntl.h> + +#include "gdbcore.h" +#include <sys/param.h> +#include <sys/dir.h> +#include <sys/user.h> +#include <sys/ioctl.h> +#include <sys/pcntl.h> +#include <sys/thread.h> +#include <sys/proc.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/mman.h> + +#include "gdbcmd.h" + +exec_file_command (filename, from_tty) + char *filename; + int from_tty; +{ + int val; + int n; + struct stat st_exec; + + /* Eliminate all traces of old exec file. + Mark text segment as empty. */ + + if (execfile) + free (execfile); + execfile = 0; + data_start = 0; + data_end = 0; + text_start = 0; + text_end = 0; + exec_data_start = 0; + exec_data_end = 0; + if (execchan >= 0) + close (execchan); + execchan = -1; + + n_exec = 0; + + /* Now open and digest the file the user requested, if any. */ + + if (filename) + { + filename = tilde_expand (filename); + make_cleanup (free, filename); + + execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, + &execfile); + if (execchan < 0) + perror_with_name (filename); + + if (myread (execchan, &filehdr, sizeof filehdr) < 0) + perror_with_name (filename); + + if (! IS_SOFF_MAGIC (filehdr.h_magic)) + error ("%s: not an executable file.", filename); + + if (myread (execchan, &opthdr, filehdr.h_opthdr) <= 0) + perror_with_name (filename); + + /* Read through the section headers. + For text, data, etc, record an entry in the exec file map. + Record text_start and text_end. */ + + lseek (execchan, (long) filehdr.h_scnptr, 0); + + for (n = 0; n < filehdr.h_nscns; n++) + { + if (myread (execchan, &scnhdr, sizeof scnhdr) < 0) + perror_with_name (filename); + + if ((scnhdr.s_flags & S_TYPMASK) >= S_TEXT + && (scnhdr.s_flags & S_TYPMASK) <= S_COMON) + { + exec_map[n_exec].mem_addr = scnhdr.s_vaddr; + exec_map[n_exec].mem_end = scnhdr.s_vaddr + scnhdr.s_size; + exec_map[n_exec].file_addr = scnhdr.s_scnptr; + exec_map[n_exec].type = scnhdr.s_flags & S_TYPMASK; + n_exec++; + + if ((scnhdr.s_flags & S_TYPMASK) == S_TEXT) + { + text_start = scnhdr.s_vaddr; + text_end = scnhdr.s_vaddr + scnhdr.s_size; + } + } + } + + fstat (execchan, &st_exec); + exec_mtime = st_exec.st_mtime; + + validate_files (); + } + else if (from_tty) + printf_filtered ("No exec file now.\n"); + + /* Tell display code (if any) about the changed file name. */ + if (exec_file_display_hook) + (*exec_file_display_hook) (filename); +} + +/* Read data from SOFF exec or core file. + Return 0 on success, EIO if address out of bounds. */ + +int +xfer_core_file (memaddr, myaddr, len) + CORE_ADDR memaddr; + char *myaddr; + int len; +{ + register int i; + register int n; + register int val; + int xferchan; + char **xferfile; + int fileptr; + int returnval = 0; + + while (len > 0) + { + xferfile = 0; + xferchan = 0; + + /* Determine which file the next bunch of addresses reside in, + and where in the file. Set the file's read/write pointer + to point at the proper place for the desired address + and set xferfile and xferchan for the correct file. + If desired address is nonexistent, leave them zero. + i is set to the number of bytes that can be handled + along with the next address. */ + + i = len; + + for (n = 0; n < n_core; n++) + { + if (memaddr >= core_map[n].mem_addr && memaddr < core_map[n].mem_end + && (core_map[n].thread == -1 + || core_map[n].thread == inferior_thread)) + { + i = min (len, core_map[n].mem_end - memaddr); + fileptr = core_map[n].file_addr + memaddr - core_map[n].mem_addr; + if (core_map[n].file_addr) + { + xferfile = &corefile; + xferchan = corechan; + } + break; + } + else if (core_map[n].mem_addr >= memaddr + && core_map[n].mem_addr < memaddr + i) + i = core_map[n].mem_addr - memaddr; + } + + if (!xferfile) + for (n = 0; n < n_exec; n++) + { + if (memaddr >= exec_map[n].mem_addr + && memaddr < exec_map[n].mem_end) + { + i = min (len, exec_map[n].mem_end - memaddr); + fileptr = exec_map[n].file_addr + memaddr + - exec_map[n].mem_addr; + if (exec_map[n].file_addr) + { + xferfile = &execfile; + xferchan = execchan; + } + break; + } + else if (exec_map[n].mem_addr >= memaddr + && exec_map[n].mem_addr < memaddr + i) + i = exec_map[n].mem_addr - memaddr; + } + + /* Now we know which file to use. + Set up its pointer and transfer the data. */ + if (xferfile) + { + if (*xferfile == 0) + if (xferfile == &execfile) + error ("No program file to examine."); + else + error ("No core dump file or running program to examine."); + val = lseek (xferchan, fileptr, 0); + if (val < 0) + perror_with_name (*xferfile); + val = myread (xferchan, myaddr, i); + if (val < 0) + perror_with_name (*xferfile); + } + /* If this address is for nonexistent memory, + read zeros if reading, or do nothing if writing. */ + else + { + bzero (myaddr, i); + returnval = EIO; + } + + memaddr += i; + myaddr += i; + len -= i; + } + return returnval; +} + + +/* Here from info files command to print an address map. */ + +print_maps () +{ + struct pmap ptrs[200]; + int n; + + /* ID strings for core and executable file sections */ + + static char *idstr[] = + { + "0", "text", "data", "tdata", "bss", "tbss", + "common", "ttext", "ctx", "tctx", "10", "11", "12", + }; + + for (n = 0; n < n_core; n++) + { + core_map[n].which = 0; + ptrs[n] = core_map[n]; + } + for (n = 0; n < n_exec; n++) + { + exec_map[n].which = 1; + ptrs[n_core+n] = exec_map[n]; + } + + qsort (ptrs, n_core + n_exec, sizeof *ptrs, ptr_cmp); + + for (n = 0; n < n_core + n_exec; n++) + { + struct pmap *p = &ptrs[n]; + if (n > 0) + { + if (p->mem_addr < ptrs[n-1].mem_end) + p->mem_addr = ptrs[n-1].mem_end; + if (p->mem_addr >= p->mem_end) + continue; + } + printf_filtered ("%08x .. %08x %-6s %s\n", + p->mem_addr, p->mem_end, idstr[p->type], + p->which ? execfile : corefile); + } +} + +/* Compare routine to put file sections in order. + Sort into increasing order on address, and put core file sections + before exec file sections if both files contain the same addresses. */ + +static ptr_cmp (a, b) + struct pmap *a, *b; +{ + if (a->mem_addr != b->mem_addr) return a->mem_addr - b->mem_addr; + return a->which - b->which; +} + +/* Trapped internal variables are used to handle special registers. + A trapped i.v. calls a hook here every time it is dereferenced, + to provide a new value for the variable, and it calls a hook here + when a new value is assigned, to do something with the value. + + The vector registers are $vl, $vs, $vm, $vN, $VN (N in 0..7). + The communication registers are $cN, $CN (N in 0..63). + They not handled as regular registers because it's expensive to + read them, and their size varies, and they have too many names. */ + + +/* Return 1 if NAME is a trapped internal variable, else 0. */ + +int +is_trapped_internalvar (name) + char *name; +{ + if ((name[0] == 'c' || name[0] == 'C') + && name[1] >= '0' && name[1] <= '9' + && (name[2] == '\0' + || (name[2] >= '0' && name[2] <= '9' + && name[3] == '\0' && name[1] != '0')) + && atoi (&name[1]) < 64) return 1; + + if ((name[0] == 'v' || name[0] == 'V') + && (((name[1] & -8) == '0' && name[2] == '\0') + || !strcmp (name, "vl") + || !strcmp (name, "vs") + || !strcmp (name, "vm"))) + return 1; + else return 0; +} + +/* Return the value of trapped internal variable VAR */ + +value +value_of_trapped_internalvar (var) + struct internalvar *var; +{ + char *name = var->name; + value val; + struct type *type; + long len = *read_vector_register (VL_REGNUM); + if (len <= 0 || len > 128) len = 128; + + if (!strcmp (name, "vl")) + { + val = value_from_long (builtin_type_int, + (LONGEST) *read_vector_register_1 (VL_REGNUM)); + } + else if (!strcmp (name, "vs")) + { + val = value_from_long (builtin_type_int, + (LONGEST) *read_vector_register_1 (VS_REGNUM)); + } + else if (!strcmp (name, "vm")) + { + long vm[4]; + long i, *p; + bcopy (read_vector_register_1 (VM_REGNUM), vm, sizeof vm); + type = vector_type (builtin_type_int, len); + val = allocate_value (type); + p = (long *) VALUE_CONTENTS (val); + for (i = 0; i < len; i++) + *p++ = !! (vm[3 - (i >> 5)] & (1 << (i & 037))); + } + else if (name[0] == 'V') + { + type = vector_type (builtin_type_long_long, len); + val = allocate_value (type); + bcopy (read_vector_register_1 (name[1] - '0'), + VALUE_CONTENTS (val), TYPE_LENGTH (type)); + } + else if (name[0] == 'v') + { + long *p1, *p2; + type = vector_type (builtin_type_long, len); + val = allocate_value (type); + p1 = read_vector_register_1 (name[1] - '0'); + p2 = (long *) VALUE_CONTENTS (val); + while (--len >= 0) {p1++; *p2++ = *p1++;} + } + + else if (name[0] == 'c') + val = value_from_long (builtin_type_int, + read_comm_register (atoi (&name[1]))); + else if (name[0] == 'C') + val = value_from_long (builtin_type_long_long, + read_comm_register (atoi (&name[1]))); + + VALUE_LVAL (val) = lval_internalvar; + VALUE_INTERNALVAR (val) = var; + return val; +} + +/* Construct the type for a vector register's value -- + array[LENGTH] of ELEMENT_TYPE. */ + +static struct type * +vector_type (element_type, length) + struct type *element_type; + long length; +{ + struct type *type = (struct type *) xmalloc (sizeof (struct type)); + bzero (type, sizeof type); + TYPE_CODE (type) = TYPE_CODE_ARRAY; + TYPE_TARGET_TYPE (type) = element_type; + TYPE_LENGTH (type) = length * TYPE_LENGTH (TYPE_TARGET_TYPE (type)); + return type; +} + +/* Handle a new value assigned to a trapped internal variable */ + +void +set_trapped_internalvar (var, val, bitpos, bitsize, offset) + struct internalvar *var; + value val; + int bitpos, bitsize, offset; +{ + char *name = var->name; + long long newval = value_as_long (val); + + if (!strcmp (name, "vl")) + write_vector_register (VL_REGNUM, 0, newval); + else if (!strcmp (name, "vs")) + write_vector_register (VS_REGNUM, 0, newval); + else if (name[0] == 'c' || name[0] == 'C') + write_comm_register (atoi (&name[1]), newval); + else if (!strcmp (name, "vm")) + error ("can't assign to $vm"); + else + { + offset /= bitsize / 8; + write_vector_register (name[1] - '0', offset, newval); + } +} + +/* Print an integer value when no format was specified. gdb normally + prints these values in decimal, but the the leading 0x80000000 of + pointers produces intolerable 10-digit negative numbers. + If it looks like an address, print it in hex instead. */ + +decout (stream, type, val) + FILE *stream; + struct type *type; + LONGEST val; +{ + long lv = val; + + switch (output_radix) + { + case 0: + if ((lv == val || (unsigned) lv == val) + && ((lv & 0xf0000000) == 0x80000000 + || ((lv & 0xf0000000) == 0xf0000000 && lv < STACK_END_ADDR))) + { + fprintf_filtered (stream, "%#x", lv); + return; + } + + case 10: + fprintf_filtered (stream, TYPE_UNSIGNED (type) ? "%llu" : "%lld", val); + return; + + case 8: + if (TYPE_LENGTH (type) <= sizeof lv) + fprintf_filtered (stream, "%#o", lv); + else + fprintf_filtered (stream, "%#llo", val); + return; + + case 16: + if (TYPE_LENGTH (type) <= sizeof lv) + fprintf_filtered (stream, "%#x", lv); + else + fprintf_filtered (stream, "%#llx", val); + return; + } +} + +/* Change the default output radix to 10 or 16, or set it to 0 (heuristic). + This command is mostly obsolete now that the print command allows + formats to apply to aggregates, but is still handy occasionally. */ + +static void +set_base_command (arg) + char *arg; +{ + int new_radix; + + if (!arg) + output_radix = 0; + else + { + new_radix = atoi (arg); + if (new_radix != 10 && new_radix != 16 && new_radix != 8) + error ("base must be 8, 10 or 16, or null"); + else output_radix = new_radix; + } +} + +/* Turn pipelining on or off in the inferior. */ + +static void +set_pipelining_command (arg) + char *arg; +{ + if (!arg) + { + sequential = !sequential; + printf_filtered ("%s\n", sequential ? "off" : "on"); + } + else if (!strcmp (arg, "on")) + sequential = 0; + else if (!strcmp (arg, "off")) + sequential = 1; + else error ("valid args are `on', to allow instructions to overlap, or\n\ +`off', to prevent it and thereby pinpoint exceptions."); +} + +/* Enable, disable, or force parallel execution in the inferior. */ + +static void +set_parallel_command (arg) + char *arg; +{ + struct rlimit rl; + int prevparallel = parallel; + + if (!strncmp (arg, "fixed", strlen (arg))) + parallel = 2; + else if (!strcmp (arg, "on")) + parallel = 1; + else if (!strcmp (arg, "off")) + parallel = 0; + else error ("valid args are `on', to allow multiple threads, or\n\ +`fixed', to force multiple threads, or\n\ +`off', to run with one thread only."); + + if ((prevparallel == 0) != (parallel == 0) && inferior_pid) + printf_filtered ("will take effect at next run.\n"); + + getrlimit (RLIMIT_CONCUR, &rl); + rl.rlim_cur = parallel ? rl.rlim_max : 1; + setrlimit (RLIMIT_CONCUR, &rl); + + if (inferior_pid) + set_fixed_scheduling (inferior_pid, parallel == 2); +} + +/* Add a new name for an existing command. */ + +static void +alias_command (arg) + char *arg; +{ + static char *aliaserr = "usage is `alias NEW OLD', no args allowed"; + char *newname = arg; + struct cmd_list_element *new, *old; + + if (!arg) + error_no_arg ("newname oldname"); + + new = lookup_cmd (&arg, cmdlist, "", -1); + if (new && !strncmp (newname, new->name, strlen (new->name))) + { + newname = new->name; + if (!(*arg == '-' + || (*arg >= 'a' && *arg <= 'z') + || (*arg >= 'A' && *arg <= 'Z') + || (*arg >= '0' && *arg <= '9'))) + error (aliaserr); + } + else + { + arg = newname; + while (*arg == '-' + || (*arg >= 'a' && *arg <= 'z') + || (*arg >= 'A' && *arg <= 'Z') + || (*arg >= '0' && *arg <= '9')) + arg++; + if (*arg != ' ' && *arg != '\t') + error (aliaserr); + *arg = '\0'; + arg++; + } + + old = lookup_cmd (&arg, cmdlist, "", 0); + + if (*arg != '\0') + error (aliaserr); + + if (new && !strncmp (newname, new->name, strlen (new->name))) + { + char *tem; + if (new->class == (int) class_user || new->class == (int) class_alias) + tem = "Redefine command \"%s\"? "; + else + tem = "Really redefine built-in command \"%s\"? "; + if (!query (tem, new->name)) + error ("Command \"%s\" not redefined.", new->name); + } + + add_com (newname, class_alias, old->function, old->doc); +} + + + +/* Print the current thread number, and any threads with signals in the + queue. */ + +thread_info () +{ + struct threadpid *p; + + if (have_inferior_p ()) + { + ps.pi_buffer = (char *) &comm_registers; + ps.pi_nbytes = sizeof comm_registers; + ps.pi_offset = 0; + ps.pi_thread = inferior_thread; + ioctl (inferior_fd, PIXRDCREGS, &ps); + } + + printf_filtered ("Current thread %d stopped with signal %d.%d (%s).\n", + inferior_thread, stop_signal, stop_sigcode, + subsig_name (stop_signal, stop_sigcode)); + + for (p = signal_stack; p->pid; p--) + printf_filtered ("Thread %d stopped with signal %d.%d (%s).\n", + p->thread, p->signo, p->subsig, + subsig_name (p->signo, p->subsig)); + + if (iscrlbit (comm_registers.crctl.lbits.cc, 64+13)) + printf_filtered ("New thread start pc %#x\n", + (long) (comm_registers.crreg.pcpsw >> 32)); +} + +/* Return string describing a signal.subcode number */ + +static char * +subsig_name (signo, subcode) + int signo, subcode; +{ + static char *subsig4[] = { + "error exit", "privileged instruction", "unknown", + "unknown", "undefined opcode", + 0}; + static char *subsig5[] = {0, + "breakpoint", "single step", "fork trap", "exec trap", "pfork trap", + "join trap", "idle trap", "last thread", "wfork trap", + "process breakpoint", "trap instruction", + 0}; + static char *subsig8[] = {0, + "int overflow", "int divide check", "float overflow", + "float divide check", "float underflow", "reserved operand", + "sqrt error", "exp error", "ln error", "sin error", "cos error", + 0}; + static char *subsig10[] = {0, + "invalid inward ring address", "invalid outward ring call", + "invalid inward ring return", "invalid syscall gate", + "invalid rtn frame length", "invalid comm reg address", + "invalid trap gate", + 0}; + static char *subsig11[] = {0, + "read access denied", "write access denied", "execute access denied", + "segment descriptor fault", "page table fault", "data reference fault", + "i/o access denied", "levt pte invalid", + 0}; + + static char **subsig_list[] = + {0, 0, 0, 0, subsig4, subsig5, 0, 0, subsig8, 0, subsig10, subsig11, 0}; + + int i; + char *p = signo < NSIG ? sys_siglist[signo] : "unknown"; + + if (signo >= (sizeof subsig_list / sizeof *subsig_list) + || !subsig_list[signo]) + return p; + for (i = 1; subsig_list[signo][i]; i++) + if (i == subcode) + return subsig_list[signo][subcode]; + return p; +} + + +/* Print a compact display of thread status, essentially x/i $pc + for all active threads. */ + +static void +threadstat () +{ + int t; + + for (t = 0; t < n_threads; t++) + if (thread_state[t] == PI_TALIVE) + { + printf_filtered ("%d%c %08x%c %d.%d ", t, + (t == inferior_thread ? '*' : ' '), thread_pc[t], + (thread_is_in_kernel[t] ? '#' : ' '), + thread_signal[t], thread_sigcode[t]); + print_insn (thread_pc[t], stdout); + printf_filtered ("\n"); + } +} + +/* Change the current thread to ARG. */ + +set_thread_command (arg) + char *arg; +{ + int thread; + + if (!arg) + { + threadstat (); + return; + } + + thread = parse_and_eval_address (arg); + + if (thread < 0 || thread > n_threads || thread_state[thread] != PI_TALIVE) + error ("no such thread."); + + select_thread (thread); + + stop_pc = read_pc (); + flush_cached_frames (); + set_current_frame (create_new_frame (read_register (FP_REGNUM), + read_pc ())); + select_frame (get_current_frame (), 0); + print_sel_frame (1); +} + +/* Here on CONT command; gdb's dispatch address is changed to come here. + Set global variable ALL_CONTINUE to tell resume() that it should + start up all threads, and that a thread switch will not blow gdb's + mind. */ + +static void +convex_cont_command (proc_count_exp, from_tty) + char *proc_count_exp; + int from_tty; +{ + all_continue = 1; + cont_command (proc_count_exp, from_tty); +} + +/* Here on 1CONT command. Resume only the current thread. */ + +one_cont_command (proc_count_exp, from_tty) + char *proc_count_exp; + int from_tty; +{ + cont_command (proc_count_exp, from_tty); +} + +/* Print the contents and lock bits of all communication registers, + or just register ARG if ARG is a communication register, + or the 3-word resource structure in memory at address ARG. */ + +comm_registers_info (arg) + char *arg; +{ + int i, regnum; + + if (arg) + { + if (sscanf (arg, "0x%x", ®num) == 1 + || sscanf (arg, "%d", ®num) == 1) + { + if (regnum > 0) + regnum &= ~0x8000; + } + else if (sscanf (arg, "$c%d", ®num) == 1) + ; + else if (sscanf (arg, "$C%d", ®num) == 1) + ; + else + regnum = parse_and_eval_address (arg); + + if (regnum >= 64) + error ("%s: invalid register name.", arg); + + /* if we got a (user) address, examine the resource struct there */ + + if (regnum < 0) + { + static int buf[3]; + read_memory (regnum, buf, sizeof buf); + printf_filtered ("%08x %08x%08x%s\n", regnum, buf[1], buf[2], + buf[0] & 0xff ? " locked" : ""); + return; + } + } + + ps.pi_buffer = (char *) &comm_registers; + ps.pi_nbytes = sizeof comm_registers; + ps.pi_offset = 0; + ps.pi_thread = inferior_thread; + ioctl (inferior_fd, PIXRDCREGS, &ps); + + for (i = 0; i < 64; i++) + if (!arg || i == regnum) + printf_filtered ("%2d 0x8%03x %016llx%s\n", i, i, + comm_registers.crreg.r4[i], + (iscrlbit (comm_registers.crctl.lbits.cc, i) + ? " locked" : "")); +} + +/* Print the psw */ + +static void +psw_info (arg) + char *arg; +{ + struct pswbit + { + int bit; + int pos; + char *text; + }; + + static struct pswbit pswbit[] = + { + { 0x80000000, -1, "A carry" }, + { 0x40000000, -1, "A integer overflow" }, + { 0x20000000, -1, "A zero divide" }, + { 0x10000000, -1, "Integer overflow enable" }, + { 0x08000000, -1, "Trace" }, + { 0x06000000, 25, "Frame length" }, + { 0x01000000, -1, "Sequential" }, + { 0x00800000, -1, "S carry" }, + { 0x00400000, -1, "S integer overflow" }, + { 0x00200000, -1, "S zero divide" }, + { 0x00100000, -1, "Zero divide enable" }, + { 0x00080000, -1, "Floating underflow" }, + { 0x00040000, -1, "Floating overflow" }, + { 0x00020000, -1, "Floating reserved operand" }, + { 0x00010000, -1, "Floating zero divide" }, + { 0x00008000, -1, "Floating error enable" }, + { 0x00004000, -1, "Floating underflow enable" }, + { 0x00002000, -1, "IEEE" }, + { 0x00001000, -1, "Sequential stores" }, + { 0x00000800, -1, "Intrinsic error" }, + { 0x00000400, -1, "Intrinsic error enable" }, + { 0x00000200, -1, "Trace thread creates" }, + { 0x00000100, -1, "Thread init trap" }, + { 0x000000e0, 5, "Reserved" }, + { 0x0000001f, 0, "Intrinsic error code" }, + {0, 0, 0}, + }; + + long psw; + struct pswbit *p; + + if (arg) + psw = parse_and_eval_address (arg); + else + psw = read_register (PS_REGNUM); + + for (p = pswbit; p->bit; p++) + { + if (p->pos < 0) + printf_filtered ("%08x %s %s\n", p->bit, + (psw & p->bit) ? "yes" : "no ", p->text); + else + printf_filtered ("%08x %3d %s\n", p->bit, + (psw & p->bit) >> p->pos, p->text); + } +} + +_initialize_convex_dep () +{ + add_com ("alias", class_support, alias_command, + "Add a new name for an existing command."); + + add_cmd ("base", class_vars, set_base_command, + "Change the integer output radix to 8, 10 or 16\n\ +or use just `set base' with no args to return to the ad-hoc default,\n\ +which is 16 for integers that look like addresses, 10 otherwise.", + &setlist); + + add_cmd ("pipeline", class_run, set_pipelining_command, + "Enable or disable overlapped execution of instructions.\n\ +With `set pipe off', exceptions are reported with\n\ +$pc pointing at the instruction after the faulting one.\n\ +The default is `set pipe on', which runs faster.", + &setlist); + + add_cmd ("parallel", class_run, set_parallel_command, + "Enable or disable multi-threaded execution of parallel code.\n\ +`set parallel off' means run the program on a single CPU.\n\ +`set parallel fixed' means run the program with all CPUs assigned to it.\n\ +`set parallel on' means run the program on any CPUs that are available.", + &setlist); + + add_com ("1cont", class_run, one_cont_command, + "Continue the program, activating only the current thread.\n\ +Args are the same as the `cont' command."); + + add_com ("thread", class_run, set_thread_command, + "Change the current thread, the one under scrutiny and control.\n\ +With no arg, show the active threads, the current one marked with *."); + + add_info ("threads", thread_info, + "List status of active threads."); + + add_info ("comm-registers", comm_registers_info, + "List communication registers and their contents.\n\ +A communication register name as argument means describe only that register.\n\ +An address as argument means describe the resource structure at that address.\n\ +`Locked' means that the register has been sent to but not yet received from."); + + add_info ("psw", psw_info, + "Display $ps, the processor status word, bit by bit.\n\ +An argument means display that value's interpretation as a psw."); + + add_cmd ("convex", no_class, 0, "Convex-specific commands.\n\ +32-bit registers $pc $ps $sp $ap $fp $a1-5 $s0-7 $v0-7 $vl $vs $vm $c0-63\n\ +64-bit registers $S0-7 $V0-7 $C0-63\n\ +\n\ +info threads display info on stopped threads waiting to signal\n\ +thread display list of active threads\n\ +thread N select thread N (its registers, stack, memory, etc.)\n\ +step, next, etc step selected thread only\n\ +1cont continue selected thread only\n\ +cont continue all threads\n\ +info comm-registers display contents of comm register(s) or a resource struct\n\ +info psw display processor status word $ps\n\ +set base N change integer radix used by `print' without a format\n\ +set pipeline off exceptions are precise, $pc points after the faulting insn\n\ +set pipeline on normal mode, $pc is somewhere ahead of faulting insn\n\ +set parallel off program runs on a single CPU\n\ +set parallel fixed all CPUs are assigned to the program\n\ +set parallel on normal mode, parallel execution on random available CPUs\n\ +", + &cmdlist); + +} |