enhanced range checks for Thumbulator

changed initial Thumb code stack pointer
This commit is contained in:
Thomas Jentzsch 2022-03-29 19:18:11 +02:00
parent 6a74c61ac5
commit 7b1e494ca3
5 changed files with 104 additions and 24 deletions

View File

@ -69,7 +69,7 @@ CartridgeBUS::CartridgeBUS(const ByteBuffer& image, size_t size,
static_cast<uInt32>(32_KB), static_cast<uInt32>(32_KB),
0x00000800, 0x00000800,
0x00000808, 0x00000808,
0x40001FDC, 0x40001FFC,
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

@ -95,7 +95,7 @@ CartridgeCDF::CartridgeCDF(const ByteBuffer& image, size_t size,
} else { } else {
cBase = 0x800; // C Base Address cBase = 0x800; // C Base Address
cStart = 0x808; // C Start Address (skip ARM header) cStart = 0x808; // C Start Address (skip ARM header)
cStack = 0x40001FDC; // C Stack cStack = 0x40001FFC; // C Stack
} }
// Create Thumbulator ARM emulator // Create Thumbulator ARM emulator

View File

@ -55,7 +55,7 @@ CartridgeDPCPlus::CartridgeDPCPlus(const ByteBuffer& image, size_t size,
static_cast<uInt32>(32_KB), static_cast<uInt32>(32_KB),
0x00000C00, 0x00000C00,
0x00000C08, 0x00000C08,
0x40001FDC, 0x40001FFC,
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

@ -353,11 +353,6 @@ 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))
fatalError("write16", addr, "abort - out of range");
if (isProtected(addr)) fatalError("write16", addr, "to driver area");
if(addr & 1) if(addr & 1)
fatalError("write16", addr, "abort - misaligned"); fatalError("write16", addr, "abort - misaligned");
#endif #endif
@ -370,6 +365,12 @@ void Thumbulator::write16(uInt32 addr, uInt32 data)
switch(addr & 0xF0000000) switch(addr & 0xF0000000)
{ {
case 0x40000000: //RAM case 0x40000000: //RAM
#ifndef UNSAFE_OPTIMIZATIONS
if(isInvalidRAM(addr))
fatalError("write16", addr, "abort - out of range");
if(isProtectedRAM(addr))
fatalError("write16", addr, "to driver area");
#endif
addr &= RAMADDMASK; addr &= RAMADDMASK;
addr >>= 1; addr >>= 1;
ram[addr] = CONV_DATA(data); ram[addr] = CONV_DATA(data);
@ -399,8 +400,6 @@ void Thumbulator::write32(uInt32 addr, uInt32 data)
#ifndef UNSAFE_OPTIMIZATIONS #ifndef UNSAFE_OPTIMIZATIONS
if(addr & 3) if(addr & 3)
fatalError("write32", addr, "abort - misaligned"); fatalError("write32", addr, "abort - misaligned");
if (isProtected(addr)) fatalError("write32", addr, "to driver area");
#endif #endif
DO_DBUG(statusMsg << "write32(" << Base::HEX8 << addr << "," << Base::HEX8 << data << ")" << endl); DO_DBUG(statusMsg << "write32(" << Base::HEX8 << addr << "," << Base::HEX8 << data << ")" << endl);
@ -546,34 +545,96 @@ void Thumbulator::write32(uInt32 addr, uInt32 data)
#ifndef UNSAFE_OPTIMIZATIONS #ifndef UNSAFE_OPTIMIZATIONS
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Thumbulator::isProtected(uInt32 addr) bool Thumbulator::isInvalidROM(uInt32 addr)
{
const uInt32 romStart = configuration == ConfigureFor::DPCplus ? 0xc00 : 0x750; // was 0x800
switch(romSize)
{
case 64_KB:
if(!(addr >= romStart && addr <= 0x0FFFF))
return true;
break;
case 128_KB:
if(!(addr >= romStart && addr <= 0x1FFFF))
return true;
break;
case 256_KB:
if(!(addr >= romStart && addr <= 0x3FFFF))
return true;
break;
case 512_KB:
if(!(addr >= romStart && addr <= 0x7FFFF))
return true;
break;
default: // assuming 32 KB
if(!(addr >= romStart && addr <= 0x07FFF))
return true;
break;
}
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Thumbulator::isInvalidRAM(uInt32 addr)
{
// Note: addr is already checked for RAM (0x4xxxxxxx)
switch(romSize)
{
case 64_KB:
case 128_KB:
if(addr > 0x40003fff)
return true;
break;
case 256_KB:
case 512_KB:
if(addr > 0x40007fff)
return true;
break;
default: // assuming 32 KB
if(addr > 0x40001fff)
return true;
break;
}
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Thumbulator::isProtectedRAM(uInt32 addr)
{ {
// Protected is within the driver RAM. // Protected is within the driver RAM.
// For CDF variations parts of the driver RAM are reused to hold the // For CDF variations parts of the driver RAM are reused to hold the
// datastream information, so is not protected. // datastream information, so are not write protected.
// Additionally for CDFJ+ the Fast Fetcher offset is not write protected. // Additionally for CDFJ+ the Fast Fetcher offset is not write protected.
if (addr < 0x40000000) return false; if (addr < 0x40000000) return false;
addr -= 0x40000000; addr -= 0x40000000;
switch (configuration) { switch(configuration) {
case ConfigureFor::DPCplus: case ConfigureFor::DPCplus:
return (addr < 0x0c00) && (addr > 0x0028); return (addr < 0x0c00) && (addr > 0x0028);
case ConfigureFor::CDF: case ConfigureFor::CDF:
return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x06e0) && (addr < (0x0e60 + 284))); return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x06e0) && (addr < (0x0e60 + 284)));
case ConfigureFor::CDF1: case ConfigureFor::CDF1:
return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x00a0) && (addr < (0x00a0 + 284))); return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x00a0) && (addr < (0x00a0 + 284)));
case ConfigureFor::CDFJ: case ConfigureFor::CDFJ:
return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x0098) && (addr < (0x0098 + 292))); return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x0098) && (addr < (0x0098 + 292)));
case ConfigureFor::CDFJplus: case ConfigureFor::CDFJplus:
return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x0098) && (addr < (0x0098 + 292))) && addr != 0x3E0; return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x0098) && (addr < (0x0098 + 292))) && addr != 0x3E0;
case ConfigureFor::BUS: case ConfigureFor::BUS:
return (addr < 0x06d8) && (addr > 0x0028); return (addr < 0x06d8) && (addr > 0x0028);
} }
return false; return false;
@ -585,10 +646,6 @@ uInt32 Thumbulator::read16(uInt32 addr)
{ {
uInt32 data; uInt32 data;
#ifndef UNSAFE_OPTIMIZATIONS #ifndef UNSAFE_OPTIMIZATIONS
if((addr > 0x40007fff) && (addr < 0x50000000))
fatalError("read16", addr, "abort - out of range");
else if((addr > 0x0007ffff) && (addr < 0x10000000))
fatalError("read16", addr, "abort - out of range");
if(addr & 1) if(addr & 1)
fatalError("read16", addr, "abort - misaligned"); fatalError("read16", addr, "abort - misaligned");
#endif #endif
@ -599,6 +656,10 @@ uInt32 Thumbulator::read16(uInt32 addr)
switch(addr & 0xF0000000) switch(addr & 0xF0000000)
{ {
case 0x00000000: //ROM case 0x00000000: //ROM
#ifndef UNSAFE_OPTIMIZATIONS
if(isInvalidROM(addr))
fatalError("read16", addr, "abort - out of range");
#endif
addr &= ROMADDMASK; addr &= ROMADDMASK;
addr >>= 1; addr >>= 1;
data = CONV_RAMROM(rom[addr]); data = CONV_RAMROM(rom[addr]);
@ -606,6 +667,10 @@ uInt32 Thumbulator::read16(uInt32 addr)
return data; return data;
case 0x40000000: //RAM case 0x40000000: //RAM
#ifndef UNSAFE_OPTIMIZATIONS
if(isInvalidRAM(addr))
fatalError("read16", addr, "abort - out of range");
#endif
addr &= RAMADDMASK; addr &= RAMADDMASK;
addr >>= 1; addr >>= 1;
data = CONV_RAMROM(ram[addr]); data = CONV_RAMROM(ram[addr]);
@ -641,7 +706,20 @@ uInt32 Thumbulator::read32(uInt32 addr)
switch(addr & 0xF0000000) switch(addr & 0xF0000000)
{ {
case 0x00000000: //ROM case 0x00000000: //ROM
#ifndef UNSAFE_OPTIMIZATIONS
if(isInvalidROM(addr))
fatalError("read32", addr, "abort - out of range");
#endif
data = read16(addr+0);
data |= (uInt32(read16(addr+2))) << 16;
DO_DBUG(statusMsg << "read32(" << Base::HEX8 << addr << ")=" << Base::HEX8 << data << endl);
return data;
case 0x40000000: //RAM case 0x40000000: //RAM
#ifndef UNSAFE_OPTIMIZATIONS
if(isInvalidRAM(addr))
fatalError("read32", addr, "abort - out of range");
#endif
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);

View File

@ -228,7 +228,9 @@ class Thumbulator
uInt32 read16(uInt32 addr); uInt32 read16(uInt32 addr);
uInt32 read32(uInt32 addr); uInt32 read32(uInt32 addr);
#ifndef UNSAFE_OPTIMIZATIONS #ifndef UNSAFE_OPTIMIZATIONS
bool isProtected(uInt32 addr); bool isInvalidROM(uInt32 addr);
bool isInvalidRAM(uInt32 addr);
bool isProtectedRAM(uInt32 addr);
#endif #endif
void write16(uInt32 addr, uInt32 data); void write16(uInt32 addr, uInt32 data);
void write32(uInt32 addr, uInt32 data); void write32(uInt32 addr, uInt32 data);