mirror of https://github.com/stella-emu/stella.git
More fixes, implement more parts of vcslib.
This commit is contained in:
parent
e0ce387c9f
commit
7bc095e130
|
@ -791,8 +791,6 @@ CortexM0::err_t CortexM0::write16(uInt32 address, uInt16 value)
|
||||||
|
|
||||||
CortexM0::err_t CortexM0::write8(uInt32 address, uInt8 value)
|
CortexM0::err_t CortexM0::write8(uInt32 address, uInt8 value)
|
||||||
{
|
{
|
||||||
if (address & 0x01) return errIntrinsic(ERR_ACCESS_ALIGNMENT_FAULT, address);
|
|
||||||
|
|
||||||
MemoryRegion& region = myRegions[myPageMap[address / PAGE_SIZE]];
|
MemoryRegion& region = myRegions[myPageMap[address / PAGE_SIZE]];
|
||||||
if (region.readOnly) return errIntrinsic(ERR_WRITE_ACCESS_DENIED, address);
|
if (region.readOnly) return errIntrinsic(ERR_WRITE_ACCESS_DENIED, address);
|
||||||
|
|
||||||
|
@ -869,6 +867,10 @@ CortexM0::err_t CortexM0::execute(uInt16 inst, uInt8 op)
|
||||||
{
|
{
|
||||||
uInt32 sp, ra, rb, rc, rm, rd, rn, rs; // NOLINT
|
uInt32 sp, ra, rb, rc, rm, rd, rn, rs; // NOLINT
|
||||||
|
|
||||||
|
#ifdef THUMB_DISS
|
||||||
|
cout << "0x" << std::hex << std::setw(8) << std::setfill('0') << (read_register(15) - 4) << " " << std::dec;
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (static_cast<Op>(op)) {
|
switch (static_cast<Op>(op)) {
|
||||||
//ADC
|
//ADC
|
||||||
case Op::adc: {
|
case Op::adc: {
|
||||||
|
@ -1085,60 +1087,70 @@ CortexM0::err_t CortexM0::execute(uInt16 inst, uInt8 op)
|
||||||
}
|
}
|
||||||
|
|
||||||
case Op::bne: {
|
case Op::bne: {
|
||||||
|
DO_DISS("bne 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||||
if(znFlags)
|
if(znFlags)
|
||||||
write_register(15, branch_target_9(inst));
|
write_register(15, branch_target_9(inst));
|
||||||
return ERR_NONE;
|
return ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Op::bcs: {
|
case Op::bcs: {
|
||||||
|
DO_DISS("bcs 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||||
if(cFlag)
|
if(cFlag)
|
||||||
write_register(15, branch_target_9(inst));
|
write_register(15, branch_target_9(inst));
|
||||||
return ERR_NONE;
|
return ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Op::bcc: {
|
case Op::bcc: {
|
||||||
|
DO_DISS("bcc 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||||
if(!cFlag)
|
if(!cFlag)
|
||||||
write_register(15, branch_target_9(inst));
|
write_register(15, branch_target_9(inst));
|
||||||
return ERR_NONE;
|
return ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Op::bmi: {
|
case Op::bmi: {
|
||||||
|
DO_DISS("bmi 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||||
if(znFlags & 0x80000000)
|
if(znFlags & 0x80000000)
|
||||||
write_register(15, branch_target_9(inst));
|
write_register(15, branch_target_9(inst));
|
||||||
return ERR_NONE;
|
return ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Op::bpl: {
|
case Op::bpl: {
|
||||||
|
DO_DISS("bpl 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||||
if(!(znFlags & 0x80000000))
|
if(!(znFlags & 0x80000000))
|
||||||
write_register(15, branch_target_9(inst));
|
write_register(15, branch_target_9(inst));
|
||||||
return ERR_NONE;
|
return ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Op::bvs: {
|
case Op::bvs: {
|
||||||
|
DO_DISS("bvs 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||||
if(vFlag)
|
if(vFlag)
|
||||||
write_register(15, branch_target_9(inst));
|
write_register(15, branch_target_9(inst));
|
||||||
return ERR_NONE;
|
return ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Op::bvc: {
|
case Op::bvc: {
|
||||||
|
DO_DISS("bvc 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||||
if(!vFlag)
|
if(!vFlag)
|
||||||
write_register(15, branch_target_9(inst));
|
write_register(15, branch_target_9(inst));
|
||||||
return ERR_NONE;
|
return ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Op::bhi: {
|
case Op::bhi: {
|
||||||
|
DO_DISS("bhi 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||||
if(cFlag && znFlags)
|
if(cFlag && znFlags)
|
||||||
write_register(15, branch_target_9(inst));
|
write_register(15, branch_target_9(inst));
|
||||||
return ERR_NONE;
|
return ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Op::bls: {
|
case Op::bls: {
|
||||||
|
DO_DISS("bls 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||||
if(!znFlags || !cFlag)
|
if(!znFlags || !cFlag)
|
||||||
write_register(15, branch_target_9(inst));
|
write_register(15, branch_target_9(inst));
|
||||||
return ERR_NONE;
|
return ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Op::bge: {
|
case Op::bge: {
|
||||||
|
DO_DISS("bge 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||||
if(((znFlags & 0x80000000) && vFlag) ||
|
if(((znFlags & 0x80000000) && vFlag) ||
|
||||||
((!(znFlags & 0x80000000)) && !vFlag))
|
((!(znFlags & 0x80000000)) && !vFlag))
|
||||||
write_register(15, branch_target_9(inst));
|
write_register(15, branch_target_9(inst));
|
||||||
|
@ -1146,6 +1158,7 @@ CortexM0::err_t CortexM0::execute(uInt16 inst, uInt8 op)
|
||||||
}
|
}
|
||||||
|
|
||||||
case Op::blt: {
|
case Op::blt: {
|
||||||
|
DO_DISS("blt 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||||
if((!(znFlags & 0x80000000) && vFlag) ||
|
if((!(znFlags & 0x80000000) && vFlag) ||
|
||||||
(((znFlags & 0x80000000)) && !vFlag))
|
(((znFlags & 0x80000000)) && !vFlag))
|
||||||
write_register(15, branch_target_9(inst));
|
write_register(15, branch_target_9(inst));
|
||||||
|
@ -1153,6 +1166,7 @@ CortexM0::err_t CortexM0::execute(uInt16 inst, uInt8 op)
|
||||||
}
|
}
|
||||||
|
|
||||||
case Op::bgt: {
|
case Op::bgt: {
|
||||||
|
DO_DISS("bgt 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||||
if(znFlags)
|
if(znFlags)
|
||||||
{
|
{
|
||||||
if(((znFlags & 0x80000000) && vFlag) ||
|
if(((znFlags & 0x80000000) && vFlag) ||
|
||||||
|
@ -1163,6 +1177,7 @@ CortexM0::err_t CortexM0::execute(uInt16 inst, uInt8 op)
|
||||||
}
|
}
|
||||||
|
|
||||||
case Op::ble: {
|
case Op::ble: {
|
||||||
|
DO_DISS("ble 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||||
if(!znFlags ||
|
if(!znFlags ||
|
||||||
(!(znFlags & 0x80000000) && vFlag) ||
|
(!(znFlags & 0x80000000) && vFlag) ||
|
||||||
(((znFlags & 0x80000000)) && !vFlag))
|
(((znFlags & 0x80000000)) && !vFlag))
|
||||||
|
@ -1172,6 +1187,7 @@ CortexM0::err_t CortexM0::execute(uInt16 inst, uInt8 op)
|
||||||
|
|
||||||
//B(2) unconditional branch
|
//B(2) unconditional branch
|
||||||
case Op::b2: {
|
case Op::b2: {
|
||||||
|
DO_DISS("b 0x" << Base::HEX8 << branch_target_12(inst) << "\n");
|
||||||
write_register(15, branch_target_12(inst));
|
write_register(15, branch_target_12(inst));
|
||||||
return ERR_NONE;
|
return ERR_NONE;
|
||||||
}
|
}
|
||||||
|
@ -1196,7 +1212,7 @@ CortexM0::err_t CortexM0::execute(uInt16 inst, uInt8 op)
|
||||||
// (bl, blx_thumb)
|
// (bl, blx_thumb)
|
||||||
case Op::bl: {
|
case Op::bl: {
|
||||||
// branch to label
|
// branch to label
|
||||||
DO_DISS('\n');
|
DO_DISS("bkpt\n");
|
||||||
rb = inst & ((1 << 11) - 1);
|
rb = inst & ((1 << 11) - 1);
|
||||||
if(rb & 1 << 10) rb |= (~((1 << 11) - 1)); //sign extend
|
if(rb & 1 << 10) rb |= (~((1 << 11) - 1)); //sign extend
|
||||||
rb <<= 12;
|
rb <<= 12;
|
||||||
|
@ -1814,8 +1830,13 @@ CortexM0::err_t CortexM0::execute(uInt16 inst, uInt8 op)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((rc & 0x01) == 0) {
|
||||||
|
reg_norm = regOld;
|
||||||
|
return errIntrinsic(ERR_INVALID_OPERATING_MODE, read_register(15) - 4);
|
||||||
|
}
|
||||||
|
|
||||||
rc += 2;
|
rc += 2;
|
||||||
write_register(15, rc);
|
write_register(15, rc & ~0x01);
|
||||||
sp += 4;
|
sp += 4;
|
||||||
}
|
}
|
||||||
write_register(13, sp);
|
write_register(13, sp);
|
||||||
|
|
|
@ -23,10 +23,44 @@
|
||||||
|
|
||||||
using namespace elfEnvironment;
|
using namespace elfEnvironment;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
CortexM0::err_t memset(uInt32 target, uInt8 value, uInt32 size, CortexM0& cortex)
|
||||||
|
{
|
||||||
|
const uInt16 value16 = value | (value << 16);
|
||||||
|
const uInt32 value32 = value16 | (value16 << 16);
|
||||||
|
CortexM0::err_t err;
|
||||||
|
uInt32 ptr = target;
|
||||||
|
|
||||||
|
while (ptr < target + size) {
|
||||||
|
if ((ptr & 0x03) == 0 && size - (ptr - target) >= 4) {
|
||||||
|
err = cortex.write32(ptr, value32);
|
||||||
|
ptr += 4;
|
||||||
|
}
|
||||||
|
else if ((ptr & 0x01) == 0 && size - (ptr - target) >= 2) {
|
||||||
|
err = cortex.write16(ptr, value16);
|
||||||
|
ptr += 4;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err = cortex.write8(ptr, value);
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err) return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
VcsLib::VcsLib(BusTransactionQueue& transactionQueue) : myTransactionQueue(transactionQueue)
|
VcsLib::VcsLib(BusTransactionQueue& transactionQueue) : myTransactionQueue(transactionQueue)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
void VcsLib::reset()
|
||||||
|
{
|
||||||
|
myStuffMaskA = myStuffMaskX = myStuffMaskY = 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void VcsLib::vcsWrite5(uInt8 zpAddress, uInt8 value)
|
void VcsLib::vcsWrite5(uInt8 zpAddress, uInt8 value)
|
||||||
{
|
{
|
||||||
|
@ -75,30 +109,53 @@ void VcsLib::vcsNop2n(uInt16 n)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void VcsLib::vcsLda2(uInt8 value)
|
||||||
|
{
|
||||||
|
myTransactionQueue
|
||||||
|
.injectROM(0xa9)
|
||||||
|
.injectROM(value);
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
uInt32 arg;
|
||||||
|
CortexM0::err_t err;
|
||||||
|
|
||||||
switch (address) {
|
switch (address) {
|
||||||
case ADDR_MEMSET:
|
case ADDR_MEMSET:
|
||||||
FatalEmulationError::raise("unimplemented: memset");
|
err = memset(cortex.getRegister(0), cortex.getRegister(1), cortex.getRegister(3), cortex);
|
||||||
|
if (err) return err;
|
||||||
|
|
||||||
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_MEMCPY:
|
case ADDR_MEMCPY:
|
||||||
FatalEmulationError::raise("unimplemented: memcpy");
|
FatalEmulationError::raise("unimplemented: memcpy");
|
||||||
|
|
||||||
case ADDR_VCS_LDA_FOR_BUS_STUFF2:
|
case ADDR_VCS_LDA_FOR_BUS_STUFF2:
|
||||||
FatalEmulationError::raise("unimplemented: vcsLdaForBusStuff2");
|
vcsLda2(myStuffMaskA);
|
||||||
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_LDX_FOR_BUS_STUFF2:
|
case ADDR_VCS_LDX_FOR_BUS_STUFF2:
|
||||||
FatalEmulationError::raise("unimplemented: vcsLdxForBusStuff2");
|
vcsLda2(myStuffMaskX);
|
||||||
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_LDY_FOR_BUS_STUFF2:
|
case ADDR_VCS_LDY_FOR_BUS_STUFF2:
|
||||||
FatalEmulationError::raise("unimplemented: vcsLdyForBusStuff2");
|
vcsLda2(myStuffMaskY);
|
||||||
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_WRITE3:
|
case ADDR_VCS_WRITE3:
|
||||||
FatalEmulationError::raise("unimplemented: vcsWrite3");
|
FatalEmulationError::raise("unimplemented: vcsWrite3");
|
||||||
|
|
||||||
case ADDR_VCS_JMP3:
|
case ADDR_VCS_JMP3:
|
||||||
FatalEmulationError::raise("unimplemented: vcsJump3");
|
myTransactionQueue
|
||||||
|
.injectROM(0x4c)
|
||||||
|
.injectROM(0x00)
|
||||||
|
.injectROM(0x10)
|
||||||
|
.setNextInjectAddress(0x1000);
|
||||||
|
|
||||||
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_NOP2:
|
case ADDR_VCS_NOP2:
|
||||||
FatalEmulationError::raise("unimplemented: vcsNop2");
|
FatalEmulationError::raise("unimplemented: vcsNop2");
|
||||||
|
@ -108,13 +165,15 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex
|
||||||
return returnFromStub(value, op);
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_WRITE5:
|
case ADDR_VCS_WRITE5:
|
||||||
FatalEmulationError::raise("unimplemented: vcsWrite5");
|
vcsWrite5(cortex.getRegister(0), cortex.getRegister(1));
|
||||||
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_WRITE6:
|
case ADDR_VCS_WRITE6:
|
||||||
FatalEmulationError::raise("unimplemented: vcsWrite6");
|
FatalEmulationError::raise("unimplemented: vcsWrite6");
|
||||||
|
|
||||||
case ADDR_VCS_LDA2:
|
case ADDR_VCS_LDA2:
|
||||||
FatalEmulationError::raise("unimplemented: vcsLda2");
|
vcsLda2(cortex.getRegister(0));
|
||||||
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_LDX2:
|
case ADDR_VCS_LDX2:
|
||||||
FatalEmulationError::raise("unimplemented: vcsLdx2");
|
FatalEmulationError::raise("unimplemented: vcsLdx2");
|
||||||
|
@ -126,7 +185,14 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex
|
||||||
FatalEmulationError::raise("unimplemented: vcsSax3");
|
FatalEmulationError::raise("unimplemented: vcsSax3");
|
||||||
|
|
||||||
case ADDR_VCS_STA3:
|
case ADDR_VCS_STA3:
|
||||||
FatalEmulationError::raise("unimplemented: vcsSta3");
|
arg = cortex.getRegister(0);
|
||||||
|
|
||||||
|
myTransactionQueue
|
||||||
|
.injectROM(0x85)
|
||||||
|
.injectROM(arg)
|
||||||
|
.yield(arg);
|
||||||
|
|
||||||
|
return returnFromStub(value, op);
|
||||||
|
|
||||||
case ADDR_VCS_STX3:
|
case ADDR_VCS_STX3:
|
||||||
FatalEmulationError::raise("unimplemented: vcsStx3");
|
FatalEmulationError::raise("unimplemented: vcsStx3");
|
||||||
|
@ -202,7 +268,7 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CortexM0::err_t VcsLib::returnFromStub(uInt16& value, uInt8& op)
|
CortexM0::err_t VcsLib::returnFromStub(uInt16& value, uInt8& op)
|
||||||
{
|
{
|
||||||
constexpr uInt16 BX_LR = 0x7047;
|
constexpr uInt16 BX_LR = 0x4770;
|
||||||
|
|
||||||
value = BX_LR;
|
value = BX_LR;
|
||||||
op = CortexM0::decodeInstructionWord(BX_LR);
|
op = CortexM0::decodeInstructionWord(BX_LR);
|
||||||
|
|
|
@ -27,6 +27,8 @@ class VcsLib: public CortexM0::BusTransactionDelegate {
|
||||||
public:
|
public:
|
||||||
explicit VcsLib(BusTransactionQueue& transactionQueue);
|
explicit VcsLib(BusTransactionQueue& transactionQueue);
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
CortexM0::err_t fetch16(uInt32 address, uInt16& value, uInt8& op, CortexM0& cortex) override;
|
CortexM0::err_t fetch16(uInt32 address, uInt16& value, uInt8& op, CortexM0& cortex) override;
|
||||||
|
|
||||||
void vcsWrite5(uInt8 zpAddress, uInt8 value);
|
void vcsWrite5(uInt8 zpAddress, uInt8 value);
|
||||||
|
@ -34,6 +36,7 @@ class VcsLib: public CortexM0::BusTransactionDelegate {
|
||||||
void vcsStartOverblank();
|
void vcsStartOverblank();
|
||||||
void vcsEndOverblank();
|
void vcsEndOverblank();
|
||||||
void vcsNop2n(uInt16 n);
|
void vcsNop2n(uInt16 n);
|
||||||
|
void vcsLda2(uInt8 value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CortexM0::err_t returnFromStub(uInt16& value, uInt8& op);
|
CortexM0::err_t returnFromStub(uInt16& value, uInt8& op);
|
||||||
|
@ -41,6 +44,10 @@ class VcsLib: public CortexM0::BusTransactionDelegate {
|
||||||
private:
|
private:
|
||||||
BusTransactionQueue& myTransactionQueue;
|
BusTransactionQueue& myTransactionQueue;
|
||||||
|
|
||||||
|
uInt8 myStuffMaskA{0xff};
|
||||||
|
uInt8 myStuffMaskX{0xff};
|
||||||
|
uInt8 myStuffMaskY{0xff};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VcsLib(const VcsLib&) = delete;
|
VcsLib(const VcsLib&) = delete;
|
||||||
VcsLib(VcsLib&&) = delete;
|
VcsLib(VcsLib&&) = delete;
|
||||||
|
|
Loading…
Reference in New Issue