Implement init function, more vcslib -> mattress monkeys works.

This commit is contained in:
Christian Speckner 2024-07-29 23:13:45 +02:00
parent 1f0ca7539d
commit ead6675e6d
4 changed files with 93 additions and 13 deletions

View File

@ -235,7 +235,10 @@ void CartridgeELF::reset()
myVcsLib.vcsEndOverblank();
myVcsLib.vcsNop2n(1024);
jumpToMain();
myExecutionStage = ExecutionStage::boot;
myInitFunctionIndex = 0;
switchExecutionStage();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -314,6 +317,14 @@ uInt8 CartridgeELF::overdrivePoke(uInt16 address, uInt8 value)
return driveBus(address, value);
}
CortexM0::err_t CartridgeELF::BusFallbackDelegate::fetch16(
uInt32 address, uInt16& value, uInt8& op, CortexM0& cortex
) {
return address == (RETURN_ADDR & ~1)
? CortexM0::errCustom(ERR_RETURN)
: CortexM0::errIntrinsic(CortexM0::ERR_UNMAPPED_FETCH16, address);
}
inline uInt64 CartridgeELF::getArmCycles() const
{
return myCortexEmu.getCycles() + myArmCyclesOffset;
@ -418,7 +429,8 @@ void CartridgeELF::setupMemoryMap()
.mapRegionData(ADDR_TABLES_BASE / CortexM0::PAGE_SIZE,
TABLES_SIZE / CortexM0::PAGE_SIZE, true, mySectionTables.get())
.mapRegionDelegate(ADDR_STUB_BASE / CortexM0::PAGE_SIZE,
STUB_SIZE / CortexM0::PAGE_SIZE, true, &myVcsLib);
STUB_SIZE / CortexM0::PAGE_SIZE, true, &myVcsLib)
.mapDefault(&myFallbackDelegate);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -454,8 +466,48 @@ uInt32 CartridgeELF::getSystemType() const
}
}
void CartridgeELF::switchExecutionStage()
{
constexpr uInt32 sp = ADDR_STACK_BASE + STACK_SIZE;
if (myExecutionStage == ExecutionStage::boot) {
myExecutionStage = ExecutionStage::preinit;
myInitFunctionIndex = 0;
}
if (myExecutionStage == ExecutionStage::preinit) {
if (myInitFunctionIndex >= myLinker->getPreinitArray().size()) {
myExecutionStage = ExecutionStage::init;
myInitFunctionIndex = 0;
}
else {
return callFn(myLinker->getPreinitArray()[myInitFunctionIndex++], sp);
}
}
if (myExecutionStage == ExecutionStage::init) {
if (myInitFunctionIndex >= myLinker->getInitArray().size()) {
myExecutionStage = ExecutionStage::main;
}
else {
return callFn(myLinker->getInitArray()[myInitFunctionIndex++], sp);
}
}
callMain();
}
void CartridgeELF::callFn(uInt32 ptr, uInt32 sp)
{
myCortexEmu
.setRegister(0, sp)
.setRegister(13, sp)
.setRegister(14, RETURN_ADDR)
.setPc(ptr);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeELF::jumpToMain()
void CartridgeELF::callMain()
{
if (!mySystem) throw runtime_error("cartridge not installed");
@ -474,11 +526,7 @@ void CartridgeELF::jumpToMain()
if (err) throw runtime_error("unable to setup main args");
myCortexEmu
.setRegister(0, sp )
.setRegister(13, sp)
.setRegister(14, RETURN_ADDR_MAIN)
.setPc(myArmEntrypoint);
callFn(myArmEntrypoint, sp);
}
void CartridgeELF::runArm()
@ -496,8 +544,20 @@ void CartridgeELF::runArm()
const CortexM0::err_t err = myCortexEmu.run(cyclesGoal, cycles);
if (err && (CortexM0::getErrCustom(err) != ERR_STOP_EXECUTION))
FatalEmulationError::raise("error executing ARM code: " + CortexM0::describeError(err));
if (err) {
if (CortexM0::getErrCustom(err) == ERR_RETURN) {
if (myExecutionStage == ExecutionStage::main) {
FatalEmulationError::raise("return from elf_main");
}
else {
switchExecutionStage();
return;
}
}
if (CortexM0::getErrCustom(err) != ERR_STOP_EXECUTION)
FatalEmulationError::raise("error executing ARM code: " + CortexM0::describeError(err));
}
}

View File

@ -65,6 +65,15 @@ class CartridgeELF: public Cartridge {
bool doesBusStuffing() override { return true; }
private:
class BusFallbackDelegate: public CortexM0::BusTransactionDelegate {
CortexM0::err_t fetch16(uInt32 address, uInt16& value, uInt8& op, CortexM0& cortex);
};
enum class ExecutionStage {
boot, preinit, init, main
};
private:
uInt64 getArmCycles() const;
@ -76,7 +85,10 @@ class CartridgeELF: public Cartridge {
uInt32 getCoreClock() const;
uInt32 getSystemType() const;
void jumpToMain();
void switchExecutionStage();
void callFn(uInt32 ptr, uInt32 sp);
void callMain();
void runArm();
@ -104,11 +116,15 @@ class CartridgeELF: public Cartridge {
unique_ptr<uInt8[]> mySectionTables;
VcsLib myVcsLib;
BusFallbackDelegate myFallbackDelegate;
ConsoleTiming myConsoleTiming{ConsoleTiming::ntsc};
uInt32 myArmCyclesPer6502Cycle{80};
Int64 myArmCyclesOffset{0};
ExecutionStage myExecutionStage{ExecutionStage::boot};
uInt32 myInitFunctionIndex{0};
};
#endif // CARTRIDGE_ELF

View File

@ -110,9 +110,10 @@ namespace elfEnvironment {
constexpr uInt32 ST_PAL_2600 = 1;
constexpr uInt32 ST_PAL60_2600 = 2;
constexpr uInt32 RETURN_ADDR_MAIN = 0xffffdead;
constexpr uInt32 RETURN_ADDR = 0xffffdead;
constexpr uInt32 ERR_STOP_EXECUTION = 1;
constexpr uInt32 ERR_RETURN = 2;
constexpr uInt32 QUEUE_SIZE_LIMIT = 10;

View File

@ -17,6 +17,8 @@
#include "VcsLib.hxx"
#include <cmath>
#include "BusTransactionQueue.hxx"
#include "ElfEnvironment.hxx"
#include "exception/FatalEmulationError.hxx"
@ -363,7 +365,8 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex
}
case ADDR_RANDINT:
FatalEmulationError::raise("unimplemented: randint ");
cortex.setRegister(0, rand());
return returnFromStub(value, op);
case ADDR_VCS_TXS2:
FatalEmulationError::raise("unimplemented: vcsTx2");