mirror of https://github.com/stella-emu/stella.git
Implement init function, more vcslib -> mattress monkeys works.
This commit is contained in:
parent
1f0ca7539d
commit
ead6675e6d
|
@ -235,7 +235,10 @@ void CartridgeELF::reset()
|
||||||
myVcsLib.vcsEndOverblank();
|
myVcsLib.vcsEndOverblank();
|
||||||
myVcsLib.vcsNop2n(1024);
|
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);
|
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
|
inline uInt64 CartridgeELF::getArmCycles() const
|
||||||
{
|
{
|
||||||
return myCortexEmu.getCycles() + myArmCyclesOffset;
|
return myCortexEmu.getCycles() + myArmCyclesOffset;
|
||||||
|
@ -418,7 +429,8 @@ void CartridgeELF::setupMemoryMap()
|
||||||
.mapRegionData(ADDR_TABLES_BASE / CortexM0::PAGE_SIZE,
|
.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,
|
.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");
|
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");
|
if (err) throw runtime_error("unable to setup main args");
|
||||||
|
|
||||||
myCortexEmu
|
callFn(myArmEntrypoint, sp);
|
||||||
.setRegister(0, sp )
|
|
||||||
.setRegister(13, sp)
|
|
||||||
.setRegister(14, RETURN_ADDR_MAIN)
|
|
||||||
.setPc(myArmEntrypoint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CartridgeELF::runArm()
|
void CartridgeELF::runArm()
|
||||||
|
@ -496,8 +544,20 @@ void CartridgeELF::runArm()
|
||||||
|
|
||||||
const CortexM0::err_t err = myCortexEmu.run(cyclesGoal, cycles);
|
const CortexM0::err_t err = myCortexEmu.run(cyclesGoal, cycles);
|
||||||
|
|
||||||
if (err && (CortexM0::getErrCustom(err) != ERR_STOP_EXECUTION))
|
if (err) {
|
||||||
FatalEmulationError::raise("error executing ARM code: " + CortexM0::describeError(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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,15 @@ class CartridgeELF: public Cartridge {
|
||||||
|
|
||||||
bool doesBusStuffing() override { return true; }
|
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:
|
private:
|
||||||
uInt64 getArmCycles() const;
|
uInt64 getArmCycles() const;
|
||||||
|
|
||||||
|
@ -76,7 +85,10 @@ class CartridgeELF: public Cartridge {
|
||||||
|
|
||||||
uInt32 getCoreClock() const;
|
uInt32 getCoreClock() const;
|
||||||
uInt32 getSystemType() const;
|
uInt32 getSystemType() const;
|
||||||
void jumpToMain();
|
|
||||||
|
void switchExecutionStage();
|
||||||
|
void callFn(uInt32 ptr, uInt32 sp);
|
||||||
|
void callMain();
|
||||||
|
|
||||||
void runArm();
|
void runArm();
|
||||||
|
|
||||||
|
@ -104,11 +116,15 @@ class CartridgeELF: public Cartridge {
|
||||||
unique_ptr<uInt8[]> mySectionTables;
|
unique_ptr<uInt8[]> mySectionTables;
|
||||||
|
|
||||||
VcsLib myVcsLib;
|
VcsLib myVcsLib;
|
||||||
|
BusFallbackDelegate myFallbackDelegate;
|
||||||
|
|
||||||
ConsoleTiming myConsoleTiming{ConsoleTiming::ntsc};
|
ConsoleTiming myConsoleTiming{ConsoleTiming::ntsc};
|
||||||
uInt32 myArmCyclesPer6502Cycle{80};
|
uInt32 myArmCyclesPer6502Cycle{80};
|
||||||
|
|
||||||
Int64 myArmCyclesOffset{0};
|
Int64 myArmCyclesOffset{0};
|
||||||
|
|
||||||
|
ExecutionStage myExecutionStage{ExecutionStage::boot};
|
||||||
|
uInt32 myInitFunctionIndex{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CARTRIDGE_ELF
|
#endif // CARTRIDGE_ELF
|
||||||
|
|
|
@ -110,9 +110,10 @@ namespace elfEnvironment {
|
||||||
constexpr uInt32 ST_PAL_2600 = 1;
|
constexpr uInt32 ST_PAL_2600 = 1;
|
||||||
constexpr uInt32 ST_PAL60_2600 = 2;
|
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_STOP_EXECUTION = 1;
|
||||||
|
constexpr uInt32 ERR_RETURN = 2;
|
||||||
|
|
||||||
constexpr uInt32 QUEUE_SIZE_LIMIT = 10;
|
constexpr uInt32 QUEUE_SIZE_LIMIT = 10;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#include "VcsLib.hxx"
|
#include "VcsLib.hxx"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
#include "BusTransactionQueue.hxx"
|
#include "BusTransactionQueue.hxx"
|
||||||
#include "ElfEnvironment.hxx"
|
#include "ElfEnvironment.hxx"
|
||||||
#include "exception/FatalEmulationError.hxx"
|
#include "exception/FatalEmulationError.hxx"
|
||||||
|
@ -363,7 +365,8 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex
|
||||||
}
|
}
|
||||||
|
|
||||||
case ADDR_RANDINT:
|
case ADDR_RANDINT:
|
||||||
FatalEmulationError::raise("unimplemented: randint ");
|
cortex.setRegister(0, rand());
|
||||||
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_TXS2:
|
case ADDR_VCS_TXS2:
|
||||||
FatalEmulationError::raise("unimplemented: vcsTx2");
|
FatalEmulationError::raise("unimplemented: vcsTx2");
|
||||||
|
|
Loading…
Reference in New Issue