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