Esempio n. 1
0
static bool checkStart(u32 start, u32 size) {
  bool invalidSize = false;
  bool invalidAddress = false;

  if (isInInterval(PSP_GetScratchpadMemoryBase(),PSP_GetScratchpadMemoryEnd(),start))
    {
      invalidSize = !isInInterval(PSP_GetScratchpadMemoryBase(),PSP_GetScratchpadMemoryEnd(),start+size-1);
    } else if (isInInterval(PSP_GetVidMemBase(),PSP_GetVidMemEnd(),start))
    {
      invalidSize = !isInInterval(PSP_GetVidMemBase(),PSP_GetVidMemEnd(),start+size-1);
    } else if (isInInterval(PSP_GetKernelMemoryBase(),PSP_GetUserMemoryEnd(),start))
    {
      invalidSize = !isInInterval(PSP_GetKernelMemoryBase(),PSP_GetUserMemoryEnd(),start+size-1);
    } else
    {
      invalidAddress = true;
    }

  if (invalidAddress)
    {
      printf("Invalid address 0x%08X.\n",start);
      return false;
    } else if (invalidSize)
    {
      printf("Invalid end address 0x%08X.\n",start+size);
      return false;
    }
  return true;
}
Esempio n. 2
0
	void Jit::SetCCAndR0ForSafeAddress(MIPSGPReg rs, s16 offset, ARMReg tempReg, bool reverse) {
		SetR0ToEffectiveAddress(rs, offset);

		// There are three valid ranges.  Each one gets a bit.
		const u32 BIT_SCRATCH = 1, BIT_RAM = 2, BIT_VRAM = 4;
		MOVI2R(tempReg, BIT_SCRATCH | BIT_RAM | BIT_VRAM);

		CMP(R0, AssumeMakeOperand2(PSP_GetScratchpadMemoryBase()));
		SetCC(CC_LO);
		BIC(tempReg, tempReg, BIT_SCRATCH);
		SetCC(CC_HS);
		CMP(R0, AssumeMakeOperand2(PSP_GetScratchpadMemoryEnd()));
		BIC(tempReg, tempReg, BIT_SCRATCH);

		// If it was in that range, later compares don't matter.
		CMP(R0, AssumeMakeOperand2(PSP_GetVidMemBase()));
		SetCC(CC_LO);
		BIC(tempReg, tempReg, BIT_VRAM);
		SetCC(CC_HS);
		CMP(R0, AssumeMakeOperand2(PSP_GetVidMemEnd()));
		BIC(tempReg, tempReg, BIT_VRAM);

		CMP(R0, AssumeMakeOperand2(PSP_GetKernelMemoryBase()));
		SetCC(CC_LO);
		BIC(tempReg, tempReg, BIT_RAM);
		SetCC(CC_HS);
		CMP(R0, AssumeMakeOperand2(PSP_GetUserMemoryEnd()));
		BIC(tempReg, tempReg, BIT_RAM);

		// If we left any bit set, the address is OK.
		SetCC(CC_AL);
		CMP(tempReg, 0);
		SetCC(reverse ? CC_EQ : CC_GT);
	}
