コード例 #1
0
void Interpreter::dcbst(UGeckoInstruction _inst)
{
	// Cache line flush. Since we don't emulate the data cache, we don't need to do anything.
	// Invalidate the jit block cache on dcbst in case new code has been loaded via the data cache
		u32 address = Helper_Get_EA_X(_inst);
		JitInterface::InvalidateICache(address & ~0x1f, 32);
}
コード例 #2
0
// Stores Word Conditional indeXed
void Interpreter::stwcxd(UGeckoInstruction inst)
{
  const u32 address = Helper_Get_EA_X(inst);

  if ((address & 0b11) != 0)
  {
    GenerateAlignmentException(address);
    return;
  }

  if (m_reserve)
  {
    if (address == m_reserve_address)
    {
      PowerPC::Write_U32(rGPR[inst.RS], address);
      if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
      {
        m_reserve = false;
        PowerPC::SetCRField(0, 2 | PowerPC::GetXER_SO());
        return;
      }
    }
  }

  PowerPC::SetCRField(0, PowerPC::GetXER_SO());
}
コード例 #3
0
// TODO: is this right? is it DSI interruptible?
void Interpreter::stswx(UGeckoInstruction inst)
{
  u32 EA = Helper_Get_EA_X(inst);

  if (UReg_MSR{MSR}.LE)
  {
    GenerateAlignmentException(EA);
    return;
  }

  u32 n = (u8)PowerPC::ppcState.xer_stringctrl;
  int r = inst.RS;
  int i = 0;

  while (n > 0)
  {
    PowerPC::Write_U8((rGPR[r] >> (24 - i)) & 0xFF, EA);

    EA++;
    n--;
    i += 8;
    if (i == 32)
    {
      i = 0;
      r = (r + 1) & 0x1f;  // wrap
    }
  }
}
コード例 #4
0
// TODO: is this right?
// FIXME: Should rollback if a DSI occurs
void Interpreter::lswx(UGeckoInstruction _inst)
{
	u32 EA = Helper_Get_EA_X(_inst);
	u32 n = rSPR(SPR_XER) & 0x7F;
	int r = _inst.RD;
	int i = 0;

	if (n > 0)
	{
		m_GPR[r] = 0;
		do
		{
			u32 TempValue = Memory::Read_U8(EA) << (24 - i);
			if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
			{
				PanicAlert("DSI exception in lswx.");
				NOTICE_LOG(POWERPC, "DSI exception in lswx");
				return;
			}
			m_GPR[r] |= TempValue;

			EA++;
			n--;
			i += 8;
			if (i == 32)
			{
				i = 0;
				r = (r + 1) & 31;
				m_GPR[r] = 0;
			}
		} while (n > 0);
	}
}
コード例 #5
0
// FIXME: Should rollback if a DSI occurs
void Interpreter::lswx(UGeckoInstruction inst)
{
  u32 EA = Helper_Get_EA_X(inst);

  if (UReg_MSR{MSR}.LE)
  {
    GenerateAlignmentException(EA);
    return;
  }

  // Confirmed by hardware test that the zero case doesn't zero rGPR[r]
  for (u32 n = 0; n < static_cast<u8>(PowerPC::ppcState.xer_stringctrl); n++)
  {
    const int reg = (inst.RD + (n >> 2)) & 0x1f;
    const int offset = (n & 3) << 3;

    if ((n & 3) == 0)
      rGPR[reg] = 0;

    const u32 temp_value = PowerPC::Read_U8(EA) << (24 - offset);
    if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
    {
      PanicAlert("DSI exception in lswx.");
      NOTICE_LOG(POWERPC, "DSI exception in lswx");
      return;
    }
    rGPR[reg] |= temp_value;

    EA++;
  }
}
コード例 #6
0
void Interpreter::dcbi(UGeckoInstruction _inst)
{
	// Removes a block from data cache. Since we don't emulate the data cache, we don't need to do anything to the data cache
	// However, we invalidate the jit block cache on dcbi
		u32 address = Helper_Get_EA_X(_inst);
		JitInterface::InvalidateICache(address & ~0x1f, 32);
}
コード例 #7
0
void Interpreter::lhzx(UGeckoInstruction _inst)
{
	u32 temp = (u32)Memory::Read_U16(Helper_Get_EA_X(_inst));
	if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
	{
		m_GPR[_inst.RD] = temp;
	}
}
コード例 #8
0
void Interpreter::dcbz(UGeckoInstruction _inst)
{
	// HACK but works... we think
	if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bDCBZOFF)
		Memory::ClearCacheLine(Helper_Get_EA_X(_inst) & (~31));
	if (!JitInterface::GetCore())
		PowerPC::CheckExceptions();
}
コード例 #9
0
void Interpreter::lwbrx(UGeckoInstruction _inst)
{
	u32 temp = Common::swap32(Memory::Read_U32(Helper_Get_EA_X(_inst)));
	if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
	{
		m_GPR[_inst.RD] = temp;
	}
}
コード例 #10
0
void Interpreter::dcbz(UGeckoInstruction _inst)
{
    // HACK but works... we think
    if (!Core::g_CoreStartupParameter.bDCBZOFF)
        Memory::Memset(Helper_Get_EA_X(_inst) & (~31), 0, 32);
    if (!JitInterface::GetCore())
        PowerPC::CheckExceptions();
}
コード例 #11
0
void Interpreter::lwzx(UGeckoInstruction _inst)
{
	u32 uAddress = Helper_Get_EA_X(_inst);
	u32 temp = Memory::Read_U32(uAddress);
	if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
	{
		m_GPR[_inst.RD] = temp;
	}
}
コード例 #12
0
void Interpreter::lhzx(UGeckoInstruction inst)
{
  const u32 temp = (u32)PowerPC::Read_U16(Helper_Get_EA_X(inst));

  if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
  {
    rGPR[inst.RD] = temp;
  }
}
コード例 #13
0
void Interpreter::lfsx(UGeckoInstruction _inst)
{
	u32 uTemp = Memory::Read_U32(Helper_Get_EA_X(_inst));
	if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
	{
		double value = *(float*)&uTemp;
		rPS0(_inst.FD) = value;
		rPS1(_inst.FD) = value;
	}
}
コード例 #14
0
void Interpreter::lfsx(UGeckoInstruction _inst)
{
	u32 uTemp = PowerPC::Read_U32(Helper_Get_EA_X(_inst));
	if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
	{
		u64 value = ConvertToDouble(uTemp);
		riPS0(_inst.FD) = value;
		riPS1(_inst.FD) = value;
	}
}
コード例 #15
0
void Interpreter::lwzx(UGeckoInstruction inst)
{
  const u32 address = Helper_Get_EA_X(inst);
  const u32 temp = PowerPC::Read_U32(address);

  if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
  {
    rGPR[inst.RD] = temp;
  }
}
コード例 #16
0
void Interpreter::dcbst(UGeckoInstruction inst)
{
  // TODO: Implement some sort of L2 emulation.
  // TODO: Raise DSI if translation fails (except for direct-store segments).

  // Invalidate the JIT cache here as a heuristic to compensate for
  // the lack of precise L1 icache emulation in the JIT. (Portable software
  // should use icbi consistently, but games aren't portable.)
  const u32 address = Helper_Get_EA_X(inst);
  JitInterface::InvalidateICache(address & ~0x1f, 32, false);
}
コード例 #17
0
void Interpreter::stfsx(UGeckoInstruction inst)
{
  const u32 address = Helper_Get_EA_X(inst);

  if ((address & 0b11) != 0)
  {
    GenerateAlignmentException(address);
    return;
  }

  PowerPC::Write_U32(ConvertToSingle(riPS0(inst.FS)), address);
}
コード例 #18
0
void Interpreter::dcbf(UGeckoInstruction _inst)
{
	//This should tell GFX backend to throw out any cached data here
	// !!! SPEEDUP HACK for OSProtectRange !!!
/*	u32 tmp1 = PowerPC::HostRead_U32(PC+4);
	u32 tmp2 = PowerPC::HostRead_U32(PC+8);

	if ((tmp1 == 0x38630020) &&
		(tmp2 == 0x4200fff8))
	{
		NPC = PC + 12;
	}*/
	u32 address = Helper_Get_EA_X(_inst);
	JitInterface::InvalidateICache(address & ~0x1f, 32, false);
}
コード例 #19
0
void Interpreter::lfdx(UGeckoInstruction inst)
{
  const u32 address = Helper_Get_EA_X(inst);

  if ((address & 0b11) != 0)
  {
    GenerateAlignmentException(address);
    return;
  }

  const u64 temp = PowerPC::Read_U64(address);

  if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
    riPS0(inst.FD) = temp;
}
コード例 #20
0
void Interpreter::ecowx(UGeckoInstruction inst)
{
  const u32 EA = Helper_Get_EA_X(inst);

  if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000))
  {
    GenerateDSIException(EA);
    return;
  }

  if (EA & 3)
  {
    GenerateAlignmentException(EA);
    return;
  }

  PowerPC::Write_U32(rGPR[inst.RS], EA);
}
コード例 #21
0
void Interpreter::lwarx(UGeckoInstruction inst)
{
  const u32 address = Helper_Get_EA_X(inst);

  if ((address & 0b11) != 0)
  {
    GenerateAlignmentException(address);
    return;
  }

  const u32 temp = PowerPC::Read_U32(address);

  if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
  {
    rGPR[inst.RD] = temp;
    m_reserve = true;
    m_reserve_address = address;
  }
}
コード例 #22
0
void Interpreter::dcbz_l(UGeckoInstruction inst)
{
  if (!HID2.LCE)
  {
    GenerateProgramException();
    return;
  }

  const u32 address = Helper_Get_EA_X(inst);

  if (!HID0.DCE)
  {
    GenerateAlignmentException(address);
    return;
  }

  // FAKE: clear memory instead of clearing the cache block
  PowerPC::ClearCacheLine(address & (~31));
}
コード例 #23
0
void Interpreter::lfsx(UGeckoInstruction inst)
{
  const u32 address = Helper_Get_EA_X(inst);

  if ((address & 0b11) != 0)
  {
    GenerateAlignmentException(address);
    return;
  }

  const u32 temp = PowerPC::Read_U32(address);

  if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
  {
    const u64 value = ConvertToDouble(temp);
    riPS0(inst.FD) = value;
    riPS1(inst.FD) = value;
  }
}
コード例 #24
0
void Interpreter::stwcxd(UGeckoInstruction _inst)
{
	// Stores Word Conditional indeXed
	u32 uAddress;
	if (g_bReserve) {
		uAddress = Helper_Get_EA_X(_inst);
		if (uAddress == g_reserveAddr) {
			Memory::Write_U32(m_GPR[_inst.RS], uAddress);
			if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
			{
				g_bReserve = false;
				SetCRField(0, 2 | GetXER_SO());
				return;
			}
		}
	}

	SetCRField(0, GetXER_SO());
}
コード例 #25
0
// TODO: is this right? is it DSI interruptible?
void Interpreter::stswx(UGeckoInstruction _inst)
{
	u32 EA = Helper_Get_EA_X(_inst);
	u32 n = rSPR(SPR_XER) & 0x7F;
	int r = _inst.RS;
	int i = 0;

	while (n > 0)
	{
		Memory::Write_U8((m_GPR[r] >> (24 - i)) & 0xFF, EA);

		EA++;
		n--;
		i += 8;
		if (i == 32)
		{
			i = 0;
			r++;
		}
	}
}
コード例 #26
0
void Interpreter::dcbz(UGeckoInstruction inst)
{
  // DCBZOFF is a hack to fix certain games which would otherwise require
  // accurate L2 emulation.
  if (SConfig::GetInstance().bDCBZOFF)
    return;

  const u32 dcbz_addr = Helper_Get_EA_X(inst);

  if (!HID0.DCE)
  {
    GenerateAlignmentException(dcbz_addr);
    return;
  }

  // Hack to stop dcbz/dcbi over low MEM1 trashing memory.
  if (SConfig::GetInstance().bLowDCBZHack && (dcbz_addr < 0x80008000) && (dcbz_addr >= 0x80000000))
    return;

  // TODO: Implement some sort of L2 emulation.
  PowerPC::ClearCacheLine(dcbz_addr & (~31));
}
コード例 #27
0
void Interpreter::dcbi(UGeckoInstruction _inst)
{
	// Removes a block from data cache. Since we don't emulate the data cache, we don't need to do anything to the data cache
	// However, we invalidate the jit block cache on dcbi
	u32 address = Helper_Get_EA_X(_inst);
	JitInterface::InvalidateICache(address & ~0x1f, 32, false);

	// The following detects a situation where the game is writing to the dcache at the address being DMA'd. As we do not
	// have dcache emulation, invalid data is being DMA'd causing audio glitches. The following code detects this and
	// enables the DMA to complete instantly before the invalid data is written. Resident Evil 2 & 3 trigger this.
	u64 dma_in_progress = DSP::DMAInProgress();
	if (dma_in_progress != 0)
	{
		u32 start_addr = (dma_in_progress >> 32) & Memory::RAM_MASK;
		u32 end_addr = (dma_in_progress & Memory::RAM_MASK) & 0xffffffff;
		u32 invalidated_addr = (address & Memory::RAM_MASK) & ~0x1f;

		if (invalidated_addr >= start_addr && invalidated_addr <= end_addr)
		{
			DSP::EnableInstantDMA();
		}
	}
コード例 #28
0
void Interpreter::stwx(UGeckoInstruction _inst)
{
	u32 uAddress = Helper_Get_EA_X(_inst);
	Memory::Write_U32(m_GPR[_inst.RS], uAddress);
}
コード例 #29
0
void Interpreter::sthx(UGeckoInstruction _inst)
{
	Memory::Write_U16((u16)m_GPR[_inst.RS], Helper_Get_EA_X(_inst));
}
コード例 #30
0
void Interpreter::sthbrx(UGeckoInstruction _inst)
{
	Memory::Write_U16(Common::swap16((u16)m_GPR[_inst.RS]), Helper_Get_EA_X(_inst));
}