Example #1
0
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
}
Example #2
0
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);
}
Example #3
0
/*!
	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);
}
Example #4
0
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);
}