diff options
Diffstat (limited to 'src/coff')
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 §ion, + 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 §ion, + 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 §ion, 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 §ion, const QByteArray &data, + uint offset, const QString &lastFilename, Log::Base &log); + const Section §ion() 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) |