1 /* SPIM S20 MIPS simulator.
2 X interface to SPIM
3 (Derived from an earlier work by Alan Siow.)
4
5 Copyright (c) 1990-2010, James R. Larus.
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
10
11 Redistributions of source code must retain the above copyright notice,
12 this list of conditions and the following disclaimer.
13
14 Redistributions in binary form must reproduce the above copyright notice,
15 this list of conditions and the following disclaimer in the documentation and/or
16 other materials provided with the distribution.
17
18 Neither the name of the James R. Larus nor the names of its contributors may be
19 used to endorse or promote products derived from this software without specific
20 prior written permission.
21
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
26 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
28 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34
35 #include <stdio.h>
36 #include <setjmp.h>
37 #include <stdarg.h>
38
39 #include <X11/Intrinsic.h>
40 #include <X11/StringDefs.h>
41 #include <X11/Shell.h>
42 #include <X11/Xlib.h>
43 #include <X11/Xaw/Cardinals.h>
44 #include <X11/Xaw/Paned.h>
45 #include <X11/Xaw/AsciiText.h>
46 #include <X11/Xaw/Text.h>
47 #include <X11/Xaw/Dialog.h>
48 #include <X11/keysym.h>
49
50 #include "spim.h"
51 #include "string-stream.h"
52 #include "spim-utils.h"
53 #include "inst.h"
54 #include "reg.h"
55 #include "mem.h"
56 #include "y.tab.h"
57 #include "buttons.h"
58 #include "windows.h"
59 #include "xspim.h"
60 #include "sym-tbl.h"
61
62
63 typedef struct _AppResources
64 {
65 String textFont;
66 Boolean bare;
67 Boolean delayed_branches;
68 Boolean delayed_loads;
69 Boolean pseudo;
70 Boolean asmm;
71 Boolean exception;
72 char *exception_file_name;
73 Boolean quiet;
74 Boolean mapped_io;
75 char *filename;
76 char *display2;
77 Boolean hex_gpr;
78 Boolean hex_fpr;
79 char *initial_data_limit;
80 char *initial_data_size;
81 char *initial_k_data_limit;
82 char *initial_k_data_size;
83 char *initial_k_text_size;
84 char *initial_stack_limit;
85 char *initial_stack_size;
86 char *initial_text_size;
87 } AppResources;
88
89
90 /* Exported variables: */
91
92 /* Not local, but not export so all files don't need setjmp.h */
93 jmp_buf spim_top_level_env; /* For ^C */
94
95 int bare_machine; /* Non-Zero => simulate bare machine */
96 int delayed_branches; /* Non-Zero => simulate delayed branches */
97 int delayed_loads; /* Non-Zero => simulate delayed loads */
98 int accept_pseudo_insts; /* Non-Zero => parse pseudo instructions */
99 int quiet; /* Non-Zero => no warning messages */
100 port message_out, console_out, console_in;
101 int mapped_io; /* Non-zero => activate memory-mapped IO */
102 int pipe_out;
103 int spim_return_value; /* Value returned when spim exits */
104
105 XtAppContext app_con;
106 Widget message, console = NULL;
107 XtAppContext app_context;
108 XFontStruct *text_font;
109 Dimension button_width;
110 int load_exception_handler;
111 char *exception_file_name = DEFAULT_EXCEPTION_HANDLER;
112 Pixmap mark;
113
114
115 /* Local functions: */
116
117 static void center_text_at_PC ();
118 static char *check_buf_limit (char *, int *, int *);
119 static void create_console_display ();
120 static void display_data_seg ();
121 static char *display_values (mem_addr from, mem_addr to, char *buf, int *limit,
122 int *n);
123 static char *display_insts (mem_addr from, mem_addr to, char *buf, int *limit,
124 int *n);
125 static void display_registers ();
126 static void initialize (AppResources app_res);
127 static mem_addr print_partial_line (mem_addr, char *, int *, int *);
128 static void show_running ();
129 static void syntax (char *program_name);
130 static void write_text_to_window (Widget w, char *s);
131
132
133 static String fallback_resources[] =
134 {
135 "*font: *-courier-medium-r-normal--12-*-75-*",
136 "*Label*font: *-adobe-helvetica-bold-r-*-*-12-*-75-*",
137 "*panel*font: *-adobe-helvetica-medium-r-*-*-12-*-75-*",
138 "*ShapeStyle: Oval",
139 "*dialog*value.translations: #override \\n <Key>Return: confirm()",
140 "*.translations: #override \\n <Ctrl>C: control_c_seen()",
141 "*Form*left: ChainLeft",
142 "*Form*right: ChainLeft",
143 "*Form*top: ChainTop",
144 "*Form*bottom: ChainTop",
145 "*console.label: SPIM Console",
146 "*Shell1*iconName: SPIM Console",
147 NULL,
148 };
149
150
151 static XtActionsRec actionTable[2] =
152 {
153 {"confirm", (XtActionProc) confirm},
154 {"control_c_seen", (XtActionProc) control_c_seen},
155 };
156
157
158 static XtResource resources[] =
159 {
160 {XtNfont, XtCFont, XtRString, sizeof (char *),
161 XtOffset (AppResources *, textFont), XtRString, NULL},
162 {"bare", "Bare", XtRBoolean, sizeof (Boolean),
163 XtOffset (AppResources *, bare), XtRImmediate, False},
164 {"delayed_branches", "Delayed_Branches", XtRBoolean, sizeof (Boolean),
165 XtOffset (AppResources *, delayed_branches), XtRImmediate, False},
166 {"delayed_loads", "Delayed_Loads", XtRBoolean, sizeof (Boolean),
167 XtOffset (AppResources *, delayed_loads), XtRImmediate, False},
168 {"pseudo", "Pseudo", XtRBoolean, sizeof (Boolean),
169 XtOffset (AppResources *, pseudo), XtRImmediate, (XtPointer)True},
170 {"asm", "Asm", XtRBoolean, sizeof (Boolean),
171 XtOffset (AppResources *, asmm), XtRImmediate, False},
172 {"exception", "Exception", XtRBoolean, sizeof (Boolean),
173 XtOffset (AppResources *, exception), XtRImmediate, (XtPointer) True},
174 {"exception_file_name", "Exception_File_Name", XtRString, sizeof (char *),
175 XtOffset (AppResources *, exception_file_name), XtRString, NULL},
176 {"quiet", "Quiet", XtRBoolean, sizeof (Boolean),
177 XtOffset (AppResources *, quiet), XtRImmediate, False},
178 {"mapped_io", "Mapped_IO", XtRBoolean, sizeof (Boolean),
179 XtOffset (AppResources *, mapped_io), XtRImmediate, False},
180
181 {"filename", "Filename", XtRString, sizeof (char *),
182 XtOffset (AppResources *, filename), XtRString, NULL},
183 {"display2", "Display2", XtRString, sizeof (char *),
184 XtOffset (AppResources *, display2), XtRString, NULL},
185 {"hexGpr", "DisplayHex", XtRBoolean, sizeof (Boolean),
186 XtOffset (AppResources *, hex_gpr), XtRImmediate, (XtPointer) True},
187 {"hexFpr", "DisplayHex", XtRBoolean, sizeof (Boolean),
188 XtOffset (AppResources *, hex_fpr), XtRImmediate, False},
189
190 {"stext", "Stext", XtRString, sizeof (char *),
191 XtOffset (AppResources *, initial_text_size), XtRString, NULL},
192 {"sdata", "Sdata", XtRString, sizeof (char *),
193 XtOffset (AppResources *, initial_data_size), XtRString, NULL},
194 {"ldata", "Ldata", XtRString, sizeof (char *),
195 XtOffset (AppResources *, initial_data_limit), XtRString, NULL},
196 {"sstack", "Sstack", XtRString, sizeof (char *),
197 XtOffset (AppResources *, initial_stack_size), XtRString, NULL},
198 {"lstack", "Lstack", XtRString, sizeof (char *),
199 XtOffset (AppResources *, initial_stack_limit), XtRString, NULL},
200 {"sktext", "Sktext", XtRString, sizeof (char *),
201 XtOffset (AppResources *, initial_k_text_size), XtRString, NULL},
202 {"skdata", "Skdata", XtRString, sizeof (char *),
203 XtOffset (AppResources *, initial_k_data_size), XtRString, NULL},
204 {"lkdata", "Lkdata", XtRString, sizeof (char *),
205 XtOffset (AppResources *, initial_k_data_limit), XtRString, NULL}
206 };
207
208
209 static XrmOptionDescRec options[] =
210 {
211 {"-asm", "asmm", XrmoptionNoArg, "True"},
212 {"-a", "asmm", XrmoptionNoArg, "True"},
213 {"-bare", "bare", XrmoptionNoArg, "True"},
214 {"-b", "bare", XrmoptionNoArg, "True"},
215 {"-delayed_branches", "delayed_branches", XrmoptionNoArg, "True"},
216 {"-db", "delayed_branches", XrmoptionNoArg, "True"},
217 {"-delayed_loads", "delayed_loads", XrmoptionNoArg, "True"},
218 {"-dl", "delayed_loads", XrmoptionNoArg, "True"},
219 {"-exception", "exception", XrmoptionNoArg, "True"},
220 {"-e", "exception", XrmoptionNoArg, "True"},
221 {"-noexception", "exception", XrmoptionNoArg, "False"},
222 {"-ne", "exception", XrmoptionNoArg, "False"},
223 {"-exception_file_name", "exception_file_name", XrmoptionSepArg, NULL},
224 {"-ef", "exception_file_name", XrmoptionSepArg, NULL},
225 {"-mapped_io", "mapped_io", XrmoptionNoArg, "True"},
226 {"-mio", "mapped_io", XrmoptionNoArg, "True"},
227 {"-nomapped_io","mapped_io", XrmoptionNoArg, "False"},
228 {"-nmio","mapped_io", XrmoptionNoArg, "False"},
229 {"-pseudo", "pseudo", XrmoptionNoArg, "True"},
230 {"-p", "pseudo", XrmoptionNoArg, "True"},
231 {"-nopseudo", "pseudo", XrmoptionNoArg, "False"},
232 {"-np", "pseudo", XrmoptionNoArg, "False"},
233 {"-quiet", "quiet", XrmoptionNoArg, "True"},
234 {"-q", "quiet", XrmoptionNoArg, "True"},
235 {"-noquiet","quiet", XrmoptionNoArg, "False"},
236 {"-nq","quiet", XrmoptionNoArg, "False"},
237 {"-trap", "exception", XrmoptionNoArg, "True"},
238 {"-t", "exception", XrmoptionNoArg, "True"},
239 {"-notrap", "exception", XrmoptionNoArg, "False"},
240 {"-nt", "exception", XrmoptionNoArg, "False"},
241 {"-trap_file_name", "exception_file_name", XrmoptionSepArg, NULL},
242 {"-tf", "exception_file_name", XrmoptionSepArg, NULL},
243 {"-stext", "stext", XrmoptionSepArg, NULL},
244 {"-st", "stext", XrmoptionSepArg, NULL},
245 {"-sdata", "sdata", XrmoptionSepArg, NULL},
246 {"-sd", "sdata", XrmoptionSepArg, NULL},
247 {"-ldata", "ldata", XrmoptionSepArg, NULL},
248 {"-ld", "ldata", XrmoptionSepArg, NULL},
249 {"-sstack", "sstack", XrmoptionSepArg, NULL},
250 {"-ss", "sstack", XrmoptionSepArg, NULL},
251 {"-lstack", "lstack", XrmoptionSepArg, NULL},
252 {"-ls", "lstack", XrmoptionSepArg, NULL},
253 {"-sktext", "sktext", XrmoptionSepArg, NULL},
254 {"-skt", "sktext", XrmoptionSepArg, NULL},
255 {"-skdata", "skdata", XrmoptionSepArg, NULL},
256 {"-skd", "skdata", XrmoptionSepArg, NULL},
257 {"-lkdata", "lkdata", XrmoptionSepArg, NULL},
258 {"-lkd", "lkdata", XrmoptionSepArg, NULL},
259 {"-file", "filename", XrmoptionSepArg, NULL},
260 {"-f", "filename", XrmoptionSepArg, NULL},
261 {"-d2", "display2", XrmoptionSepArg, NULL},
262 {"-hexgpr", "hexGpr", XrmoptionNoArg, "True"},
263 {"-nohexgpr", "hexGpr", XrmoptionNoArg, "False"},
264 {"-hexfpr", "hexFpr", XrmoptionNoArg, "True"},
265 {"-nohexfpr", "hexFpr", XrmoptionNoArg, "False"},
266 };
267
268
269 #define TICK_WIDTH 10
270
271 #define TICK_HEIGHT 10
272
273 static unsigned char tick_bits[] = {
274 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x80, 0x01, 0xc1, 0x00, 0x63, 0x00,
275 0x36, 0x00, 0x1c, 0x00, 0x08, 0x00, 0x00, 0x00};
276
277
278 /* Flags to control the way that registers are displayed. */
279
280 static int print_gpr_hex; /* Print GPRs in hex/decimal */
281 static int print_fpr_hex; /* Print FPRs in hex/floating point */
282
283
284 /* Local variables: */
285
286 static Dimension app_width;
287 static Dimension button_height;
288 static Dimension command_height;
289 static Dimension command_hspace;
290 static Dimension command_vspace;
291 static int console_is_visible;
292 static Dimension display_height;
293 static char *file_name = NULL;
294 static Dimension reg_min_height;
295 static Dimension reg_max_height;
296 static Dimension segment_height;
297 static Widget shell1;
298 static int spim_is_running = 0;
299 static Widget toplevel;
300 static Widget pane1;
301
302
303
304 static void
initialize(AppResources app_res)305 initialize (AppResources app_res)
306 {
307 bare_machine = 0;
308 delayed_branches = 0;
309 delayed_loads = 0;
310 accept_pseudo_insts = 1;
311 quiet = 0;
312
313 if (app_res.bare)
314 {
315 bare_machine = 1;
316 delayed_branches = 1;
317 delayed_loads = 1;
318 }
319
320 if (app_res.asmm)
321 {
322 bare_machine = 0;
323 delayed_branches = 0;
324 delayed_loads = 0;
325 }
326
327 if (app_res.delayed_branches)
328 delayed_branches = 1;
329
330 if (app_res.delayed_loads)
331 delayed_loads = 1;
332
333 if (app_res.pseudo)
334 accept_pseudo_insts = 1;
335 else
336 accept_pseudo_insts = 0;
337
338 if (app_res.exception)
339 load_exception_handler = 1;
340 else
341 load_exception_handler = 0;
342
343 if (app_res.exception_file_name)
344 {
345 exception_file_name = app_res.exception_file_name;
346 load_exception_handler = 1;
347 }
348
349 if (app_res.quiet)
350 quiet = 1;
351 else
352 quiet = 0;
353
354 if (app_res.mapped_io)
355 mapped_io = 1;
356 else
357 mapped_io = 0;
358
359 if (app_res.filename)
360 file_name = app_res.filename;
361
362 if (app_res.textFont == NULL)
363 app_res.textFont = XtNewString ("8x13");
364 if (!(text_font = XLoadQueryFont (XtDisplay (toplevel), app_res.textFont)))
365 fatal_error ("Cannot open font %s\n", app_res.textFont);
366
367 mark = XCreateBitmapFromData (XtDisplay (toplevel),
368 RootWindowOfScreen (XtScreen (toplevel)),
369 (char*)tick_bits, TICK_WIDTH, TICK_HEIGHT);
370
371 button_height = TEXTHEIGHT * 1.6;
372 button_width = TEXTWIDTH * 12;
373 app_width = 6 * (button_width + 16);
374 if ((unsigned)app_width < TEXTWIDTH * 4 * 22) /* Register display width */
375 app_width = TEXTWIDTH * 4 * 22;
376 command_hspace = 8;
377 command_vspace = 8;
378 command_height = (button_height * 2) + (command_vspace * 3);
379 reg_min_height = 15 * TEXTHEIGHT + 4;
380 reg_max_height = reg_min_height + 10 * TEXTHEIGHT + 4;
381 segment_height = 8 * TEXTHEIGHT + 4;
382 display_height = 8 * TEXTHEIGHT + 4;
383 print_gpr_hex = app_res.hex_gpr;
384 print_fpr_hex = app_res.hex_fpr;
385 }
386
387
388 static void
create_console_display()389 create_console_display ()
390 {
391 Arg args[10];
392 Cardinal n;
393
394 n = 0;
395 XtSetArg (args[n], XtNeditType, XawtextAppend); n++;
396 XtSetArg (args[n], XtNscrollVertical, XawtextScrollWhenNeeded); n++;
397 XtSetArg (args[n], XtNpreferredPaneSize, TEXTHEIGHT * 24); n++;
398 XtSetArg (args[n], XtNwidth, TEXTWIDTH * 80); n++;
399 console = XtCreateManagedWidget ("console", asciiTextWidgetClass, pane1,
400 args, n);
401 XawTextEnableRedisplay (console);
402 console_out.f = (FILE*) console;
403 }
404
405 void
clear_console_display()406 clear_console_display ()
407 {
408 Arg args[10];
409 Cardinal n;
410
411 XtSetArg (args[0], XtNstring, "");
412 XtSetValues(console, args, 1);
413 }
414
415
416 int
main(int argc,char ** argv)417 main (int argc, char **argv)
418 {
419 Widget toplevel2;
420 AppResources app_res;
421 Display *display;
422
423 spim_return_value = 0;
424
425 if (getenv ("SPIM_EXCEPTION_HANDLER") != NULL)
426 exception_file_name = getenv("SPIM_EXCEPTION_HANDLER");
427
428 toplevel = XtAppInitialize (&app_context, "Xspim", options,
429 XtNumber (options), &argc, argv,
430 fallback_resources, NULL, ZERO);
431
432 if (argc >= 0 && argv[argc] != NULL && argv[argc][0] == '-')
433 syntax (argv[0]); /* Bad command line argument */
434
435 XtGetApplicationResources (toplevel, (XtPointer) &app_res, resources,
436 XtNumber (resources), NULL, ZERO);
437
438 if (app_res.display2 == NULL)
439 display = XtDisplay (toplevel);
440 else
441 display = XtOpenDisplay (app_context, app_res.display2, "xspim",
442 "Xspim", NULL, ZERO, &argc, argv);
443
444 toplevel2 = XtAppCreateShell ("xspim","Xspim",applicationShellWidgetClass,
445 display, NULL, ZERO);
446
447 XtAppAddActions (app_context, actionTable, XtNumber (actionTable));
448
449 initialize (app_res);
450
451 /* Console window */
452
453 shell1 = XtCreatePopupShell ("Shell1", topLevelShellWidgetClass,
454 toplevel, NULL, ZERO);
455 pane1 = XtCreateManagedWidget ("pane1", panedWidgetClass, shell1,
456 NULL, ZERO);
457 create_console_display ();
458
459 create_sub_windows (toplevel, app_width, reg_min_height, reg_max_height,
460 command_height, command_hspace, command_vspace,
461 button_height, segment_height, display_height);
462
463 XtRealizeWidget (toplevel);
464
465 if (app_res.initial_text_size != NULL)
466 initial_text_size = atoi (app_res.initial_text_size);
467 if (app_res.initial_data_size != NULL)
468 initial_data_size = atoi (app_res.initial_data_size);
469 if (app_res.initial_data_limit != NULL)
470 initial_data_limit = atoi (app_res.initial_data_limit);
471 if (app_res.initial_stack_size != NULL)
472 initial_stack_size = atoi (app_res.initial_stack_size);
473 if (app_res.initial_stack_limit != NULL)
474 initial_stack_limit = atoi (app_res.initial_stack_limit);
475 if (app_res.initial_k_text_size != NULL)
476 initial_k_text_size = atoi (app_res.initial_k_text_size);
477 if (app_res.initial_k_data_size != NULL)
478 initial_k_data_size = atoi (app_res.initial_k_data_size);
479 if (app_res.initial_k_data_limit != NULL)
480 initial_k_data_limit = atoi (app_res.initial_k_data_limit);
481
482 write_startup_message ();
483 initialize_world (load_exception_handler ? exception_file_name : NULL);
484
485 if (file_name == NULL && argc > 1 && argv[argc - 1] != NULL)
486 {
487 /* The first unprocessed argument (aside from program name) is taken
488 as a filename containing input program. */
489 file_name = argv[argc - 1];
490 }
491
492 if (file_name)
493 {
494 read_file (file_name);
495 record_file_name_for_prompt (file_name);
496 }
497 else
498 {
499 PC = starting_address ();
500 redisplay_text ();
501 center_text_at_PC ();
502 redisplay_data ();
503 }
504
505 XtAppMainLoop (app_context);
506 return (spim_return_value);
507 }
508
509
510 static void
syntax(char * program_name)511 syntax (char *program_name)
512 {
513 XtDestroyApplicationContext (app_context);
514 fprintf (stderr, "Usage:\n %s", program_name);
515
516 fprintf (stderr, "-bare Bare machine (no pseudo-ops, delayed branches and loads)\n");
517 fprintf (stderr, "-asm Extended machine (pseudo-ops, no delayed branches and loads) (default)\n");
518 fprintf (stderr, "-delayed_branches Execute delayed branches\n");
519 fprintf (stderr, "-delayed_loads Execute delayed loads\n");
520 fprintf (stderr, "-exception Load exception handler (default)\n");
521 fprintf (stderr, "-noexception Do not load exception handler\n");
522 fprintf (stderr, "-exception_file <file> Specify exception handler in place of default\n");
523 fprintf (stderr, "-quiet Do not print warnings\n");
524 fprintf (stderr, "-noquiet Print warnings (default)\n");
525 fprintf (stderr, "-mapped_io Enable memory-mapped IO\n");
526 fprintf (stderr, "-nomapped_io Do not enable memory-mapped IO (default)\n");
527 fprintf (stderr, "-file <file> <args> Assembly code file and arguments to program\n");
528 exit (1);
529 }
530
531
532 void
control_c_seen(int arg)533 control_c_seen (int arg)
534 {
535 write_output (message_out, "\nExecution interrupted\n");
536 redisplay_data ();
537 continue_prompt (1);
538 if (spim_is_running)
539 longjmp (spim_top_level_env, 1);
540 }
541
542
543 void
popup_console(Widget w,XtPointer client_data,XtPointer call_data)544 popup_console (Widget w, XtPointer client_data, XtPointer call_data)
545 {
546 if (console_is_visible)
547 {
548 console_is_visible = 0;
549 XtPopdown (shell1);
550 }
551 else
552 {
553 console_is_visible = 1;
554 XtPopup (shell1, XtGrabNone);
555 }
556 }
557
558
559 void
read_file(char * name)560 read_file (char *name)
561 {
562 int error_flag;
563
564 if (*name == '\0')
565 error_flag = 1;
566 else
567 error_flag = read_assembly_file (name);
568
569 if (!error_flag)
570 {
571 PC = find_symbol_address (DEFAULT_RUN_LOCATION);
572 redisplay_text ();
573 center_text_at_PC ();
574 redisplay_data ();
575 }
576 }
577
578
579 void
start_program(mem_addr addr)580 start_program (mem_addr addr)
581 {
582 if (addr == 0)
583 addr = starting_address ();
584
585 if (addr != 0)
586 execute_program (addr, DEFAULT_RUN_STEPS, 0, 0);
587 }
588
589
590 void
execute_program(mem_addr pc,int steps,int display,int cont_bkpt)591 execute_program (mem_addr pc, int steps, int display, int cont_bkpt)
592 {
593 if (!setjmp (spim_top_level_env))
594 {
595 char *undefs = undefined_symbol_string ();
596 if (undefs != NULL)
597 {
598 write_output (message_out, "The following symbols are undefined:\n");
599 write_output (message_out, undefs);
600 write_output (message_out, "\n");
601 free (undefs);
602 }
603
604 spim_is_running = 1;
605 show_running ();
606
607 if (run_program (pc, steps, display, cont_bkpt))
608 continue_prompt (0);
609 }
610 redisplay_text ();
611 spim_is_running = 0;
612 center_text_at_PC ();
613 redisplay_data ();
614 }
615
616
617 static void
show_running()618 show_running ()
619 {
620 Arg args[1];
621
622 XtSetArg (args[0], XtNstring, "Running.....");
623 XtSetValues (register_window, args, ONE);
624 }
625
626
627 /* Redisplay the contents of the registers and, if modified, the data
628 and stack segments. */
629
630 void
redisplay_data()631 redisplay_data ()
632 {
633 display_registers ();
634 display_data_seg ();
635 }
636
637
638 /* Redisplay the contents of the registers in a wide variety of
639 formats. */
640
641 static void
display_registers()642 display_registers ()
643 {
644 Arg args [2];
645 static str_stream ss;
646
647 ss_clear (&ss);
648 format_registers (&ss, print_gpr_hex, print_fpr_hex);
649
650 XtSetArg (args[0], XtNstring, (String)ss_to_string (&ss));
651 XtSetArg (args[1], XtNlength, ss_length (&ss));
652 XtSetValues (register_window, args, TWO);
653 }
654
655
656 /* Redisplay the text segment and ktext segments if they have changed. */
657
658 void
redisplay_text()659 redisplay_text ()
660 {
661 Arg args [2];
662 static str_stream ss;
663
664 if (!text_modified)
665 return;
666
667 ss_clear (&ss);
668
669 format_insts (&ss, TEXT_BOT, text_top);
670 ss_printf (&ss, "\n\tKERNEL\n");
671 format_insts (&ss, K_TEXT_BOT, k_text_top);
672
673 XtSetArg (args[0], XtNstring, ss_to_string(&ss));
674 XtSetArg (args[1], XtNlength, ss_length (&ss));
675 XtSetValues (text_window, args, TWO);
676
677 text_modified = 0;
678 }
679
680
681 /* Center the text window at the instruction at the current PC and
682 highlight the instruction. */
683
684 static void
center_text_at_PC()685 center_text_at_PC ()
686 {
687 char buf[100];
688 XawTextBlock text;
689 XawTextPosition start, finish;
690 static mem_addr prev_PC = 0;
691
692 XawTextUnsetSelection(text_window);
693
694 if (PC < TEXT_BOT || (PC > text_top && (PC < K_TEXT_BOT || PC > k_text_top)))
695 return;
696
697 sprintf (buf, "\n[0x%08x]", PC);
698 text.firstPos = 0;
699 text.length = strlen (buf);
700 text.ptr = buf;
701 text.format = FMT8BIT;
702
703 /* Find start of line at PC: */
704 start = XawTextSearch (text_window, prev_PC <= PC ? XawsdRight : XawsdLeft,
705 &text);
706
707 if (start == XawTextSearchError)
708 {
709 start = XawTextSearch (text_window,
710 prev_PC > PC ? XawsdRight : XawsdLeft,
711 &text);
712 }
713
714 if (start == XawTextSearchError)
715 {
716 if (PC != 0x00400000) return;
717 XawTextSetInsertionPoint (text_window, 0);
718 }
719 else
720 XawTextSetInsertionPoint (text_window, start + 1);
721
722 /* Find end of the line: */
723 text.length = 1;
724 finish = XawTextSearch (text_window, XawsdRight, &text);
725 if (finish == XawTextSearchError)
726 return;
727
728 /* Highlight the line: */
729 XawTextSetSelection(text_window, start + 1, finish);
730
731 prev_PC = PC;
732 }
733
734
735 /* Display the contents of the data and stack segments, if they have
736 been modified. */
737
738 static void
display_data_seg()739 display_data_seg ()
740 {
741 Arg args [2];
742 static str_stream ss;
743
744 if (!data_modified)
745 return;
746
747 ss_clear (&ss);
748 format_data_segs(&ss);
749
750 XtSetArg (args[0], XtNstring, ss_to_string (&ss));
751 XtSetArg (args[1], XtNlength, ss_length (&ss));
752 XtSetValues (data_window, args, TWO);
753
754 data_modified = 0;
755 }
756
757
758
759
760 /* IO facilities: */
761
762
763 void
write_output(port fp,char * fmt,...)764 write_output (port fp, char *fmt, ...)
765 {
766 va_list args;
767 Widget w;
768 char io_buffer [IO_BUFFSIZE];
769
770 va_start (args, fmt);
771 w = (Widget) fp.f;
772
773 if (w == console && !console_is_visible)
774 {
775 XtPopup (shell1, XtGrabNone);
776 console_is_visible = 1;
777 }
778
779 vsprintf (io_buffer, fmt, args);
780 va_end (args);
781
782 write_text_to_window (w, io_buffer);
783
784 /* Look for keyboard input (such as ^C) */
785 while (XtAppPending (app_context))
786 {
787 XEvent event;
788
789 XtAppNextEvent (app_context, &event);
790 XtDispatchEvent (&event);
791 }
792 }
793
794
795 /* Simulate the semantics of fgets, not gets, on an x-window. */
796
797 void
read_input(char * str,int str_size)798 read_input (char *str, int str_size)
799 {
800 char buffer[11];
801 KeySym key;
802 XComposeStatus compose;
803 XEvent event;
804 char *ptr;
805
806 if (!console_is_visible)
807 {
808 XtPopup (shell1, XtGrabNone);
809 console_is_visible = 1;
810 }
811
812 ptr = str;
813
814 while (1 < str_size) /* Reserve space for null */
815 {
816 XtAppNextEvent (app_context, &event);
817 if (event.type == KeyPress)
818 {
819 int chars = XLookupString (&event.xkey, buffer, 10, &key, &compose);
820 if ((key == XK_Return) || (key == XK_KP_Enter))
821 {
822 *ptr++ = '\n';
823
824 write_text_to_window (console, "\n");
825 break;
826 }
827 else if (*buffer == 3) /* ^C */
828 XtDispatchEvent (&event);
829 else if (chars > 0)
830 {
831 /* Event is a character, not a modifier key */
832 int n = (chars < str_size - 1 ? chars : str_size - 1);
833
834 strncpy (ptr, buffer, n);
835 ptr += n;
836 str_size -= n;
837
838 buffer[chars] = '\0';
839 write_text_to_window (console, buffer);
840 }
841 }
842 else
843 XtDispatchEvent (&event);
844 }
845
846 if (0 < str_size)
847 *ptr = '\0';
848 }
849
850
851 /* Checking for console input is messy with X windows. A key stroke appears
852 as an X event, which must be read to check its type. In addition, the
853 functions that read events all block. So, when we check if console input
854 is available, we may see an event for a keystroke. If so, save the
855 keystroke for the next time the program reads a character. */
856
857 static int previous_char = -1;
858
859 int
console_input_available()860 console_input_available ()
861 {
862 XEvent event;
863
864 if (!console_is_visible)
865 {
866 XtPopup (shell1, XtGrabNone);
867 console_is_visible = 1;
868 }
869
870 if (XtAppPending (app_context) != 0)
871 {
872 /* There is an event to process: */
873 XtAppNextEvent (app_context, &event);
874 if (event.type == KeyPress)
875 {
876 /* Event is a key stroke: */
877 char buffer[11];
878 KeySym key;
879 XComposeStatus compose;
880 if (XLookupString (&event.xkey, buffer, 10, &key, &compose) > 0)
881 {
882 /* Event is a character, not a modifier key */
883 if ((key == XK_Return) || (key == XK_KP_Enter))
884 previous_char = '\n';
885 else if (buffer[0] == 3) /* ^C */
886 XtDispatchEvent (&event);
887 else if (buffer[0] != 0)
888 previous_char = (int)buffer[0];
889 return (1); /* There is a character */
890 }
891 }
892 else
893 {
894 XtDispatchEvent (&event);
895 }
896 }
897 return (0); /* There is no character */
898 }
899
900 char
get_console_char()901 get_console_char ()
902 {
903 /* assert (previous_char != -1); */
904 return (char)previous_char;
905 }
906
907
908 void
put_console_char(char c)909 put_console_char (char c)
910 {
911 char buf[4];
912
913 buf[0] = c;
914 buf[1] = '\0';
915 if (!console_is_visible)
916 {
917 XtPopup (shell1, XtGrabNone);
918 console_is_visible = 1;
919 }
920 write_text_to_window (console, buf);
921 }
922
923
924
925 /* Print an error message. */
926
927 void
error(char * fmt,...)928 error (char *fmt, ...)
929 {
930 va_list args;
931 char io_buffer [IO_BUFFSIZE];
932
933 va_start (args, fmt);
934 vsprintf (io_buffer, fmt, args);
935 va_end (args);
936 if (message != 0)
937 write_text_to_window (message, io_buffer);
938 else
939 fprintf (stderr, "%s", io_buffer);
940 }
941
942
943 /* Print the error message then exit. */
944
945 void
fatal_error(char * fmt,...)946 fatal_error (char *fmt, ...)
947 {
948 va_list args;
949 va_start (args, fmt);
950 fmt = va_arg (args, char *);
951
952 #ifdef NO_VFPRINTF
953 _doprnt (fmt, args, stderr);
954 #else
955 vfprintf (stderr, fmt, args);
956 #endif
957 exit (-1);
958 }
959
960
961 void
run_error(char * fmt,...)962 run_error (char *fmt, ...)
963 {
964 va_list args;
965 char io_buffer [IO_BUFFSIZE];
966
967 va_start (args, fmt);
968 vsprintf (io_buffer, fmt, args);
969 va_end (args);
970 if (message != 0)
971 write_text_to_window (message, io_buffer);
972 else
973 fprintf (stderr, "%s", io_buffer);
974 if (spim_is_running)
975 longjmp (spim_top_level_env, 1);
976 }
977
978
979 static void
write_text_to_window(Widget w,char * s)980 write_text_to_window (Widget w, char *s)
981 {
982 XawTextBlock textblock;
983 XawTextPosition ip = XawTextGetInsertionPoint (w);
984
985 if (!s || strlen (s) == 0) return;
986
987 textblock.firstPos = 0;
988 textblock.length = strlen (s);
989 textblock.ptr = s;
990 textblock.format = FMT8BIT;
991
992 XawTextReplace (w, ip, ip, &textblock);
993 XawTextSetInsertionPoint (w,
994 XawTextGetInsertionPoint (w) + textblock.length);
995 }
996