📄 asm.c
字号:
*/ while ((*p == ' ') || (*p == '\t')) { p++; } if ((*p == '\n') || (*p == 0)) { continue; } /* * If this isn't an assembler pseudo-op, just assemble the * instruction and move on. */ while ((*p == ' ') || (*p == '\t')) { p++; } if (*p == ';') { continue; } if (*p != '.') { int size, code[ASM_MAX_WORDS], result; infoPtr->dot = (infoPtr->dot + 3) & ~3; result = Asm_Assemble(machPtr, fileName, p, infoPtr->dot, line, infoPtr->flags & ASM_SIZE_ONLY, &size, code); if (result == TCL_OK && !(infoPtr->flags & ASM_SIZE_ONLY)) { result = StoreWords(machPtr, infoPtr->dot, code, machPtr->codeLine++, size); sprintf(msg, "(0x%08x) 0x%08x %s", infoPtr->dot, *code, line); Tcl_SetVar(machPtr->interp, "msg", msg, TCL_GLOBAL_ONLY); Tcl_VarEval(machPtr->interp, ".code.t insert end $msg", (char *)NULL); } infoPtr->dot += size*4; goto endOfLine; } /* * Handle an assembler pseudo-op. */ curToken = p; for (i = 0, p++; (i < MAX_NAME_SIZE) && isalpha(*p); i++, p++) { pseudoOp[i] = *p; } if (i >= MAX_NAME_SIZE) { IndicateError(machPtr->interp, "pseudo-op name too long", line, curToken); goto endOfLine; } pseudoOp[i] = 0; while ((*p == ' ') || (*p == '\t')) { p++; } if ((pseudoOp[0] == 'a') && (strcmp(pseudoOp, "align") == 0)) { if (Sym_EvalExpr(machPtr, fileName, p, 0, &i, &end) != TCL_OK) { IndicateError(machPtr->interp, machPtr->interp->result, line, p); goto endOfLine; } p = end; if (i == 0) { machPtr->interp->result = "\".align 0\" not supported"; goto endOfLine; } else { i = (1 << i) - 1; infoPtr->dot = (infoPtr->dot + i) & ~i; } } else if ((pseudoOp[0] == 'a') && (strcmp(pseudoOp, "ascii") == 0)) { nullTerm = 0; /* * Read one or more ASCII strings from the input line. Each * must be surrounded by quotes, and they must be separated * by commas. */ doString: while (1) { while ((*p == ' ') || (*p == '\t')) { p++; } if (*p != '"') { IndicateError(machPtr->interp, "missing \" at start of string", line, p); goto endOfLine; } p++; i = Gp_PutString(machPtr, p, '"', infoPtr->dot, nullTerm, &end); if (*end != '"') { IndicateError(machPtr->interp, "missing \" at end of string", line, end-1); goto endOfLine; } p = end+1; infoPtr->dot += i; while ((*p == ' ') || (*p == '\t')) { p++; } if (*p != ',') { break; } p++; } } else if ((pseudoOp[0] == 'a') && (strcmp(pseudoOp, "asciiz") == 0)) { nullTerm = 1; goto doString; } else if ((pseudoOp[0] == 'b') && (strcmp(pseudoOp, "byte") == 0)) { while (1) { curToken = p; if (Sym_EvalExpr(machPtr, fileName, p, 0, &i, &end) != TCL_OK) { IndicateError(machPtr->interp, machPtr->interp->result, line, p); goto endOfLine; } Gp_PutByte(machPtr, infoPtr->dot, i); infoPtr->dot += 1; for (p = end; (*p == ' ') || (*p == '\t'); p++) { /* Null body; just skip space. */ } if (*p != ',') { break; } p++; } } else if ((pseudoOp[0] == 'd') && (strcmp(pseudoOp, "data") == 0)) { if (infoPtr->flags & ASM_CODE) { infoPtr->codeAddr = infoPtr->dot; } else { infoPtr->dataAddr = infoPtr->dot; } if (Sym_EvalExpr(machPtr, fileName, p, 0, &i, &end) != TCL_OK) { Tcl_Return(machPtr->interp, (char *) NULL, TCL_STATIC); } else { p = end; infoPtr->dataAddr = i; } infoPtr->dot = infoPtr->dataAddr; infoPtr->flags &= ~ASM_CODE; } else if ((pseudoOp[0] == 'g') && (strcmp(pseudoOp, "global") == 0)) { if (!isalpha(*p) && (*p != '_')) { IndicateError(machPtr->interp, "symbol name must start with letter or '_'", line, p); goto endOfLine; } curToken = p; while (isalnum(*p) || (*p == '_') || (*p == '$')) { p++; } savedChar = *p; *p = 0; if (infoPtr->flags & ASM_SIZE_ONLY) { Sym_AddSymbol(machPtr, fileName, curToken, 0, SYM_GLOBAL|SYM_NO_ADDR); if (*machPtr->interp->result != 0) { AddErrMsg(machPtr->interp, infoPtr, 1); } } *p = savedChar; } else if ((pseudoOp[0] == 's') && (strcmp(pseudoOp, "space") == 0)) { if (Sym_EvalExpr(machPtr, fileName, p, 0, &i, &end) != TCL_OK) { IndicateError(machPtr->interp, machPtr->interp->result, line, p); goto endOfLine; } p = end; while (i > 0) { Gp_PutByte(machPtr, infoPtr->dot, 0); infoPtr->dot += 1; i -= 1; } } else if ((pseudoOp[0] == 't') && (strcmp(pseudoOp, "text") == 0)) { if (infoPtr->flags & ASM_CODE) { infoPtr->codeAddr = infoPtr->dot; } else { infoPtr->dataAddr = infoPtr->dot; } if (Sym_EvalExpr(machPtr, fileName, p, 0, &i, &end) != TCL_OK) { Tcl_Return(machPtr->interp, (char *) NULL, TCL_STATIC); } else { p = end; infoPtr->codeAddr = i; } infoPtr->dot = infoPtr->codeAddr; infoPtr->flags |= ASM_CODE; } else if ((pseudoOp[0] == 'w') && (strcmp(pseudoOp, "word") == 0)) { while (1) { curToken = p; if (Sym_EvalExpr(machPtr, fileName, p, 0, &i, &end) != TCL_OK) { IndicateError(machPtr->interp, machPtr->interp->result, line, p); goto endOfLine; } infoPtr->dot = (infoPtr->dot + 3) & ~3; (void) StoreWords(machPtr, infoPtr->dot, &i, 0, 1); infoPtr->dot += 4; for (p = end; (*p == ' ') || (*p == '\t'); p++) { /* Null body; just skip space. */ } if (*p != ',') { break; } p++; } } else if ((pseudoOp[0] == 'f') && (strcmp(pseudoOp, "float") == 0)) { while (1) { float f; int *pi = (int *)&f; curToken = p; f = strtod(p, &end); if (p == end) { IndicateError(machPtr->interp, "illegal floating number", line, p); goto endOfLine; } infoPtr->dot = (infoPtr->dot + 3) & ~3; (void) StoreWords(machPtr, infoPtr->dot, pi, 0, 1); infoPtr->dot += 4; for (p = end; (*p == ' ') || (*p == '\t'); p++) { /* Null body; just skip space. */ } if (*p != ',') { break; } p++; } } else if ((pseudoOp[0] == 'd') && (strcmp(pseudoOp, "double") == 0)) { while (1) { double d; int *pi = (int *)&d; curToken = p; d = strtod(p, &end); if (p == end) { IndicateError(machPtr->interp, "illegal double number", line, p); goto endOfLine; } infoPtr->dot = (infoPtr->dot + 3) & ~3; (void) StoreWords(machPtr, infoPtr->dot, pi, 0, 2); infoPtr->dot += 8; for (p = end; (*p == ' ') || (*p == '\t'); p++) { /* Null body; just skip space. */ } if (*p != ',') { break; } p++; } } else { IndicateError(machPtr->interp, "unknown pseudo-op", line, curToken); goto endOfLine; } /* * Check for extraneous garbage at the end of the line. */ while (isspace(*p)) { p++; } if ((*p != '#') && (*p != 0)) { IndicateError(machPtr->interp, "extra junk at end of line", line, p); } /* * Done with the line. If there has been an error, add it onto * the list of error messages that has accumulated during the * assembly. Increase the storage allocated to error messages * if necessary to accommodate the new message. */ endOfLine: if (*machPtr->interp->result != 0) { if (infoPtr->flags & ASM_SIZE_ONLY) { Tcl_Return(machPtr->interp, (char *) NULL, TCL_STATIC); } else { AddErrMsg(machPtr->interp, infoPtr, 1); if (infoPtr->errorCount > ASM_MAX_ERRORS) { goto endOfFile; } } } } endOfFile: fclose(f); if (infoPtr->flags & ASM_CODE) { infoPtr->codeAddr = infoPtr->dot; } else { infoPtr->dataAddr = infoPtr->dot; }}/* *---------------------------------------------------------------------- * * AddErrMsg -- * * Given an error message in an interpreter, add it onto a list of * error messages being accumulated for an assembly and clear the * interpreter's message. * * Results: * None. * * Side effects: * The message is added to the list of messages in infoPtr, and * the interpreter's result is re-initialized. * *---------------------------------------------------------------------- */static voidAddErrMsg(interp, infoPtr, addHeader) Tcl_Interp *interp; /* Interpreter containing error * message. */ register LoadInfo *infoPtr; /* State of assembly, to which error * message is to be added. */ int addHeader; /* Non-zero means tack on message * header identifying file and line * number. */{ int length, hdrLength, totalLength; char header[100]; length = strlen(interp->result); if (length == 0) { return; } if (addHeader) { sprintf(header, "%.50s(%d): ", infoPtr->file, infoPtr->lineNum); } else { header[0] = 0; } hdrLength = strlen(header); totalLength = hdrLength + length + 2; /* * Grow the error message area if the current area isn't large * enough. */ if (totalLength > ((infoPtr->message + infoPtr->totalBytes) - (infoPtr->end + 1))) { char *newMsg; if (infoPtr->totalBytes == 0) { infoPtr->totalBytes = 4*totalLength; } else { infoPtr->totalBytes = 2*(infoPtr->totalBytes + totalLength); } newMsg = calloc(1, (unsigned) infoPtr->totalBytes); if (infoPtr->message != NULL) { strcpy(newMsg, infoPtr->message); infoPtr->end += newMsg - infoPtr->message; } else { infoPtr->end = newMsg; } infoPtr->message = newMsg; } if (infoPtr->end != infoPtr->message) { *infoPtr->end = '\n'; infoPtr->end += 1; } sprintf(infoPtr->end, "%s%s", header, interp->result); infoPtr->end += hdrLength + length; infoPtr->errorCount += 1; Tcl_Return(interp, (char *) NULL, TCL_STATIC);}/* *---------------------------------------------------------------------- * * StoreWords -- * * Place a given range of words in the memory of a machine. * * Results: * A standard Tcl result (normally TCL_OK plus empty string); error * information is returned through machPtr->interp. * * Side effects: * MachPtr's memory is modified to hold new information. * *---------------------------------------------------------------------- */static intStoreWords(machPtr, address, wordPtr, codeLine, numWords) register DLX *machPtr; /* Machine into which to store. */ unsigned int address; /* Word-aligned byte address in * machine's memory. */ int *wordPtr; /* Words to store into machine's * memory. */ int codeLine; /* Line in which the instruction is displayed in the .code.t window. */ int numWords; /* Number of words to store. */{ int index; register MemWord *memPtr; for ( ; numWords > 0; wordPtr++, address += 4, numWords--) { index = ADDR_TO_INDEX(address); if (index >= machPtr->numWords) { sprintf(machPtr->interp->result, "can't store at address 0x%x: no such memory location", address); return TCL_ERROR; } memPtr = machPtr->memPtr + index; memPtr->value = *wordPtr; memPtr->line = codeLine; memPtr->opCode = OP_NOT_COMPILED; } return TCL_OK;}/* *---------------------------------------------------------------------- * * IndicateError -- * * Generate an error message that also points out the position * in a string where the error was detected. * * Results: * There is no return value. Interp's result is modified to hold * errMsg followed by string, with position pos highlighted in * string. * * Side effects: * None. * *---------------------------------------------------------------------- */static voidIndicateError(interp, errMsg, string, pos) Tcl_Interp *interp; /* Interpreter to hold error message. The * result area must be in the initial * empty state. */ char *errMsg; /* Message describing the problem. */ char *string; /* Input string that contained the problem. */ char *pos; /* Location in string of the character where * problem was detected. */{ int msgLength, stringLength; char *newMsg; msgLength = strlen(errMsg); stringLength = strlen(string); if (string[stringLength-1] == '\n') { stringLength -= 1; } /* * Always allocate new storage for the new message. This is needed * because (a) the space required may exceed the size of the static * result buffer, and (b) "errMsg" may actually be in the static * buffer so we have to be careful not to trash it while generating * the new message. */ newMsg = calloc(1, (unsigned) (msgLength + stringLength + 10)); sprintf(newMsg, "%s: %.*s => %.*s", errMsg, pos-string, string, stringLength - (pos-string), pos); Tcl_Return(interp, newMsg, TCL_DYNAMIC);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -