home *** CD-ROM | disk | FTP | other *** search
- /* SPIM S20 MIPS simulator.
- Copyright (C) 1990 by James Larus (larus@cs.wisc.edu).
-
- Macintosh Version by Philip Delaquess (delaques@gcg.com)
- Copyright (C) 1993 by Saunders College Publishing and Morgan Kaufman Publishers.
-
- 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.
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <setjmp.h>
-
- #include "mactext.h"
-
- #include "spim.h"
- #include "inst.h"
- #include "mem.h"
- #include "reg.h"
-
- char mess_buff[256];
- int source_file;
-
- static Boolean running = TRUE, RunningCPU = FALSE;
-
- DialogPtr RunningDlg; /* this little f--ker is global */
- static DialogPtr RunDlg, StepDlg, BreakpointsDlg, PrintDlg, SetDlg;
- static Rect DragBoundary;
-
- static SPIMTextWindow TextWindow, DataWindow, ConsoleWindow, SessionWindow;
-
- static jmp_buf JumpBuff;
-
- static short StartupVolume; /* where trap handler must reside */
-
- static CursHandle WristWatch;
-
- /* This handles fatal errors from all over. */
-
- void MacFatalError(char *message)
- {
- char *s;
- DialogPtr dialog;
- short item;
-
- FreeMacMemory();
- for (s = message; *s; ++s)
- if ( *s < ' ' ) *s = ' ';
- CtoPstr(message);
- ParamText(message, "\p", "\p", "\p");
- dialog = GetNewDialog(136, 0, (WindowPtr) -1);
- InitCursor();
- ModalDialog(0, &item);
- ExitToShell();
- } /* MacFatalError */
-
- /* This tells the user why SPIM stopped, and asks what to do.
- It returns TRUE if the user want to keep going, or FALSE if she wants to abort.
- */
-
- static Boolean doHaltDialog(Boolean interrupted)
- {
- char pcString[32];
- DialogPtr dialog;
- short item;
-
- sprintf(pcString, "0x%08X", PC);
- CtoPstr(pcString);
- ParamText(interrupted ? "\pInterrupted" : "\pBreakpoint",
- pcString, "\p", "\p");
- dialog = GetNewDialog(135, 0, (WindowPtr) -1);
- ModalDialog(0, &item);
- DisposDialog(dialog);
- return item == 1 ? TRUE : FALSE;
- } /* doHaltDialog */
-
- /* This reports normal completion of a program. Is this necessary? */
-
- static void reportCompletion()
- {
- #if 0
- static DialogPtr dialog;
- short item;
-
- if ( !dialog )
- dialog = GetNewDialog(137, 0, (WindowPtr) -1);
- else {
- ShowWindow(dialog);
- SelectWindow(dialog);
- }
- ModalDialog(0, &item);
- HideWindow(dialog);
- #endif
- } /* reportCompletion */
-
- /* This prepares for a long jump, then runs the program for a while. */
-
- static void execute_program(mem_addr start, int steps, int display, int cont)
- {
- PC = start;
- while ( 1 ) {
- /* are we being sent here by a long jump? */
- if ( setjmp(JumpBuff) ) {
- /* interrupted -- do we continue? */
- HideWindow(RunningDlg);
- if ( !doHaltDialog(TRUE) )
- break; /* do not continue */
- else {
- /* convert to a run command even if we were stepping */
- steps = DEFAULT_RUN_STEPS;
- display = 0;
- cont = 0;
- }
- }
- /* start or continue running */
- ShowWindow(RunningDlg);
- SelectWindow(RunningDlg);
- RunningCPU = TRUE;
- if ( !run_program(PC, steps, display, cont) ) {
- /* no breakpoint -- all done */
- RunningCPU = FALSE;
- HideWindow(RunningDlg);
- if ( !display )
- reportCompletion();
- break;
- }
- /* breakpoint -- do we continue? */
- RunningCPU = FALSE;
- HideWindow(RunningDlg);
- if ( !doHaltDialog(FALSE) )
- break;
- /* step over the breakpoint */
- RunningCPU = TRUE;
- run_program(PC, 1, display, 1);
- RunningCPU = FALSE;
- }
- } /* execute_program */
-
- /* This sees if the Halt button in the program run dialog got nailed. */
-
- int IntCheck()
- {
- EventRecord event;
- DialogPtr dlg;
- short item;
-
- if ( GetNextEvent(everyEvent, &event) ) {
- if ( IsDialogEvent(&event) ) {
- if ( DialogSelect(&event, &dlg, &item) && dlg == RunningDlg && item == 2 )
- return 1;
- }
- }
- return 0;
- } /* IntCheck */
-
- /* This copes with the detection of an interrupt. */
-
- void control_c_seen()
- {
- longjmp(JumpBuff, 1);
- } /* control_c_seen */
-
- /* This gets a dialog's edit text as a C string. */
-
- static void getITextAsCStr(DialogPtr dialog, short item, char *text)
- {
- short type;
- Handle handle;
- Rect box;
- Str255 result;
-
- GetDItem(dialog, item, &type, &handle, &box);
- GetIText(handle, result);
- PtoCstr(result);
- strcpy(text, (char *) result);
- } /* getITextAsCStr */
-
- /* This handles the buttons in the Step dialog. */
-
- static void doStep(short item)
- {
- char nsText[256];
- int address, nSteps;
-
- getITextAsCStr(StepDlg, 2, nsText);
- sscanf(nsText, "%d", &nSteps);
- address = starting_address();
- switch ( item ) {
- case 3 :
- /* step */
- execute_program(address, nSteps, 1, 1);
- FormatRegisters();
- if ( data_modified )
- CountData();
- data_modified = 0;
- RecenterText();
- break;
- case 4 :
- /* run */
- HideWindow(StepDlg);
- execute_program(address, DEFAULT_RUN_STEPS, 0, 0);
- FormatRegisters();
- if ( data_modified )
- CountData();
- data_modified = 0;
- RecenterText();
- break;
- }
- } /* doStep */
-
- static void doRun()
- {
- char aText[256];
- int address;
-
- if ( PC )
- address = PC;
- else
- address = find_symbol_address(DEFAULT_RUN_LOCATION);
- getITextAsCStr(RunDlg, 2, aText);
- sscanf(aText, "%d", &address);
- if ( !address )
- address = starting_address();
- HideWindow(RunDlg);
- execute_program(address, DEFAULT_RUN_STEPS, 0, 0);
- FormatRegisters();
- if ( data_modified )
- CountData();
- data_modified = 0;
- RecenterText();
- } /* doRun */
-
- /* This performs a set values command. */
-
- static void setValues()
- {
- char address[256], *p, *q, *eptr, ebuf[256];
- mem_word value, addr;
- int reg_no;
-
- getITextAsCStr(SetDlg, 4, address);
- value = strtoul(address, NULL, 16);
- getITextAsCStr(SetDlg, 2, address);
-
- for (p = address; isspace(*p); ++p)
- ;
- for (q = p; *q; ++q)
- if ( *q >= 'a' && *q <= 'z' )
- *q += 'A' - 'a';
-
- if ( (reg_no = register_name_to_number(p)) < 0 ) {
- if ( strchr("Rr$", *p) )
- reg_no = register_name_to_number(p + 1);
- }
-
- if ( !reg_no )
- error("Cannot modify register zero.\n");
- else if ( reg_no > 0 ) {
- R[reg_no] = value;
- FormatRegisters();
- }
- else if ( !strncmp(p, "STATUS", 6) ) {
- Status_Reg = value;
- FormatRegisters();
- }
- else if ( !strncmp(p, "EPC", 3) ) {
- EPC = value;
- FormatRegisters();
- }
- else if ( !strncmp(p, "PC", 2) ) {
- PC = value;
- FormatRegisters();
- }
- else {
- addr = strtoul(p, &eptr, 16);
- if ( eptr == p ) {
- sprintf(ebuf, "Unknown location: %s\n", p);
- error(ebuf);
- }
- else {
- SET_MEM_WORD(addr, value);
- CountData();
- }
- }
- } /* setValues */
-
- /* This turns the text of an address spec into an address. */
-
- static mem_addr getAddress(char *p)
- {
- while(isspace(*p))
- p++;
- if(isdigit(*p))
- return strtoul(p, NULL, 16);
- else
- return find_symbol_address(p);
- } /* end getAddress() */
-
- /* This performs a print values command. */
-
- static void printValues(short item)
- {
- mem_addr from, to;
- char address[256];
-
- if ( item == 6 )
- print_symbols();
- else {
- getITextAsCStr(PrintDlg, 2, address);
- from = getAddress(address);
- getITextAsCStr(PrintDlg, 4, address);
- to = getAddress(address);
- do
- print_mem(from);
- while ( (from += BYTES_PER_WORD) <= to );
- }
- } /* printValues */
-
- /* This handles a button in the breakpoints dialog. */
-
- static void doBreakpoint(short item)
- {
- char address[256];
-
- getITextAsCStr(BreakpointsDlg, 2, address);
- switch ( item ) {
- case 3 :
- add_breakpoint(getAddress(address));
- break;
- case 4 :
- delete_breakpoint(getAddress(address));
- break;
- case 5 :
- list_breakpoints();
- break;
- }
- } /* doBreakpoint */
-
- /* This handles a hit on any of my dialog buttons. */
-
- static void doDialogEvent(DialogPtr dialog, short item)
- {
- if ( dialog == SetDlg )
- setValues();
- else if ( dialog == PrintDlg )
- printValues(item);
- else if ( dialog == BreakpointsDlg )
- doBreakpoint(item);
- else if ( dialog == StepDlg )
- doStep(item);
- else if ( dialog == RunDlg )
- doRun();
- } /* doDialogEvent */
-
- static void showAboutBox()
- {
- DialogPtr dlg;
- short item;
-
- dlg = GetNewDialog(128, 0, (WindowPtr) -1);
- ModalDialog(0, &item);
- DisposDialog(dlg);
- } /* showAboutBox */
-
- /* This puts up the standard input file dialog. If the user picks a file, we
- hand it off to the parser.
- */
-
- static void selectLoadFile()
- {
- Point upperLeft;
- SFTypeList typeList;
- SFReply reply;
- extern Boolean Assembling;
- extern short MessageCount;
-
- upperLeft.h = upperLeft.v = 100;
- typeList[0] = 'TEXT';
- SFGetFile(upperLeft, "\p", 0, 1, typeList, 0, &reply);
- if ( reply.good ) {
- SetVol(0, reply.vRefNum);
- PtoCstr(reply.fName);
- MessageCount = 0;
- Assembling = TRUE;
- SetCursor(*WristWatch);
- read_assembly_file((char *) (reply.fName));
- Assembling = FALSE;
- CountText();
- CountData();
- InitCursor();
- write_output(message_out, "Loaded ");
- write_output(message_out, (char *) reply.fName);
- write_output(message_out, ".\n");
- }
- } /* selectLoadFile */
-
- static void doMenuEvent(long resultCode)
- {
- short menuCode, itemCode, currentVolume, type;
- Handle hand;
- Rect box;
- mem_addr address;
- Str255 addrStr;
-
- menuCode = HiWord(resultCode);
- itemCode = LoWord(resultCode);
- switch ( menuCode ) {
- case 128 :
- /* apple menu */
- if ( itemCode == 1 )
- showAboutBox();
- else if ( itemCode == 2 )
- SelectTextWindow(&Help);
- else {
- Str255 theItem;
- GetItem(GetMHandle(menuCode), itemCode, theItem);
- OpenDeskAcc(theItem);
- }
- break;
- case 129 :
- /* file menu */
- switch ( itemCode ) {
- case 1 :
- selectLoadFile();
- break;
- case 4 :
- running = FALSE;
- break;
- }
- break;
- case 130 :
- /* edit menu */
- break;
- case 131 :
- /* window menu */
- switch ( itemCode ) {
- case 1 :
- SelectTextWindow(&Registers);
- break;
- case 2 :
- SelectTextWindow(&Text);
- break;
- case 3 :
- SelectTextWindow(&Data);
- break;
- case 4 :
- SelectTextWindow(&Session);
- break;
- case 5 :
- SelectTextWindow(&Console);
- break;
- case 7 :
- /* tile vertically */
- TileTextWindows(TRUE);
- break;
- case 8 :
- /* tile horizontally */
- TileTextWindows(FALSE);
- break;
- case 9 :
- /* close all */
- HideWindow(Registers.window);
- HideWindow(Text.window);
- HideWindow(Data.window);
- HideWindow(Session.window);
- HideWindow(Console.window);
- break;
- }
- break;
- case 132 :
- /* options menu */
- switch ( itemCode ) {
- case 1 :
- bare_machine = 1 - bare_machine;
- CheckItem(GetMHandle(menuCode), itemCode, bare_machine ? TRUE : FALSE);
- break;
- case 2 :
- quiet = 1 - quiet;
- CheckItem(GetMHandle(menuCode), itemCode, quiet ? TRUE : FALSE);
- break;
- }
- break;
- case 133 :
- /* execute menu */
- switch ( itemCode ) {
- case 1 :
- if ( PC )
- address = PC;
- else {
- address = find_symbol_address(DEFAULT_RUN_LOCATION);
- if ( !address )
- address = TEXT_BOT;
- }
- sprintf((char *) addrStr, "0x%X", address);
- CtoPstr(addrStr);
- GetDItem(RunDlg, 2, &type, &hand, &box);
- SetIText(hand, addrStr);
- SelIText(RunDlg, 2, 0, 32767);
- ShowWindow(RunDlg);
- SelectWindow(RunDlg);
- break;
- case 2 :
- SelIText(StepDlg, 2, 0, 32767);
- ShowWindow(StepDlg);
- SelectWindow(StepDlg);
- break;
- case 4 :
- SelIText(BreakpointsDlg, 2, 0, 32767);
- ShowWindow(BreakpointsDlg);
- SelectWindow(BreakpointsDlg);
- break;
- }
- break;
- case 134 :
- /* data menu */
- switch ( itemCode ) {
- case 1 :
- SelIText(PrintDlg, 2, 0, 32767);
- ShowWindow(PrintDlg);
- SelectWindow(PrintDlg);
- break;
- case 2 :
- SelIText(SetDlg, 2, 0, 32767);
- ShowWindow(SetDlg);
- SelectWindow(SetDlg);
- break;
- }
- break;
- case 200 :
- /* clear submenu */
- switch ( itemCode ) {
- case 1 :
- /* clear registers */
- initialize_registers();
- write_output(message_out, "Cleared registers.\n");
- FormatRegisters();
- break;
- case 2 :
- /* clear console */
- ClearConsole();
- write_output(message_out, "Cleared console.\n");
- break;
- case 3 :
- /* clear all */
- ResetMacMemory();
- ClearConsole();
- GetVol(0, ¤tVolume);
- SetVol(0, StartupVolume);
- text_seg = 0;
- data_seg = 0;
- stack_seg = 0;
- k_text_seg = 0;
- k_data_seg = 0;
- FGR = 0;
- ReinitInst();
- initialize_world(!bare_machine);
- SetVol(0, currentVolume);
- write_output(message_out, "Cleared registers, memory and console.\n");
- CountText();
- CountData();
- break;
- }
- break;
- }
- HiliteMenu(0);
- } /* doMenuEvent */
-
- /* This handles mouse-down events. */
-
- static void doMouseDown(EventRecord *event)
- {
- WindowPtr whichWindow;
- short code;
-
- switch ( code = FindWindow(event->where, &whichWindow) ) {
- case inDesk :
- break;
- case inMenuBar :
- doMenuEvent(MenuSelect(event->where));
- break;
- case inSysWindow :
- SystemClick(event, whichWindow);
- break;
- case inContent :
- if ( whichWindow == FrontWindow() )
- ClickTextWindow(whichWindow, event);
- else
- SelectWindow(whichWindow);
- break;
- case inDrag :
- DragWindow(whichWindow, event->where, &DragBoundary);
- break;
- case inGrow :
- SizeTextWindow(whichWindow, event->where);
- break;
- case inGoAway :
- if ( TrackGoAway(whichWindow, event->where) )
- HideWindow(whichWindow);
- break;
- case inZoomIn :
- case inZoomOut :
- if ( TrackBox(whichWindow, event->where, code) ) {
- ZoomWindow(whichWindow, code, TRUE);
- RecalculateTextWindow(whichWindow);
- }
- break;
- }
- } /* doMouseDown */
-
- main()
- {
- Handle mBar;
- MenuHandle menu;
- EventRecord event;
- Boolean gotEvent, isDlgEvent;
-
- /* init mac toolbox */
- MaxApplZone();
- InitGraf(&thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(0);
-
- WristWatch = GetCursor(watchCursor);
- SetCursor(*WristWatch);
-
- /* init this app */
- mBar = GetNewMBar(128);
- SetMenuBar(mBar);
- DrawMenuBar();
- menu = GetMHandle(128);
- AddResMenu(menu, 'DRVR');
- menu = GetMenu(200);
- InsertMenu(menu, -1);
-
- RunDlg = GetNewDialog(129, 0, (WindowPtr) -1);
- StepDlg = GetNewDialog(130, 0, (WindowPtr) -1);
- BreakpointsDlg = GetNewDialog(131, 0, (WindowPtr) -1);
- PrintDlg = GetNewDialog(132, 0, (WindowPtr) -1);
- SetDlg = GetNewDialog(133, 0, (WindowPtr) -1);
- RunningDlg = GetNewDialog(134, 0, (WindowPtr) -1);
-
- GetVol(0, &StartupVolume);
-
- DragBoundary = screenBits.bounds;
- InsetRect(&DragBoundary, 4, 4);
- DragBoundary.top += 20;
-
- InitTextWindows();
- message_out = (int) &Session;
- console_out = (int) &Console;
-
- CreateMacMemory();
- initialize_world(1);
-
- FormatRegisters();
- CountText();
- CountData();
-
- /* main loop */
- FlushEvents(everyEvent, 0);
- InitCursor();
- showAboutBox();
- SelectTextWindow(&Console);
- SelectTextWindow(&Session);
- TileTextWindows(TRUE);
- while ( running ) {
- gotEvent = GetNextEvent(everyEvent, &event);
- isDlgEvent = IsDialogEvent(&event);
- if ( isDlgEvent ) {
- DialogPtr whichDlg;
- short whichItem;
-
- if ( event.what == keyDown && event.modifiers & cmdKey )
- doMenuEvent(MenuKey(event.message & charCodeMask));
- else if ( DialogSelect(&event, &whichDlg, &whichItem) )
- doDialogEvent(whichDlg, whichItem);
-
- }
- else if ( gotEvent ) {
- switch ( event.what ) {
- case mouseDown :
- doMouseDown(&event);
- break;
- case keyDown :
- if ( event.modifiers & cmdKey )
- doMenuEvent(MenuKey(event.message & charCodeMask));
- break;
- case activateEvt :
- ActivateTextWindow((WindowPtr) event.message,
- event.modifiers & activeFlag ? TRUE : FALSE);
- break;
- case updateEvt :
- UpdateTextWindow((WindowPtr) event.message);
- break;
- }
- }
- }
- } /* main */
-
- void error(char *text)
- {
- write_output(message_out, text);
- }
-
- int run_error(char *text)
- {
- write_output(message_out, text);
- if ( RunningCPU )
- longjmp(JumpBuff, 1);
- return 0;
- }
-