This commit is contained in:
Thomas Jentzsch 2021-12-11 23:28:17 +01:00
commit 4a09170877
5 changed files with 70 additions and 50 deletions

View File

@ -67,9 +67,9 @@ CartridgeBUS::CartridgeBUS(const ByteBuffer& image, size_t size,
reinterpret_cast<uInt16*>(myImage.get()), reinterpret_cast<uInt16*>(myImage.get()),
reinterpret_cast<uInt16*>(myRAM.data()), reinterpret_cast<uInt16*>(myRAM.data()),
static_cast<uInt32>(32_KB), static_cast<uInt32>(32_KB),
0x00000800, Thumbulator::rom_base + 0x0800,
0x00000808, Thumbulator::rom_base + 0x0808,
0x40001FDC, Thumbulator::ram_base + 0x1FDC,
devSettings ? settings.getBool("dev.thumb.trapfatal") : false, devSettings ? settings.getBool("dev.thumb.trapfatal") : false,
devSettings ? static_cast<double>( devSettings ? static_cast<double>(
settings.getFloat("dev.thumb.cyclefactor")) : 1.0, settings.getFloat("dev.thumb.cyclefactor")) : 1.0,
@ -256,8 +256,8 @@ uInt8 CartridgeBUS::peek(uInt16 address)
// get sample value from ROM or RAM // get sample value from ROM or RAM
if (sampleaddress < 0x8000) if (sampleaddress < 0x8000)
peekvalue = myImage[sampleaddress]; peekvalue = myImage[sampleaddress];
else if (sampleaddress >= 0x40000000 && sampleaddress < 0x40002000) // check for RAM else if (sampleaddress >= Thumbulator::ram_base && sampleaddress < Thumbulator::ram_base + 0x2000) // check for RAM
peekvalue = myRAM[sampleaddress - 0x40000000]; peekvalue = myRAM[sampleaddress - Thumbulator::ram_base];
else else
peekvalue = 0; peekvalue = 0;
@ -707,7 +707,7 @@ uInt32 CartridgeBUS::getWaveform(uInt8 index) const
(myRAM[WAVEFORM + index*4 + 2] << 16) + (myRAM[WAVEFORM + index*4 + 2] << 16) +
(myRAM[WAVEFORM + index*4 + 3] << 24); // high byte (myRAM[WAVEFORM + index*4 + 3] << 24); // high byte
result -= 0x40000800; result -= Thumbulator::ram_base + 0x0800;
if (result >= 4096) if (result >= 4096)
result = 0; result = 0;

View File

@ -90,13 +90,13 @@ CartridgeCDF::CartridgeCDF(const ByteBuffer& image, size_t size,
// C addresses // C addresses
uInt32 cBase, cStart, cStack; uInt32 cBase, cStart, cStack;
if (isCDFJplus()) { if (isCDFJplus()) {
cBase = getUInt32(myImage.get(), 0x17F8) & 0xFFFFFFFE; // C Base Address cBase = Thumbulator::rom_base + getUInt32(myImage.get(), 0x17F8) & 0x0FFFFFFE; // C Base Address
cStart = cBase; // C Start Address cStart = cBase; // C Start Address
cStack = getUInt32(myImage.get(), 0x17F4); // C Stack cStack = Thumbulator::ram_base + (getUInt32(myImage.get(), 0x17F4) & 0x0FFFFFFF); // C Stack
} else { } else {
cBase = 0x800; // C Base Address cBase = Thumbulator::rom_base + 0x800; // C Base Address
cStart = 0x808; // C Start Address (skip ARM header) cStart = Thumbulator::rom_base + 0x808; // C Start Address (skip ARM header)
cStack = 0x40001FDC; // C Stack cStack = Thumbulator::ram_base + 0x1FDC; // C Stack
} }
// Create Thumbulator ARM emulator // Create Thumbulator ARM emulator
@ -296,8 +296,8 @@ uInt8 CartridgeCDF::peek(uInt16 address)
// get sample value from ROM or RAM // get sample value from ROM or RAM
if (sampleaddress < 0x00080000) if (sampleaddress < 0x00080000)
peekvalue = myImage[sampleaddress]; peekvalue = myImage[sampleaddress];
else if (sampleaddress >= 0x40000000 && sampleaddress < 0x40008000) // check for RAM else if (sampleaddress >= Thumbulator::ram_base && sampleaddress < Thumbulator::ram_base + 0x8000) // check for RAM
peekvalue = myRAM[sampleaddress - 0x40000000]; peekvalue = myRAM[sampleaddress - Thumbulator::ram_base];
else else
peekvalue = 0; peekvalue = 0;
@ -677,7 +677,7 @@ uInt32 CartridgeCDF::getWaveform(uInt8 index) const
(myRAM[address + 2] << 16) + (myRAM[address + 2] << 16) +
(myRAM[address + 3] << 24); // high byte (myRAM[address + 3] << 24); // high byte
result -= (0x40000000 + uInt32(2_KB)); result -= (Thumbulator::ram_base + uInt32(2_KB));
if (!isCDFJplus()) { if (!isCDFJplus()) {
if (result >= 4096) { if (result >= 4096) {

View File

@ -53,9 +53,9 @@ CartridgeDPCPlus::CartridgeDPCPlus(const ByteBuffer& image, size_t size,
(reinterpret_cast<uInt16*>(myImage.get()), (reinterpret_cast<uInt16*>(myImage.get()),
reinterpret_cast<uInt16*>(myDPCRAM.data()), reinterpret_cast<uInt16*>(myDPCRAM.data()),
static_cast<uInt32>(32_KB), static_cast<uInt32>(32_KB),
0x00000C00, Thumbulator::rom_base + 0x0C00,
0x00000C08, Thumbulator::rom_base + 0x0C08,
0x40001FDC, Thumbulator::ram_base + 0x1FDC,
devSettings ? settings.getBool("dev.thumb.trapfatal") : false, devSettings ? settings.getBool("dev.thumb.trapfatal") : false,
devSettings ? static_cast<double>( devSettings ? static_cast<double>(
settings.getFloat("dev.thumb.cyclefactor")) : 1.0, settings.getFloat("dev.thumb.cyclefactor")) : 1.0,

View File

@ -123,6 +123,8 @@ using Common::Base;
#define INC_ARM_CYCLES(m) #define INC_ARM_CYCLES(m)
#endif #endif
//#define UNSAFE_OPTIMIZATIONS
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Thumbulator::Thumbulator(const uInt16* rom_ptr, uInt16* ram_ptr, uInt32 rom_size, Thumbulator::Thumbulator(const uInt16* rom_ptr, uInt16* ram_ptr, uInt32 rom_size,
const uInt32 c_base, const uInt32 c_start, const uInt32 c_stack, const uInt32 c_base, const uInt32 c_start, const uInt32 c_stack,
@ -325,7 +327,7 @@ uInt32 Thumbulator::fetch16(uInt32 addr)
switch(addr & 0xF0000000) switch(addr & 0xF0000000)
{ {
case 0x00000000: //ROM case rom_base: //ROM
addr &= ROMADDMASK; addr &= ROMADDMASK;
if(addr < 0x50) if(addr < 0x50)
fatalError("fetch16", addr, "abort"); fatalError("fetch16", addr, "abort");
@ -334,7 +336,7 @@ uInt32 Thumbulator::fetch16(uInt32 addr)
DO_DBUG(statusMsg << "fetch16(" << Base::HEX8 << addr << ")=" << Base::HEX4 << data << endl); DO_DBUG(statusMsg << "fetch16(" << Base::HEX8 << addr << ")=" << Base::HEX4 << data << endl);
return data; return data;
case 0x40000000: //RAM case ram_base: //RAM
addr &= RAMADDMASK; addr &= RAMADDMASK;
addr >>= 1; addr >>= 1;
data = CONV_RAMROM(ram[addr]); data = CONV_RAMROM(ram[addr]);
@ -353,7 +355,7 @@ uInt32 Thumbulator::fetch16(uInt32 addr)
void Thumbulator::write16(uInt32 addr, uInt32 data) void Thumbulator::write16(uInt32 addr, uInt32 data)
{ {
#ifndef UNSAFE_OPTIMIZATIONS #ifndef UNSAFE_OPTIMIZATIONS
if((addr > 0x40007fff) && (addr < 0x50000000)) if((addr > Thumbulator::ram_base + 0x7fff) && (addr < Thumbulator::ram_base + 0x10000000))
fatalError("write16", addr, "abort - out of range"); fatalError("write16", addr, "abort - out of range");
if (isProtected(addr)) fatalError("write16", addr, "to driver area"); if (isProtected(addr)) fatalError("write16", addr, "to driver area");
@ -369,7 +371,7 @@ void Thumbulator::write16(uInt32 addr, uInt32 data)
switch(addr & 0xF0000000) switch(addr & 0xF0000000)
{ {
case 0x40000000: //RAM case ram_base: //RAM
addr &= RAMADDMASK; addr &= RAMADDMASK;
addr >>= 1; addr >>= 1;
ram[addr] = CONV_DATA(data); ram[addr] = CONV_DATA(data);
@ -531,7 +533,7 @@ void Thumbulator::write32(uInt32 addr, uInt32 data)
return; return;
#ifndef UNSAFE_OPTIMIZATIONS #ifndef UNSAFE_OPTIMIZATIONS
case 0x40000000: //RAM case ram_base: //RAM
#else #else
default: default:
#endif #endif
@ -548,8 +550,8 @@ void Thumbulator::write32(uInt32 addr, uInt32 data)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Thumbulator::isProtected(uInt32 addr) bool Thumbulator::isProtected(uInt32 addr)
{ {
if (addr < 0x40000000) return false; if (addr < ram_base) return false;
addr -= 0x40000000; addr -= ram_base;
switch (configuration) { switch (configuration) {
case ConfigureFor::DPCplus: case ConfigureFor::DPCplus:
@ -578,9 +580,9 @@ uInt32 Thumbulator::read16(uInt32 addr)
{ {
uInt32 data; uInt32 data;
#ifndef UNSAFE_OPTIMIZATIONS #ifndef UNSAFE_OPTIMIZATIONS
if((addr > 0x40007fff) && (addr < 0x50000000)) if((addr > Thumbulator::ram_base + 0x7fff) && (addr < Thumbulator::ram_base + 0x10000000))
fatalError("read16", addr, "abort - out of range"); fatalError("read16", addr, "abort - out of range");
else if((addr > 0x0007ffff) && (addr < 0x10000000)) else if((addr > Thumbulator::rom_base + 0x0007ffff) && (addr < Thumbulator::rom_base + 0x10000000))
fatalError("read16", addr, "abort - out of range"); fatalError("read16", addr, "abort - out of range");
if(addr & 1) if(addr & 1)
fatalError("read16", addr, "abort - misaligned"); fatalError("read16", addr, "abort - misaligned");
@ -591,14 +593,16 @@ uInt32 Thumbulator::read16(uInt32 addr)
switch(addr & 0xF0000000) switch(addr & 0xF0000000)
{ {
case 0x00000000: //ROM //case 0x00000000: //ROM
case rom_base: //ROM
addr &= ROMADDMASK; addr &= ROMADDMASK;
addr >>= 1; addr >>= 1;
data = CONV_RAMROM(rom[addr]); data = CONV_RAMROM(rom[addr]);
DO_DBUG(statusMsg << "read16(" << Base::HEX8 << addr << ")=" << Base::HEX4 << data << endl); DO_DBUG(statusMsg << "read16(" << Base::HEX8 << addr << ")=" << Base::HEX4 << data << endl);
return data; return data;
case 0x40000000: //RAM //case 0x40000000: //RAM
case ram_base: //RAM
addr &= RAMADDMASK; addr &= RAMADDMASK;
addr >>= 1; addr >>= 1;
data = CONV_RAMROM(ram[addr]); data = CONV_RAMROM(ram[addr]);
@ -633,8 +637,10 @@ uInt32 Thumbulator::read32(uInt32 addr)
uInt32 data; uInt32 data;
switch(addr & 0xF0000000) switch(addr & 0xF0000000)
{ {
case 0x00000000: //ROM case rom_base: //ROM
case 0x40000000: //RAM //case 0x00000000: //ROM
case ram_base: //RAM
//case 0x40000000: //RAM
data = read16(addr+0); data = read16(addr+0);
data |= (uInt32(read16(addr+2))) << 16; data |= (uInt32(read16(addr+2))) << 16;
DO_DBUG(statusMsg << "read32(" << Base::HEX8 << addr << ")=" << Base::HEX8 << data << endl); DO_DBUG(statusMsg << "read32(" << Base::HEX8 << addr << ")=" << Base::HEX8 << data << endl);
@ -1061,8 +1067,9 @@ int Thumbulator::execute()
Op decodedOp; Op decodedOp;
#ifndef UNSAFE_OPTIMIZATIONS #ifndef UNSAFE_OPTIMIZATIONS
if ((instructionPtr & 0xF0000000) == 0 && instructionPtr < romSize) if ((instructionPtr & 0xF0000000) == rom_base
decodedOp = decodedRom[instructionPtr >> 1]; && instructionPtr >= rom_base && instructionPtr < rom_base + romSize)
decodedOp = decodedRom[(instructionPtr - rom_base) >> 1];
else else
decodedOp = decodeInstructionWord(inst); decodedOp = decodeInstructionWord(inst);
#else #else
@ -1565,10 +1572,10 @@ int Thumbulator::execute()
// address to test for is + 4 due to pipelining // address to test for is + 4 due to pipelining
#define BUS_SetNote (0x000006da + 4) #define BUS_SetNote (rom_base + 0x06da + 4)
#define BUS_ResetWave (0x000006de + 4) #define BUS_ResetWave (rom_base + 0x06de + 4)
#define BUS_GetWavePtr (0x000006e2 + 4) #define BUS_GetWavePtr (rom_base + 0x06e2 + 4)
#define BUS_SetWaveSize (0x000006e6 + 4) #define BUS_SetWaveSize (rom_base + 0x06e6 + 4)
if (pc == BUS_SetNote) if (pc == BUS_SetNote)
{ {
@ -1590,7 +1597,7 @@ int Thumbulator::execute()
myCartridge->thumbCallback(3, read_register(2), read_register(3)); myCartridge->thumbCallback(3, read_register(2), read_register(3));
handled = true; handled = true;
} }
else if (pc == 0x0000083a) else if (pc == Thumbulator::rom_base + 0x083a)
{ {
// exiting Custom ARM code, returning to BUS Driver control // exiting Custom ARM code, returning to BUS Driver control
} }
@ -1626,10 +1633,10 @@ int Thumbulator::execute()
// address to test for is + 4 due to pipelining // address to test for is + 4 due to pipelining
#define CDF_SetNote (0x000006e2 + 4) #define CDF_SetNote (rom_base + 0x06e2 + 4)
#define CDF_ResetWave (0x000006e6 + 4) #define CDF_ResetWave (rom_base + 0x06e6 + 4)
#define CDF_GetWavePtr (0x000006ea + 4) #define CDF_GetWavePtr (rom_base + 0x06ea + 4)
#define CDF_SetWaveSize (0x000006ee + 4) #define CDF_SetWaveSize (rom_base + 0x06ee + 4)
if (pc == CDF_SetNote) if (pc == CDF_SetNote)
{ {
@ -1651,7 +1658,7 @@ int Thumbulator::execute()
myCartridge->thumbCallback(3, read_register(2), read_register(3)); myCartridge->thumbCallback(3, read_register(2), read_register(3));
handled = true; handled = true;
} }
else if (pc == 0x0000083a) else if (pc == Thumbulator::rom_base + 0x083a)
{ {
// exiting Custom ARM code, returning to CDF Driver control // exiting Custom ARM code, returning to CDF Driver control
} }
@ -1689,10 +1696,10 @@ int Thumbulator::execute()
// address to test for is + 4 due to pipelining // address to test for is + 4 due to pipelining
#define CDF1_SetNote (0x00000752 + 4) #define CDF1_SetNote (rom_base + 0x0752 + 4)
#define CDF1_ResetWave (0x00000756 + 4) #define CDF1_ResetWave (rom_base + 0x0756 + 4)
#define CDF1_GetWavePtr (0x0000075a + 4) #define CDF1_GetWavePtr (rom_base + 0x075a + 4)
#define CDF1_SetWaveSize (0x0000075e + 4) #define CDF1_SetWaveSize (rom_base + 0x075e + 4)
if (pc == CDF1_SetNote) if (pc == CDF1_SetNote)
{ {
@ -1730,7 +1737,7 @@ int Thumbulator::execute()
INC_ARM_CYCLES(2 + _flashCycles + 2); // ARM code ReturnC INC_ARM_CYCLES(2 + _flashCycles + 2); // ARM code ReturnC
handled = true; handled = true;
} }
else if (pc == 0x0000083a) else if (pc == Thumbulator::rom_base + 0x083a)
{ {
// exiting Custom ARM code, returning to CDFJ Driver control // exiting Custom ARM code, returning to CDFJ Driver control
} }
@ -2898,9 +2905,9 @@ int Thumbulator::reset()
cpsr = 0; cpsr = 0;
handler_mode = false; handler_mode = false;
systick_ctrl = 0x00000004; systick_ctrl = rom_base + 0x0004; // TODO: not 100% sure about rom_base here
systick_reload = 0x00000000; systick_reload = rom_base;
systick_count = 0x00000000; systick_count = rom_base;
systick_calibrate = 0x00ABCDEF; systick_calibrate = 0x00ABCDEF;
// fxq: don't care about below so much (maybe to guess timing???) // fxq: don't care about below so much (maybe to guess timing???)

View File

@ -34,6 +34,10 @@ class Cartridge;
#define UNSAFE_OPTIMIZATIONS #define UNSAFE_OPTIMIZATIONS
#endif #endif
// Note: This is still experimental, no guarantees!
// TODO: make selectable from command line
#define STM32F4 // compile for UnoCart/PlusCart using STM32F407xxx CPU
#define ROMADDMASK 0x7FFFF #define ROMADDMASK 0x7FFFF
#define RAMADDMASK 0x7FFF #define RAMADDMASK 0x7FFF
@ -95,6 +99,15 @@ class Thumbulator
uInt32 mamDataHits{0}, mamDataMisses{0}; uInt32 mamDataHits{0}, mamDataMisses{0};
#endif #endif
}; };
#ifndef STM32F4
// Harmony/Encore base adresses
static constexpr uInt32 ram_base = 0x40000000;
static constexpr uInt32 rom_base = 0x00000000;
#else
// UnoCart/PlusCart base adresses (TODO!)
static constexpr uInt32 ram_base = 0x10000000;
static constexpr uInt32 rom_base = 0x20000000;
#endif
Thumbulator(const uInt16* rom_ptr, uInt16* ram_ptr, uInt32 rom_size, Thumbulator(const uInt16* rom_ptr, uInt16* ram_ptr, uInt32 rom_size,
const uInt32 c_base, const uInt32 c_start, const uInt32 c_stack, const uInt32 c_base, const uInt32 c_start, const uInt32 c_stack,