Esempio n. 3
0
void Jit::WriteExitDestInEAX()
{
	// TODO: Some wasted potential, dispatcher will always read this back into EAX.
	MOV(32, M(&mips_->pc), R(EAX));
	WriteDowncount();

	// Validate the jump to avoid a crash?
	if (!g_Config.bFastMemory)
	{
		CMP(32, R(EAX), Imm32(PSP_GetKernelMemoryBase()));
		FixupBranch tooLow = J_CC(CC_L);
		CMP(32, R(EAX), Imm32(PSP_GetUserMemoryEnd()));
		FixupBranch tooHigh = J_CC(CC_GE);

		JMP(asm_.dispatcher, true);

		SetJumpTarget(tooLow);
		SetJumpTarget(tooHigh);

		ABI_CallFunctionA(thunks.ProtectFunction((void *) Memory::GetPointer, 1), R(EAX));
		CMP(32, R(EAX), Imm32(0));
		J_CC(CC_NE, asm_.dispatcher, true);

		// TODO: "Ignore" this so other threads can continue?
		if (g_Config.bIgnoreBadMemAccess)
			MOV(32, M((void*)&coreState), Imm32(CORE_ERROR));
		JMP(asm_.dispatcherCheckCoreState, true);
	}
	else
		JMP(asm_.dispatcher, true);
}
Esempio n. 4
0
void __KernelMemoryInit()
{
	kernelMemory.Init(PSP_GetKernelMemoryBase(), PSP_GetKernelMemoryEnd()-PSP_GetKernelMemoryBase());
	userMemory.Init(PSP_GetUserMemoryBase(), PSP_GetUserMemoryEnd()-PSP_GetUserMemoryBase());
	INFO_LOG(HLE, "Kernel and user memory pools initialized");

	vplWaitTimer = CoreTiming::RegisterEvent("VplTimeout", __KernelVplTimeout);
}
Esempio n. 5
0
OpArg Jit::JitSafeMem::PrepareMemoryOpArg(ReadType type)
{
	// We may not even need to move into EAX as a temporary.
	bool needTemp = alignMask_ != 0xFFFFFFFF;
#ifdef _M_IX86
	// We always mask on 32 bit in fast memory mode.
	needTemp = needTemp || fast_;
#endif

	if (jit_->gpr.R(raddr_).IsSimpleReg() && !needTemp)
	{
		jit_->gpr.MapReg(raddr_, true, false);
		xaddr_ = jit_->gpr.RX(raddr_);
	}
	else
	{
		jit_->MOV(32, R(EAX), jit_->gpr.R(raddr_));
		xaddr_ = EAX;
	}

	MemCheckAsm(type);

	if (!fast_)
	{
		// Is it in physical ram?
		jit_->CMP(32, R(xaddr_), Imm32(PSP_GetKernelMemoryBase() - offset_));
		tooLow_ = jit_->J_CC(CC_B);
		jit_->CMP(32, R(xaddr_), Imm32(PSP_GetUserMemoryEnd() - offset_ - (size_ - 1)));
		tooHigh_ = jit_->J_CC(CC_AE);

		// We may need to jump back up here.
		safe_ = jit_->GetCodePtr();
	}
	else
	{
#ifdef _M_IX86
		jit_->AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
#endif
	}

	// TODO: This could be more optimal, but the common case is that we want xaddr_ not to include offset_.
	// Since we need to align them after add, we add and subtract.
	if (alignMask_ != 0xFFFFFFFF)
	{
		jit_->ADD(32, R(xaddr_), Imm32(offset_));
		jit_->AND(32, R(xaddr_), Imm32(alignMask_));
		jit_->SUB(32, R(xaddr_), Imm32(offset_));
	}

#ifdef _M_IX86
	return MDisp(xaddr_, (u32) Memory::base + offset_);
#else
	return MComplex(RBX, xaddr_, SCALE_1, offset_);
#endif
}
void JitBlockCache::FinalizeBlock(int block_num, bool block_link) {
    JitBlock &b = blocks_[block_num];

    b.originalFirstOpcode = Memory::Read_Opcode_JIT(b.originalAddress);
    MIPSOpcode opcode = GetEmuHackOpForBlock(block_num);
    Memory::Write_Opcode_JIT(b.originalAddress, opcode);

    AddBlockMap(block_num);

    u32 latestExit = 0;
    if (block_link) {
        for (int i = 0; i < MAX_JIT_BLOCK_EXITS; i++) {
            if (b.exitAddress[i] != INVALID_EXIT) {
                links_to_.insert(std::make_pair(b.exitAddress[i], block_num));
                latestExit = std::max(latestExit, b.exitAddress[i]);
            }
        }

        LinkBlock(block_num);
        LinkBlockExits(block_num);
    }

    if (Memory::IsScratchpadAddress(b.originalAddress)) {
        ExpandRange(blockMemRanges_[JITBLOCK_RANGE_SCRATCH], b.originalAddress, latestExit);
    }
    const u32 halfUserMemory = (PSP_GetUserMemoryEnd() - PSP_GetUserMemoryBase()) / 2;
    if (b.originalAddress < PSP_GetUserMemoryBase() + halfUserMemory) {
        ExpandRange(blockMemRanges_[JITBLOCK_RANGE_RAMBOTTOM], b.originalAddress, latestExit);
    }
    if (latestExit > PSP_GetUserMemoryBase() + halfUserMemory) {
        ExpandRange(blockMemRanges_[JITBLOCK_RANGE_RAMTOP], b.originalAddress, latestExit);
    }

#if defined USE_OPROFILE && USE_OPROFILE
    char buf[100];
    sprintf(buf, "EmuCode%x", b.originalAddress);
    const u8* blockStart = blocks_[block_num].checkedEntry;
    op_write_native_code(agent, buf, (uint64_t)blockStart, blockStart, b.normalEntry + b.codeSize - b.checkedEntry);
#endif

#ifdef USE_VTUNE
    sprintf(b.blockName, "EmuCode_0x%08x", b.originalAddress);

    iJIT_Method_Load jmethod = {0};
    jmethod.method_id = iJIT_GetNewMethodID();
    jmethod.class_file_name = "";
    jmethod.source_file_name = __FILE__;
    jmethod.method_load_address = (void*)blocks_[block_num].checkedEntry;
    jmethod.method_size = b.normalEntry + b.codeSize - b.checkedEntry;
    jmethod.line_number_size = 0;
    jmethod.method_name = b.blockName;
    iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&jmethod);
