]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/convex-tdep.c
write.c, configure.in changes
[thirdparty/binutils-gdb.git] / gdb / convex-tdep.c
CommitLineData
dd3b648e 1/* Convex stuff for GDB.
e1a623e7 2 Copyright (C) 1990, 1991 Free Software Foundation, Inc.
dd3b648e
RP
3
4This file is part of GDB.
5
99a7de40 6This program is free software; you can redistribute it and/or modify
dd3b648e 7it under the terms of the GNU General Public License as published by
99a7de40
JG
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
dd3b648e 10
99a7de40 11This program is distributed in the hope that it will be useful,
dd3b648e
RP
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
99a7de40
JG
17along with this program; if not, write to the Free Software
18Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
dd3b648e 19
dd3b648e 20#include "defs.h"
dd3b648e
RP
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
45exec_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
136int
137xfer_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 bzero (myaddr, 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
240print_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
286static 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
306int
307is_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')
2e4964ad
FF
319 || STREQ (name, "vl")
320 || STREQ (name, "vs")
321 || STREQ (name, "vm")))
dd3b648e
RP
322 return 1;
323 else return 0;
324}
325
326/* Return the value of trapped internal variable VAR */
327
328value
329value_of_trapped_internalvar (var)
330 struct internalvar *var;
331{
332 char *name = var->name;
333 value val;
334 struct type *type;
a8a69e63 335 struct type *range_type;
dd3b648e
RP
336 long len = *read_vector_register (VL_REGNUM);
337 if (len <= 0 || len > 128) len = 128;
338
2e4964ad 339 if (STREQ (name, "vl"))
dd3b648e 340 {
06b6c733 341 val = value_from_longest (builtin_type_int,
dd3b648e
RP
342 (LONGEST) *read_vector_register_1 (VL_REGNUM));
343 }
2e4964ad 344 else if (STREQ (name, "vs"))
dd3b648e 345 {
06b6c733 346 val = value_from_longest (builtin_type_int,
dd3b648e
RP
347 (LONGEST) *read_vector_register_1 (VS_REGNUM));
348 }
2e4964ad 349 else if (STREQ (name, "vm"))
dd3b648e
RP
350 {
351 long vm[4];
352 long i, *p;
353 bcopy (read_vector_register_1 (VM_REGNUM), vm, sizeof vm);
a8a69e63
FF
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);
dd3b648e
RP
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 {
a8a69e63
FF
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);
dd3b648e
RP
370 val = allocate_value (type);
371 bcopy (read_vector_register_1 (name[1] - '0'),
372 VALUE_CONTENTS (val), TYPE_LENGTH (type));
373 }
374 else if (name[0] == 'v')
375 {
376 long *p1, *p2;
a8a69e63
FF
377 range_type =
378 create_range_type ((struct type *) NULL, builtin_type_int 0, len - 1);
379 type =
380 create_array_type ((struct type *) NULL, builtin_type_long,
381 range_type);
dd3b648e
RP
382 val = allocate_value (type);
383 p1 = read_vector_register_1 (name[1] - '0');
384 p2 = (long *) VALUE_CONTENTS (val);
385 while (--len >= 0) {p1++; *p2++ = *p1++;}
386 }
387
388 else if (name[0] == 'c')
06b6c733 389 val = value_from_longest (builtin_type_int,
dd3b648e
RP
390 read_comm_register (atoi (&name[1])));
391 else if (name[0] == 'C')
06b6c733 392 val = value_from_longest (builtin_type_long_long,
dd3b648e
RP
393 read_comm_register (atoi (&name[1])));
394
395 VALUE_LVAL (val) = lval_internalvar;
396 VALUE_INTERNALVAR (val) = var;
397 return val;
398}
399
dd3b648e
RP
400/* Handle a new value assigned to a trapped internal variable */
401
402void
403set_trapped_internalvar (var, val, bitpos, bitsize, offset)
404 struct internalvar *var;
405 value val;
406 int bitpos, bitsize, offset;
407{
408 char *name = var->name;
409 long long newval = value_as_long (val);
410
2e4964ad 411 if (STREQ (name, "vl"))
dd3b648e 412 write_vector_register (VL_REGNUM, 0, newval);
2e4964ad 413 else if (STREQ (name, "vs"))
dd3b648e
RP
414 write_vector_register (VS_REGNUM, 0, newval);
415 else if (name[0] == 'c' || name[0] == 'C')
416 write_comm_register (atoi (&name[1]), newval);
2e4964ad 417 else if (STREQ (name, "vm"))
dd3b648e
RP
418 error ("can't assign to $vm");
419 else
420 {
421 offset /= bitsize / 8;
422 write_vector_register (name[1] - '0', offset, newval);
423 }
424}
425
426/* Print an integer value when no format was specified. gdb normally
427 prints these values in decimal, but the the leading 0x80000000 of
428 pointers produces intolerable 10-digit negative numbers.
429 If it looks like an address, print it in hex instead. */
430
431decout (stream, type, val)
432 FILE *stream;
433 struct type *type;
434 LONGEST val;
435{
436 long lv = val;
437
438 switch (output_radix)
439 {
440 case 0:
441 if ((lv == val || (unsigned) lv == val)
442 && ((lv & 0xf0000000) == 0x80000000
443 || ((lv & 0xf0000000) == 0xf0000000 && lv < STACK_END_ADDR)))
444 {
445 fprintf_filtered (stream, "%#x", lv);
446 return;
447 }
448
449 case 10:
450 fprintf_filtered (stream, TYPE_UNSIGNED (type) ? "%llu" : "%lld", val);
451 return;
452
453 case 8:
454 if (TYPE_LENGTH (type) <= sizeof lv)
455 fprintf_filtered (stream, "%#o", lv);
456 else
457 fprintf_filtered (stream, "%#llo", val);
458 return;
459
460 case 16:
461 if (TYPE_LENGTH (type) <= sizeof lv)
462 fprintf_filtered (stream, "%#x", lv);
463 else
464 fprintf_filtered (stream, "%#llx", val);
465 return;
466 }
467}
468
469/* Change the default output radix to 10 or 16, or set it to 0 (heuristic).
470 This command is mostly obsolete now that the print command allows
471 formats to apply to aggregates, but is still handy occasionally. */
472
473static void
474set_base_command (arg)
475 char *arg;
476{
477 int new_radix;
478
479 if (!arg)
480 output_radix = 0;
481 else
482 {
483 new_radix = atoi (arg);
484 if (new_radix != 10 && new_radix != 16 && new_radix != 8)
485 error ("base must be 8, 10 or 16, or null");
486 else output_radix = new_radix;
487 }
488}
489
490/* Turn pipelining on or off in the inferior. */
491
492static void
493set_pipelining_command (arg)
494 char *arg;
495{
496 if (!arg)
497 {
498 sequential = !sequential;
499 printf_filtered ("%s\n", sequential ? "off" : "on");
500 }
2e4964ad 501 else if (STREQ (arg, "on"))
dd3b648e 502 sequential = 0;
2e4964ad 503 else if (STREQ (arg, "off"))
dd3b648e
RP
504 sequential = 1;
505 else error ("valid args are `on', to allow instructions to overlap, or\n\
506`off', to prevent it and thereby pinpoint exceptions.");
507}
508
509/* Enable, disable, or force parallel execution in the inferior. */
510
511static void
512set_parallel_command (arg)
513 char *arg;
514{
515 struct rlimit rl;
516 int prevparallel = parallel;
517
518 if (!strncmp (arg, "fixed", strlen (arg)))
519 parallel = 2;
2e4964ad 520 else if (STREQ (arg, "on"))
dd3b648e 521 parallel = 1;
2e4964ad 522 else if (STREQ (arg, "off"))
dd3b648e
RP
523 parallel = 0;
524 else error ("valid args are `on', to allow multiple threads, or\n\
525`fixed', to force multiple threads, or\n\
526`off', to run with one thread only.");
527
528 if ((prevparallel == 0) != (parallel == 0) && inferior_pid)
529 printf_filtered ("will take effect at next run.\n");
530
531 getrlimit (RLIMIT_CONCUR, &rl);
532 rl.rlim_cur = parallel ? rl.rlim_max : 1;
533 setrlimit (RLIMIT_CONCUR, &rl);
534
535 if (inferior_pid)
536 set_fixed_scheduling (inferior_pid, parallel == 2);
537}
538
539/* Add a new name for an existing command. */
540
541static void
542alias_command (arg)
543 char *arg;
544{
545 static char *aliaserr = "usage is `alias NEW OLD', no args allowed";
546 char *newname = arg;
547 struct cmd_list_element *new, *old;
548
549 if (!arg)
550 error_no_arg ("newname oldname");
551
552 new = lookup_cmd (&arg, cmdlist, "", -1);
553 if (new && !strncmp (newname, new->name, strlen (new->name)))
554 {
555 newname = new->name;
556 if (!(*arg == '-'
557 || (*arg >= 'a' && *arg <= 'z')
558 || (*arg >= 'A' && *arg <= 'Z')
559 || (*arg >= '0' && *arg <= '9')))
560 error (aliaserr);
561 }
562 else
563 {
564 arg = newname;
565 while (*arg == '-'
566 || (*arg >= 'a' && *arg <= 'z')
567 || (*arg >= 'A' && *arg <= 'Z')
568 || (*arg >= '0' && *arg <= '9'))
569 arg++;
570 if (*arg != ' ' && *arg != '\t')
571 error (aliaserr);
572 *arg = '\0';
573 arg++;
574 }
575
576 old = lookup_cmd (&arg, cmdlist, "", 0);
577
578 if (*arg != '\0')
579 error (aliaserr);
580
581 if (new && !strncmp (newname, new->name, strlen (new->name)))
582 {
583 char *tem;
584 if (new->class == (int) class_user || new->class == (int) class_alias)
585 tem = "Redefine command \"%s\"? ";
586 else
587 tem = "Really redefine built-in command \"%s\"? ";
588 if (!query (tem, new->name))
589 error ("Command \"%s\" not redefined.", new->name);
590 }
591
592 add_com (newname, class_alias, old->function, old->doc);
593}
594
595
596
597/* Print the current thread number, and any threads with signals in the
598 queue. */
599
600thread_info ()
601{
602 struct threadpid *p;
603
604 if (have_inferior_p ())
605 {
606 ps.pi_buffer = (char *) &comm_registers;
607 ps.pi_nbytes = sizeof comm_registers;
608 ps.pi_offset = 0;
609 ps.pi_thread = inferior_thread;
610 ioctl (inferior_fd, PIXRDCREGS, &ps);
611 }
612
613 printf_filtered ("Current thread %d stopped with signal %d.%d (%s).\n",
614 inferior_thread, stop_signal, stop_sigcode,
615 subsig_name (stop_signal, stop_sigcode));
616
617 for (p = signal_stack; p->pid; p--)
618 printf_filtered ("Thread %d stopped with signal %d.%d (%s).\n",
619 p->thread, p->signo, p->subsig,
620 subsig_name (p->signo, p->subsig));
621
622 if (iscrlbit (comm_registers.crctl.lbits.cc, 64+13))
623 printf_filtered ("New thread start pc %#x\n",
624 (long) (comm_registers.crreg.pcpsw >> 32));
625}
626
627/* Return string describing a signal.subcode number */
628
629static char *
630subsig_name (signo, subcode)
631 int signo, subcode;
632{
633 static char *subsig4[] = {
634 "error exit", "privileged instruction", "unknown",
635 "unknown", "undefined opcode",
636 0};
637 static char *subsig5[] = {0,
638 "breakpoint", "single step", "fork trap", "exec trap", "pfork trap",
639 "join trap", "idle trap", "last thread", "wfork trap",
640 "process breakpoint", "trap instruction",
641 0};
642 static char *subsig8[] = {0,
643 "int overflow", "int divide check", "float overflow",
644 "float divide check", "float underflow", "reserved operand",
645 "sqrt error", "exp error", "ln error", "sin error", "cos error",
646 0};
647 static char *subsig10[] = {0,
648 "invalid inward ring address", "invalid outward ring call",
649 "invalid inward ring return", "invalid syscall gate",
650 "invalid rtn frame length", "invalid comm reg address",
651 "invalid trap gate",
652 0};
653 static char *subsig11[] = {0,
654 "read access denied", "write access denied", "execute access denied",
655 "segment descriptor fault", "page table fault", "data reference fault",
656 "i/o access denied", "levt pte invalid",
657 0};
658
659 static char **subsig_list[] =
660 {0, 0, 0, 0, subsig4, subsig5, 0, 0, subsig8, 0, subsig10, subsig11, 0};
661
662 int i;
4ace50a5 663 char *p;
dd3b648e 664
4ace50a5
FF
665 if ((p = strsignal (signo)) == NULL)
666 p = "unknown";
dd3b648e
RP
667 if (signo >= (sizeof subsig_list / sizeof *subsig_list)
668 || !subsig_list[signo])
669 return p;
670 for (i = 1; subsig_list[signo][i]; i++)
671 if (i == subcode)
672 return subsig_list[signo][subcode];
673 return p;
674}
675
676
677/* Print a compact display of thread status, essentially x/i $pc
678 for all active threads. */
679
680static void
681threadstat ()
682{
683 int t;
684
685 for (t = 0; t < n_threads; t++)
686 if (thread_state[t] == PI_TALIVE)
687 {
688 printf_filtered ("%d%c %08x%c %d.%d ", t,
689 (t == inferior_thread ? '*' : ' '), thread_pc[t],
690 (thread_is_in_kernel[t] ? '#' : ' '),
691 thread_signal[t], thread_sigcode[t]);
692 print_insn (thread_pc[t], stdout);
693 printf_filtered ("\n");
694 }
695}
696
697/* Change the current thread to ARG. */
698
699set_thread_command (arg)
700 char *arg;
701{
702 int thread;
703
704 if (!arg)
705 {
706 threadstat ();
707 return;
708 }
709
710 thread = parse_and_eval_address (arg);
711
712 if (thread < 0 || thread > n_threads || thread_state[thread] != PI_TALIVE)
713 error ("no such thread.");
714
715 select_thread (thread);
716
717 stop_pc = read_pc ();
718 flush_cached_frames ();
719 set_current_frame (create_new_frame (read_register (FP_REGNUM),
720 read_pc ()));
721 select_frame (get_current_frame (), 0);
cadbb07a 722 print_stack_frame (selected_frame, selected_frame_level, -1);
dd3b648e
RP
723}
724
725/* Here on CONT command; gdb's dispatch address is changed to come here.
726 Set global variable ALL_CONTINUE to tell resume() that it should
727 start up all threads, and that a thread switch will not blow gdb's
728 mind. */
729
730static void
731convex_cont_command (proc_count_exp, from_tty)
732 char *proc_count_exp;
733 int from_tty;
734{
735 all_continue = 1;
736 cont_command (proc_count_exp, from_tty);
737}
738
739/* Here on 1CONT command. Resume only the current thread. */
740
741one_cont_command (proc_count_exp, from_tty)
742 char *proc_count_exp;
743 int from_tty;
744{
745 cont_command (proc_count_exp, from_tty);
746}
747
748/* Print the contents and lock bits of all communication registers,
749 or just register ARG if ARG is a communication register,
750 or the 3-word resource structure in memory at address ARG. */
751
752comm_registers_info (arg)
753 char *arg;
754{
755 int i, regnum;
756
757 if (arg)
758 {
e1a623e7 759 if (sscanf (arg, "$c%d", &regnum) == 1) {
dd3b648e 760 ;
e1a623e7 761 } else if (sscanf (arg, "$C%d", &regnum) == 1) {
dd3b648e 762 ;
e1a623e7 763 } else {
dd3b648e 764 regnum = parse_and_eval_address (arg);
e1a623e7
JG
765 if (regnum > 0)
766 regnum &= ~0x8000;
767 }
dd3b648e
RP
768
769 if (regnum >= 64)
770 error ("%s: invalid register name.", arg);
771
772 /* if we got a (user) address, examine the resource struct there */
773
774 if (regnum < 0)
775 {
776 static int buf[3];
777 read_memory (regnum, buf, sizeof buf);
778 printf_filtered ("%08x %08x%08x%s\n", regnum, buf[1], buf[2],
779 buf[0] & 0xff ? " locked" : "");
780 return;
781 }
782 }
783
784 ps.pi_buffer = (char *) &comm_registers;
785 ps.pi_nbytes = sizeof comm_registers;
786 ps.pi_offset = 0;
787 ps.pi_thread = inferior_thread;
788 ioctl (inferior_fd, PIXRDCREGS, &ps);
789
790 for (i = 0; i < 64; i++)
791 if (!arg || i == regnum)
792 printf_filtered ("%2d 0x8%03x %016llx%s\n", i, i,
793 comm_registers.crreg.r4[i],
794 (iscrlbit (comm_registers.crctl.lbits.cc, i)
795 ? " locked" : ""));
796}
797
798/* Print the psw */
799
800static void
801psw_info (arg)
802 char *arg;
803{
804 struct pswbit
805 {
806 int bit;
807 int pos;
808 char *text;
809 };
810
811 static struct pswbit pswbit[] =
812 {
813 { 0x80000000, -1, "A carry" },
814 { 0x40000000, -1, "A integer overflow" },
815 { 0x20000000, -1, "A zero divide" },
816 { 0x10000000, -1, "Integer overflow enable" },
817 { 0x08000000, -1, "Trace" },
818 { 0x06000000, 25, "Frame length" },
819 { 0x01000000, -1, "Sequential" },
820 { 0x00800000, -1, "S carry" },
821 { 0x00400000, -1, "S integer overflow" },
822 { 0x00200000, -1, "S zero divide" },
823 { 0x00100000, -1, "Zero divide enable" },
824 { 0x00080000, -1, "Floating underflow" },
825 { 0x00040000, -1, "Floating overflow" },
826 { 0x00020000, -1, "Floating reserved operand" },
827 { 0x00010000, -1, "Floating zero divide" },
828 { 0x00008000, -1, "Floating error enable" },
829 { 0x00004000, -1, "Floating underflow enable" },
830 { 0x00002000, -1, "IEEE" },
831 { 0x00001000, -1, "Sequential stores" },
832 { 0x00000800, -1, "Intrinsic error" },
833 { 0x00000400, -1, "Intrinsic error enable" },
834 { 0x00000200, -1, "Trace thread creates" },
835 { 0x00000100, -1, "Thread init trap" },
836 { 0x000000e0, 5, "Reserved" },
837 { 0x0000001f, 0, "Intrinsic error code" },
838 {0, 0, 0},
839 };
840
841 long psw;
842 struct pswbit *p;
843
844 if (arg)
845 psw = parse_and_eval_address (arg);
846 else
847 psw = read_register (PS_REGNUM);
848
849 for (p = pswbit; p->bit; p++)
850 {
851 if (p->pos < 0)
852 printf_filtered ("%08x %s %s\n", p->bit,
853 (psw & p->bit) ? "yes" : "no ", p->text);
854 else
855 printf_filtered ("%08x %3d %s\n", p->bit,
856 (psw & p->bit) >> p->pos, p->text);
857 }
858}
859\f
860_initialize_convex_dep ()
861{
862 add_com ("alias", class_support, alias_command,
863 "Add a new name for an existing command.");
864
865 add_cmd ("base", class_vars, set_base_command,
866 "Change the integer output radix to 8, 10 or 16\n\
867or use just `set base' with no args to return to the ad-hoc default,\n\
868which is 16 for integers that look like addresses, 10 otherwise.",
869 &setlist);
870
871 add_cmd ("pipeline", class_run, set_pipelining_command,
872 "Enable or disable overlapped execution of instructions.\n\
873With `set pipe off', exceptions are reported with\n\
874$pc pointing at the instruction after the faulting one.\n\
875The default is `set pipe on', which runs faster.",
876 &setlist);
877
878 add_cmd ("parallel", class_run, set_parallel_command,
879 "Enable or disable multi-threaded execution of parallel code.\n\
880`set parallel off' means run the program on a single CPU.\n\
881`set parallel fixed' means run the program with all CPUs assigned to it.\n\
882`set parallel on' means run the program on any CPUs that are available.",
883 &setlist);
884
885 add_com ("1cont", class_run, one_cont_command,
886 "Continue the program, activating only the current thread.\n\
887Args are the same as the `cont' command.");
888
889 add_com ("thread", class_run, set_thread_command,
890 "Change the current thread, the one under scrutiny and control.\n\
891With no arg, show the active threads, the current one marked with *.");
892
893 add_info ("threads", thread_info,
894 "List status of active threads.");
895
896 add_info ("comm-registers", comm_registers_info,
897 "List communication registers and their contents.\n\
898A communication register name as argument means describe only that register.\n\
899An address as argument means describe the resource structure at that address.\n\
900`Locked' means that the register has been sent to but not yet received from.");
901
902 add_info ("psw", psw_info,
903 "Display $ps, the processor status word, bit by bit.\n\
904An argument means display that value's interpretation as a psw.");
905
906 add_cmd ("convex", no_class, 0, "Convex-specific commands.\n\
90732-bit registers $pc $ps $sp $ap $fp $a1-5 $s0-7 $v0-7 $vl $vs $vm $c0-63\n\
90864-bit registers $S0-7 $V0-7 $C0-63\n\
909\n\
910info threads display info on stopped threads waiting to signal\n\
911thread display list of active threads\n\
912thread N select thread N (its registers, stack, memory, etc.)\n\
913step, next, etc step selected thread only\n\
9141cont continue selected thread only\n\
915cont continue all threads\n\
916info comm-registers display contents of comm register(s) or a resource struct\n\
917info psw display processor status word $ps\n\
918set base N change integer radix used by `print' without a format\n\
919set pipeline off exceptions are precise, $pc points after the faulting insn\n\
920set pipeline on normal mode, $pc is somewhere ahead of faulting insn\n\
921set parallel off program runs on a single CPU\n\
922set parallel fixed all CPUs are assigned to the program\n\
923set parallel on normal mode, parallel execution on random available CPUs\n\
924",
925 &cmdlist);
926
927}