📄 pcspimview.cpp
字号:
// SPIM S20 MIPS simulator.
// Definitions for the SPIM S20.
//
// Copyright (C) 1990-2004 by James Larus (larus@cs.wisc.edu).
// ALL RIGHTS RESERVED.
// Changes for DOS and Windows versions by David A. Carley (dac@cs.wisc.edu)
//
// SPIM is distributed under the following conditions:
//
// You may make copies of SPIM for your own use and modify those copies.
//
// All copies of SPIM must retain my name and copyright notice.
//
// You may not sell SPIM or distributed SPIM in conjunction with a
// commerical product or service without the expressed written consent of
// James Larus.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE.
/* $Header: /Software/SPIM/PCSpim/PCSpimView.cpp 22 2/05/05 3:53p Jim $ */
// PCSpimView.cpp : implementation of the CPCSpimView class
//
#include "stdafx.h"
#include "PCSpim.h"
#include "PCSpimDoc.h"
#include "PCSpimView.h"
#include "MainFrm.h"
#include "ConsoleWnd.h"
#include "util.h"
#include "SpimReg.h"
#ifndef EXCEPTION_FILE_PATH
#define EXCEPTION_FILE_PATH "C:\\Program Files\\PCSpim\\exceptions.s"
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CPCSpimView
IMPLEMENT_DYNCREATE(CPCSpimView, CView)
BEGIN_MESSAGE_MAP(CPCSpimView, CView)
//{{AFX_MSG_MAP(CPCSpimView)
ON_WM_CREATE()
ON_COMMAND(ID_SIMULATOR_REINITIALIZE, OnSimulatorReinitialize)
ON_COMMAND(ID_SIMULATOR_CLEAR_REGISTERS, OnSimulatorClearRegisters)
ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
ON_COMMAND(ID_SIMULATOR_GO, OnSimulatorRun)
ON_COMMAND(ID_SIMULATOR_BREAKPOINTS, OnSimulatorBreakpoints)
ON_COMMAND(ID_SIMULATOR_SETVALUE, OnSimulatorSetvalue)
ON_COMMAND(ID_SIMULATOR_BREAK, OnSimulatorBreak)
ON_COMMAND(ID_SIMULATOR_SETTINGS, OnSimulatorSettings)
ON_UPDATE_COMMAND_UI(ID_SIMULATOR_RELOAD, OnUpdateSimulatorReload)
ON_COMMAND(ID_SIMULATOR_RELOAD, OnSimulatorReload)
ON_UPDATE_COMMAND_UI(ID_SIMULATOR_BREAK, OnUpdateSimulatorBreak)
ON_COMMAND(ID_SIMULATOR_STEP, OnSimulatorStep)
ON_COMMAND(ID_SIMULATOR_MULTISTEP, OnSimulatorMultistep)
ON_COMMAND(ID_SIMULATOR_DISPLAYSYMBOLS, OnSimulatorDisplaysymbols)
ON_COMMAND(ID_WINDOW_CASCADE, OnWindowCascade)
ON_COMMAND(ID_WINDOW_NEXT, OnWindowNext)
ON_COMMAND(ID_WINDOW_PREVIOUS, OnWindowPrevious)
ON_COMMAND(ID_WINDOW_TILE, OnWindowTile)
ON_COMMAND(ID_WINDOW_CLEAR_CONSOLE, OnWindowClearConsole)
ON_UPDATE_COMMAND_UI(ID_SIMULATOR_SETVALUE, OnUpdateSimulatorSetvalue)
ON_UPDATE_COMMAND_UI(ID_SIMULATOR_BREAKPOINTS, OnUpdateSimulatorBreakpoints)
ON_UPDATE_COMMAND_UI(ID_SIMULATOR_DISPLAYSYMBOLS, OnUpdateSimulatorDisplaysymbols)
ON_UPDATE_COMMAND_UI(ID_SIMULATOR_CLEAR_REGISTERS, OnUpdateSimulatorClearRegisters)
ON_UPDATE_COMMAND_UI(ID_SIMULATOR_REINITIALIZE, OnUpdateSimulatorReinitialize)
ON_COMMAND(ID_WINDOW_MESSAGES, OnWindowMessages)
ON_COMMAND(ID_WINDOW_REGISTERS, OnWindowRegisters)
ON_COMMAND(ID_WINDOW_TEXTSEG, OnWindowTextseg)
ON_COMMAND(ID_WINDOW_DATASEG, OnWindowDataseg)
ON_COMMAND(ID_WINDOW_CONSOLE, OnWindowConsole)
ON_WM_DESTROY()
ON_COMMAND(ID_WINDOW_ARRANGEICONS, OnWindowArrangeicons)
ON_COMMAND(ID_FILE_SAVE_LOG, OnFileSaveLog)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPCSpimView construction/destruction
CPCSpimView::CPCSpimView()
{
g_fRunning = FALSE;
m_fStackInitialized = FALSE;
m_fCapture = FALSE;
m_fConsoleMinimized = TRUE;
m_fSimulatorInitialized = FALSE;
m_strCurFilename.Empty();
}
CPCSpimView::~CPCSpimView()
{
}
/////////////////////////////////////////////////////////////////////////////
// CPCSpimView drawing
void CPCSpimView::OnDraw(CDC* pDC)
{
CPCSpimDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDC->IsPrinting())
{
RECT r;
GetClientRect(&r);
pDC->FillSolidRect(&r, GetSysColor(COLOR_3DFACE));
}
}
/////////////////////////////////////////////////////////////////////////////
// CPCSpimView diagnostics
#ifdef _DEBUG
void CPCSpimView::AssertValid() const
{
CView::AssertValid();
}
void CPCSpimView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CPCSpimDoc* CPCSpimView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CPCSpimDoc)));
return (CPCSpimDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CPCSpimView message handlers
#define GETCHILDWININFO(szRegPathStub) \
if (g_fSaveWinPos) \
{ \
if (pApp->GetSetting(szRegPathStub##POS, &r)) \
pr = &r; \
\
dwStyle = WS_CHILD; \
nMinMax = pApp->GetSetting(szRegPathStub##MINMAX, SW_SHOW); \
} \
else \
{ \
r.left = r.top = r.right = r.bottom = 0; pr = NULL; \
nMinMax = SW_SHOW ; \
}
static void
InitSpimWins(CEdit& Win, RECT& r, int nMinMax, BOOL ScrollVert, BOOL ScrollHorz)
{
Win.ShowWindow(nMinMax);
if (ScrollVert)
Win.ShowScrollBar(SB_VERT, TRUE);
if (ScrollHorz)
Win.ShowScrollBar(SB_HORZ, TRUE);
}
int CPCSpimView::OnCreate(LPCREATESTRUCT pcs)
{
if (CView::OnCreate(pcs) == -1)
return -1;
// The simulation support code needs to be able to access this.
g_pView = this;
// Don't draw over the top of the children.
DWORD dwStyle = GetWindowLong(m_hWnd, GWL_STYLE);
dwStyle |= WS_CLIPCHILDREN;
SetWindowLong(m_hWnd, GWL_STYLE, dwStyle);
CPCSpimApp *pApp = (CPCSpimApp *)AfxGetApp();
RECT r, *pr;
int nMinMax;
// Console is a special case. We save position, but not minmax.
if (g_fSaveWinPos && pApp->GetSetting(SPIM_REG_CONSOLEPOS, &r))
{
pr = &r;
}
else
{
pr = NULL;
}
m_wndConsole.Create(NULL,
"Console",
pr,
ES_AUTOHSCROLL | ES_AUTOVSCROLL,
0,
WS_POPUP);
m_wndConsole.m_fActAsConsole = TRUE;
// Messages window
GETCHILDWININFO(SPIM_REG_MESSAGES);
m_wndMessages.Create(ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE,
r,
this,
1);
InitSpimWins(m_wndMessages, r, nMinMax, TRUE, TRUE);
// Data segment window
GETCHILDWININFO(SPIM_REG_DATASEG);
m_wndDataSeg.Create(ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE,
r,
this,
1);
InitSpimWins(m_wndDataSeg, r, nMinMax, TRUE, TRUE);
m_wndDataSeg.SetLimitText(0x7FFFFFFE); // Allow lots of space
// Text segment window
GETCHILDWININFO(SPIM_REG_TEXTSEG);
m_wndTextSeg.Create(ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE | ES_NOHIDESEL,
r,
this,
1);
InitSpimWins(m_wndTextSeg, r, nMinMax, TRUE, TRUE);
m_wndTextSeg.SetLimitText(0x7FFFFFFE); // Allow lots of space
// Register window
GETCHILDWININFO(SPIM_REG_REGISTERS);
m_wndRegisters.Create(ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE,
r,
this,
1);
InitSpimWins(m_wndRegisters, r, nMinMax, TRUE, TRUE);
// Get font info from registry and use to set windows' font.
//
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
strcpy(lf.lfFaceName, (char*)pApp->GetSetting(SPIM_REG_FONTFACE, "Courier")); /* Default: Courier 16pt, normal weight */
lf.lfHeight = pApp->GetSetting(SPIM_REG_FONTHEIGHT, 16);
lf.lfWeight = pApp->GetSetting(SPIM_REG_FONTWEIGHT, 400);
lf.lfItalic = pApp->GetSetting(SPIM_REG_FONTITALIC, 0);
SetSpimFont(&lf);
// Load settings
Initialize();
// Create the breakpoint window (should be initially hidden)
m_dlgBP.Create(this);
return 0;
}
void CPCSpimView::WriteToMessage(LPCTSTR szText)
{
if (m_fCapture)
{
TCHAR *szTemp = MakeCRLFValid(szText);
m_strMsgCaptureBuf += szTemp;
delete [] szTemp;
}
else
{
CString buf ('\0', m_wndMessages.GetWindowTextLength());
m_wndMessages.GetWindowText(buf);
char* text2 = MakeCRLFValid(szText);
buf += text2;
delete text2;
m_wndMessages.SetWindowText(buf);
// Position last few lines in window.
m_wndMessages.LineScroll(m_wndMessages.GetLineCount() - 4, 0) ;
m_wndMessages.UpdateWindow();
}
}
void CPCSpimView::WriteToConsole(LPCTSTR szText)
{
m_wndConsole.WriteText(szText);
}
void CPCSpimView::Initialize()
{
CPCSpimApp *pApp = (CPCSpimApp *)AfxGetApp();
// Load the settings from the registry.
bare_machine = pApp->GetSetting(SPIM_REG_BARE, FALSE);
delayed_branches = pApp->GetSetting(SPIM_REG_DELAYEDBRANCHES, FALSE);
delayed_loads = pApp->GetSetting(SPIM_REG_DELAYEDLOADS, FALSE);
accept_pseudo_insts = pApp->GetSetting(SPIM_REG_PSEUDO, TRUE);
quiet = pApp->GetSetting(SPIM_REG_QUIET, FALSE);
mapped_io = pApp->GetSetting(SPIM_REG_MAPPEDIO, TRUE);
g_fLoadExceptionHandler = pApp->GetSetting(SPIM_REG_LOADEXCEPTION, TRUE);
g_fGenRegHex = pApp->GetSetting(SPIM_REG_GENREG_HEX, TRUE);
g_fFPRegHex = pApp->GetSetting(SPIM_REG_FPREG_HEX, FALSE);
g_checkUndefinedSymbols = pApp->GetSetting(SPIM_REG_CHECK_UNDEF, TRUE);
LPCTSTR szBuf = pApp->GetSetting(SPIM_REG_EXCEPTIONFILE, EXCEPTION_FILE_PATH);
delete [] exception_file_name;
exception_file_name = new TCHAR[lstrlen(szBuf) + 1];
lstrcpy(exception_file_name, szBuf);
if (lstrlen(exception_file_name) == 0)
{
g_fLoadExceptionHandler = FALSE;
}
if (bare_machine)
{
delayed_branches = 1;
delayed_loads = 1;
}
// We're using these just as unique identifiers in the output code.
message_out.i = 0, console_out.i = 1;
// Now that we've set all of the defaults, and loaded the
// registry settings, process the commandline for overrides.
ProcessCommandLine();
InitializeSimulator();
if (!m_strCurFilename.IsEmpty())
{
LoadFile(m_strCurFilename); // From command line
}
}
void CPCSpimView::InitializeSimulator()
{
OFSTRUCT ofs;
m_wndConsole.Clear();
m_wndMessages.Clear();
l_TestExceptionExists:
if (g_fLoadExceptionHandler &&
(HFILE_ERROR == OpenFile(exception_file_name, &ofs, OF_EXIST)))
{
int nRet
= MessageBox(
"The exception file specified in the Settings dialog does not exist.\n"
"Please specify an existing file, or turn off exception file loading.\n"
"\n"
"Would you like to open the Settings dialog?",
NULL, MB_YESNO | MB_ICONEXCLAMATION);
if (nRet == IDYES)
{
SendMessage(WM_COMMAND, MAKEWPARAM(ID_SIMULATOR_SETTINGS, 0), NULL);
goto l_TestExceptionExists;
}
return;
}
else
{
write_startup_message();
initialize_world(g_fLoadExceptionHandler ? exception_file_name : NULL);
// We need to set up the stack for the next time we run.
m_fStackInitialized = FALSE;
m_fSimulatorInitialized = TRUE;
UpdateStatusDisplay();
HighlightCurrentInstruction();
}
}
void CPCSpimView::OnSimulatorReinitialize()
{
ReinitializeSimulator();
m_strCurFilename.Empty();
}
void CPCSpimView::ReinitializeSimulator()
{
write_output(message_out, "Memory and registers cleared and the simulator reinitialized.\n\n");
InitializeSimulator();
}
void CPCSpimView::OnSimulatorClearRegisters()
{
initialize_registers();
UpdateStatusDisplay();
write_output(message_out, "Registers cleared.\n\n");
}
void CPCSpimView::OnFileOpen()
{
TCHAR szFilters[] = "Assembly files (*.s; *.asm)|*.s;*.asm|All Files (*.*)|*.*||";
// Prompt for a filename.
CFileDialog dlg(TRUE,
NULL,
NULL,
OFN_HIDEREADONLY | OFN_FILEMUSTEXIST,
szFilters,
this);
if (dlg.DoModal() != IDOK)
return;
// Load the file
LoadFile(dlg.GetPathName());
}
void CPCSpimView::InitStack(LPCTSTR szCmdLine)
{
int argc = 0;
char *argv[10000];
char *a;
char *argsOrig = new char[lstrlen(szCmdLine) + 1];
char *args = argsOrig;
lstrcpy(args, szCmdLine);
if (m_fStackInitialized)
{
return;
}
while (*args != '\0')
{
/* Skip leading blanks */
while (*args == ' ' || *args == '\t') args++;
/* First non-blank char */
a = args;
/* Last non-blank, non-null char */
while (*args != ' ' && *args != '\t' && *args != '\0') args++;
/* Terminate word */
if (a != args)
{
if (*args != '\0')
*args++ = '\0'; /* Null terminate */
argv [argc++] = a;
}
}
initialize_run_stack (argc, argv);
m_fStackInitialized = TRUE;
delete [] argsOrig;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -