You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
piklab/src/devices/pic/base/pic_register.cpp

288 lines
8.9 KiB

/***************************************************************************
* 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 "pic_register.h"
#include "pic.h"
//-----------------------------------------------------------------------------
Pic::RegistersData::RegistersData(const Data &data)
: nbBanks(0), accessBankSplit(0), _data(data)
{}
Address Pic::RegistersData::mirroredAddress(Address address) const
{
Address mirror = address;
for (uint i=0; i<uint(mirrored.count()); i++) {
int delta = -1;
for (uint k=0; k<uint(mirrored[i].count()); k++) {
if ( address<mirrored[i][k].start
|| address>=mirrored[i][k].start+mirrored[i][k].length ) continue;
delta = address - mirrored[i][k].start;
break;
}
if ( delta==-1 ) continue;
for (uint k=0; k<uint(mirrored[i].count()); k++)
mirror = TQMIN(mirrored[i][k].start + delta, mirror);
break;
}
return mirror;
}
Device::RegisterProperties Pic::RegistersData::properties(Address address) const
{
switch ( type(address) ) {
case Mirrored:
case UnusedRegister: return Device::NotAccessible;
case Gpr: return (Device::Readable | Device::Writable);
case Sfr: {
Device::RegisterProperties properties = Device::NotAccessible;
RegisterBitProperties rbp = RegisterBitUnused;
TQMap<TQString, RegisterData>::const_iterator it;
for (it=sfrs.begin(); it!=sfrs.end(); ++it) {
if ( it.data().address!=address ) continue;
for (uint i=0; i<Device::MAX_NB_PORT_BITS; i++) rbp |= it.data().bits[i].properties;
if ( rbp & RegisterBitRead ) properties |= Device::Readable;
if ( rbp & RegisterBitWrite ) properties |= Device::Writable;
break;
}
return properties;
}
}
Q_ASSERT(false);
return Device::NotAccessible;
}
Pic::RegisterType Pic::RegistersData::type(Address address) const
{
for (uint i=0; i<uint(unused.count()); i++)
if ( address>=unused[i].start && address<unused[i].start+unused[i].length ) return UnusedRegister;
if ( !sfrNames[address].isEmpty() ) return Sfr;
Address mirror = mirroredAddress(address);
if ( !sfrNames[mirror].isEmpty() ) return Mirrored;
if ( address==mirror ) return Gpr;
return Mirrored;
}
TQString Pic::RegistersData::label(Address address) const
{
switch ( type(address) ) {
case UnusedRegister: return "---";
case Mirrored: return i18n("Mirror of %1").tqarg(toHexLabel(mirroredAddress(address), nbCharsAddress()));
case Gpr: return "<GPR>";
case Sfr: return sfrNames[address];
}
Q_ASSERT(false);
return TQString();
}
bool Pic::RegistersData::hasPort(uint index) const
{
Q_ASSERT( index<Device::MAX_NB_PORTS );
if ( sfrs.contains("GPIO") ) return ( index==0 );
if ( !sfrs.contains(portName(index)) ) return false;
return true;
}
int Pic::RegistersData::portIndex(Address address) const
{
TQString name = sfrNames[address];
if ( name.isEmpty() ) return -1;
for (uint i=0; i<Device::MAX_NB_PORTS; i++) {
if ( !hasPort(i) ) continue;
if ( name==portName(i) || name==trisName(i) || name==latchName(i) ) return i;
}
return -1;
}
bool Pic::RegistersData::hasPortBit(uint index, uint bit) const
{
if ( !hasPort(index) ) return false;
const RegisterData &port = sfrs[portName(index)];
return ( port.bits[bit].properties!=RegisterBitUnused );
}
TQString Pic::RegistersData::portName(uint index) const
{
if ( sfrs.contains("GPIO") ) {
if ( index!=0 ) return TQString();
return "GPIO";
}
return TQString("PORT") + char('A' + index);
}
TQString Pic::RegistersData::trisName(uint index) const
{
if ( sfrs.contains("GPIO") ) {
if ( index!=0 ) return TQString();
return "TRISIO";
}
if ( _data.architecture()==Architecture::P17C ) {
if ( index==0 ) return TQString();
return TQString("DDR") + char('A' + index);
}
return TQString("TRIS") + char('A' + index);
}
bool Pic::RegistersData::hasTris(uint index) const
{
TQString name = trisName(index);
if ( name.isEmpty() ) return false;
return sfrs.contains(name);
}
TQString Pic::RegistersData::latchName(uint index) const
{
if ( _data.architecture()==Architecture::P10X || _data.architecture()==Architecture::P16X || _data.architecture()==Architecture::P17C )
return TQString();
return TQString("LAT") + char('A' + index);
}
bool Pic::RegistersData::hasLatch(uint index) const
{
TQString name = latchName(index);
if ( name.isEmpty() ) return false;
return sfrs.contains(name);
}
TQString Pic::RegistersData::portBitName(uint index, uint bit) const
{
if ( sfrs.contains("GPIO") ) return TQString("GP") + TQString::number(bit);
return TQString("R") + char('A' + index) + TQString::number(bit);
}
TQValueList<Register::TypeData> Pic::RegistersData::relatedRegisters(const Register::TypeData &data) const
{
TQValueList<Register::TypeData> list;
if ( data.type()==Register::Regular ) {
int i = portIndex(data.address());
if ( i==-1 ) list.append(data);
else {
list.append(Register::TypeData(sfrs[portName(i)].address, nbChars()));
if ( hasTris(i) ) list.append(Register::TypeData(sfrs[trisName(i)].address, nbChars()));
if ( hasLatch(i) ) list.append(Register::TypeData(sfrs[latchName(i)].address, nbChars()));
}
} else if ( data.type()==Register::Combined ) {
uint nb = nbBitsToNbBytes(4*data.nbChars()) / nbBytes();
for (uint i=0; i<nb; i++) list.append(Register::TypeData(data.address() + i*nbBytes(), nbChars()));
} else list.append(data);
return list;
}
bool Pic::RegistersData::isBankUsed(uint i) const
{
Q_ASSERT( i<nbBanks );
return !(unusedBankMask & (1 << i));
}
bool Pic::RegistersData::bankHasSfrs(uint i) const
{
if ( i==0 ) return true;
if ( (_data.architecture()==Pic::Architecture::P18F || _data.architecture()==Pic::Architecture::P18J) && i==15 ) return true;
if ( !isBankUsed(i) ) return false;
TQMap<Address, TQString>::const_iterator it;
for (it=sfrNames.begin(); it!=sfrNames.end(); ++it)
if ( bankFromAddress(it.key())==i ) return true;
return false;
}
bool Pic::RegistersData::hasSharedGprs(uint &firstIndex, bool &all) const
{
bool ok = false;
all = true;
for (uint i=0; i<nbRegistersPerBank(); i++) {
Address address = addressFromIndex(i);
if ( type(address)!=Gpr ) continue;
uint k = 1;
for (; k<nbBanks; k++) {
RegisterType t = type(address + k*nbBytesPerBank());
if ( t!=Mirrored ) break;
}
if ( k==nbBanks ) {
if ( !ok ) firstIndex = i;
ok = true;
} else all = false;
}
return ok;
}
uint Pic::RegistersData::firstGprIndex() const
{
for (uint i=0; i<nbRegistersPerBank(); i++)
if ( type(addressFromIndex(i))==Gpr ) return i;
Q_ASSERT(false);
return 0;
}
//----------------------------------------------------------------------------
TQDataStream &Pic::operator <<(TQDataStream &s, const RangeData &rd)
{
s << rd.start << rd.length;
return s;
}
TQDataStream &Pic::operator >>(TQDataStream &s, RangeData &rd)
{
s >> rd.start >> rd.length;
return s;
}
TQDataStream &Pic::operator <<(TQDataStream &s, const RegisterBitData &rbd)
{
s << TQ_UINT8(rbd.properties) << TQ_UINT8(rbd.por) << TQ_UINT8(rbd.mclr);
return s;
}
TQDataStream &Pic::operator >>(TQDataStream &s, RegisterBitData &rbd)
{
TQ_UINT8 properties, por, mclr;
s >> properties >> por >> mclr;
rbd.properties = RegisterBitProperties(properties);
rbd.por = RegisterBitState(por);
rbd.mclr = RegisterBitState(mclr);
return s;
}
TQDataStream &Pic::operator <<(TQDataStream &s, const RegisterData &rd)
{
s << rd.address;
for (int i=0; i<Device::MAX_NB_PORT_BITS; i++) s << rd.bits[i];
return s;
}
TQDataStream &Pic::operator >>(TQDataStream &s, RegisterData &rd)
{
s >> rd.address;
for (int i=0; i<Device::MAX_NB_PORT_BITS; i++) s >> rd.bits[i];
return s;
}
TQDataStream &Pic::operator <<(TQDataStream &s, const CombinedData &rd)
{
s << rd.address << rd.nbChars;
return s;
}
TQDataStream &Pic::operator >>(TQDataStream &s, CombinedData &rd)
{
s >> rd.address >> rd.nbChars;
return s;
}
TQDataStream &Pic::operator <<(TQDataStream &s, const RegistersData &rd)
{
s << rd.nbBanks << rd.accessBankSplit << rd.unusedBankMask;
s << rd.sfrs << rd.mirrored << rd.unused << rd.combined;
return s;
}
TQDataStream &Pic::operator >>(TQDataStream &s, RegistersData &rd)
{
s >> rd.nbBanks >> rd.accessBankSplit >> rd.unusedBankMask;
s >> rd.sfrs >> rd.mirrored >> rd.unused >> rd.combined;
rd.sfrNames.clear();
TQMap<TQString, RegisterData>::const_iterator it;
for(it=rd.sfrs.begin(); it!=rd.sfrs.end(); ++it) rd.sfrNames[it.data().address] = it.key();
return s;
}