📄 stop.c
字号:
/* * stop.c -- * * This procedure provides code that manipulates spies and stops * for the simulator. * * This file is part of DISC. It was modified by Yinong Zhang * (yinong@ecn.purdue.edu) from the file "stop.c" in the distribution * of "dlxsim" available at: * ftp://max.stanford.edu/pub/hennessy-patterson.software/dlx.tar.Z * * The original source code is copyright as follows: * * Copyright 1989 Regents of the University of California * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies. The University of California * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. * */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <tcl.h>#include "dlx.h"#include "sym.h"/* *---------------------------------------------------------------------- * * Stop_StopCmd -- * * This procedure is invoked to process the "stop" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */intStop_StopCmd(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ DLX *machPtr = (DLX *) clientData; int length; register Stop *stopPtr; Stop *prevPtr; MemWord *wordPtr; if (argc == 1) { Sim_Stop(machPtr); return TCL_OK; } length = strlen(argv[1]); /* * "At" option: create a new stop. */ if (strncmp(argv[1], "at", length) == 0) { unsigned int address; int result; char *end; if ((argc != 3) && (argc != 4)) { sprintf(interp->result, "wrong # args: should be \"%.50s at location [command]\"", argv[0]); return TCL_ERROR; } result = Sym_EvalExpr(machPtr, (char *) NULL, argv[2], 0, (int *) &address, &end); if (result != TCL_OK) { return result; } if (*end != 0) { sprintf(interp->result, "bad address \"%.50s\" in \"%.50s\" command", argv[2], argv[0]); return TCL_ERROR; } address = ADDR_TO_INDEX(address); if (address >= machPtr->numWords) { sprintf(interp->result, "location %.50s doesn't exist in the machine's memory", argv[2]); return TCL_ERROR; } wordPtr = &machPtr->memPtr[address]; for (stopPtr = wordPtr->stopList; stopPtr != NULL; stopPtr = stopPtr->nextPtr) { if (stopPtr->command == NULL) { sprintf(interp->result, "stop already set at %.50s", argv[2]); return TCL_OK; } prevPtr = stopPtr; } stopPtr = (Stop *) calloc(1, sizeof(Stop)); if (argc == 3) { stopPtr->command = (char *) NULL; } else { stopPtr->command = calloc(1, (unsigned) (strlen(argv[3]) + 1)); strcpy(stopPtr->command, argv[3]); } stopPtr->number = machPtr->stopNum; machPtr->stopNum += 1; stopPtr->address = INDEX_TO_ADDR(address); stopPtr->nextPtr = NULL; stopPtr->overallPtr = NULL; if (wordPtr->stopList == NULL) { wordPtr->stopList = stopPtr; } else { prevPtr->nextPtr = stopPtr; } if (machPtr->stopList == NULL) { machPtr->stopList = stopPtr; } else { for (prevPtr = machPtr->stopList; prevPtr->overallPtr != NULL; prevPtr = prevPtr->overallPtr) { /* Empty loop body. */ } prevPtr->overallPtr = stopPtr; } return TCL_OK; } /* * "Delete" option: eliminate a stop. */ if (strncmp(argv[1], "delete", length) == 0) { int number, i; char *end; if (argc < 3) { sprintf(interp->result, "wrong # args: should be \"%.50s delete num num ...\"", argv[0]); return TCL_ERROR; } for (i = 2; i < argc; i++) { number = strtol(argv[i], &end, 0); if (*end != 0) { sprintf(interp->result, "bad stop number \"%.50s\"", argv[i]); return TCL_ERROR; } for (stopPtr = machPtr->stopList; stopPtr != NULL; stopPtr = stopPtr->overallPtr) { if (stopPtr->number == number) { break; } prevPtr = stopPtr; } if (stopPtr == NULL) { sprintf(interp->result, "there is no stop \"%.50s\" defined", argv[i]); return TCL_ERROR; } if (machPtr->stopList == stopPtr) { machPtr->stopList = stopPtr->overallPtr; } else { prevPtr->overallPtr = stopPtr->overallPtr; } wordPtr = &machPtr->memPtr[ADDR_TO_INDEX(stopPtr->address)]; if (wordPtr->stopList == stopPtr) { wordPtr->stopList = stopPtr->nextPtr; } else { for (prevPtr = wordPtr->stopList; prevPtr != NULL; prevPtr = prevPtr->nextPtr) { if (prevPtr->nextPtr == stopPtr) { prevPtr->nextPtr = stopPtr->nextPtr; break; } } } if (stopPtr->command != NULL) { free(stopPtr->command); } free((char *) stopPtr); } return TCL_OK; } /* * "Info" option: print info about all the stops that are currently * defined. */ if (strncmp(argv[1], "info", length) == 0) { char msg[40]; if (machPtr->stopList == NULL) { /* printf("No stops are currently set.\n"); */ return TCL_OK; } /* printf("Num Address Action\n"); */ for (stopPtr = machPtr->stopList; stopPtr != NULL; stopPtr = stopPtr->overallPtr) { sprintf(msg, "#%-2d %s", stopPtr->number, Sym_GetString(machPtr, stopPtr->address)); Tcl_SetVar(machPtr->interp, "msg", msg, TCL_GLOBAL_ONLY); Tcl_VarEval(machPtr->interp, ".stop.list.list insert end $msg", (char *)NULL); /* if (stopPtr->command != NULL) { printf(" %s\n", stopPtr->command); } else { printf(" stop\n"); } */ } return TCL_OK; } sprintf(interp->result, "bad option \"%.50s\" for \"%.50s\": %s", argv[1], argv[0], "should be at, delete, or info"); return TCL_ERROR;}/* *---------------------------------------------------------------------- * * Stop_Execute -- * * Scan through a list of spies associated with a memory word, * executing the Tcl commands associated with each one. If any * of the commands returns a result other than TCL_OK, then quit * immediately. * * Results: * TCL_OK, if the stop commands all terminated normally; otherwise * the result of the first command that didn't terminate normally. * MachPtr->interp gets a result stored in it too. * * Side effects: * Whatever the commands do. * *---------------------------------------------------------------------- */intStop_Execute(machPtr, stopPtr) DLX *machPtr; /* Machine being executed. */ register Stop *stopPtr; /* First in list of stops. */{ int result = TCL_OK; int stopFlag = 0; int stopNum = -1; /* * The code below checks each individual stop operation to * see if it caused an actual stop (the first to request a * stop is reported as the triggered stop). */ for ( ; stopPtr != NULL; stopPtr = stopPtr->nextPtr) { if (machPtr->flags & STOP_REQUESTED) { stopFlag |= STOP_REQUESTED; machPtr->flags &= ~STOP_REQUESTED; } if (stopPtr->command == NULL) { Sim_Stop(machPtr); } else { result = Tcl_Eval(machPtr->interp, stopPtr->command); if (result != TCL_OK) { return result; } else { if (*machPtr->interp->result != 0) { printf("%s\n", machPtr->interp->result); } Tcl_Return(machPtr->interp, (char *) NULL, TCL_STATIC); } } if ((machPtr->flags & STOP_REQUESTED) && (stopNum == -1)) { stopNum = stopPtr->number; } } machPtr->flags |= stopFlag; if (stopNum != -1) { unsigned int pcAddr; pcAddr = INDEX_TO_ADDR(machPtr->regs[PC_REG]); sprintf(machPtr->interp->result, "stop %d, pc = %.50s: %.80s", stopNum, Sym_GetString(machPtr, pcAddr), Asm_Disassemble(machPtr, machPtr->memPtr[machPtr->regs[PC_REG]].value, pcAddr)); } return TCL_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -