mirror of https://github.com/stella-emu/stella.git
Implement most of vcslib.
This commit is contained in:
parent
948ad8d67e
commit
e7de075b20
|
@ -21,10 +21,10 @@
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
BusTransactionQueue::Transaction BusTransactionQueue::Transaction::transactionYield(
|
BusTransactionQueue::Transaction BusTransactionQueue::Transaction::transactionYield(
|
||||||
uInt16 address, uInt64 timestamp
|
uInt16 address, uInt64 timestamp, uInt16 mask
|
||||||
) {
|
) {
|
||||||
address &= 0x1fff;
|
address &= 0x1fff;
|
||||||
return {.address = address, .value = 0, .timestamp = timestamp, .yield = true};
|
return {.address = address, .mask = mask, .value = 0, .timestamp = timestamp, .yield = true};
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -32,7 +32,7 @@ BusTransactionQueue::Transaction BusTransactionQueue::Transaction::transactionDr
|
||||||
uInt16 address, uInt8 value, uInt64 timestamp
|
uInt16 address, uInt8 value, uInt64 timestamp
|
||||||
) {
|
) {
|
||||||
address &= 0x1fff;
|
address &= 0x1fff;
|
||||||
return {.address = address, .value = value, .timestamp = timestamp, .yield = false};
|
return {.address = address, .mask = 0xffff, .value = value, .timestamp = timestamp, .yield = false};
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -112,9 +112,9 @@ BusTransactionQueue& BusTransactionQueue::stuffByte(uInt8 value, uInt16 address)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
BusTransactionQueue& BusTransactionQueue::yield(uInt16 address)
|
BusTransactionQueue& BusTransactionQueue::yield(uInt16 address, uInt16 mask)
|
||||||
{
|
{
|
||||||
push(Transaction::transactionYield(address, myTimestamp));
|
push(Transaction::transactionYield(address, myTimestamp, mask));
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,10 @@ BusTransactionQueue::Transaction* BusTransactionQueue::getNextTransaction(uInt16
|
||||||
if (myQueueSize == 0) return nullptr;
|
if (myQueueSize == 0) return nullptr;
|
||||||
|
|
||||||
Transaction* nextTransaction = &myQueue[myQueueNext];
|
Transaction* nextTransaction = &myQueue[myQueueNext];
|
||||||
if (nextTransaction->address != (address & 0x1fff) || nextTransaction->timestamp > timestamp) return nullptr;
|
if (
|
||||||
|
nextTransaction->address != (address & 0x1fff & nextTransaction->mask) ||
|
||||||
|
nextTransaction->timestamp > timestamp
|
||||||
|
) return nullptr;
|
||||||
|
|
||||||
myQueueNext = (myQueueNext + 1) % myQueueCapacity;
|
myQueueNext = (myQueueNext + 1) % myQueueCapacity;
|
||||||
myQueueSize--;
|
myQueueSize--;
|
||||||
|
|
|
@ -23,12 +23,13 @@
|
||||||
class BusTransactionQueue {
|
class BusTransactionQueue {
|
||||||
public:
|
public:
|
||||||
struct Transaction {
|
struct Transaction {
|
||||||
static Transaction transactionYield(uInt16 address, uInt64 timestamp);
|
static Transaction transactionYield(uInt16 address, uInt64 timestamp, uInt16 mask);
|
||||||
static Transaction transactionDrive(uInt16 address, uInt8 value, uInt64 timestamp);
|
static Transaction transactionDrive(uInt16 address, uInt8 value, uInt64 timestamp);
|
||||||
|
|
||||||
void setBusState(bool& drive, uInt8& value) const;
|
void setBusState(bool& drive, uInt8& value) const;
|
||||||
|
|
||||||
uInt16 address{0};
|
uInt16 address{0};
|
||||||
|
uInt16 mask{0xffff};
|
||||||
uInt8 value{0};
|
uInt8 value{0};
|
||||||
uInt64 timestamp{0};
|
uInt64 timestamp{0};
|
||||||
bool yield{false};
|
bool yield{false};
|
||||||
|
@ -48,7 +49,7 @@ class BusTransactionQueue {
|
||||||
BusTransactionQueue& injectROMAt(uInt8 value, uInt16 address);
|
BusTransactionQueue& injectROMAt(uInt8 value, uInt16 address);
|
||||||
BusTransactionQueue& stuffByte(uInt8 value, uInt16 address);
|
BusTransactionQueue& stuffByte(uInt8 value, uInt16 address);
|
||||||
|
|
||||||
BusTransactionQueue& yield(uInt16 address);
|
BusTransactionQueue& yield(uInt16 address, uInt16 mask = 0xffff);
|
||||||
|
|
||||||
bool hasPendingTransaction() const;
|
bool hasPendingTransaction() const;
|
||||||
Transaction* getNextTransaction(uInt16 address, uInt64 timestamp);
|
Transaction* getNextTransaction(uInt16 address, uInt64 timestamp);
|
||||||
|
|
|
@ -176,6 +176,15 @@ void VcsLib::vcsLda2(uInt8 value)
|
||||||
.injectROM(value);
|
.injectROM(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CortexM0::err_t VcsLib::stackOperation(uInt16& value, uInt8& op, uInt8 opcode)
|
||||||
|
{
|
||||||
|
myTransactionQueue
|
||||||
|
.injectROM(opcode)
|
||||||
|
.yield(0, 0x1000);
|
||||||
|
|
||||||
|
return returnFromStub(value, op);
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, CortexM0& cortex)
|
CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, CortexM0& cortex)
|
||||||
{
|
{
|
||||||
|
@ -244,7 +253,17 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex
|
||||||
return returnFromStub(value, op);
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_WRITE6:
|
case ADDR_VCS_WRITE6:
|
||||||
FatalEmulationError::raise("unimplemented: vcsWrite6");
|
arg = cortex.getRegister(0);
|
||||||
|
|
||||||
|
myTransactionQueue
|
||||||
|
.injectROM(0xa9)
|
||||||
|
.injectROM(cortex.getRegister(1))
|
||||||
|
.injectROM(0x8d)
|
||||||
|
.injectROM(arg)
|
||||||
|
.injectROM(arg >> 8)
|
||||||
|
.yield(arg);
|
||||||
|
|
||||||
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_LDA2:
|
case ADDR_VCS_LDA2:
|
||||||
vcsLda2(cortex.getRegister(0));
|
vcsLda2(cortex.getRegister(0));
|
||||||
|
@ -265,7 +284,14 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex
|
||||||
return returnFromStub(value, op);
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_SAX3:
|
case ADDR_VCS_SAX3:
|
||||||
FatalEmulationError::raise("unimplemented: vcsSax3");
|
arg = cortex.getRegister(0);
|
||||||
|
|
||||||
|
myTransactionQueue
|
||||||
|
.injectROM(0x87)
|
||||||
|
.injectROM(arg)
|
||||||
|
.yield(arg);
|
||||||
|
|
||||||
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_STA3:
|
case ADDR_VCS_STA3:
|
||||||
arg = cortex.getRegister(0);
|
arg = cortex.getRegister(0);
|
||||||
|
@ -371,22 +397,32 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex
|
||||||
return returnFromStub(value, op);
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_TXS2:
|
case ADDR_VCS_TXS2:
|
||||||
FatalEmulationError::raise("unimplemented: vcsTx2");
|
myTransactionQueue.injectROM(0x9a);
|
||||||
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_JSR6:
|
case ADDR_VCS_JSR6:
|
||||||
FatalEmulationError::raise("unimplemented: vcsJsr6");
|
arg = cortex.getRegister(0);
|
||||||
|
|
||||||
|
myTransactionQueue
|
||||||
|
.injectROM(0x20)
|
||||||
|
.injectROM(arg)
|
||||||
|
.yield(0, 0x1000)
|
||||||
|
.injectROM(arg >> 8)
|
||||||
|
.setNextInjectAddress(arg & 0x1fff);
|
||||||
|
|
||||||
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_PHA3:
|
case ADDR_VCS_PHA3:
|
||||||
FatalEmulationError::raise("unimplemented: vcsPha3");
|
return stackOperation(value, op, 0x48);
|
||||||
|
|
||||||
case ADDR_VCS_PHP3:
|
case ADDR_VCS_PHP3:
|
||||||
FatalEmulationError::raise("unimplemented: vcsPph3");
|
return stackOperation(value, op, 0x08);
|
||||||
|
|
||||||
case ADDR_VCS_PLA4:
|
case ADDR_VCS_PLA4:
|
||||||
FatalEmulationError::raise("unimplemented: vcsPla4");
|
return stackOperation(value, op, 0x68);
|
||||||
|
|
||||||
case ADDR_VCS_PLP4:
|
case ADDR_VCS_PLP4:
|
||||||
FatalEmulationError::raise("unimplemented: vcsPlp4");
|
return stackOperation(value, op, 0x28);
|
||||||
|
|
||||||
case ADDR_VCS_PLA4_EX:
|
case ADDR_VCS_PLA4_EX:
|
||||||
FatalEmulationError::raise("unimplemented: vcsPla4Ex");
|
FatalEmulationError::raise("unimplemented: vcsPla4Ex");
|
||||||
|
@ -395,7 +431,15 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex
|
||||||
FatalEmulationError::raise("unimplemented: vcsPlp4Ex");
|
FatalEmulationError::raise("unimplemented: vcsPlp4Ex");
|
||||||
|
|
||||||
case ADDR_VCS_JMP_TO_RAM3:
|
case ADDR_VCS_JMP_TO_RAM3:
|
||||||
FatalEmulationError::raise("unimplemented: vcsJmpToRam3");
|
arg = cortex.getRegister(0);
|
||||||
|
|
||||||
|
myTransactionQueue
|
||||||
|
.injectROM(0x4c)
|
||||||
|
.injectROM(arg)
|
||||||
|
.injectROM(arg >> 8)
|
||||||
|
.yield(arg);
|
||||||
|
|
||||||
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_WAIT_FOR_ADDRESS:
|
case ADDR_VCS_WAIT_FOR_ADDRESS:
|
||||||
FatalEmulationError::raise("unimplemented: vcsWaitForAddress");
|
FatalEmulationError::raise("unimplemented: vcsWaitForAddress");
|
||||||
|
|
|
@ -59,6 +59,8 @@ class VcsLib: public CortexM0::BusTransactionDelegate {
|
||||||
return CortexM0::ERR_NONE;
|
return CortexM0::ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CortexM0::err_t stackOperation(uInt16& value, uInt8& op, uInt8 opcode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BusTransactionQueue& myTransactionQueue;
|
BusTransactionQueue& myTransactionQueue;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue