⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 getput.c

📁 计算机系统结构的讲义,浓缩了一本一千多页的书.真的是好东西.
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * 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 + -