#endif
}
Esempio n. 7
0
void Jit::WriteExitDestInEAX()
{
	// TODO: Some wasted potential, dispatcher will always read this back into EAX.
	MOV(32, M(&mips_->pc), R(EAX));

	// If we need to verify coreState and rewind, we may not jump yet.
	if (js.afterOp & (JitState::AFTER_CORE_STATE | JitState::AFTER_REWIND_PC_BAD_STATE))
	{
		// CORE_RUNNING is <= CORE_NEXTFRAME.
		CMP(32, M((void*)&coreState), Imm32(CORE_NEXTFRAME));
		FixupBranch skipCheck = J_CC(CC_LE);
		MOV(32, M(&mips_->pc), Imm32(js.compilerPC));
		WriteSyscallExit();
		SetJumpTarget(skipCheck);

		js.afterOp = JitState::AFTER_NONE;
	}

	WriteDowncount();

	// Validate the jump to avoid a crash?
	if (!g_Config.bFastMemory)
	{
		CMP(32, R(EAX), Imm32(PSP_GetKernelMemoryBase()));
		FixupBranch tooLow = J_CC(CC_B);
		CMP(32, R(EAX), Imm32(PSP_GetUserMemoryEnd()));
		FixupBranch tooHigh = J_CC(CC_AE);

		// Need to set neg flag again if necessary.
		SUB(32, M(&currentMIPS->downcount), Imm32(0));
		JMP(asm_.dispatcher, true);

		SetJumpTarget(tooLow);
		SetJumpTarget(tooHigh);

		CallProtectedFunction((void *) Memory::GetPointer, R(EAX));
		CMP(32, R(EAX), Imm32(0));
		FixupBranch skip = J_CC(CC_NE);

		// TODO: "Ignore" this so other threads can continue?
		if (g_Config.bIgnoreBadMemAccess)
			CallProtectedFunction((void *) Core_UpdateState, Imm32(CORE_ERROR));

		SUB(32, M(&currentMIPS->downcount), Imm32(0));
		JMP(asm_.dispatcherCheckCoreState, true);
		SetJumpTarget(skip);

		SUB(32, M(&currentMIPS->downcount), Imm32(0));
		J_CC(CC_NE, asm_.dispatcher, true);
	}
	else
		JMP(asm_.dispatcher, true);
}
Esempio n. 8
0
void DumpMemoryWindow::changeMode(HWND hwnd, Mode newMode)
{
	char buffer[128];
	selectedMode = newMode;
	
	SendMessage(GetDlgItem(hwnd,IDC_DUMP_USERMEMORY),BM_SETCHECK,selectedMode == MODE_RAM ? BST_CHECKED : BST_UNCHECKED,0);
	SendMessage(GetDlgItem(hwnd,IDC_DUMP_VRAM),BM_SETCHECK,selectedMode == MODE_VRAM ? BST_CHECKED : BST_UNCHECKED,0);
	SendMessage(GetDlgItem(hwnd,IDC_DUMP_SCRATCHPAD),BM_SETCHECK,selectedMode == MODE_SCRATCHPAD ? BST_CHECKED : BST_UNCHECKED,0);
	SendMessage(GetDlgItem(hwnd,IDC_DUMP_CUSTOMRANGE),BM_SETCHECK,selectedMode == MODE_CUSTOM ? BST_CHECKED : BST_UNCHECKED,0);

	if (selectedMode == MODE_CUSTOM)
	{
		EnableWindow(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),TRUE);
		EnableWindow(GetDlgItem(hwnd,IDC_DUMP_SIZE),TRUE);

		if (filenameChosen == false)
			SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_FILENAME),"Custom.dump");
	} else {
		u32 start, size;
		const char* defaultFileName;

		switch (selectedMode)
		{
		case MODE_RAM:
			start = PSP_GetUserMemoryBase();
			size = PSP_GetUserMemoryEnd()-start;
			defaultFileName = "RAM.dump";
			break;
		case MODE_VRAM:
			start = PSP_GetVidMemBase();
			size = PSP_GetVidMemEnd()-start;
			defaultFileName = "VRAM.dump";
			break;
		case MODE_SCRATCHPAD:
			start = PSP_GetScratchpadMemoryBase();
			size = PSP_GetScratchpadMemoryEnd()-start;
			defaultFileName = "Scratchpad.dump";
			break;
		}
		
		sprintf(buffer,"0x%08X",start);
		SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),buffer);
		EnableWindow(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),FALSE);

		sprintf(buffer,"0x%08X",size);
		SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_SIZE),buffer);
		EnableWindow(GetDlgItem(hwnd,IDC_DUMP_SIZE),FALSE);
		
		if (filenameChosen == false)
			SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_FILENAME),defaultFileName);
	}
}
Esempio n. 9
0
void __KernelMemoryInit()
{
	kernelMemory.Init(PSP_GetKernelMemoryBase(), PSP_GetKernelMemoryEnd()-PSP_GetKernelMemoryBase());
	userMemory.Init(PSP_GetUserMemoryBase(), PSP_GetUserMemoryEnd()-PSP_GetUserMemoryBase());
	INFO_LOG(HLE, "Kernel and user memory pools initialized");

	vplWaitTimer = CoreTiming::RegisterEvent("VplTimeout", __KernelVplTimeout);

	flags_ = 0;
	sdkVersion_ = 0;
	compilerVersion_ = 0;
	memset(tlsUsedIndexes, 0, sizeof(tlsUsedIndexes));
}
Esempio n. 10
0
OpArg Jit::JitSafeMem::PrepareMemoryOpArg()
{
	// We may not even need to move into EAX as a temporary.
	// TODO: Except on x86 in fastmem mode.
	if (jit_->gpr.R(raddr_).IsSimpleReg())
	{
		jit_->gpr.BindToRegister(raddr_, true, false);
		xaddr_ = jit_->gpr.RX(raddr_);
	}
	else
	{
		jit_->MOV(32, R(EAX), jit_->gpr.R(raddr_));
		xaddr_ = EAX;
	}

	if (!g_Config.bFastMemory)
	{
		// Is it in physical ram?
		jit_->CMP(32, R(xaddr_), Imm32(PSP_GetKernelMemoryBase() - offset_));
		tooLow_ = jit_->J_CC(CC_L);
		jit_->CMP(32, R(xaddr_), Imm32(PSP_GetUserMemoryEnd() - offset_));
		tooHigh_ = jit_->J_CC(CC_GE);

		// We may need to jump back up here.
		safe_ = jit_->GetCodePtr();
	}
	else
	{
#ifdef _M_IX86
		// Need to modify it, too bad.
		if (xaddr_ != EAX)
			jit_->MOV(32, R(EAX), R(xaddr_));
		jit_->AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
		xaddr_ = EAX;
#endif
	}

#ifdef _M_IX86
		return MDisp(xaddr_, (u32) Memory::base + offset_);
#else
		return MComplex(RBX, xaddr_, SCALE_1, offset_);
#endif
}
Esempio n. 11
0
bool DumpMemoryWindow::fetchDialogData(HWND hwnd)
{
	char str[256],errorMessage[256];
	PostfixExpression exp;

	// parse start address
	GetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),str,256);
	if (cpu->initExpression(str,exp) == false
		|| cpu->parseExpression(exp,start) == false)
	{
		sprintf(errorMessage,"Invalid address expression \"%s\".",str);
		MessageBoxA(hwnd,errorMessage,"Error",MB_OK);
		return false;
	}
	
	// parse size
	GetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_SIZE),str,256);
	if (cpu->initExpression(str,exp) == false
		|| cpu->parseExpression(exp,size) == false)
	{
		sprintf(errorMessage,"Invalid size expression \"%s\".",str);
		MessageBoxA(hwnd,errorMessage,"Error",MB_OK);
		return false;
	}

	if (size == 0)
	{
		MessageBoxA(hwnd,"Invalid size 0.","Error",MB_OK);
		return false;
	}
	
	// get filename
	GetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_FILENAME),fileName,MAX_PATH);
	if (strlen(fileName) == 0) return false;

	// now check if data makes sense...
	bool invalidSize = false;
	bool invalidAddress = false;
	if (isInInterval(PSP_GetScratchpadMemoryBase(),PSP_GetScratchpadMemoryEnd(),start))
	{
		invalidSize = !isInInterval(PSP_GetScratchpadMemoryBase(),PSP_GetScratchpadMemoryEnd(),start+size-1);
	} else if (isInInterval(PSP_GetVidMemBase(),PSP_GetVidMemEnd(),start))
	{
		invalidSize = !isInInterval(PSP_GetVidMemBase(),PSP_GetVidMemEnd(),start+size-1);
	} else if (isInInterval(PSP_GetKernelMemoryBase(),PSP_GetUserMemoryEnd(),start))
	{
		invalidSize = !isInInterval(PSP_GetKernelMemoryBase(),PSP_GetUserMemoryEnd(),start+size-1);
	} else 
	{
		invalidAddress = true;
	}

	if (invalidAddress)
	{
		sprintf(errorMessage,"Invalid address 0x%08X.",start);
		MessageBoxA(hwnd,errorMessage,"Error",MB_OK);
		return false;
	} else if (invalidSize)
	{
		sprintf(errorMessage,"Invalid end address 0x%08X.",start+size);
		MessageBoxA(hwnd,errorMessage,"Error",MB_OK);
		return false;
	}

	return true;
}