void test_disassembleBytecodes_should_disassemble_an_array_of_bytecode(void) {
  char buffer[500] = {0};
  int bytecode[20] = {0};
  bytecode[0] = ldrImm(REG_4, -128);
  bytecode[1] = ldrMem(REG_0, REG_1, 8);
  bytecode[2] = strMem(REG_0, REG_1, 8);
  bytecode[3] = ldrMemSafe(REG_0, REG_1, 8);
  bytecode[4] = strMemSafe(REG_0, REG_1, 8);
  bytecode[5] = movReg(REG_0, DATA, REG_4, NOP, NOP);
  bytecode[6] = movReg(REG_0, DATA, REG_4, LSL, 4);
  bytecode[7] = movReg(REG_0, DATA, REG_4, LSR, 2);
  bytecode[8] = movReg(REG_0, DATA, REG_4, ASR, 6);
  bytecode[9] = movReg(REG_0, DATA, REG_4, RR, 5);
  bytecode[10] = ldm(REG_7, R4|R5|R6, INC, UPDATE);
  bytecode[11] = ldm(REG_7, R0|R5|R6, DEC, NO_UPDATE);
  bytecode[12] = stm(REG_7, R1|R2|R5|R6, DEC, UPDATE);
  bytecode[13] = stm(REG_7, R3|R4|R5|R6, INC, NO_UPDATE);
  bytecode[14] = ldms(REG_7, R3|R4|R5|R6, INC, NO_UPDATE);
  bytecode[15] = stms(REG_7, R0|R1|R2|R3|R4|R5|R6, DEC, NO_UPDATE);
  bytecode[16] = halt(); // Indicates end of bytecodes

  disassembleBytecodes(buffer, bytecode);
  printf("test_disassembleBytecodes_should_disassemble_an_array_of_bytecode\n");
  printf("%s\n", &buffer[0]);
}
示例#2
0
void NesCpuTranslator::mExitPoint()
{
	// restore registers and return to caller
#if defined(FRAME_POINTER_FOR_GDB)
	__ ldm(ia_w, sp, kCalleeSaved | fp.bit() | pc.bit());
#else
	__ ldm(ia_w, sp, kCalleeSaved | pc.bit());
#endif
}
示例#3
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);
}
示例#4
0
void NesSyncCompiler::mLeaveToCpu()
{
	__ add(r3, pc, Operand(Assembler::kInstrSize));
	__ str(r3, MemOperand(m_dataBase, offsetof(NesSyncData,nextPc)));
	// return to cpu emulation
	__ ldm(ia_w, sp, m_regList | pc.bit());
	// nesSyncRecData.nextPc points here now
}
示例#5
0
int instruction_cycle(CPU *cpu) {
	int halted = 1;
	
	(*cpu).ir = (*cpu).mem[(*cpu).pc];
	handleInstruction(cpu);
	switch ((*cpu).opcode){
		case 0:
		  halted = 0;
		  printf("Halt!");
		  break;
		case 1:
		  ld(cpu);
		  break;
		case 2:
		  st(cpu);	
		  break;
		case 3:
		  add(cpu);
		  break;
		case 4:
		  neg(cpu);
		  break;
		case 5:
		  ldm(cpu);
		  break;
		case 6:
		  addm(cpu);
		  break;
		case 7:
		  br(cpu);
		  break;
		case 8:
		  brp(cpu);
		  break;
		case 9:
		  io(cpu);
		  break;
		default:
		  printf("Error:Invalid opcode at address %d,Invalid number: %d",(*cpu).pc,(*cpu).mem[(*cpu).pc]);
		  break;
	}
	(*cpu).pc++;
	return halted;
	// For Lab 7, we just print a message and halt after the 10th call
	//
	//char suffix[][4] = {"", "st","nd","rd","th"};
	//printf("Calling instruction_cycle for %d%s time\n", call_nbr, suffix[min(call_nbr,4)]);

}
示例#6
0
void NesCpuTranslator::mHandleEvent()
{
	Label saveState;
	Label loadState;
	Label exit;

	// arguments: r1 = event

	// reg list for saving state
	// r0 contains 6502.PC address
	// r2 contains 6502.P flags
	RegList regList =	r0.bit() | r2.bit() | mA.bit() |
						mX.bit() | mY.bit() | mS.bit();

	// regs member of NesCpuRecData should be placed at the start of the object
	Q_ASSERT(offsetof(NesCpuRecData,regs) == 0);
	__ cmp(r1, Operand(NesCpuBase::SaveStateEvent));
	__ b(&saveState, eq);
	__ cmp(r1, Operand(NesCpuBase::LoadStateEvent));
	__ b(&loadState, eq);

// exitEvent:
	mExitPoint();

// loadState:
	__ bind(&loadState);
	__ ldm(ia, mDataBase, regList);
	mUnpackFlags(r2, r1);
	mSaveInternalFlags();
	mLoadLabelAddress(r0, lr);
	// mCycles is zeroed later
	__ b(&exit);

// saveState:
	__ bind(&saveState);
	mRestoreInternalFlags();
	mPackFlags(r2);
	__ stm(ia, mDataBase, regList);

	// saveState occurs on frame end, ticks() will be used on new frame
	// so set it to zero
	__ mov(ip, Operand(0));
	__ str(ip, MemOperand(mDataBase, offsetof(NesCpuRecData,currentCycles)));

// exit:
	__ bind(&exit);
}
示例#7
0
文件: ldm.c 项目: inhee/M-ulator
static void ldm_t2(uint32_t inst) {
	uint16_t reg_list = inst & 0x1fff;
	bool M = !!(inst & 0x4000);
	bool P = !!(inst & 0x8000);
	uint8_t rn = (inst & 0xf0000) >> 16;
	bool W = !!(inst & 0x200000);

	if ((W == 1) && (rn == 0xd))
		CORE_ERR_unpredictable("ldm_t2 --> pop\n");

	uint16_t registers = (P << 15) | (M << 14) | reg_list;
	bool wback = (W == 1);

	if ((rn == 15) || (hamming(registers) < 2) || ((P == 1) && (M == 1)))
		CORE_ERR_unpredictable("ldm_t2, long ||'s\n");

	if ((registers & 0x8000) && in_ITblock() && !last_in_ITblock())
		CORE_ERR_unpredictable("ldm_t2, itstate stuff\n");

	if (wback && (registers & (1 << (rn))))
		CORE_ERR_unpredictable("ldm_t2, writeback mismatch?\n");

	return ldm(rn, registers, wback);
}
示例#8
0
void NesCpuTranslator::mSync()
{
	// r0 - 6502.PC address of the next instruction

	__ bind(&m_syncLabel);
	Label exitSync;
	Label handleEvent;
	mSaveInternalFlags();
	// IRQ can be cleared, so we must fetch additional cycles every time
	mFetchAdditionalCycles();
	mHandleInterrupts();

	// IRQ may be pending and P.I can be set, in this case we may not call
	// nesSync if mCycles < 0
	__ mov(mCycles, mCycles, SetCC);
	__ b(&m_checkInterruptsForNextInstruction, mi);

	__ bind(&m_syncWithoutInterruptHandling);

	int preserved = r0.bit() | lr.bit();
#if defined(FRAME_POINTER_FOR_GDB)
	preserved |= fp.bit();
#endif
	__ stm(db_w, sp, preserved);
#if defined(FRAME_POINTER_FOR_GDB)
	__ add(fp, sp, Operand(2*4));
#endif

	Label dontSyncWithApuAndClock;
	__ ldr(ip, MemOperand(mDataBase, offsetof(NesCpuRecData,startCycles)));
	__ add(r0, mCycles, ip, SetCC);
	__ b(&dontSyncWithApuAndClock, eq);
	mCallCFunction(offsetof(NesCpuRecData,apuClock));
	if (nesMapper->hasClock()) {
		__ ldr(ip, MemOperand(mDataBase, offsetof(NesCpuRecData,startCycles)));
		__ add(r0, mCycles, ip, SetCC);
		mCallCFunction(offsetof(NesCpuRecData,mapperClock));
	}
	__ bind(&dontSyncWithApuAndClock);

	__ mov(r0, mCycles);
	mCallCFunction(offsetof(NesCpuRecData,nesSync));
	__ str(r0, MemOperand(mDataBase, offsetof(NesCpuRecData,startCycles)));
	__ rsb(mCycles, r0, Operand(0), SetCC);
	__ ldm(ia_w, sp, preserved);

	// if r0 >= 0 then it means we should handle an event
	__ b(&handleEvent, pl);

	// interrupts handling is a little tricky:
	//   - once interrupt occurs save cycles in the memory
	//   - force mSync to be called next time by setting mCycles to zero
	//   - handle interrupt in the new mSync call
	__ bind(&m_checkInterruptsForNextInstruction);
	mClearAlert();
	__ ldr(ip, MemOperand(mDataBase, offsetof(NesCpuRecData,interrupts)));
	__ mov(ip, ip, SetCC);
	__ b(&exitSync, eq);
	// interrupt is pending here
	__ str(mCycles, MemOperand(mDataBase,
							   offsetof(NesCpuRecData,additionalCycles)));
	__ mov(mCycles, Operand(0));
	__ b(&exitSync);

// handleEvent:
	__ bind(&handleEvent);
	__ rsb(r1, mCycles, Operand(0));
	__ mov(mCycles, Operand(0));
	__ str(mCycles, MemOperand(mDataBase, offsetof(NesCpuRecData,startCycles)));
	mHandleEvent();
	__ b(&m_syncWithoutInterruptHandling);

// exitSync:
	__ bind(&exitSync);
	mRestoreInternalFlags();
	// r0 must be loaded here with 6502.PC address of the next instruction
	__ mov(pc, lr);
}