/// <summary> /// Formats and stringifies an instruction as well as its parameters. /// </summary> /// <param name="currPgrmCtr">The value that the program counter would theoretically be at /// upon encountering this instruction.</param> /// <param name="inst">The disassembled instruction to stringify.</param> /// <param name="symTable">A reverse symbol table used to map addresses back to label names.</param> /// <returns>A string representing the instruction and its parameters that can be written to a text file.</returns> public string GetFormattedInstruction(int currPgrmCtr, DisassembledInstruction inst, ReverseSymbolTable symTable) { string retStr = string.Empty; // first, see if the program counter has a symbol mapped to it. if (symTable.ContainsSymbol(currPgrmCtr)) { Symbol sym = symTable.GetSymbol(currPgrmCtr); retStr += sym.LabelName + ":\t\t"; } else { retStr += "\t\t\t"; } retStr += "flw "; if (inst.Parameters.Count() != 3) { throw new ArgumentException("Floating point I instruction expected 3 arguments, received " + inst.Parameters.Count()); } string rd = ReverseRegisterMap.GetStringifiedFloatingPtRegisterValue(inst.Parameters.ElementAt(0)); string rs1 = ReverseRegisterMap.GetStringifiedRegisterValue(inst.Parameters.ElementAt(1)); int offset = inst.Parameters.ElementAt(2); retStr += rd + ", " + offset + "(" + rs1 + ")"; return(retStr); }
/// <summary> /// Formats and stringifies an instruction as well as its parameters. /// </summary> /// <param name="currPgrmCtr">The value that the program counter would theoretically be at /// upon encountering this instruction.</param> /// <param name="inst">The disassembled instruction to stringify.</param> /// <param name="symTable">A reverse symbol table used to map addresses back to label names.</param> /// <returns>A string representing the instruction and its parameters that can be written to a text file.</returns> public string GetFormattedInstruction(int currPgrmCtr, DisassembledInstruction inst, ReverseSymbolTable symTable) { string retStr = string.Empty; // first, see if the program counter has a symbol mapped to it. if (symTable.ContainsSymbol(currPgrmCtr)) { Symbol sym = symTable.GetSymbol(currPgrmCtr); retStr += sym.LabelName + ":\t\t"; } else { retStr += "\t\t\t"; } retStr += m_Name + ' '; if (inst.Parameters.Count() != 2) { throw new ArgumentException("U-type instruction expected 2 arguments, received " + inst.Parameters.Count()); } string rd = ReverseRegisterMap.GetStringifiedRegisterValue(inst.Parameters.ElementAt(0)); int immediate = inst.Parameters.ElementAt(1); retStr += rd + ", 0x" + immediate.ToString("X2"); return(retStr); }
/// <summary> /// Formats and stringifies an instruction as well as its parameters. /// </summary> /// <param name="currPgrmCtr">The value that the program counter would theoretically be at /// upon encountering this instruction.</param> /// <param name="inst">The disassembled instruction to stringify.</param> /// <param name="symTable">A reverse symbol table used to map addresses back to label names.</param> /// <returns>A string representing the instruction and its parameters that can be written to a text file.</returns> public string GetFormattedInstruction(int currPgrmCtr, DisassembledInstruction inst, ReverseSymbolTable symTable) { string retStr = string.Empty; // first, see if the program counter has a symbol mapped to it. if (symTable.ContainsSymbol(currPgrmCtr)) { Symbol sym = symTable.GetSymbol(currPgrmCtr); retStr += sym.LabelName + ":\t\t"; } else { retStr += "\t\t\t"; } retStr += m_Name + ' '; if (inst.Parameters.Count() != 3) { throw new ArgumentException("sb instruction expected 3 arguments, received " + inst.Parameters.Count()); } string rs1 = ReverseRegisterMap.GetStringifiedRegisterValue(inst.Parameters.ElementAt(0)); string rs2 = ReverseRegisterMap.GetStringifiedRegisterValue(inst.Parameters.ElementAt(1)); retStr += rs1 + ", " + rs2 + ", "; int offset = inst.Parameters.ElementAt(2); int address = currPgrmCtr + offset; // see if there's a symbol mapped to it. if (symTable.ContainsSymbol(address)) { Symbol sym = symTable.GetSymbol(address); retStr += sym.LabelName; } else { retStr += "0x" + address.ToString("X2"); } return(retStr); }
/// <summary> /// Formats and stringifies an instruction as well as its parameters. /// </summary> /// <param name="currPgrmCtr">The value that the program counter would theoretically be at /// upon encountering this instruction.</param> /// <param name="inst">The disassembled instruction to stringify.</param> /// <param name="symTable">A reverse symbol table used to map addresses back to label names.</param> /// <returns>A string representing the instruction and its parameters that can be written to a text file.</returns> public string GetFormattedInstruction(int currPgrmCtr, DisassembledInstruction inst, ReverseSymbolTable symTable) { string retStr = string.Empty; // first, see if the program counter has a symbol mapped to it. if (symTable.ContainsSymbol(currPgrmCtr)) { Symbol sym = symTable.GetSymbol(currPgrmCtr); retStr += sym.LabelName + ":\t\t"; } else { retStr += "\t\t\t"; } retStr += m_Name; return(retStr); }
/// <summary> /// Writes out the .data segment of the file. /// </summary> /// <param name="writer">The StreamWriter to use while writing the file.</param> /// <param name="symTable">The reverse lookup symbol table to use for symbol mapping.</param> /// <param name="dataSegment">The accessor to the file's data segment.</param> private void GenerateDataSegment(StreamWriter writer, ReverseSymbolTable symTable, DataSegmentAccessor dataSegment) { int currAlignment = CommonConstants.DEFAULT_ALIGNMENT; writer.WriteLine(".data"); int processedByteCount = 0; int currAddress = dataSegment.BaseRuntimeDataAddress; foreach (MetadataElement elem in m_File.Metadata) { // don't do any processing if we're looking at padding bytes. if (processedByteCount % currAlignment == 0) { // first, see if there's a label associated with the data element. if (symTable.ContainsSymbol(currAddress)) { // if so, write it out. Symbol sym = symTable.GetSymbol(currAddress); writer.Write(sym.LabelName); writer.Write(":\t\t"); } else { writer.Write("\t\t\t"); } // determine what to write out. switch (elem.TypeCode) { case ObjectTypeCode.Byte: { writer.Write(".byte "); byte value = dataSegment.ReadUnsignedByte(currAddress); writer.WriteLine(value); processedByteCount += sizeof(byte); break; } case ObjectTypeCode.Half: { writer.Write(".half "); short value = dataSegment.ReadShort(currAddress); writer.WriteLine(value); processedByteCount += sizeof(short); break; } case ObjectTypeCode.Word: { writer.Write(".word "); int value = dataSegment.ReadWord(currAddress); writer.WriteLine(value); processedByteCount += sizeof(int); break; } case ObjectTypeCode.Dword: { writer.Write(".dword "); long value = dataSegment.ReadLong(currAddress); writer.WriteLine(value); processedByteCount += sizeof(long); break; } case ObjectTypeCode.String: { writer.Write(".asciiz "); string value = dataSegment.ReadString(currAddress); string processedValue = ProcessString(value); writer.WriteLine(processedValue); processedByteCount += value.Length; // account for a null terminating byte here. ++processedByteCount; break; } case ObjectTypeCode.AlignmentChange: { currAlignment = elem.Alignment; break; } } } else { // otherwise, assume we're at a padding byte and don't print it. ++processedByteCount; } currAddress += elem.Size; } }
/// <summary> /// Writes out the .data segment of the file. /// </summary> /// <param name="writer">The StreamWriter to use while writing the file.</param> /// <param name="symTable">The reverse lookup symbol table to use for symbol mapping.</param> /// <param name="dataSegment">The accessor to the file's data segment.</param> private void GenerateDataSegment(StreamWriter writer, ReverseSymbolTable symTable, DataSegmentAccessor dataSegment) { int currAddress = dataSegment.BaseRuntimeDataAddress; writer.WriteLine(".data"); int endAddress = currAddress + dataSegment.SegmentSize; // get the address of each symbol in the .data segment, and sort // them in ascending order. var symbolAddresses = symTable.AllSymbols .SelectIf(sym => sym.Address, sym => dataSegment.BaseRuntimeDataAddress <= sym.Address && sym.Address < endAddress) .OrderBy(num => num); while (currAddress < endAddress) { // are there any addresses in our symbol table that fall between our current // address and the next address we'll examine? if (symbolAddresses.Any(address => currAddress <= address && address < (currAddress + sizeof(int)))) { // okay, slightly narrow our screen if (symbolAddresses.Any(address => currAddress <= address && address < (currAddress + sizeof(short)))) { if (symTable.ContainsSymbol(currAddress)) { Symbol sym = symTable.GetSymbol(currAddress); writer.Write(sym.LabelName); writer.Write(":\t\t"); switch (sym.Size) { case sizeof(byte): { writer.Write(".byte "); sbyte value = dataSegment.ReadSignedByte(currAddress); writer.WriteLine(value.ToString(StringifyAsHexadecimal(value, 2))); currAddress += sizeof(byte); break; } case sizeof(short): { writer.Write(".half "); short value = dataSegment.ReadShort(currAddress); writer.WriteLine(StringifyAsHexadecimal(value, 4)); currAddress += sizeof(short); break; } case sizeof(int): { writer.Write(".word "); int value = dataSegment.ReadWord(currAddress); writer.WriteLine(StringifyAsHexadecimal(value, 8)); currAddress += sizeof(int); break; } case sizeof(long): { writer.Write(".dword "); long value = dataSegment.ReadLong(currAddress); writer.WriteLine(StringifyAsHexadecimal(value, 16)); currAddress += sizeof(int); break; } default: { // just be cheap for now and write out numeric values // (even though this could be an ascii string, in theory). // maybe at some point the assembler will be nice enough // to force strings into .strtable section for smarter // heuristics, but we don't want to force that upon the user // unless the user specifically directs us so. // (or maybe we do?). if someone thinks of a better // algorithm that can be done in the disassembler, I'm // al ears. int numWordsInSize = sym.Size / sizeof(int); int numLeftover = sym.Size % sizeof(int); int numHalfWordsInRemainingBytes = numLeftover / sizeof(int); int numRemainingBytes = numLeftover % sizeof(int); for (int i = 0; i < numWordsInSize; ++i) { writer.Write(".word "); int value = dataSegment.ReadWord(currAddress); writer.WriteLine(StringifyAsHexadecimal(value, 8)); currAddress += sizeof(int); } for (int i = 0; i < numHalfWordsInRemainingBytes; ++i) { writer.Write(".half "); short value = dataSegment.ReadShort(currAddress); writer.WriteLine(StringifyAsHexadecimal(value, 4)); currAddress += sizeof(short); } for (int i = 0; i < numRemainingBytes; ++i) { writer.Write(".byte "); sbyte value = dataSegment.ReadSignedByte(currAddress); writer.WriteLine(StringifyAsHexadecimal(value, 2)); currAddress += sizeof(byte); } break; } // todo: determine if we need to perform alignment // detection (as in theory at this point we could judge // if the new byte offset is on a word boundary). } } else { writer.Write(".byte "); sbyte value = dataSegment.ReadSignedByte(currAddress); writer.WriteLine(value.ToString(StringifyAsHexadecimal(value, 2))); currAddress += sizeof(byte); break; } } else { writer.Write(".half "); short value = dataSegment.ReadShort(currAddress); writer.WriteLine(StringifyAsHexadecimal(value, 4)); currAddress += sizeof(short); } } else { writer.Write(".word "); int value = dataSegment.ReadWord(currAddress); writer.WriteLine(StringifyAsHexadecimal(value, 8)); currAddress += sizeof(int); } } }