More fixes, implement more parts of vcslib.

This commit is contained in:
Christian Speckner 2024-07-27 23:52:22 +02:00
parent e0ce387c9f
commit 7bc095e130
3 changed files with 107 additions and 13 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;