summaryrefslogtreecommitdiffstats
path: root/src/coff/base/disassembler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/coff/base/disassembler.cpp')
-rw-r--r--src/coff/base/disassembler.cpp289
1 files changed, 289 insertions, 0 deletions
diff --git a/src/coff/base/disassembler.cpp b/src/coff/base/disassembler.cpp
new file mode 100644
index 0000000..663c163
--- /dev/null
+++ b/src/coff/base/disassembler.cpp
@@ -0,0 +1,289 @@
+/***************************************************************************
+ * Copyright (C) 2006-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "disassembler.h"
+
+#include <qregexp.h>
+
+#include "devices/base/device_group.h"
+#include "devices/pic/pic/pic_memory.h"
+#include "coff_object.h"
+
+//-----------------------------------------------------------------------------
+QString SourceLine::comment(PURL::SourceFamily family, const QString &text)
+{
+ switch (family.type()) {
+ case PURL::SourceFamily::Asm: return "; " + text;
+ case PURL::SourceFamily::C: return "/* " + text + " */";
+ case PURL::SourceFamily::JAL: return "-- " + text;
+ case PURL::SourceFamily::Cpp: return "// " + text;
+ case PURL::SourceFamily::Basic: return "' " + text;
+ case PURL::SourceFamily::Nb_Types: break;
+ }
+ Q_ASSERT(false);
+ return QString::null;
+}
+
+namespace SourceLine
+{
+class LineData {
+public:
+ LineData() : group(-1) {}
+ QString text, comment;
+ int group;
+};
+} // namespace
+
+QStringList SourceLine::lines(PURL::SourceFamily family, const List &list, uint nbSpaces)
+{
+ QValueList<LineData> lines;
+ QValueList<uint> groupCommentColumn;
+ groupCommentColumn.append(0);
+ List::const_iterator it;
+ for (it=list.begin(); it!=list.end(); ++it) {
+ LineData data;
+ switch((*it).type) {
+ case Indented:
+ data.text = repeat(" ", nbSpaces);
+ case NotIndented:
+ if ( (*it).code.isEmpty() && !(*it).comment.isEmpty() ) data.text += comment(family, (*it).comment);
+ else {
+ data.text += (*it).code;
+ data.comment = (*it).comment;
+ data.group = groupCommentColumn.count() - 1;
+ groupCommentColumn[data.group] = qMax(groupCommentColumn[data.group], uint(data.text.length()));
+ }
+ break;
+ case Separator:
+ data.text = comment(family, "-----------------------------------------------------------------------");
+ groupCommentColumn.append(0);
+ break;
+ case Empty:
+ break;
+ case Title:
+ data.text = comment(family, (*it).comment);
+ break;
+ }
+ lines += data;
+ }
+ QStringList slines;
+ QValueList<LineData>::const_iterator lit;
+ for (lit=lines.begin(); lit!=lines.end(); ++lit) {
+ if ( (*lit).group==-1 || (*lit).comment.isEmpty() ) slines += (*lit).text;
+ else {
+ uint col = groupCommentColumn[(*lit).group] + 1;
+ slines += (*lit).text.leftJustify(col, ' ') + comment(family, (*lit).comment);
+ }
+ }
+ return slines;
+}
+
+QString SourceLine::text(PURL::SourceFamily family, const List &list, uint nbSpaces)
+{
+ return lines(family, list, nbSpaces).join("\n") + "\n";
+}
+
+QString SourceLine::transformConfigName(const Pic::Data &data, uint wordIndex, const QString &name)
+{
+ if ( !data.is18Family() ) return name;
+ bool ok;
+ (void)fromHexLabel(name, &ok);
+ if (ok) return name;
+ QString s = name + '_';
+ if ( data.name()=="18C601" || data.name()=="18C801" || data.name().startsWith("18F" ) )
+ s += QString::number(wordIndex/2+1) + (wordIndex%2==0 ? 'L' : 'H');
+ else s += QString::number(wordIndex);
+ return s;
+}
+
+QStringList SourceLine::ignoredConfigNames(const Pic::Data &data, uint wordIndex)
+{
+ QStringList cnames;
+ const QStringList &names = data.config()._words[wordIndex].ignoredCNames;
+ for (uint i=0; i<uint(names.count()); i++) cnames += transformConfigName(data, wordIndex, names[i]);
+ return cnames;
+}
+
+QStringList SourceLine::extraConfigNames(const Pic::Data &data, uint wordIndex, const Pic::Config::Value &value)
+{
+ QStringList cnames;
+ const QStringList &names = value.configNames[Pic::ConfigNameType::Extra];
+ for (uint i=0; i<uint(names.count()); i++) cnames += transformConfigName(data, wordIndex, names[i]);
+ return cnames;
+}
+
+QStringList SourceLine::configNames(Pic::ConfigNameType type, const Pic::Memory &memory, uint word, bool &ok)
+{
+ ok = true;
+ const Pic::Data &data = memory.device();
+ const Pic::Config &config = data.config();
+ BitValue v = memory.normalizedWord(Pic::MemoryRangeType::Config, word);
+ const Pic::Config::Word &cword = config._words[word];
+ QStringList cnames;
+ for (uint k=0; k<uint(cword.masks.count()); k++) {
+ const Pic::Config::Mask &cmask = cword.masks[k];
+ if ( cmask.value.isInside(cword.pmask) ) continue; // protected bits
+ for (int l=cmask.values.count()-1; l>=0; l--) {
+ const Pic::Config::Value &cvalue = cmask.values[l];
+ if ( !cvalue.value.isInside(v) ) continue;
+ QStringList vcnames = cvalue.configNames[type];
+ if ( vcnames.isEmpty() && type!=Pic::ConfigNameType::Default ) vcnames = cvalue.configNames[Pic::ConfigNameType::Default];
+ for (uint i=0; i<uint(vcnames.count()); i++) {
+ if ( vcnames[i].isEmpty() ) ok = false;
+ else cnames += transformConfigName(data, word, vcnames[i]);
+ }
+ break;
+ }
+ }
+ return cnames;
+}
+
+//-----------------------------------------------------------------------------
+QString GPUtils::toDeviceName(const QString &device)
+{
+ if ( device.startsWith("PS") ) return device.lower();
+ return "p" + device.lower();
+}
+
+SourceLine::List GPUtils::includeLines(const Device::Data &data)
+{
+ SourceLine::List lines;
+ QString include = toDeviceName(data.name());
+ if ( data.name()=="12CR509A" ) include = "p12c509a";
+ else if ( QRegExp("16CR?5.?[A-C]?").exactMatch(data.name()) ) include = "p16c5x";
+ else if ( QRegExp("16F5.?").exactMatch(data.name()) ) include = "p16f5x";
+ else if ( data.name()=="16CR620A" ) include = "p16c620a";
+ lines.appendIndentedCode("#include <" + include + ".inc>");
+ return lines;
+}
+
+SourceLine::List GPUtils::generateConfigLines(const Pic::Memory &memory, bool &ok)
+{
+ SourceLine::List lines;
+ const Pic::Data &data = memory.device();
+ const Pic::Config &config = data.config();
+ for (uint i=0; i<data.nbWords(Pic::MemoryRangeType::Config); i++) {
+ const Pic::Config::Word &cword = config._words[i];
+ QStringList cnames = SourceLine::configNames(Pic::ConfigNameType::Default, memory, i, ok);
+ if ( cnames.isEmpty() ) continue;
+ QString code = "__CONFIG ";
+ if ( !cword.name.isEmpty() ) code += "_" + cword.name + ", ";
+ code += cnames.join(" & ");
+ lines.appendIndentedCode(code);
+ }
+ return lines;
+}
+
+SourceLine::List GPUtils::disassemble(const Pic::Memory &memory)
+{
+ SourceLine::List lines;
+ const Pic::Data &data = memory.device();
+
+ // includes
+ lines += includeLines(data);
+ lines.appendNotIndentedCode("processor " + toDeviceName(data.name()));
+
+ // memory config
+ bool isDefault = true;
+ for (uint k=0; k<data.nbWords(Pic::MemoryRangeType::Config); k++) {
+ BitValue op = memory.normalizedWord(Pic::MemoryRangeType::Config, k);
+ BitValue mask = data.config()._words[k].usedMask();
+ if ( !mask.isInside(op) ) isDefault = false; // this is not completely correct but otherwise empty config is written...
+ }
+ if ( !isDefault ) {
+ lines.appendEmpty();
+ lines.appendSeparator();
+ bool ok;
+ lines += generateConfigLines(memory, ok);
+ }
+
+ // user ids
+ QString tmp;
+ for (uint k=0; k<data.nbWords(Pic::MemoryRangeType::UserId); k++) {
+ BitValue op = memory.normalizedWord(Pic::MemoryRangeType::UserId, k);
+ BitValue mask = data.userIdRecommendedMask();
+ if ( mask.isInside(op) ) continue;
+ if ( data.is18Family() ) {
+ Address ad = data.range(Pic::MemoryRangeType::UserId).start + data.range(Pic::MemoryRangeType::UserId).hexFileOffset + k*data.addressIncrement(Pic::MemoryRangeType::UserId);
+ lines.appendIndentedCode("__IDLOCS " + toHexLabel(ad, data.nbCharsAddress()) + ", " + toHexLabel(op, data.nbCharsWord(Pic::MemoryRangeType::UserId)));
+ } else tmp += toHex(op.nybble(0), 1);
+ }
+ if ( !tmp.isEmpty() ) {
+ lines.appendEmpty();
+ lines.appendSeparator();
+ lines.appendIndentedCode("__IDLOCS 0x" + tmp);
+ }
+
+ // memory code
+ lines.appendEmpty();
+ lines.appendSeparator();
+ lines.appendTitle("code memory");
+ bool first = true, newOrg = true;
+ uint nb = data.nbWords(Pic::MemoryRangeType::Code);
+ for (uint k=0; k<nb; k++) {
+ BitValue op = memory.normalizedWord(Pic::MemoryRangeType::Code, k);
+ BitValue mask = data.mask(Pic::MemoryRangeType::Code);
+ if ( mask.isInside(op) ) newOrg = true;
+ else {
+ if (newOrg) {
+ if ( !first ) tmp += '\n';
+ first = false;
+ Address org = data.range(Pic::MemoryRangeType::Code).start + data.range(Pic::MemoryRangeType::Code).hexFileOffset + k*data.addressIncrement(Pic::MemoryRangeType::Code);
+ lines.appendNotIndentedCode("org " + toHexLabel(org, data.nbCharsAddress()));
+ newOrg = false;
+ }
+ char buffer[512];
+ buffer[0] = 0;
+ BitValue op2 = ((k+1)<nb ? memory.word(Pic::MemoryRangeType::Code, k+1) : 0);
+ uint n = Coff::disassemble(op.toUInt(), op2.toUInt(), k, data.architecture(), buffer, 512);
+ lines.appendIndentedCode(QString(buffer));
+ if ( n==2 ) k++;
+ }
+ }
+
+ // eeprom data
+ lines.appendEmpty();
+ lines.appendSeparator();
+ lines.appendTitle("eeprom memory");
+ newOrg = true;
+ nb = data.nbWords(Pic::MemoryRangeType::Eeprom);
+ for (uint k=0; k<nb; k++) {
+ BitValue op = memory.normalizedWord(Pic::MemoryRangeType::Eeprom, k);
+ BitValue mask = data.mask(Pic::MemoryRangeType::Eeprom);
+ if ( mask.isInside(op) ) newOrg = true;
+ else {
+ if (newOrg) {
+ Address org = data.range(Pic::MemoryRangeType::Eeprom).start + data.range(Pic::MemoryRangeType::Eeprom).hexFileOffset + k*data.addressIncrement(Pic::MemoryRangeType::Eeprom);
+ lines.appendNotIndentedCode("org " + toHexLabel(org, data.nbCharsAddress()));
+ newOrg = false;
+ }
+ lines.appendIndentedCode("de " + toHexLabel(op, data.nbCharsWord(Pic::MemoryRangeType::Eeprom)));
+ }
+ }
+
+ lines.appendNotIndentedCode("end");
+ return lines;
+}
+
+//-----------------------------------------------------------------------------
+SourceLine::List Tool::SourceGenerator::templateSourceFile(PURL::ToolType type, const Device::Data &data, bool &ok) const
+{
+ SourceLine::List lines;
+ lines.appendSeparator();
+ lines.appendTitle(i18n("Template source file generated by piklab"));
+ lines += includeLines(type, data);
+ lines.appendEmpty();
+ lines.appendSeparator();
+ lines.appendTitle(i18n("Configuration bits: adapt to your setup and needs"));
+ Device::Memory *memory = data.group().createMemory(data);
+ lines += configLines(type, *memory, ok);
+ delete memory;
+ lines.appendEmpty();
+ lines += sourceFileContent(type, data, ok);
+ return lines;
+}