📄 getput.c
字号:
/* * getput.c -- * * This file implements commands to query or change the state * of the DLX machine being simulated. * * This file is part of DISC. It was modified by Yinong Zhang * (yinong@ecn.purdue.edu) from the file "getput.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 <ctype.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <tcl.h>#include "dlx.h"#include "sym.h"/* * Forward declarations for procedures declared later in this file: */static int GetAddress(DLX *, char *, unsigned int *, int *);static char * GetString(DLX *, unsigned int, int *);/* *---------------------------------------------------------------------- * * Gp_GetCmd -- * * This procedure is invoked to process the "get" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */intGp_GetCmd(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ DLX *machPtr = (DLX *) clientData; unsigned int address; int isReg, result, totalSpace, spaceNeeded; enum {BINARY, HEX, DECIMAL, CHAR, STRING, INS} format = HEX; int length = 4; /* # bytes in each value to print. */ int count = 1; /* # of values to print. */ int addrIsValue = 0; /* Print address instead of value. */ char *p; /* Points to NULL char. at end of * current result. */ int dynamic = 0; char *locString, *valueString; char locBuf[100], valueBuf[100]; if ((argc != 2) && (argc != 3)) { sprintf(interp->result, "wrong # args: should be \"%.50s location [flags]\"", argv[0]); return TCL_ERROR; } result = GetAddress(machPtr, argv[1], &address, &isReg); if (result != TCL_OK) { return result; } /* * Parse flags. */ if (argc == 3) { for (p = argv[2]; *p != 0; p++) { if (*p == 'b') { length = 1; } else if (*p == 'h') { length = 2; } else if (*p == 'w') { length = 4; } else if (*p == 'x') { format = HEX; } else if (*p == 'd') { format = DECIMAL; } else if (*p == 'B') { format = BINARY; } else if (*p == 'c') { format = CHAR; length = 1; } else if (*p == 's') { if (isReg) { sprintf(interp->result, "can't get \"%.50s\" as string", argv[1]); return TCL_ERROR; } format = STRING; length = 1; } else if (*p == 'i') { format = INS; } else if (isdigit(*p)) { char *end; count = strtoul(p, &end, 10); p = end-1; } else if (*p == 'v') { addrIsValue = 1; } else { sprintf(interp->result, "bad flag \"%c\" in \"%.50s\" command", *p, argv[0]); return TCL_ERROR; } } } /* * Enter a loop to format <location value> pairs. Round the address * down to an even boundary appropriate for the output type. */ if (!isReg && !addrIsValue) { address &= ~(length-1); } p = interp->result; totalSpace = TCL_RESULT_SIZE; while (1) { int value; /* * Get the value to print. */ if (addrIsValue) { value = address; } else if (isReg) { if (address == PC_REG) { value = Sim_GetPC(machPtr); } else if (address == NEXT_PC_REG) { value = INDEX_TO_ADDR(value); } else { value = machPtr->regs[address]; } } else { if (ADDR_TO_INDEX(address) < machPtr->numWords) { value = machPtr->memPtr[ADDR_TO_INDEX(address)].value; } else if (Io_Read(machPtr, (address & ~0x3), &(value)) == 0) { sprintf(interp->result, "location \"%.50s\" doesn't exist in memory", argv[1]); return TCL_ERROR; } if (length == 1) { switch (address & 0x3) { case 0: value >>= 24; break; case 1: value >>= 16; break; case 2: value >>= 8; break; } } else if ((length == 2) && !(address & 0x2)) { value >>= 16; } } if (length == 1) { value &= 0xff; if ((format == DECIMAL) && (value & 0x80)) { value |= 0xffffff00; } } if (length == 2) { value &= 0xffff; if ((format == DECIMAL) && (value & 0x8000)) { value |= 0xffff0000; } } /* * Format the value's address, leaving a pointer to it * in locString. */ locString = locBuf; if (addrIsValue) { locString = ""; } else if (isReg) { (void) sprintf(locBuf, "%s:\t", Asm_RegNames[address]); } else { (void) sprintf(locBuf, "%s:\t", Sym_GetString(machPtr, address)); } /* * Format the value itself, leaving a pointer in valueString. */ valueString = valueBuf; switch (format) { case HEX: (void) sprintf(valueBuf, "0x%08x", value); break; case DECIMAL: (void) sprintf(valueBuf, "%d", value); break; case BINARY: { int i; for (i = 31; i >= 0; i--) { if (value & (1<<i)) { *valueString = '1'; valueString++; } else if (valueString != valueBuf) { *valueString = '0'; valueString++; } } if (valueString == valueBuf) { *valueString = '0'; valueString++; } *valueString = 0; valueString = valueBuf; break; } case CHAR: if (isprint(value)) { (void) sprintf(valueBuf, "%c (0x%x)", (char) value, value); } else { (void) sprintf(valueBuf, "0x%x", value); } break; case STRING: valueString = GetString(machPtr, address, &length); break; case INS: valueString = Asm_Disassemble(machPtr, value, address); break; } /* * Make sure there's enough space for this value in the * result buffer (grow the output buffer if necessary), * then put the value into the buffer. */ spaceNeeded = (p - interp->result) + strlen(locString) + strlen(valueString); while (totalSpace <= spaceNeeded) { char *newSpace; int spaceUsed; totalSpace *= 2; newSpace = calloc(1, (unsigned) totalSpace); spaceUsed = p-interp->result; memcpy (newSpace, interp->result, spaceUsed); if (dynamic) { free(interp->result); } dynamic = 1; interp->result = newSpace; p = newSpace + spaceUsed; } strcpy(p, locString); strcat(p, valueString); p += strlen(p); /* * Go on to the next value, if there are any more. */ count -= 1; if (count == 0) { break; } if (isReg) { address += 1; if (address >= TOTAL_REGS) { break; } } else { address += length; if (ADDR_TO_INDEX(address) >= machPtr->numWords) { break; } } *p = '\n'; p++; } return TCL_OK;}/* *---------------------------------------------------------------------- * * Gp_FGetCmd -- * * This procedure is invoked to process the "fget" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */intGp_FGetCmd(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ DLX *machPtr = (DLX *) clientData; unsigned int address; int isReg, result, totalSpace, spaceNeeded; enum {FLOAT, DOUBLE} format = FLOAT; int length = 4; /* # bytes in each value to print. */ int count = 1; /* # of values to print. */ char *p; /* Points to NULL char. at end of * current result. */ int dynamic = 0; char *locString, *valueString; char locBuf[100], valueBuf[100]; if ((argc != 2) && (argc != 3)) { sprintf(interp->result, "wrong # args: should be \"%.50s location [flags]\"", argv[0]); return TCL_ERROR; } result = GetAddress(machPtr, argv[1], &address, &isReg); if (result != TCL_OK) { return result; } /* * Parse flags. */ if (argc == 3) { for (p = argv[2]; *p != 0; p++) { if (*p == 'f') { format = FLOAT; length = 4; } else if (*p == 'd') { format = DOUBLE; length = 8; } else if (isdigit(*p)) { char *end; count = strtoul(p, &end, 10); p = end-1; } else { sprintf(interp->result, "bad flag \"%c\" in \"%.50s\" command", *p, argv[0]); return TCL_ERROR; } } } /* * Enter a loop to format <location value> pairs. Round the address * down to an even boundary appropriate for the output type. */ if (!isReg) { address &= ~3; } p = interp->result; totalSpace = TCL_RESULT_SIZE; while (1) { int value[2]; double *pd = (double *)&(value[0]); float *pf = (float *)&(value[0]); /* * Get the value to print. */ if (isReg) { switch (address) { case PC_REG : case NEXT_PC_REG : sprintf(interp->result, "Cannot print in floating point format"); return TCL_ERROR; default : value[0] = machPtr->regs[address]; if (((format == FLOAT) && (address > 63)) || ((format == DOUBLE) && ((address < 32) || (address > 63)))) { sprintf(interp->result, "Cannot print in floating point format"); return TCL_ERROR; } else if ((format == DOUBLE) && (address % 2)) { sprintf(interp->result, "Misaligned double floating point register"); return TCL_ERROR; } if (format == DOUBLE) value[1] = machPtr->regs[address + 1]; break; } } else { if (ADDR_TO_INDEX(address) < machPtr->numWords) { value[0] = machPtr->memPtr[ADDR_TO_INDEX(address)].value; if (format == DOUBLE) { value[1] = machPtr->memPtr[ADDR_TO_INDEX(address+4)].value; } } else if (Io_Read(machPtr, (address & ~0x3), &(value[0])) == 0) { sprintf(interp->result, "location \"%.50s\" doesn't exist in memory", argv[1]); return TCL_ERROR; } } /* * Format the value's address, leaving a pointer to it * in locString. */ locString = locBuf; if (isReg) { (void) sprintf(locBuf, "%s:\t", Asm_RegNames[address]); } else { (void) sprintf(locBuf, "%s:\t", Sym_GetString(machPtr, address)); } /* * Format the value itself, leaving a pointer in valueString. */ valueString = valueBuf; switch (format) { case FLOAT: (void) sprintf(valueBuf, "%f", *pf); break; case DOUBLE: (void) sprintf(valueBuf, "%lf", *pd); break; } /* * Make sure there's enough space for this value in the * result buffer (grow the output buffer if necessary), * then put the value into the buffer. */ spaceNeeded = (p - interp->result) + strlen(locString) + strlen(valueString); while (totalSpace <= spaceNeeded) { char *newSpace; int spaceUsed; totalSpace *= 2; newSpace = calloc(1, (unsigned) totalSpace); spaceUsed = p-interp->result; memcpy (newSpace, interp->result, spaceUsed); if (dynamic) { free(interp->result); } dynamic = 1; interp->result = newSpace; p = newSpace + spaceUsed; } strcpy(p, locString); strcat(p, valueString); p += strlen(p); /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -