mirror of https://github.com/stella-emu/stella.git
Stub vcslib.
This commit is contained in:
parent
9e1c416f5d
commit
5a3ec4a8bc
|
@ -176,7 +176,7 @@ namespace {
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeELF::CartridgeELF(const ByteBuffer& image, size_t size, string_view md5,
|
||||
const Settings& settings)
|
||||
: Cartridge(settings, md5), myImageSize(size)
|
||||
: Cartridge(settings, md5), myImageSize(size), myVcslibDelegate(*this)
|
||||
{
|
||||
myImage = make_unique<uInt8[]>(size);
|
||||
std::memcpy(myImage.get(), image.get(), size);
|
||||
|
@ -436,6 +436,137 @@ void CartridgeELF::BusTransactionQueue::push(const BusTransaction& transaction)
|
|||
myQueue[(myQueueNext + myQueueSize++) % TRANSACTION_QUEUE_CAPACITY] = transaction;
|
||||
}
|
||||
|
||||
CortexM0::err_t CartridgeELF::VcslibDelegate::fetch16(uInt32 address, uInt16& value, uInt8& op, CortexM0& cortex)
|
||||
{
|
||||
switch (address) {
|
||||
case ADDR_MEMSET:
|
||||
FatalEmulationError::raise("unimplemented: memset");
|
||||
|
||||
case ADDR_MEMCPY:
|
||||
FatalEmulationError::raise("unimplemented: memcpy");
|
||||
|
||||
case ADDR_VCS_LDA_FOR_BUS_STUFF2:
|
||||
FatalEmulationError::raise("unimplemented: vcsLdaForBusStuff2");
|
||||
|
||||
case ADDR_VCS_LDX_FOR_BUS_STUFF2:
|
||||
FatalEmulationError::raise("unimplemented: vcsLdxForBusStuff2");
|
||||
|
||||
case ADDR_VCS_LDY_FOR_BUS_STUFF2:
|
||||
FatalEmulationError::raise("unimplemented: vcsLdyForBusStuff2");
|
||||
|
||||
case ADDR_VCS_WRITE3:
|
||||
FatalEmulationError::raise("unimplemented: vcsWrite3");
|
||||
|
||||
case ADDR_VCS_JMP3:
|
||||
FatalEmulationError::raise("unimplemented: vcsJump3");
|
||||
|
||||
case ADDR_VCS_NOP2:
|
||||
FatalEmulationError::raise("unimplemented: vcsNop2");
|
||||
|
||||
case ADDR_VCS_NOP2N:
|
||||
FatalEmulationError::raise("unimplemented: vcsNop2n");
|
||||
|
||||
case ADDR_VCS_WRITE5:
|
||||
FatalEmulationError::raise("unimplemented: vcsWrite5");
|
||||
|
||||
case ADDR_VCS_WRITE6:
|
||||
FatalEmulationError::raise("unimplemented: vcsWrite6");
|
||||
|
||||
case ADDR_VCS_LDA2:
|
||||
FatalEmulationError::raise("unimplemented: vcsLda2");
|
||||
|
||||
case ADDR_VCS_LDX2:
|
||||
FatalEmulationError::raise("unimplemented: vcsLdx2");
|
||||
|
||||
case ADDR_VCS_LDY2:
|
||||
FatalEmulationError::raise("unimplemented: vcsLdy2");
|
||||
|
||||
case ADDR_VCS_SAX3:
|
||||
FatalEmulationError::raise("unimplemented: vcsSax3");
|
||||
|
||||
case ADDR_VCS_STA3:
|
||||
FatalEmulationError::raise("unimplemented: vcsSta3");
|
||||
|
||||
case ADDR_VCS_STX3:
|
||||
FatalEmulationError::raise("unimplemented: vcsStx3");
|
||||
|
||||
case ADDR_VCS_STY3:
|
||||
FatalEmulationError::raise("unimplemented: vcsSty3");
|
||||
|
||||
case ADDR_VCS_STA4:
|
||||
FatalEmulationError::raise("unimplemented: vcsSta4");
|
||||
|
||||
case ADDR_VCS_STX4:
|
||||
FatalEmulationError::raise("unimplemented: vcsStx4");
|
||||
|
||||
case ADDR_VCS_STY4:
|
||||
FatalEmulationError::raise("unimplemented: vcsSty4");
|
||||
|
||||
case ADDR_VCS_COPY_OVERBLANK_TO_RIOT_RAM:
|
||||
myCart.vcsCopyOverblankToRiotRam();
|
||||
return returnFromStub(value, op);
|
||||
|
||||
case ADDR_VCS_START_OVERBLANK:
|
||||
myCart.vcsStartOverblank();
|
||||
return returnFromStub(value, op);
|
||||
|
||||
case ADDR_VCS_END_OVERBLANK:
|
||||
FatalEmulationError::raise("unimplemented: vcsEndOverblank");
|
||||
|
||||
case ADDR_VCS_READ4:
|
||||
FatalEmulationError::raise("unimplemented: vcsRead4");
|
||||
|
||||
case ADDR_RANDINT:
|
||||
FatalEmulationError::raise("unimplemented: randint ");
|
||||
|
||||
case ADDR_VCS_TXS2:
|
||||
FatalEmulationError::raise("unimplemented: vcsTx2");
|
||||
|
||||
case ADDR_VCS_JSR6:
|
||||
FatalEmulationError::raise("unimplemented: vcsJsr6");
|
||||
|
||||
case ADDR_VCS_PHA3:
|
||||
FatalEmulationError::raise("unimplemented: vcsPha3");
|
||||
|
||||
case ADDR_VCS_PHP3:
|
||||
FatalEmulationError::raise("unimplemented: vcsPph3");
|
||||
|
||||
case ADDR_VCS_PLA4:
|
||||
FatalEmulationError::raise("unimplemented: vcsPla4");
|
||||
|
||||
case ADDR_VCS_PLP4:
|
||||
FatalEmulationError::raise("unimplemented: vcsPlp4");
|
||||
|
||||
case ADDR_VCS_PLA4_EX:
|
||||
FatalEmulationError::raise("unimplemented: vcsPla4Ex");
|
||||
|
||||
case ADDR_VCS_PLP4_EX:
|
||||
FatalEmulationError::raise("unimplemented: vcsPlp4Ex");
|
||||
|
||||
case ADDR_VCS_JMP_TO_RAM3:
|
||||
FatalEmulationError::raise("unimplemented: vcsJmpToRam3");
|
||||
|
||||
case ADDR_VCS_WAIT_FOR_ADDRESS:
|
||||
FatalEmulationError::raise("unimplemented: vcsWaitForAddress");
|
||||
|
||||
case ADDR_INJECT_DMA_DATA:
|
||||
FatalEmulationError::raise("unimplemented: vcsInjectDmaData");
|
||||
|
||||
default:
|
||||
return CortexM0::errIntrinsic(CortexM0::ERR_UNMAPPED_FETCH16, address);
|
||||
}
|
||||
}
|
||||
|
||||
CortexM0::err_t CartridgeELF::VcslibDelegate::returnFromStub(uInt16& value, uInt8& op)
|
||||
{
|
||||
constexpr uInt16 BX_LR = 0x7047;
|
||||
|
||||
value = BX_LR;
|
||||
op = CortexM0::decodeInstructionWord(BX_LR);
|
||||
|
||||
return CortexM0::ERR_NONE;
|
||||
}
|
||||
|
||||
void CartridgeELF::parseAndLinkElf()
|
||||
{
|
||||
ElfParser elfParser;
|
||||
|
@ -502,7 +633,9 @@ void CartridgeELF::setupMemoryMap()
|
|||
.mapRegionData(ADDR_RODATA_BASE / CortexM0::PAGE_SIZE,
|
||||
RODATA_SIZE / CortexM0::PAGE_SIZE, true, mySectionRodata.get())
|
||||
.mapRegionData(ADDR_TABLES_BASE / CortexM0::PAGE_SIZE,
|
||||
TABLES_SIZE / CortexM0::PAGE_SIZE, true, mySectionTables.get());
|
||||
TABLES_SIZE / CortexM0::PAGE_SIZE, true, mySectionTables.get())
|
||||
.mapRegionDelegate(ADDR_STUB_BASE / CortexM0::PAGE_SIZE,
|
||||
STUB_SIZE / CortexM0::PAGE_SIZE, true, &myVcslibDelegate);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -106,6 +106,21 @@ class CartridgeELF: public Cartridge {
|
|||
uInt16 myNextInjectAddress{0};
|
||||
};
|
||||
|
||||
class VcslibDelegate: public CortexM0::BusTransactionDelegate {
|
||||
public:
|
||||
VcslibDelegate(CartridgeELF& cart) : myCart(cart) {}
|
||||
|
||||
CortexM0::err_t fetch16(uInt32 address, uInt16& value, uInt8& op, CortexM0& cortex) override;
|
||||
|
||||
private:
|
||||
CortexM0::err_t returnFromStub(uInt16& value, uInt8& op);
|
||||
|
||||
private:
|
||||
CartridgeELF& myCart;
|
||||
};
|
||||
|
||||
friend VcslibDelegate;
|
||||
|
||||
private:
|
||||
void parseAndLinkElf();
|
||||
void setupMemoryMap();
|
||||
|
@ -132,6 +147,8 @@ class CartridgeELF: public Cartridge {
|
|||
unique_ptr<uInt8[]> mySectionData;
|
||||
unique_ptr<uInt8[]> mySectionRodata;
|
||||
unique_ptr<uInt8[]> mySectionTables;
|
||||
|
||||
VcslibDelegate myVcslibDelegate;
|
||||
};
|
||||
|
||||
#endif // CARTRIDGE_ELF
|
||||
|
|
|
@ -397,10 +397,40 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
CortexM0::err_t CortexM0::BusTransactionDelegate::read32(uInt32 address, uInt32& value, CortexM0& cortex)
|
||||
{
|
||||
return errIntrinsic(ERR_UNMAPPED_READ32, address);
|
||||
}
|
||||
|
||||
CortexM0::err_t CortexM0::BusTransactionDelegate::read16(uInt32 address, uInt16& value, CortexM0& cortex)
|
||||
{
|
||||
return errIntrinsic(ERR_UNMAPPED_READ16, address);
|
||||
}
|
||||
|
||||
CortexM0::err_t CortexM0::BusTransactionDelegate::read8(uInt32 address, uInt8& value, CortexM0& cortex)
|
||||
{
|
||||
return errIntrinsic(ERR_UNMAPPED_READ8, address);
|
||||
}
|
||||
|
||||
CortexM0::err_t CortexM0::BusTransactionDelegate::write32(uInt32 address, uInt32 value, CortexM0& cortex)
|
||||
{
|
||||
return errIntrinsic(ERR_UNMAPPED_WRITE32, address);
|
||||
}
|
||||
|
||||
CortexM0::err_t CortexM0::BusTransactionDelegate::write16(uInt32 address, uInt16 value, CortexM0& cortex)
|
||||
{
|
||||
return errIntrinsic(ERR_UNMAPPED_WRITE16, address);
|
||||
}
|
||||
|
||||
CortexM0::err_t CortexM0::BusTransactionDelegate::write8(uInt32 address, uInt8 value, CortexM0& cortex)
|
||||
{
|
||||
return errIntrinsic(ERR_UNMAPPED_WRITE8, address);
|
||||
}
|
||||
|
||||
CortexM0::err_t CortexM0::BusTransactionDelegate::fetch16(
|
||||
uInt32 address, uInt16& value, uInt8& op
|
||||
uInt32 address, uInt16& value, uInt8& op, CortexM0& cortex
|
||||
) {
|
||||
const err_t err = read16(address, value);
|
||||
const err_t err = read16(address, value, cortex);
|
||||
if (err) return err;
|
||||
|
||||
op = decodeInstructionWord(value);
|
||||
|
@ -537,7 +567,7 @@ CortexM0::err_t CortexM0::read32(uInt32 address, uInt32& value)
|
|||
|
||||
switch (region.type) {
|
||||
case MemoryRegionType::delegate:
|
||||
return region.access.delegate->read32(address, value);
|
||||
return region.access.delegate->read32(address, value, *this);
|
||||
|
||||
case MemoryRegionType::directCode:
|
||||
value = READ32(region.access.accessCode.backingStore, address - region.base);
|
||||
|
@ -549,7 +579,7 @@ CortexM0::err_t CortexM0::read32(uInt32 address, uInt32& value)
|
|||
|
||||
default:
|
||||
return myDefaultDelegate ?
|
||||
myDefaultDelegate->read32(address, value) : errIntrinsic(ERR_UNMAPPED_ACCESS, address);
|
||||
myDefaultDelegate->read32(address, value, *this) : errIntrinsic(ERR_UNMAPPED_READ32, address);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -561,7 +591,7 @@ CortexM0::err_t CortexM0::read16(uInt32 address, uInt16& value)
|
|||
|
||||
switch (region.type) {
|
||||
case MemoryRegionType::delegate:
|
||||
return region.access.delegate->read16(address, value);
|
||||
return region.access.delegate->read16(address, value, *this);
|
||||
|
||||
case MemoryRegionType::directCode:
|
||||
value = READ16(region.access.accessCode.backingStore, address - region.base);
|
||||
|
@ -573,7 +603,7 @@ CortexM0::err_t CortexM0::read16(uInt32 address, uInt16& value)
|
|||
|
||||
default:
|
||||
return myDefaultDelegate ?
|
||||
myDefaultDelegate->read16(address, value) : errIntrinsic(ERR_UNMAPPED_ACCESS, address);
|
||||
myDefaultDelegate->read16(address, value, *this) : errIntrinsic(ERR_UNMAPPED_READ16, address);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -583,7 +613,7 @@ CortexM0::err_t CortexM0::read8(uInt32 address, uInt8& value)
|
|||
|
||||
switch (region.type) {
|
||||
case MemoryRegionType::delegate:
|
||||
return region.access.delegate->read8(address, value);
|
||||
return region.access.delegate->read8(address, value, *this);
|
||||
|
||||
case MemoryRegionType::directCode:
|
||||
value = region.access.accessCode.backingStore[address - region.base];
|
||||
|
@ -595,7 +625,7 @@ CortexM0::err_t CortexM0::read8(uInt32 address, uInt8& value)
|
|||
|
||||
default:
|
||||
return myDefaultDelegate ?
|
||||
myDefaultDelegate->read8(address, value) : errIntrinsic(ERR_UNMAPPED_ACCESS, address);
|
||||
myDefaultDelegate->read8(address, value, *this) : errIntrinsic(ERR_UNMAPPED_READ8, address);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -608,7 +638,7 @@ CortexM0::err_t CortexM0::write32(uInt32 address, uInt32 value)
|
|||
|
||||
switch (region.type) {
|
||||
case MemoryRegionType::delegate:
|
||||
return region.access.delegate->write32(address, value);
|
||||
return region.access.delegate->write32(address, value, *this);
|
||||
|
||||
case MemoryRegionType::directCode:
|
||||
WRITE32(region.access.accessCode.backingStore, address - region.base, value);
|
||||
|
@ -620,7 +650,7 @@ CortexM0::err_t CortexM0::write32(uInt32 address, uInt32 value)
|
|||
|
||||
default:
|
||||
return myDefaultDelegate ?
|
||||
myDefaultDelegate->write32(address, value) : errIntrinsic(ERR_UNMAPPED_ACCESS, address);
|
||||
myDefaultDelegate->write32(address, value, *this) : errIntrinsic(ERR_UNMAPPED_WRITE32, address);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -633,7 +663,7 @@ CortexM0::err_t CortexM0::write16(uInt32 address, uInt16 value)
|
|||
|
||||
switch (region.type) {
|
||||
case MemoryRegionType::delegate:
|
||||
return region.access.delegate->write16(address, value);
|
||||
return region.access.delegate->write16(address, value, *this);
|
||||
|
||||
case MemoryRegionType::directCode: {
|
||||
const uInt32 offset = address - region.base;
|
||||
|
@ -650,7 +680,7 @@ CortexM0::err_t CortexM0::write16(uInt32 address, uInt16 value)
|
|||
|
||||
default:
|
||||
return myDefaultDelegate ?
|
||||
myDefaultDelegate->write16(address, value) : errIntrinsic(ERR_UNMAPPED_ACCESS, address);
|
||||
myDefaultDelegate->write16(address, value, *this) : errIntrinsic(ERR_UNMAPPED_WRITE16, address);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -663,7 +693,7 @@ CortexM0::err_t CortexM0::write8(uInt32 address, uInt8 value)
|
|||
|
||||
switch (region.type) {
|
||||
case MemoryRegionType::delegate:
|
||||
return region.access.delegate->write8(address, value);
|
||||
return region.access.delegate->write8(address, value, *this);
|
||||
|
||||
case MemoryRegionType::directCode: {
|
||||
const uInt32 offset = address - region.base;
|
||||
|
@ -680,7 +710,7 @@ CortexM0::err_t CortexM0::write8(uInt32 address, uInt8 value)
|
|||
|
||||
default:
|
||||
return myDefaultDelegate ?
|
||||
myDefaultDelegate->write8(address, value) : errIntrinsic(ERR_UNMAPPED_ACCESS, address);
|
||||
myDefaultDelegate->write8(address, value, *this) : errIntrinsic(ERR_UNMAPPED_WRITE8, address);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -692,7 +722,7 @@ CortexM0::err_t CortexM0::fetch16(uInt32 address, uInt16& value, uInt8& op)
|
|||
|
||||
switch (region.type) {
|
||||
case MemoryRegionType::delegate:
|
||||
return region.access.delegate->fetch16(address, value, op);
|
||||
return region.access.delegate->fetch16(address, value, op, *this);
|
||||
|
||||
case MemoryRegionType::directCode: {
|
||||
const uInt32 offset = address - region.base;
|
||||
|
@ -711,7 +741,7 @@ CortexM0::err_t CortexM0::fetch16(uInt32 address, uInt16& value, uInt8& op)
|
|||
|
||||
default:
|
||||
return myDefaultDelegate ?
|
||||
myDefaultDelegate->fetch16(address, value, op) : errIntrinsic(ERR_UNMAPPED_ACCESS, address);
|
||||
myDefaultDelegate->fetch16(address, value, op, *this) : errIntrinsic(ERR_UNMAPPED_FETCH16, address);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,28 +34,34 @@ class CortexM0
|
|||
public:
|
||||
virtual ~BusTransactionDelegate() = default;
|
||||
|
||||
virtual err_t read32(uInt32 address, uInt32& value) = 0;
|
||||
virtual err_t read16(uInt32 address, uInt16& value) = 0;
|
||||
virtual err_t read8(uInt32 address, uInt8& value) = 0;
|
||||
virtual err_t read32(uInt32 address, uInt32& value, CortexM0& cortex);
|
||||
virtual err_t read16(uInt32 address, uInt16& value, CortexM0& cortex);
|
||||
virtual err_t read8(uInt32 address, uInt8& value, CortexM0& cortex);
|
||||
|
||||
virtual err_t write32(uInt32 address, uInt32 value) = 0;
|
||||
virtual err_t write16(uInt32 address, uInt16 value) = 0;
|
||||
virtual err_t write8(uInt32 address, uInt8 value) = 0;
|
||||
virtual err_t write32(uInt32 address, uInt32 value, CortexM0& cortex);
|
||||
virtual err_t write16(uInt32 address, uInt16 value, CortexM0& cortex);
|
||||
virtual err_t write8(uInt32 address, uInt8 value, CortexM0& cortex);
|
||||
|
||||
virtual err_t fetch16(uInt32 address, uInt16& value, uInt8& op);
|
||||
virtual err_t fetch16(uInt32 address, uInt16& value, uInt8& op, CortexM0& cortex);
|
||||
};
|
||||
|
||||
static constexpr uInt32 PAGE_SIZE = 4096;
|
||||
|
||||
static constexpr err_t ERR_NONE = 0;
|
||||
static constexpr err_t ERR_UNMAPPED_ACCESS = 1;
|
||||
static constexpr err_t ERR_WRITE_ACCESS_DENIED = 2;
|
||||
static constexpr err_t ERR_ACCESS_ALIGNMENT_FAULT = 3;
|
||||
static constexpr err_t ERR_BKPT = 4;
|
||||
static constexpr err_t ERR_INVALID_OPERATING_MODE = 5;
|
||||
static constexpr err_t ERR_UNIMPLEMENTED_INST = 6;
|
||||
static constexpr err_t ERR_SWI = 7;
|
||||
static constexpr err_t ERR_UNDEFINED_INST = 8;
|
||||
static constexpr err_t ERR_UNMAPPED_READ32 = 1;
|
||||
static constexpr err_t ERR_UNMAPPED_READ16 = 2;
|
||||
static constexpr err_t ERR_UNMAPPED_READ8 = 3;
|
||||
static constexpr err_t ERR_UNMAPPED_WRITE32 = 4;
|
||||
static constexpr err_t ERR_UNMAPPED_WRITE16 = 5;
|
||||
static constexpr err_t ERR_UNMAPPED_WRITE8 = 6;
|
||||
static constexpr err_t ERR_UNMAPPED_FETCH16 = 7;
|
||||
static constexpr err_t ERR_WRITE_ACCESS_DENIED = 8;
|
||||
static constexpr err_t ERR_ACCESS_ALIGNMENT_FAULT = 9;
|
||||
static constexpr err_t ERR_BKPT = 10;
|
||||
static constexpr err_t ERR_INVALID_OPERATING_MODE = 11;
|
||||
static constexpr err_t ERR_UNIMPLEMENTED_INST = 12;
|
||||
static constexpr err_t ERR_SWI = 13;
|
||||
static constexpr err_t ERR_UNDEFINED_INST = 14;
|
||||
|
||||
static inline bool isErrCustom(err_t err) {
|
||||
return (err & 0xff) == 0;
|
||||
|
|
Loading…
Reference in New Issue