From 2f239d90f9080c11596ed5bd217ffdd755d87b77 Mon Sep 17 00:00:00 2001 From: Christian Speckner Date: Thu, 25 Jul 2024 23:10:05 +0200 Subject: [PATCH] Stub vcslib. --- src/emucore/CartELF.cxx | 137 ++++++++++++++++++++++++++++++++++++++- src/emucore/CartELF.hxx | 17 +++++ src/emucore/CortexM0.cxx | 62 +++++++++++++----- src/emucore/CortexM0.hxx | 36 +++++----- 4 files changed, 219 insertions(+), 33 deletions(-) diff --git a/src/emucore/CartELF.cxx b/src/emucore/CartELF.cxx index c2ec2ecde..52a005586 100644 --- a/src/emucore/CartELF.cxx +++ b/src/emucore/CartELF.cxx @@ -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(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); } diff --git a/src/emucore/CartELF.hxx b/src/emucore/CartELF.hxx index d79cdcec8..168aa28e2 100644 --- a/src/emucore/CartELF.hxx +++ b/src/emucore/CartELF.hxx @@ -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 mySectionData; unique_ptr mySectionRodata; unique_ptr mySectionTables; + + VcslibDelegate myVcslibDelegate; }; #endif // CARTRIDGE_ELF diff --git a/src/emucore/CortexM0.cxx b/src/emucore/CortexM0.cxx index 8fd2aecb2..3f3064906 100644 --- a/src/emucore/CortexM0.cxx +++ b/src/emucore/CortexM0.cxx @@ -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); } } diff --git a/src/emucore/CortexM0.hxx b/src/emucore/CortexM0.hxx index c83d02062..d16666123 100644 --- a/src/emucore/CortexM0.hxx +++ b/src/emucore/CortexM0.hxx @@ -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;