/* * This fucntion commit the second step of the program. * adding addresses to the three symbol tables. */ void secondStep() { int memIdx = 0, labelAddress = 0; IC = 0; DC = 0; lineNumber = 0; QUE_setPtrToHead(); while(strcmp(QUE_getLabel(),"NULL") != 0 && memIdx != -1) { if((labelAddress = getLabelAddress(QUE_getLabel(), labelTABLE)) != -1){ memIdx = setLabelAddressInMemory(memIdx, labelAddress); /* update label address on memory*/ QUE_setIsExtern(FALSE); }else{ if(getLabelAddress(QUE_getLabel(), externTABLE) == -1) fprintf(stderr, "\n[line %d]: the label %s is not exists on file ",QUE_getLine(), QUE_getLabel()); else{ QUE_setIsExtern(TRUE); if(mem[QUE_getLine() + 1].fieldNum == 3 && mem[QUE_getLine() + 1].cml.label.addr == 0){ mem[QUE_getLine() + 1].cml.label.era = 1; memIdx = QUE_getLine() + 2; QUE_setLine(QUE_getLine() + 1); }else{ mem[QUE_getLine() + 2].cml.label.era = 1; memIdx = QUE_getLine() + 3; QUE_setLine(QUE_getLine() + 2); } } } QUE_getNext(); } seAddressEnEX(entryTABLE); seAddressEnEX(externTABLE); }
void Assembler::replaceLabels(){ for(int i=0; i<alignedProgram.size(); i++){ ProgramAtom atom = alignedProgram[i]; if(atom.type == DIRECTIVE_INSTRUCTION){ //Modified replacement string mnemonic = parser.extractFirstToken(atom.token); mnemonic = parser.toLower(mnemonic); bool isBranch = parser.tokenIsBranchInstructionName(mnemonic); bool isJump = parser.tokenIsJumpInstructionName(mnemonic); vector<string> instructionTokens = parser.tokenizeInstruction(atom.token); if(isBranch || isJump){ string lastToken = instructionTokens[instructionTokens.size() - 1]; if(!tokenIsInLabelDB(lastToken)){ //EXCEPTION string error = ERROR_UNRECOGNIZED_LABEL; string offendingToken = lastToken; addException(AssemblerException(*atom.programLine, error, offendingToken)); continue; } virtualAddr labelAddr = getLabelAddress(lastToken); virtualAddr instructionAddr = atom.addr; virtualAddr immediateVal = 0; if(isBranch){ int32_t offset = labelAddr - instructionAddr - 4; //pc still increments by 4 on branches offset >>= 2; immediateVal = (virtualAddr)offset; }else if(isJump){ immediateVal = (labelAddr & 0x0FFFFFFF) >> 2; } string immediateString = parser.literals.getHexLiteralString(immediateVal); instructionTokens[instructionTokens.size() - 1] = immediateString; string newInstructionString = parser.combineInstructionTokens(instructionTokens); alignedProgram[i].token = newInstructionString; }else{
/* Function that updates the label of the operand and it's value from table of signs Input: Operand struct RunStatus struct integer line Number Output: True if it was able to update the address , FALSE otherwise */ int updateOperandLabelAddress(Operand *op, RunStatus *runStatus, int lineNum) { int labelAddress; int dataAddress; unsigned int startValueData; if (op -> type == DIRECT) /*Label is taken from "tag table"*/ { labelAddress = getLabelAddress(runStatus , op, 1); if (labelAddress == -1) { printf("ERROR: Line #%d, Label \"%s\" doesn't exist.\n", lineNum+1, op->str); runStatus -> errNum ++; return FALSE; } } else if ( op -> type == DYNAMIC) { labelAddress = getLabelAddress(runStatus , op, 0); if (labelAddress != -1) /*Parsing the dynamic range*/ { /* Getting the value depends on cell type (data / command)*/ if (runStatus -> finalLabelArray[labelAddress].isData) { dataAddress = runStatus -> finalLabelArray[labelAddress].memAddress - runStatus -> ic - FIRST_MEM_ADDR; startValueData = runStatus -> dataArray[dataAddress]; } else { startValueData = getIntFromWord(runStatus -> finalLabelArray[labelAddress].word); } /* Parsing the specified range*/ op -> val = getRequiredBitsFromLabel(startValueData, op -> up, op-> down); } else { printf("ERROR: Line #%d, Label \"%s\" doesn't exist.\n", lineNum+1, op->str); runStatus -> errNum ++; return FALSE; } } return TRUE; }
uint32_t handleBranch(Assembler *assembler, char **tokens) { CondCodes cond = mnemToCondCode(&tokens[0][1]); uint32_t address = isalpha(tokens[1][0]) ? //address starts with a char so is a label getLabelAddress(assembler, tokens[1]) : //else it's a numeric value getValue(tokens[1]); uint32_t offset = calcOffset(assembler, address, true); return genBranch(cond, offset); }
/** * This function checks if the label stands on standards. if it doesn't - the function prints error note. * ln - the last line. * returns TRUE if the label is fine, otherwisr - FALSE. */ int isLabelOK(line ln) { int flag = 0; if(strcmp(ln.word, "NULL") == 0) return FALSE; if(!isalpha(ln.word[0])) fprintf(stderr, "\n[line %d]: First character of label must be a letter", lineNumber); else flag++; if(strlen(ln.word) > maxStringLength) fprintf(stderr, "\n[line %d]: The label length is longer than the maximum available (%d)",lineNumber, maxStringLength); else flag++; if(isRegister(ln.word)) fprintf(stderr, "\n[line %d]: The name of the label %s is equal to register. YOU CANNOT USE THIS NAME", lineNumber , ln.word); else flag++; if(getLabelAddress(ln.word, labelTABLE) != -1) fprintf(stderr, "\n[line %d]: The label %s is already exists on program", lineNumber ,ln.word); else flag++; if(flag == 4) return TRUE; return FALSE; }
//Post-processing void Assembler::pseudoInstructionReplace(){ for(int i=0; i<alignedProgram.size(); i++){ ProgramAtom atom = alignedProgram[i]; string line = atom.token; if(atom.type == DIRECTIVE_INSTRUCTION){ string mnemonic = parser.extractFirstToken(atom.token); mnemonic = parser.toLower(mnemonic); if(parser.tokenIsPseudoInstructionName(mnemonic)){ int pseudoInstructionNumber = parser.getPseudoInstructionNameNumber(mnemonic); int numInsertedLines = parser.getPseudoInstructionNumberOfLinesToInsert(mnemonic); vector<string> tokenizedInstruction = parser.tokenizeInstruction(line); switch(pseudoInstructionNumber){ //TODO: add exceptions for incorrect number of instruction arguments case 0: { //bge $reg1, $reg2, label if(tokenizedInstruction.size() != 4){addException(AssemblerException(*atom.programLine, ERROR_INVALID_PSEUDOINSTRUCTION, atom.programLine->text));continue;} string registerName1 = tokenizedInstruction[1]; string registerName2 = tokenizedInstruction[2]; string labelName = tokenizedInstruction[3]; string line1 = "slt\t$at, " + registerName1 + ", " + registerName2; string line2 = "beq\t$at, $zero, " + labelName; alignedProgram[i].token = line1; alignedProgram[i+1].token = line2; } break; case 1: { //bgt $reg1, $reg2, label if(tokenizedInstruction.size() != 4){addException(AssemblerException(*atom.programLine, ERROR_INVALID_PSEUDOINSTRUCTION, atom.programLine->text));continue;} string registerName1 = tokenizedInstruction[1]; string registerName2 = tokenizedInstruction[2]; string labelName = tokenizedInstruction[3]; string line1 = "slt\t$at, " + registerName2 + ", " + registerName1; string line2 = "bne\t$at, $zero, " + labelName; alignedProgram[i].token = line1; alignedProgram[i+1].token = line2; } break; case 2: { //ble $reg1, $reg2, label if(tokenizedInstruction.size() != 4){addException(AssemblerException(*atom.programLine, ERROR_INVALID_PSEUDOINSTRUCTION, atom.programLine->text));continue;} string registerName1 = tokenizedInstruction[1]; string registerName2 = tokenizedInstruction[2]; string labelName = tokenizedInstruction[3]; string line1 = "slt\t$at, " + registerName2 + ", " + registerName1; string line2 = "beq\t$at, $zero, " + labelName; alignedProgram[i].token = line1; alignedProgram[i+1].token = line2; } break; case 3: { //blt $reg1, $reg2, label if(tokenizedInstruction.size() != 4){addException(AssemblerException(*atom.programLine, ERROR_INVALID_PSEUDOINSTRUCTION, atom.programLine->text));continue;} string registerName1 = tokenizedInstruction[1]; string registerName2 = tokenizedInstruction[2]; string labelName = tokenizedInstruction[3]; string line1 = "slt\t$at, " + registerName1 + ", " + registerName2; string line2 = "bne\t$at, $zero, " + labelName; alignedProgram[i].token = line1; alignedProgram[i+1].token = line2; } break; case 4: { //clear $reg if(tokenizedInstruction.size() != 2){addException(AssemblerException(*atom.programLine, ERROR_INVALID_PSEUDOINSTRUCTION, atom.programLine->text));continue;} string registerName1 = tokenizedInstruction[1]; string line1 = "add\t" + registerName1 + ", $zero, $zero"; alignedProgram[i].token = line1; } break; case 5: { //la $reg, label if(tokenizedInstruction.size() != 3){addException(AssemblerException(*atom.programLine, ERROR_INVALID_PSEUDOINSTRUCTION, atom.programLine->text));continue;} string labelName = tokenizedInstruction[2]; if(!tokenIsInLabelDB(labelName)){ //EXCEPTION string error = ERROR_UNRECOGNIZED_LABEL; string offendingToken = labelName; addException(AssemblerException(*atom.programLine, error, offendingToken)); continue; } virtualAddr labelAddr = getLabelAddress(labelName); virtualAddr msb = labelAddr >> (SIZE_BITS_VIRTUAL_ADDR / 2); virtualAddr lsb = labelAddr & 0x0000FFFF; string msbHex = parser.literals.getHexLiteralString(msb); string lsbHex = parser.literals.getHexLiteralString(lsb); string registerName = tokenizedInstruction[1]; string line1 = "lui\t" + registerName + ", " + msbHex; string line2 = "ori\t" + registerName + ", " + registerName + ", " + lsbHex; alignedProgram[i].token = line1; alignedProgram[i+1].token = line2; } break; case 6: { //li $reg, imm if(tokenizedInstruction.size() != 3){addException(AssemblerException(*atom.programLine, ERROR_INVALID_PSEUDOINSTRUCTION, atom.programLine->text));continue;} string immediateString = tokenizedInstruction[2]; //EXCEPTION //TODO uint32_t immediateVal; try{ immediateVal = parser.literals.getLiteralValue(immediateString); }catch(InvalidTokenException &e){ string error = ERROR_INVALID_IMMEDIATE_LI; string offendingToken = immediateString; addException(AssemblerException(*atom.programLine, error, offendingToken)); continue; } virtualAddr msb = immediateVal >> (SIZE_BITS_WORD / 2); virtualAddr lsb = immediateVal & 0x0000FFFF; string msbHex = parser.literals.getHexLiteralString(msb); string lsbHex = parser.literals.getHexLiteralString(lsb); string registerName = tokenizedInstruction[1]; string line1 = "lui\t" + registerName + ", " + msbHex; string line2 = "ori\t" + registerName + ", " + registerName + ", " + lsbHex; alignedProgram[i].token = line1; alignedProgram[i+1].token = line2; } break; case 7: { //move $reg1, $reg2 if(tokenizedInstruction.size() != 3){addException(AssemblerException(*atom.programLine, ERROR_INVALID_PSEUDOINSTRUCTION, atom.programLine->text));continue;} string registerName1 = tokenizedInstruction[1]; string registerName2 = tokenizedInstruction[2]; string line1 = "add\t" + registerName1 + ", " + registerName2 + ", $zero"; alignedProgram[i].token = line1; } break; case 8: { //neg $reg1, $reg2 if(tokenizedInstruction.size() != 3){addException(AssemblerException(*atom.programLine, ERROR_INVALID_PSEUDOINSTRUCTION, atom.programLine->text));continue;} string registerName1 = tokenizedInstruction[1]; string registerName2 = tokenizedInstruction[2]; string line1 = "sub\t" + registerName1 + ", $zero, " + registerName2; alignedProgram[i].token = line1; } break; case 9: { //not $reg1, $reg2 if(tokenizedInstruction.size() != 3){addException(AssemblerException(*atom.programLine, ERROR_INVALID_PSEUDOINSTRUCTION, atom.programLine->text));continue;} string registerName1 = tokenizedInstruction[1]; string registerName2 = tokenizedInstruction[2]; string line1 = "addi\t" + registerName1 + ", $zero, -1"; string line2 = "xor\t" + registerName1 + ", " + registerName1 + "," + registerName2; alignedProgram[i].token = line1; alignedProgram[i+1].token = line2; } break; /* PUSH: sub $sp,$sp,4 sw $t2,($sp) POP: lw $t2,($sp) addiu $sp,$sp,4 */ case 10: { //push $reg if(tokenizedInstruction.size() != 2){addException(AssemblerException(*atom.programLine, ERROR_INVALID_PSEUDOINSTRUCTION, atom.programLine->text));continue;} string registerName1 = tokenizedInstruction[1]; string line1 = "sub\t$sp, $sp, 4"; string line2 = "sw\t" + registerName1 + ", 0($sp)"; alignedProgram[i].token = line1; alignedProgram[i+1].token = line2; } break; case 11: { //pop $reg if(tokenizedInstruction.size() != 2){addException(AssemblerException(*atom.programLine, ERROR_INVALID_PSEUDOINSTRUCTION, atom.programLine->text));continue;} string registerName1 = tokenizedInstruction[1]; string line1 = "lw\t" + registerName1 + ", 0($sp)"; string line2 = "addi\t$sp, $sp, 4"; alignedProgram[i].token = line1; alignedProgram[i+1].token = line2; } break; case 12: { //peak $reg if(tokenizedInstruction.size() != 2){addException(AssemblerException(*atom.programLine, ERROR_INVALID_PSEUDOINSTRUCTION, atom.programLine->text));continue;} string registerName = tokenizedInstruction[1]; string line = "lw\t" + registerName + ", 0($sp)"; alignedProgram[i].token = line; } break; case 13: { //rem } break; case 14: { //sge } break; case 15: { //sgt } break; default: break; } i += numInsertedLines; }else{ } }else{ } } }