From 7bc095e130850740070d41a098002c5644e72379 Mon Sep 17 00:00:00 2001 From: Christian Speckner Date: Sat, 27 Jul 2024 23:52:22 +0200 Subject: [PATCH] More fixes, implement more parts of vcslib. --- src/emucore/CortexM0.cxx | 29 +++++++++++-- src/emucore/elf/VcsLib.cxx | 84 ++++++++++++++++++++++++++++++++++---- src/emucore/elf/VcsLib.hxx | 7 ++++ 3 files changed, 107 insertions(+), 13 deletions(-) diff --git a/src/emucore/CortexM0.cxx b/src/emucore/CortexM0.cxx index 63c5bac54..7ef9829e2 100644 --- a/src/emucore/CortexM0.cxx +++ b/src/emucore/CortexM0.cxx @@ -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)) { //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); diff --git a/src/emucore/elf/VcsLib.cxx b/src/emucore/elf/VcsLib.cxx index 668f89641..8b3b9df94 100644 --- a/src/emucore/elf/VcsLib.cxx +++ b/src/emucore/elf/VcsLib.cxx @@ -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); diff --git a/src/emucore/elf/VcsLib.hxx b/src/emucore/elf/VcsLib.hxx index 8a712d087..0e4f68365 100644 --- a/src/emucore/elf/VcsLib.hxx +++ b/src/emucore/elf/VcsLib.hxx @@ -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;