mirror of https://github.com/stella-emu/stella.git
enhanced range checks for Thumbulator
changed initial Thumb code stack pointer
This commit is contained in:
parent
6a74c61ac5
commit
7b1e494ca3
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue