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)
|
||||
{
|
||||
if (address & 0x01) return errIntrinsic(ERR_ACCESS_ALIGNMENT_FAULT, address);
|
||||
|
||||
MemoryRegion& region = myRegions[myPageMap[address / PAGE_SIZE]];
|
||||
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
|
||||
|
||||
#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)) {
|
||||
//ADC
|
||||
case Op::adc: {
|
||||
|
@ -1085,60 +1087,70 @@ CortexM0::err_t CortexM0::execute(uInt16 inst, uInt8 op)
|
|||
}
|
||||
|
||||
case Op::bne: {
|
||||
DO_DISS("bne 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||
if(znFlags)
|
||||
write_register(15, branch_target_9(inst));
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
case Op::bcs: {
|
||||
DO_DISS("bcs 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||
if(cFlag)
|
||||
write_register(15, branch_target_9(inst));
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
case Op::bcc: {
|
||||
DO_DISS("bcc 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||
if(!cFlag)
|
||||
write_register(15, branch_target_9(inst));
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
case Op::bmi: {
|
||||
DO_DISS("bmi 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||
if(znFlags & 0x80000000)
|
||||
write_register(15, branch_target_9(inst));
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
case Op::bpl: {
|
||||
DO_DISS("bpl 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||
if(!(znFlags & 0x80000000))
|
||||
write_register(15, branch_target_9(inst));
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
case Op::bvs: {
|
||||
DO_DISS("bvs 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||
if(vFlag)
|
||||
write_register(15, branch_target_9(inst));
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
case Op::bvc: {
|
||||
DO_DISS("bvc 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||
if(!vFlag)
|
||||
write_register(15, branch_target_9(inst));
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
case Op::bhi: {
|
||||
DO_DISS("bhi 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||
if(cFlag && znFlags)
|
||||
write_register(15, branch_target_9(inst));
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
case Op::bls: {
|
||||
DO_DISS("bls 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||
if(!znFlags || !cFlag)
|
||||
write_register(15, branch_target_9(inst));
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
case Op::bge: {
|
||||
DO_DISS("bge 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||
if(((znFlags & 0x80000000) && vFlag) ||
|
||||
((!(znFlags & 0x80000000)) && !vFlag))
|
||||
write_register(15, branch_target_9(inst));
|
||||
|
@ -1146,6 +1158,7 @@ CortexM0::err_t CortexM0::execute(uInt16 inst, uInt8 op)
|
|||
}
|
||||
|
||||
case Op::blt: {
|
||||
DO_DISS("blt 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||
if((!(znFlags & 0x80000000) && vFlag) ||
|
||||
(((znFlags & 0x80000000)) && !vFlag))
|
||||
write_register(15, branch_target_9(inst));
|
||||
|
@ -1153,6 +1166,7 @@ CortexM0::err_t CortexM0::execute(uInt16 inst, uInt8 op)
|
|||
}
|
||||
|
||||
case Op::bgt: {
|
||||
DO_DISS("bgt 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||
if(znFlags)
|
||||
{
|
||||
if(((znFlags & 0x80000000) && vFlag) ||
|
||||
|
@ -1163,6 +1177,7 @@ CortexM0::err_t CortexM0::execute(uInt16 inst, uInt8 op)
|
|||
}
|
||||
|
||||
case Op::ble: {
|
||||
DO_DISS("ble 0x" << Base::HEX8 << branch_target_9(inst) << "\n");
|
||||
if(!znFlags ||
|
||||
(!(znFlags & 0x80000000) && vFlag) ||
|
||||
(((znFlags & 0x80000000)) && !vFlag))
|
||||
|
@ -1172,6 +1187,7 @@ CortexM0::err_t CortexM0::execute(uInt16 inst, uInt8 op)
|
|||
|
||||
//B(2) unconditional branch
|
||||
case Op::b2: {
|
||||
DO_DISS("b 0x" << Base::HEX8 << branch_target_12(inst) << "\n");
|
||||
write_register(15, branch_target_12(inst));
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
@ -1196,7 +1212,7 @@ CortexM0::err_t CortexM0::execute(uInt16 inst, uInt8 op)
|
|||
// (bl, blx_thumb)
|
||||
case Op::bl: {
|
||||
// branch to label
|
||||
DO_DISS('\n');
|
||||
DO_DISS("bkpt\n");
|
||||
rb = inst & ((1 << 11) - 1);
|
||||
if(rb & 1 << 10) rb |= (~((1 << 11) - 1)); //sign extend
|
||||
rb <<= 12;
|
||||
|
@ -1814,8 +1830,13 @@ CortexM0::err_t CortexM0::execute(uInt16 inst, uInt8 op)
|
|||
return err;
|
||||
}
|
||||
|
||||
if ((rc & 0x01) == 0) {
|
||||
reg_norm = regOld;
|
||||
return errIntrinsic(ERR_INVALID_OPERATING_MODE, read_register(15) - 4);
|
||||
}
|
||||
|
||||
rc += 2;
|
||||
write_register(15, rc);
|
||||
write_register(15, rc & ~0x01);
|
||||
sp += 4;
|
||||
}
|
||||
write_register(13, sp);
|
||||
|
|
|
@ -23,10 +23,44 @@
|
|||
|
||||
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)
|
||||
{}
|
||||
|
||||
void VcsLib::reset()
|
||||
{
|
||||
myStuffMaskA = myStuffMaskX = myStuffMaskY = 0xff;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
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)
|
||||
{
|
||||
uInt32 arg;
|
||||
CortexM0::err_t err;
|
||||
|
||||
switch (address) {
|
||||
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:
|
||||
FatalEmulationError::raise("unimplemented: memcpy");
|
||||
|
||||
case ADDR_VCS_LDA_FOR_BUS_STUFF2:
|
||||
FatalEmulationError::raise("unimplemented: vcsLdaForBusStuff2");
|
||||
vcsLda2(myStuffMaskA);
|
||||
return returnFromStub(value, op);
|
||||
|
||||
case ADDR_VCS_LDX_FOR_BUS_STUFF2:
|
||||
FatalEmulationError::raise("unimplemented: vcsLdxForBusStuff2");
|
||||
vcsLda2(myStuffMaskX);
|
||||
return returnFromStub(value, op);
|
||||
|
||||
case ADDR_VCS_LDY_FOR_BUS_STUFF2:
|
||||
FatalEmulationError::raise("unimplemented: vcsLdyForBusStuff2");
|
||||
vcsLda2(myStuffMaskY);
|
||||
return returnFromStub(value, op);
|
||||
|
||||
case ADDR_VCS_WRITE3:
|
||||
FatalEmulationError::raise("unimplemented: vcsWrite3");
|
||||
|
||||
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:
|
||||
FatalEmulationError::raise("unimplemented: vcsNop2");
|
||||
|
@ -108,13 +165,15 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex
|
|||
return returnFromStub(value, op);
|
||||
|
||||
case ADDR_VCS_WRITE5:
|
||||
FatalEmulationError::raise("unimplemented: vcsWrite5");
|
||||
vcsWrite5(cortex.getRegister(0), cortex.getRegister(1));
|
||||
return returnFromStub(value, op);
|
||||
|
||||
case ADDR_VCS_WRITE6:
|
||||
FatalEmulationError::raise("unimplemented: vcsWrite6");
|
||||
|
||||
case ADDR_VCS_LDA2:
|
||||
FatalEmulationError::raise("unimplemented: vcsLda2");
|
||||
vcsLda2(cortex.getRegister(0));
|
||||
return returnFromStub(value, op);
|
||||
|
||||
case ADDR_VCS_LDX2:
|
||||
FatalEmulationError::raise("unimplemented: vcsLdx2");
|
||||
|
@ -126,7 +185,14 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex
|
|||
FatalEmulationError::raise("unimplemented: vcsSax3");
|
||||
|
||||
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:
|
||||
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)
|
||||
{
|
||||
constexpr uInt16 BX_LR = 0x7047;
|
||||
constexpr uInt16 BX_LR = 0x4770;
|
||||
|
||||
value = BX_LR;
|
||||
op = CortexM0::decodeInstructionWord(BX_LR);
|
||||
|
|
|
@ -27,6 +27,8 @@ class VcsLib: public CortexM0::BusTransactionDelegate {
|
|||
public:
|
||||
explicit VcsLib(BusTransactionQueue& transactionQueue);
|
||||
|
||||
void reset();
|
||||
|
||||
CortexM0::err_t fetch16(uInt32 address, uInt16& value, uInt8& op, CortexM0& cortex) override;
|
||||
|
||||
void vcsWrite5(uInt8 zpAddress, uInt8 value);
|
||||
|
@ -34,6 +36,7 @@ class VcsLib: public CortexM0::BusTransactionDelegate {
|
|||
void vcsStartOverblank();
|
||||
void vcsEndOverblank();
|
||||
void vcsNop2n(uInt16 n);
|
||||
void vcsLda2(uInt8 value);
|
||||
|
||||
private:
|
||||
CortexM0::err_t returnFromStub(uInt16& value, uInt8& op);
|
||||
|
@ -41,6 +44,10 @@ class VcsLib: public CortexM0::BusTransactionDelegate {
|
|||
private:
|
||||
BusTransactionQueue& myTransactionQueue;
|
||||
|
||||
uInt8 myStuffMaskA{0xff};
|
||||
uInt8 myStuffMaskX{0xff};
|
||||
uInt8 myStuffMaskY{0xff};
|
||||
|
||||
private:
|
||||
VcsLib(const VcsLib&) = delete;
|
||||
VcsLib(VcsLib&&) = delete;
|
||||
|
|
Loading…
Reference in New Issue