void NesSyncCompiler::mCallCFunction(int offsetInData) { #if defined(CAN_USE_ARMV7_INSTRUCTIONS) __ mov(ip, Operand(*(u32 *)((u8 *)&syncData + offsetInData))); __ blx(ip); #else __ ldr(ip, MemOperand(m_dataBase, offsetInData)); __ blx(ip); #endif }
void MacroAssembler::lowLevelDebug(const char *s, Register ra, Register rb, Register rc) { Q_ASSERT(ra.code() < 13 && rb.code() < 13 && rc.code() < 13); int preserved = 0x1fff | lr.bit(); stm(db_w, sp, preserved); add(fp, sp, Operand(12*4)); mrs(r4, CPSR); Label omitString; b(&omitString); int sPtr = intptr_t(buffer_ + pcOffset()); do { db(*s); } while (*(s++)); while (pcOffset() & 3) db('\0'); bind(&omitString); ldr(r3, MemOperand(sp, rc.code()*4)); ldr(r2, MemOperand(sp, rb.code()*4)); ldr(r1, MemOperand(sp, ra.code()*4)); mov(r0, Operand(sPtr)); void (*qDebugPtr)(const char *,...) = &qDebug; mov(ip, Operand(intptr_t(qDebugPtr))); blx(ip); msr(CPSR_f, Operand(r4)); ldm(ia_w, sp, preserved); }
/*! Loads C function address based on the given \a offset and calls this function. */ inline void NesCpuTranslator::mCallCFunction(int funcOffset) { __ ldr(ip, MemOperand(mDataBase, funcOffset)); __ blx(ip); }
void NesSyncCompiler::mClock(int ppuCycles) { /* Here the compiler will generate following function: syncData.baseCycleCounter += baseCycles; u64 cpuCyclesNow = syncData.baseCycleCounter / nesEmu.clockDividerForCpu(); syncData.cpuCycleCounter += additionalCpuCycles; int newCpuCycles = cpuCyclesNow - syncData.cpuCycleCounter; if (newCpuCycles > 0) { syncData.cpuCycleCounter += newCpuCycles; return newCpuCycles; } return 0; If return value != 0 it will return to the cpu emulation also. */ int baseCycles = ppuCycles * nesEmu.clockDividerForPpu(); Q_ASSERT(baseCycles >= 0); __ Ldrd(r0, r1, MemOperand(m_dataBase, offsetof(NesSyncData,baseCycleCounter))); __ add(r0, r0, Operand(baseCycles), SetCC); __ adc(r1, r1, Operand(0)); __ Strd(r0, r1, MemOperand(m_dataBase, offsetof(NesSyncData,baseCycleCounter))); if (nesEmu.clockDividerForCpu() == 12 #if !defined(CAN_USE_ARMV7_INSTRUCTIONS) || nesEmu.clockDividerForCpu() == 16 #endif ) { __ mov(r2, Operand(nesEmu.clockDividerForCpu())); __ mov(r3, Operand(0)); u8 *uldiv = reinterpret_cast<u8 *>(&__aeabi_uldivmod); __ mov(ip, Operand(reinterpret_cast<u32>(uldiv))); __ blx(ip); #if defined(CAN_USE_ARMV7_INSTRUCTIONS) } else if (nesEmu.clockDividerForCpu() == 16) { __ bfi(r0, r1, 0, 4); __ mov(r0, Operand(r0, ROR, 4)); __ mov(r1, Operand(r1, LSR, 4)); #endif } else { UNREACHABLE(); } __ Ldrd(r2, r3, MemOperand(m_dataBase, offsetof(NesSyncData,cpuCycleCounter))); __ add(r2, r2, m_additionalCpuCycles, SetCC); __ adc(r3, r3, Operand(0)); __ Strd(r2, r3, MemOperand(m_dataBase, offsetof(NesSyncData,cpuCycleCounter))); // clear additionalCpuCycles here because mClock can be executed multiple // times in single synchronization step __ mov(m_additionalCpuCycles, Operand(0)); __ sub(r0, r0, r2); __ cmp(r0, Operand(0)); __ mov(r0, Operand(0), LeaveCC, le); Label holdCpu; __ b(&holdCpu, le); __ add(r2, r2, r0, SetCC); __ adc(r3, r3, Operand(0)); __ Strd(r2, r3, MemOperand(m_dataBase, offsetof(NesSyncData,cpuCycleCounter))); mLeaveToCpu(); __ bind(&holdCpu); }