/* SPIM S20 MIPS simulator. X interface to SPIM Copyright (C) 1990 by James Larus (larus@cs.wisc.edu), James R. Goodman, and Alan Yuen-wui Siow. SPIM is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. SPIM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to James R. Larus, Computer Sciences Department, University of Wisconsin--Madison, 1210 West Dayton Street, Madison, WI 53706, USA or to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* $Header: /home/aa/projects/spim/public_html/cvsroot/spimsal/xspim.c,v 1.2 2000/07/25 20:47:24 cs61c Exp $ */ #include #include "spim.h" #include #include #include #include #include #include #include #include #include #include #include #include #ifndef DST_NONE #include #endif #include "xspim.h" #include "buttons.h" #include "windows.h" #include "inst.h" #include "mem.h" #include "reg.h" #include "y.tab.h" #include "sym_tbl.h" /* Local functions: */ static void display_data_seg (); static char *display_values (); static char *display_insts (); static void display_registers (); static void initialize (); static void showRunning (); static void syntax (); static void writeText (); static void center_text_at_PC (); static void unmark_text(); static void NextEvent(); /* Exported variables: */ int console_uses_stdin = 0; /* Set to 1 from spim and 0 for xspim */ typedef struct t_node { struct timeval timeout; int exception_code; struct t_node *next; } time_node; typedef struct _AppResources { String textFont; Boolean bare; Boolean asmm; Boolean trap; Boolean quiet; Boolean memio; char *filename; char *display2; Boolean hex_gpr; Boolean hex_fpr; Boolean hex_fgr; char *initial_data_limit; char *initial_data_size; char *initial_k_data_limit; char *initial_k_data_size; char *initial_k_text_size; char *initial_stack_limit; char *initial_stack_size; char *initial_text_size; } AppResources; static String fallback_resources[] = { "*font: *-courier-medium-r-normal--12-*-75-*", "*Label*font: *-adobe-helvetica-bold-r-*-*-12-*-75-*", "*panel*font: *-adobe-helvetica-medium-r-*-*-12-*-75-*", "*ShapeStyle: Oval", "*dialog*value.translations: #override \\n Return: Confirm()", "*.translations: #override \\n C: control_c_seen()", "*Form*left: ChainLeft", "*Form*right: ChainLeft", "*Form*top: ChainTop", "*Form*bottom: ChainTop", "*terminal1.label: SPIM Console", "*Shell1*iconName: SPIM Console", "*terminal2.label: SPIM Terminal 2", "*Shell2*iconName: SPIM Terminal 2", NULL, }; XtActionsRec actionTable[] = { {"Confirm", Confirm}, {"control_c_seen", control_c_seen}, }; static XtResource resources[] = { {XtNfont, XtCFont, XtRString, sizeof (char *), XtOffset (AppResources *, textFont), XtRString, NULL}, {"bare", "Bare", XtRBoolean, sizeof (Boolean), XtOffset (AppResources *, bare), XtRImmediate, False}, {"asmm", "Asmm", XtRBoolean, sizeof (Boolean), XtOffset (AppResources *, asmm), XtRImmediate, False}, {"trap", "Trap", XtRBoolean, sizeof (Boolean), XtOffset (AppResources *, trap), XtRImmediate, (XtPointer) True}, {"quiet", "Quiet", XtRBoolean, sizeof (Boolean), XtOffset (AppResources *, quiet), XtRImmediate, False}, {"memio", "Memio", XtRBoolean, sizeof (Boolean), XtOffset (AppResources *, memio), XtRImmediate, False}, {"filename", "Filename", XtRString, sizeof (char *), XtOffset (AppResources *, filename), XtRString, NULL}, {"display2", "Display2", XtRString, sizeof (char *), XtOffset (AppResources *, display2), XtRString, NULL}, {"hexGpr", "DisplayHex", XtRBoolean, sizeof (Boolean), XtOffset (AppResources *, hex_gpr), XtRImmediate, (XtPointer) True}, {"hexFpr", "DisplayHex", XtRBoolean, sizeof (Boolean), XtOffset (AppResources *, hex_fpr), XtRImmediate, False}, {"hexFgr", "DisplayHex", XtRBoolean, sizeof (Boolean), XtOffset (AppResources *, hex_fgr), XtRImmediate, False}, {"stext", "Stext", XtRString, sizeof (char *), XtOffset (AppResources *, initial_text_size), XtRString, NULL}, {"sdata", "Sdata", XtRString, sizeof (char *), XtOffset (AppResources *, initial_data_size), XtRString, NULL}, {"ldata", "Ldata", XtRString, sizeof (char *), XtOffset (AppResources *, initial_data_limit), XtRString, NULL}, {"sstack", "Sstack", XtRString, sizeof (char *), XtOffset (AppResources *, initial_stack_size), XtRString, NULL}, {"lstack", "Lstack", XtRString, sizeof (char *), XtOffset (AppResources *, initial_stack_limit), XtRString, NULL}, {"sktext", "Sktext", XtRString, sizeof (char *), XtOffset (AppResources *, initial_k_text_size), XtRString, NULL}, {"skdata", "Skdata", XtRString, sizeof (char *), XtOffset (AppResources *, initial_k_data_size), XtRString, NULL}, {"lkdata", "Lkdata", XtRString, sizeof (char *), XtOffset (AppResources *, initial_k_data_limit), XtRString, NULL} }; static XrmOptionDescRec options[] = { {"-bare", "bare", XrmoptionNoArg, "True"}, {"-asm", "asmm", XrmoptionNoArg, "True"}, {"-trap", "trap", XrmoptionNoArg, "True"}, {"-notrap", "trap", XrmoptionNoArg, "False"}, {"-quiet", "quiet", XrmoptionNoArg, "True"}, {"-noquiet","quiet", XrmoptionNoArg, "False"}, {"-memio", "memio", XrmoptionNoArg, "True"}, {"-file", "filename", XrmoptionSepArg, NULL}, {"-d2", "display2", XrmoptionSepArg, NULL}, {"-hexgpr", "hexGpr", XrmoptionNoArg, "True"}, {"-nohexgpr", "hexGpr", XrmoptionNoArg, "False"}, {"-hexfpr", "hexFpr", XrmoptionNoArg, "True"}, {"-nohexfpr", "hexFpr", XrmoptionNoArg, "False"}, {"-hexfgr", "hexFgr", XrmoptionNoArg, "True"}, {"-nohexfgr", "hexFgr", XrmoptionNoArg, "False"}, {"-stext", "stext", XrmoptionSepArg, NULL}, {"-sdata", "sdata", XrmoptionSepArg, NULL}, {"-ldata", "ldata", XrmoptionSepArg, NULL}, {"-sstack", "sstack", XrmoptionSepArg, NULL}, {"-lstack", "lstack", XrmoptionSepArg, NULL}, {"-sktext", "sktext", XrmoptionSepArg, NULL}, {"-skdata", "skdata", XrmoptionSepArg, NULL}, {"-lkdata", "lkdata", XrmoptionSepArg, NULL} }; #define TICK_WIDTH 10 #define TICK_HEIGHT 10 static char tick_bits[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x80, 0x01, 0xc1, 0x00, 0x63, 0x00, 0x36, 0x00, 0x1c, 0x00, 0x08, 0x00, 0x00, 0x00}; static char *ASCII_rep[128] = { "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", " bs", " ht", " nl", " vt", " ff", " cr", " so", " si", "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", "can", " em", "sub", "esc", " fs", " gs", " rs", " us", " sp", " !", " \"", " #", " $", " %", " &", " '", " (", " )", " *", " +", " ,", " -", " .", " /", " 0", " 1", " 2", " 3", " 4", " 5", " 6", " 7", " 8", " 9", " :", " ;", " <", " =", " >", " ?", " @", " A", " B", " C", " D", " E", " F", " G", " H", " I", " J", " K", " L", " M", " N", " O", " P", " Q", " R", " S", " T", " U", " V", " W", " X", " Y", " Z", " [", " \\", " ]", " ^", " _", " `", " a", " b", " c", " d", " e", " f", " g", " h", " i", " j", " k", " l", " m", " n", " o", " p", " q", " r", " s", " t", " u", " v", " w", " x", " y", " z", " {", " |", " }", " ~", "del" }; /* Flags to control the way that registers are displayed. */ int print_gpr_hex; /* Print GPRs in hex/decimal */ int print_fpr_hex; /* Print FPRs in hex/floating point */ int print_fgr_hex; /* Print FGRs in hex/floating point */ /* Exported variables: */ XtAppContext app_context; Dimension button_width; int load_trap_handler; Pixmap mark; Widget message, console, terminal; jmp_buf spim_top_level_env; /* For ^C */ XFontStruct *text_font; int source_file; int spim_is_running = 0; char mess_buff[512]; /* Local variables: */ static Dimension app_width; static Dimension button_height; static Dimension command_height; static Dimension command_hspace; static Dimension command_vspace; static int console_is_visible; static Dimension display_height; static char *file_name = NULL; static time_node *queue; static Dimension reg_min_height; static Dimension reg_max_height; static Dimension segment_height; static Widget shell1; static Widget shell2; static int terminal_is_visible; static Widget toplevel; static Widget* pane1_ptr = NULL; /* added to support clear_console_display() */ /* Imported variables: */ Widget register_window, text_window, data_window; mem_addr program_starting_address; long initial_text_size, initial_data_size, initial_data_limit; long initial_stack_size, initial_stack_limit, initial_k_text_size; long initial_k_data_size, initial_k_data_limit; static void initialize (AppResources app_res) { if (app_res.bare) bare_machine = 1; if (app_res.asmm) bare_machine = 0; if (app_res.trap) load_trap_handler = 1; else load_trap_handler = 0; if (app_res.quiet) quiet = 1; else quiet = 0; if (app_res.memio) #ifndef NOMEMIO memio = 1; #else error("-memio option disabled. Recompile spim without -DNOMEMIO\n"); #endif /* NOMEMIO */ else memio = 0; if (app_res.filename) file_name = app_res.filename; if (app_res.textFont == NULL) app_res.textFont = XtNewString ("8x13"); if (!(text_font = XLoadQueryFont (XtDisplay (toplevel), app_res.textFont))) { sprintf(mess_buff, "Cannot open font %s\n", app_res.textFont); fatal_error (mess_buff); } mark = XCreateBitmapFromData (XtDisplay (toplevel), RootWindowOfScreen (XtScreen (toplevel)), tick_bits, TICK_WIDTH, TICK_HEIGHT); button_height = TEXTHEIGHT * 1.6; button_width = TEXTWIDTH * 12; app_width = 6 * (button_width + 16); if (app_width < TEXTWIDTH * 4 * 22) /* Register display width */ app_width = TEXTWIDTH * 4 * 22; command_hspace = 8; command_vspace = 8; command_height = (button_height * 2) + (command_vspace * 3) + 2; reg_min_height = 19 * TEXTHEIGHT + 4; reg_max_height = reg_min_height + 8 * TEXTHEIGHT + 4; segment_height = 10 * TEXTHEIGHT + 4; display_height = 8 * TEXTHEIGHT + 4; print_gpr_hex = app_res.hex_gpr; print_fpr_hex = app_res.hex_fpr; print_fgr_hex = app_res.hex_fgr; } int main (int argc, char **argv) { Widget toplevel2, pane1, pane2; AppResources app_res; Display *display; Arg args[10]; Cardinal n; toplevel = XtAppInitialize (&app_context, "Xspim", options, XtNumber (options), &argc, argv, fallback_resources, NULL, ZERO); if (argc != 1) syntax (app_context, argv[0]); XtGetApplicationResources (toplevel, (XtPointer) &app_res, resources, XtNumber (resources), NULL, ZERO); if (app_res.display2 == NULL) display = XtDisplay (toplevel); else display = XtOpenDisplay (app_context, app_res.display2, "xspim", "Xspim", NULL, ZERO, &argc, argv); toplevel2 = XtAppCreateShell ("xspim","Xspim",applicationShellWidgetClass, display, NULL, ZERO); XtAppAddActions (app_context, actionTable, XtNumber (actionTable)); initialize (app_res); /* Console window */ shell1 = XtCreatePopupShell ("Shell1", topLevelShellWidgetClass, toplevel, NULL, ZERO); pane1 = XtCreateManagedWidget ("pane1", panedWidgetClass, shell1, NULL, ZERO); pane1_ptr = &pane1; /* lets clear_console_display() access pane1 */ n = 0; XtSetArg (args[n], XtNeditType, XawtextRead); n++; XtSetArg (args[n], XtNscrollVertical, XawtextScrollWhenNeeded); n++; XtSetArg (args[n], XtNpreferredPaneSize, TEXTHEIGHT * 24); n++; XtSetArg (args[n], XtNwidth, TEXTWIDTH * 80); n++; console = XtCreateManagedWidget ("console", asciiTextWidgetClass, pane1, args, n); console_out = (int) console; /* Terminal window */ shell2 = XtCreatePopupShell ("Shell2", topLevelShellWidgetClass, toplevel2, NULL, ZERO); pane2 = XtCreateManagedWidget ("pane2", panedWidgetClass, shell2, NULL, ZERO); terminal = XtCreateManagedWidget ("terminal", asciiTextWidgetClass, pane2, args, n); terminal_out = (int) terminal; CreateSubWindows (toplevel, app_width, reg_min_height, reg_max_height, command_height, command_hspace, command_vspace, button_height, segment_height, display_height); XtRealizeWidget (toplevel); if (app_res.initial_text_size != NULL) initial_text_size = atoi (app_res.initial_text_size); if (app_res.initial_data_size != NULL) initial_data_size = atoi (app_res.initial_data_size); if (app_res.initial_data_limit != NULL) initial_data_limit = atoi (app_res.initial_data_limit); if (app_res.initial_stack_size != NULL) initial_stack_size = atoi (app_res.initial_stack_size); if (app_res.initial_stack_limit != NULL) initial_stack_limit = atoi (app_res.initial_stack_limit); if (app_res.initial_k_text_size != NULL) initial_k_text_size = atoi (app_res.initial_k_text_size); if (app_res.initial_k_data_size != NULL) initial_k_data_size = atoi (app_res.initial_k_data_size); if (app_res.initial_k_data_limit != NULL) initial_k_data_limit = atoi (app_res.initial_k_data_limit); initialize_world (load_trap_handler); if (file_name) { read_file (file_name, 1); xspim_file_name = str_copy (file_name); } else { redisplay_text (); redisplay_data (); } XtAppMainLoop (app_context); return (0); } static void syntax (XtAppContext app_context, char *call) { XtDestroyApplicationContext (app_context); fprintf (stderr, "Usage:\n %s", call); fprintf (stderr, "\t[ -bare/-asm ] [ -trap/-notrap ] [ -quiet/noquiet ]\n"); fprintf (stderr, "\t[ -d2 ] [ -file ]\n"); fprintf (stderr, "\t[ -s ] [ -l ] [ -memio ]\n"); exit (1); } void control_c_seen () { write_output (message_out, "\nExecution interrupted\n"); redisplay_data (); ContinuePrompt (1); if (spim_is_running) longjmp (spim_top_level_env, 1); } void PopConsole (Widget w, XtPointer client_data, XtPointer call_data) { if (console_is_visible) { console_is_visible = 0; XtPopdown (shell1); } else { console_is_visible = 1; XtPopup (shell1, XtGrabNone); } } void PopTerminal (Widget w, XtPointer client_data, XtPointer call_data) { if (terminal_is_visible) { terminal_is_visible = 0; XtPopdown (shell2); } else { terminal_is_visible = 1; XtPopup (shell2, XtGrabNone); } } void read_file (char *name, int assembly_file) { int error_flag = 0; if (*name == '\0') error_flag = 1; else if (assembly_file) error_flag = read_assembly_file (name); if (!error_flag) { redisplay_text (); redisplay_data (); } } void start_program (mem_addr addr) { if (addr == 0) addr = starting_address (); if (addr) { execute_program (addr, DEFAULT_RUN_STEPS, 0, 0); queue = NULL; } } void execute_program (mem_addr pc, int steps, int display, int cont_bkpt) { Arg args[2]; int n; if (spim_is_running) { XBell(XtDisplay(toplevel), BELL_VOLUME); return; } if (!setjmp (spim_top_level_env)) { n = 0; XtSetArg (args[n], XtNeditType, XawtextAppend); n++; XtSetValues (console, args, ONE); XtSetValues (terminal, args, ONE); spim_is_running = 1; showRunning (); if (run_program (pc, steps, display, cont_bkpt)) ContinuePrompt (0); } n = 0; XtSetArg (args[n], XtNeditType, XawtextRead); n++; XtSetValues (console, args, ONE); XtSetValues (terminal, args, ONE); spim_is_running = 0; redisplay_data (); center_text_at_PC (); } static void showRunning () { Arg args[1]; XtSetArg (args[0], XtNstring, "Running....."); XtSetValues (register_window, args, ONE); unmark_text(); } /* Redisplay the contents of the registers and, if modified, the data and stack segments. */ void redisplay_data () { display_registers (); display_data_seg (); } /* Redisplay the contents of the registers in a wide variety of formats. */ static String buf = NULL; static void display_registers () { int i; String bufp; char *grstr, *fpstr, *fgstr; char *grfill, *fpfill, *fgfill; Arg args [2]; static char *reg_names[] = {"r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"}; if (buf == NULL) buf = (char *) malloc (16 * K); bufp = buf; *buf = '\0'; if (print_gpr_hex) grstr = "R%-2d (%2s) = %08x", grfill = " "; else grstr = "R%-2d (%2s) = %-10d", grfill = " "; if (print_fpr_hex) fpstr = "FP%-2d=%08x%08x", fpfill = " "; else fpstr = "FP%-2d = %-10.4f", fpfill = " "; if (print_fgr_hex) fgstr = "FG%-2d = %08x", fgfill = " "; else fgstr = "FG%-2d = %-10.4f", fgfill = " "; sprintf (bufp, " PC = %08x ", PC); bufp += strlen (bufp); sprintf (bufp, " EPC = %08x ", EPC); bufp += strlen (bufp); sprintf (bufp, " Cause = %08x ", Cause); bufp += strlen (bufp); sprintf (bufp, " BadVAddr= %08x\n", BadVAddr); bufp += strlen (bufp); sprintf (bufp, " Status = %08x ", Status_Reg); bufp += strlen (bufp); sprintf (bufp, " HI = %08x ", HI); bufp += strlen (bufp); sprintf (bufp, " LO = %08x\n", LO); bufp += strlen (bufp); sprintf (bufp, "\t\t\t\t General Registers\n"); bufp += strlen (bufp); for (i = 0; i < 8; i++) { sprintf (bufp, grstr, i, reg_names[i], R[i]); bufp += strlen (bufp); sprintf (bufp, grfill); bufp += strlen (bufp); sprintf (bufp, grstr, i+8, reg_names[i+8], R[i+8]); bufp += strlen (bufp); sprintf (bufp, grfill); bufp += strlen (bufp); sprintf (bufp, grstr, i+16, reg_names[i+16], R[i+16]); bufp += strlen (bufp); sprintf (bufp, grfill); bufp += strlen (bufp); sprintf (bufp, grstr, i+24, reg_names[i+24], R[i+24]); bufp += strlen (bufp); sprintf (bufp, "\n"); bufp += 1; } sprintf (bufp, "\t\t\t Double Floating Point Registers\n"); bufp += strlen (bufp); if (print_fpr_hex) for (i = 0; i < 4; i += 1) { sprintf (bufp, fpstr, 2*i, FWR[2*i], FWR[2*i+1]); bufp += strlen (bufp); sprintf (bufp, fpfill); bufp += strlen (bufp); sprintf (bufp, fpstr, 2*i+8, FWR[2*i+8], FWR[2*i+8+1]); bufp += strlen (bufp); sprintf (bufp, fpfill); bufp += strlen (bufp); sprintf (bufp, fpstr, 2*i+16, FWR[2*i+16], FWR[2*i+16+1]); bufp += strlen (bufp); sprintf (bufp, fpfill); bufp += strlen (bufp); sprintf (bufp, fpstr, 2*i+24, FWR[2*i+24], FWR[2*i+24+1]); bufp += strlen (bufp); sprintf (bufp, "\n"); bufp += 1; } else for (i = 0; i < 4; i += 1) { sprintf (bufp, fpstr, 2*i, FPR[i]); bufp += strlen (bufp); sprintf (bufp, fpfill); bufp += strlen (bufp); sprintf (bufp, fpstr, 2*i+8, FPR[i+4]); bufp += strlen (bufp); sprintf (bufp, fpfill); bufp += strlen (bufp); sprintf (bufp, fpstr, 2*i+16, FPR[i+8]); bufp += strlen (bufp); sprintf (bufp, fpfill); bufp += strlen (bufp); sprintf (bufp, fpstr, 2*i+24, FPR[i+12]); bufp += strlen (bufp); sprintf (bufp, "\n"); bufp += 1; } sprintf (bufp, "\t\t\t Single Floating Point Registers\n"); bufp += strlen (bufp); if (print_fgr_hex) for (i = 0; i < 8; i += 2) { sprintf (bufp, fgstr, i, FWR[i]); bufp += strlen (bufp); sprintf (bufp, fgfill); bufp += strlen (bufp); sprintf (bufp, fgstr, i+8, FWR[i+8]); bufp += strlen (bufp); sprintf (bufp, fgfill); bufp += strlen (bufp); sprintf (bufp, fgstr, i+16, FWR[i+16]); bufp += strlen (bufp); sprintf (bufp, fgfill); bufp += strlen (bufp); sprintf (bufp, fgstr, i+24, FWR[i+24]); bufp += strlen (bufp); sprintf (bufp, "\n"); bufp += 1; } else for (i = 0; i < 8; i += 2) { sprintf (bufp, fgstr, i, FGR[i]); bufp += strlen (bufp); sprintf (bufp, fgfill); bufp += strlen (bufp); sprintf (bufp, fgstr, i+8, FGR[i+8]); bufp += strlen (bufp); sprintf (bufp, fgfill); bufp += strlen (bufp); sprintf (bufp, fgstr, i+16, FGR[i+16]); bufp += strlen (bufp); sprintf (bufp, fgfill); bufp += strlen (bufp); sprintf (bufp, fgstr, i+24, FGR[i+24]); bufp += strlen (bufp); sprintf (bufp, "\n"); bufp += 1; } if (bufp - buf > 8*K) { fprintf(stderr, "Buffer overflow, register window, size %d.\n", bufp-buf); } XtSetArg (args[0], XtNstring, buf); XtSetArg (args[1], XtNlength, 8*K); XtSetValues (register_window, args, TWO); } static char *find(char *text, mem_addr addr, int dir, char *old_ptr) /* dir = 1 -- forwards */ /* dir = 0 -- backwards */ { char tmp[20]; char *ptr; if (old_ptr == NULL) { dir = 1; old_ptr = text; } ptr = old_ptr; sprintf(tmp, "\n[0x%08x]", addr); if (dir) while (*ptr != '\0') { if (*ptr != '\n') ptr++; else { if (0 == strncmp(ptr, tmp, 13)) return ptr; ptr++; } } else while (ptr >= text) { if (*ptr != '\n') ptr--; else { if (0 == strncmp(ptr, tmp, 13)) return ptr; ptr--; } } if (old_ptr != text) { return find(text, addr, 1, text); } return NULL; } static mem_addr prev_PC = 0; static char *ptr_PC; static mem_addr prev_EPC = 0; static char *ptr_EPC; static mem_addr prev_ra = 0; static char *ptr_ra; static char *text_buf = NULL; static int text_limit; /* Redisplay the text segment and ktext segments. */ void redisplay_text () { int n; Arg args [2]; if (text_modified) { if (text_buf == NULL) { text_buf = (char *) malloc (16*K); text_limit = 16*K; } *text_buf = '\0'; n = 0; text_buf = display_insts (TEXT_BOT, text_top, text_buf, &text_limit, &n); sprintf (&text_buf[n], "\n\tKERNEL\n"); n += strlen (&text_buf[n]); text_buf = display_insts (K_TEXT_BOT, k_text_top, text_buf, &text_limit, &n); XtSetArg (args[0], XtNstring, text_buf); XtSetArg (args[1], XtNlength, text_limit); XtSetValues (text_window, args, TWO); prev_PC = 0; prev_EPC = 0; prev_ra = 0; text_modified = 0; } if (prev_PC) { ptr_PC[13] = ' '; ptr_PC[14] = ' '; ptr_PC[15] = ' '; ptr_PC[16] = ' '; ptr_PC[17] = ' '; } if (prev_EPC) { ptr_EPC[13] = ' '; ptr_EPC[14] = ' '; ptr_EPC[15] = ' '; ptr_EPC[16] = ' '; ptr_EPC[17] = ' '; } if (prev_ra) { ptr_ra[13] = ' '; ptr_ra[14] = ' '; ptr_ra[15] = ' '; ptr_ra[16] = ' '; ptr_ra[17] = ' '; } if ((EPC >= TEXT_BOT && EPC <= text_top) || (EPC >= K_TEXT_BOT && EPC <= k_text_top)){ ptr_EPC = find(text_buf, EPC, EPC >= prev_EPC, ptr_EPC); if (ptr_EPC) { prev_EPC = EPC; ptr_EPC[13] = '<'; ptr_EPC[14] = 'E'; ptr_EPC[15] = 'P'; ptr_EPC[16] = 'C'; ptr_EPC[17] = '>'; } else prev_EPC = 0; } if ((R[31] >= TEXT_BOT && R[31] <= text_top) || (R[31] >= K_TEXT_BOT && R[31] <= k_text_top)){ ptr_ra = find(text_buf, R[31], R[31] >= prev_ra, ptr_ra); if (ptr_ra) { prev_ra = R[31]; ptr_ra[13] = '<'; ptr_ra[14] = '$'; ptr_ra[15] = 'r'; ptr_ra[16] = 'a'; ptr_ra[17] = '>'; } else prev_ra = 0; } if ((PC >= TEXT_BOT && PC <= text_top) || (PC >= K_TEXT_BOT && PC <= k_text_top)){ ptr_PC = find(text_buf, PC, PC >= prev_PC, ptr_PC); if (ptr_PC) { prev_PC = PC; ptr_PC[13] = '<'; ptr_PC[14] = 'P'; ptr_PC[15] = 'C'; ptr_PC[16] = '>'; ptr_PC[17] = ' '; } else prev_PC = 0; } XtSetArg (args[0], XtNstring, text_buf); XtSetArg (args[1], XtNlength, text_limit); XtSetValues (text_window, args, TWO); return; } static void unmark_text() { Arg args [2]; if (prev_PC || prev_EPC || prev_ra) { if (prev_PC) { ptr_PC[13] = ' '; ptr_PC[14] = ' '; ptr_PC[15] = ' '; ptr_PC[16] = ' '; ptr_PC[17] = ' '; } if (prev_EPC) { ptr_EPC[13] = ' '; ptr_EPC[14] = ' '; ptr_EPC[15] = ' '; ptr_EPC[16] = ' '; ptr_EPC[17] = ' '; } if (prev_ra) { ptr_ra[13] = ' '; ptr_ra[14] = ' '; ptr_ra[15] = ' '; ptr_ra[16] = ' '; ptr_ra[17] = ' '; } prev_PC = 0; prev_EPC = 0; prev_ra = 0; XtSetArg (args[0], XtNstring, text_buf); XtSetArg (args[1], XtNlength, text_limit); XtSetValues (text_window, args, TWO); } } /* Write a printable representation of the instructions in memory address FROM...TO to buffer BUF, which is of size LIMIT and whose next free location is N. Return the, possible realloc'ed, buffer. */ static char * display_insts (from, to, buf, limit, n) mem_addr from, to; char *buf; int *limit, *n; { instruction *inst; mem_addr i; for (i = from; i < to; i += 4) { READ_MEM_INST (inst, i); if (inst != NULL) { *n += print_inst_internal (&buf[*n], inst, i); if ((*limit - *n) < 1*K) { *limit = 2 * *limit; if ((buf = (char *) realloc (buf, *limit)) == 0) fatal_error ("realloc failed\n"); } } } return (buf); } /* Center the text window at the instruction at the current PC and highlight the instruction. */ static void center_text_at_PC () { char buf[20]; XawTextBlock text; XawTextPosition start; static mem_addr prev_PC = 0; XawTextDisableRedisplay(text_window); redisplay_text(); if ((PC < TEXT_BOT || PC > text_top) && (PC < K_TEXT_BOT || PC > k_text_top)){ XawTextEnableRedisplay(text_window); return; } sprintf (buf, "\n[0x%08x]", PC); text.firstPos = 0; text.length = strlen (buf); text.ptr = buf; text.format = FMT8BIT; start = XawTextSearch (text_window, prev_PC <= PC ? XawsdRight : XawsdLeft, &text); if (start == XawTextSearchError) { start = XawTextSearch (text_window, prev_PC > PC ? XawsdRight : XawsdLeft, &text); if (start == XawTextSearchError) { XawTextEnableRedisplay(text_window); return; } } XawTextSetInsertionPoint (text_window, start+2); prev_PC = PC; XawTextEnableRedisplay(text_window); } /* Display the contents of the data and stack segments, if they have been modified. */ static void display_data_seg () { char *buf; int limit, n; Arg args [2]; if (!data_modified) return; buf = (char *) malloc (16*K); *buf = '\0'; limit = 16*K; n = 0; sprintf (&buf[n], "\n\tDATA\n"); n += strlen (&buf[n]); buf = display_values (DATA_BOT, data_top, buf, &limit, &n); sprintf (&buf[n], "\n\tSTACK\n"); n += strlen (&buf[n]); if ((R[29] < STACK_TOP) && (R[29] > STACK_TOP - STACK_LIMIT)) { buf = display_values (R[29] - BYTES_PER_WORD, STACK_TOP, buf, &limit, &n); } else { sprintf (&buf[n], "\n", STACK_TOP - STACK_LIMIT, STACK_TOP); n += strlen (&buf[n]); } sprintf (&buf[n], "\n\tKERNEL DATA\n"); n += strlen (&buf[n]); buf = display_values (K_DATA_BOT, k_data_top, buf, &limit, &n); XtSetArg (args[0], XtNstring, buf); XtSetArg (args[1], XtNlength, limit); XtSetValues (data_window, args, TWO); free (buf); data_modified = 0; } /* Write a printable representation of the data in memory address FROM...TO to buffer BUF, which is of size LIMIT and whose next free location is N. Return the, possible realloc'ed, buffer. */ static char * display_values (from, to, buf, limit, n) mem_addr from, to; char *buf; int *limit, *n; { mem_addr i, j; mem_addr tmp; for (i = from & 0xfffffffc; i < to; i += BYTES_PER_WORD) { mem_word val; /* Look for a block of 4 or more zero memory words */ for (j = 0; i + j < to; j += BYTES_PER_WORD) { READ_MEM_WORD (val, i + j); if (val != 0) break; } if ((i + j < to) && j != 0) j = j - BYTES_PER_WORD; if (j >= 4 * BYTES_PER_WORD) { sprintf (&buf[*n], "[0x%08x]...[0x%08x] 0x00000000\n", i, i +j); *n += strlen (&buf[*n]); if ((*limit - *n) < 1*K) { *limit = 2 * *limit; if ((buf = (char *) realloc (buf, *limit)) == 0) fatal_error ("realloc failed\n"); } i = i + j; continue; } /* Otherwise, print the next four words on a single line */ sprintf (&buf[*n], "[0x%08x] 0x%08x", i, val); *n += strlen (&buf[*n]); tmp = i; for ( ; i % 16 != 12; ) { i += BYTES_PER_WORD; READ_MEM_WORD (val, i); sprintf (&buf[*n], " 0x%08x", val); *n += strlen (&buf[*n]); } sprintf(&buf[*n], " - "); *n += strlen (&buf[*n]); READ_MEM_BYTE (val, tmp); sprintf(&buf[*n], " %s", ASCII_rep[val&0x7f]); *n += strlen (&buf[*n]); for ( ; tmp % 16 != 15; ) { tmp += 1; READ_MEM_BYTE (val, tmp); sprintf(&buf[*n], " %s", ASCII_rep[val&0x7f]); *n += strlen (&buf[*n]); } sprintf (&buf[*n], "\n"); *n += 1; if ((*limit - *n) < 1*K) { *limit = 2 * *limit; if ((buf = (char *) realloc (buf, *limit)) == 0) fatal_error ("realloc failed\n"); } } return (buf); } void initialize_console () { XawTextEnableRedisplay (console); writeText (console, "\n"); } void clear_console_display (void) { Arg args[10]; Cardinal n = 0; XtDestroyWidget (console); /* destroy previous console */ XtSetArg (args[n], XtNeditType, XawtextRead); n++; XtSetArg (args[n], XtNscrollVertical, XawtextScrollWhenNeeded); n++; XtSetArg (args[n], XtNpreferredPaneSize, TEXTHEIGHT * 24); n++; XtSetArg (args[n], XtNwidth, TEXTWIDTH * 80); n++; console = XtCreateManagedWidget ("console", asciiTextWidgetClass, *pane1_ptr, args, n); console_out = (int) console; } /* Print an error message. */ void error (char *string) /* Display only */ { char io_buffer [IO_BUFFSIZE]; sprintf (io_buffer, "%s", string); if (message != 0) writeText (message, io_buffer); else fprintf (stderr, "%s", io_buffer); } int run_error (char *string) /* Display and return to top level */ { char io_buffer [IO_BUFFSIZE]; sprintf (io_buffer, "%s", string); if (message != 0) writeText (message, io_buffer); else fprintf (stderr, "%s", io_buffer); if (spim_is_running) longjmp (spim_top_level_env, 1); return (0); /* So it can be used in expressions */ } void write_output (long w, char *string) { char io_buffer [IO_BUFFSIZE]; if (((Widget) w) == console && !console_is_visible) { XtPopup (shell1, XtGrabNone); console_is_visible = 1; } else if (((Widget) w) == terminal && !terminal_is_visible) { XtPopup (shell2, XtGrabNone); terminal_is_visible = 1; } sprintf (io_buffer, "%s", string); writeText (((Widget) w), io_buffer); } static void writeText (w, s) Widget w; char *s; { XawTextBlock textblock; XawTextPosition ip = XawTextGetInsertionPoint (w); if (!s || strlen (s) == 0) return; textblock.firstPos = 0; textblock.length = strlen (s); textblock.ptr = s; textblock.format = FMT8BIT; XawTextReplace (w, ip, ip, &textblock); XawTextSetInsertionPoint (w, XawTextGetInsertionPoint (w) + textblock.length); } #define QSIZE 256 static char cqueues[QSIZE][2]; static char chead[2]; static char ctail[2]; static void enqueue(char c, int q) { char tmp; tmp = (ctail[q] + 1) % QSIZE; if (tmp == chead[q]) { XBell(XtDisplay(toplevel), BELL_VOLUME); return; } cqueues[ctail[q]][q] = c; ctail[q] = tmp; } static int dequeue(int q) { char c; if (chead[q] == ctail[q]) return -1; c = cqueues[chead[q]][q]; chead[q] = (chead[q] + 1) % QSIZE; return c; } int read_input_maybe (int which) /* Returns -1 on all other events */ /* Should _not_ block ever! */ { if (!console_is_visible) { XtPopup (shell1, XtGrabNone); console_is_visible = 1; } PollInput(); return dequeue(which); } /* Simulate the semantics of fgets, not gets, on an x-window. */ void read_input (char *str, int str_size) { char *ptr, *old_ptr; int c; ptr = str; str_size -= 1; /* Reserve space for null */ if (!console_is_visible) { XtPopup (shell1, XtGrabNone); console_is_visible = 1; } while (1) { PollInput(); while (-1 == (c = dequeue(0))) { display_data_seg(); NextEvent(); } old_ptr = ptr; *ptr++ = c; *ptr = '\0'; str_size--; writeText (console, old_ptr); if ((str_size <= 0) || (c == '\n')) return; } } void HandleEvent(XEvent *event) { char buffer; KeySym key; XComposeStatus compose; int charcount; if (event->type == KeyPress) { charcount = XLookupString (&(event->xkey), &buffer, 1, &key, &compose); switch (key) { case XK_Shift_L: case XK_Shift_R: case XK_Control_L: case XK_Control_R: case XK_Caps_Lock: case XK_Shift_Lock: case XK_Meta_L: case XK_Meta_R: case XK_Alt_L: case XK_Alt_R: XtDispatchEvent(event); return; case XK_Return: case XK_KP_Enter: buffer = '\n'; default: if (buffer == 3) { XtDispatchEvent(event); return; } if (event->xkey.window == XtWindow(console)) enqueue(buffer & 0x7f, 0); else if (event->xkey.window == XtWindow(terminal)) { enqueue(buffer & 0x7f, 1); } else { XtDispatchEvent(event); return; } } return; } XtDispatchEvent (event); } void PollInput() { XEvent event; while (XtAppPending(app_context)) { XtAppNextEvent(app_context, &event); HandleEvent(&event); } } static void NextEvent() { XEvent event; XtAppNextEvent(app_context, &event); HandleEvent(&event); }