summaryrefslogtreecommitdiffstats
path: root/src/coff
diff options
context:
space:
mode:
Diffstat (limited to 'src/coff')
-rw-r--r--src/coff/Makefile.am1
-rw-r--r--src/coff/base/Makefile.am13
-rw-r--r--src/coff/base/base.pro6
-rw-r--r--src/coff/base/cdb_parser.cpp417
-rw-r--r--src/coff/base/cdb_parser.h166
-rw-r--r--src/coff/base/coff.cpp97
-rw-r--r--src/coff/base/coff.h64
-rw-r--r--src/coff/base/coff.xml342
-rw-r--r--src/coff/base/coff_archive.cpp129
-rw-r--r--src/coff/base/coff_archive.h53
-rw-r--r--src/coff/base/coff_data.h22
-rw-r--r--src/coff/base/coff_object.cpp658
-rw-r--r--src/coff/base/coff_object.h322
-rw-r--r--src/coff/base/disassembler.cpp289
-rw-r--r--src/coff/base/disassembler.h80
-rw-r--r--src/coff/base/gpdis.cpp349
-rw-r--r--src/coff/base/gpopcode.cpp348
-rw-r--r--src/coff/base/gpopcode.h107
-rw-r--r--src/coff/base/text_coff.cpp262
-rw-r--r--src/coff/base/text_coff.h45
-rw-r--r--src/coff/coff.pro2
-rw-r--r--src/coff/xml/Makefile.am14
-rw-r--r--src/coff/xml/gpprocessor.cpp340
-rw-r--r--src/coff/xml/gpprocessor.h371
-rw-r--r--src/coff/xml/xml.pro17
-rw-r--r--src/coff/xml/xml_coff_parser.cpp116
26 files changed, 4630 insertions, 0 deletions
diff --git a/src/coff/Makefile.am b/src/coff/Makefile.am
new file mode 100644
index 0000000..4e5921f
--- /dev/null
+++ b/src/coff/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = xml base
diff --git a/src/coff/base/Makefile.am b/src/coff/base/Makefile.am
new file mode 100644
index 0000000..c6ffbab
--- /dev/null
+++ b/src/coff/base/Makefile.am
@@ -0,0 +1,13 @@
+INCLUDES = -I$(top_srcdir)/src $(all_includes)
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libcoff.la
+libcoff_la_LDFLAGS = $(all_libraries)
+libcoff_la_SOURCES = coff.cpp gpdis.cpp gpopcode.cpp disassembler.cpp \
+ coff_data.cpp text_coff.cpp cdb_parser.cpp coff_archive.cpp coff_object.cpp
+libcoff_la_DEPENDENCIES = coff_data.cpp
+
+noinst_DATA = coff.xml
+coff_data.cpp: ../xml/xml_coff_parser coff.xml
+ ../xml/xml_coff_parser
+CLEANFILES = coff_data.cpp
diff --git a/src/coff/base/base.pro b/src/coff/base/base.pro
new file mode 100644
index 0000000..4b4986c
--- /dev/null
+++ b/src/coff/base/base.pro
@@ -0,0 +1,6 @@
+STOPDIR = ../../..
+include($${STOPDIR}/lib.pro)
+
+TARGET = coff
+HEADERS += gpopcode.h disassembler.h coff.h coff_object.h coff_archive.h text_coff.h coff_data.h cdb_parser.h
+SOURCES += gpopcode.cpp gpdis.cpp disassembler.cpp coff.cpp coff_object.cpp coff_archive.cpp text_coff.cpp coff_data.cpp cdb_parser.cpp
diff --git a/src/coff/base/cdb_parser.cpp b/src/coff/base/cdb_parser.cpp
new file mode 100644
index 0000000..2e38b84
--- /dev/null
+++ b/src/coff/base/cdb_parser.cpp
@@ -0,0 +1,417 @@
+/***************************************************************************
+ * Copyright (C) 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 "cdb_parser.h"
+
+#include <ctype.h>
+#include "common/global/pfile.h"
+
+//----------------------------------------------------------------------------
+const CDB::ScopeType::Data CDB::ScopeType::DATA[Nb_Types] = {
+ { "G", I18N_NOOP("Global") },
+ { "F", I18N_NOOP("File") },
+ { "L", I18N_NOOP("Local") },
+ { "S", I18N_NOOP("Structure") } // ??
+};
+
+const CDB::VarType::Data CDB::VarType::DATA[Nb_Types] = {
+ { "DA", I18N_NOOP("Array") },
+ { "DF", I18N_NOOP("Function") },
+ { "DG", I18N_NOOP("Generic Pointer") },
+ { "DC", I18N_NOOP("Code Pointer") },
+ { "DX", I18N_NOOP("External RAM Pointer") },
+ { "DD", I18N_NOOP("Internal RAM Pointer") },
+ { "DP", I18N_NOOP("Paged Pointer") },
+ { "DI", I18N_NOOP("Upper-128-byte Pointer") },
+ { "SL", I18N_NOOP("Long") },
+ { "SI", I18N_NOOP("Int") },
+ { "SC", I18N_NOOP("Char") },
+ { "SS", I18N_NOOP("Short") },
+ { "SV", I18N_NOOP("Void") },
+ { "SF", I18N_NOOP("Float") },
+ { "ST", I18N_NOOP("Structure") },
+ { "SX", I18N_NOOP("SBIT") },
+ { "SB", I18N_NOOP("Bit Field") }
+};
+
+const CDB::Sign::Data CDB::Sign::DATA[Nb_Types] = {
+ { "S", I18N_NOOP("Signed") },
+ { "U", I18N_NOOP("Unsigned") }
+};
+
+const CDB::AddressSpaceType::Data CDB::AddressSpaceType::DATA[Nb_Types] = {
+ { "A", I18N_NOOP("External Stack") },
+ { "B", I18N_NOOP("Internal Stack") },
+ { "C", I18N_NOOP("Code") },
+ { "D", I18N_NOOP("Code / Static Segment") },
+ { "E", I18N_NOOP("Lower-128-byte Internal RAM") },
+ { "F", I18N_NOOP("External RAM") },
+ { "G", I18N_NOOP("Internal RAM") },
+ { "H", I18N_NOOP("Bit Addressable") },
+ { "I", I18N_NOOP("SFR Space") },
+ { "J", I18N_NOOP("SBIT Space") },
+ { "R", I18N_NOOP("Register Space") },
+ { "Z", I18N_NOOP("Function or Undefined Space") },
+};
+
+//----------------------------------------------------------------------------
+CDB::Object::Object(const PURL::Url &url, Log::Base &log)
+ : _log(log)
+{
+ PURL::File file(url, log);
+ if ( !file.openForRead() ) return;
+ QStringList lines = file.readLines();
+
+ for (_line=0; _line<uint(lines.count()); _line++) {
+ _col = 0;
+ _current = lines[_line];
+ if ( _current.isEmpty() ) continue;
+ char c;
+ if ( !readChar(c) ) return;
+ if ( !readAndCheckChar(':') ) return;
+ Record *record = 0;
+ bool ok;
+ switch (c) {
+ case 'M': ok = parseModuleRecord(record); break;
+ case 'F': ok = parseFunctionRecord(record); break;
+ case 'S': ok = parseSymbolRecord(record); break;
+ case 'T': ok = parseTypeRecord(record); break;
+ case 'L': ok = parseLinkerRecord(record); break;
+ default:
+ log.log(Log::LineType::Error, i18n("Unrecognized record"));
+ return;
+ }
+ if (!ok) {
+ delete record;
+ return;
+ }
+ _records.append(record);
+ }
+}
+
+CDB::Object::~Object()
+{
+ for (uint i=0; i<uint(_records.count()); i++) delete _records[i];
+}
+
+void CDB::Object::log(Log::LineType type, const QString &message)
+{
+ _log.log(type, message + " " + i18n("at line #%1, column #%2").arg(_line+1).arg(_col+1));
+}
+
+void CDB::Object::logMalformed(const QString &detail)
+{
+ log(Log::LineType::Error, i18n("Malformed record: ") + detail);
+}
+
+bool CDB::Object::readChar(char &c)
+{
+ if ( _col==uint(_current.length()) ) {
+ logMalformed(i18n("unexpected end of line"));
+ return false;
+ }
+ c = _current[_col].latin1();
+ _col++;
+ return true;
+}
+
+bool CDB::Object::readAndCheckChar(char c)
+{
+ char r;
+ if ( !readChar(r) ) return false;
+ if ( r!=c ) {
+ logMalformed(i18n("was expecting '%1'").arg(c));
+ return false;
+ }
+ return true;
+}
+
+bool CDB::Object::getString(const QString &s, QString &r)
+{
+ r = s;
+ if ( r.isEmpty() ) {
+ logMalformed(i18n("empty name"));
+ return false;
+ }
+ return true;
+}
+
+bool CDB::Object::readFixedLengthString(QString &s, uint size)
+{
+ s = QString::null;
+ for (uint i=0; i<size; i++) {
+ char c;
+ if ( !readChar(c) ) return false;
+ s += c;
+ }
+ return true;
+}
+
+bool CDB::Object::readStoppedString(QString &name, char stop)
+{
+ QString s;
+ for (;;) {
+ if ( _col==uint(_current.length()) ) {
+ if ( stop!=0 ) {
+ logMalformed(i18n("unexpected end of line"));
+ return false;
+ }
+ break;
+ }
+ if ( _current[_col]==stop ) break;
+ s += _current[_col];
+ _col++;
+ }
+ return getString(s, name);
+}
+
+bool CDB::Object::getUInt(const QString &s, uint &v)
+{
+ bool ok;
+ v = s.toUInt(&ok);
+ if ( !ok ) logMalformed(i18n("was expecting an uint"));
+ return ok;
+}
+
+bool CDB::Object::readUInt(uint &v)
+{
+ QString s;
+ for (;;) {
+ if ( _col==uint(_current.length()) ) break;
+ if ( !isdigit(_current[_col].latin1()) ) break;
+ s += _current[_col];
+ _col++;
+ }
+ return getUInt(s, v);
+}
+
+bool CDB::Object::readBool(bool &b)
+{
+ char c;
+ if ( !readChar(c) ) return false;
+ if ( c=='0' ) b = false;
+ else if ( c=='1' ) b = true;
+ else {
+ logMalformed(i18n("was expecting a bool ('%1')").arg(c));
+ return false;
+ }
+ return true;
+}
+
+bool CDB::Object::readHex(uint &v)
+{
+ QString s;
+ for (;;) {
+ if ( _col==uint(_current.length()) ) break;
+ if ( !isxdigit(_current[_col].latin1()) ) break;
+ s += _current[_col];
+ _col++;
+ }
+ return getUInt(s, v);
+}
+
+bool CDB::Object::parseModuleRecord(Record * &record)
+{
+ ModuleRecord *mr = new ModuleRecord;
+ record = mr;
+ return readStoppedString(mr->filename, 0);
+}
+
+bool CDB::Object::parse(Scope &scope, QString &name)
+{
+ QString s;
+ if ( !readFixedLengthString(s, 1) ) return false;
+ scope.type = ScopeType::fromKey(s);
+ switch (scope.type.type()) {
+ case ScopeType::Structure:
+ case ScopeType::Global: break;
+ case ScopeType::File:
+ case ScopeType::Local:
+ if ( !readStoppedString(scope.name, '$') ) return false;
+ break;
+ case ScopeType::Nb_Types:
+ logMalformed(i18n("unknown ScopeType"));
+ return false;
+ }
+ if ( !readAndCheckChar('$') ) return false;
+ if ( !readStoppedString(name, '$') ) return false;
+ if ( !readAndCheckChar('$') ) return false;
+ if ( !readUInt(scope.level) ) return false;
+ if ( !readAndCheckChar('$') ) return false;
+ if ( !readUInt(scope.block) ) return false;
+ return true;
+}
+
+bool CDB::Object::parse(TypeChain &typeChain)
+{
+ uint nb;
+ if ( !readAndCheckChar('{') ) return false;
+ if ( !readUInt(nb) ) return false;
+ if ( !readAndCheckChar('}') ) return false;
+ QString s;
+ if ( !readStoppedString(s, ':') ) return false;
+ QStringList list = QStringList::split(',', s, true);
+ for (uint i=0; i<uint(list.count()); i++) {
+ DCLType type;
+ QString key = list[i].mid(0, 2);
+ type.type = VarType::fromKey(key);
+ switch (type.type.type()) {
+ case VarType::Array:
+ case VarType::BitField:
+ if ( !getUInt(list[i].mid(2), type.nb) ) return false;
+ break;
+ case VarType::Structure:
+ if ( !getString(list[i].mid(2), type.name) ) return false;
+ break;
+ case VarType::Nb_Types:
+ logMalformed(i18n("unknown DCLType"));
+ return false;
+ default: break;
+ }
+ typeChain.types.append(type);
+ }
+ if ( !readAndCheckChar(':') ) return false;
+ if ( !readFixedLengthString(s, 1) ) return false;
+ typeChain.sign = Sign::fromKey(s);
+ if ( typeChain.sign==Sign::Nb_Types ) {
+ logMalformed(i18n("unknown Sign"));
+ return false;
+ }
+ return true;
+}
+
+bool CDB::Object::parse(AddressSpace &as)
+{
+ QString s;
+ if ( !readFixedLengthString(s, 1) ) return false;
+ as.type = AddressSpaceType::fromKey(s);
+ if ( as.type==AddressSpaceType::Nb_Types ) {
+ logMalformed(i18n("unknown AddressSpaceType"));
+ return false;
+ }
+ if ( !readAndCheckChar(',') ) return false;
+ if ( !readBool(as.onStack) ) return false;
+ if ( !readAndCheckChar(',') ) return false;
+ if ( !readUInt(as.stackOffset) ) return false;
+ if ( as.type==AddressSpaceType::Register ) {
+ if ( !readAndCheckChar(',') ) return false;
+ if ( !readAndCheckChar('[') ) return false;
+ if ( !readStoppedString(s, ']') ) return false;
+ as.registers = QStringList::split(',', s, true);
+ if ( as.registers.count()==0 ) {
+ logMalformed(i18n("no register defined"));
+ return false;
+ }
+ if ( !readAndCheckChar(']') ) return false;
+ }
+ return true;
+}
+
+bool CDB::Object::parse(SymbolRecord &sr)
+{
+ if ( !parse(sr.scope, sr.name) ) return false;
+ if ( !readAndCheckChar('(') ) return false;
+ if ( !parse(sr.typeChain) ) return false;
+ if ( !readAndCheckChar(')') ) return false;
+ if ( !readAndCheckChar(',') ) return false;
+ if ( !parse(sr.addressSpace) ) return false;
+ return true;
+}
+
+bool CDB::Object::parse(TypeMember &tm)
+{
+ if ( !readAndCheckChar('(') ) return false;
+ if ( !readAndCheckChar('{') ) return false;
+ if ( !readUInt(tm.offset) ) return false;
+ if ( !readAndCheckChar('}') ) return false;
+ if ( !readAndCheckChar('S') ) return false;
+ if ( !readAndCheckChar(':') ) return false;
+ if ( !parse(tm.symbol) ) return false;
+ if ( !readAndCheckChar(')') ) return false;
+ return true;
+}
+
+bool CDB::Object::parseSymbolRecord(Record * &record)
+{
+ SymbolRecord *sr = new SymbolRecord;
+ record = sr;
+ if ( !parse(*sr) ) return false;
+ return true;
+}
+
+bool CDB::Object::parseFunctionRecord(Record * &record)
+{
+ FunctionRecord *fr = new FunctionRecord;
+ record = fr;
+ if ( !parse(*fr) ) return false;
+ if ( !readAndCheckChar(',') ) return false;
+ if ( !readBool(fr->isInterruptHandler) ) return false;
+ if ( !readAndCheckChar(',') ) return false;
+ if ( !readUInt(fr->interruptHandler) ) return false;
+ if ( !readAndCheckChar(',') ) return false;
+ if ( !readUInt(fr->registerBank) ) return false;
+ return true;
+}
+
+bool CDB::Object::parseTypeRecord(Record * &record)
+{
+ TypeRecord *tr = new TypeRecord;
+ record = tr;
+ if ( !readAndCheckChar('F') ) return false;
+ if ( !readStoppedString(tr->filename, '$') ) return false;
+ if ( !readAndCheckChar('$') ) return false;
+ if ( !readStoppedString(tr->name, '[') ) return false;
+ if ( !readAndCheckChar('[') ) return false;
+ for (;;) {
+ TypeMember tm;
+ if ( !parse(tm) ) return false;
+ tr->members.append(tm);
+ if ( _current[_col]==']' ) break;
+ }
+ if ( !readAndCheckChar(']') ) return false;
+ return true;
+}
+
+bool CDB::Object::parseLinkerRecord(Record * &record)
+{
+ LinkerRecord *lr = new LinkerRecord;
+ record = lr;
+ char c;
+ if ( !readChar(c) ) return false;
+ switch (c) {
+ case 'A':
+ lr->type = LinkerRecord::AsmLine;
+ if ( !readAndCheckChar('$') ) return false;
+ if ( !readStoppedString(lr->filename, '$') ) return false;
+ if ( !readAndCheckChar('$') ) return false;
+ if ( !readUInt(lr->line) ) return false;
+ break;
+ case 'C':
+ lr->type = LinkerRecord::CLine;
+ if ( !readAndCheckChar('$') ) return false;
+ if ( !readStoppedString(lr->filename, '$') ) return false;
+ if ( !readAndCheckChar('$') ) return false;
+ if ( !readUInt(lr->line) ) return false;
+ if ( !readAndCheckChar('$') ) return false;
+ if ( !readUInt(lr->level) ) return false;
+ if ( !readAndCheckChar('$') ) return false;
+ if ( !readUInt(lr->block) ) return false;
+ break;
+ case 'X':
+ lr->type = LinkerRecord::EndAddress;
+ if ( !parse(lr->scope, lr->name) ) return false;
+ break;
+ default:
+ lr->type = LinkerRecord::Address;
+ if ( !parse(lr->scope, lr->name) ) return false;
+ break;
+ }
+ if ( !readAndCheckChar(':') ) return false;
+ if ( !readHex(lr->address) ) return false;
+ return true;
+}
diff --git a/src/coff/base/cdb_parser.h b/src/coff/base/cdb_parser.h
new file mode 100644
index 0000000..42572ab
--- /dev/null
+++ b/src/coff/base/cdb_parser.h
@@ -0,0 +1,166 @@
+/***************************************************************************
+ * Copyright (C) 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. *
+ ***************************************************************************/
+#ifndef SDCC_CDB_PARSER_H
+#define SDCC_CDB_PARSER_H
+
+#include "common/common/key_enum.h"
+#include "common/global/log.h"
+#include "common/global/purl.h"
+
+namespace CDB
+{
+
+//----------------------------------------------------------------------------
+class Record
+{
+public:
+};
+
+class ModuleRecord : public Record
+{
+public:
+ QString filename;
+};
+
+BEGIN_DECLARE_ENUM(ScopeType)
+ Global = 0, File, Local, Structure
+END_DECLARE_ENUM_STD(ScopeType)
+
+class Scope
+{
+public:
+ ScopeType type;
+ QString name; // file or function name
+ uint level, block;
+};
+
+BEGIN_DECLARE_ENUM(VarType)
+ Array = 0, Function, GenericPointer, CodePointer, ExternalRamPointer,
+ InternalRamPointer, PagedPointer, Upper128bytesPointer, Long, Int, Char,
+ Short, Void, Float, Structure, Sbit, BitField
+END_DECLARE_ENUM_STD(VarType)
+
+class DCLType
+{
+public:
+ VarType type;
+ uint nb; // for Array and BitField
+ QString name; // for Structure
+};
+
+BEGIN_DECLARE_ENUM(Sign)
+ Signed = 0, Unsigned
+END_DECLARE_ENUM_STD(Sign)
+
+class TypeChain
+{
+public:
+ QValueVector<DCLType> types;
+ Sign sign;
+};
+
+BEGIN_DECLARE_ENUM(AddressSpaceType)
+ ExternalStack = 0, InternalStack, Code, CodeStaticSegment,
+ Lower128bytesInternalRam, ExternalRam, InternalRam, BitAddressable,
+ SFR, SBIT, Register, FunctionOrUndefined
+END_DECLARE_ENUM_STD(AddressSpaceType)
+
+class AddressSpace {
+public:
+ AddressSpaceType type;
+ bool onStack;
+ uint stackOffset; // valid if onStack is true
+ QStringList registers; // for Register type
+};
+
+class SymbolRecord : public Record
+{
+public:
+ QString name;
+ Scope scope;
+ TypeChain typeChain;
+ AddressSpace addressSpace;
+};
+
+class FunctionRecord : public SymbolRecord
+{
+public:
+ bool isInterruptHandler;
+ uint interruptHandler, registerBank; // if isInterruptHandler is true
+};
+
+class TypeMember
+{
+public:
+ uint offset;
+ SymbolRecord symbol;
+};
+
+class TypeRecord : public Record
+{
+public:
+ QString filename, name;
+ QValueVector<TypeMember> members;
+};
+
+class LinkerRecord : public Record
+{
+public:
+ enum Type { Address = 0, EndAddress, AsmLine, CLine, Nb_Types };
+ Type type;
+ Scope scope; // for Address and EndAddress
+ QString name; // for Address and EndAddress
+ uint address;
+ uint line; // for AsmLine and CLine
+ QString filename; // for AsmLine and CLine
+ uint block, level; // for CLine
+};
+
+//----------------------------------------------------------------------------
+class Object
+{
+public:
+ Object(const PURL::Url &url, Log::Base &log);
+ virtual ~Object();
+
+private:
+ Log::Base &_log;
+ QString _current;
+ uint _line, _col;
+ QValueVector<Record *> _records;
+
+ void log(Log::LineType type, const QString &message);
+ void logMalformed(const QString &detail);
+ bool readBool(bool &b);
+ bool getUInt(const QString &s, uint &r);
+ bool readUInt(uint &v);
+ bool readChar(char &c);
+ bool readAndCheckChar(char c);
+ bool getString(const QString &s, QString &r);
+ bool readStoppedString(QString &s, char stop);
+ bool readFixedLengthString(QString &s, uint size);
+ bool readHex(uint &v);
+
+ bool parse(Scope &scope, QString &name);
+ bool parse(TypeChain &typeChain);
+ bool parse(TypeRecord &typeRecord);
+ bool parse(SymbolRecord &sr);
+ bool parse(AddressSpace &addressSpace);
+ bool parse(TypeMember &typeMember);
+
+ bool parseModuleRecord(Record * &record);
+ bool parseFunctionRecord(Record * &record);
+ bool parseSymbolRecord(Record * &record);
+ bool parseTypeRecord(Record * &record);
+ bool parseLinkerRecord(Record * &record);
+};
+
+} // namespace
+
+#endif
diff --git a/src/coff/base/coff.cpp b/src/coff/base/coff.cpp
new file mode 100644
index 0000000..5eaad84
--- /dev/null
+++ b/src/coff/base/coff.cpp
@@ -0,0 +1,97 @@
+/***************************************************************************
+ * 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 "coff.h"
+
+#include <time.h>
+
+#include "common/common/misc.h"
+#include "devices/list/device_list.h"
+#include "devices/base/device_group.h"
+#include "devices/pic/base/pic_register.h"
+#include "coff_data.h"
+#include "common/global/pfile.h"
+
+//----------------------------------------------------------------------------
+const CoffType::Data CoffType::DATA[Nb_Types] = {
+ { "archive", I18N_NOOP("Archive") },
+ { "object", I18N_NOOP("Object") }
+};
+
+const Coff::Format::Data Coff::Format::DATA[Nb_Types] = {
+ { 0, I18N_NOOP("Old Microchip"), 0x1234, { 20, 16, 40, 18, 16, 12 } },
+ { 0, I18N_NOOP("PIC30"), 0x1236, { 20, 28, 40, 18, 8, 10 } }, // from PIC30 binutils "coff.h" file
+ { 0, I18N_NOOP("New Microchip"), 0x1240, { 20, 18, 40, 20, 16, 12 } } // (C18 >= 3.0)
+};
+
+CoffType Coff::identify(const PURL::Url &url, Log::Base &log)
+{
+ PURL::File file(url, log);
+ if ( !file.openForRead() ) return CoffType::Nb_Types;
+ QByteArray data = file.readAll();
+ if ( log.hasError() ) return CoffType::Nb_Types;
+ uint offset = 0;
+ Format format;
+ Q_UINT32 magic;
+ return identify(data, offset, log, format, magic);
+}
+
+CoffType Coff::identify(const QByteArray &data, uint &offset, Log::Base &log, Format &format, Q_UINT32 &magic)
+{
+ QString id = "!<arch>\012";
+ if ( data.count()>=id.length() ) {
+ QString s = QString::fromAscii(data.data(), id.length());
+ if ( s==id ) {
+ offset += id.length();
+ return CoffType::Archive;
+ }
+ }
+ if ( !getULong(data, offset, 2, log, magic) ) return CoffType::Nb_Types;
+ log.log(Log::DebugLevel::Extra, QString("COFF format: %1").arg(toHexLabel(magic, 4)));
+ format = Format::Nb_Types;
+ FOR_EACH(Format, f) if ( magic==f.data().magic ) format = f;
+ return CoffType::Object;
+}
+
+//----------------------------------------------------------------------------
+bool Coff::getULong(const QByteArray &data, uint &offset, uint nbBytes, Log::Base &log, Q_UINT32 &v)
+{
+ bool ok;
+ v = ::getULong(data, offset, nbBytes, &ok);
+ if ( !ok ) {
+ log.log(Log::LineType::Error, i18n("COFF file is truncated (offset: %1 nbBytes: %2 size:%3).").arg(offset).arg(nbBytes).arg(data.count()));
+ return false;
+ }
+ offset += nbBytes;
+ return true;
+}
+
+bool Coff::getString(const QByteArray &data, uint &offset, uint nbChars, Log::Base &log, QString &name)
+{
+ if ( !checkAvailable(data, offset, nbChars) ) {
+ log.log(Log::LineType::Error, i18n("COFF file is truncated (offset: %1 nbBytes: %2 size:%3).").arg(offset).arg(nbChars).arg(data.count()));
+ return false;
+ }
+ name = QString::fromAscii(data.data()+offset, nbChars);
+ offset += nbChars;
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool Coff::Base::initParse(CoffType type, QByteArray &data, uint &offset, Log::Base &log)
+{
+ PURL::File file(_url, log);
+ if ( !file.openForRead() ) return false;
+ data = file.readAll();
+ if ( log.hasError() ) return false;
+ if ( identify(data, offset, log, _format, _magic)!=type ) {
+ log.log(Log::LineType::Error, i18n("Could not recognize file (magic number is %1).").arg(toHexLabel(_magic, 4)));
+ return false;
+ }
+ return true;
+}
diff --git a/src/coff/base/coff.h b/src/coff/base/coff.h
new file mode 100644
index 0000000..edd0ae5
--- /dev/null
+++ b/src/coff/base/coff.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+#ifndef COFF_H
+#define COFF_H
+
+#include "common/global/global.h"
+#include "devices/pic/base/pic.h"
+#include "common/global/purl.h"
+#include "common/global/log.h"
+
+BEGIN_DECLARE_ENUM(CoffType)
+ Archive = 0, Object
+END_DECLARE_ENUM_STD(CoffType)
+
+//----------------------------------------------------------------------------
+namespace Coff
+{
+extern bool getString(const QByteArray &data, uint &offset, uint nbChars, Log::Base &log, QString &name);
+extern bool getULong(const QByteArray &data, uint &offset, uint nbBytes, Log::Base &log, Q_UINT32 &v);
+
+//----------------------------------------------------------------------------
+enum SizeType { HeaderSize = 0, OptHeaderSize, SectionHeaderSize, SymbolSize,
+ LineNumberSize, RelocationSize, Nb_SizeTypes };
+struct FormatData {
+ const char *key, *label;
+ uint magic;
+ uint sizes[Nb_SizeTypes];
+};
+BEGIN_DECLARE_ENUM(Format)
+ OldMicrochip = 0, PIC30, NewMicrochip
+END_DECLARE_ENUM(Format, FormatData)
+
+extern CoffType identify(const PURL::Url &url, Log::Base &log);
+extern CoffType identify(const QByteArray &data, uint &offset, Log::Base &log, Format &format, Q_UINT32 &magic);
+
+//----------------------------------------------------------------------------
+class Base
+{
+public:
+ Base(const PURL::Url &url) : _url(url) {}
+ virtual ~Base() {}
+ virtual bool parse(Log::Base &log) = 0;
+ PURL::Url url() const { return _url; }
+ uint magic() const { return _magic; }
+
+ virtual Log::KeyList information() const = 0;
+
+protected:
+ PURL::Url _url;
+ Format _format;
+ Q_UINT32 _magic;
+
+ bool initParse(CoffType type, QByteArray &data, uint &offset, Log::Base &log);
+};
+
+} // namespace
+
+#endif
diff --git a/src/coff/base/coff.xml b/src/coff/base/coff.xml
new file mode 100644
index 0000000..229d11a
--- /dev/null
+++ b/src/coff/base/coff.xml
@@ -0,0 +1,342 @@
+<!-- ************************************************************************* -->
+<!-- * Copyright (C) 2006 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. * -->
+<!-- *************************************************************************/-->
+<!DOCTYPE piklab>
+
+<type name="coff">
+ <device name="10f200" id="0xf200" />
+ <device name="10f202" id="0xf202" />
+ <device name="10f204" id="0xf204" />
+ <device name="10f206" id="0xf206" />
+ <device name="10f220" id="0xf220" />
+ <device name="10f222" id="0xf222" />
+ <device name="12c508" id="0x2508" />
+ <device name="12c508a" id="0x508a" />
+ <device name="12c509" id="0x2509" />
+ <device name="12c509a" id="0x509a" />
+ <device name="12c671" id="0x2671" />
+ <device name="12c672" id="0x2672" />
+ <device name="12ce518" id="0x2518" />
+ <device name="12ce519" id="0x2519" />
+ <device name="12ce673" id="0x2673" />
+ <device name="12ce674" id="0x2674" />
+ <device name="12cr509a" id="0xd09a" />
+ <device name="12f508" id="0x2508" />
+ <device name="12f509" id="0x2509" />
+ <device name="12f510" id="0x2510" />
+ <device name="12f629" id="0x2629" />
+ <device name="12f635" id="0x2635" />
+ <device name="12f675" id="0x2675" />
+ <device name="12f683" id="0x2683" />
+ <device name="14000" id="0x4000" />
+<!-- <device name="16c5x" id="0x658a" /> -->
+<!-- <device name="16cxx" id="0x6c77" /> -->
+ <device name="16c432" id="0x6432" />
+ <device name="16c433" id="0x6433" />
+ <device name="16c505" id="0x2505" />
+ <device name="16c52" id="0x6c52" />
+ <device name="16c54" id="0x6c54" />
+ <device name="16c54a" id="0x654a" />
+ <device name="16c54b" id="0x654b" />
+ <device name="16c54c" id="0x654c" />
+ <device name="16c55" id="0x6c55" />
+ <device name="16c55a" id="0x655a" />
+ <device name="16c554" id="0x6554" />
+ <device name="16c557" id="0x6557" />
+ <device name="16c558" id="0x6558" />
+ <device name="16c56" id="0x6c56" />
+ <device name="16c56a" id="0x656a" />
+ <device name="16c57" id="0x6c57" />
+ <device name="16c57c" id="0x657c" />
+ <device name="16c58a" id="0x658a" />
+ <device name="16c58b" id="0x658b" />
+ <device name="16c61" id="0x6c61" />
+ <device name="16c62" id="0x6c62" />
+ <device name="16c62a" id="0x662a" />
+ <device name="16c62b" id="0x662b" />
+ <device name="16c620" id="0x6620" />
+ <device name="16c620a" id="0x620a" />
+ <device name="16c621" id="0x6621" />
+ <device name="16c621a" id="0x621a" />
+ <device name="16c622" id="0x6622" />
+ <device name="16c622a" id="0x622a" />
+ <device name="16c63" id="0x6c63" />
+ <device name="16c63a" id="0x663a" />
+ <device name="16c64" id="0x6c64" />
+ <device name="16c64a" id="0x664a" />
+ <device name="16c642" id="0x6642" />
+ <device name="16c65" id="0x6c65" />
+ <device name="16c65a" id="0x665a" />
+ <device name="16c65b" id="0x665b" />
+ <device name="16c66" id="0x6c66" />
+ <device name="16c662" id="0x6662" />
+ <device name="16c67" id="0x6c67" />
+ <device name="16c71" id="0x6c71" />
+ <device name="16c710" id="0x6710" />
+ <device name="16c711" id="0x6711" />
+ <device name="16c712" id="0x6712" />
+ <device name="16c715" id="0x6715" />
+ <device name="16c716" id="0x6716" />
+ <device name="16c717" id="0x6717" />
+ <device name="16c72" id="0x6c72" />
+ <device name="16c72a" id="0x672a" />
+ <device name="16c73" id="0x673a" />
+ <device name="16c73a" id="0x673a" />
+ <device name="16c73b" id="0x673b" />
+ <device name="16c74" id="0x6c74" />
+ <device name="16c745" id="0x6745" />
+<!-- <device name="16c747" id="0x6747" /> -->
+ <device name="16c74a" id="0x674a" />
+ <device name="16c74b" id="0x674b" />
+ <device name="16c76" id="0x6c76" />
+ <device name="16c765" id="0x6765" />
+ <device name="16c77" id="0x6c77" />
+ <device name="16c770" id="0x6770" />
+ <device name="16c771" id="0x6771" />
+ <device name="16c773" id="0x6773" />
+ <device name="16c774" id="0x6774" />
+ <device name="16c781" id="0x6781" />
+ <device name="16c782" id="0x6782" />
+ <device name="16c84" id="0x6c84" />
+ <device name="16c923" id="0x6923" />
+ <device name="16c924" id="0x6924" />
+ <device name="16c925" id="0x6925" />
+ <device name="16c926" id="0x6926" />
+ <device name="16ce623" id="0x6623" />
+ <device name="16ce624" id="0x6624" />
+ <device name="16ce625" id="0x6625" />
+<!-- <device name="16cr54" id="0xdc54" /> -->
+ <device name="16cr54a" id="0xd54a" />
+ <device name="16cr54b" id="0xd54b" />
+ <device name="16cr54c" id="0xdc54" />
+ <device name="16cr56a" id="0xd56a" />
+<!-- <device name="16cr57a" id="0xd57a" /> -->
+ <device name="16cr57b" id="0xd57b" />
+ <device name="16cr57c" id="0xd57c" />
+ <device name="16cr58a" id="0xd58a" />
+ <device name="16cr58b" id="0xd58b" />
+ <device name="16cr62" id="0xdc62" />
+ <device name="16cr620a" id="0xd20a" />
+ <device name="16cr63" id="0x6d63" />
+ <device name="16cr64" id="0xdc64" />
+ <device name="16cr65" id="0x6d65" />
+ <device name="16cr72" id="0x6d72" />
+ <device name="16cr83" id="0xdc83" />
+ <device name="16cr84" id="0xdc84" />
+ <device name="16f505" id="0x654f" />
+ <device name="16f54" id="0x654f" />
+ <device name="16f57" id="0x657f" />
+ <device name="16f59" id="0x659f" />
+ <device name="16f610" id="0x6610" />
+ <device name="16f627" id="0x6627" />
+ <device name="16f627a" id="0x627a" />
+ <device name="16f628" id="0x6628" />
+ <device name="16f628a" id="0x628a" />
+ <device name="16f630" id="0x6630" />
+ <device name="16f636" id="0x6636" />
+ <device name="16f639" id="0x6639" />
+ <device name="16f648a" id="0x648a" />
+ <device name="16f676" id="0x6676" />
+ <device name="16f684" id="0x6684" />
+ <device name="16f685" id="0x6685" />
+ <device name="16f687" id="0x6687" />
+ <device name="16f688" id="0x6688" />
+ <device name="16f689" id="0x6689" />
+ <device name="16f690" id="0x6690" />
+ <device name="16f716" id="0x716f" />
+ <device name="16f72" id="0x672f" />
+ <device name="16f73" id="0x673f" />
+ <device name="16f737" id="0x737f" />
+ <device name="16f74" id="0x674f" />
+ <device name="16f747" id="0x6747" />
+ <device name="16f76" id="0x676f" />
+ <device name="16f767" id="0x767f" />
+ <device name="16f77" id="0x677f" />
+ <device name="16f777" id="0x777f" />
+ <device name="16f785" id="0x785f" />
+ <device name="16f818" id="0x818f" />
+ <device name="16f819" id="0x819f" />
+ <device name="16f83" id="0x6c83" />
+ <device name="16f84" id="0x6f84" />
+ <device name="16f84a" id="0x684a" />
+ <device name="16f87" id="0x687f" />
+ <device name="16f870" id="0x870f" />
+ <device name="16f871" id="0x871f" />
+ <device name="16f872" id="0x872f" />
+ <device name="16f873" id="0x873f" />
+ <device name="16f873a" id="0x873a" />
+ <device name="16f874" id="0x874f" />
+ <device name="16f874a" id="0x874a" />
+ <device name="16f876" id="0x876f" />
+ <device name="16f876a" id="0x876a" />
+ <device name="16f877" id="0x877f" />
+ <device name="16f877a" id="0x877a" />
+ <device name="16f88" id="0x688f" />
+ <device name="16f882" id="0x882f" />
+ <device name="16f883" id="0x883f" />
+ <device name="16f884" id="0x884f" />
+ <device name="16f886" id="0x886f" />
+ <device name="16f887" id="0x887f" />
+ <device name="16f913" id="0x913f" />
+ <device name="16f914" id="0x914f" />
+ <device name="16f916" id="0x916f" />
+ <device name="16f917" id="0x917f" />
+ <device name="16hv540" id="0x6540" />
+<!-- <device name="17cxx" id="0x7756" /> -->
+ <device name="17c42" id="0x7c42" />
+ <device name="17c42a" id="0x742a" />
+ <device name="17c43" id="0x7c43" />
+ <device name="17c44" id="0x7c44" />
+ <device name="17c752" id="0x7752" />
+ <device name="17c756" id="0x7756" />
+ <device name="17c756a" id="0x756a" />
+ <device name="17c762" id="0x7762" />
+ <device name="17c766" id="0x7766" />
+ <device name="17cr42" id="0xe42a" />
+ <device name="17cr43" id="0xec43" />
+
+ <device name="18c242" id="0x8242" />
+ <device name="18c252" id="0x8252" />
+ <device name="18c442" id="0x8442" />
+ <device name="18c452" id="0x8452" />
+ <device name="18c601" id="0x8601" />
+ <device name="18c658" id="0x8658" />
+ <device name="18c801" id="0x8801" />
+ <device name="18c858" id="0x8858" />
+ <device name="18f1220" id="0xa122" />
+ <device name="18f1230" id="0xa123 0x1230" />
+<!-- <device name="18f1231" id="0x1231" /> -->
+ <device name="18f1320" id="0xa132" />
+ <device name="18f1330" id="0xa133 0x1330" />
+<!-- <device name="18f1331" id="0x1331" /> -->
+ <device name="18f2220" id="0xa222" />
+ <device name="18f2221" id="0x2221" />
+ <device name="18f2320" id="0xa232" />
+ <device name="18f2321" id="0x2321" />
+ <device name="18f2331" id="0x2331" />
+ <device name="18f2410" id="0x2410" />
+ <device name="18f242" id="0x242f" />
+ <device name="18f2420" id="0x2420" />
+ <device name="18f2431" id="0x2431" />
+ <device name="18f2439" id="0x2439" />
+ <device name="18f2450" id="0x2450" />
+ <device name="18f2455" id="0x2455" />
+ <device name="18f248" id="0x8248" />
+ <device name="18f2480" id="0x2480" />
+ <device name="18f24J10" id="0xD410" />
+ <device name="18f2510" id="0x2510" />
+ <device name="18f2515" id="0x2515" />
+ <device name="18f252" id="0x252f" />
+ <device name="18f2520" id="0x2520" />
+ <device name="18f2525" id="0x2525" />
+ <device name="18f2539" id="0x2539" />
+ <device name="18f2550" id="0x2550" />
+ <device name="18f258" id="0x8258" />
+ <device name="18f2580" id="0x2580" />
+ <device name="18f2585" id="0x2585" />
+ <device name="18f25J10" id="0xD510" />
+ <device name="18f2610" id="0x2610 0xa261" />
+ <device name="18f2620" id="0x2620 0xa262" />
+ <device name="18f2680" id="0x2680" />
+<!-- <device name="18f2681" id="0x2681" /> -->
+ <device name="18f2682" id="0x2682" />
+ <device name="18f2685" id="0x2685" />
+ <device name="18f4220" id="0xa422" />
+ <device name="18f4221" id="0x4221" />
+ <device name="18f4320" id="0xa432" />
+ <device name="18f4321" id="0x4321" />
+ <device name="18f4331" id="0x4331" />
+ <device name="18f4410" id="0x4410" />
+ <device name="18f442" id="0x442f" />
+ <device name="18f4420" id="0x4420" />
+ <device name="18f4431" id="0x4431" />
+ <device name="18f4439" id="0x4439" />
+ <device name="18f4450" id="0x4450" />
+ <device name="18f4455" id="0x4455" />
+ <device name="18f448" id="0x8448" />
+ <device name="18f4480" id="0x4480" />
+ <device name="18f44J10" id="0xE410" />
+ <device name="18f4510" id="0x4510" />
+ <device name="18f4515" id="0x4515" />
+ <device name="18f452" id="0x452f" />
+ <device name="18f4520" id="0x4520" />
+ <device name="18f4525" id="0x4525" />
+ <device name="18f4539" id="0x4539" />
+ <device name="18f4550" id="0x4550" />
+ <device name="18f458" id="0x8458" />
+ <device name="18f4580" id="0x4580" />
+ <device name="18f4585" id="0x4585" />
+ <device name="18f45J10" id="0xE510" />
+ <device name="18f4610" id="0xa461 0x4610" />
+ <device name="18f4620" id="0xa462 0x4620" />
+ <device name="18f4680" id="0x4680" />
+<!-- <device name="18f4681" id="0x4681" /> -->
+ <device name="18f4682" id="0x4682" />
+ <device name="18f4685" id="0x4685" />
+ <device name="18f6310" id="0xa631 0x6310" />
+ <device name="18f6390" id="0xa639 0x6390" />
+ <device name="18f6410" id="0xa641 0x6410" />
+ <device name="18f6490" id="0xa649 0x6490" />
+<!-- <device name="18f64j15" id="0xb415" /> -->
+ <device name="18f6520" id="0xa652" />
+ <device name="18f6525" id="0x6525" />
+ <device name="18f6527" id="0x6527" />
+ <device name="18f6585" id="0x6585" />
+ <device name="18f65j10" id="0xb510" />
+ <device name="18f65j15" id="0xb515" />
+ <device name="18f6620" id="0xa662" />
+ <device name="18f6621" id="0xa621" />
+ <device name="18f6622" id="0xf622" />
+ <device name="18f6627" id="0xa627 0x6627" />
+ <device name="18f6680" id="0x6680" />
+ <device name="18f66j10" id="0xb610" />
+ <device name="18f66j15" id="0xb615" />
+ <device name="18f66j60" id="0xb660" />
+ <device name="18f66j65" id="0xb665" />
+ <device name="18f6720" id="0xa672" />
+ <device name="18f6722" id="0x6722" />
+ <device name="18f67j10" id="0xb710" />
+ <device name="18f67j60" id="0xb760" />
+ <device name="18f8310" id="0x8310" />
+ <device name="18f8390" id="0x8390" />
+ <device name="18f8410" id="0x8410" />
+ <device name="18f8490" id="0x8490" />
+<!-- <device name="18f84j15" id="0xc415" /> -->
+ <device name="18f8520" id="0xa852" />
+ <device name="18f8525" id="0x8525" />
+ <device name="18f8527" id="0x8527" />
+ <device name="18f8585" id="0x8585" />
+ <device name="18f85j10" id="0xc510" />
+ <device name="18f85j15" id="0xc515" />
+ <device name="18f8620" id="0xa862" />
+ <device name="18f8621" id="0x8621" />
+ <device name="18f8622" id="0x8622" />
+ <device name="18f8627" id="0x8627" />
+ <device name="18f8680" id="0x8680" />
+ <device name="18f86j10" id="0xc610" />
+ <device name="18f86j15" id="0xc615" />
+ <device name="18f86j60" id="0xc660" />
+ <device name="18f86j65" id="0xc665" />
+ <device name="18f8720" id="0xa872" />
+ <device name="18f8722" id="0x8721" />
+ <device name="18f87j10" id="0xc710" />
+ <device name="18f87j60" id="0xc760" />
+ <device name="18f96j60" id="0xd660" />
+ <device name="18f96j65" id="0xd665" />
+ <device name="18f97j60" id="0xd760" />
+<!--
+ <device name="rf509af" id="0x6509" />
+ <device name="rf509ag" id="0x7509" />
+ <device name="rf675f" id="0x3675" />
+ <device name="rf675h" id="0x4675" />
+ <device name="rf675k" id="0x5675" />
+ <device name="sx18" id="0x0018" />
+ <device name="sx20" id="0x0020" />
+ <device name="sx28" id="0x0028" />
+-->
+</type>
diff --git a/src/coff/base/coff_archive.cpp b/src/coff/base/coff_archive.cpp
new file mode 100644
index 0000000..72a8883
--- /dev/null
+++ b/src/coff/base/coff_archive.cpp
@@ -0,0 +1,129 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 "coff_archive.h"
+
+//----------------------------------------------------------------------------
+Coff::Member::Member(const QByteArray &data, uint &offset, Log::Base &log)
+{
+ // parse header
+ QString s;
+ if ( !getString(data, offset, 256, log, s) ) return;
+ int i = s.find('/');
+ if ( i==-1 ) {
+ log.log(Log::LineType::Error, i18n("Member name not terminated by '/' (\"%1\").").arg(s));
+ return;
+ }
+ _name = s.mid(0, i);
+ if ( !getString(data, offset, 12, log, s) ) return; // mtime
+ if ( !getString(data, offset, 10, log, s) ) return;
+ i = s.find('l');
+ if ( i==-1 ) {
+ log.log(Log::LineType::Error, i18n("File size not terminated by 'l' (\"%1\").").arg(s));
+ return;
+ }
+ bool ok;
+ _nbBytes = s.mid(0, i).toUInt(&ok);
+ if ( !ok ) {
+ log.log(Log::LineType::Error, i18n("Wrong format for file size \"%1\".").arg(s));
+ return;
+ }
+ Q_UINT32 v;
+ if ( !getULong(data, offset, 2, log, v) ) return;
+ log.log(Log::DebugLevel::Extra, i18n("Magic number: %1").arg(toHexLabel(v, 4)));
+// if ( v!=0x600A ) {
+// log.log(Log::LineType::Error, i18n("Wrong magic for Microchip archive (\"%1\").").arg(toHexLabel(v, 4)));
+// return;
+// }
+ offset += _nbBytes;
+}
+
+//----------------------------------------------------------------------------
+Coff::Archive::Archive(const PURL::Url &url)
+ : Base(url)
+{}
+
+bool Coff::Archive::parse(Log::Base &log)
+{
+ QByteArray data;
+ uint offset = 0, symbolEnd = 0;
+ Member *symbol = 0;
+ if ( !initParse(CoffType::Archive, data, offset, log) ) return false;
+ for (;;) {
+ if ( offset==uint(data.count()) ) break; // end of archive
+ uint start = offset;
+ Member *member = new Member(data, offset, log);
+ if ( log.hasError() ) return false;
+ if ( member->name().isEmpty() ) {
+ symbolEnd = offset;
+ symbol = member;
+ } else {
+ _members[member->name()] = member;
+ _offsets[start] = member;
+ }
+ }
+ if (symbol) {
+ if ( !readSymbols(data, symbolEnd - symbol->nbBytes(), log) ) return false;
+ delete symbol;
+ }
+ return true;
+}
+
+Coff::Archive::~Archive()
+{
+ QMap<QString, Member *>::const_iterator it;
+ for (it=_members.begin(); it!=_members.end(); ++it) delete it.data();
+}
+
+bool Coff::Archive::readSymbols(const QByteArray &data, uint offset, Log::Base &log)
+{
+ Q_UINT32 nb;
+ if ( !getULong(data, offset, 4, log, nb) ) return false;
+ QValueVector<Member *> members(nb);
+ for (uint i=0; i<nb; i++) {
+ Q_UINT32 start;
+ if ( !getULong(data, offset, 4, log, start) ) return false;
+ if ( !_offsets.contains(start) ) {
+ log.log(Log::LineType::Error, i18n("Unknown file member offset: %1").arg(toHexLabel(start, 8)));
+ return false;
+ }
+ members[i] = _offsets[start];
+ }
+ for (uint i=0; i<nb; i++) {
+ QString name(data.data() + offset);
+ offset += name.length() + 1;
+ _symbols[name] = members[i];
+ }
+ return true;
+}
+
+Log::KeyList Coff::Archive::information() const
+{
+ Log::KeyList keys(i18n("Information:"));
+ keys.append(i18n("No. of file members:"), QString::number(members().count()));
+ keys.append(i18n("No. of symbols:"), QString::number(symbols().count()));
+ return keys;
+}
+
+Log::KeyList Coff::Archive::membersInformation() const
+{
+ Log::KeyList keys(i18n("File Members:"));
+ QMap<QString, Member *>::const_iterator it;
+ for (it=members().begin(); it!=members().end(); ++it)
+ keys.append(it.key(), i18n("size: %1 bytes").arg(it.data()->nbBytes()));
+ return keys;
+}
+
+Log::KeyList Coff::Archive::symbolsInformation() const
+{
+ Log::KeyList keys(i18n("Symbols:"));
+ QMap<QString, Member *>::const_iterator it;
+ for (it=symbols().begin(); it!=symbols().end(); ++it)
+ keys.append(it.key(), it.data()->name());
+ return keys;
+}
diff --git a/src/coff/base/coff_archive.h b/src/coff/base/coff_archive.h
new file mode 100644
index 0000000..ba43a38
--- /dev/null
+++ b/src/coff/base/coff_archive.h
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * Copyright (C) 2006 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. *
+ ***************************************************************************/
+#ifndef COFF_ARCHIVE_H
+#define COFF_ARCHIVE_H
+
+#include "coff.h"
+
+namespace Coff
+{
+//----------------------------------------------------------------------------
+class Member
+{
+public:
+ Member(const QByteArray &data, uint &offset, Log::Base &log);
+ QString name() const { return _name; }
+ uint nbBytes() const { return _nbBytes; }
+
+private:
+ QString _name;
+ uint _nbBytes;
+};
+
+//----------------------------------------------------------------------------
+class Archive : public Base
+{
+public:
+ Archive(const PURL::Url &url);
+ virtual ~Archive();
+ virtual bool parse(Log::Base &log);
+ const QMap<QString, Member *>members() const { return _members; }
+ const QMap<QString, Member *>symbols() const { return _symbols; }
+
+ virtual Log::KeyList information() const;
+ Log::KeyList membersInformation() const;
+ Log::KeyList symbolsInformation() const;
+
+private:
+ QMap<QString, Member *> _members; // name -> Member *
+ QMap<uint, Member *> _offsets; // offset -> Member *
+ QMap<QString, Member *> _symbols; // name -> Member *
+
+ bool readSymbols(const QByteArray &data, uint offset, Log::Base &log);
+};
+
+} // namespace
+
+#endif
diff --git a/src/coff/base/coff_data.h b/src/coff/base/coff_data.h
new file mode 100644
index 0000000..9676e42
--- /dev/null
+++ b/src/coff/base/coff_data.h
@@ -0,0 +1,22 @@
+/***************************************************************************
+ * Copyright (C) 2006 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. *
+ ***************************************************************************/
+#ifndef COFF_DATA_H
+#define COFF_DATA_H
+
+namespace Coff
+{
+ enum { MAX_NB_IDS = 2 };
+ struct Data {
+ uint ids[MAX_NB_IDS];
+ };
+ extern QString findId(uint id);
+
+} // namespace
+
+#endif
diff --git a/src/coff/base/coff_object.cpp b/src/coff/base/coff_object.cpp
new file mode 100644
index 0000000..f4109f9
--- /dev/null
+++ b/src/coff/base/coff_object.cpp
@@ -0,0 +1,658 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 "coff_object.h"
+
+#include "common/common/misc.h"
+#include "devices/list/device_list.h"
+#include "devices/base/device_group.h"
+#include "devices/pic/base/pic_register.h"
+#include "coff_data.h"
+#include "common/global/pfile.h"
+
+//----------------------------------------------------------------------------
+bool Coff::getName(const QByteArray &data, uint &offset, uint nbChars, uint stringTableOffset,
+ Log::Base &log, QString &name)
+{
+ Q_UINT32 v;
+ if ( !getULong(data, offset, 4, log, v) ) return false;
+ if ( v!=0 ) { // name is not in string table
+ offset -= 4;
+ return getString(data, offset, nbChars, log, name);
+ }
+ if ( !getULong(data, offset, 4, log, v) ) return false;
+ // ### do a sanity check here
+ name = QString(data.data()+stringTableOffset+v);
+ return true;
+}
+
+const Coff::OptHeaderFormat::Data Coff::OptHeaderFormat::DATA[Nb_Types] = {
+ { 0, I18N_NOOP("Old Microchip") },
+ { 0, I18N_NOOP("New Microchip") },
+ { 0, I18N_NOOP("PICC Compiler") },
+ { 0, I18N_NOOP("CCS Compiler") }
+};
+
+const Coff::OptHeaderData Coff::OPT_HEADER_DATA[] = {
+ { 0x5678, OptHeaderFormat::OldMicrochip, true },
+ { 0x0000, OptHeaderFormat::NewMicrochip, true },
+ { 0x0001, OptHeaderFormat::NewMicrochip, true }, // PIC30 with debug
+ { 0x1388, OptHeaderFormat::Picc, false }, // PICC
+ { 0x1B78, OptHeaderFormat::Ccsc, false }, // CCSC
+ { 0x0000, OptHeaderFormat::Nb_Types, false }
+};
+
+//----------------------------------------------------------------------------
+const Coff::AuxSymbolType::Data Coff::AuxSymbolType::DATA[Nb_Types] = {
+ { 0, I18N_NOOP("Direct") },
+ { 0, I18N_NOOP("File") },
+ { 0, I18N_NOOP("Indentifier") },
+ { 0, I18N_NOOP("Section") }
+};
+
+Coff::AuxSymbol *Coff::AuxSymbol::factory(const Object &object, AuxSymbolType type, const QByteArray &data, uint offset, uint stringTableOffset, Log::Base &log)
+{
+ switch (type.type()) {
+ case AuxSymbolType::Direct: return new AuxSymbolDirect(object, data, offset, stringTableOffset, log);
+ case AuxSymbolType::File: return new AuxSymbolFile(object, data, offset, stringTableOffset, log);
+ case AuxSymbolType::Identifier: return new AuxSymbolIdentifier(object, data, offset, stringTableOffset, log);
+ case AuxSymbolType::Section: return new AuxSymbolSection(object, data, offset, stringTableOffset, log);
+ case AuxSymbolType::Nb_Types: return new AuxSymbolUnknown(object);
+ }
+ Q_ASSERT(false);
+ return 0;
+}
+
+Coff::AuxSymbolDirect::AuxSymbolDirect(const Object &object, const QByteArray &data, uint start, uint stringTableOffset, Log::Base &log)
+ : AuxSymbol(object)
+{
+ uint offset = start;
+ Q_UINT32 v;
+ if ( !getULong(data, offset, 1, log, v) ) return;
+ _command = v;
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ _string = QString(data.data()+stringTableOffset+v);
+}
+
+Coff::AuxSymbolFile::AuxSymbolFile(const Object &object, const QByteArray &data, uint start, uint stringTableOffset, Log::Base &log)
+ : AuxSymbol(object)
+{
+ uint offset = start;
+ Q_UINT32 v;
+ if ( object.format()==Format::PIC30 ) {
+ if ( !getName(data, offset, 14, stringTableOffset, log, _filename) ) return;
+ _line = 0;
+ } else {
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ _filename = QString(data.data()+stringTableOffset+v);
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ _line = v;
+ }
+}
+
+Coff::AuxSymbolIdentifier::AuxSymbolIdentifier(const Object &object, const QByteArray &data, uint start, uint stringTableOffset, Log::Base &log)
+ : AuxSymbol(object)
+{
+ uint offset = start;
+ Q_UINT32 v;
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ _string = QString(data.data()+stringTableOffset+v);
+}
+
+Coff::AuxSymbolSection::AuxSymbolSection(const Object &object, const QByteArray &data, uint start, uint, Log::Base &log)
+ : AuxSymbol(object)
+{
+ uint offset = start;
+ Q_UINT32 v;
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ _length = v;
+ if ( !getULong(data, offset, 2, log, v) ) return;
+ _nbRelocations = v;
+ if ( !getULong(data, offset, 2, log, v) ) return;
+ _nbLineNumbers = v;
+}
+
+//----------------------------------------------------------------------------
+const Coff::SymbolSectionType::Data Coff::SymbolSectionType::DATA[Nb_Types] = {
+ { 0, I18N_NOOP("Inside Section") },
+ { 0, I18N_NOOP("Undefined Section") },
+ { 0, I18N_NOOP("Absolute Value") },
+ { 0, I18N_NOOP("Debug Symbol") }
+};
+
+const Coff::SymbolClass::Data Coff::SymbolClass::DATA[Nb_Types] = {
+ { 0, I18N_NOOP("Automatic Variable"), 1 },
+ { 0, I18N_NOOP("External Symbol"), 2 },
+ { 0, I18N_NOOP("Static Symbol"), 3 },
+ { 0, I18N_NOOP("Register Variable"), 4 },
+ { 0, I18N_NOOP("External Definition"), 5 },
+ { 0, I18N_NOOP("Label"), 6 },
+ { 0, I18N_NOOP("Undefined Label"), 7 },
+ { 0, I18N_NOOP("Member of Structure"), 8 },
+ { 0, I18N_NOOP("Function Argument"), 9 },
+ { 0, I18N_NOOP("Structure Tag"), 10 },
+ { 0, I18N_NOOP("Member of Union"), 11 },
+ { 0, I18N_NOOP("Union Tag"), 12 },
+ { 0, I18N_NOOP("Type Definition"), 13 },
+ { 0, I18N_NOOP("Undefined Static"), 14 },
+ { 0, I18N_NOOP("Enumeration Tag"), 15 },
+ { 0, I18N_NOOP("Member of Enumeration"), 16 },
+ { 0, I18N_NOOP("Register Parameter"), 17 },
+ { 0, I18N_NOOP("Bit Field"), 18 },
+ { 0, I18N_NOOP("Auto Argument"), 19 },
+ { 0, I18N_NOOP("Dummy Entry (end of block)"), 20 },
+ { 0, I18N_NOOP("Beginning or End of Block"), 100 },
+ { 0, I18N_NOOP("Beginning or End of Function"), 101 },
+ { 0, I18N_NOOP("End of Structure"), 102 },
+ { 0, I18N_NOOP("Filename"), 103 },
+ { 0, I18N_NOOP("Line Number"), 104 },
+ { 0, I18N_NOOP("Duplicate Tag"), 105 },
+ { 0, I18N_NOOP("Section"), 109 }
+};
+
+const Coff::SymbolType::Data Coff::SymbolType::DATA[Nb_Types] = {
+ { 0, I18N_NOOP("Void"), 0x0001 },
+ { 0, I18N_NOOP("Char"), 0x0010 },
+ { 0, I18N_NOOP("Short"), 0x0011 },
+ { 0, I18N_NOOP("Int"), 0x0100 },
+ { 0, I18N_NOOP("Long"), 0x0101 },
+ { 0, I18N_NOOP("Float"), 0x0110 },
+ { 0, I18N_NOOP("Double"), 0x0111 },
+ { 0, I18N_NOOP("Structure"), 0x1000 },
+ { 0, I18N_NOOP("Union"), 0x1001 },
+ { 0, I18N_NOOP("Enumeration"), 0x1010 },
+ { 0, I18N_NOOP("Member Of Enumeration"), 0x1011 },
+ { 0, I18N_NOOP("Unsigned Char"), 0x1100 },
+ { 0, I18N_NOOP("Unsigned Short"), 0x1101 },
+ { 0, I18N_NOOP("Unsigned Int"), 0x1110 },
+ { 0, I18N_NOOP("Unsigned Long"), 0x1111 },
+ { 0, I18N_NOOP("Long Double"), 0x10000 }
+};
+
+const Coff::SymbolDerivedType::Data Coff::SymbolDerivedType::DATA[Nb_Types] = {
+ { 0, I18N_NOOP("Pointer"), 0x010000 },
+ { 0, I18N_NOOP("Function"), 0x100000 },
+ { 0, I18N_NOOP("Array"), 0x110000 }
+};
+
+Coff::Symbol::Symbol(const Object &object, const QByteArray &data, uint start,
+ uint stringTableOffset, const QString &lastFilename, Log::Base &log)
+ : BaseSymbol(object)
+{
+ uint offset = start;
+ Q_UINT32 v;
+ if ( !getName(data, offset, 8, stringTableOffset, log, _name) ) return;
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ _value = v;
+ if ( !getULong(data, offset, 2, log, v) ) return;
+ _section = v;
+ uint nb = (object.format()==Format::NewMicrochip ? 4 : 2);
+ if ( !getULong(data, offset, nb, log, v) ) return;
+ _type = SymbolType::Nb_Types;
+ FOR_EACH(SymbolType, type)
+ if ( (v & 0x001111)==type.data().id ) { _type = type; break; }
+ _dtype = SymbolDerivedType::Nb_Types;
+ FOR_EACH(SymbolDerivedType, dtype)
+ if ( (v & 0x110000)==dtype.data().id ) { _dtype = dtype; break; }
+ if ( !getULong(data, offset, 1, log, v) ) return;
+ _sclass = SymbolClass::Nb_Types;
+ FOR_EACH(SymbolClass, sclass)
+ if ( v==sclass.data().id ) { _sclass = sclass; break; }
+ if ( !getULong(data, offset, 1, log, v) ) return;
+ uint nbAux = v;
+ //qDebug("symbol: %s value=%s type=%i dtype=%i class=%i nbAux=%i section=%i", _name.latin1(), toHexLabel(_value, 4).latin1(), _type, _dtype, _class, nbAux, _section);
+
+ AuxSymbolType auxType = AuxSymbolType::Nb_Types;
+ if ( _name==".direct" ) auxType = AuxSymbolType::Direct;
+ else if ( _name==".ident" ) auxType = AuxSymbolType::Identifier;
+ else if ( _sclass==SymbolClass::Filename ) auxType = AuxSymbolType::File;
+ else if ( _sclass==SymbolClass::Section ) auxType = AuxSymbolType::Section;
+ if ( auxType!=AuxSymbolType::Nb_Types && nbAux==0 ) log.log(Log::LineType::Warning, i18n("Symbol without needed auxilliary symbol (type=%1)").arg(auxType.type()));
+ Q_ASSERT( (offset-start)==object.size(SymbolSize) );
+ _aux.resize(nbAux);
+ for (uint i=0; i<nbAux; i++) {
+ _aux[i] = AuxSymbol::factory(object, auxType, data, offset, stringTableOffset, log);
+ offset += object.size(SymbolSize);
+ if ( log.hasError() ) return;
+ }
+
+ _filename = lastFilename;
+ for (uint i=0; i<uint(_aux.count()); i++)
+ if ( _aux[i]->type()==AuxSymbolType::File ) _filename = static_cast<AuxSymbolFile *>(_aux[i])->filename();
+}
+
+Coff::SymbolSectionType Coff::Symbol::sectionType() const
+{
+ switch (_section) {
+ case 0x0000: return SymbolSectionType::UndefinedSection;
+ case 0xFFFF: return SymbolSectionType::AbsoluteValue;
+ case 0xFFFE: return SymbolSectionType::DebugSymbol;
+ }
+ return SymbolSectionType::InsideSection;
+}
+
+//----------------------------------------------------------------------------
+Coff::Relocation::Relocation(const Object &object, const Section &section,
+ const QByteArray &data, uint start, Log::Base &log)
+ : Element(object), _symbol(0)
+{
+ uint offset = start;
+ Q_UINT32 v;
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ _address = v;
+ if ( _address>section.size() ) log.log(Log::LineType::Warning, i18n("Relocation address beyong section size: %1/%2").arg(v).arg(section.size()));
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ if ( v>=object.nbSymbols() ) {
+ log.log(Log::LineType::Error, i18n("Relocation has unknown symbol: %1").arg(v));
+ return;
+ }
+ if ( object.symbol(v)->isAuxSymbol() ) {
+ log.log(Log::LineType::Error, i18n("Relocation is an auxiliary symbol: %1").arg(v));
+ return;
+ }
+ _symbol = static_cast<const Symbol *>(object.symbol(v));
+ if ( object.format()!=Format::PIC30 ) {
+ if ( !getULong(data, offset, 2, log, v) ) return;
+ _offset = short(v);
+ }
+ if ( !getULong(data, offset, 2, log, v) ) return;
+ _type = v;
+ //qDebug("reloc %s: address=%s offset=%i type=%i", _symbol->_name.latin1(), toHexLabel(_address, 4).latin1(), _offset, _type);
+}
+
+//----------------------------------------------------------------------------
+Coff::CodeLine::CodeLine(const Object &object, const Section &section,
+ const QByteArray &data, uint start, const QString &lastFilename, Log::Base &log)
+ : Element(object), _section(section), _symbol(0)
+{
+ uint offset = start;
+ Q_UINT32 v;
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ uint tmp = v;
+ if ( object.format()==Format::PIC30 ) {
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ _line = v;
+ if ( _line!=0 ) {
+ _address = tmp;
+ _filename = lastFilename;
+ //qDebug("code line %i: %s", _line, toHexLabel(_address, nbChars(_address)).latin1());
+ } else {
+ if ( tmp>=object.nbSymbols() ) {
+ log.log(Log::LineType::Error, i18n("Codeline has unknown symbol: %1").arg(tmp));
+ return;
+ }
+ if ( object.symbol(tmp)->isAuxSymbol() ) {
+ log.log(Log::LineType::Error, i18n("Codeline is an auxiliary symbol: %1").arg(tmp));
+ return;
+ }
+ _symbol = static_cast<const Symbol *>(object.symbol(tmp));
+ _filename = _symbol->filename();
+ //qDebug("code line %i: %s", _line, _symbol->_name.latin1());
+ }
+ } else {
+ if ( tmp>=object.nbSymbols() ) {
+ log.log(Log::LineType::Error, i18n("Codeline has unknown symbol: %1").arg(tmp));
+ return;
+ }
+ if ( object.symbol(tmp)->isAuxSymbol() ) {
+ log.log(Log::LineType::Error, i18n("Codeline is an auxiliary symbol: %1").arg(tmp));
+ return;
+ }
+ _symbol = static_cast<const Symbol *>(object.symbol(tmp));
+ _filename = _symbol->filename();
+ if ( !getULong(data, offset, 2, log, v) ) return;
+ _line = v;
+ if ( object.optHeaderFormat()==OptHeaderFormat::Picc && _line>=2 ) _line -= 2; // #### ??
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ _address = v;
+ if ( !getULong(data, offset, 2, log, v) ) return;
+ // flags
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ // function index
+ //qDebug("code line %i: %s", _line, toHexLabel(_address, nbChars(_address)).latin1());
+ }
+// if ( _symbol && _symbol->_class!=Symbol::CFile )
+// log.log(Log::LineType::Warning, i18n("Line without file symbol associated (%1:%2 %3).")
+// .arg(_section._name).arg(toHexLabel(_address, nbChars(_address))).arg(_symbol->_class));
+}
+
+//----------------------------------------------------------------------------
+const Coff::SectionType::Data Coff::SectionType::DATA[Nb_Types] = {
+ { 0, I18N_NOOP("Config") },
+ { 0, I18N_NOOP("Device ID") },
+ { 0, I18N_NOOP("User IDs") },
+ { 0, I18N_NOOP("Uninitialized Data") },
+ { 0, I18N_NOOP("Initialized Data") },
+ { 0, I18N_NOOP("Rom Data") },
+ { 0, I18N_NOOP("Code") }
+};
+
+Coff::Section::Section(const Device::Data &device, const Object &object,
+ const QByteArray &data, uint start, uint stringTableOffset, Log::Base &log)
+ : Element(object)
+{
+ uint offset = start;
+ Q_UINT32 v;
+ if ( !getName(data, offset, 8, stringTableOffset, log, _name) ) return;
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ _address = v;
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ //if ( _address!=v ) log.log(Log::LineType::Warning, i18n("Virtual address (%1) does not match physical address (%2) in %3.")
+ // .arg(toHexLabel(v, 4)).arg(toHexLabel(_address, 4)).arg(_name));
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ _size = v;
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ uint dataOffset = v;
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ uint relocationOffset = v;
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ uint lineNumberOffset = v;
+ if ( !getULong(data, offset, 2, log, v) ) return;
+ uint nbRelocations = v;
+ if ( !getULong(data, offset, 2, log, v) ) return;
+ uint nbLineNumbers = v;
+ if ( !getULong(data, offset, 4, log, v) ) return;
+ _flags = v;
+
+ // read data
+ Q_ASSERT ( device.group().name()=="pic" );
+ const Pic::Data &pdata = static_cast<const Pic::Data &>(device);
+ //qDebug("section %s: address=%s size=%i flags=%i", _name.data(), toHexLabel(_address, 4).latin1(), _size, int(_flags));
+ if ( _size!=0 && dataOffset!=0 ) {
+ uint inc = 1;
+ uint nbWords = _size;
+ uint nbBytesWord = 1;
+ bool b = ( (_flags & FText) || (_flags & FDataRom) );
+ if (b) {
+ nbBytesWord = pdata.nbBytesWord(Pic::MemoryRangeType::Code);
+ nbWords /= nbBytesWord;
+ inc = pdata.addressIncrement(Pic::MemoryRangeType::Code);
+ }
+ for (uint i=0; i<nbWords; i++) {
+ Address address = _address + inc*i;
+ if ( !getULong(data, dataOffset, nbBytesWord, log, v) ) return;
+ _instructions[address].value = v;
+ }
+ for (uint i=0; i<nbWords; i++) {
+ Address address = _address + inc*i;
+ BitValue op = _instructions[address].value;
+ if ( _flags & FText ) {
+ char buffer[512];
+ buffer[0] = 0;
+ BitValue op2 = ((i+1)<nbWords ? _instructions[address+inc].value : 0);
+ uint nbop = disassemble(op.toUInt(), op2.toUInt(), address.toUInt()/inc, pdata.architecture(), buffer, 512);
+ _instructions[address].disasm = QString(buffer);
+ _instructions[address].opcode = toHex(op, pdata.nbCharsWord(Pic::MemoryRangeType::Code));
+ if ( nbop==2 ) {
+ _instructions[address+inc].opcode = toHex(op2, pdata.nbCharsWord(Pic::MemoryRangeType::Code));
+ i++;
+ }
+ //qDebug(" %s: %s (%s %s)", toHex(address, 4).data(), _data[address].disasm.data(), _data[address].opcode.data(), (nbop==2 ? _data[address+inc].opcode.data() : ""));
+ } else if ( _flags & FDataRom ) _instructions[address].opcode = toHex(op, 4);
+ else if ( _flags & FData ) _instructions[address].opcode = toHex(op.maskWith(0xFF), 2);
+ }
+ }
+
+ // read relocations
+ if ( relocationOffset!=0 ) {
+ _relocations.resize(nbRelocations);
+ for (uint i=0; i<nbRelocations; i++) {
+ _relocations[i] = new Relocation(object, *this, data, relocationOffset, log);
+ relocationOffset += object.size(RelocationSize);
+ if ( log.hasError() ) return;
+ }
+ }
+
+ // read line numbers
+ if ( lineNumberOffset!=0 ) {
+ QString lastFilename;
+ _lines.resize(nbLineNumbers);
+ for (uint i=0; i<nbLineNumbers; i++) {
+ _lines[i] = new CodeLine(object, *this, data, lineNumberOffset, lastFilename, log);
+ lastFilename = _lines[i]->filename();
+ lineNumberOffset += object.size(LineNumberSize);
+ if ( log.hasError() ) return;
+ }
+ }
+}
+
+Coff::Section::~Section()
+{
+ for (uint i=0; i<uint(_relocations.count()); i++) delete _relocations[i];
+ for (uint i=0; i<uint(_lines.count()); i++) delete _lines[i];
+}
+
+Coff::SectionType Coff::Section::type() const
+{
+ if ( _name==".config" ) return SectionType::Config;
+ if ( _name==".devid" ) return SectionType::DeviceId;
+ if ( _name==".idlocs" ) return SectionType::UserIds;
+ if ( _flags & FText ) return SectionType::Code;
+ if ( _flags & FData ) return SectionType::InitializedData;
+ if ( _flags & FBSS ) return SectionType::UninitializedData;
+ if ( _flags & FDataRom ) return SectionType::DataRom;
+ return SectionType::Nb_Types;
+}
+
+//----------------------------------------------------------------------------
+Coff::Object::Object(const Device::Data *device, const PURL::Url &url)
+ : Base(url), _device(device)
+{}
+
+bool Coff::Object::parse(Log::Base &log)
+{
+ // header
+ QByteArray data;
+ uint offset = 0;
+ if ( !initParse(CoffType::Object, data, offset, log) ) return false;
+ if ( _format==Format::Nb_Types ) {
+ log.log(Log::LineType::Error, i18n("COFF format not supported: magic number is %1.").arg(toHexLabel(_magic, 4)));
+ return false;
+ }
+ log.log(Log::DebugLevel::Extra, QString("COFF format: %1").arg(toHexLabel(_magic, 4)));
+ if ( !parseHeader(data, offset, log) ) return false;
+
+ // optionnal header
+ Q_ASSERT( offset==size(HeaderSize) );
+ if ( !getULong(data, offset, 2, log, _optHeaderMagic) ) return false;
+ log.log(Log::DebugLevel::Extra, QString("COFF optionnal header format: %1").arg(toHexLabel(_optHeaderMagic, 4)));
+ _optHeaderFormat = OptHeaderFormat::Nb_Types;
+ uint i = 0;
+ for (; OPT_HEADER_DATA[i].optHeaderFormat!=OptHeaderFormat::Nb_Types; i++) if ( _optHeaderMagic==OPT_HEADER_DATA[i].magic ) break;
+ _optHeaderFormat = OPT_HEADER_DATA[i].optHeaderFormat;
+ if ( _optHeaderFormat==OptHeaderFormat::Nb_Types ) {
+ log.log(Log::LineType::Warning, i18n("Optional header format not supported: magic number is %1.").arg(toHexLabel(_optHeaderMagic, 4)));
+ offset += size(OptHeaderSize)-2;
+ } else if ( !OPT_HEADER_DATA[i].parsed ) {
+ log.log(Log::DebugLevel::Normal, QString("Optional header not parsed: magic number is %1.").arg(toHexLabel(_optHeaderMagic, 4)));
+ offset += size(OptHeaderSize)-2;
+ } else if ( !parseOptionnalHeader(data, offset, log) ) return false;
+
+ // parse symbol table
+ uint stringTableOffset = _symbolOffset + _nbSymbols*size(SymbolSize);
+ QString lastFilename;
+ _symbols.resize(_nbSymbols);
+ for (uint i=0; i<_nbSymbols; i++) {
+ Symbol *s = new Symbol(*this, data, _symbolOffset, stringTableOffset, lastFilename, log);
+ if ( log.hasError() ) return false;
+ if ( !s->filename().isEmpty() ) lastFilename = s->filename();
+ _symbols[i] = s;
+ _msymbols[s->name()] = s;
+ _symbolOffset += size(SymbolSize);
+ for (uint k=0; k<uint(s->auxSymbols().count()); k++) {
+ i++;
+ _symbols[i] = s->auxSymbols()[k];
+ _symbolOffset += size(SymbolSize);
+ }
+ }
+
+ // parse sections
+ Q_ASSERT( offset==(size(HeaderSize) + size(OptHeaderSize)) );
+ _sections.resize(_nbSections);
+ for (uint i=0; i<_nbSections; i++) {
+ _sections[i] = new Section(*_device, *this, data, offset, stringTableOffset, log);
+ offset += size(SectionHeaderSize);
+ if ( log.hasError() ) return false;
+ }
+
+ // extract filenames
+ for (uint i=0; i<_nbSymbols; i++) {
+ if ( _symbols[i]==0 || _symbols[i]->isAuxSymbol() ) continue;
+ QString s = static_cast<const Symbol *>(_symbols[i])->filename();
+ if ( s.isEmpty() || s=="fake" || _filenames.contains(s) ) continue;
+ _filenames.append(s);
+ }
+
+ // extract variables
+ for (uint i=0; i<nbSymbols(); i++) {
+ if ( _symbols[i]==0 || _symbols[i]->isAuxSymbol() ) continue;
+ const Symbol *sym = static_cast<const Symbol *>(_symbols[i]);
+ if ( sym->symbolClass()!=SymbolClass::Static ) continue;
+ if ( sym->sectionType()!=SymbolSectionType::InsideSection ) continue;
+ QString name = sym->name();
+ if ( name.startsWith("_$_") || name.startsWith("__") || name.startsWith(".") ) continue; // special variables (?)
+ _variables[name] = sym->value() & 0xFFF; // #### ??
+ }
+
+ return true;
+}
+
+bool Coff::Object::parseHeader(const QByteArray &data, uint &offset, Log::Base &log)
+{
+ Q_UINT32 v;
+ if ( !getULong(data, offset, 2, log, v) ) return false;
+ _nbSections = v;
+ if ( !getULong(data, offset, 4, log, v) ) return false;
+// time_t time = v;
+ if ( !getULong(data, offset, 4, log, v) ) return false;
+ _symbolOffset = v;
+ if ( !getULong(data, offset, 4, log, v) ) return false;
+ _nbSymbols = v;
+ if ( !getULong(data, offset, 2, log, v) ) return false;
+ if ( v!=size(OptHeaderSize) ) {
+ log.log(Log::LineType::Error, i18n("Optionnal header size is not %1: %2").arg(size(OptHeaderSize)).arg(v));
+ return false;
+ }
+ if ( !getULong(data, offset, 2, log, v) ) return false;
+ _flags = Flags(v);
+ return true;
+}
+
+bool Coff::Object::parseOptionnalHeader(const QByteArray &data, uint &offset, Log::Base &log)
+{
+ Q_UINT32 v;
+ int nb = (_format==Format::NewMicrochip ? 4 : 2);
+ if ( !getULong(data, offset, nb, log, v) ) return false; // version stamp
+ if ( _format==Format::PIC30 ) {
+ if ( !getULong(data, offset, 4, log, v) ) return false; // text size in bytes, padded to firmware boundary
+ if ( !getULong(data, offset, 4, log, v) ) return false; // initialized data "
+ if ( !getULong(data, offset, 4, log, v) ) return false; // uninitialized data "
+ if ( !getULong(data, offset, 4, log, v) ) return false; // entry point
+ if ( !getULong(data, offset, 4, log, v) ) return false; // offset of text
+ if ( !getULong(data, offset, 4, log, v) ) return false; // offset of data
+ if ( _device==0 ) _device = Device::lister().data("30F2010"); // for e.g.
+ } else {
+ if ( !getULong(data, offset, 4, log, v) ) return false;
+ // #### at least for C18 compiler, it can be compiled for generic processor: in such case
+ // the pic type will be 18C452 in non-extended mode and 18F4620 for extended mode...
+ QString name = Coff::findId(v);
+ log.log(Log::DebugLevel::Normal, QString("Device name: \"%1\"").arg(name));
+ if ( name.isEmpty() ) {
+ log.log(Log::DebugLevel::Normal, QString("Unknown processor type: %1").arg(toHexLabel(v, 4)));
+ log.log(Log::LineType::Error, i18n("Could not determine processor (%1).").arg(toHexLabel(v, 4)));
+ return false;
+ } else if ( _device==0 ) _device = Device::lister().data(name);
+ else if ( name!=_device->name() ) log.log(Log::DebugLevel::Normal, QString("Different processor name: %1").arg(name));
+ if ( !getULong(data, offset, 4, log, v) ) return false;
+ const Pic::Data *pdata = static_cast<const Pic::Data *>(_device);
+ if (pdata) {
+ uint nbBits = pdata->nbBitsWord(Pic::MemoryRangeType::Code) / pdata->addressIncrement(Pic::MemoryRangeType::Code);
+ if ( v!=nbBits ) log.log(Log::DebugLevel::Normal, QString("Rom width is not %1: %2").arg(nbBits).arg(v));
+ }
+ if ( !getULong(data, offset, 4, log, v) ) return false;
+ if (pdata) {
+ uint nbBits = pdata->registersData().nbBits();
+ if ( v!=nbBits ) log.log(Log::DebugLevel::Normal, QString("Ram width is not %1: %2").arg(nbBits).arg(v));
+ }
+ }
+ return true;
+}
+
+Coff::Object::~Object()
+{
+ for (uint i=0; i<nbSymbols(); i++) delete _symbols[i];
+ for (uint i=0; i<nbSections(); i++) delete _sections[i];
+}
+
+QString Coff::Object::variableName(Address address) const
+{
+ QMap<QString, Address>::const_iterator it;
+ for (it=_variables.begin(); it!=_variables.end(); ++it)
+ if ( it.data()==address ) return it.key();
+ return QString::null;
+}
+
+//----------------------------------------------------------------------------
+QValueVector<Pic::RegisterNameData> Pic::sfrList(const Pic::Data &data)
+{
+ QValueVector<Pic::RegisterNameData> list;
+ const Pic::RegistersData &rdata = data.registersData();
+ for (uint i=0; i<rdata.nbRegisters(); i++) {
+ uint address = rdata.nbBytes() * i;
+ Pic::RegisterType type = rdata.type(address);
+ Device::RegisterProperties rp = rdata.properties(address);
+ if ( !(rp & Device::Readable) ) continue;
+ Register::TypeData rtd(address, rdata.nbChars());
+ if ( type==Pic::Sfr ) list.append(Pic::RegisterNameData(rdata.label(address), rtd));
+ }
+ QMap<QString, Pic::CombinedData>::const_iterator it;
+ for (it=rdata.combined.begin(); it!=rdata.combined.end(); ++it) {
+ Register::TypeData td(it.key(), it.data().address, it.data().nbChars);
+ list.append(Pic::RegisterNameData(it.key(), td));
+ }
+ if ( data.architecture()==Pic::Architecture::P16X )
+ list.append(Pic::RegisterNameData("WREG", Register::TypeData("WREG", rdata.nbChars())));
+ qHeapSort(list);
+ return list;
+}
+
+QValueVector<Pic::RegisterNameData> Pic::gprList(const Pic::Data &data, const Coff::Object *coff)
+{
+ QValueVector<Pic::RegisterNameData> list;
+ const Pic::RegistersData &rdata = data.registersData();
+ for (uint i=0; i<rdata.nbRegisters(); i++) {
+ uint address = rdata.nbBytes() * i;
+ Pic::RegisterType type = rdata.type(address);
+ Device::RegisterProperties rp = rdata.properties(address);
+ if ( !(rp & Device::Readable) ) continue;
+ if (type==Pic::Gpr ) {
+ QString s = toHexLabel(address, rdata.nbCharsAddress());
+ if (coff) {
+ QString name = coff->variableName(address);
+ if ( !name.isEmpty() ) s += " (" + name + ")";
+ }
+ Register::TypeData rtd(address, rdata.nbChars());
+ list.append(Pic::RegisterNameData(s, rtd));
+ }
+ }
+ return list;
+}
+
+QValueVector<Pic::RegisterNameData> Pic::variableList(const Pic::Data &data, const Coff::Object &coff)
+{
+ QValueVector<Pic::RegisterNameData> list;
+ const Pic::RegistersData &rdata = data.registersData();
+ QMap<QString, Address> variables = coff.variables();
+ QMap<QString, Address>::const_iterator vit;
+ for (vit=variables.begin(); vit!=variables.end(); ++vit) {
+ Register::TypeData rtd(vit.data(), rdata.nbChars());
+ list.append(Pic::RegisterNameData(vit.key() + " (" + toHexLabel(vit.data(), rdata.nbCharsAddress()) + ")", rtd));
+ }
+ qHeapSort(list);
+ return list;
+}
diff --git a/src/coff/base/coff_object.h b/src/coff/base/coff_object.h
new file mode 100644
index 0000000..8b98129
--- /dev/null
+++ b/src/coff/base/coff_object.h
@@ -0,0 +1,322 @@
+/***************************************************************************
+ * Copyright (C) 2006 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. *
+ ***************************************************************************/
+#ifndef COFF_OBJECT_H
+#define COFF_OBJECT_H
+
+#include "coff.h"
+#include "devices/base/register.h"
+
+namespace Coff
+{
+//----------------------------------------------------------------------------
+extern bool getName(const QByteArray &data, uint &offset, uint nbChars, uint stringTableOffset, Log::Base &log, QString &name);
+extern int disassemble(long int opcode, long int opcode2, int org, Pic::Architecture architecture, char *buffer, size_t sizeof_buffer);
+
+BEGIN_DECLARE_ENUM(OptHeaderFormat)
+ OldMicrochip = 0, NewMicrochip, Picc, Ccsc
+END_DECLARE_ENUM_STD(OptHeaderFormat)
+
+struct OptHeaderData {
+ uint magic;
+ OptHeaderFormat optHeaderFormat;
+ bool parsed;
+};
+extern const OptHeaderData OPT_HEADER_DATA[];
+
+class Object;
+class Section;
+
+//----------------------------------------------------------------------------
+class Element
+{
+public:
+ Element(const Object &object) : _object(object) {}
+ virtual ~Element() {}
+
+protected:
+ const Object &_object;
+};
+
+//----------------------------------------------------------------------------
+class BaseSymbol : public Element
+{
+public:
+ BaseSymbol(const Object &object) : Element(object) {}
+ virtual bool isAuxSymbol() const = 0;
+};
+
+BEGIN_DECLARE_ENUM(AuxSymbolType)
+ Direct = 0, File, Identifier, Section
+END_DECLARE_ENUM_STD(AuxSymbolType)
+
+class AuxSymbol : public BaseSymbol
+{
+public:
+ virtual bool isAuxSymbol() const { return true; }
+ static AuxSymbol *factory(const Object &object, AuxSymbolType type, const QByteArray &data,
+ uint offset, uint stringTableOffset, Log::Base &log);
+
+public:
+ AuxSymbol(const Object &object) : BaseSymbol(object) {}
+ virtual AuxSymbolType type() const = 0;
+};
+
+class AuxSymbolDirect : public AuxSymbol
+{
+public:
+ AuxSymbolDirect(const Object &object, const QByteArray &data, uint offset, uint stringTableOffset, Log::Base &log);
+ virtual AuxSymbolType type() const { return AuxSymbolType::Direct; }
+
+private:
+ uchar _command;
+ QString _string;
+};
+
+class AuxSymbolFile : public AuxSymbol
+{
+public:
+ AuxSymbolFile(const Object &object, const QByteArray &data, uint offset, uint stringTableOffset, Log::Base &log);
+ virtual AuxSymbolType type() const { return AuxSymbolType::File; }
+ QString filename() const { return _filename; }
+ uint line() const { return _line; }
+
+private:
+ uint _line;
+ QString _filename;
+};
+
+class AuxSymbolIdentifier : public AuxSymbol
+{
+public:
+ AuxSymbolIdentifier(const Object &object, const QByteArray &data, uint offset, uint stringTableOffset, Log::Base &log);
+ virtual AuxSymbolType type() const { return AuxSymbolType::Identifier; }
+ QString string() const { return _string; }
+
+private:
+ QString _string;
+};
+
+class AuxSymbolSection : public AuxSymbol
+{
+public:
+ AuxSymbolSection(const Object &object, const QByteArray &data, uint offset, uint stringTableOffset, Log::Base &log);
+ virtual AuxSymbolType type() const { return AuxSymbolType::Section; }
+
+private:
+ uint _length, _nbRelocations, _nbLineNumbers;
+};
+
+class AuxSymbolUnknown : public AuxSymbol
+{
+public:
+ AuxSymbolUnknown(const Object &object) : AuxSymbol(object) {}
+ virtual AuxSymbolType type() const { return AuxSymbolType::Nb_Types; }
+};
+
+//----------------------------------------------------------------------------
+BEGIN_DECLARE_ENUM(SymbolSectionType)
+ InsideSection = 0, UndefinedSection, AbsoluteValue, DebugSymbol
+END_DECLARE_ENUM_STD(SymbolSectionType)
+
+struct SymbolClassData {
+ const char *key, *label;
+ uint id;
+};
+BEGIN_DECLARE_ENUM(SymbolClass)
+ Automatic = 0, External, Static, Register, ExternalDefinition,
+ Label, UndefinedLabel, MemberOfStructure, FunctionArgument, StructureTag,
+ MemberOfUnion, UnionTag, TypeDefinition, UndefinedStatic, EnumerationTag,
+ MemberOfEnumeration, RegisterParameter, BitField, AutoArgument, EndOfBlock,
+ BeginEndOfBlock, BeginEndOfFunction, EndOfStructure, Filename, LineNumber,
+ DuplicateTag, Section
+END_DECLARE_ENUM(SymbolClass, SymbolClassData)
+
+struct SymbolTypeData {
+ const char *key, *label;
+ uint id;
+};
+BEGIN_DECLARE_ENUM(SymbolType)
+ Void = 0, Char, Short, Int, Long, Float, Double, Struct, Union,
+ Enum, MemberOfEnum, UChar, UShort, UInt, ULong, LongDouble
+END_DECLARE_ENUM(SymbolType, SymbolTypeData)
+
+struct SymbolDerivedTypeData {
+ const char *key, *label;
+ uint id;
+};
+BEGIN_DECLARE_ENUM(SymbolDerivedType)
+ Pointer = 0, Function, Array
+END_DECLARE_ENUM(SymbolDerivedType, SymbolDerivedTypeData)
+
+class Symbol : public BaseSymbol
+{
+public:
+ Symbol(const Object &object, const QByteArray &data, uint offset, uint stringTableOffset,
+ const QString &lastFilename, Log::Base &log);
+ virtual bool isAuxSymbol() const { return false; }
+ QString name() const { return _name; }
+ QString filename() const { return _filename; }
+ const QValueVector<AuxSymbol *> &auxSymbols() const { return _aux; }
+ SymbolClass symbolClass() const { return _sclass; }
+ SymbolSectionType sectionType() const;
+ SymbolType type() const { return _type; }
+ SymbolDerivedType derivedType() const { return _dtype; }
+ uint value() const { return _value; }
+ uint section() const { Q_ASSERT( sectionType()==SymbolSectionType::InsideSection ); return _section; }
+
+private:
+ QString _name, _filename;
+ uint _value, _section;
+ SymbolClass _sclass;
+ SymbolType _type;
+ SymbolDerivedType _dtype;
+ QValueVector<AuxSymbol *> _aux;
+};
+
+//----------------------------------------------------------------------------
+class Relocation : public Element
+{
+public:
+ Relocation(const Object &object, const Section &section, const QByteArray &data,
+ uint offset, Log::Base &log);
+
+private:
+ ulong _address, _type;
+ short _offset;
+ const Symbol *_symbol;
+};
+
+//----------------------------------------------------------------------------
+class CodeLine : public Element
+{
+public:
+ CodeLine(const Object &object, const Section &section, const QByteArray &data,
+ uint offset, const QString &lastFilename, Log::Base &log);
+ const Section &section() const { return _section; }
+ QString filename() const { return _filename; }
+ uint line() const { return _line; }
+ Address address() const { return _address; }
+ const Symbol *symbol() const { return _symbol; }
+
+private:
+ const Section &_section;
+ uint _line;
+ Address _address;
+ QString _filename;
+ const Symbol *_symbol;
+};
+
+//----------------------------------------------------------------------------
+BEGIN_DECLARE_ENUM(SectionType)
+ Config = 0, DeviceId, UserIds, UninitializedData, InitializedData, DataRom, Code
+END_DECLARE_ENUM_STD(SectionType)
+
+class Section : public Element
+{
+public:
+ class InstructionData {
+ public:
+ BitValue value;
+ QString opcode, disasm;
+ };
+
+public:
+ Section(const Device::Data &device, const Object &object, const QByteArray &data, uint offset,
+ uint stringTableOffset, Log::Base &log);
+ ~Section();
+ SectionType type() const;
+ QString name() const { return _name; }
+ Address address() const { return _address; }
+ uint size() const { return _size; }
+ uint flags() const { return _flags; }
+ const QMap<Address, InstructionData> &instructions() const { return _instructions; }
+ const QValueVector<Relocation *> &relocations() const { return _relocations; }
+ const QValueVector<CodeLine *> &lines() const { return _lines; }
+
+private:
+ QString _name;
+ Address _address;
+ uint _size, _flags;
+ QMap<Address, InstructionData> _instructions;
+ QValueVector<Relocation *> _relocations;
+ QValueVector<CodeLine *> _lines;
+
+ enum Flag { FText = 0x00020, FData = 0x00040, FBSS = 0x00080, FDataRom = 0x00100,
+ FAbs = 0x01000, FShared = 0x02000, FOverlay = 0x04000, FAccess = 0x08000,
+ FActivationRecord = 0x10000 };
+};
+
+//----------------------------------------------------------------------------
+class Object : public Base
+{
+public:
+ Object(const Device::Data *device, const PURL::Url &url);
+ virtual ~Object();
+ virtual bool parse(Log::Base &log);
+ Format format() const { return _format; }
+ const Device::Data *device() const { return _device; }
+ uint size(SizeType stype) const { return _format.data().sizes[stype]; }
+ OptHeaderFormat optHeaderFormat() const { return _optHeaderFormat; }
+ uint optHeaderMagic() const { return _optHeaderMagic; }
+ uint nbSymbols() const { return _symbols.count(); }
+ const BaseSymbol *symbol(uint i) const { return _symbols[i]; }
+ const Symbol *symbol(const QString &name) const { return (_msymbols.contains(name) ? _msymbols[name] : 0); }
+ uint nbSections() const { return _sections.count(); }
+ const Section *section(uint i) const { return _sections[i]; }
+ const QStringList &filenames() const { return _filenames; }
+ const QMap<QString, Address> &variables() const { return _variables; }
+ QString variableName(Address address) const;
+
+ enum Flag { RelocationStripped = 0x0001, Executable = 0x0002, LineNumberStripped = 0x0004,
+ SymbolStripped = 0x0080, Extended18 = 0x4000, Generic = 0x8000 };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+protected:
+ Q_UINT32 _optHeaderMagic;
+ OptHeaderFormat _optHeaderFormat;
+ const Device::Data *_device;
+ uint _nbSections, _nbSymbols, _symbolOffset;
+ Flags _flags;
+ QValueVector<BaseSymbol *> _symbols;
+ QMap<QString, Symbol *> _msymbols; // name -> Symbol *
+ QValueVector<Section *> _sections;
+ QStringList _filenames;
+ QMap<QString, Address> _variables; // name -> address
+
+ virtual bool parseHeader(const QByteArray &data, uint &offset, Log::Base &log);
+ virtual bool parseOptionnalHeader(const QByteArray &data, uint &offset, Log::Base &log);
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(Object::Flags)
+
+} // namespace
+
+//----------------------------------------------------------------------------
+namespace Pic
+{
+
+class RegisterNameData
+{
+public:
+ RegisterNameData() {}
+ RegisterNameData(const QString &label, const Register::TypeData &data) : _label(label), _data(data) {}
+ QString label() const { return _label; }
+ const Register::TypeData &data() const { return _data; }
+ bool operator <(const RegisterNameData &rnd) const { return _label<rnd._label; };
+
+private:
+ QString _label;
+ Register::TypeData _data;
+};
+extern QValueVector<RegisterNameData> sfrList(const Pic::Data &data);
+extern QValueVector<RegisterNameData> gprList(const Pic::Data &data, const Coff::Object *coff);
+extern QValueVector<RegisterNameData> variableList(const Pic::Data &data, const Coff::Object &coff);
+
+} // namespace
+
+#endif
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;
+}
diff --git a/src/coff/base/disassembler.h b/src/coff/base/disassembler.h
new file mode 100644
index 0000000..e713610
--- /dev/null
+++ b/src/coff/base/disassembler.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+ * Copyright (C) 2006 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. *
+ ***************************************************************************/
+#ifndef DISASSEMBLER_H
+#define DISASSEMBLER_H
+
+#include "common/common/purl_base.h"
+#include "devices/pic/base/pic_config.h"
+namespace Device { class Data; class Memory; }
+namespace Pic { class Data; class Memory; }
+
+//-----------------------------------------------------------------------------
+namespace SourceLine
+{
+
+enum Type { Indented, NotIndented, Title, Separator, Empty };
+
+class Data {
+public:
+ Data(Type _type = Empty, const QString &_code = QString::null, const QString &_comment = QString::null)
+ : type(_type), code(_code), comment(_comment) {}
+ Type type;
+ QString code, comment;
+};
+
+class List : public QValueList<Data>
+{
+public:
+ List() {}
+ void appendSeparator() { append(Separator); }
+ void appendEmpty() { append(Empty); }
+ void appendTitle(const QString &text) { append(Data(Title, QString::null, text)); }
+ void appendIndentedCode(const QString &code, const QString &comment = QString::null) { append(Data(Indented, code, comment)); }
+ void appendNotIndentedCode(const QString &code, const QString &comment = QString::null) { append(Data(NotIndented, code, comment)); }
+};
+
+extern QString comment(PURL::SourceFamily family, const QString &text);
+extern QStringList lines(PURL::SourceFamily family, const List &list, uint nbSpaces);
+extern QString text(PURL::SourceFamily family, const List &list, uint nbSpaces);
+extern QString transformConfigName(const Pic::Data &data, uint wordIndex, const QString &name);
+extern QStringList ignoredConfigNames(const Pic::Data &data, uint wordIndex);
+extern QStringList extraConfigNames(const Pic::Data &data, uint wordIndex, const Pic::Config::Value &value);
+extern QStringList configNames(Pic::ConfigNameType type, const Pic::Memory &memory, uint word, bool &ok);
+
+} // namespace
+
+//-----------------------------------------------------------------------------
+namespace GPUtils
+{
+
+extern QString toDeviceName(const QString &device);
+extern SourceLine::List includeLines(const Device::Data &data);
+extern SourceLine::List generateConfigLines(const Pic::Memory &memory, bool &ok);
+extern SourceLine::List disassemble(const Pic::Memory &memory);
+
+} // namespace
+
+//-----------------------------------------------------------------------------
+namespace Tool
+{
+
+class SourceGenerator
+{
+public:
+ SourceGenerator() {}
+ virtual ~SourceGenerator() {}
+ virtual SourceLine::List configLines(PURL::ToolType type, const Device::Memory &memory, bool &ok) const = 0;
+ SourceLine::List templateSourceFile(PURL::ToolType type, const Device::Data &data, bool &ok) const;
+ virtual SourceLine::List sourceFileContent(PURL::ToolType type, const Device::Data &data, bool &ok) const = 0;
+ virtual SourceLine::List includeLines(PURL::ToolType type, const Device::Data &data) const = 0;
+};
+
+} // namespace
+
+#endif
diff --git a/src/coff/base/gpdis.cpp b/src/coff/base/gpdis.cpp
new file mode 100644
index 0000000..2df4f24
--- /dev/null
+++ b/src/coff/base/gpdis.cpp
@@ -0,0 +1,349 @@
+/* Disassemble memory
+ Copyright (C) 2001, 2002, 2003, 2004, 2005
+ Craig Franklin
+
+This file is part of gputils.
+
+gputils 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, or (at your option)
+any later version.
+
+gputils is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with gputils; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include <assert.h>
+#include "devices/pic/base/pic.h"
+#include "coff_object.h"
+#include "gpopcode.h"
+
+#define DECODE_ARG0 snprintf(buffer, sizeof_buffer, "%s", instruction->name)
+
+#define DECODE_ARG1(ARG1) snprintf(buffer, sizeof_buffer, "%s\t%#lx", \
+ instruction->name,\
+ ARG1)
+
+#define DECODE_ARG1WF(ARG1, ARG2) snprintf(buffer, sizeof_buffer, "%s\t%#lx, %s", \
+ instruction->name,\
+ ARG1, \
+ (ARG2 ? "f" : "w"))
+
+#define DECODE_ARG2(ARG1, ARG2) snprintf(buffer, sizeof_buffer, "%s\t%#lx, %#lx", \
+ instruction->name,\
+ ARG1, \
+ ARG2)
+
+#define DECODE_ARG3(ARG1, ARG2, ARG3) snprintf(buffer, sizeof_buffer, "%s\t%#lx, %#lx, %#lx", \
+ instruction->name,\
+ ARG1, \
+ ARG2, \
+ ARG3)
+
+bool gp_decode_mnemonics = false;
+bool gp_decode_extended = false;
+
+int Coff::disassemble(long int opcode, long int opcode2,
+ int org,
+ Pic::Architecture architecture,
+ char *buffer,
+ size_t sizeof_buffer)
+{
+ int i;
+ int value;
+ struct insn *instruction = NULL;
+ int num_words = 1;
+
+ switch (architecture.type()) {
+ case Pic::Architecture::P24F:
+ case Pic::Architecture::P24H:
+ case Pic::Architecture::P30F:
+ case Pic::Architecture::P33F:
+ snprintf(buffer, sizeof_buffer, "--");
+ return 0;
+ case Pic::Architecture::P10X:
+ for(i = 0; i < num_op_12c5xx; i++) {
+ if((op_12c5xx[i].mask & opcode) == op_12c5xx[i].opcode) {
+ instruction = &op_12c5xx[i];
+ break;
+ }
+ }
+ break;
+/* case PROC_CLASS_SX:
+ for(i = 0; i < num_op_sx; i++) {
+ if((op_sx[i].mask & opcode) == op_sx[i].opcode) {
+ instruction = &op_sx[i];
+ break;
+ }
+ }
+ break;
+*/
+ case Pic::Architecture::P16X:
+ for(i = 0; i < num_op_16cxx; i++) {
+ if((op_16cxx[i].mask & opcode) == op_16cxx[i].opcode) {
+ instruction = &op_16cxx[i];
+ break;
+ }
+ }
+ break;
+ case Pic::Architecture::P17C:
+ for(i = 0; i < num_op_17cxx; i++) {
+ if((op_17cxx[i].mask & opcode) == op_17cxx[i].opcode) {
+ instruction = &op_17cxx[i];
+ break;
+ }
+ }
+ break;
+ case Pic::Architecture::P18C:
+ case Pic::Architecture::P18F:
+ case Pic::Architecture::P18J:
+ if (gp_decode_mnemonics) {
+ for(i = 0; i < num_op_18cxx_sp; i++) {
+ if((op_18cxx_sp[i].mask & opcode) == op_18cxx_sp[i].opcode) {
+ instruction = &op_18cxx_sp[i];
+ break;
+ }
+ }
+ }
+ if (instruction == NULL) {
+ for(i = 0; i < num_op_18cxx; i++) {
+ if((op_18cxx[i].mask & opcode) == op_18cxx[i].opcode) {
+ instruction = &op_18cxx[i];
+ break;
+ }
+ }
+ }
+ if ((instruction == NULL) && (gp_decode_extended)) {
+ /* might be from the extended instruction set */
+ for(i = 0; i < num_op_18cxx_ext; i++) {
+ if((op_18cxx_ext[i].mask & opcode) == op_18cxx_ext[i].opcode) {
+ instruction = &op_18cxx_ext[i];
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ if (instruction == NULL) {
+ snprintf(buffer, sizeof_buffer, "dw\t%#lx ;unknown opcode", opcode);
+ return num_words;
+ }
+
+ switch (instruction->classType)
+ {
+ case INSN_CLASS_LIT3_BANK:
+ DECODE_ARG1((opcode & 0x7) << 5);
+ break;
+ case INSN_CLASS_LIT3_PAGE:
+ DECODE_ARG1((opcode & 0x7) << 9);
+ break;
+ case INSN_CLASS_LIT1:
+ DECODE_ARG1(opcode & 1);
+ break;
+ case INSN_CLASS_LIT4:
+ DECODE_ARG1(opcode & 0xf);
+ break;
+ case INSN_CLASS_LIT4S:
+ DECODE_ARG1((opcode & 0xf0) >> 4);
+ break;
+ case INSN_CLASS_LIT6:
+ DECODE_ARG1(opcode & 0x3f);
+ break;
+ case INSN_CLASS_LIT8:
+ case INSN_CLASS_LIT8C12:
+ case INSN_CLASS_LIT8C16:
+ DECODE_ARG1(opcode & 0xff);
+ break;
+ case INSN_CLASS_LIT9:
+ DECODE_ARG1(opcode & 0x1ff);
+ break;
+ case INSN_CLASS_LIT11:
+ DECODE_ARG1(opcode & 0x7ff);
+ break;
+ case INSN_CLASS_LIT13:
+ DECODE_ARG1(opcode & 0x1fff);
+ break;
+ case INSN_CLASS_LITFSR:
+ DECODE_ARG2(((opcode >> 6) & 0x3), (opcode & 0x3f));
+ break;
+ case INSN_CLASS_RBRA8:
+ value = opcode & 0xff;
+ /* twos complement number */
+ if (value & 0x80) {
+ value = -((value ^ 0xff) + 1);
+ }
+ DECODE_ARG1((unsigned long)(org + value + 1) * 2);
+ break;
+ case INSN_CLASS_RBRA11:
+ value = opcode & 0x7ff;
+ /* twos complement number */
+ if (value & 0x400) {
+ value = -((value ^ 0x7ff) + 1);
+ }
+ DECODE_ARG1((unsigned long)(org + value + 1) * 2);
+ break;
+ case INSN_CLASS_LIT20:
+ {
+ long int dest;
+
+ num_words = 2;
+ dest = (opcode2 & 0xfff) << 8;
+ dest |= opcode & 0xff;
+ DECODE_ARG1(dest * 2);
+ }
+ break;
+ case INSN_CLASS_CALL20:
+ {
+ long int dest;
+
+ num_words = 2;
+ dest = (opcode2 & 0xfff) << 8;
+ dest |= opcode & 0xff;
+ snprintf(buffer, sizeof_buffer, "%s\t%#lx, %#lx",
+ instruction->name,
+ dest * 2,
+ (opcode >> 8) & 1);
+ }
+ break;
+ case INSN_CLASS_FLIT12:
+ {
+ long int k;
+ long int file;
+
+ num_words = 2;
+ k = opcode2 & 0xff;
+ k |= ((opcode & 0xf) << 8);
+ file = (opcode >> 4) & 0x3;
+ DECODE_ARG2(file, k);
+ }
+ break;
+ case INSN_CLASS_FF:
+ {
+ long int file1;
+ long int file2;
+
+ num_words = 2;
+ file1 = opcode & 0xfff;
+ file2 = opcode2 & 0xfff;
+ DECODE_ARG2(file1, file2);
+ }
+ break;
+ case INSN_CLASS_FP:
+ DECODE_ARG2((opcode & 0xff), ((opcode >> 8) & 0x1f));
+ break;
+ case INSN_CLASS_PF:
+ DECODE_ARG2(((opcode >> 8) & 0x1f), (opcode & 0xff));
+ break;
+ case INSN_CLASS_SF:
+ {
+ long int offset;
+ long int file;
+
+ num_words = 2;
+ offset = opcode & 0x7f;
+ file = opcode2 & 0xfff;
+ DECODE_ARG2(offset, file);
+ }
+ break;
+ case INSN_CLASS_SS:
+ {
+ long int offset1;
+ long int offset2;
+
+ num_words = 2;
+ offset1 = opcode & 0x7f;
+ offset2 = opcode2 & 0x7f;
+ DECODE_ARG2(offset1, offset2);
+ }
+ break;
+ case INSN_CLASS_OPF5:
+ DECODE_ARG1(opcode & 0x1f);
+ break;
+ case INSN_CLASS_OPWF5:
+ DECODE_ARG1WF((opcode & 0x1f), ((opcode >> 5) & 1));
+ break;
+ case INSN_CLASS_B5:
+ DECODE_ARG2((opcode & 0x1f), ((opcode >> 5) & 7));
+ break;
+ case INSN_CLASS_B8:
+ DECODE_ARG2((opcode & 0xff), ((opcode >> 8) & 7));
+ break;
+ case INSN_CLASS_OPF7:
+ DECODE_ARG1(opcode & 0x7f);
+ break;
+ case INSN_CLASS_OPF8:
+ DECODE_ARG1(opcode & 0xff);
+ break;
+ case INSN_CLASS_OPWF7:
+ DECODE_ARG1WF((opcode & 0x7f), ((opcode >> 7) & 1));
+ break;
+ case INSN_CLASS_OPWF8:
+ DECODE_ARG1WF((opcode & 0xff), ((opcode >> 8) & 1));
+ break;
+ case INSN_CLASS_B7:
+ DECODE_ARG2((opcode & 0x7f), ((opcode >> 7) & 7));
+ break;
+ case INSN_CLASS_OPFA8:
+ DECODE_ARG2((opcode & 0xff), ((opcode >> 8) & 1));
+ break;
+ case INSN_CLASS_BA8:
+ DECODE_ARG3((opcode & 0xff), ((opcode >> 9) & 7), ((opcode >> 8) & 1));
+ break;
+ case INSN_CLASS_OPWFA8:
+ DECODE_ARG3((opcode & 0xff), ((opcode >> 9) & 1), ((opcode >> 8) & 1));
+ break;
+ case INSN_CLASS_IMPLICIT:
+ DECODE_ARG0;
+ break;
+ case INSN_CLASS_TBL:
+ {
+ char op[5];
+
+ switch(opcode & 0x3)
+ {
+ case 0:
+ strncpy(op, "*", sizeof(op));
+ break;
+ case 1:
+ strncpy(op, "*+", sizeof(op));
+ break;
+ case 2:
+ strncpy(op, "*-", sizeof(op));
+ break;
+ case 3:
+ strncpy(op, "+*", sizeof(op));
+ break;
+ default:
+ assert(0);
+ }
+
+ snprintf(buffer,
+ sizeof_buffer,
+ "%s\t%s",
+ instruction->name,
+ op);
+ }
+ break;
+ case INSN_CLASS_TBL2:
+ DECODE_ARG2(((opcode >> 9) & 1), (opcode & 0xff));
+ break;
+ case INSN_CLASS_TBL3:
+ DECODE_ARG3(((opcode >> 9) & 1),
+ ((opcode >> 8) & 1),
+ (opcode & 0xff));
+ break;
+ default:
+ assert(0);
+ }
+
+ return num_words;
+}
diff --git a/src/coff/base/gpopcode.cpp b/src/coff/base/gpopcode.cpp
new file mode 100644
index 0000000..87cb3b4
--- /dev/null
+++ b/src/coff/base/gpopcode.cpp
@@ -0,0 +1,348 @@
+/* GNU PIC opcode definitions
+ Copyright (C) 2001, 2002, 2003, 2004, 2005
+ Craig Franklin
+
+This file is part of gputils.
+
+gputils 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, or (at your option)
+any later version.
+
+gputils is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with gputils; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "gpopcode.h"
+
+/* FIXME: use const struct */
+
+/* PIC 12-bit instruction set */
+struct insn op_12c5xx[] = {
+ { "addwf", 0xfc0, 0x1c0, INSN_CLASS_OPWF5 },
+ { "andlw", 0xf00, 0xe00, INSN_CLASS_LIT8 },
+ { "andwf", 0xfc0, 0x140, INSN_CLASS_OPWF5 },
+ { "bcf", 0xf00, 0x400, INSN_CLASS_B5 },
+ { "bsf", 0xf00, 0x500, INSN_CLASS_B5 },
+ { "btfsc", 0xf00, 0x600, INSN_CLASS_B5 },
+ { "btfss", 0xf00, 0x700, INSN_CLASS_B5 },
+ { "call", 0xf00, 0x900, INSN_CLASS_LIT8C12 },
+ { "clrf", 0xfe0, 0x060, INSN_CLASS_OPF5 },
+ { "clrw", 0xfff, 0x040, INSN_CLASS_IMPLICIT },
+ { "clrwdt", 0xfff, 0x004, INSN_CLASS_IMPLICIT },
+ { "comf", 0xfc0, 0x240, INSN_CLASS_OPWF5 },
+ { "decf", 0xfc0, 0x0c0, INSN_CLASS_OPWF5 },
+ { "decfsz", 0xfc0, 0x2c0, INSN_CLASS_OPWF5 },
+ { "goto", 0xe00, 0xa00, INSN_CLASS_LIT9 },
+ { "incf", 0xfc0, 0x280, INSN_CLASS_OPWF5 },
+ { "incfsz", 0xfc0, 0x3c0, INSN_CLASS_OPWF5 },
+ { "iorlw", 0xf00, 0xd00, INSN_CLASS_LIT8 },
+ { "iorwf", 0xfc0, 0x100, INSN_CLASS_OPWF5 },
+ { "movf", 0xfc0, 0x200, INSN_CLASS_OPWF5 },
+ { "movlw", 0xf00, 0xc00, INSN_CLASS_LIT8 },
+ { "movwf", 0xfe0, 0x020, INSN_CLASS_OPF5 },
+ { "nop", 0xfff, 0x000, INSN_CLASS_IMPLICIT },
+ { "option", 0xfff, 0x002, INSN_CLASS_IMPLICIT },
+ { "retlw", 0xf00, 0x800, INSN_CLASS_LIT8 },
+ { "return", 0xfff, 0x800, INSN_CLASS_IMPLICIT }, /* FIXME: special mnemonic */
+ { "rlf", 0xfc0, 0x340, INSN_CLASS_OPWF5 },
+ { "rrf", 0xfc0, 0x300, INSN_CLASS_OPWF5 },
+ { "sleep", 0xfff, 0x003, INSN_CLASS_IMPLICIT },
+ { "subwf", 0xfc0, 0x080, INSN_CLASS_OPWF5 },
+ { "swapf", 0xfc0, 0x380, INSN_CLASS_OPWF5 },
+ { "tris", 0xff8, 0x000, INSN_CLASS_OPF5 },
+ { "xorlw", 0xf00, 0xf00, INSN_CLASS_LIT8 },
+ { "xorwf", 0xfc0, 0x180, INSN_CLASS_OPWF5 }
+};
+
+const int num_op_12c5xx = TABLE_SIZE(op_12c5xx);
+
+/* Scenix SX has a superset of the PIC 12-bit instruction set */
+/*
+ * It would be nice if there was a more elegant way to do this,
+ * either by adding a flags field to struct insn, or by allowing a
+ * processor to have more than one associated table.
+ */
+struct insn op_sx[] = {
+ { "addwf", 0xfc0, 0x1c0, INSN_CLASS_OPWF5 },
+ { "andlw", 0xf00, 0xe00, INSN_CLASS_LIT8 },
+ { "andwf", 0xfc0, 0x140, INSN_CLASS_OPWF5 },
+ { "bank", 0xff8, 0x018, INSN_CLASS_LIT3_BANK }, /* SX only */
+ { "bcf", 0xf00, 0x400, INSN_CLASS_B5 },
+ { "bsf", 0xf00, 0x500, INSN_CLASS_B5 },
+ { "btfsc", 0xf00, 0x600, INSN_CLASS_B5 },
+ { "btfss", 0xf00, 0x700, INSN_CLASS_B5 },
+ { "call", 0xf00, 0x900, INSN_CLASS_LIT8C12 },
+ { "clrf", 0xfe0, 0x060, INSN_CLASS_OPF5 },
+ { "clrw", 0xfff, 0x040, INSN_CLASS_IMPLICIT },
+ { "clrwdt", 0xfff, 0x004, INSN_CLASS_IMPLICIT },
+ { "comf", 0xfc0, 0x240, INSN_CLASS_OPWF5 },
+ { "decf", 0xfc0, 0x0c0, INSN_CLASS_OPWF5 },
+ { "decfsz", 0xfc0, 0x2c0, INSN_CLASS_OPWF5 },
+ { "goto", 0xe00, 0xa00, INSN_CLASS_LIT9 },
+ { "incf", 0xfc0, 0x280, INSN_CLASS_OPWF5 },
+ { "incfsz", 0xfc0, 0x3c0, INSN_CLASS_OPWF5 },
+ { "iorlw", 0xf00, 0xd00, INSN_CLASS_LIT8 },
+ { "iorwf", 0xfc0, 0x100, INSN_CLASS_OPWF5 },
+ { "iread", 0xfff, 0x041, INSN_CLASS_IMPLICIT }, /* SX only */
+ { "mode", 0xff0, 0x050, INSN_CLASS_LIT4 }, /* SX only */
+ { "movf", 0xfc0, 0x200, INSN_CLASS_OPWF5 },
+ { "movlw", 0xf00, 0xc00, INSN_CLASS_LIT8 },
+ { "movmw", 0xfff, 0x042, INSN_CLASS_IMPLICIT }, /* SX only */
+ { "movwf", 0xfe0, 0x020, INSN_CLASS_OPF5 },
+ { "movwm", 0xfff, 0x043, INSN_CLASS_IMPLICIT }, /* SX only */
+ { "nop", 0xfff, 0x000, INSN_CLASS_IMPLICIT },
+ { "option", 0xfff, 0x002, INSN_CLASS_IMPLICIT },
+ { "page", 0xff8, 0x010, INSN_CLASS_LIT3_PAGE }, /* SX only */
+ { "reti", 0xfff, 0x00e, INSN_CLASS_IMPLICIT }, /* SX only */
+ { "retiw", 0xfff, 0x00f, INSN_CLASS_IMPLICIT }, /* SX only */
+ { "retlw", 0xf00, 0x800, INSN_CLASS_LIT8 },
+ { "retp", 0xfff, 0x00d, INSN_CLASS_IMPLICIT }, /* SX only */
+ { "return", 0xfff, 0x00c, INSN_CLASS_IMPLICIT }, /* SX only */
+ { "rlf", 0xfc0, 0x340, INSN_CLASS_OPWF5 },
+ { "rrf", 0xfc0, 0x300, INSN_CLASS_OPWF5 },
+ { "sleep", 0xfff, 0x003, INSN_CLASS_IMPLICIT },
+ { "subwf", 0xfc0, 0x080, INSN_CLASS_OPWF5 },
+ { "swapf", 0xfc0, 0x380, INSN_CLASS_OPWF5 },
+ { "tris", 0xff8, 0x000, INSN_CLASS_OPF5 },
+ { "xorlw", 0xf00, 0xf00, INSN_CLASS_LIT8 },
+ { "xorwf", 0xfc0, 0x180, INSN_CLASS_OPWF5 }
+};
+
+const int num_op_sx = TABLE_SIZE(op_sx);
+
+/* PIC 14-bit instruction set */
+struct insn op_16cxx[] = {
+ { "addlw", 0x3e00, 0x3e00, INSN_CLASS_LIT8 },
+ { "addwf", 0x3f00, 0x0700, INSN_CLASS_OPWF7 },
+ { "andlw", 0x3f00, 0x3900, INSN_CLASS_LIT8 },
+ { "andwf", 0x3f00, 0x0500, INSN_CLASS_OPWF7 },
+ { "bcf", 0x3c00, 0x1000, INSN_CLASS_B7 },
+ { "bsf", 0x3c00, 0x1400, INSN_CLASS_B7 },
+ { "btfsc", 0x3c00, 0x1800, INSN_CLASS_B7 },
+ { "btfss", 0x3c00, 0x1c00, INSN_CLASS_B7 },
+ { "call", 0x3800, 0x2000, INSN_CLASS_LIT11 },
+ { "clrf", 0x3f80, 0x0180, INSN_CLASS_OPF7 },
+ { "clrw", 0x3fff, 0x0103, INSN_CLASS_IMPLICIT },
+ { "clrwdt", 0x3fff, 0x0064, INSN_CLASS_IMPLICIT },
+ { "comf", 0x3f00, 0x0900, INSN_CLASS_OPWF7 },
+ { "decf", 0x3f00, 0x0300, INSN_CLASS_OPWF7 },
+ { "decfsz", 0x3f00, 0x0b00, INSN_CLASS_OPWF7 },
+ { "goto", 0x3800, 0x2800, INSN_CLASS_LIT11 },
+ { "incf", 0x3f00, 0x0a00, INSN_CLASS_OPWF7 },
+ { "incfsz", 0x3f00, 0x0f00, INSN_CLASS_OPWF7 },
+ { "iorlw", 0x3f00, 0x3800, INSN_CLASS_LIT8 },
+ { "iorwf", 0x3f00, 0x0400, INSN_CLASS_OPWF7 },
+ { "movf", 0x3f00, 0x0800, INSN_CLASS_OPWF7 },
+ { "movlw", 0x3c00, 0x3000, INSN_CLASS_LIT8 },
+ { "movwf", 0x3f80, 0x0080, INSN_CLASS_OPF7 },
+ { "nop", 0x3f9f, 0x0000, INSN_CLASS_IMPLICIT },
+ { "option", 0x3fff, 0x0062, INSN_CLASS_IMPLICIT },
+ { "retfie", 0x3fff, 0x0009, INSN_CLASS_IMPLICIT },
+ { "retlw", 0x3c00, 0x3400, INSN_CLASS_LIT8 },
+ { "return", 0x3fff, 0x0008, INSN_CLASS_IMPLICIT },
+ { "rlf", 0x3f00, 0x0d00, INSN_CLASS_OPWF7 },
+ { "rrf", 0x3f00, 0x0c00, INSN_CLASS_OPWF7 },
+ { "sleep", 0x3fff, 0x0063, INSN_CLASS_IMPLICIT },
+ { "sublw", 0x3e00, 0x3c00, INSN_CLASS_LIT8 },
+ { "subwf", 0x3f00, 0x0200, INSN_CLASS_OPWF7 },
+ { "swapf", 0x3f00, 0x0e00, INSN_CLASS_OPWF7 },
+ { "tris", 0x3ff8, 0x0060, INSN_CLASS_OPF7 },
+ { "xorlw", 0x3f00, 0x3a00, INSN_CLASS_LIT8 },
+ { "xorwf", 0x3f00, 0x0600, INSN_CLASS_OPWF7 }
+};
+
+const int num_op_16cxx = TABLE_SIZE(op_16cxx);
+
+/* PIC 16-bit instruction set */
+struct insn op_17cxx[] = {
+ { "addlw", 0xff00, 0xb100, INSN_CLASS_LIT8 },
+ { "addwf", 0xfe00, 0x0e00, INSN_CLASS_OPWF8 },
+ { "addwfc", 0xfe00, 0x1000, INSN_CLASS_OPWF8 },
+ { "andlw", 0xff00, 0xb500, INSN_CLASS_LIT8 },
+ { "andwf", 0xfe00, 0x0a00, INSN_CLASS_OPWF8 },
+ { "bcf", 0xf800, 0x8800, INSN_CLASS_B8 },
+ { "bsf", 0xf800, 0x8000, INSN_CLASS_B8 },
+ { "btfsc", 0xf800, 0x9800, INSN_CLASS_B8 },
+ { "btfss", 0xf800, 0x9000, INSN_CLASS_B8 },
+ { "btg", 0xf800, 0x3800, INSN_CLASS_B8 },
+ { "call", 0xe000, 0xe000, INSN_CLASS_LIT13 },
+ { "clrf", 0xfe00, 0x2800, INSN_CLASS_OPWF8 },
+ { "clrwdt", 0xffff, 0x0004, INSN_CLASS_IMPLICIT },
+ { "comf", 0xfe00, 0x1200, INSN_CLASS_OPWF8 },
+ { "cpfseq", 0xff00, 0x3100, INSN_CLASS_OPF8 },
+ { "cpfsgt", 0xff00, 0x3200, INSN_CLASS_OPF8 },
+ { "cpfslt", 0xff00, 0x3000, INSN_CLASS_OPF8 },
+ { "daw", 0xfe00, 0x2e00, INSN_CLASS_OPWF8 },
+ { "decf", 0xfe00, 0x0600, INSN_CLASS_OPWF8 },
+ { "decfsz", 0xfe00, 0x1600, INSN_CLASS_OPWF8 },
+ { "dcfsnz", 0xfe00, 0x2600, INSN_CLASS_OPWF8 },
+ { "goto", 0xe000, 0xc000, INSN_CLASS_LIT13 },
+ { "incf", 0xfe00, 0x1400, INSN_CLASS_OPWF8 },
+ { "incfsz", 0xfe00, 0x1e00, INSN_CLASS_OPWF8 },
+ { "infsnz", 0xfe00, 0x2400, INSN_CLASS_OPWF8 },
+ { "iorlw", 0xff00, 0xb300, INSN_CLASS_LIT8 },
+ { "iorwf", 0xfe00, 0x0800, INSN_CLASS_OPWF8 },
+ { "lcall", 0xff00, 0xb700, INSN_CLASS_LIT8C16 },
+ { "movfp", 0xe000, 0x6000, INSN_CLASS_FP },
+ { "movpf", 0xe000, 0x4000, INSN_CLASS_PF },
+ { "movlb", 0xff00, 0xb800, INSN_CLASS_LIT8 },
+ { "movlr", 0xfe00, 0xba00, INSN_CLASS_LIT4S },
+ { "movlw", 0xff00, 0xb000, INSN_CLASS_LIT8 },
+ { "movwf", 0xff00, 0x0100, INSN_CLASS_OPF8 },
+ { "mullw", 0xff00, 0xbc00, INSN_CLASS_LIT8 },
+ { "mulwf", 0xff00, 0x3400, INSN_CLASS_OPF8 },
+ { "negw", 0xfe00, 0x2c00, INSN_CLASS_OPWF8 },
+ { "nop", 0xffff, 0x0000, INSN_CLASS_IMPLICIT },
+ { "retfie", 0xffff, 0x0005, INSN_CLASS_IMPLICIT },
+ { "retlw", 0xff00, 0xb600, INSN_CLASS_LIT8 },
+ { "return", 0xffff, 0x0002, INSN_CLASS_IMPLICIT },
+ { "rlcf", 0xfe00, 0x1a00, INSN_CLASS_OPWF8 },
+ { "rlncf", 0xfe00, 0x2200, INSN_CLASS_OPWF8 },
+ { "rrcf", 0xfe00, 0x1800, INSN_CLASS_OPWF8 },
+ { "rrncf", 0xfe00, 0x2000, INSN_CLASS_OPWF8 },
+ { "setf", 0xfe00, 0x2a00, INSN_CLASS_OPWF8 },
+ { "sleep", 0xffff, 0x0003, INSN_CLASS_IMPLICIT },
+ { "sublw", 0xff00, 0xb200, INSN_CLASS_LIT8 },
+ { "subwf", 0xfe00, 0x0400, INSN_CLASS_OPWF8 },
+ { "subwfb", 0xfe00, 0x0200, INSN_CLASS_OPWF8 },
+ { "swapf", 0xfe00, 0x1c00, INSN_CLASS_OPWF8 },
+ { "tablrd", 0xfc00, 0xa800, INSN_CLASS_TBL3 },
+ { "tablwt", 0xfc00, 0xac00, INSN_CLASS_TBL3 },
+ { "tlrd", 0xfc00, 0xa000, INSN_CLASS_TBL2 },
+ { "tlwt", 0xfc00, 0xa400, INSN_CLASS_TBL2 },
+ { "tstfsz", 0xff00, 0x3300, INSN_CLASS_OPF8 },
+ { "xorlw", 0xff00, 0xb400, INSN_CLASS_LIT8 },
+ { "xorwf", 0xfe00, 0x0c00, INSN_CLASS_OPWF8 }
+};
+
+const int num_op_17cxx = TABLE_SIZE(op_17cxx);
+
+struct insn op_18cxx[] = {
+ { "addlw", 0xff00, 0x0f00, INSN_CLASS_LIT8 },
+ { "addwf", 0xfc00, 0x2400, INSN_CLASS_OPWFA8 },
+ { "addwfc", 0xfc00, 0x2000, INSN_CLASS_OPWFA8 },
+ { "andlw", 0xff00, 0x0b00, INSN_CLASS_LIT8 },
+ { "andwf", 0xfc00, 0x1400, INSN_CLASS_OPWFA8 },
+ { "bc", 0xff00, 0xe200, INSN_CLASS_RBRA8 },
+ { "bcf", 0xf000, 0x9000, INSN_CLASS_BA8 },
+ { "bn", 0xff00, 0xe600, INSN_CLASS_RBRA8 },
+ { "bnc", 0xff00, 0xe300, INSN_CLASS_RBRA8 },
+ { "bnn", 0xff00, 0xe700, INSN_CLASS_RBRA8 },
+ { "bnov", 0xff00, 0xe500, INSN_CLASS_RBRA8 },
+ { "bnz", 0xff00, 0xe100, INSN_CLASS_RBRA8 },
+ { "bov", 0xff00, 0xe400, INSN_CLASS_RBRA8 },
+ { "bra", 0xf800, 0xd000, INSN_CLASS_RBRA11 },
+ { "bsf", 0xf000, 0x8000, INSN_CLASS_BA8 },
+ { "btfsc", 0xf000, 0xb000, INSN_CLASS_BA8 },
+ { "btfss", 0xf000, 0xa000, INSN_CLASS_BA8 },
+ { "btg", 0xf000, 0x7000, INSN_CLASS_BA8 },
+ { "bz", 0xff00, 0xe000, INSN_CLASS_RBRA8 },
+ { "call", 0xfe00, 0xec00, INSN_CLASS_CALL20 },
+ { "clrf", 0xfe00, 0x6a00, INSN_CLASS_OPFA8 },
+ { "clrwdt", 0xffff, 0x0004, INSN_CLASS_IMPLICIT },
+ { "comf", 0xfc00, 0x1c00, INSN_CLASS_OPWFA8 },
+ { "cpfseq", 0xfe00, 0x6200, INSN_CLASS_OPFA8 },
+ { "cpfsgt", 0xfe00, 0x6400, INSN_CLASS_OPFA8 },
+ { "cpfslt", 0xfe00, 0x6000, INSN_CLASS_OPFA8 },
+ { "daw", 0xffff, 0x0007, INSN_CLASS_IMPLICIT },
+ { "decf", 0xfc00, 0x0400, INSN_CLASS_OPWFA8 },
+ { "decfsz", 0xfc00, 0x2c00, INSN_CLASS_OPWFA8 },
+ { "dcfsnz", 0xfc00, 0x4c00, INSN_CLASS_OPWFA8 },
+ { "goto", 0xff00, 0xef00, INSN_CLASS_LIT20 },
+ { "incf", 0xfc00, 0x2800, INSN_CLASS_OPWFA8 },
+ { "incfsz", 0xfc00, 0x3c00, INSN_CLASS_OPWFA8 },
+ { "infsnz", 0xfc00, 0x4800, INSN_CLASS_OPWFA8 },
+ { "iorlw", 0xff00, 0x0900, INSN_CLASS_LIT8 },
+ { "iorwf", 0xfc00, 0x1000, INSN_CLASS_OPWFA8 },
+ { "lfsr", 0xffc0, 0xee00, INSN_CLASS_FLIT12 },
+ { "movf", 0xfc00, 0x5000, INSN_CLASS_OPWFA8 },
+ { "movff", 0xf000, 0xc000, INSN_CLASS_FF },
+ { "movlb", 0xff00, 0x0100, INSN_CLASS_LIT8 },
+ { "movlw", 0xff00, 0x0e00, INSN_CLASS_LIT8 },
+ { "movwf", 0xfe00, 0x6e00, INSN_CLASS_OPFA8 },
+ { "mullw", 0xff00, 0x0d00, INSN_CLASS_LIT8 },
+ { "mulwf", 0xfe00, 0x0200, INSN_CLASS_OPFA8 },
+ { "negf", 0xfe00, 0x6c00, INSN_CLASS_OPFA8 },
+ { "nop", 0xffff, 0x0000, INSN_CLASS_IMPLICIT },
+ { "pop", 0xffff, 0x0006, INSN_CLASS_IMPLICIT },
+ { "push", 0xffff, 0x0005, INSN_CLASS_IMPLICIT },
+ { "rcall", 0xf800, 0xd800, INSN_CLASS_RBRA11 },
+ { "reset", 0xffff, 0x00ff, INSN_CLASS_IMPLICIT },
+ { "retfie", 0xfffe, 0x0010, INSN_CLASS_LIT1 },
+ { "retlw", 0xff00, 0x0c00, INSN_CLASS_LIT8 },
+ { "return", 0xfffe, 0x0012, INSN_CLASS_LIT1 },
+ { "rlcf", 0xfc00, 0x3400, INSN_CLASS_OPWFA8 },
+ { "rlncf", 0xfc00, 0x4400, INSN_CLASS_OPWFA8 },
+ { "rrcf", 0xfc00, 0x3000, INSN_CLASS_OPWFA8 },
+ { "rrncf", 0xfc00, 0x4000, INSN_CLASS_OPWFA8 },
+ { "setf", 0xfe00, 0x6800, INSN_CLASS_OPFA8 },
+ { "sleep", 0xffff, 0x0003, INSN_CLASS_IMPLICIT },
+ { "subfwb", 0xfc00, 0x5400, INSN_CLASS_OPWFA8 },
+ { "sublw", 0xff00, 0x0800, INSN_CLASS_LIT8 },
+ { "subwf", 0xfc00, 0x5c00, INSN_CLASS_OPWFA8 },
+ { "subwfb", 0xfc00, 0x5800, INSN_CLASS_OPWFA8 },
+ { "swapf", 0xfc00, 0x3800, INSN_CLASS_OPWFA8 },
+ { "tblrd", 0xfffc, 0x0008, INSN_CLASS_TBL },
+ { "tblwt", 0xfffc, 0x000c, INSN_CLASS_TBL },
+ { "tstfsz", 0xfe00, 0x6600, INSN_CLASS_OPFA8 },
+ { "xorlw", 0xff00, 0x0a00, INSN_CLASS_LIT8 },
+ { "xorwf", 0xfc00, 0x1800, INSN_CLASS_OPWFA8 }
+};
+
+const int num_op_18cxx = TABLE_SIZE(op_18cxx);
+
+/* PIC 16-bit "Special" instruction set */
+struct insn op_18cxx_sp[] = {
+ { "clrc", 0xffff, 0x90d8, INSN_CLASS_IMPLICIT },
+ { "clrdc", 0xffff, 0x92d8, INSN_CLASS_IMPLICIT },
+ { "clrn", 0xffff, 0x98d8, INSN_CLASS_IMPLICIT },
+ { "clrov", 0xffff, 0x96d8, INSN_CLASS_IMPLICIT },
+ { "clrw", 0xffff, 0x6ae8, INSN_CLASS_IMPLICIT },
+ { "clrz", 0xffff, 0x94d8, INSN_CLASS_IMPLICIT },
+ { "setc", 0xffff, 0x80d8, INSN_CLASS_IMPLICIT },
+ { "setdc", 0xffff, 0x82d8, INSN_CLASS_IMPLICIT },
+ { "setn", 0xffff, 0x88d8, INSN_CLASS_IMPLICIT },
+ { "setov", 0xffff, 0x86d8, INSN_CLASS_IMPLICIT },
+ { "setz", 0xffff, 0x84d8, INSN_CLASS_IMPLICIT },
+ { "skpc", 0xffff, 0xa0d8, INSN_CLASS_IMPLICIT },
+ { "skpdc", 0xffff, 0xa2d8, INSN_CLASS_IMPLICIT },
+ { "skpn", 0xffff, 0xa8d8, INSN_CLASS_IMPLICIT },
+ { "skpov", 0xffff, 0xa6d8, INSN_CLASS_IMPLICIT },
+ { "skpz", 0xffff, 0xa4d8, INSN_CLASS_IMPLICIT },
+ { "skpnc", 0xffff, 0xb0d8, INSN_CLASS_IMPLICIT },
+ { "skpndc", 0xffff, 0xb2d8, INSN_CLASS_IMPLICIT },
+ { "skpnn", 0xffff, 0xb8d8, INSN_CLASS_IMPLICIT },
+ { "skpnov", 0xffff, 0xb6d8, INSN_CLASS_IMPLICIT },
+ { "skpnz", 0xffff, 0xb4d8, INSN_CLASS_IMPLICIT },
+ { "tgc", 0xffff, 0x70d8, INSN_CLASS_IMPLICIT },
+ { "tgdc", 0xffff, 0x72d8, INSN_CLASS_IMPLICIT },
+ { "tgn", 0xffff, 0x78d8, INSN_CLASS_IMPLICIT },
+ { "tgov", 0xffff, 0x76d8, INSN_CLASS_IMPLICIT },
+ { "tgz", 0xffff, 0x74d8, INSN_CLASS_IMPLICIT }
+
+};
+
+const int num_op_18cxx_sp = TABLE_SIZE(op_18cxx_sp);
+
+/* PIC 16-bit Extended instruction set */
+struct insn op_18cxx_ext[] = {
+ { "addfsr", 0xff00, 0xe800, INSN_CLASS_LITFSR },
+ { "addulnk", 0xffc0, 0xe8c0, INSN_CLASS_LIT6 },
+ { "callw", 0xffff, 0x0014, INSN_CLASS_IMPLICIT },
+ { "movsf", 0xff80, 0xeb00, INSN_CLASS_SF },
+ { "movss", 0xff80, 0xeb80, INSN_CLASS_SS },
+ { "pushl", 0xff00, 0xea00, INSN_CLASS_LIT8 },
+ { "subfsr", 0xff00, 0xe900, INSN_CLASS_LITFSR },
+ { "subulnk", 0xffc0, 0xe9c0, INSN_CLASS_LIT6 }
+
+};
+
+const int num_op_18cxx_ext = TABLE_SIZE(op_18cxx_ext);
+
diff --git a/src/coff/base/gpopcode.h b/src/coff/base/gpopcode.h
new file mode 100644
index 0000000..aed25f9
--- /dev/null
+++ b/src/coff/base/gpopcode.h
@@ -0,0 +1,107 @@
+/* GNU PIC opcode definitions
+ Copyright (C) 2001, 2002, 2003, 2004, 2005
+ Craig Franklin
+
+This file is part of gputils.
+
+gputils 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, or (at your option)
+any later version.
+
+gputils is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with gputils; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#ifndef __GPOPCODE_H__
+#define __GPOPCODE_H__
+
+enum insn_class {
+ INSN_CLASS_LIT1, /* bit 0 contains a 1 bit literal */
+ INSN_CLASS_LIT4S, /* Bits 7:4 contain a 4 bit literal, bits 3:0 are unused */
+ INSN_CLASS_LIT6, /* bits 5:0 contain an 6 bit literal */
+ INSN_CLASS_LIT8, /* bits 7:0 contain an 8 bit literal */
+ INSN_CLASS_LIT8C12, /* bits 7:0 contain an 8 bit literal, 12 bit CALL */
+ INSN_CLASS_LIT8C16, /* bits 7:0 contain an 8 bit literal, 16 bit CALL */
+ INSN_CLASS_LIT9, /* bits 8:0 contain a 9 bit literal */
+ INSN_CLASS_LIT11, /* bits 10:0 contain an 11 bit literal */
+ INSN_CLASS_LIT13, /* bits 12:0 contain an 11 bit literal */
+ INSN_CLASS_LITFSR, /* bits 5:0 contain an 6 bit literal for fsr 7:6 */
+ INSN_CLASS_IMPLICIT, /* instruction has no variable bits at all */
+ INSN_CLASS_OPF5, /* bits 4:0 contain a register address */
+ INSN_CLASS_OPWF5, /* as above, but bit 5 has a destination flag */
+ INSN_CLASS_B5, /* as for OPF5, but bits 7:5 have bit number */
+ INSN_CLASS_OPF7, /* bits 6:0 contain a register address */
+ INSN_CLASS_OPWF7, /* as above, but bit 7 has destination flag */
+ INSN_CLASS_B7, /* as for OPF7, but bits 9:7 have bit number */
+
+ INSN_CLASS_OPF8, /* bits 7:0 contain a register address */
+ INSN_CLASS_OPFA8, /* bits 7:0 contain a register address & bit has access flag */
+ INSN_CLASS_OPWF8, /* as above, but bit 8 has dest flag */
+ INSN_CLASS_OPWFA8, /* as above, but bit 9 has dest flag & bit 8 has access flag */
+ INSN_CLASS_B8, /* like OPF7, but bits 9:11 have bit number */
+ INSN_CLASS_BA8, /* like OPF7, but bits 9:11 have bit number & bit 8 has access flag */
+ INSN_CLASS_LIT20, /* 20bit lit, bits 7:0 in first word bits 19:8 in second */
+ INSN_CLASS_CALL20, /* Like LIT20, but bit 8 has fast push flag */
+ INSN_CLASS_RBRA8, /* Bits 7:0 contain a relative branch address */
+ INSN_CLASS_RBRA11, /* Bits 10:0 contain a relative branch address */
+ INSN_CLASS_FLIT12, /* LFSR, 12bit lit loaded into 1 of 4 FSRs */
+ INSN_CLASS_FF, /* two 12bit file addresses */
+ INSN_CLASS_FP, /* Bits 7:0 contain a register address, bits 12:8 contains a peripheral address */
+ INSN_CLASS_PF, /* Bits 7:0 contain a register address, bits 12:8 contains a peripheral address */
+
+ INSN_CLASS_SF, /* 7 bit offset added to FSR2, fetched memory placed at 12 bit address */
+ INSN_CLASS_SS, /* two 7 bit offsets, memory moved using FSR2 */
+
+ INSN_CLASS_TBL, /* a table read or write instruction */
+ INSN_CLASS_TBL2, /* a table read or write instruction.
+ Bits 7:0 contains a register address; Bit 8 is unused;
+ Bit 9, table byte select. (0:lower ; 1:upper) */
+ INSN_CLASS_TBL3, /* a table read or write instruction.
+ Bits 7:0 contains a register address;
+ Bit 8, 1 if increment pointer, 0 otherwise;
+ Bit 9, table byte select. (0:lower ; 1:upper) */
+ INSN_CLASS_FUNC, /* instruction is an assembler function */
+ INSN_CLASS_LIT3_BANK, /* SX: bits 3:0 contain a 3 bit literal, shifted 5 bits */
+ INSN_CLASS_LIT3_PAGE, /* SX: bits 3:0 contain a 3 bit literal, shifted 9 bits */
+ INSN_CLASS_LIT4 /* SX: bits 3:0 contain a 4 bit literal */
+};
+
+struct insn {
+ const char *name;
+ long int mask;
+ long int opcode;
+ enum insn_class classType;
+ //int attribs;
+};
+
+#define TABLE_SIZE(X) (sizeof(X) / sizeof(X[0]))
+
+extern struct insn op_12c5xx[];
+extern const int num_op_12c5xx;
+
+extern struct insn op_sx[];
+extern const int num_op_sx;
+
+extern struct insn op_16cxx[];
+extern const int num_op_16cxx;
+
+extern struct insn op_17cxx[];
+extern const int num_op_17cxx;
+
+extern struct insn op_18cxx[];
+extern const int num_op_18cxx;
+
+extern struct insn op_18cxx_sp[];
+extern const int num_op_18cxx_sp;
+
+extern struct insn op_18cxx_ext[];
+extern const int num_op_18cxx_ext;
+
+#endif
diff --git a/src/coff/base/text_coff.cpp b/src/coff/base/text_coff.cpp
new file mode 100644
index 0000000..0d0862e
--- /dev/null
+++ b/src/coff/base/text_coff.cpp
@@ -0,0 +1,262 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 "text_coff.h"
+
+#include "common/global/pfile.h"
+
+namespace Coff
+{
+class CodeData {
+public:
+ QString address, opcode, disasm1, disasm2;
+};
+class LineData {
+public:
+ QValueVector<CodeData> codes;
+ QString lineNumber, lineText;
+};
+class FileData {
+public:
+ PURL::Url url;
+ bool read;
+ QValueVector<LineData> lines;
+};
+}
+
+Coff::TextObject::TextObject(const Device::Data *device, const PURL::Url &url)
+ : Object(device, url), _initialized(true)
+{}
+
+bool Coff::TextObject::parse(Log::Base &log)
+{
+ bool ok = Object::parse(log);
+ _initialized = !ok;
+ return ok;
+}
+
+PURL::Url Coff::TextObject::urlForFilename(const QString &filename) const
+{
+ PURL::Url rurl = PURL::Url::fromPathOrUrl(filename);
+ return rurl.toAbsolute(url().directory());
+}
+
+const Coff::Section *Coff::TextObject::section(const CodeLine &cline) const
+{
+ if ( cline.section().instructions().contains(cline.address()) ) return &cline.section();
+ // possible for coff generated by picc...
+ for (uint i=0; i<uint(_sections.count()); i++) {
+ if ( _sections[i]->type()!=SectionType::Code ) continue;
+ if ( _sections[i]->instructions().contains(cline.address()) ) return _sections[i];
+ }
+ return 0;
+}
+
+void Coff::TextObject::init() const
+{
+ if (_initialized) return;
+ _initialized = true;
+
+ // open and read files
+ QMap<QString, FileData> fd;
+ for (uint i=0; i<uint(_sections.count()); i++) {
+ if ( _sections[i]->type()!=SectionType::Code ) continue;
+ for (uint k=0; k<uint(_sections[i]->lines().count()); k++) {
+ QString filename = _sections[i]->lines()[k]->filename();
+ if ( filename.isEmpty() || fd.contains(filename) ) continue;
+ _filenames.append(filename);
+ FileData fdata;
+ fdata.url = urlForFilename(filename);
+ Log::StringView sview;
+ PURL::File file(fdata.url, sview);
+ fdata.read = file.openForRead();
+ if (fdata.read) {
+ QStringList lines = file.readLines();
+ fdata.lines.resize(lines.count());
+ for (uint i=0; i<uint(lines.count()); i++)
+ fdata.lines[i].lineText = lines[i];
+ } else fdata.lines.resize(nbLines(filename));
+ fd[filename] = fdata;
+ }
+ }
+
+ // create strings (for later justification)
+ const uint addressWidth = _device->nbCharsAddress();
+ uint opcodeWidth = 0, disasm1Width = 0, disasm2Width = 0, lineNumberWidth = 0, lineTextWidth = 0;
+ QMap<QString, FileData>::iterator it;
+ for (it=fd.begin(); it!=fd.end(); ++it) {
+ for (uint i=0; i<uint(it.data().lines.count()); i++) {
+ LineData &ldata = it.data().lines[i];
+ QValueVector<const CodeLine *> lines = findCodeLines(it.key(), i);
+ ldata.codes.resize(lines.count());
+ for (uint k=0; k<uint(lines.count()); k++) {
+ Address address = lines[k]->address();
+ ldata.codes[k].address = toHex(address, addressWidth).upper();
+ const Section *sec = section(*lines[k]);
+ if (sec) {
+ ldata.codes[k].opcode = "0x" + sec->instructions()[address].opcode.upper();
+ //qDebug("%s: %s", ldata.codes[k].address.latin1(), ldata.codes[k].opcode.latin1());
+ opcodeWidth = qMax(opcodeWidth, uint(ldata.codes[k].opcode.length()));
+ QString s = sec->instructions()[address].disasm;
+ int j = s.find('\t');
+ if ( j!=-1 ) {
+ ldata.codes[k].disasm2 = s.mid(j+1);
+ disasm2Width = qMax(disasm2Width, uint(ldata.codes[k].disasm2.length()));
+ }
+ ldata.codes[k].disasm1 = (j==-1 ? s : s.mid(0, j));
+ disasm1Width = qMax(disasm1Width, uint(ldata.codes[k].disasm1.length()));
+ }
+ }
+ ldata.lineNumber = QString::number(i+1);
+ lineNumberWidth = qMax(lineNumberWidth, uint(ldata.lineNumber.length()));
+ lineTextWidth = qMax(lineTextWidth, uint(ldata.lineText.length()));
+ }
+ }
+ uint asmWidth = addressWidth + 4 + opcodeWidth + 4 + disasm1Width + 2 + disasm2Width;
+ uint totalWidth = asmWidth + 4 + lineNumberWidth + 2 + lineTextWidth;
+
+ // create text
+ for (it = fd.begin(); it!=fd.end(); ++it) {
+ QString s = QString("--- ") + it.data().url.pretty() + " ";
+ _list += s.leftJustify(totalWidth, '-');
+ if ( !it.data().read ) {
+ s = QString("--- ") + i18n("File could not be read") + " ";
+ _list += s.leftJustify(totalWidth, '-');
+ }
+ for (uint i=0; i<uint(it.data().lines.count()); i++) {
+ const LineData &ldata = it.data().lines[i];
+ QString cline = repeat(" ", 4) + ldata.lineNumber.leftJustify(lineNumberWidth) + ": " + ldata.lineText;
+ if ( ldata.codes.count()==0 ) _list += stripEndingWhiteSpaces(repeat(" ", asmWidth) + cline);
+ else for (uint k=0; k<uint(ldata.codes.count()); k++) {
+ if ( ldata.codes[k].opcode.isEmpty() ) continue;
+ QString line;
+ line += ldata.codes[k].address + repeat(" ", 4);
+ line += ldata.codes[k].opcode.leftJustify(opcodeWidth) + repeat(" ", 4);
+ line += ldata.codes[k].disasm1.leftJustify(disasm1Width) + repeat(" ", 2);
+ line += ldata.codes[k].disasm2.leftJustify(disasm2Width);
+ _lines[fromHex(ldata.codes[k].address, 0)] = _list.count()+1;
+ if ( k==0 ) line += cline;
+ _list += stripEndingWhiteSpaces(line);
+ }
+ }
+ }
+}
+
+uint Coff::TextObject::nbLines(const QString &filename) const
+{
+ init();
+ uint nb = 0;
+ for (uint i=0; i<uint(_sections.count()); i++) {
+ if ( _sections[i]->type()!=SectionType::Code ) continue;
+ for (uint k=0; k<uint(_sections[i]->lines().count()); k++) {
+ const CodeLine *cl = _sections[i]->lines()[k];
+ if ( cl->filename()==filename ) nb = qMax(nb, cl->line());
+ }
+ }
+ return nb;
+}
+
+QValueVector<const Coff::CodeLine *> Coff::TextObject::findCodeLines(const QString &filename, uint line) const
+{
+ init();
+ QValueVector<const CodeLine *> list;
+ for (uint i=0; i<uint(_sections.count()); i++) {
+ if ( _sections[i]->type()!=SectionType::Code ) continue;
+ for (uint k=0; k<uint(_sections[i]->lines().count()); k++) {
+ const CodeLine *cl = _sections[i]->lines()[k];
+ if ( (cl->line()-1)==line && cl->filename()==filename ) list.append(cl);
+ }
+ }
+ return list;
+}
+
+int Coff::TextObject::lineForAddress(const PURL::Url &url, Address address) const
+{
+ init();
+ if ( url==_url && _lines.contains(address) ) return _lines[address]-1;
+ for (uint i=0; i<uint(_sections.count()); i++) {
+ if ( _sections[i]->type()!=SectionType::Code ) continue;
+ for (uint k=0; k<uint(_sections[i]->lines().count()); k++) {
+ const CodeLine *cl = _sections[i]->lines()[k];
+ if ( cl->address()!=address ) continue;
+ QString filename = cl->filename();
+ if ( filename.isEmpty() || urlForFilename(filename)!=url ) continue;
+ return cl->line()-1;
+ }
+ }
+ return -1;
+}
+
+QMap<PURL::Url, uint> Coff::TextObject::sourceLinesForAddress(Address address) const
+{
+ QMap<PURL::Url, uint> slines;
+ init();
+ for (uint i=0; i<uint(_sections.count()); i++) {
+ if ( _sections[i]->type()!=SectionType::Code ) continue;
+ for (uint k=0; k<uint(_sections[i]->lines().count()); k++) {
+ const CodeLine *cl = _sections[i]->lines()[k];
+ if ( cl->address()!=address ) continue;
+ QString filename = cl->filename();
+ if ( filename.isEmpty() ) continue;
+ slines[urlForFilename(filename)] = cl->line()-1;
+ }
+ }
+ if ( _lines.contains(address) ) slines[_url] = _lines[address] - 1;
+ return slines;
+}
+
+QValueVector<Address> Coff::TextObject::addresses(const PURL::Url &url, uint line) const
+{
+ init();
+ QValueVector<Address> ad;
+ if ( url==_url ) {
+ QMap<Address, uint>::const_iterator it;
+ for (it=_lines.begin(); it!=_lines.end(); ++it)
+ if ( line==(it.data()-1) ) ad.append(it.key());
+ return ad;
+ }
+ for (uint i=0; i<uint(_sections.count()); i++) {
+ if ( _sections[i]->type()!=SectionType::Code ) continue;
+ for (uint k=0; k<uint(_sections[i]->lines().count()); k++) {
+ const CodeLine *cl = _sections[i]->lines()[k];
+ if ( line!=(cl->line()-1) ) continue;
+ QString filename = cl->filename();
+ if ( filename.isEmpty() || urlForFilename(filename)!=url ) continue;
+ ad.append(cl->address());
+ }
+ }
+ return ad;
+}
+
+const QStringList &Coff::TextObject::filenames() const
+{
+ init();
+ return _filenames;
+}
+
+QString Coff::TextObject::disassembly() const
+{
+ init();
+ if ( _list.isEmpty() ) return i18n("Parsing COFF file is not supported for this device or an error occured.");
+ return _list.join("\n");
+}
+
+Log::KeyList Coff::TextObject::information() const
+{
+ Log::KeyList keys;
+ keys.append(i18n("Format:"), i18n("%1 (magic id: %2)").arg(format().label()).arg(toHexLabel(format().data().magic, 4)));
+ QString name = (format()==Format::PIC30 || device()==0 ? "?" : device()->name());
+ keys.append(i18n("Device:"), name);
+ OptHeaderFormat ohf = optHeaderFormat();
+ QString label = (ohf==OptHeaderFormat::Nb_Types ? i18n("Unknown") : ohf.label());
+ keys.append(i18n("Option header:"), i18n("%1 (magic id: %2)").arg(label).arg(toHexLabel(optHeaderMagic(), 4)));
+ keys.append(i18n("No. of sections:"), QString::number(nbSections()));
+ keys.append(i18n("No. of symbols:"), QString::number(nbSymbols()));
+ keys.append(i18n("No. of variables:"), QString::number(variables().count()));
+ return keys;
+}
diff --git a/src/coff/base/text_coff.h b/src/coff/base/text_coff.h
new file mode 100644
index 0000000..7b6e673
--- /dev/null
+++ b/src/coff/base/text_coff.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * Copyright (C) 2006 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. *
+ ***************************************************************************/
+#ifndef TEXT_COFF_H
+#define TEXT_COFF_H
+
+#include "coff_object.h"
+
+namespace Coff
+{
+
+class TextObject : public Object
+{
+public:
+ TextObject(const Device::Data *device, const PURL::Url &url);
+ virtual bool parse(Log::Base &log);
+ int lineForAddress(const PURL::Url &url, Address address) const;
+ QMap<PURL::Url, uint> sourceLinesForAddress(Address address) const; // url -> line
+ QValueVector<Address> addresses(const PURL::Url &url, uint line) const;
+ const QStringList &filenames() const;
+
+ QString disassembly() const;
+ virtual Log::KeyList information() const;
+
+private:
+ mutable bool _initialized;
+ mutable QMap<Address, uint> _lines; // address -> line in disassembly listing
+ mutable QStringList _list;
+ mutable QStringList _filenames;
+
+ uint nbLines(const QString &filename) const;
+ QValueVector<const CodeLine *> findCodeLines(const QString &filename, uint line) const;
+ PURL::Url urlForFilename(const QString &filename) const;
+ void init() const;
+ const Section *section(const CodeLine &cline) const;
+};
+
+} // namespace
+
+#endif
diff --git a/src/coff/coff.pro b/src/coff/coff.pro
new file mode 100644
index 0000000..262f5c8
--- /dev/null
+++ b/src/coff/coff.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS = xml base \ No newline at end of file
diff --git a/src/coff/xml/Makefile.am b/src/coff/xml/Makefile.am
new file mode 100644
index 0000000..368e2e7
--- /dev/null
+++ b/src/coff/xml/Makefile.am
@@ -0,0 +1,14 @@
+INCLUDES = -I$(top_srcdir)/src $(all_includes)
+METASOURCES = AUTO
+
+noinst_PROGRAMS = xml_coff_parser
+xml_coff_parser_SOURCES = xml_coff_parser.cpp gpprocessor.cpp
+OBJECTS = $(top_builddir)/src/devices/list/libdevicelistnoui.la \
+ $(top_builddir)/src/devices/pic/pic/libpic.la $(top_builddir)/src/devices/pic/base/libpicbase.la \
+ $(top_builddir)/src/devices/pic/xml_data/libpicxml.la \
+ $(top_builddir)/src/devices/mem24/mem24/libmem24.la $(top_builddir)/src/devices/mem24/base/libmem24base.la \
+ $(top_builddir)/src/devices/mem24/xml_data/libmem24xml.la \
+ $(top_builddir)/src/xml_to_data/libxmltodata.la $(top_builddir)/src/devices/base/libdevicebase.la \
+ $(top_builddir)/src/common/common/libcommon.la
+xml_coff_parser_LDADD = $(OBJECTS) $(LIB_KDECORE)
+xml_coff_parser_DEPENDENCIES = $(OBJECTS)
diff --git a/src/coff/xml/gpprocessor.cpp b/src/coff/xml/gpprocessor.cpp
new file mode 100644
index 0000000..85477e9
--- /dev/null
+++ b/src/coff/xml/gpprocessor.cpp
@@ -0,0 +1,340 @@
+/* GNU PIC processor definitions
+ Copyright (C) 2001, 2002, 2003, 2004, 2005
+ Craig Franklin
+
+This file is part of gputils.
+
+gputils 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, or (at your option)
+any later version.
+
+gputils is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with gputils; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "gpprocessor.h"
+
+/* XXXPRO: Need to add a line here for any extra processors. Please
+ keep this list sorted! */
+
+const struct px pics[] = {
+ { eeprom8, PROC_CLASS_EEPROM8, "__EEPROM8", { "eeprom8", "eeprom8", "eeprom8" }, 0x0, 0, 0, -1, NULL },
+ { generic, PROC_CLASS_GENERIC, "__GEN", { "generic", "gen", "unknown" }, 0x0, 0, 0, -1, NULL },
+ { pic10f200, PROC_CLASS_PIC12, "__10F200", { "pic10f200", "p10f200", "10f200" }, 0xf200, 1, 1, 0xff, "10f200.lkr" },
+ { pic10f202, PROC_CLASS_PIC12, "__10F202", { "pic10f202", "p10f202", "10f202" }, 0xf202, 1, 1, 0x1ff, "10f202.lkr" },
+ { pic10f204, PROC_CLASS_PIC12, "__10F204", { "pic10f204", "p10f204", "10f204" }, 0xf204, 1, 1, 0xff, "10f204.lkr" },
+ { pic10f206, PROC_CLASS_PIC12, "__10F206", { "pic10f206", "p10f206", "10f206" }, 0xf206, 1, 1, 0x1ff, "10f206.lkr" },
+ { pic10f220, PROC_CLASS_PIC12, "__10F220", { "pic10f220", "p10f220", "10f220" }, 0xf220, 1, 1, 0xff, "10f220.lkr" },
+ { pic10f222, PROC_CLASS_PIC12, "__10F222", { "pic10f222", "p10f222", "10f222" }, 0xf222, 1, 1, 0x1ff, "10f222.lkr" },
+ { pic12c508, PROC_CLASS_PIC12, "__12C508", { "pic12c508", "p12c508", "12c508" }, 0x2508, 1, 1, 0x1ff, "12c508.lkr" },
+ { pic12c508a, PROC_CLASS_PIC12, "__12C508A", { "pic12c508a", "p12c508a", "12c508a" }, 0x508a, 1, 1, 0x1ff, "12c508a.lkr" },
+ { pic12c509, PROC_CLASS_PIC12, "__12C509", { "pic12c509", "p12c509", "12c509" }, 0x2509, 1, 2, 0x3ff, "12c509.lkr" },
+ { pic12c509a, PROC_CLASS_PIC12, "__12C509A", { "pic12c509a", "p12c509a", "12c509a" }, 0x509a, 1, 2, 0x3ff, "12c509a.lkr" },
+ { pic12c671, PROC_CLASS_PIC14, "__12C671", { "pic12c671", "p12c671", "12c671" }, 0x2671, 1, 2, 0x3ff, "12c671.lkr" },
+ { pic12c672, PROC_CLASS_PIC14, "__12C672", { "pic12c672", "p12c672", "12c672" }, 0x2672, 1, 2, 0x7ff, "12c672.lkr" },
+ { pic12ce518, PROC_CLASS_PIC12, "__12CE518", { "pic12ce518", "p12ce518", "12ce518" }, 0x2518, 1, 1, 0x1ff, "12ce518.lkr" },
+ { pic12ce519, PROC_CLASS_PIC12, "__12CE519", { "pic12ce519", "p12ce519", "12ce519" }, 0x2519, 1, 2, 0x3ff, "12ce519.lkr" },
+ { pic12ce673, PROC_CLASS_PIC14, "__12CE673", { "pic12ce673", "p12ce673", "12ce673" }, 0x2673, 1, 2, 0x3ff, "12ce673.lkr" },
+ { pic12ce674, PROC_CLASS_PIC14, "__12CE674", { "pic12ce674", "p12ce674", "12ce674" }, 0x2674, 1, 2, 0x7ff, "12ce674.lkr" },
+ { pic12cr509a, PROC_CLASS_PIC12, "__12CR509A", { "pic12cr509a", "p12cr509a", "12cr509a" }, 0xd09a, 1, 2, 0x3ff, "12cr509a.lkr" },
+ { pic12f508, PROC_CLASS_PIC12, "__12F508", { "pic12f508", "p12f508", "12f508" }, 0x2508, 1, 1, 0x1ff, "12f508.lkr" },
+ { pic12f509, PROC_CLASS_PIC12, "__12F509", { "pic12f509", "p12f509", "12f509" }, 0x2509, 2, 2, 0x3ff, "12f509.lkr" },
+ { pic12f510, PROC_CLASS_PIC12, "__12F510", { "pic12f510", "p12f510", "12f510" }, 0x2510, 1, 2, 0x3ff, "12f510.lkr" },
+ { pic12f629, PROC_CLASS_PIC14, "__12F629", { "pic12f629", "p12f629", "12f629" }, 0x2629, 1, 2, 0x3fe, "12f629.lkr" },
+ { pic12f635, PROC_CLASS_PIC14, "__12F635", { "pic12f635", "p12f635", "12f635" }, 0x2635, 1, 4, 0x3ff, "12f635.lkr" },
+ { pic12f675, PROC_CLASS_PIC14, "__12F675", { "pic12f675", "p12f675", "12f675" }, 0x2675, 1, 2, 0x3fe, "12f675.lkr" },
+ { pic12f683, PROC_CLASS_PIC14, "__12F683", { "pic12f683", "p12f683", "12f683" }, 0x2683, 1, 2, 0x7ff, "12f683.lkr" },
+ { pic14000, PROC_CLASS_PIC14, "__14000", { "pic14000", "p14000", "14000" }, 0x4000, 2, 2, 0xfbf, "14000.lkr" },
+ { pic16c5x, PROC_CLASS_PIC12, "__16C5X", { "pic16c5x", "p16c5x", "16c5x" }, 0x658a, 4, 4, -1, NULL },
+ { pic16cxx, PROC_CLASS_PIC14, "__16CXX", { "pic16cxx", "p16cxx", "16cxx" }, 0x6c77, 4, 4, -1, NULL },
+ { pic16c432, PROC_CLASS_PIC14, "__16C432", { "pic16c432", "p16c432", "16c432" }, 0x6432, 1, 2, 0x7ff, "16c432.lkr" },
+ { pic16c433, PROC_CLASS_PIC14, "__16C433", { "pic16c433", "p16c433", "16c433" }, 0x6433, 1, 2, 0x7ff, "16c433.lkr" },
+ { pic16c505, PROC_CLASS_PIC12, "__16C505", { "pic16c505", "p16c505", "16c505" }, 0x2505, 1, 4, 0x3ff, "16c505.lkr" },
+ { pic16c52, PROC_CLASS_PIC12, "__16C52", { "pic16c52", "p16c52", "16c52" }, 0x6c52, 1, 1, 0x17f, "16c52.lkr" },
+ { pic16c54, PROC_CLASS_PIC12, "__16C54", { "pic16c54", "p16c54", "16c54" }, 0x6c54, 1, 1, 0x1ff, "16c54.lkr" },
+ { pic16c54a, PROC_CLASS_PIC12, "__16C54A", { "pic16c54a", "p16c54a", "16c54a" }, 0x654a, 1, 1, 0x1ff, "16c54a.lkr" },
+ { pic16c54b, PROC_CLASS_PIC12, "__16C54B", { "pic16c54b", "p16c54b", "16c54b" }, 0x654b, 1, 1, 0x1ff, "16c54b.lkr" },
+ { pic16c54c, PROC_CLASS_PIC12, "__16C54C", { "pic16c54c", "p16c54c", "16c54c" }, 0x654c, 1, 1, 0x1ff, "16c54c.lkr" },
+ { pic16c55, PROC_CLASS_PIC12, "__16C55", { "pic16c55", "p16c55", "16c55" }, 0x6c55, 1, 1, 0x1ff, "16c55.lkr" },
+ { pic16c55a, PROC_CLASS_PIC12, "__16C55A", { "pic16c55a", "p16c55a", "16c55a" }, 0x655a, 1, 1, 0x1ff, "16c55a.lkr" },
+ { pic16c554, PROC_CLASS_PIC14, "__16C554", { "pic16c554", "p16c554", "16c554" }, 0x6554, 1, 2, 0x1ff, "16c554.lkr" },
+ { pic16c557, PROC_CLASS_PIC14, "__16C557", { "pic16c557", "p16c557", "16c557" }, 0x6557, 1, 2, 0x7ff, "16c557.lkr" },
+ { pic16c558, PROC_CLASS_PIC14, "__16C558", { "pic16c558", "p16c558", "16c558" }, 0x6558, 1, 2, 0x7ff, "16c558.lkr" },
+ { pic16c56, PROC_CLASS_PIC12, "__16C56", { "pic16c56", "p16c56", "16c56" }, 0x6c56, 2, 1, 0x3ff, "16c56.lkr" },
+ { pic16c56a, PROC_CLASS_PIC12, "__16C56A", { "pic16c56a", "p16c56a", "16c56a" }, 0x656a, 2, 1, 0x3ff, "16c56a.lkr" },
+ { pic16c57, PROC_CLASS_PIC12, "__16C57", { "pic16c57", "p16c57", "16c57" }, 0x6c57, 4, 4, 0x7ff, "16c57.lkr" },
+ { pic16c57c, PROC_CLASS_PIC12, "__16C57C", { "pic16c57c", "p16c57c", "16c57c" }, 0x657c, 4, 4, 0x7ff, "16c57c.lkr" },
+ { pic16c58a, PROC_CLASS_PIC12, "__16C58A", { "pic16c58a", "p16c58a", "16c58a" }, 0x658a, 4, 4, 0x7ff, "16c58a.lkr" },
+ { pic16c58b, PROC_CLASS_PIC12, "__16C58B", { "pic16c58b", "p16c58b", "16c58b" }, 0x658b, 4, 4, 0x7ff, "16c58b.lkr" },
+ { pic16c61, PROC_CLASS_PIC14, "__16C61", { "pic16c61", "p16c61", "16c61" }, 0x6c61, 1, 2, 0x3ff, "16c61.lkr" },
+ { pic16c62, PROC_CLASS_PIC14, "__16C62", { "pic16c62", "p16c62", "16c62" }, 0x6c62, 1, 2, 0x7ff, "16c62.lkr" },
+ { pic16c62a, PROC_CLASS_PIC14, "__16C62A", { "pic16c62a", "p16c62a", "16c62a" }, 0x662a, 1, 2, 0x7ff, "16c62a.lkr" },
+ { pic16c62b, PROC_CLASS_PIC14, "__16C62B", { "pic16c62b", "p16c62b", "16c62b" }, 0x662b, 1, 2, 0x7ff, "16c62b.lkr" },
+ { pic16c620, PROC_CLASS_PIC14, "__16C620", { "pic16c620", "p16c620", "16c620" }, 0x6620, 1, 2, 0x1ff, "16c620.lkr" },
+ { pic16c620a, PROC_CLASS_PIC14, "__16C620A", { "pic16c620a", "p16c620a", "16c620a" }, 0x620a, 1, 2, 0x1ff, "16c620a.lkr" },
+ { pic16c621, PROC_CLASS_PIC14, "__16C621", { "pic16c621", "p16c621", "16c621" }, 0x6621, 1, 2, 0x3ff, "16c621.lkr" },
+ { pic16c621a, PROC_CLASS_PIC14, "__16C621A", { "pic16c621a", "p16c621a", "16c621a" }, 0x621a, 1, 2, 0x3ff, "16c621a.lkr" },
+ { pic16c622, PROC_CLASS_PIC14, "__16C622", { "pic16c622", "p16c622", "16c622" }, 0x6622, 1, 2, 0x7ff, "16c622.lkr" },
+ { pic16c622a, PROC_CLASS_PIC14, "__16C622A", { "pic16c622a", "p16c622a", "16c622a" }, 0x622a, 1, 2, 0x7ff, "16c622a.lkr" },
+ { pic16c63, PROC_CLASS_PIC14, "__16C63", { "pic16c63", "p16c63", "16c63" }, 0x6c63, 2, 2, 0xfff, "16c63.lkr" },
+ { pic16c63a, PROC_CLASS_PIC14, "__16C63A", { "pic16c63a", "p16c63a", "16c63a" }, 0x663a, 2, 2, 0xfff, "16c63a.lkr" },
+ { pic16c64, PROC_CLASS_PIC14, "__16C64", { "pic16c64", "p16c64", "16c64" }, 0x6c64, 1, 2, 0x7ff, "16c64.lkr" },
+ { pic16c64a, PROC_CLASS_PIC14, "__16C64A", { "pic16c64a", "p16c64a", "16c64a" }, 0x664a, 1, 2, 0x7ff, "16c64a.lkr" },
+ { pic16c642, PROC_CLASS_PIC14, "__16C642", { "pic16c642", "p16c642", "16c642" }, 0x6642, 2, 2, 0xfff, "16c642.lkr" },
+ { pic16c65, PROC_CLASS_PIC14, "__16C65", { "pic16c65", "p16c65", "16c65" }, 0x6c65, 2, 2, 0xfff, "16c65.lkr" },
+ { pic16c65a, PROC_CLASS_PIC14, "__16C65A", { "pic16c65a", "p16c65a", "16c65a" }, 0x665a, 2, 2, 0xfff, "16c65a.lkr" },
+ { pic16c65b, PROC_CLASS_PIC14, "__16C65B", { "pic16c65b", "p16c65b", "16c65b" }, 0x665b, 2, 2, 0xfff, "16c65b.lkr" },
+ { pic16c66, PROC_CLASS_PIC14, "__16C66", { "pic16c66", "p16c66", "16c66" }, 0x6c66, 4, 4, 0x1fff, "16c66.lkr" },
+ { pic16c662, PROC_CLASS_PIC14, "__16C662", { "pic16c662", "p16c662", "16c662" }, 0x6662, 2, 2, 0xfff, "16c662.lkr" },
+ { pic16c67, PROC_CLASS_PIC14, "__16C67", { "pic16c67", "p16c67", "16c67" }, 0x6c67, 4, 4, 0x1fff, "16c67.lkr" },
+ { pic16c71, PROC_CLASS_PIC14, "__16C71", { "pic16c71", "p16c71", "16c71" }, 0x6c71, 1, 2, 0x3ff, "16c71.lkr" },
+ { pic16c710, PROC_CLASS_PIC14, "__16C710", { "pic16c710", "p16c710", "16c710" }, 0x6710, 1, 2, 0x1ff, "16c710.lkr" },
+ { pic16c711, PROC_CLASS_PIC14, "__16C711", { "pic16c711", "p16c711", "16c711" }, 0x6711, 1, 2, 0x3ff, "16c711.lkr" },
+ { pic16c712, PROC_CLASS_PIC14, "__16C712", { "pic16c712", "p16c712", "16c712" }, 0x6712, 1, 2, 0x3ff, "16c712.lkr" },
+ { pic16c715, PROC_CLASS_PIC14, "__16C715", { "pic16c715", "p16c715", "16c715" }, 0x6715, 1, 2, 0x7ff, "16c715.lkr" },
+ { pic16c716, PROC_CLASS_PIC14, "__16C716", { "pic16c716", "p16c716", "16c716" }, 0x6716, 1, 2, 0x7ff, "16c716.lkr" },
+ { pic16c717, PROC_CLASS_PIC14, "__16C717", { "pic16c717", "p16c717", "16c717" }, 0x6717, 1, 4, 0x7ff, "16c717.lkr" },
+ { pic16c72, PROC_CLASS_PIC14, "__16C72", { "pic16c72", "p16c72", "16c72" }, 0x6c72, 1, 2, 0x7ff, "16c72.lkr" },
+ { pic16c72a, PROC_CLASS_PIC14, "__16C72A", { "pic16c72a", "p16c72a", "16c72a" }, 0x672a, 1, 2, 0x7ff, "16c72a.lkr" },
+ { pic16c73, PROC_CLASS_PIC14, "__16C73", { "pic16c73", "p16c73", "16c73" }, 0x673a, 2, 2, 0xfff, "16c73.lkr" },
+ { pic16c73a, PROC_CLASS_PIC14, "__16C73A", { "pic16c73a", "p16c73a", "16c73a" }, 0x673a, 2, 2, 0xfff, "16c73a.lkr" },
+ { pic16c73b, PROC_CLASS_PIC14, "__16C73B", { "pic16c73b", "p16c73b", "16c73b" }, 0x673b, 2, 2, 0xfff, "16c73b.lkr" },
+ { pic16c74, PROC_CLASS_PIC14, "__16C74", { "pic16c74", "p16c74", "16c74" }, 0x6c74, 2, 2, 0xfff, "16c74.lkr" },
+ { pic16c745, PROC_CLASS_PIC14, "__16C745", { "pic16c745", "p16c745", "16c745" }, 0x6745, 4, 4, 0x1fff, "16c745.lkr" },
+ { pic16c74a, PROC_CLASS_PIC14, "__16C74A", { "pic16c74a", "p16c74a", "16c74a" }, 0x674a, 2, 2, 0xfff, "16c74a.lkr" },
+ { pic16c74b, PROC_CLASS_PIC14, "__16C74B", { "pic16c74b", "p16c74b", "16c74b" }, 0x674b, 2, 2, 0xfff, "16c74b.lkr" },
+ { pic16c76, PROC_CLASS_PIC14, "__16C76", { "pic16c76", "p16c76", "16c76" }, 0x6c76, 4, 4, 0x1fff, "16c76.lkr" },
+ { pic16c765, PROC_CLASS_PIC14, "__16C765", { "pic16c765", "p16c765", "16c765" }, 0x6765, 4, 4, 0x1fff, "16c765.lkr" },
+ { pic16c77, PROC_CLASS_PIC14, "__16C77", { "pic16c77", "p16c77", "16c77" }, 0x6c77, 4, 4, 0x1fff, "16c77.lkr" },
+ { pic16c770, PROC_CLASS_PIC14, "__16C770", { "pic16c770", "p16c770", "16c770" }, 0x6770, 1, 4, 0x7ff, "16c770.lkr" },
+ { pic16c771, PROC_CLASS_PIC14, "__16C771", { "pic16c771", "p16c771", "16c771" }, 0x6771, 2, 4, 0xfff, "16c771.lkr" },
+ { pic16c773, PROC_CLASS_PIC14, "__16C773", { "pic16c773", "p16c773", "16c773" }, 0x6773, 2, 4, 0xfff, "16c773.lkr" },
+ { pic16c774, PROC_CLASS_PIC14, "__16C774", { "pic16c774", "p16c774", "16c774" }, 0x6774, 2, 4, 0xfff, "16c774.lkr" },
+ { pic16c781, PROC_CLASS_PIC14, "__16C781", { "pic16c781", "p16c781", "16c781" }, 0x6781, 1, 4, 0x3ff, "16c781.lkr" },
+ { pic16c782, PROC_CLASS_PIC14, "__16C782", { "pic16c782", "p16c782", "16c782" }, 0x6782, 1, 4, 0x7ff, "16c782.lkr" },
+ { pic16c84, PROC_CLASS_PIC14, "__16C84", { "pic16c84", "p16c84", "16c84" }, 0x6c84, 1, 2, 0x3ff, "16c84.lkr" },
+ { pic16c923, PROC_CLASS_PIC14, "__16C923", { "pic16c923", "p16c923", "16c923" }, 0x6923, 2, 4, 0xfff, "16c923.lkr" },
+ { pic16c924, PROC_CLASS_PIC14, "__16C924", { "pic16c924", "p16c924", "16c924" }, 0x6924, 2, 4, 0xfff, "16c924.lkr" },
+ { pic16c925, PROC_CLASS_PIC14, "__16C925", { "pic16c925", "p16c925", "16c925" }, 0x6925, 2, 4, 0xfff, "16c925.lkr" },
+ { pic16c926, PROC_CLASS_PIC14, "__16C926", { "pic16c926", "p16c926", "16c926" }, 0x6926, 4, 4, 0x1fff, "16c926.lkr" },
+ { pic16ce623, PROC_CLASS_PIC14, "__16CE623", { "pic16ce623", "p16ce623", "16ce623" }, 0x6623, 1, 2, 0x1ff, "16ce623.lkr" },
+ { pic16ce624, PROC_CLASS_PIC14, "__16CE624", { "pic16ce624", "p16ce624", "16ce624" }, 0x6624, 1, 2, 0x3ff, "16ce624.lkr" },
+ { pic16ce625, PROC_CLASS_PIC14, "__16CE625", { "pic16ce625", "p16ce625", "16ce625" }, 0x6625, 1, 2, 0x7ff, "16ce625.lkr" },
+ { pic16cr54, PROC_CLASS_PIC12, "__16CR54", { "pic16cr54", "p16cr54", "16cr54" }, 0xdc54, 1, 1, 0x1ff, "16cr54.lkr" },
+ { pic16cr54a, PROC_CLASS_PIC12, "__16CR54A", { "pic16cr54a", "p16cr54a", "16cr54a" }, 0xd54a, 1, 1, 0x1ff, "16cr54a.lkr" },
+ { pic16cr54b, PROC_CLASS_PIC12, "__16CR54B", { "pic16cr54b", "p16cr54b", "16cr54b" }, 0xd54b, 1, 1, 0x1ff, "16cr54b.lkr" },
+ { pic16cr54c, PROC_CLASS_PIC12, "__16CR54C", { "pic16cr54c", "p16cr54c", "16cr54c" }, 0xdc54, 1, 1, 0x1ff, "16cr54c.lkr" },
+ { pic16cr56a, PROC_CLASS_PIC12, "__16CR56A", { "pic16cr56a", "p16cr56a", "16cr56a" }, 0xd56a, 2, 1, 0x3ff, "16cr56a.lkr" },
+ { pic16cr57a, PROC_CLASS_PIC12, "__16CR57A", { "pic16cr57a", "p16cr57a", "16cr57a" }, 0xd57a, 4, 4, 0x7ff, "16cr57a.lkr" },
+ { pic16cr57b, PROC_CLASS_PIC12, "__16CR57B", { "pic16cr57b", "p16cr57b", "16cr57b" }, 0xd57b, 4, 4, 0x7ff, "16cr57b.lkr" },
+ { pic16cr57c, PROC_CLASS_PIC12, "__16CR57C", { "pic16cr57c", "p16cr57c", "16cr57c" }, 0xd57c, 4, 4, 0x7ff, "16cr57c.lkr" },
+ { pic16cr58a, PROC_CLASS_PIC12, "__16CR58A", { "pic16cr58a", "p16cr58a", "16cr58a" }, 0xd58a, 4, 4, 0x7ff, "16cr58a.lkr" },
+ { pic16cr58b, PROC_CLASS_PIC12, "__16CR58B", { "pic16cr58b", "p16cr58b", "16cr58b" }, 0xd58b, 4, 4, 0x7ff, "16cr58b.lkr" },
+ { pic16cr62, PROC_CLASS_PIC14, "__16CR62", { "pic16cr62", "p16cr62", "16cr62" }, 0xdc62, 1, 2, 0x7ff, "16cr62.lkr" },
+ { pic16cr620a, PROC_CLASS_PIC14, "__16CR620A", { "pic16cr620a", "p16cr620a", "16cr620a" }, 0xd20a, 1, 2, 0x1ff, "16cr620a.lkr" },
+ { pic16cr63, PROC_CLASS_PIC14, "__16CR63", { "pic16cr63", "p16cr63", "16cr63" }, 0x6d63, 2, 2, 0xfff, "16cr63.lkr" },
+ { pic16cr64, PROC_CLASS_PIC14, "__16CR64", { "pic16cr64", "p16cr64", "16cr64" }, 0xdc64, 1, 2, 0x7ff, "16cr64.lkr" },
+ { pic16cr65, PROC_CLASS_PIC14, "__16CR65", { "pic16cr65", "p16cr65", "16cr65" }, 0x6d65, 2, 2, 0xfff, "16cr65.lkr" },
+ { pic16cr72, PROC_CLASS_PIC14, "__16CR72", { "pic16cr72", "p16cr72", "16cr72" }, 0x6d72, 1, 2, 0x7ff, "16cr72.lkr" },
+ { pic16cr83, PROC_CLASS_PIC14, "__16CR83", { "pic16cr83", "p16cr83", "16cr83" }, 0xdc83, 1, 2, 0x1ff, "16cr83.lkr" },
+ { pic16cr84, PROC_CLASS_PIC14, "__16CR84", { "pic16cr84", "p16cr84", "16cr84" }, 0xdc84, 1, 2, 0x3ff, "16cr84.lkr" },
+ { pic16f505, PROC_CLASS_PIC12, "__16F505", { "pic16f505", "p16f505", "16f505" }, 0x654f, 2, 4, 0x3ff, "16f505.lkr" },
+ { pic16f54, PROC_CLASS_PIC12, "__16F54", { "pic16f54", "p16f54", "16f54" }, 0x654f, 1, 1, 0x1ff, "16f54.lkr" },
+ { pic16f57, PROC_CLASS_PIC12, "__16F57", { "pic16f57", "p16f57", "16f57" }, 0x657f, 4, 4, 0x7ff, "16f57.lkr" },
+ { pic16f59, PROC_CLASS_PIC12, "__16F59", { "pic16f59", "p16f59", "16f59" }, 0x659f, 4, 4, 0x7ff, "16f59.lkr" },
+ { pic16f610, PROC_CLASS_PIC14, "__16F610", { "pic16f610", "p16f610", "16f610" }, 0x6610, 1, 4, 0x3ff, "16f610.lkr" },
+ { pic16f627, PROC_CLASS_PIC14, "__16F627", { "pic16f627", "p16f627", "16f627" }, 0x6627, 1, 4, 0x3ff, "16f627.lkr" },
+ { pic16f627a, PROC_CLASS_PIC14, "__16F627A", { "pic16f627a", "p16f627a", "16f627a" }, 0x627a, 1, 4, 0x3ff, "16f627a.lkr" },
+ { pic16f628, PROC_CLASS_PIC14, "__16F628", { "pic16f628", "p16f628", "16f628" }, 0x6628, 1, 4, 0x7ff, "16f628.lkr" },
+ { pic16f628a, PROC_CLASS_PIC14, "__16F628A", { "pic16f628a", "p16f628a", "16f628a" }, 0x628a, 1, 4, 0x7ff, "16f628a.lkr" },
+ { pic16f630, PROC_CLASS_PIC14, "__16F630", { "pic16f630", "p16f630", "16f630" }, 0x6630, 1, 2, 0x3fe, "16f630.lkr" },
+ { pic16f636, PROC_CLASS_PIC14, "__16F636", { "pic16f636", "p16f636", "16f636" }, 0x6636, 1, 4, 0x7ff, "16f636.lkr" },
+ { pic16f639, PROC_CLASS_PIC14, "__16F639", { "pic16f639", "p16f639", "16f639" }, 0x6639, 1, 4, 0x7ff, "16f639.lkr" },
+ { pic16f648a, PROC_CLASS_PIC14, "__16F648A", { "pic16f648a", "p16f648a", "16f648a" }, 0x648a, 2, 4, 0xfff, "16f648a.lkr" },
+ { pic16f676, PROC_CLASS_PIC14, "__16F676", { "pic16f676", "p16f676", "16f676" }, 0x6676, 1, 2, 0x3fe, "16f676.lkr" },
+ { pic16f684, PROC_CLASS_PIC14, "__16F684", { "pic16f684", "p16f684", "16f684" }, 0x6684, 1, 2, 0x7ff, "16f684.lkr" },
+ { pic16f685, PROC_CLASS_PIC14, "__16F685", { "pic16f685", "p16f685", "16f685" }, 0x6685, 2, 4, 0xfff, "16f685.lkr" },
+ { pic16f687, PROC_CLASS_PIC14, "__16F687", { "pic16f687", "p16f687", "16f687" }, 0x6687, 1, 4, 0x7ff, "16f687.lkr" },
+ { pic16f688, PROC_CLASS_PIC14, "__16F688", { "pic16f688", "p16f688", "16f688" }, 0x6688, 2, 4, 0xfff, "16f688.lkr" },
+ { pic16f689, PROC_CLASS_PIC14, "__16F689", { "pic16f689", "p16f689", "16f689" }, 0x6689, 2, 4, 0xfff, "16f689.lkr" },
+ { pic16f690, PROC_CLASS_PIC14, "__16F690", { "pic16f690", "p16f690", "16f690" }, 0x6690, 2, 4, 0xfff, "16f690.lkr" },
+ { pic16f716, PROC_CLASS_PIC14, "__16F716", { "pic16f716", "p16f716", "16f716" }, 0x716f, 1, 2, 0x7ff, "16f716.lkr" },
+ { pic16f72, PROC_CLASS_PIC14, "__16F72", { "pic16f72", "p16f72", "16f72" }, 0x672f, 1, 4, 0x7ff, "16f72.lkr" },
+ { pic16f73, PROC_CLASS_PIC14, "__16F73", { "pic16f73", "p16f73", "16f73" }, 0x673f, 2, 4, 0xfff, "16f73.lkr" },
+ { pic16f737, PROC_CLASS_PIC14, "__16F737", { "pic16f737", "p16f737", "16f737" }, 0x737f, 2, 4, 0xfff, "16f737.lkr" },
+ { pic16f74, PROC_CLASS_PIC14, "__16F74", { "pic16f74", "p16f74", "16f74" }, 0x674f, 2, 4, 0xfff, "16f74.lkr" },
+ { pic16f747, PROC_CLASS_PIC14, "__16F747", { "pic16f747", "p16f747", "16f747" }, 0x6747, 2, 4, 0xfff, "16f747.lkr" },
+ { pic16f76, PROC_CLASS_PIC14, "__16F76", { "pic16f76", "p16f76", "16f76" }, 0x676f, 4, 4, 0x1fff, "16f76.lkr" },
+ { pic16f767, PROC_CLASS_PIC14, "__16F767", { "pic16f767", "p16f767", "16f767" }, 0x767f, 4, 4, 0x1fff, "16f767.lkr" },
+ { pic16f77, PROC_CLASS_PIC14, "__16F77", { "pic16f77", "p16f77", "16f77" }, 0x677f, 4, 4, 0x1fff, "16f77.lkr" },
+ { pic16f777, PROC_CLASS_PIC14, "__16F777", { "pic16f777", "p16f777", "16f777" }, 0x777f, 4, 4, 0x1fff, "16f777.lkr" },
+ { pic16f785, PROC_CLASS_PIC14, "__16F785", { "pic16f785", "p16f785", "16f785" }, 0x785f, 1, 4, 0x7ff, "16f785.lkr" },
+ { pic16f818, PROC_CLASS_PIC14, "__16F818", { "pic16f818", "p16f818", "16f818" }, 0x818f, 1, 4, 0x3ff, "16f818.lkr" },
+ { pic16f819, PROC_CLASS_PIC14, "__16F819", { "pic16f819", "p16f819", "16f819" }, 0x819f, 1, 4, 0x7ff, "16f819.lkr" },
+ { pic16f83, PROC_CLASS_PIC14, "__16F83", { "pic16f83", "p16f83", "16f83" }, 0x6c83, 1, 2, 0x1ff, "16f83.lkr" },
+ { pic16f84, PROC_CLASS_PIC14, "__16F84", { "pic16f84", "p16f84", "16f84" }, 0x6f84, 1, 2, 0x3ff, "16f84.lkr" },
+ { pic16f84a, PROC_CLASS_PIC14, "__16F84A", { "pic16f84a", "p16f84a", "16f84a" }, 0x684a, 1, 2, 0x3ff, "16f84a.lkr" },
+ { pic16f87, PROC_CLASS_PIC14, "__16F87", { "pic16f87", "p16f87", "16f87" }, 0x687f, 2, 4, 0xfff, "16f87.lkr" },
+ { pic16f870, PROC_CLASS_PIC14, "__16F870", { "pic16f870", "p16f870", "16f870" }, 0x870f, 1, 4, 0x7ff, "16f870.lkr" },
+ { pic16f871, PROC_CLASS_PIC14, "__16F871", { "pic16f871", "p16f871", "16f871" }, 0x871f, 1, 4, 0x7ff, "16f871.lkr" },
+ { pic16f872, PROC_CLASS_PIC14, "__16F872", { "pic16f872", "p16f872", "16f872" }, 0x872f, 1, 4, 0x7ff, "16f872.lkr" },
+ { pic16f873, PROC_CLASS_PIC14, "__16F873", { "pic16f873", "p16f873", "16f873" }, 0x873f, 2, 4, 0xfff, "16f873.lkr" },
+ { pic16f873a, PROC_CLASS_PIC14, "__16F873A", { "pic16f873a", "p16f873a", "16f873a" }, 0x873a, 2, 4, 0xfff, "16f873a.lkr" },
+ { pic16f874, PROC_CLASS_PIC14, "__16F874", { "pic16f874", "p16f874", "16f874" }, 0x874f, 2, 4, 0xfff, "16f874.lkr" },
+ { pic16f874a, PROC_CLASS_PIC14, "__16F874A", { "pic16f874a", "p16f874a", "16f874a" }, 0x874a, 2, 4, 0xfff, "16f874a.lkr" },
+ { pic16f876, PROC_CLASS_PIC14, "__16F876", { "pic16f876", "p16f876", "16f876" }, 0x876f, 4, 4, 0x1fff, "16f876.lkr" },
+ { pic16f876a, PROC_CLASS_PIC14, "__16F876A", { "pic16f876a", "p16f876a", "16f876a" }, 0x876a, 4, 4, 0x1fff, "16f876a.lkr" },
+ { pic16f877, PROC_CLASS_PIC14, "__16F877", { "pic16f877", "p16f877", "16f877" }, 0x877f, 4, 4, 0x1fff, "16f877.lkr" },
+ { pic16f877a, PROC_CLASS_PIC14, "__16F877A", { "pic16f877a", "p16f877a", "16f877a" }, 0x877a, 4, 4, 0x1fff, "16f877a.lkr" },
+ { pic16f88, PROC_CLASS_PIC14, "__16F88", { "pic16f88", "p16f88", "16f88" }, 0x688f, 4, 4, 0xfff, "16f88.lkr" },
+ { pic16f882, PROC_CLASS_PIC14, "__16F882", { "pic16f882", "p16f882", "16f882" }, 0x882f, 4, 4, 0x7ff, "16f882.lkr" },
+ { pic16f883, PROC_CLASS_PIC14, "__16F883", { "pic16f883", "p16f883", "16f883" }, 0x883f, 4, 4, 0xfff, "16f883.lkr" },
+ { pic16f884, PROC_CLASS_PIC14, "__16F884", { "pic16f884", "p16f884", "16f884" }, 0x884f, 4, 4, 0xfff, "16f884.lkr" },
+ { pic16f886, PROC_CLASS_PIC14, "__16F886", { "pic16f886", "p16f886", "16f886" }, 0x886f, 4, 4, 0x1fff, "16f886.lkr" },
+ { pic16f887, PROC_CLASS_PIC14, "__16F887", { "pic16f887", "p16f887", "16f887" }, 0x887f, 4, 4, 0x1fff, "16f887.lkr" },
+ { pic16f913, PROC_CLASS_PIC14, "__16F913", { "pic16f913", "p16f913", "16f913" }, 0x913f, 2, 4, 0xfff, "16f913.lkr" },
+ { pic16f914, PROC_CLASS_PIC14, "__16F914", { "pic16f914", "p16f914", "16f914" }, 0x914f, 4, 4, 0xfff, "16f914.lkr" },
+ { pic16f916, PROC_CLASS_PIC14, "__16F916", { "pic16f916", "p16f916", "16f916" }, 0x916f, 2, 4, 0x1fff, "16f916.lkr" },
+ { pic16f917, PROC_CLASS_PIC14, "__16F917", { "pic16f917", "p16f917", "16f917" }, 0x917f, 4, 4, 0x1fff, "16f917.lkr" },
+ { pic16hv540, PROC_CLASS_PIC12, "__16HV540", { "pic16hv540", "p16hv540", "16hv540" }, 0x6540, 1, 1, 0x1ff, "16hv540.lkr" },
+ { pic17cxx, PROC_CLASS_PIC16, "__17CXX", { "pic17cxx", "p17cxx", "17cxx" }, 0x7756, 0, 0, -1, NULL },
+ { pic17c42, PROC_CLASS_PIC16, "__17C42", { "pic17c42", "p17c42", "17c42" }, 0x7c42, 0, 0, 0x7ff, "17c42.lkr" },
+ { pic17c42a, PROC_CLASS_PIC16, "__17C42A", { "pic17c42a", "p17c42a", "17c42a" }, 0x742a, 0, 0, 0x7ff, "17c42a.lkr" },
+ { pic17c43, PROC_CLASS_PIC16, "__17C43", { "pic17c43", "p17c43", "17c43" }, 0x7c43, 0, 0, 0xfff, "17c43.lkr" },
+ { pic17c44, PROC_CLASS_PIC16, "__17C44", { "pic17c44", "p17c44", "17c44" }, 0x7c44, 0, 0, 0x1fff, "17c44.lkr" },
+ { pic17c752, PROC_CLASS_PIC16, "__17C752", { "pic17c752", "p17c752", "17c752" }, 0x7752, 0, 0, 0x1fff, "17c752.lkr" },
+ { pic17c756, PROC_CLASS_PIC16, "__17C756", { "pic17c756", "p17c756", "17c756" }, 0x7756, 0, 0, 0x3fff, "17c756.lkr" },
+ { pic17c756a, PROC_CLASS_PIC16, "__17C756A", { "pic17c756a", "p17c756a", "17c756a" }, 0x756a, 0, 0, 0x3fff, "17c756a.lkr" },
+ { pic17c762, PROC_CLASS_PIC16, "__17C762", { "pic17c762", "p17c762", "17c762" }, 0x7762, 0, 0, 0x1fff, "17c762.lkr" },
+ { pic17c766, PROC_CLASS_PIC16, "__17C766", { "pic17c766", "p17c766", "17c766" }, 0x7766, 0, 0, 0x3fff, "17c766.lkr" },
+ { pic17cr42, PROC_CLASS_PIC16, "__17CR42", { "pic17cr42", "p17cr42", "17cr42" }, 0xe42a, 0, 0, 0x7ff, "17cr42.lkr" },
+ { pic17cr43, PROC_CLASS_PIC16, "__17CR43", { "pic17cr43", "p17cr43", "17cr43" }, 0xec43, 0, 0, 0xfff, "17cr43.lkr" },
+ { pic18cxx, PROC_CLASS_PIC16E, "__18CXX", { "pic18cxx", "p18cxx", "18cxx" }, 0x8452, 0, 0, -1, NULL },
+ { pic18c242, PROC_CLASS_PIC16E, "__18C242", { "pic18c242", "p18c242", "18c242" }, 0x8242, 0, 0, 0x3fff, "18c242.lkr" },
+ { pic18c252, PROC_CLASS_PIC16E, "__18C252", { "pic18c252", "p18c252", "18c252" }, 0x8252, 0, 0, 0x7fff, "18c252.lkr" },
+ { pic18c442, PROC_CLASS_PIC16E, "__18C442", { "pic18c442", "p18c442", "18c442" }, 0x8442, 0, 0, 0x3fff, "18c442.lkr" },
+ { pic18c452, PROC_CLASS_PIC16E, "__18C452", { "pic18c452", "p18c452", "18c452" }, 0x8452, 0, 0, 0x7fff, "18c452.lkr" },
+ { pic18c601, PROC_CLASS_PIC16E, "__18C601", { "pic18c601", "p18c601", "18c601" }, 0x8601, 0, 0, 0x3ffff, "18c601.lkr" },
+ { pic18c658, PROC_CLASS_PIC16E, "__18C658", { "pic18c658", "p18c658", "18c658" }, 0x8658, 0, 0, 0x7fff, "18c658.lkr" },
+ { pic18c801, PROC_CLASS_PIC16E, "__18C801", { "pic18c801", "p18c801", "18c801" }, 0x8801, 0, 0, 0x1fffff, "18c801.lkr" },
+ { pic18c858, PROC_CLASS_PIC16E, "__18C858", { "pic18c858", "p18c858", "18c858" }, 0x8858, 0, 0, 0x7fff, "18c858.lkr" },
+ { pic18f1220, PROC_CLASS_PIC16E, "__18F1220", { "pic18f1220", "p18f1220", "18f1220" }, 0xa122, 0, 0, 0xfff, "18f1220.lkr" },
+ { pic18f1230, PROC_CLASS_PIC16E, "__18F1230", { "pic18f1230", "p18f1230", "18f1230" }, 0xa123, 0, 0, 0xfff, "18f1230.lkr" },
+ { pic18f1320, PROC_CLASS_PIC16E, "__18F1320", { "pic18f1320", "p18f1320", "18f1320" }, 0xa132, 0, 0, 0x1fff, "18f1320.lkr" },
+ { pic18f1330, PROC_CLASS_PIC16E, "__18F1330", { "pic18f1330", "p18f1330", "18f1330" }, 0xa133, 0, 0, 0x1fff, "18f1330.lkr" },
+ { pic18f2220, PROC_CLASS_PIC16E, "__18F2220", { "pic18f2220", "p18f2220", "18f2220" }, 0xa222, 0, 0, 0xfff, "18f2220.lkr" },
+ { pic18f2320, PROC_CLASS_PIC16E, "__18F2320", { "pic18f2320", "p18f2320", "18f2320" }, 0xa232, 0, 0, 0x1fff, "18f2320.lkr" },
+ { pic18f2331, PROC_CLASS_PIC16E, "__18F2331", { "pic18f2331", "p18f2331", "18f2331" }, 0x2331, 0, 0, 0x1fff, "18f2331.lkr" },
+ { pic18f2410, PROC_CLASS_PIC16E, "__18F2410", { "pic18f2410", "p18f2410", "18f2410" }, 0x2410, 0, 0, 0x3fff, "18f2410.lkr" },
+ { pic18f242, PROC_CLASS_PIC16E, "__18F242", { "pic18f242", "p18f242", "18f242" }, 0x242f, 0, 0, 0x3fff, "18f242.lkr" },
+ { pic18f2420, PROC_CLASS_PIC16E, "__18F2420", { "pic18f2420", "p18f2420", "18f2420" }, 0x2420, 0, 0, 0x3fff, "18f2420.lkr" },
+ { pic18f2431, PROC_CLASS_PIC16E, "__18F2431", { "pic18f2431", "p18f2431", "18f2431" }, 0x2431, 0, 0, 0x3fff, "18f2431.lkr" },
+ { pic18f2439, PROC_CLASS_PIC16E, "__18F2439", { "pic18f2439", "p18f2439", "18f2439" }, 0x2439, 0, 0, 0x2fff, "18f2439.lkr" },
+ { pic18f2455, PROC_CLASS_PIC16E, "__18F2455", { "pic18f2455", "p18f2455", "18f2455" }, 0x2455, 0, 0, 0x5fff, "18f2455.lkr" },
+ { pic18f248, PROC_CLASS_PIC16E, "__18F248", { "pic18f248", "p18f248", "18f248" }, 0x8248, 0, 0, 0x3fff, "18f248.lkr" },
+ { pic18f2480, PROC_CLASS_PIC16E, "__18F2480", { "pic18f2480", "p18f2480", "18f2480" }, 0x2480, 0, 0, 0x3fff, "18f2480.lkr" },
+ { pic18f24j10, PROC_CLASS_PIC16E, "__18F24J10", { "pic18f24j10", "p18f24j10", "18f24j10" }, 0xd410, 0, 0, 0x3ff7, "18f24j10.lkr" },
+ { pic18f2510, PROC_CLASS_PIC16E, "__18F2510", { "pic18f2510", "p18f2510", "18f2510" }, 0x2510, 0, 0, 0x7fff, "18f2510.lkr" },
+ { pic18f2515, PROC_CLASS_PIC16E, "__18F2515", { "pic18f2515", "p18f2515", "18f2515" }, 0x2515, 0, 0, 0xbfff, "18f2515.lkr" },
+ { pic18f252, PROC_CLASS_PIC16E, "__18F252", { "pic18f252", "p18f252", "18f252" }, 0x252f, 0, 0, 0x7fff, "18f252.lkr" },
+ { pic18f2520, PROC_CLASS_PIC16E, "__18F2520", { "pic18f2520", "p18f2520", "18f2520" }, 0x2520, 0, 0, 0x7fff, "18f2520.lkr" },
+ { pic18f2525, PROC_CLASS_PIC16E, "__18F2525", { "pic18f2525", "p18f2525", "18f2525" }, 0x2525, 0, 0, 0xbfff, "18f2525.lkr" },
+ { pic18f2539, PROC_CLASS_PIC16E, "__18F2539", { "pic18f2539", "p18f2539", "18f2539" }, 0x2539, 0, 0, 0x5fff, "18f2539.lkr" },
+ { pic18f2550, PROC_CLASS_PIC16E, "__18F2550", { "pic18f2550", "p18f2550", "18f2550" }, 0x2550, 0, 0, 0x7fff, "18f2550.lkr" },
+ { pic18f258, PROC_CLASS_PIC16E, "__18F258", { "pic18f258", "p18f258", "18f258" }, 0x8258, 0, 0, 0x7fff, "18f258.lkr" },
+ { pic18f2580, PROC_CLASS_PIC16E, "__18F2580", { "pic18f2580", "p18f2580", "18f2580" }, 0x2580, 0, 0, 0x7fff, "18f2580.lkr" },
+ { pic18f2585, PROC_CLASS_PIC16E, "__18F2585", { "pic18f2585", "p18f2585", "18f2585" }, 0x2585, 0, 0, 0xbfff, "18f2585.lkr" },
+ { pic18f25j10, PROC_CLASS_PIC16E, "__18F25J10", { "pic18f25j10", "p18f25j10", "18f25j10" }, 0xd510, 0, 0, 0x7ff7, "18f25j10.lkr" },
+ { pic18f2610, PROC_CLASS_PIC16E, "__18F2610", { "pic18f2610", "p18f2610", "18f2610" }, 0xa261, 0, 0, 0xffff, "18f2610.lkr" },
+ { pic18f2620, PROC_CLASS_PIC16E, "__18F2620", { "pic18f2620", "p18f2620", "18f2620" }, 0xa262, 0, 0, 0xffff, "18f2620.lkr" },
+ { pic18f2680, PROC_CLASS_PIC16E, "__18F2680", { "pic18f2680", "p18f2680", "18f2680" }, 0x2680, 0, 0, 0xffff, "18f2680.lkr" },
+ { pic18f2681, PROC_CLASS_PIC16E, "__18F2681", { "pic18f2681", "p18f2681", "18f2681" }, 0x2681, 0, 0, -1, "18f2681.lkr" },
+ { pic18f2682, PROC_CLASS_PIC16E, "__18F2682", { "pic18f2682", "p18f2682", "18f2682" }, 0x2682, 0, 0, 0x13fff, "18f2682.lkr" },
+ { pic18f2685, PROC_CLASS_PIC16E, "__18F2685", { "pic18f2685", "p18f2685", "18f2685" }, 0x2685, 0, 0, 0x17fff, "18f2685.lkr" },
+ { pic18f4220, PROC_CLASS_PIC16E, "__18F4220", { "pic18f4220", "p18f4220", "18f4220" }, 0xa422, 0, 0, 0xfff, "18f4220.lkr" },
+ { pic18f4320, PROC_CLASS_PIC16E, "__18F4320", { "pic18f4320", "p18f4320", "18f4320" }, 0xa432, 0, 0, 0x1fff, "18f4320.lkr" },
+ { pic18f4331, PROC_CLASS_PIC16E, "__18F4331", { "pic18f4331", "p18f4331", "18f4331" }, 0x4331, 0, 0, 0x1fff, "18f4331.lkr" },
+ { pic18f4410, PROC_CLASS_PIC16E, "__18F4410", { "pic18f4410", "p18f4410", "18f4410" }, 0x4410, 0, 0, 0x3fff, "18f4410.lkr" },
+ { pic18f442, PROC_CLASS_PIC16E, "__18F442", { "pic18f442", "p18f442", "18f442" }, 0x442f, 0, 0, 0x3fff, "18f442.lkr" },
+ { pic18f4420, PROC_CLASS_PIC16E, "__18F4420", { "pic18f4420", "p18f4420", "18f4420" }, 0x4420, 0, 0, 0x3fff, "18f4420.lkr" },
+ { pic18f4431, PROC_CLASS_PIC16E, "__18F4431", { "pic18f4431", "p18f4431", "18f4431" }, 0x4431, 0, 0, 0x1fff, "18f4431.lkr" },
+ { pic18f4439, PROC_CLASS_PIC16E, "__18F4439", { "pic18f4439", "p18f4439", "18f4439" }, 0x4439, 0, 0, 0x2fff, "18f4439.lkr" },
+ { pic18f4455, PROC_CLASS_PIC16E, "__18F4455", { "pic18f4455", "p18f4455", "18f4455" }, 0x4455, 0, 0, 0x5fff, "18f4455.lkr" },
+ { pic18f448, PROC_CLASS_PIC16E, "__18F448", { "pic18f448", "p18f448", "18f448" }, 0x8448, 0, 0, 0x3fff, "18f448.lkr" },
+ { pic18f4480, PROC_CLASS_PIC16E, "__18F4480", { "pic18f4480", "p18f4480", "18f4480" }, 0x4480, 0, 0, 0x3fff, "18f4480.lkr" },
+ { pic18f44j10, PROC_CLASS_PIC16E, "__18F44J10", { "pic18f44j10", "p18f44j10", "18f44j10" }, 0xe410, 0, 0, 0x3ff7, "18f44j10.lkr" },
+ { pic18f4510, PROC_CLASS_PIC16E, "__18F4510", { "pic18f4510", "p18f4510", "18f4510" }, 0x4510, 0, 0, 0x7fff, "18f4510.lkr" },
+ { pic18f4515, PROC_CLASS_PIC16E, "__18F4515", { "pic18f4515", "p18f4515", "18f4515" }, 0x4515, 0, 0, 0xbfff, "18f4515.lkr" },
+ { pic18f452, PROC_CLASS_PIC16E, "__18F452", { "pic18f452", "p18f452", "18f452" }, 0x452f, 0, 0, 0x7fff, "18f452.lkr" },
+ { pic18f4520, PROC_CLASS_PIC16E, "__18F4520", { "pic18f4520", "p18f4520", "18f4520" }, 0x4520, 0, 0, 0x7fff, "18f4520.lkr" },
+ { pic18f4525, PROC_CLASS_PIC16E, "__18F4525", { "pic18f4525", "p18f4525", "18f4525" }, 0x4525, 0, 0, 0xbfff, "18f4525.lkr" },
+ { pic18f4539, PROC_CLASS_PIC16E, "__18F4539", { "pic18f4539", "p18f4539", "18f4539" }, 0x4539, 0, 0, 0x5fff, "18f4539.lkr" },
+ { pic18f4550, PROC_CLASS_PIC16E, "__18F4550", { "pic18f4550", "p18f4550", "18f4550" }, 0x4550, 0, 0, 0x7fff, "18f4550.lkr" },
+ { pic18f458, PROC_CLASS_PIC16E, "__18F458", { "pic18f458", "p18f458", "18f458" }, 0x8458, 0, 0, 0x7fff, "18f458.lkr" },
+ { pic18f4580, PROC_CLASS_PIC16E, "__18F4580", { "pic18f4580", "p18f4580", "18f4580" }, 0x4580, 0, 0, 0x7fff, "18f4580.lkr" },
+ { pic18f4585, PROC_CLASS_PIC16E, "__18F4585", { "pic18f4585", "p18f4585", "18f4585" }, 0x4585, 0, 0, 0xbfff, "18f4585.lkr" },
+ { pic18f45j10, PROC_CLASS_PIC16E, "__18F45J10", { "pic18f45j10", "p18f45j10", "18f45j10" }, 0xe510, 0, 0, 0x7ff7, "18f45j10.lkr" },
+ { pic18f4610, PROC_CLASS_PIC16E, "__18F4610", { "pic18f4610", "p18f4610", "18f4610" }, 0xa461, 0, 0, 0xffff, "18f4610.lkr" },
+ { pic18f4620, PROC_CLASS_PIC16E, "__18F4620", { "pic18f4620", "p18f4620", "18f4620" }, 0xa462, 0, 0, 0xffff, "18f4620.lkr" },
+ { pic18f4680, PROC_CLASS_PIC16E, "__18F4680", { "pic18f4680", "p18f4680", "18f4680" }, 0x4680, 0, 0, 0xffff, "18f4680.lkr" },
+ { pic18f4681, PROC_CLASS_PIC16E, "__18F4681", { "pic18f4681", "p18f4681", "18f4681" }, 0x4681, 0, 0, -1, "18f4681.lkr" },
+ { pic18f4682, PROC_CLASS_PIC16E, "__18F4682", { "pic18f4682", "p18f4682", "18f4682" }, 0x4682, 0, 0, 0x13fff, "18f4682.lkr" },
+ { pic18f4685, PROC_CLASS_PIC16E, "__18F4685", { "pic18f4685", "p18f4685", "18f4685" }, 0x4685, 0, 0, 0x17fff, "18f4685.lkr" },
+ { pic18f6310, PROC_CLASS_PIC16E, "__18F6310", { "pic18f6310", "p18f6310", "18f6310" }, 0xa631, 0, 0, 0x1fff, "18f6310.lkr" },
+ { pic18f6390, PROC_CLASS_PIC16E, "__18F6390", { "pic18f6390", "p18f6390", "18f6390" }, 0xa639, 0, 0, 0x1fff, "18f6390.lkr" },
+ { pic18f6410, PROC_CLASS_PIC16E, "__18F6410", { "pic18f6410", "p18f6410", "18f6410" }, 0xa641, 0, 0, 0x3fff, "18f6410.lkr" },
+ { pic18f6490, PROC_CLASS_PIC16E, "__18F6490", { "pic18f6490", "p18f6490", "18f6490" }, 0xa649, 0, 0, 0x3fff, "18f6490.lkr" },
+ { pic18f64j15, PROC_CLASS_PIC16E, "__18F64J15", { "pic18f64j15", "p18f64j15", "18f64j15" }, 0xb415, 0, 0, -1, "18f64j15.lkr" },
+ { pic18f6520, PROC_CLASS_PIC16E, "__18F6520", { "pic18f6520", "p18f6520", "18f6520" }, 0xa652, 0, 0, 0x7fff, "18f6520.lkr" },
+ { pic18f6525, PROC_CLASS_PIC16E, "__18F6525", { "pic18f6525", "p18f6525", "18f6525" }, 0x6525, 0, 0, 0xbfff, "18f6525.lkr" },
+ { pic18f6585, PROC_CLASS_PIC16E, "__18F6585", { "pic18f6585", "p18f6585", "18f6585" }, 0x6585, 0, 0, 0xbfff, "18f6585.lkr" },
+ { pic18f65j10, PROC_CLASS_PIC16E, "__18F65J10", { "pic18f65j10", "p18f65j10", "18f65j10" }, 0xb510, 0, 0, 0xbfff, "18f65j10.lkr" },
+ { pic18f65j15, PROC_CLASS_PIC16E, "__18F65J15", { "pic18f65j15", "p18f65j15", "18f65j15" }, 0xb515, 0, 0, 0xbff7, "18f65j15.lkr" },
+ { pic18f6620, PROC_CLASS_PIC16E, "__18F6620", { "pic18f6620", "p18f6620", "18f6620" }, 0xa662, 0, 0, 0xffff, "18f6620.lkr" },
+ { pic18f6621, PROC_CLASS_PIC16E, "__18F6621", { "pic18f6621", "p18f6621", "18f6621" }, 0xa621, 0, 0, 0xffff, "18f6621.lkr" },
+ { pic18f6627, PROC_CLASS_PIC16E, "__18F6627", { "pic18f6627", "p18f6627", "18f6627" }, 0xa627, 0, 0, 0x17fff, "18f6627.lkr" },
+ { pic18f6680, PROC_CLASS_PIC16E, "__18F6680", { "pic18f6680", "p18f6680", "18f6680" }, 0x6680, 0, 0, 0xffff, "18f6680.lkr" },
+ { pic18f66j10, PROC_CLASS_PIC16E, "__18F66J10", { "pic18f66j10", "p18f66j10", "18f66j10" }, 0xb610, 0, 0, 0xfff7, "18f66j10.lkr" },
+ { pic18f66j15, PROC_CLASS_PIC16E, "__18F66J15", { "pic18f66j15", "p18f66j15", "18f66j15" }, 0xb615, 0, 0, 0x17ff7, "18f66j15.lkr" },
+ { pic18f6720, PROC_CLASS_PIC16E, "__18F6720", { "pic18f6720", "p18f6720", "18f6720" }, 0xa672, 0, 0, 0x1ffff, "18f6720.lkr" },
+ { pic18f6722, PROC_CLASS_PIC16E, "__18F6722", { "pic18f6722", "p18f6722", "18f6722" }, 0x6722, 0, 0, 0x1ffff, "18f6722.lkr" },
+ { pic18f67j10, PROC_CLASS_PIC16E, "__18F67J10", { "pic18f67j10", "p18f67j10", "18f67j10" }, 0xb710, 0, 0, 0x1fff7, "18f67j10.lkr" },
+ { pic18f8310, PROC_CLASS_PIC16E, "__18F8310", { "pic18f8310", "p18f8310", "18f8310" }, 0x8310, 0, 0, 0x1fff, "18f8310.lkr" },
+ { pic18f8390, PROC_CLASS_PIC16E, "__18F8390", { "pic18f8390", "p18f8390", "18f8390" }, 0x8390, 0, 0, 0x1fff, "18f8390.lkr" },
+ { pic18f8410, PROC_CLASS_PIC16E, "__18F8410", { "pic18f8410", "p18f8410", "18f8410" }, 0x8410, 0, 0, 0x3fff, "18f8410.lkr" },
+ { pic18f8490, PROC_CLASS_PIC16E, "__18F8490", { "pic18f8490", "p18f8490", "18f8490" }, 0x8490, 0, 0, 0x3fff, "18f8490.lkr" },
+ { pic18f84j15, PROC_CLASS_PIC16E, "__18F84J15", { "pic18f84j15", "p18f84j15", "18f84j15" }, 0xc415, 0, 0, -1, "18f84j15.lkr" },
+ { pic18f8520, PROC_CLASS_PIC16E, "__18F8520", { "pic18f8520", "p18f8520", "18f8520" }, 0xa852, 0, 0, 0x7fff, "18f8520.lkr" },
+ { pic18f8525, PROC_CLASS_PIC16E, "__18F8525", { "pic18f8525", "p18f8525", "18f8525" }, 0x8525, 0, 0, 0xbfff, "18f8525.lkr" },
+ { pic18f8585, PROC_CLASS_PIC16E, "__18F8585", { "pic18f8585", "p18f8585", "18f8585" }, 0x8585, 0, 0, 0xbfff, "18f8585.lkr" },
+ { pic18f85j10, PROC_CLASS_PIC16E, "__18F85J10", { "pic18f85j10", "p18f85j10", "18f85j10" }, 0xc510, 0, 0, 0x7ff7, "18f85j10.lkr" },
+ { pic18f85j15, PROC_CLASS_PIC16E, "__18F85J15", { "pic18f85j15", "p18f85j15", "18f85j15" }, 0xc515, 0, 0, 0xbff7, "18f85j15.lkr" },
+ { pic18f8620, PROC_CLASS_PIC16E, "__18F8620", { "pic18f8620", "p18f8620", "18f8620" }, 0xa862, 0, 0, 0xffff, "18f8620.lkr" },
+ { pic18f8621, PROC_CLASS_PIC16E, "__18F8621", { "pic18f8621", "p18f8621", "18f8621" }, 0x8621, 0, 0, 0xffff, "18f8621.lkr" },
+ { pic18f8627, PROC_CLASS_PIC16E, "__18F8627", { "pic18f8627", "p18f8627", "18f8627" }, 0x8627, 0, 0, 0x17fff, "18f8627.lkr" },
+ { pic18f8680, PROC_CLASS_PIC16E, "__18F8680", { "pic18f8680", "p18f8680", "18f8680" }, 0x8680, 0, 0, 0xffff, "18f8680.lkr" },
+ { pic18f86j10, PROC_CLASS_PIC16E, "__18F86J10", { "pic18f86j10", "p18f86j10", "18f86j10" }, 0xc610, 0, 0, 0xfff7, "18f86j10.lkr" },
+ { pic18f86j15, PROC_CLASS_PIC16E, "__18F86J15", { "pic18f86j15", "p18f86j15", "18f86j15" }, 0xc615, 0, 0, 0x17ff7, "18f86j15.lkr" },
+ { pic18f8720, PROC_CLASS_PIC16E, "__18F8720", { "pic18f8720", "p18f8720", "18f8720" }, 0xa872, 0, 0, 0x1ffff, "18f8720.lkr" },
+ { pic18f8722, PROC_CLASS_PIC16E, "__18F8722", { "pic18f8722", "p18f8722", "18f8722" }, 0x8721, 0, 0, 0x1ffff, "18f8722.lkr" },
+ { pic18f87j10, PROC_CLASS_PIC16E, "__18F87J10", { "pic18f87j10", "p18f87j10", "18f87j10" }, 0xc710, 0, 0, 0x1fff7, "18f87j10.lkr" },
+ { rf509af, PROC_CLASS_PIC12, "__RF509AF", { "rf509af", "rf509af", "rf509af" }, 0x6509, 0, 0, 0x3ff, "rf509af.lkr" },
+ { rf509ag, PROC_CLASS_PIC12, "__RF509AG", { "rf509ag", "rf509ag", "rf509ag" }, 0x7509, 0, 0, 0x3ff, "rf509ag.lkr" },
+ { rf675f, PROC_CLASS_PIC14, "__RF675F", { "rf675f", "rf675f", "rf675f" }, 0x3675, 0, 0, 0x3fe, "rf675f.lkr" },
+ { rf675h, PROC_CLASS_PIC14, "__RF675H", { "rf675h", "rf675h", "rf675h" }, 0x4675, 0, 0, 0x3fe, "rf675h.lkr" },
+ { rf675k, PROC_CLASS_PIC14, "__RF675K", { "rf675k", "rf675k", "rf675k" }, 0x5675, 0, 0, 0x3fe, "rf675k.lkr" },
+ { sx18, PROC_CLASS_SX, "__SX18", { "sx18ac", "sx18", "sx18" }, 0x0018, 0, 0, 0x7ff, NULL },
+ { sx20, PROC_CLASS_SX, "__SX20", { "sx20ac", "sx20", "sx20" }, 0x0020, 0, 0, 0x7ff, NULL },
+ { sx28, PROC_CLASS_SX, "__SX28", { "sx28ac", "sx28", "sx28" }, 0x0028, 0, 0, 0x7ff, NULL },
+ { sx48, PROC_CLASS_SX, "__SX48", { "sx48bd", "sx48", "sx48" }, 0x0048, 0, 0, 0xfff, NULL },
+ { sx52, PROC_CLASS_SX, "__SX52", { "sx52bd", "sx52", "sx52" }, 0x0052, 0, 0, 0xfff, NULL },
+
+ { no_processor,PROC_CLASS_UNKNOWN, 0, { 0, 0, 0, }, 0x0, 0, 0, 0x0, 0 }
+};
diff --git a/src/coff/xml/gpprocessor.h b/src/coff/xml/gpprocessor.h
new file mode 100644
index 0000000..5e0ad41
--- /dev/null
+++ b/src/coff/xml/gpprocessor.h
@@ -0,0 +1,371 @@
+/* GNU PIC processor definitions
+ Copyright (C) 2001, 2002, 2003, 2004, 2005
+ Craig Franklin
+
+This file is part of gputils.
+
+gputils 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, or (at your option)
+any later version.
+
+gputils is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with gputils; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#ifndef __GPPROCESSOR_H__
+#define __GPPROCESSOR_H__
+
+enum proc_class {
+ PROC_CLASS_UNKNOWN, /* Unknown device */
+ PROC_CLASS_EEPROM8, /* 8 bit EEPROM */
+ PROC_CLASS_GENERIC, /* 12 bit device */
+ PROC_CLASS_PIC12, /* 12 bit devices */
+ PROC_CLASS_SX, /* 12 bit devices */
+ PROC_CLASS_PIC14, /* 14 bit devices */
+ PROC_CLASS_PIC16, /* 16 bit devices */
+ PROC_CLASS_PIC16E /* enhanced 16 bit devices */
+};
+
+/* XXXPRO: Need to add an entry for any extra processors. Please keep
+ this list sorted! */
+
+enum pic_processor {
+ no_processor,
+ eeprom8,
+ generic,
+ pic10f200,
+ pic10f202,
+ pic10f204,
+ pic10f206,
+ pic10f220,
+ pic10f222,
+ pic12c508,
+ pic12c508a,
+ pic12c509,
+ pic12c509a,
+ pic12c671,
+ pic12c672,
+ pic12ce518,
+ pic12ce519,
+ pic12ce673,
+ pic12ce674,
+ pic12cr509a,
+ pic12f508,
+ pic12f509,
+ pic12f510,
+ pic12f629,
+ pic12f635,
+ pic12f675,
+ pic12f683,
+ pic14000,
+ pic16c5x,
+ pic16cxx,
+ pic16c432,
+ pic16c433,
+ pic16c505,
+ pic16c54,
+ pic16c52,
+ pic16c54a,
+ pic16c54b,
+ pic16c54c,
+ pic16c55,
+ pic16c55a,
+ pic16c554,
+ pic16c557,
+ pic16c558,
+ pic16c56,
+ pic16c56a,
+ pic16c57,
+ pic16c57c,
+ pic16c58a,
+ pic16c58b,
+ pic16c61,
+ pic16c62,
+ pic16c62a,
+ pic16c62b,
+ pic16c620,
+ pic16c620a,
+ pic16c621,
+ pic16c621a,
+ pic16c622,
+ pic16c622a,
+ pic16c63,
+ pic16c63a,
+ pic16c64,
+ pic16c64a,
+ pic16c642,
+ pic16c65,
+ pic16c65a,
+ pic16c65b,
+ pic16c66,
+ pic16c662,
+ pic16c67,
+ pic16c71,
+ pic16c710,
+ pic16c711,
+ pic16c712,
+ pic16c715,
+ pic16c716,
+ pic16c717,
+ pic16c72,
+ pic16c72a,
+ pic16c73,
+ pic16c73a,
+ pic16c73b,
+ pic16c74,
+ pic16c745,
+ pic16c74a,
+ pic16c74b,
+ pic16c76,
+ pic16c765,
+ pic16c77,
+ pic16c770,
+ pic16c771,
+ pic16c773,
+ pic16c774,
+ pic16c781,
+ pic16c782,
+ pic16c84,
+ pic16c923,
+ pic16c924,
+ pic16c925,
+ pic16c926,
+ pic16ce623,
+ pic16ce624,
+ pic16ce625,
+ pic16cr54,
+ pic16cr54a,
+ pic16cr54b,
+ pic16cr54c,
+ pic16cr56a,
+ pic16cr57a,
+ pic16cr57b,
+ pic16cr57c,
+ pic16cr58a,
+ pic16cr58b,
+ pic16cr62,
+ pic16cr620a,
+ pic16cr63,
+ pic16cr64,
+ pic16cr65,
+ pic16cr72,
+ pic16cr83,
+ pic16cr84,
+ pic16f505,
+ pic16f54,
+ pic16f57,
+ pic16f59,
+ pic16f610,
+ pic16f627,
+ pic16f627a,
+ pic16f628,
+ pic16f628a,
+ pic16f630,
+ pic16f636,
+ pic16f639,
+ pic16f648a,
+ pic16f676,
+ pic16f684,
+ pic16f685,
+ pic16f687,
+ pic16f688,
+ pic16f689,
+ pic16f690,
+ pic16f716,
+ pic16f72,
+ pic16f73,
+ pic16f737,
+ pic16f74,
+ pic16f747,
+ pic16f76,
+ pic16f767,
+ pic16f77,
+ pic16f777,
+ pic16f785,
+ pic16f818,
+ pic16f819,
+ pic16f83,
+ pic16f84,
+ pic16f87,
+ pic16f84a,
+ pic16f870,
+ pic16f871,
+ pic16f872,
+ pic16f873,
+ pic16f873a,
+ pic16f874,
+ pic16f874a,
+ pic16f876,
+ pic16f876a,
+ pic16f877,
+ pic16f877a,
+ pic16f88,
+ pic16f882,
+ pic16f883,
+ pic16f884,
+ pic16f886,
+ pic16f887,
+ pic16f913,
+ pic16f914,
+ pic16f916,
+ pic16f917,
+ pic16hv540,
+ pic17cxx,
+ pic17c42,
+ pic17c42a,
+ pic17c43,
+ pic17c44,
+ pic17c752,
+ pic17c756,
+ pic17c756a,
+ pic17c762,
+ pic17c766,
+ pic17cr42,
+ pic17cr43,
+ pic18cxx,
+ pic18c242,
+ pic18c252,
+ pic18c442,
+ pic18c452,
+ pic18c601,
+ pic18c658,
+ pic18c801,
+ pic18c858,
+ pic18f1220,
+ pic18f1230,
+ pic18f1320,
+ pic18f1330,
+ pic18f2220,
+ pic18f2320,
+ pic18f2331,
+ pic18f2410,
+ pic18f242,
+ pic18f2420,
+ pic18f2431,
+ pic18f2439,
+ pic18f2455,
+ pic18f248,
+ pic18f2480,
+ pic18f24j10,
+ pic18f2510,
+ pic18f2515,
+ pic18f252,
+ pic18f2525,
+ pic18f2539,
+ pic18f2550,
+ pic18f2520,
+ pic18f258,
+ pic18f2580,
+ pic18f2585,
+ pic18f25j10,
+ pic18f2610,
+ pic18f2620,
+ pic18f2680,
+ pic18f2681,
+ pic18f2682,
+ pic18f2685,
+ pic18f4220,
+ pic18f4320,
+ pic18f4331,
+ pic18f4410,
+ pic18f442,
+ pic18f4420,
+ pic18f4431,
+ pic18f4439,
+ pic18f4455,
+ pic18f448,
+ pic18f4480,
+ pic18f44j10,
+ pic18f4510,
+ pic18f4515,
+ pic18f452,
+ pic18f4520,
+ pic18f4525,
+ pic18f4539,
+ pic18f4550,
+ pic18f458,
+ pic18f4580,
+ pic18f4585,
+ pic18f45j10,
+ pic18f4610,
+ pic18f4620,
+ pic18f4680,
+ pic18f4681,
+ pic18f4682,
+ pic18f4685,
+ pic18f6310,
+ pic18f6390,
+ pic18f6410,
+ pic18f6490,
+ pic18f64j15,
+ pic18f6520,
+ pic18f6525,
+ pic18f6585,
+ pic18f65j10,
+ pic18f65j15,
+ pic18f6620,
+ pic18f6621,
+ pic18f6627,
+ pic18f6680,
+ pic18f66j10,
+ pic18f66j15,
+ pic18f6720,
+ pic18f6722,
+ pic18f67j10,
+ pic18f8310,
+ pic18f8390,
+ pic18f8410,
+ pic18f8490,
+ pic18f84j15,
+ pic18f8520,
+ pic18f8525,
+ pic18f8585,
+ pic18f85j10,
+ pic18f85j15,
+ pic18f8620,
+ pic18f8621,
+ pic18f8627,
+ pic18f8680,
+ pic18f86j10,
+ pic18f86j15,
+ pic18f8720,
+ pic18f8722,
+ pic18f87j10,
+ rf509af,
+ rf509ag,
+ rf675f,
+ rf675h,
+ rf675k,
+ sx18,
+ sx20,
+ sx28,
+ sx48,
+ sx52
+};
+
+#define MAX_NAMES 3 /* Maximum number of names a processor can have */
+#if !defined(NULL)
+# define NULL 0
+#endif
+
+struct px {
+ enum pic_processor tag;
+ enum proc_class pclass;
+ const char *defined_as;
+ const char *names[MAX_NAMES];
+ unsigned long coff_type;
+ int num_pages;
+ int num_banks;
+ long maxrom;
+ const char *script;
+};
+extern const px pics[];
+
+#endif
diff --git a/src/coff/xml/xml.pro b/src/coff/xml/xml.pro
new file mode 100644
index 0000000..bf1dc3a
--- /dev/null
+++ b/src/coff/xml/xml.pro
@@ -0,0 +1,17 @@
+STOPDIR = ../../..
+include($${STOPDIR}/app.pro)
+
+TARGET = xml_coff_parser
+SOURCES += gpprocessor.cpp xml_coff_parser.cpp
+LIBS += ../../devices/list/libdevicelist.a \
+ ../../devices/mem24/mem24/libmem24.a ../../devices/mem24/xml_data/libmem24xml.a \
+ ../../devices/mem24/base/libmem24base.a \
+ ../../devices/pic/pic/libpic.a ../../devices/pic/xml_data/libpicxml.a \
+ ../../devices/pic/base/libpicbase.a ../../xml_to_data/libxmltodata.a \
+ ../../devices/base/libdevicebase.a ../../common/global/libglobal.a \
+ ../../common/nokde/libnokde.a ../../common/common/libcommon.a
+
+unix:QMAKE_POST_LINK = cd ../base && ../xml/xml_coff_parser
+unix:QMAKE_CLEAN += ../base/coff_data.cpp
+win32:QMAKE_POST_LINK = cd ..\base && ..\xml\xml_coff_parser.exe
+win32:QMAKE_CLEAN += ..\base\coff_data.cpp
diff --git a/src/coff/xml/xml_coff_parser.cpp b/src/coff/xml/xml_coff_parser.cpp
new file mode 100644
index 0000000..b6fa2d8
--- /dev/null
+++ b/src/coff/xml/xml_coff_parser.cpp
@@ -0,0 +1,116 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 "xml_to_data/prog_xml_to_data.h"
+#include "coff/base/coff_data.h"
+
+#include "devices/base/device_group.h"
+#include "devices/pic/base/pic.h"
+#include "devices/list/device_list.h"
+#include "gpprocessor.h"
+
+//-----------------------------------------------------------------------------
+namespace Coff
+{
+
+class XmlToData : public ExtXmlToData<Data>
+{
+public:
+ XmlToData() : ExtXmlToData<Data>("coff", "Coff") {}
+
+private:
+ QMap<uint, bool> _ids;
+ virtual bool hasFamilies() const { return false; }
+ virtual void parseData(QDomElement element, Data &data);
+ virtual void outputData(const Data &data, QTextStream &s) const;
+ virtual void outputFunctions(QTextStream &s) const;
+ virtual void parse();
+};
+
+void Coff::XmlToData::parseData(QDomElement element, Data &data)
+{
+ QStringList list = QStringList::split(' ', element.attribute("id"));
+ if ( list.isEmpty() ) qFatal("Missing id");
+ if ( list.count()>MAX_NB_IDS ) qFatal("Please raise MAX_NB_IDS");
+ for (uint i=0; i<MAX_NB_IDS; i++) {
+ if ( i<uint(list.count()) ) {
+ bool ok;
+ data.ids[i] = fromHexLabel(list[i], 4, &ok);
+ if ( !ok ) qFatal("Invalid id");
+ //if ( _ids.contains(data.ids[i]) ) qFatal("Duplicated id");
+ //_ids[data.ids[i]] = true;
+ } else data.ids[i] = 0;
+ }
+}
+
+void Coff::XmlToData::outputData(const Data &data, QTextStream &s) const
+{
+ s << "{ ";
+ for (uint i=0; i<MAX_NB_IDS; i++) {
+ if ( i!=0 ) s << ", ";
+ s << toHexLabel(data.ids[i], 4);
+ }
+ s << "}";
+}
+
+void Coff::XmlToData::outputFunctions(QTextStream &s) const
+{
+ ExtXmlToData<Data>::outputFunctions(s);
+ s << "QString findId(uint id)" << endl;
+ s << "{" << endl;
+ s << " for (uint i=0; DATA_LIST[i]; i++) {" << endl;
+ s << " for (uint k=0; k<MAX_NB_IDS; k++)" << endl;
+ s << " if ( DATA_LIST[i]->data.ids[k]==id ) return DATA_LIST[i]->name;" << endl;
+ s << " }" << endl;
+ s << " return QString::null;" << endl;
+ s << "}" << endl;
+}
+
+void Coff::XmlToData::parse()
+{
+ ExtXmlToData<Data>::parse();
+
+ // check what devices we are missing
+ const ::Group::Base *gpic = Device::lister().group("pic");
+ ::Group::Base::ConstIterator it;
+ for (it=gpic->begin(); it!=gpic->end(); ++it) {
+ const Pic::Data *data = static_cast<const Pic::Data*>(it.data().data);
+ switch (data->architecture().type()) {
+ case Pic::Architecture::P10X:
+ case Pic::Architecture::P16X:
+ case Pic::Architecture::P17C:
+ case Pic::Architecture::P18C:
+ case Pic::Architecture::P18F:
+ case Pic::Architecture::P18J: break;
+ case Pic::Architecture::P24F:
+ case Pic::Architecture::P24H:
+ case Pic::Architecture::P30F:
+ case Pic::Architecture::P33F: continue;
+ case Pic::Architecture::Nb_Types: Q_ASSERT(false); continue;
+ }
+ if ( !hasDevice(data->name()) ) qWarning("No id for device %s", data->name().latin1());
+ }
+
+ // extract COFF id from gputils
+ for (uint i=0; pics[i].tag!=no_processor; i++) {
+ _current = QString(pics[i].names[2]).upper();
+ if ( !Device::lister().isSupported(_current) ) continue;
+ if ( !hasDevice(_current) ) qDebug(">> add new id %s: %s", _current.latin1(), toHexLabel(pics[i].coff_type, 4).latin1());
+ else {
+ bool ok = false;
+ for (uint k=0; k<MAX_NB_IDS; k++)
+ if ( _map[_current].data.ids[k]==pics[i].coff_type ) ok = true;
+ if ( !ok ) qFatal(QString("Different ids"));
+ }
+ }
+}
+
+} // namespace
+
+//-----------------------------------------------------------------------------
+XML_MAIN(Coff::XmlToData)