mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2025-04-10 19:15:14 +00:00
422 lines
10 KiB
C++
422 lines
10 KiB
C++
/**
|
|
** Supermodel
|
|
** A Sega Model 3 Arcade Emulator.
|
|
** Copyright 2011 Bart Trzynadlowski, Nik Henson
|
|
**
|
|
** This file is part of Supermodel.
|
|
**
|
|
** Supermodel 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 3 of the License, or (at your option)
|
|
** any later version.
|
|
**
|
|
** Supermodel 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 Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
|
**/
|
|
|
|
/*
|
|
* Register.cpp
|
|
*/
|
|
|
|
#ifdef SUPERMODEL_DEBUGGER
|
|
|
|
#include "CPUDebug.h"
|
|
#include "Debugger.h"
|
|
#include "Register.h"
|
|
|
|
#include <cstdio>
|
|
#include <string>
|
|
|
|
namespace Debugger
|
|
{
|
|
CRegister::CRegister(CCPUDebug *regCPU, const char *regName, const char *regGroup, UINT8 regDataWidth) :
|
|
cpu(regCPU), name(regName), group(regGroup), dataWidth(regDataWidth)
|
|
{
|
|
//
|
|
}
|
|
|
|
double CRegister::GetValueAsFPoint()
|
|
{
|
|
return (double)GetValueAsInt();
|
|
}
|
|
|
|
CRegMonitor::CRegMonitor(CRegister *theReg) : reg(theReg)
|
|
{
|
|
//
|
|
}
|
|
|
|
CPCRegister::CPCRegMonitor::CPCRegMonitor(CPCRegister *theReg) : CRegMonitor(theReg)
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
bool CPCRegister::CPCRegMonitor::HasChanged()
|
|
{
|
|
return m_prevPC != reg->cpu->pc;
|
|
}
|
|
|
|
void CPCRegister::CPCRegMonitor::GetBeforeValue(char *str)
|
|
{
|
|
reg->cpu->FormatAddress(str, m_prevPC);
|
|
}
|
|
|
|
void CPCRegister::CPCRegMonitor::Reset()
|
|
{
|
|
m_prevPC = reg->cpu->pc;
|
|
}
|
|
|
|
CPCRegister::CPCRegister(CCPUDebug *cpu, const char *name, const char *group) : CRegister(cpu, name, group, cpu->memBusWidth)
|
|
{
|
|
//
|
|
}
|
|
|
|
UINT32 CPCRegister::Get()
|
|
{
|
|
return cpu->pc;
|
|
}
|
|
|
|
bool CPCRegister::Set(UINT32 val)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void CPCRegister::GetValue(char *str)
|
|
{
|
|
if (cpu->instrCount > 0)
|
|
cpu->FormatAddress(str, cpu->pc);
|
|
else
|
|
{
|
|
str[0] = '-';
|
|
str[1] = '\0';
|
|
}
|
|
}
|
|
|
|
UINT64 CPCRegister::GetValueAsInt()
|
|
{
|
|
return cpu->pc;
|
|
}
|
|
|
|
bool CPCRegister::SetValue(const char *str)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
CRegMonitor *CPCRegister::CreateMonitor()
|
|
{
|
|
return new CPCRegMonitor(this);
|
|
}
|
|
|
|
CAddrRegister::CAddrRegMonitor::CAddrRegMonitor(CAddrRegister *theReg) : CRegMonitor(theReg)
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
bool CAddrRegister::CAddrRegMonitor::HasChanged()
|
|
{
|
|
return m_prevAddr != ((CAddrRegister*)reg)->Get();
|
|
}
|
|
|
|
void CAddrRegister::CAddrRegMonitor::GetBeforeValue(char *str)
|
|
{
|
|
reg->cpu->FormatAddress(str, m_prevAddr);
|
|
}
|
|
|
|
void CAddrRegister::CAddrRegMonitor::Reset()
|
|
{
|
|
m_prevAddr = ((CAddrRegister*)reg)->Get();
|
|
}
|
|
|
|
CAddrRegister::CAddrRegister(CCPUDebug *cpu, const char *name, const char *group, unsigned id, GetInt32FPtr getFunc, SetInt32FPtr setFunc) :
|
|
CRegister(cpu, name, group, cpu->memBusWidth), m_id(id), m_getFunc(getFunc), m_setFunc(setFunc)
|
|
{
|
|
//
|
|
}
|
|
|
|
UINT32 CAddrRegister::Get()
|
|
{
|
|
return m_getFunc(cpu, m_id);
|
|
}
|
|
|
|
bool CAddrRegister::Set(UINT32 val)
|
|
{
|
|
return m_setFunc(cpu, m_id, val);
|
|
}
|
|
|
|
void CAddrRegister::GetValue(char *str)
|
|
{
|
|
cpu->FormatAddress(str, Get());
|
|
}
|
|
|
|
UINT64 CAddrRegister::GetValueAsInt()
|
|
{
|
|
return Get();
|
|
}
|
|
|
|
bool CAddrRegister::SetValue(const char *str)
|
|
{
|
|
UINT32 addr;
|
|
if (!cpu->ParseAddress(str, &addr))
|
|
return false;
|
|
return Set(addr);
|
|
}
|
|
|
|
CRegMonitor *CAddrRegister::CreateMonitor()
|
|
{
|
|
return new CAddrRegMonitor(this);
|
|
}
|
|
|
|
CIntRegister::CIntRegMonitor::CIntRegMonitor(CIntRegister *theReg) : CRegMonitor(theReg)
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
bool CIntRegister::CIntRegMonitor::HasChanged()
|
|
{
|
|
return m_prevVal != ((CIntRegister*)reg)->Get();
|
|
}
|
|
|
|
void CIntRegister::CIntRegMonitor::GetBeforeValue(char *str)
|
|
{
|
|
reg->cpu->FormatData(str, reg->dataWidth / 8, m_prevVal);
|
|
}
|
|
|
|
void CIntRegister::CIntRegMonitor::Reset()
|
|
{
|
|
m_prevVal = ((CIntRegister*)reg)->Get();
|
|
}
|
|
|
|
CIntRegister::CIntRegister(CCPUDebug *cpu, const char *name, const char *group, unsigned id, GetInt8FPtr getFunc, SetInt8FPtr setFunc) :
|
|
CRegister(cpu, name, group, 8), m_id(id),
|
|
m_get8Func(getFunc), m_set8Func(setFunc), m_get16Func(NULL), m_set16Func(NULL),
|
|
m_get32Func(NULL), m_set32Func(NULL), m_get64Func(NULL), m_set64Func(NULL)
|
|
{
|
|
//
|
|
}
|
|
|
|
CIntRegister::CIntRegister(CCPUDebug *cpu, const char *name, const char *group, unsigned id, GetInt16FPtr getFunc, SetInt16FPtr setFunc) :
|
|
CRegister(cpu, name, group, 16), m_id(id),
|
|
m_get8Func(NULL), m_set8Func(NULL), m_get16Func(getFunc), m_set16Func(setFunc),
|
|
m_get32Func(NULL), m_set32Func(NULL), m_get64Func(NULL), m_set64Func(NULL)
|
|
{
|
|
//
|
|
}
|
|
|
|
CIntRegister::CIntRegister(CCPUDebug *cpu, const char *name, const char *group, unsigned id, GetInt32FPtr getFunc, SetInt32FPtr setFunc) :
|
|
CRegister(cpu, name, group, 32), m_id(id),
|
|
m_get8Func(NULL), m_set8Func(NULL), m_get16Func(NULL), m_set16Func(NULL),
|
|
m_get32Func(getFunc), m_set32Func(setFunc), m_get64Func(NULL), m_set64Func(NULL)
|
|
{
|
|
//
|
|
}
|
|
|
|
CIntRegister::CIntRegister(CCPUDebug *cpu, const char *name, const char *group, unsigned id, GetInt64FPtr getFunc, SetInt64FPtr setFunc) :
|
|
CRegister(cpu, name, group, 64), m_id(id),
|
|
m_get8Func(NULL), m_set8Func(NULL), m_get16Func(NULL), m_set16Func(NULL),
|
|
m_get32Func(NULL), m_set32Func(NULL), m_get64Func(getFunc), m_set64Func(setFunc)
|
|
{
|
|
//
|
|
}
|
|
|
|
UINT64 CIntRegister::Get()
|
|
{
|
|
switch (dataWidth / 8)
|
|
{
|
|
case 1: return (UINT64)m_get8Func(cpu, m_id);
|
|
case 2: return (UINT64)m_get16Func(cpu, m_id);
|
|
case 4: return (UINT64)m_get32Func(cpu, m_id);
|
|
case 8: return m_get64Func(cpu, m_id);
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
bool CIntRegister::Set(UINT64 val)
|
|
{
|
|
switch (dataWidth / 8)
|
|
{
|
|
case 1: return m_set8Func != NULL && m_set8Func(cpu, m_id, (UINT8)val);
|
|
case 2: return m_set16Func != NULL && m_set16Func(cpu, m_id, (UINT16)val);
|
|
case 4: return m_set32Func != NULL && m_set32Func(cpu, m_id, (UINT32)val);
|
|
case 8: return m_set64Func != NULL && m_set64Func(cpu, m_id, val);
|
|
default: return false;
|
|
}
|
|
}
|
|
|
|
void CIntRegister::GetValue(char *str)
|
|
{
|
|
cpu->FormatData(str, dataWidth / 8, Get());
|
|
}
|
|
|
|
UINT64 CIntRegister::GetValueAsInt()
|
|
{
|
|
return Get();
|
|
}
|
|
|
|
bool CIntRegister::SetValue(const char *str)
|
|
{
|
|
UINT64 data;
|
|
if (!cpu->ParseData(str, dataWidth / 8, &data))
|
|
return false;
|
|
return Set(data);
|
|
}
|
|
|
|
CRegMonitor *CIntRegister::CreateMonitor()
|
|
{
|
|
return new CIntRegMonitor(this);
|
|
}
|
|
|
|
CStatusRegister::CStatusRegister(CCPUDebug *cpu, const char *name, const char *group, unsigned id, GetInt8FPtr getFunc, SetInt8FPtr setFunc) :
|
|
CIntRegister(cpu, name, group, id, getFunc, setFunc), numBits(0), offChr('.')
|
|
{
|
|
memset(&m_bitChrs, '\0', sizeof(m_bitChrs));
|
|
}
|
|
|
|
CStatusRegister::CStatusRegister(CCPUDebug *cpu, const char *name, const char *group, unsigned id, GetInt16FPtr getFunc, SetInt16FPtr setFunc) :
|
|
CIntRegister(cpu, name, group, id, getFunc, setFunc), numBits(0), offChr('.')
|
|
{
|
|
memset(&m_bitChrs, '\0', sizeof(m_bitChrs));
|
|
}
|
|
|
|
CStatusRegister::CStatusRegister(CCPUDebug *cpu, const char *name, const char *group, unsigned id, GetInt32FPtr getFunc, SetInt32FPtr setFunc) :
|
|
CIntRegister(cpu, name, group, id, getFunc, setFunc), numBits(0), offChr('.')
|
|
{
|
|
memset(&m_bitChrs, '\0', sizeof(m_bitChrs));
|
|
}
|
|
|
|
CStatusRegister::CStatusRegister(CCPUDebug *cpu, const char *name, const char *group, unsigned id, GetInt64FPtr getFunc, SetInt64FPtr setFunc) :
|
|
CIntRegister(cpu, name, group, id, getFunc, setFunc), numBits(0), offChr('.')
|
|
{
|
|
memset(&m_bitChrs, '\0', sizeof(m_bitChrs));
|
|
}
|
|
|
|
char &CStatusRegister::operator[](const unsigned index)
|
|
{
|
|
if (index >= dataWidth)
|
|
exit(1);
|
|
numBits = std::max<unsigned>(numBits, index);
|
|
return m_bitChrs[index];
|
|
}
|
|
|
|
void CStatusRegister::SetBits(const char *bitStr)
|
|
{
|
|
// Find end
|
|
const char *p = bitStr;
|
|
while (*p != '\0')
|
|
p++;
|
|
unsigned i = 0;
|
|
while (p-- > bitStr && i < dataWidth)
|
|
{
|
|
if (*p != offChr)
|
|
m_bitChrs[i] = *p;
|
|
i++;
|
|
}
|
|
numBits = i;
|
|
}
|
|
|
|
void CStatusRegister::GetValue(char *str)
|
|
{
|
|
UINT64 val = Get();
|
|
char *p = str + numBits;
|
|
*p-- = '\0';
|
|
for (unsigned i = 0; i < numBits; i++)
|
|
{
|
|
*p-- = (val&0x01 ? m_bitChrs[i] : offChr);
|
|
val >>= 1;
|
|
}
|
|
}
|
|
|
|
bool CStatusRegister::SetValue(const char *str)
|
|
{
|
|
UINT64 val = 0;
|
|
while (*str != '\0')
|
|
{
|
|
if (*str != offChr)
|
|
{
|
|
for (unsigned i = 0; i < numBits; i++)
|
|
{
|
|
if (m_bitChrs[i] == *str)
|
|
{
|
|
val |= 1LL<<i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
str++;
|
|
}
|
|
return Set(val);
|
|
}
|
|
|
|
CFPointRegister::CFPointRegMonitor::CFPointRegMonitor(CFPointRegister *theReg) : CRegMonitor(theReg)
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
bool CFPointRegister::CFPointRegMonitor::HasChanged()
|
|
{
|
|
return m_prevVal != ((CFPointRegister*)reg)->Get();
|
|
}
|
|
|
|
void CFPointRegister::CFPointRegMonitor::GetBeforeValue(char *str)
|
|
{
|
|
sprintf(str, "%f", m_prevVal);
|
|
}
|
|
|
|
void CFPointRegister::CFPointRegMonitor::Reset()
|
|
{
|
|
m_prevVal = ((CFPointRegister*)reg)->Get();
|
|
}
|
|
|
|
CFPointRegister::CFPointRegister(CCPUDebug *cpu, const char *name, const char *group, unsigned id, GetFPointFPtr getFunc, SetFPointFPtr setFunc) :
|
|
CRegister(cpu, name, group, 8), m_id(id), m_getFunc(getFunc), m_setFunc(setFunc)
|
|
{
|
|
//
|
|
}
|
|
|
|
double CFPointRegister::Get()
|
|
{
|
|
return m_getFunc(cpu, m_id);
|
|
}
|
|
|
|
bool CFPointRegister::Set(double val)
|
|
{
|
|
if (m_setFunc == NULL)
|
|
return false;
|
|
m_setFunc(cpu, m_id, val);
|
|
return true;
|
|
}
|
|
|
|
void CFPointRegister::GetValue(char *str)
|
|
{
|
|
sprintf(str, "%lf", Get());
|
|
}
|
|
|
|
UINT64 CFPointRegister::GetValueAsInt()
|
|
{
|
|
return (UINT64)Get();
|
|
}
|
|
|
|
double CFPointRegister::GetValueAsFPoint()
|
|
{
|
|
return Get();
|
|
}
|
|
|
|
bool CFPointRegister::SetValue(const char *str)
|
|
{
|
|
double val;
|
|
if (sscanf(str, "%lf", &val) != 1)
|
|
return false;
|
|
return Set(val);
|
|
}
|
|
|
|
CRegMonitor *CFPointRegister::CreateMonitor()
|
|
{
|
|
return new CFPointRegMonitor(this);
|
|
}
|
|
}
|
|
|
|
#endif // SUPERMODEL_DEBUGGER
|