]> Git Repo - binutils.git/blob - gdb/convex-tdep.c
Modified Files:
[binutils.git] / gdb / convex-tdep.c
1 /* Convex stuff for GDB.
2    Copyright (C) 1990, 1991 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include "defs.h"
21 #include "command.h"
22 #include "symtab.h"
23 #include "value.h"
24 #include "frame.h"
25 #include "inferior.h"
26 #include "wait.h"
27
28 #include <signal.h>
29 #include <fcntl.h>
30
31 #include "gdbcore.h"
32 #include <sys/param.h>
33 #include <sys/dir.h>
34 #include <sys/user.h>
35 #include <sys/ioctl.h>
36 #include <sys/pcntl.h>
37 #include <sys/thread.h>
38 #include <sys/proc.h>
39 #include <sys/file.h>
40 #include <sys/stat.h>
41 #include <sys/mman.h>
42
43 #include "gdbcmd.h"
44
45 exec_file_command (filename, from_tty)
46      char *filename;
47      int from_tty;
48 {
49   int val;
50   int n;
51   struct stat st_exec;
52
53   /* Eliminate all traces of old exec file.
54      Mark text segment as empty.  */
55
56   if (execfile)
57     free (execfile);
58   execfile = 0;
59   data_start = 0;
60   data_end = 0;
61   text_start = 0;
62   text_end = 0;
63   exec_data_start = 0;
64   exec_data_end = 0;
65   if (execchan >= 0)
66     close (execchan);
67   execchan = -1;
68
69   n_exec = 0;
70
71   /* Now open and digest the file the user requested, if any.  */
72
73   if (filename)
74     {
75       filename = tilde_expand (filename);
76       make_cleanup (free, filename);
77       
78       execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
79                         &execfile);
80       if (execchan < 0)
81         perror_with_name (filename);
82
83       if (myread (execchan, &filehdr, sizeof filehdr) < 0)
84         perror_with_name (filename);
85
86       if (! IS_SOFF_MAGIC (filehdr.h_magic))
87         error ("%s: not an executable file.", filename);
88
89       if (myread (execchan, &opthdr, filehdr.h_opthdr) <= 0)
90         perror_with_name (filename);
91
92       /* Read through the section headers.
93          For text, data, etc, record an entry in the exec file map.
94          Record text_start and text_end.  */
95
96       lseek (execchan, (long) filehdr.h_scnptr, 0);
97
98       for (n = 0; n < filehdr.h_nscns; n++)
99         {
100           if (myread (execchan, &scnhdr, sizeof scnhdr) < 0)
101             perror_with_name (filename);
102
103           if ((scnhdr.s_flags & S_TYPMASK) >= S_TEXT
104               && (scnhdr.s_flags & S_TYPMASK) <= S_COMON)
105             {
106               exec_map[n_exec].mem_addr = scnhdr.s_vaddr;
107               exec_map[n_exec].mem_end = scnhdr.s_vaddr + scnhdr.s_size;
108               exec_map[n_exec].file_addr = scnhdr.s_scnptr;
109               exec_map[n_exec].type = scnhdr.s_flags & S_TYPMASK;
110               n_exec++;
111
112               if ((scnhdr.s_flags & S_TYPMASK) == S_TEXT)
113                 {
114                   text_start = scnhdr.s_vaddr;
115                   text_end =  scnhdr.s_vaddr + scnhdr.s_size;
116                 }
117             }
118         }
119
120       fstat (execchan, &st_exec);
121       exec_mtime = st_exec.st_mtime;
122       
123       validate_files ();
124     }
125   else if (from_tty)
126     printf_filtered ("No exec file now.\n");
127
128   /* Tell display code (if any) about the changed file name.  */
129   if (exec_file_display_hook)
130     (*exec_file_display_hook) (filename);
131 }
132
133 /* Read data from SOFF exec or core file.
134    Return 0 on success, EIO if address out of bounds. */
135
136 int
137 xfer_core_file (memaddr, myaddr, len)
138      CORE_ADDR memaddr;
139      char *myaddr;
140      int len;
141 {
142   register int i;
143   register int n;
144   register int val;
145   int xferchan;
146   char **xferfile;
147   int fileptr;
148   int returnval = 0;
149
150   while (len > 0)
151     {
152       xferfile = 0;
153       xferchan = 0;
154
155       /* Determine which file the next bunch of addresses reside in,
156          and where in the file.  Set the file's read/write pointer
157          to point at the proper place for the desired address
158          and set xferfile and xferchan for the correct file.
159          If desired address is nonexistent, leave them zero.
160          i is set to the number of bytes that can be handled
161          along with the next address.  */
162
163       i = len;
164
165       for (n = 0; n < n_core; n++)
166         {
167           if (memaddr >= core_map[n].mem_addr && memaddr < core_map[n].mem_end
168               && (core_map[n].thread == -1
169                   || core_map[n].thread == inferior_thread))
170             {
171               i = min (len, core_map[n].mem_end - memaddr);
172               fileptr = core_map[n].file_addr + memaddr - core_map[n].mem_addr;
173               if (core_map[n].file_addr)
174                 {
175                   xferfile = &corefile;
176                   xferchan = corechan;
177                 }
178               break;
179             }
180           else if (core_map[n].mem_addr >= memaddr
181                    && core_map[n].mem_addr < memaddr + i)
182             i = core_map[n].mem_addr - memaddr;
183         }
184
185       if (!xferfile) 
186         for (n = 0; n < n_exec; n++)
187           {
188             if (memaddr >= exec_map[n].mem_addr
189                 && memaddr < exec_map[n].mem_end)
190               {
191                 i = min (len, exec_map[n].mem_end - memaddr);
192                 fileptr = exec_map[n].file_addr + memaddr
193                   - exec_map[n].mem_addr;
194                 if (exec_map[n].file_addr)
195                   {
196                     xferfile = &execfile;
197                     xferchan = execchan;
198                   }
199                 break;
200               }
201             else if (exec_map[n].mem_addr >= memaddr
202                      && exec_map[n].mem_addr < memaddr + i)
203               i = exec_map[n].mem_addr - memaddr;
204           }
205
206       /* Now we know which file to use.
207          Set up its pointer and transfer the data.  */
208       if (xferfile)
209         {
210           if (*xferfile == 0)
211             if (xferfile == &execfile)
212               error ("No program file to examine.");
213             else
214               error ("No core dump file or running program to examine.");
215           val = lseek (xferchan, fileptr, 0);
216           if (val < 0)
217             perror_with_name (*xferfile);
218           val = myread (xferchan, myaddr, i);
219           if (val < 0)
220             perror_with_name (*xferfile);
221         }
222       /* If this address is for nonexistent memory,
223          read zeros if reading, or do nothing if writing.  */
224       else
225         {
226           memset (myaddr, '\0', i);
227           returnval = EIO;
228         }
229
230       memaddr += i;
231       myaddr += i;
232       len -= i;
233     }
234   return returnval;
235 }
236
237
238 /* Here from info files command to print an address map.  */
239
240 print_maps ()
241 {
242   struct pmap ptrs[200];
243   int n;
244
245   /* ID strings for core and executable file sections */
246
247   static char *idstr[] =
248     {
249       "0", "text", "data", "tdata", "bss", "tbss", 
250       "common", "ttext", "ctx", "tctx", "10", "11", "12",
251     };
252
253   for (n = 0; n < n_core; n++)
254     {
255       core_map[n].which = 0;
256       ptrs[n] = core_map[n];
257     }
258   for (n = 0; n < n_exec; n++)
259     {
260       exec_map[n].which = 1;
261       ptrs[n_core+n] = exec_map[n];
262     }
263
264   qsort (ptrs, n_core + n_exec, sizeof *ptrs, ptr_cmp);
265
266   for (n = 0; n < n_core + n_exec; n++)
267     {
268       struct pmap *p = &ptrs[n];
269       if (n > 0)
270         {
271           if (p->mem_addr < ptrs[n-1].mem_end)
272             p->mem_addr = ptrs[n-1].mem_end;
273           if (p->mem_addr >= p->mem_end)
274             continue;
275         }
276       printf_filtered ("%08x .. %08x  %-6s  %s\n",
277                        p->mem_addr, p->mem_end, idstr[p->type],
278                        p->which ? execfile : corefile);
279     }
280 }
281
282 /* Compare routine to put file sections in order.
283    Sort into increasing order on address, and put core file sections
284    before exec file sections if both files contain the same addresses.  */
285
286 static ptr_cmp (a, b)
287      struct pmap *a, *b;
288 {
289   if (a->mem_addr != b->mem_addr) return a->mem_addr - b->mem_addr;
290   return a->which - b->which;
291 }
292 \f
293 /* Trapped internal variables are used to handle special registers.
294    A trapped i.v. calls a hook here every time it is dereferenced,
295    to provide a new value for the variable, and it calls a hook here
296    when a new value is assigned, to do something with the value.
297    
298    The vector registers are $vl, $vs, $vm, $vN, $VN (N in 0..7).
299    The communication registers are $cN, $CN (N in 0..63).
300    They not handled as regular registers because it's expensive to
301    read them, and their size varies, and they have too many names.  */
302
303
304 /* Return 1 if NAME is a trapped internal variable, else 0. */
305
306 int
307 is_trapped_internalvar (name)
308      char *name;
309 {
310     if ((name[0] == 'c' || name[0] == 'C')
311         && name[1] >= '0' && name[1] <= '9'
312         && (name[2] == '\0'
313             || (name[2] >= '0' && name[2] <= '9'
314                 && name[3] == '\0' && name[1] != '0'))
315         && atoi (&name[1]) < 64) return 1;
316
317   if ((name[0] == 'v' || name[0] == 'V')
318       && (((name[1] & -8) == '0' && name[2] == '\0')
319           || STREQ (name, "vl")
320           || STREQ (name, "vs") 
321           || STREQ (name, "vm")))
322     return 1;
323   else return 0;
324 }
325
326 /* Return the value of trapped internal variable VAR */
327
328 value
329 value_of_trapped_internalvar (var)
330      struct internalvar *var;
331 {
332   char *name = var->name;
333   value val;
334   struct type *type;
335   struct type *range_type;
336   long len = *read_vector_register (VL_REGNUM);
337   if (len <= 0 || len > 128) len = 128;
338
339   if (STREQ (name, "vl"))
340     {
341       val = value_from_longest (builtin_type_int,
342                              (LONGEST) *read_vector_register_1 (VL_REGNUM));
343     }
344   else if (STREQ (name, "vs"))
345     {
346       val = value_from_longest (builtin_type_int,
347                              (LONGEST) *read_vector_register_1 (VS_REGNUM));
348     }
349   else if (STREQ (name, "vm"))
350     {
351       long vm[4];
352       long i, *p;
353       memcpy (vm, read_vector_register_1 (VM_REGNUM), sizeof vm);
354       range_type =
355         create_range_type ((struct type *) NULL, builtin_type_int, 0, len - 1);
356       type =
357         create_array_type ((struct type *) NULL, builtin_type_int, range_type);
358       val = allocate_value (type);
359       p = (long *) VALUE_CONTENTS (val);
360       for (i = 0; i < len; i++) 
361         *p++ = !! (vm[3 - (i >> 5)] & (1 << (i & 037)));
362     }
363   else if (name[0] == 'V')
364     {
365       range_type =
366         create_range_type ((struct type *) NULL, builtin_type_int 0, len - 1);
367       type =
368         create_array_type ((struct type *) NULL, builtin_type_long_long,
369                            range_type);
370       val = allocate_value (type);
371       memcpy (VALUE_CONTENTS (val),
372              read_vector_register_1 (name[1] - '0'),
373              TYPE_LENGTH (type));
374     }
375   else if (name[0] == 'v')
376     {
377       long *p1, *p2;
378       range_type =
379         create_range_type ((struct type *) NULL, builtin_type_int 0, len - 1);
380       type =
381         create_array_type ((struct type *) NULL, builtin_type_long,
382                            range_type);
383       val = allocate_value (type);
384       p1 = read_vector_register_1 (name[1] - '0');
385       p2 = (long *) VALUE_CONTENTS (val);
386       while (--len >= 0) {p1++; *p2++ = *p1++;}
387     }
388
389   else if (name[0] == 'c')
390     val = value_from_longest (builtin_type_int,
391                            read_comm_register (atoi (&name[1])));
392   else if (name[0] == 'C')
393     val = value_from_longest (builtin_type_long_long,
394                            read_comm_register (atoi (&name[1])));
395
396   VALUE_LVAL (val) = lval_internalvar;
397   VALUE_INTERNALVAR (val) = var;
398   return val;
399 }
400
401 /* Handle a new value assigned to a trapped internal variable */
402
403 void
404 set_trapped_internalvar (var, val, bitpos, bitsize, offset)
405      struct internalvar *var;
406      value val;
407      int bitpos, bitsize, offset;
408
409   char *name = var->name;
410   long long newval = value_as_long (val);
411
412   if (STREQ (name, "vl")) 
413     write_vector_register (VL_REGNUM, 0, newval);
414   else if (STREQ (name, "vs"))
415     write_vector_register (VS_REGNUM, 0, newval);
416   else if (name[0] == 'c' || name[0] == 'C')
417     write_comm_register (atoi (&name[1]), newval);
418   else if (STREQ (name, "vm"))
419     error ("can't assign to $vm");
420   else
421     {
422       offset /= bitsize / 8;
423       write_vector_register (name[1] - '0', offset, newval);
424     }
425 }
426
427 /* Print an integer value when no format was specified.  gdb normally
428    prints these values in decimal, but the the leading 0x80000000 of
429    pointers produces intolerable 10-digit negative numbers.
430    If it looks like an address, print it in hex instead.  */
431
432 decout (stream, type, val)
433      FILE *stream;
434      struct type *type;
435      LONGEST val;
436 {
437   long lv = val;
438
439   switch (output_radix)
440     {
441     case 0:
442       if ((lv == val || (unsigned) lv == val)
443           && ((lv & 0xf0000000) == 0x80000000
444               || ((lv & 0xf0000000) == 0xf0000000 && lv < STACK_END_ADDR)))
445         {
446           fprintf_filtered (stream, "%#x", lv);
447           return;
448         }
449
450     case 10:
451       fprintf_filtered (stream, TYPE_UNSIGNED (type) ? "%llu" : "%lld", val);
452       return;
453
454     case 8:
455       if (TYPE_LENGTH (type) <= sizeof lv)
456         fprintf_filtered (stream, "%#o", lv);
457       else
458         fprintf_filtered (stream, "%#llo", val);
459       return;
460
461     case 16:
462       if (TYPE_LENGTH (type) <= sizeof lv)
463         fprintf_filtered (stream, "%#x", lv);
464       else
465         fprintf_filtered (stream, "%#llx", val);
466       return;
467     }
468 }
469
470 /* Change the default output radix to 10 or 16, or set it to 0 (heuristic).
471    This command is mostly obsolete now that the print command allows
472    formats to apply to aggregates, but is still handy occasionally.  */
473
474 static void
475 set_base_command (arg)
476     char *arg;
477 {
478   int new_radix;
479
480   if (!arg)
481     output_radix = 0;
482   else
483     {
484       new_radix = atoi (arg);
485       if (new_radix != 10 && new_radix != 16 && new_radix != 8) 
486         error ("base must be 8, 10 or 16, or null");
487       else output_radix = new_radix;
488     }
489 }
490
491 /* Turn pipelining on or off in the inferior. */
492
493 static void
494 set_pipelining_command (arg)
495     char *arg;
496 {
497   if (!arg)
498     {
499       sequential = !sequential;
500       printf_filtered ("%s\n", sequential ? "off" : "on");
501     }
502   else if (STREQ (arg, "on"))
503     sequential = 0;
504   else if (STREQ (arg, "off"))
505     sequential = 1;
506   else error ("valid args are `on', to allow instructions to overlap, or\n\
507 `off', to prevent it and thereby pinpoint exceptions.");
508 }
509
510 /* Enable, disable, or force parallel execution in the inferior.  */
511
512 static void
513 set_parallel_command (arg)
514      char *arg;
515 {
516   struct rlimit rl;
517   int prevparallel = parallel;
518
519   if (!strncmp (arg, "fixed", strlen (arg)))
520     parallel = 2;  
521   else if (STREQ (arg, "on"))
522     parallel = 1;
523   else if (STREQ (arg, "off"))
524     parallel = 0;
525   else error ("valid args are `on', to allow multiple threads, or\n\
526 `fixed', to force multiple threads, or\n\
527 `off', to run with one thread only.");
528
529   if ((prevparallel == 0) != (parallel == 0) && inferior_pid)
530     printf_filtered ("will take effect at next run.\n");
531
532   getrlimit (RLIMIT_CONCUR, &rl);
533   rl.rlim_cur = parallel ? rl.rlim_max : 1;
534   setrlimit (RLIMIT_CONCUR, &rl);
535
536   if (inferior_pid)
537     set_fixed_scheduling (inferior_pid, parallel == 2);
538 }
539
540 /* Add a new name for an existing command.  */
541
542 static void 
543 alias_command (arg)
544     char *arg;
545 {
546     static char *aliaserr = "usage is `alias NEW OLD', no args allowed";
547     char *newname = arg;
548     struct cmd_list_element *new, *old;
549
550     if (!arg)
551       error_no_arg ("newname oldname");
552         
553     new = lookup_cmd (&arg, cmdlist, "", -1);
554     if (new && !strncmp (newname, new->name, strlen (new->name)))
555       {
556         newname = new->name;
557         if (!(*arg == '-' 
558               || (*arg >= 'a' && *arg <= 'z')
559               || (*arg >= 'A' && *arg <= 'Z')
560               || (*arg >= '0' && *arg <= '9')))
561           error (aliaserr);
562       }
563     else
564       {
565         arg = newname;
566         while (*arg == '-' 
567                || (*arg >= 'a' && *arg <= 'z')
568                || (*arg >= 'A' && *arg <= 'Z')
569                || (*arg >= '0' && *arg <= '9'))
570           arg++;
571         if (*arg != ' ' && *arg != '\t')
572           error (aliaserr);
573         *arg = '\0';
574         arg++;
575       }
576
577     old = lookup_cmd (&arg, cmdlist, "", 0);
578
579     if (*arg != '\0')
580       error (aliaserr);
581
582     if (new && !strncmp (newname, new->name, strlen (new->name)))
583       {
584         char *tem;
585         if (new->class == (int) class_user || new->class == (int) class_alias)
586           tem = "Redefine command \"%s\"? ";
587         else
588           tem = "Really redefine built-in command \"%s\"? ";
589         if (!query (tem, new->name))
590           error ("Command \"%s\" not redefined.", new->name);
591       }
592
593     add_com (newname, class_alias, old->function, old->doc);
594 }
595
596
597
598 /* Print the current thread number, and any threads with signals in the
599    queue.  */
600
601 thread_info ()
602 {
603   struct threadpid *p;
604
605   if (have_inferior_p ())
606     {
607       ps.pi_buffer = (char *) &comm_registers;
608       ps.pi_nbytes = sizeof comm_registers;
609       ps.pi_offset = 0;
610       ps.pi_thread = inferior_thread;
611       ioctl (inferior_fd, PIXRDCREGS, &ps);
612     }
613
614   /* FIXME: stop_signal is from target.h but stop_sigcode is a
615      convex-specific thing.  */
616   printf_filtered ("Current thread %d stopped with signal %d.%d (%s).\n",
617                    inferior_thread, stop_signal, stop_sigcode,
618                    subsig_name (stop_signal, stop_sigcode));
619   
620   for (p = signal_stack; p->pid; p--)
621     printf_filtered ("Thread %d stopped with signal %d.%d (%s).\n",
622                      p->thread, p->signo, p->subsig,
623                      subsig_name (p->signo, p->subsig));
624                 
625   if (iscrlbit (comm_registers.crctl.lbits.cc, 64+13))
626     printf_filtered ("New thread start pc %#x\n",
627                      (long) (comm_registers.crreg.pcpsw >> 32));
628 }
629
630 /* Return string describing a signal.subcode number */
631
632 static char *
633 subsig_name (signo, subcode)
634      int signo, subcode;
635 {
636   static char *subsig4[] = {
637     "error exit", "privileged instruction", "unknown",
638     "unknown", "undefined opcode",
639     0};
640   static char *subsig5[] = {0,
641     "breakpoint", "single step", "fork trap", "exec trap", "pfork trap",
642     "join trap", "idle trap", "last thread", "wfork trap",
643     "process breakpoint", "trap instruction",
644     0};
645   static char *subsig8[] = {0,
646     "int overflow", "int divide check", "float overflow",
647     "float divide check", "float underflow", "reserved operand",
648     "sqrt error", "exp error", "ln error", "sin error", "cos error",
649     0};
650   static char *subsig10[] = {0,
651     "invalid inward ring address", "invalid outward ring call",
652     "invalid inward ring return", "invalid syscall gate",
653     "invalid rtn frame length", "invalid comm reg address",
654     "invalid trap gate",
655     0};
656   static char *subsig11[] = {0,
657     "read access denied", "write access denied", "execute access denied",
658     "segment descriptor fault", "page table fault", "data reference fault",
659     "i/o access denied", "levt pte invalid",
660     0};
661
662   static char **subsig_list[] = 
663     {0, 0, 0, 0, subsig4, subsig5, 0, 0, subsig8, 0, subsig10, subsig11, 0};
664
665   int i;
666   char *p;
667
668   if ((p = strsignal (signo)) == NULL)
669     p = "unknown";
670   if (signo >= (sizeof subsig_list / sizeof *subsig_list)
671       || !subsig_list[signo])
672     return p;
673   for (i = 1; subsig_list[signo][i]; i++)
674     if (i == subcode)
675       return subsig_list[signo][subcode];
676   return p;
677 }
678
679
680 /* Print a compact display of thread status, essentially x/i $pc
681    for all active threads.  */
682
683 static void
684 threadstat ()
685 {
686   int t;
687
688   for (t = 0; t < n_threads; t++)
689     if (thread_state[t] == PI_TALIVE)
690       {
691         printf_filtered ("%d%c %08x%c %d.%d ", t,
692                          (t == inferior_thread ? '*' : ' '), thread_pc[t],
693                          (thread_is_in_kernel[t] ? '#' : ' '),
694                          thread_signal[t], thread_sigcode[t]);
695         print_insn (thread_pc[t], stdout);
696         printf_filtered ("\n");
697       }
698 }
699
700 /* Change the current thread to ARG.  */
701
702 set_thread_command (arg)
703      char *arg;
704 {
705     int thread;
706
707     if (!arg)
708       {
709         threadstat ();
710         return;
711       }
712
713     thread = parse_and_eval_address (arg);
714
715     if (thread < 0 || thread > n_threads || thread_state[thread] != PI_TALIVE)
716       error ("no such thread.");
717
718     select_thread (thread);
719
720     stop_pc = read_pc ();
721     flush_cached_frames ();
722     set_current_frame (create_new_frame (read_register (FP_REGNUM),
723                                          read_pc ()));
724     select_frame (get_current_frame (), 0);
725     print_stack_frame (selected_frame, selected_frame_level, -1);
726 }
727
728 /* Here on CONT command; gdb's dispatch address is changed to come here.
729    Set global variable ALL_CONTINUE to tell resume() that it should
730    start up all threads, and that a thread switch will not blow gdb's
731    mind.  */
732
733 static void
734 convex_cont_command (proc_count_exp, from_tty)
735      char *proc_count_exp;
736      int from_tty;
737 {
738   all_continue = 1;
739   cont_command (proc_count_exp, from_tty);
740 }
741
742 /* Here on 1CONT command.  Resume only the current thread.  */
743
744 one_cont_command (proc_count_exp, from_tty)
745      char *proc_count_exp;
746      int from_tty;
747 {
748   cont_command (proc_count_exp, from_tty);
749 }
750
751 /* Print the contents and lock bits of all communication registers,
752    or just register ARG if ARG is a communication register,
753    or the 3-word resource structure in memory at address ARG.  */
754
755 comm_registers_info (arg)
756     char *arg;
757 {
758   int i, regnum;
759
760   if (arg)
761     {
762              if (sscanf (arg, "$c%d", &regnum) == 1) {
763         ;
764       } else if (sscanf (arg, "$C%d", &regnum) == 1) {
765         ;
766       } else {
767         regnum = parse_and_eval_address (arg);
768         if (regnum > 0)
769           regnum &= ~0x8000;
770       }
771
772       if (regnum >= 64)
773         error ("%s: invalid register name.", arg);
774
775       /* if we got a (user) address, examine the resource struct there */
776
777       if (regnum < 0)
778         {
779           static int buf[3];
780           read_memory (regnum, buf, sizeof buf);
781           printf_filtered ("%08x  %08x%08x%s\n", regnum, buf[1], buf[2],
782                            buf[0] & 0xff ? " locked" : "");
783           return;
784         }
785     }
786
787   ps.pi_buffer = (char *) &comm_registers;
788   ps.pi_nbytes = sizeof comm_registers;
789   ps.pi_offset = 0;
790   ps.pi_thread = inferior_thread;
791   ioctl (inferior_fd, PIXRDCREGS, &ps);
792
793   for (i = 0; i < 64; i++)
794     if (!arg || i == regnum)
795       printf_filtered ("%2d 0x8%03x %016llx%s\n", i, i,
796                        comm_registers.crreg.r4[i],
797                        (iscrlbit (comm_registers.crctl.lbits.cc, i)
798                         ? " locked" : ""));
799 }
800
801 /* Print the psw */
802
803 static void 
804 psw_info (arg)
805     char *arg;
806 {
807   struct pswbit
808     {
809       int bit;
810       int pos;
811       char *text;
812     };
813
814   static struct pswbit pswbit[] =
815     {
816       { 0x80000000, -1, "A carry" }, 
817       { 0x40000000, -1, "A integer overflow" }, 
818       { 0x20000000, -1, "A zero divide" }, 
819       { 0x10000000, -1, "Integer overflow enable" }, 
820       { 0x08000000, -1, "Trace" }, 
821       { 0x06000000, 25, "Frame length" }, 
822       { 0x01000000, -1, "Sequential" }, 
823       { 0x00800000, -1, "S carry" }, 
824       { 0x00400000, -1, "S integer overflow" }, 
825       { 0x00200000, -1, "S zero divide" }, 
826       { 0x00100000, -1, "Zero divide enable" }, 
827       { 0x00080000, -1, "Floating underflow" }, 
828       { 0x00040000, -1, "Floating overflow" }, 
829       { 0x00020000, -1, "Floating reserved operand" }, 
830       { 0x00010000, -1, "Floating zero divide" }, 
831       { 0x00008000, -1, "Floating error enable" }, 
832       { 0x00004000, -1, "Floating underflow enable" }, 
833       { 0x00002000, -1, "IEEE" }, 
834       { 0x00001000, -1, "Sequential stores" }, 
835       { 0x00000800, -1, "Intrinsic error" }, 
836       { 0x00000400, -1, "Intrinsic error enable" }, 
837       { 0x00000200, -1, "Trace thread creates" }, 
838       { 0x00000100, -1, "Thread init trap" }, 
839       { 0x000000e0,  5, "Reserved" },
840       { 0x0000001f,  0, "Intrinsic error code" },
841       {0, 0, 0},
842     };
843
844   long psw;
845   struct pswbit *p;
846
847   if (arg)
848     psw = parse_and_eval_address (arg);
849   else
850     psw = read_register (PS_REGNUM);
851
852   for (p = pswbit; p->bit; p++)
853     {
854       if (p->pos < 0)
855         printf_filtered ("%08x  %s  %s\n", p->bit,
856                          (psw & p->bit) ? "yes" : "no ", p->text);
857       else
858         printf_filtered ("%08x %3d   %s\n", p->bit,
859                          (psw & p->bit) >> p->pos, p->text);
860     }
861 }
862 \f
863 void
864 _initialize_convex_dep ()
865 {
866   add_com ("alias", class_support, alias_command,
867            "Add a new name for an existing command.");
868
869   add_cmd ("base", class_vars, set_base_command,
870            "Change the integer output radix to 8, 10 or 16\n\
871 or use just `set base' with no args to return to the ad-hoc default,\n\
872 which is 16 for integers that look like addresses, 10 otherwise.",
873            &setlist);
874
875   add_cmd ("pipeline", class_run, set_pipelining_command,
876            "Enable or disable overlapped execution of instructions.\n\
877 With `set pipe off', exceptions are reported with\n\
878 $pc pointing at the instruction after the faulting one.\n\
879 The default is `set pipe on', which runs faster.",
880            &setlist);
881
882   add_cmd ("parallel", class_run, set_parallel_command,
883            "Enable or disable multi-threaded execution of parallel code.\n\
884 `set parallel off' means run the program on a single CPU.\n\
885 `set parallel fixed' means run the program with all CPUs assigned to it.\n\
886 `set parallel on' means run the program on any CPUs that are available.",
887            &setlist);
888
889   add_com ("1cont", class_run, one_cont_command,
890            "Continue the program, activating only the current thread.\n\
891 Args are the same as the `cont' command.");
892
893   add_com ("thread", class_run, set_thread_command,
894            "Change the current thread, the one under scrutiny and control.\n\
895 With no arg, show the active threads, the current one marked with *.");
896
897   add_info ("threads", thread_info,
898             "List status of active threads.");
899
900   add_info ("comm-registers", comm_registers_info,
901             "List communication registers and their contents.\n\
902 A communication register name as argument means describe only that register.\n\
903 An address as argument means describe the resource structure at that address.\n\
904 `Locked' means that the register has been sent to but not yet received from.");
905
906   add_info ("psw", psw_info, 
907             "Display $ps, the processor status word, bit by bit.\n\
908 An argument means display that value's interpretation as a psw.");
909
910   add_cmd ("convex", no_class, 0, "Convex-specific commands.\n\
911 32-bit registers  $pc $ps $sp $ap $fp $a1-5 $s0-7 $v0-7 $vl $vs $vm $c0-63\n\
912 64-bit registers  $S0-7 $V0-7 $C0-63\n\
913 \n\
914 info threads        display info on stopped threads waiting to signal\n\
915 thread              display list of active threads\n\
916 thread N            select thread N (its registers, stack, memory, etc.)\n\
917 step, next, etc     step selected thread only\n\
918 1cont               continue selected thread only\n\
919 cont                continue all threads\n\
920 info comm-registers display contents of comm register(s) or a resource struct\n\
921 info psw            display processor status word $ps\n\
922 set base N          change integer radix used by `print' without a format\n\
923 set pipeline off    exceptions are precise, $pc points after the faulting insn\n\
924 set pipeline on     normal mode, $pc is somewhere ahead of faulting insn\n\
925 set parallel off    program runs on a single CPU\n\
926 set parallel fixed  all CPUs are assigned to the program\n\
927 set parallel on     normal mode, parallel execution on random available CPUs\n\
928 ",
929            &cmdlist);
930
931 }
This page took 0.076326 seconds and 4 git commands to generate.