mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-29 00:59:44 -06:00
Merge branch 'master' into wii-network
This commit is contained in:
@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
@ -85,14 +85,14 @@ void LoadBPReg(const BPCmd &bp, BPMemory &bpMem)
|
||||
|
||||
void GetTlutLoadData(u32 &tlutAddr, u32 &memAddr, u32 &tlutXferCount, BPMemory &bpMem)
|
||||
{
|
||||
tlutAddr = (bpMem.tlutXferDest & 0x3FF) << 9;
|
||||
tlutXferCount = (bpMem.tlutXferDest & 0x1FFC00) >> 5;
|
||||
tlutAddr = (bpMem.tmem_config.tlut_dest & 0x3FF) << 9;
|
||||
tlutXferCount = (bpMem.tmem_config.tlut_dest & 0x1FFC00) >> 5;
|
||||
|
||||
// TODO - figure out a cleaner way.
|
||||
if (Core::g_CoreStartupParameter.bWii)
|
||||
memAddr = bpmem.tlutXferSrc << 5;
|
||||
memAddr = bpmem.tmem_config.tlut_src << 5;
|
||||
else
|
||||
memAddr = (bpmem.tlutXferSrc & 0xFFFFF) << 5;
|
||||
memAddr = (bpmem.tmem_config.tlut_src & 0xFFFFF) << 5;
|
||||
}
|
||||
|
||||
void LoadCPReg(u32 subCmd, u32 value, CPMemory &cpMem)
|
||||
|
@ -49,6 +49,9 @@ DSPLLE::DSPLLE() {
|
||||
m_cycle_count = 0;
|
||||
}
|
||||
|
||||
Common::Event dspEvent;
|
||||
Common::Event ppcEvent;
|
||||
|
||||
void DSPLLE::DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(g_dsp.r);
|
||||
@ -96,7 +99,10 @@ void DSPLLE::dsp_thread(DSPLLE *dsp_lle)
|
||||
Common::AtomicStore(dsp_lle->m_cycle_count, 0);
|
||||
}
|
||||
else
|
||||
Common::YieldCPU();
|
||||
{
|
||||
ppcEvent.Set();
|
||||
dspEvent.Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,6 +144,8 @@ void DSPLLE::DSP_StopSoundStream()
|
||||
m_bIsRunning = false;
|
||||
if (m_bDSPThread)
|
||||
{
|
||||
ppcEvent.Set();
|
||||
dspEvent.Set();
|
||||
m_hDSPThread.join();
|
||||
}
|
||||
}
|
||||
@ -274,9 +282,10 @@ void DSPLLE::DSP_Update(int cycles)
|
||||
else
|
||||
{
|
||||
// Wait for dsp thread to complete its cycle. Note: this logic should be thought through.
|
||||
while (m_cycle_count != 0)
|
||||
;
|
||||
ppcEvent.Wait();
|
||||
Common::AtomicStore(m_cycle_count, dsp_cycles);
|
||||
dspEvent.Set();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1126,7 +1126,7 @@ bool GCMemcard::Format(u8 * card_data, bool sjis, u16 SizeMb)
|
||||
gcp.bat_backup = (BlockAlloc *)(card_data + BLOCK_SIZE*4);
|
||||
|
||||
*(u16*)gcp.hdr->SizeMb = BE16(SizeMb);
|
||||
*(u16*)gcp.hdr->Encoding = BE16(sjis ? 1 : 0);
|
||||
gcp.hdr->Encoding = BE16(sjis ? 1 : 0);
|
||||
|
||||
FormatInternal(gcp);
|
||||
return true;
|
||||
@ -1148,7 +1148,7 @@ bool GCMemcard::Format(bool sjis, u16 SizeMb)
|
||||
gcp.bat_backup = &bat_backup;
|
||||
|
||||
*(u16*)hdr.SizeMb = BE16(SizeMb);
|
||||
*(u16*)hdr.Encoding = BE16(sjis ? 1 : 0);
|
||||
hdr.Encoding = BE16(sjis ? 1 : 0);
|
||||
FormatInternal(gcp);
|
||||
|
||||
m_sizeMb = SizeMb;
|
||||
|
@ -91,7 +91,7 @@ private:
|
||||
// end Serial in libogc
|
||||
u8 deviceID[2]; //0x0020 2 0 if formated in slot A 1 if formated in slot B
|
||||
u8 SizeMb[2]; //0x0022 2 size of memcard in Mbits
|
||||
u8 Encoding[2]; //0x0024 2 encoding (ASCII or japanese)
|
||||
u16 Encoding; //0x0024 2 encoding (ASCII or japanese)
|
||||
u8 Unused1[468]; //0x0026 468 unused (0xff)
|
||||
u8 UpdateCounter[2];//0x01fa 2 update Counter (?, probably unused)
|
||||
u16 Checksum; //0x01fc 2 Additive Checksum
|
||||
|
@ -129,7 +129,7 @@ int FindWiimotes(Wiimote **wm, int max_wiimotes)
|
||||
[bti setInquiryLength: 5];
|
||||
[bti setSearchCriteria: kBluetoothServiceClassMajorAny
|
||||
majorDeviceClass: kBluetoothDeviceClassMajorPeripheral
|
||||
minorDeviceClass: kBluetoothDeviceClassMinorPeripheral2Joystick
|
||||
minorDeviceClass: kBluetoothDeviceClassMinorAny
|
||||
];
|
||||
[bti setUpdateNewDeviceNames: NO];
|
||||
|
||||
@ -177,6 +177,10 @@ bool Wiimote::Connect()
|
||||
if (IsConnected())
|
||||
return false;
|
||||
|
||||
if ([btd remoteNameRequest:nil] == kIOReturnSuccess)
|
||||
m_motion_plus_inside =
|
||||
static_cast<bool>([[btd getName] hasSuffix:@"-TR"]);
|
||||
|
||||
[btd openL2CAPChannelSync: &cchan
|
||||
withPSM: kBluetoothL2CAPPSMHIDControl delegate: cbt];
|
||||
[btd openL2CAPChannelSync: &ichan
|
||||
@ -244,7 +248,7 @@ int Wiimote::IOWrite(unsigned char *buf, int len)
|
||||
if (!IsConnected())
|
||||
return 0;
|
||||
|
||||
ret = [cchan writeAsync: buf length: len refcon: nil];
|
||||
ret = [ichan writeAsync: buf length: len refcon: nil];
|
||||
|
||||
if (ret == kIOReturnSuccess)
|
||||
return len;
|
||||
|
@ -50,6 +50,7 @@ Wiimote::Wiimote(const unsigned int _index)
|
||||
#endif
|
||||
, leds(0), m_last_data_report(Report((u8 *)NULL, 0))
|
||||
, m_channel(0), m_connected(false)
|
||||
, m_motion_plus_inside(false)
|
||||
{
|
||||
#if defined(__linux__) && HAVE_BLUEZ
|
||||
bdaddr = (bdaddr_t){{0, 0, 0, 0, 0, 0}};
|
||||
@ -142,15 +143,16 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const data, const
|
||||
rpt.second = (u8)size;
|
||||
memcpy(rpt.first, (u8*)data, size);
|
||||
|
||||
// Convert output DATA packets to SET_REPORT packets.
|
||||
// Nintendo Wiimotes work without this translation, but 3rd
|
||||
// Convert output DATA packets to SET_REPORT packets for non-TR
|
||||
// Wiimotes. Nintendo Wiimotes work without this translation, but 3rd
|
||||
// party ones don't.
|
||||
u8 head = m_motion_plus_inside ? 0xa2 : 0x52;
|
||||
if (rpt.first[0] == 0xa2)
|
||||
{
|
||||
rpt.first[0] = 0x52;
|
||||
rpt.first[0] = head;
|
||||
}
|
||||
|
||||
if (rpt.first[0] == 0x52 && rpt.first[1] == 0x18 && rpt.second == 23)
|
||||
if (rpt.first[0] == head && rpt.first[1] == 0x18 && rpt.second == 23)
|
||||
{
|
||||
m_audio_reports.Push(rpt);
|
||||
return;
|
||||
|
@ -95,6 +95,7 @@ private:
|
||||
void ThreadFunc();
|
||||
|
||||
bool m_connected;
|
||||
bool m_motion_plus_inside;
|
||||
std::thread m_wiimote_thread;
|
||||
Common::FifoQueue<Report> m_read_reports;
|
||||
Common::FifoQueue<Report> m_write_reports;
|
||||
|
@ -211,7 +211,9 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32
|
||||
// Don't do anything if the log is unselected
|
||||
if (LogManager::GetInstance()->IsEnabled(LogTypes::FILEMON))
|
||||
{
|
||||
const char *pFilename = m_pFileSystem->GetFileName(DVDAddress);
|
||||
const char *pFilename = NULL;
|
||||
if (m_pFileSystem)
|
||||
pFilename = m_pFileSystem->GetFileName(DVDAddress);
|
||||
if (pFilename != NULL)
|
||||
{
|
||||
INFO_LOG(WII_IPC_DVD, "DVDLowRead: %s (0x%llx) - (DVDAddr: 0x%llx, Size: 0x%x)",
|
||||
@ -233,7 +235,7 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32
|
||||
|
||||
if (!VolumeHandler::ReadToPtr(Memory::GetPointer(_BufferOut), DVDAddress, Size))
|
||||
{
|
||||
PanicAlertT("Cant read from DVD_Plugin - DVD-Interface: Fatal Error");
|
||||
PanicAlertT("DVDLowRead - Fatal Error: failed to read from volume");
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -325,10 +327,9 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32
|
||||
PanicAlertT("Detected attempt to read more data from the DVD than fit inside the out buffer. Clamp.");
|
||||
Size = _BufferOutSize;
|
||||
}
|
||||
|
||||
if (!VolumeHandler::RAWReadToPtr(Memory::GetPointer(_BufferOut), DVDAddress, Size))
|
||||
if(!VolumeHandler::RAWReadToPtr(Memory::GetPointer(_BufferOut), DVDAddress, Size))
|
||||
{
|
||||
PanicAlertT("Cant read from DVD_Plugin - DVD-Interface: Fatal Error");
|
||||
PanicAlertT("DVDLowUnencryptedRead - Fatal Error: failed to read from volume");
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -348,7 +349,9 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32
|
||||
case DVDLowSeek:
|
||||
{
|
||||
u64 DVDAddress = Memory::Read_U32(_BufferIn + 0x4) << 2;
|
||||
const char *pFilename = m_pFileSystem->GetFileName(DVDAddress);
|
||||
const char *pFilename = NULL;
|
||||
if (m_pFileSystem)
|
||||
pFilename = m_pFileSystem->GetFileName(DVDAddress);
|
||||
if (pFilename != NULL)
|
||||
{
|
||||
INFO_LOG(WII_IPC_DVD, "DVDLowSeek: %s (0x%llx) - (DVDAddr: 0x%llx)",
|
||||
|
@ -120,7 +120,7 @@ bool CWII_IPC_HLE_Device_es::Open(u32 _CommandAddress, u32 _Mode)
|
||||
{
|
||||
// blindly grab the titleID from the disc - it's unencrypted at:
|
||||
// offset 0x0F8001DC and 0x0F80044C
|
||||
VolumeHandler::RAWReadToPtr((u8*)&m_TitleID, (u64)0x0F8001DC, 8);
|
||||
VolumeHandler::GetVolume()->GetTitleID((u8*)&m_TitleID);
|
||||
m_TitleID = Common::swap64(m_TitleID);
|
||||
}
|
||||
else
|
||||
@ -189,11 +189,11 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||
|
||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
||||
|
||||
const DiscIO::INANDContentLoader& rNANDCOntent = AccessContentDevice(TitleID);
|
||||
const DiscIO::INANDContentLoader& rNANDContent = AccessContentDevice(TitleID);
|
||||
u16 NumberOfPrivateContent = 0;
|
||||
if (rNANDCOntent.IsValid()) // Not sure if dolphin will ever fail this check
|
||||
if (rNANDContent.IsValid()) // Not sure if dolphin will ever fail this check
|
||||
{
|
||||
NumberOfPrivateContent = rNANDCOntent.GetNumEntries();
|
||||
NumberOfPrivateContent = rNANDContent.GetNumEntries();
|
||||
|
||||
if ((u32)(TitleID>>32) == 0x00010000)
|
||||
Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address);
|
||||
@ -203,10 +203,10 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
||||
}
|
||||
else
|
||||
Memory::Write_U32((u32)rNANDCOntent.GetContentSize(), _CommandAddress + 0x4);
|
||||
Memory::Write_U32((u32)rNANDContent.GetContentSize(), _CommandAddress + 0x4);
|
||||
|
||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTSCNT: TitleID: %08x/%08x content count %i",
|
||||
(u32)(TitleID>>32), (u32)TitleID, rNANDCOntent.IsValid() ? NumberOfPrivateContent : (u32)rNANDCOntent.GetContentSize());
|
||||
(u32)(TitleID>>32), (u32)TitleID, rNANDContent.IsValid() ? NumberOfPrivateContent : (u32)rNANDContent.GetContentSize());
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -266,24 +266,27 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_OPENCONTENT:
|
||||
{
|
||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1);
|
||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0);
|
||||
case IOCTL_ES_OPENCONTENT:
|
||||
{
|
||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1);
|
||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0);
|
||||
|
||||
u32 CFD = AccessIdentID++;
|
||||
u32 Index = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
||||
u32 CFD = AccessIdentID++;
|
||||
u32 Index = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
||||
|
||||
m_ContentAccessMap[CFD].m_Position = 0;
|
||||
m_ContentAccessMap[CFD].m_pContent = AccessContentDevice(m_TitleID).GetContentByIndex(Index);
|
||||
_dbg_assert_(WII_IPC_ES, m_ContentAccessMap[CFD].m_pContent != NULL);
|
||||
m_ContentAccessMap[CFD].m_Position = 0;
|
||||
m_ContentAccessMap[CFD].m_pContent = AccessContentDevice(m_TitleID).GetContentByIndex(Index);
|
||||
_dbg_assert_(WII_IPC_ES, m_ContentAccessMap[CFD].m_pContent != NULL);
|
||||
|
||||
Memory::Write_U32(CFD, _CommandAddress + 0x4);
|
||||
if (m_ContentAccessMap[CFD].m_pContent == NULL)
|
||||
CFD = 0xffffffff; //TODO: what is the correct error value here?
|
||||
|
||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
Memory::Write_U32(CFD, _CommandAddress + 0x4);
|
||||
|
||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_READCONTENT:
|
||||
{
|
||||
@ -383,7 +386,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
||||
|
||||
char* Path = (char*)Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address);
|
||||
sprintf(Path, "/%08x/%08x/data", (u32)(TitleID >> 32), (u32)TitleID);
|
||||
sprintf(Path, "/title/%08x/%08x/data", (u32)(TitleID >> 32), (u32)TitleID);
|
||||
|
||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLEDIR: %s", Path);
|
||||
}
|
||||
@ -551,11 +554,6 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||
|
||||
const DiscIO::INANDContentLoader& Loader = AccessContentDevice(TitleID);
|
||||
|
||||
// Assert if title is not a disc title and the loader is not valid
|
||||
_dbg_assert_msg_(WII_IPC_ES, ((u32)(TitleID >> 32) == 0x00010000) ||
|
||||
((u32)(TitleID >> 32) == 0x00010004) || Loader.IsValid(),
|
||||
"Loader not valid for TitleID %08x/%08x", (u32)(TitleID >> 32), (u32)TitleID);
|
||||
|
||||
u32 TMDViewCnt = 0;
|
||||
if (Loader.IsValid())
|
||||
{
|
||||
@ -687,7 +685,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||
// TODO: actually use this param in when writing to the outbuffer :/
|
||||
MaxCount = Memory::Read_U32(Buffer.InBuffer[1].m_Address);
|
||||
}
|
||||
const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitleID);
|
||||
const DiscIO::INANDContentLoader& Loader = AccessContentDevice(TitleID);
|
||||
|
||||
|
||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x buffersize: %i", (u32)(TitleID >> 32), (u32)TitleID, MaxCount);
|
||||
@ -1003,7 +1001,7 @@ const DiscIO::INANDContentLoader& CWII_IPC_HLE_Device_es::AccessContentDevice(u6
|
||||
|
||||
m_NANDContent[_TitleID] = &DiscIO::CNANDContentManager::Access().GetNANDLoader(_TitleID);
|
||||
|
||||
_dbg_assert_msg_(WII_IPC_ES, m_NANDContent[_TitleID]->IsValid(), "NandContent not valid for TitleID %08x/%08x", (u32)(_TitleID >> 32), (u32)_TitleID);
|
||||
_dbg_assert_msg_(WII_IPC_ES, ((u32)(_TitleID >> 32) == 0x00010000) || m_NANDContent[_TitleID]->IsValid(), "NandContent not valid for TitleID %08x/%08x", (u32)(_TitleID >> 32), (u32)_TitleID);
|
||||
return *m_NANDContent[_TitleID];
|
||||
}
|
||||
|
||||
@ -1025,11 +1023,10 @@ u32 CWII_IPC_HLE_Device_es::ES_DIVerify(u8* _pTMD, u32 _sz)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
std::string tmdPath = Common::GetTMDFileName(tmdTitleID),
|
||||
dataPath = Common::GetTitleDataPath(tmdTitleID);
|
||||
std::string tmdPath = Common::GetTMDFileName(tmdTitleID);
|
||||
|
||||
File::CreateFullPath(tmdPath);
|
||||
File::CreateFullPath(dataPath);
|
||||
File::CreateFullPath(Common::GetTitleDataPath(tmdTitleID));
|
||||
if(!File::Exists(tmdPath))
|
||||
{
|
||||
File::IOFile _pTMDFile(tmdPath, "wb");
|
||||
|
@ -401,7 +401,7 @@ void Interpreter::dcbtst(UGeckoInstruction _inst)
|
||||
void Interpreter::dcbz(UGeckoInstruction _inst)
|
||||
{
|
||||
// HACK but works... we think
|
||||
if (!HID0.DCFA)
|
||||
if (HID2.WPE || !HID0.DCFA)
|
||||
Memory::Memset(Helper_Get_EA_X(_inst) & (~31), 0, 32);
|
||||
}
|
||||
|
||||
|
@ -150,6 +150,8 @@ public:
|
||||
void GenerateConstantOverflow(bool overflow);
|
||||
void GenerateOverflow();
|
||||
void FinalizeCarryOverflow(bool oe, bool inv = false);
|
||||
void GetCarryEAXAndClear();
|
||||
void FinalizeCarryGenerateOverflowEAX(bool oe, bool inv = false);
|
||||
void GenerateCarry();
|
||||
void GenerateRC();
|
||||
void ComputeRC(const Gen::OpArg & arg);
|
||||
@ -177,6 +179,7 @@ public:
|
||||
void mulhwux(UGeckoInstruction inst);
|
||||
void mullwx(UGeckoInstruction inst);
|
||||
void divwux(UGeckoInstruction inst);
|
||||
void divwx(UGeckoInstruction inst);
|
||||
void srawix(UGeckoInstruction inst);
|
||||
void srawx(UGeckoInstruction inst);
|
||||
void addex(UGeckoInstruction inst);
|
||||
|
@ -311,8 +311,8 @@ static GekkoOPTemplate table31_2[] =
|
||||
{138, &Jit64::addex}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
|
||||
{234, &Jit64::addmex}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
|
||||
{202, &Jit64::addzex}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
|
||||
{491, &Jit64::Default}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
|
||||
{1003, &Jit64::Default}, //"divwox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
|
||||
{491, &Jit64::divwx}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
|
||||
{1003, &Jit64::divwx}, //"divwox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
|
||||
{459, &Jit64::divwux}, //"divwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
|
||||
{971, &Jit64::divwux}, //"divwuox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
|
||||
{75, &Jit64::Default}, //"mulhwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
|
||||
|
@ -73,13 +73,53 @@ void Jit64::FinalizeCarryOverflow(bool oe, bool inv)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Output carry is inverted
|
||||
// Do carry
|
||||
FixupBranch carry1 = J_CC(inv ? CC_C : CC_NC);
|
||||
JitSetCA();
|
||||
SetJumpTarget(carry1);
|
||||
}
|
||||
}
|
||||
|
||||
void Jit64::GetCarryEAXAndClear()
|
||||
{
|
||||
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||
BTR(32, R(EAX), Imm8(29));
|
||||
}
|
||||
|
||||
// Assumes that XER is in EAX and that the CA bit is clear.
|
||||
void Jit64::FinalizeCarryGenerateOverflowEAX(bool oe, bool inv)
|
||||
{
|
||||
// USES_XER
|
||||
if (oe)
|
||||
{
|
||||
FixupBranch jno = J_CC(CC_NO);
|
||||
// Do carry
|
||||
FixupBranch carry1 = J_CC(inv ? CC_C : CC_NC);
|
||||
OR(32, R(EAX), Imm32(XER_CA_MASK));
|
||||
SetJumpTarget(carry1);
|
||||
//XER[OV/SO] = 1
|
||||
OR(32, R(EAX), Imm32(XER_SO_MASK | XER_OV_MASK));
|
||||
FixupBranch exit = J();
|
||||
SetJumpTarget(jno);
|
||||
// Do carry
|
||||
FixupBranch carry2 = J_CC(inv ? CC_C : CC_NC);
|
||||
OR(32, R(EAX), Imm32(XER_CA_MASK));
|
||||
SetJumpTarget(carry2);
|
||||
//XER[OV] = 0
|
||||
AND(32, R(EAX), Imm32(~XER_OV_MASK));
|
||||
SetJumpTarget(exit);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do carry
|
||||
FixupBranch carry1 = J_CC(inv ? CC_C : CC_NC);
|
||||
OR(32, R(EAX), Imm32(XER_CA_MASK));
|
||||
SetJumpTarget(carry1);
|
||||
}
|
||||
// Dump EAX back into XER
|
||||
MOV(32, M(&PowerPC::ppcState.spr[SPR_XER]), R(EAX));
|
||||
}
|
||||
|
||||
// Assumes that the flags were just set through an addition.
|
||||
void Jit64::GenerateCarry() {
|
||||
// USES_XER
|
||||
@ -122,7 +162,10 @@ void Jit64::ComputeRC(const Gen::OpArg & arg) {
|
||||
}
|
||||
else
|
||||
{
|
||||
CMP(32, arg, Imm8(0));
|
||||
if (arg.IsSimpleReg())
|
||||
TEST(32, arg, arg);
|
||||
else
|
||||
CMP(32, arg, Imm8(0));
|
||||
FixupBranch pLesser = J_CC(CC_L);
|
||||
FixupBranch pGreater = J_CC(CC_G);
|
||||
MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x2)); // _x86Reg == 0
|
||||
@ -908,33 +951,31 @@ void Jit64::subfex(UGeckoInstruction inst)
|
||||
gpr.Lock(a, b, d);
|
||||
gpr.BindToRegister(d, (d == a || d == b), true);
|
||||
|
||||
// Get CA and clear it (along with OV if applicable)
|
||||
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||
JitClearCAOV(inst.OE);
|
||||
SHR(32, R(EAX), Imm8(30));
|
||||
|
||||
// Convert carry to borrow
|
||||
CMC();
|
||||
GetCarryEAXAndClear();
|
||||
|
||||
bool invertedCarry = false;
|
||||
if (d == b)
|
||||
{
|
||||
// Convert carry to borrow
|
||||
CMC();
|
||||
SBB(32, gpr.R(d), gpr.R(a));
|
||||
invertedCarry = true;
|
||||
}
|
||||
else if (d == a)
|
||||
{
|
||||
MOV(32, R(EAX), gpr.R(a));
|
||||
MOV(32, gpr.R(d), gpr.R(b));
|
||||
SBB(32, gpr.R(d), R(EAX));
|
||||
NOT(32, gpr.R(d));
|
||||
ADC(32, gpr.R(d), gpr.R(b));
|
||||
}
|
||||
else
|
||||
{
|
||||
MOV(32, gpr.R(d), gpr.R(b));
|
||||
SBB(32, gpr.R(d), gpr.R(a));
|
||||
MOV(32, gpr.R(d), gpr.R(a));
|
||||
NOT(32, gpr.R(d));
|
||||
ADC(32, gpr.R(d), gpr.R(b));
|
||||
}
|
||||
if (inst.Rc) {
|
||||
GenerateRC();
|
||||
}
|
||||
FinalizeCarryOverflow(inst.OE, true);
|
||||
FinalizeCarryGenerateOverflowEAX(inst.OE, invertedCarry);
|
||||
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
@ -948,9 +989,7 @@ void Jit64::subfmex(UGeckoInstruction inst)
|
||||
gpr.Lock(a, d);
|
||||
gpr.BindToRegister(d, d == a);
|
||||
|
||||
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||
JitClearCAOV(inst.OE);
|
||||
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||
GetCarryEAXAndClear();
|
||||
if (d != a)
|
||||
{
|
||||
MOV(32, gpr.R(d), gpr.R(a));
|
||||
@ -961,7 +1000,7 @@ void Jit64::subfmex(UGeckoInstruction inst)
|
||||
{
|
||||
GenerateRC();
|
||||
}
|
||||
FinalizeCarryOverflow(inst.OE);
|
||||
FinalizeCarryGenerateOverflowEAX(inst.OE);
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
|
||||
@ -974,9 +1013,8 @@ void Jit64::subfzex(UGeckoInstruction inst)
|
||||
|
||||
gpr.Lock(a, d);
|
||||
gpr.BindToRegister(d, d == a);
|
||||
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||
JitClearCAOV(inst.OE);
|
||||
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||
|
||||
GetCarryEAXAndClear();
|
||||
if (d != a)
|
||||
{
|
||||
MOV(32, gpr.R(d), gpr.R(a));
|
||||
@ -987,7 +1025,7 @@ void Jit64::subfzex(UGeckoInstruction inst)
|
||||
{
|
||||
GenerateRC();
|
||||
}
|
||||
FinalizeCarryOverflow(inst.OE);
|
||||
FinalizeCarryGenerateOverflowEAX(inst.OE);
|
||||
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
@ -1047,17 +1085,39 @@ void Jit64::mulli(UGeckoInstruction inst)
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(Integer)
|
||||
int a = inst.RA, d = inst.RD;
|
||||
u32 imm = inst.SIMM_16;
|
||||
|
||||
if (gpr.R(a).IsImm())
|
||||
{
|
||||
gpr.SetImmediate32(d, (s32)gpr.R(a).offset * (s32)inst.SIMM_16);
|
||||
gpr.SetImmediate32(d, (u32)gpr.R(a).offset * imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpr.Lock(a, d);
|
||||
gpr.BindToRegister(d, (d == a), true);
|
||||
gpr.KillImmediate(a, true, false);
|
||||
IMUL(32, gpr.RX(d), gpr.R(a), Imm32((u32)(s32)inst.SIMM_16));
|
||||
if (imm == 0)
|
||||
XOR(32, gpr.R(d), gpr.R(d));
|
||||
else if(imm == -1)
|
||||
{
|
||||
if (d != a)
|
||||
MOV(32, gpr.R(d), gpr.R(a));
|
||||
NEG(32, gpr.R(d));
|
||||
}
|
||||
else if((imm & (imm - 1)) == 0)
|
||||
{
|
||||
u32 shift = 0;
|
||||
if (imm & 0xFFFF0000) shift |= 16;
|
||||
if (imm & 0xFF00FF00) shift |= 8;
|
||||
if (imm & 0xF0F0F0F0) shift |= 4;
|
||||
if (imm & 0xCCCCCCCC) shift |= 2;
|
||||
if (imm & 0xAAAAAAAA) shift |= 1;
|
||||
if (d != a)
|
||||
MOV(32, gpr.R(d), gpr.R(a));
|
||||
if (shift)
|
||||
SHL(32, gpr.R(d), Imm8(shift));
|
||||
}
|
||||
else
|
||||
IMUL(32, gpr.RX(d), gpr.R(a), Imm32(imm));
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
}
|
||||
@ -1081,13 +1141,42 @@ void Jit64::mullwx(UGeckoInstruction inst)
|
||||
{
|
||||
gpr.Lock(a, b, d);
|
||||
gpr.BindToRegister(d, (d == a || d == b), true);
|
||||
if (d == a) {
|
||||
if (gpr.R(a).IsImm() || gpr.R(b).IsImm())
|
||||
{
|
||||
u32 imm = gpr.R(a).IsImm() ? (u32)gpr.R(a).offset : (u32)gpr.R(b).offset;
|
||||
int src = gpr.R(a).IsImm() ? b : a;
|
||||
if (imm == 0)
|
||||
XOR(32, gpr.R(d), gpr.R(d));
|
||||
else if(imm == -1)
|
||||
{
|
||||
if (d != src)
|
||||
MOV(32, gpr.R(d), gpr.R(src));
|
||||
NEG(32, gpr.R(d));
|
||||
}
|
||||
else if((imm & (imm - 1)) == 0 && !inst.OE)
|
||||
{
|
||||
u32 shift = 0;
|
||||
if (imm & 0xFFFF0000) shift |= 16;
|
||||
if (imm & 0xFF00FF00) shift |= 8;
|
||||
if (imm & 0xF0F0F0F0) shift |= 4;
|
||||
if (imm & 0xCCCCCCCC) shift |= 2;
|
||||
if (imm & 0xAAAAAAAA) shift |= 1;
|
||||
if (d != src)
|
||||
MOV(32, gpr.R(d), gpr.R(src));
|
||||
if (shift)
|
||||
SHL(32, gpr.R(d), Imm8(shift));
|
||||
}
|
||||
else
|
||||
IMUL(32, gpr.RX(d), gpr.R(src), Imm32(imm));
|
||||
}
|
||||
else if (d == a)
|
||||
IMUL(32, gpr.RX(d), gpr.R(b));
|
||||
} else if (d == b) {
|
||||
IMUL(32, gpr.RX(d), gpr.R(a));
|
||||
} else {
|
||||
MOV(32, gpr.R(d), gpr.R(b));
|
||||
else if (d == b)
|
||||
IMUL(32, gpr.RX(d), gpr.R(a));
|
||||
else
|
||||
{
|
||||
MOV(32, gpr.R(d), gpr.R(b));
|
||||
IMUL(32, gpr.RX(d), gpr.R(a));
|
||||
}
|
||||
if (inst.OE)
|
||||
{
|
||||
@ -1157,6 +1246,103 @@ void Jit64::divwux(UGeckoInstruction inst)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (gpr.R(b).IsImm())
|
||||
{
|
||||
u32 divisor = (u32)gpr.R(b).offset;
|
||||
if (divisor == 0)
|
||||
{
|
||||
gpr.SetImmediate32(d, 0);
|
||||
if (inst.OE)
|
||||
{
|
||||
GenerateConstantOverflow(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 shift = 31;
|
||||
while(!(divisor & (1 << shift)))
|
||||
shift--;
|
||||
|
||||
if (divisor == (1 << shift))
|
||||
{
|
||||
gpr.Lock(a, b, d);
|
||||
gpr.BindToRegister(d, d == a, true);
|
||||
if (d != a)
|
||||
MOV(32, gpr.R(d), gpr.R(a));
|
||||
if (shift)
|
||||
SHR(32, gpr.R(d), Imm8(shift));
|
||||
}
|
||||
else
|
||||
{
|
||||
u64 magic_dividend = 0x100000000ULL << shift;
|
||||
u32 magic = (u32)(magic_dividend / divisor);
|
||||
u32 max_quotient = magic >> shift;
|
||||
|
||||
// Test for failure in round-up method
|
||||
if (((u64)(magic+1) * (max_quotient*divisor-1)) >> (shift + 32) != max_quotient-1)
|
||||
{
|
||||
// If failed, use slower round-down method
|
||||
#ifdef _M_X64
|
||||
gpr.Lock(a, b, d);
|
||||
gpr.BindToRegister(d, d == a, true);
|
||||
MOV(32, R(EAX), Imm32(magic));
|
||||
if (d != a)
|
||||
MOV(32, gpr.R(d), gpr.R(a));
|
||||
IMUL(64, gpr.RX(d), R(RAX));
|
||||
ADD(64, gpr.R(d), R(RAX));
|
||||
SHR(64, gpr.R(d), Imm8(shift+32));
|
||||
#else
|
||||
gpr.FlushLockX(EDX);
|
||||
gpr.Lock(a, b, d);
|
||||
gpr.BindToRegister(d, d == a, true);
|
||||
MOV(32, R(EAX), Imm32(magic));
|
||||
MUL(32, gpr.R(a));
|
||||
XOR(32, gpr.R(d), gpr.R(d));
|
||||
ADD(32, R(EAX), Imm32(magic));
|
||||
ADC(32, gpr.R(d), R(EDX));
|
||||
if (shift)
|
||||
SHR(32, gpr.R(d), Imm8(shift));
|
||||
gpr.UnlockAllX();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// If success, use faster round-up method
|
||||
#ifdef _M_X64
|
||||
gpr.Lock(a, b, d);
|
||||
gpr.BindToRegister(a, true, false);
|
||||
gpr.BindToRegister(d, false, true);
|
||||
if (d == a)
|
||||
{
|
||||
MOV(32, R(EAX), Imm32(magic+1));
|
||||
IMUL(64, gpr.RX(d), R(RAX));
|
||||
}
|
||||
else
|
||||
{
|
||||
MOV(32, gpr.R(d), Imm32(magic+1));
|
||||
IMUL(64, gpr.RX(d), gpr.R(a));
|
||||
}
|
||||
SHR(64, gpr.R(d), Imm8(shift+32));
|
||||
#else
|
||||
gpr.FlushLockX(EDX);
|
||||
gpr.Lock(a, b, d);
|
||||
gpr.BindToRegister(d, d == a, true);
|
||||
MOV(32, R(EAX), Imm32(magic+1));
|
||||
MUL(32, gpr.R(a));
|
||||
MOV(32, gpr.R(d), R(EDX));
|
||||
if (shift)
|
||||
SHR(32, gpr.R(d), Imm8(shift));
|
||||
gpr.UnlockAllX();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (inst.OE)
|
||||
{
|
||||
GenerateConstantOverflow(false);
|
||||
}
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gpr.FlushLockX(EDX);
|
||||
@ -1166,7 +1352,6 @@ void Jit64::divwux(UGeckoInstruction inst)
|
||||
XOR(32, R(EDX), R(EDX));
|
||||
gpr.KillImmediate(b, true, false);
|
||||
CMP(32, gpr.R(b), Imm32(0));
|
||||
// doesn't handle if OE is set, but int doesn't either...
|
||||
FixupBranch not_div_by_zero = J_CC(CC_NZ);
|
||||
MOV(32, gpr.R(d), R(EDX));
|
||||
if (inst.OE)
|
||||
@ -1193,6 +1378,80 @@ void Jit64::divwux(UGeckoInstruction inst)
|
||||
}
|
||||
}
|
||||
|
||||
void Jit64::divwx(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(Integer)
|
||||
int a = inst.RA, b = inst.RB, d = inst.RD;
|
||||
|
||||
if (gpr.R(a).IsImm() && gpr.R(b).IsImm())
|
||||
{
|
||||
s32 i = (s32)gpr.R(a).offset, j = (s32)gpr.R(b).offset;
|
||||
if( j == 0 || i == 0x80000000 && j == -1)
|
||||
{
|
||||
gpr.SetImmediate32(d, (i >> 31) ^ j);
|
||||
if (inst.OE)
|
||||
{
|
||||
GenerateConstantOverflow(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gpr.SetImmediate32(d, i / j);
|
||||
if (inst.OE)
|
||||
{
|
||||
GenerateConstantOverflow(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gpr.FlushLockX(EDX);
|
||||
gpr.Lock(a, b, d);
|
||||
gpr.BindToRegister(d, (d == a || d == b), true);
|
||||
MOV(32, R(EAX), gpr.R(a));
|
||||
CDQ();
|
||||
gpr.BindToRegister(b, true, false);
|
||||
TEST(32, gpr.R(b), gpr.R(b));
|
||||
FixupBranch not_div_by_zero = J_CC(CC_NZ);
|
||||
MOV(32, gpr.R(d), R(EDX));
|
||||
if (inst.OE)
|
||||
{
|
||||
GenerateConstantOverflow(true);
|
||||
}
|
||||
FixupBranch end1 = J();
|
||||
SetJumpTarget(not_div_by_zero);
|
||||
CMP(32, gpr.R(b), R(EDX));
|
||||
FixupBranch not_div_by_neg_one = J_CC(CC_NZ);
|
||||
MOV(32, gpr.R(d), R(EAX));
|
||||
NEG(32, gpr.R(d));
|
||||
FixupBranch no_overflow = J_CC(CC_NO);
|
||||
XOR(32, gpr.R(d), gpr.R(d));
|
||||
if (inst.OE)
|
||||
{
|
||||
GenerateConstantOverflow(true);
|
||||
}
|
||||
FixupBranch end2 = J();
|
||||
SetJumpTarget(not_div_by_neg_one);
|
||||
IDIV(32, gpr.R(b));
|
||||
MOV(32, gpr.R(d), R(EAX));
|
||||
SetJumpTarget(no_overflow);
|
||||
if (inst.OE)
|
||||
{
|
||||
GenerateConstantOverflow(false);
|
||||
}
|
||||
SetJumpTarget(end1);
|
||||
SetJumpTarget(end2);
|
||||
gpr.UnlockAll();
|
||||
gpr.UnlockAllX();
|
||||
}
|
||||
|
||||
if (inst.Rc)
|
||||
{
|
||||
ComputeRC(gpr.R(d));
|
||||
}
|
||||
}
|
||||
|
||||
void Jit64::addx(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START
|
||||
@ -1264,31 +1523,29 @@ void Jit64::addex(UGeckoInstruction inst)
|
||||
{
|
||||
gpr.Lock(a, b, d);
|
||||
gpr.BindToRegister(d, true);
|
||||
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||
JitClearCAOV(inst.OE);
|
||||
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||
|
||||
GetCarryEAXAndClear();
|
||||
ADC(32, gpr.R(d), gpr.R((d == a) ? b : a));
|
||||
if (inst.Rc)
|
||||
{
|
||||
GenerateRC();
|
||||
}
|
||||
FinalizeCarryOverflow(inst.OE);
|
||||
FinalizeCarryGenerateOverflowEAX(inst.OE);
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
gpr.Lock(a, b, d);
|
||||
gpr.BindToRegister(d, false);
|
||||
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||
JitClearCAOV(inst.OE);
|
||||
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||
|
||||
GetCarryEAXAndClear();
|
||||
MOV(32, gpr.R(d), gpr.R(a));
|
||||
ADC(32, gpr.R(d), gpr.R(b));
|
||||
if (inst.Rc)
|
||||
{
|
||||
GenerateRC();
|
||||
}
|
||||
FinalizeCarryOverflow(inst.OE);
|
||||
FinalizeCarryGenerateOverflowEAX(inst.OE);
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
}
|
||||
@ -1340,31 +1597,29 @@ void Jit64::addmex(UGeckoInstruction inst)
|
||||
{
|
||||
gpr.Lock(d);
|
||||
gpr.BindToRegister(d, true);
|
||||
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||
JitClearCAOV(inst.OE);
|
||||
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||
|
||||
GetCarryEAXAndClear();
|
||||
ADC(32, gpr.R(d), Imm32(0xFFFFFFFF));
|
||||
if (inst.Rc)
|
||||
{
|
||||
GenerateRC();
|
||||
}
|
||||
FinalizeCarryOverflow(inst.OE);
|
||||
FinalizeCarryGenerateOverflowEAX(inst.OE);
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
gpr.Lock(a, d);
|
||||
gpr.BindToRegister(d, false);
|
||||
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||
JitClearCAOV(inst.OE);
|
||||
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||
|
||||
GetCarryEAXAndClear();
|
||||
MOV(32, gpr.R(d), gpr.R(a));
|
||||
ADC(32, gpr.R(d), Imm32(0xFFFFFFFF));
|
||||
if (inst.Rc)
|
||||
{
|
||||
GenerateRC();
|
||||
}
|
||||
FinalizeCarryOverflow(inst.OE);
|
||||
FinalizeCarryGenerateOverflowEAX(inst.OE);
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
}
|
||||
@ -1380,31 +1635,29 @@ void Jit64::addzex(UGeckoInstruction inst)
|
||||
{
|
||||
gpr.Lock(d);
|
||||
gpr.BindToRegister(d, true);
|
||||
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||
JitClearCAOV(inst.OE);
|
||||
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||
|
||||
GetCarryEAXAndClear();
|
||||
ADC(32, gpr.R(d), Imm8(0));
|
||||
if (inst.Rc)
|
||||
{
|
||||
GenerateRC();
|
||||
}
|
||||
FinalizeCarryOverflow(inst.OE);
|
||||
FinalizeCarryGenerateOverflowEAX(inst.OE);
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
gpr.Lock(a, d);
|
||||
gpr.BindToRegister(d, false);
|
||||
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||
JitClearCAOV(inst.OE);
|
||||
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||
|
||||
GetCarryEAXAndClear();
|
||||
MOV(32, gpr.R(d), gpr.R(a));
|
||||
ADC(32, gpr.R(d), Imm8(0));
|
||||
if (inst.Rc)
|
||||
{
|
||||
GenerateRC();
|
||||
}
|
||||
FinalizeCarryOverflow(inst.OE);
|
||||
FinalizeCarryGenerateOverflowEAX(inst.OE);
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
}
|
||||
@ -1581,7 +1834,7 @@ void Jit64::rlwnmx(UGeckoInstruction inst)
|
||||
{
|
||||
gpr.FlushLockX(ECX);
|
||||
gpr.Lock(a, b, s);
|
||||
gpr.BindToRegister(a, true, true);
|
||||
gpr.BindToRegister(a, (a == b || a == s), true);
|
||||
MOV(32, R(ECX), gpr.R(b));
|
||||
if (a != s)
|
||||
{
|
||||
@ -1651,9 +1904,22 @@ void Jit64::srwx(UGeckoInstruction inst)
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _M_X64
|
||||
gpr.FlushLockX(ECX);
|
||||
gpr.Lock(a, b, s);
|
||||
gpr.BindToRegister(a, true, true);
|
||||
gpr.BindToRegister(a, (a == b || a == s), true);
|
||||
MOV(32, R(ECX), gpr.R(b));
|
||||
if (a != s)
|
||||
{
|
||||
MOV(32, gpr.R(a), gpr.R(s));
|
||||
}
|
||||
SHR(64, gpr.R(a), R(ECX));
|
||||
gpr.UnlockAll();
|
||||
gpr.UnlockAllX();
|
||||
#else
|
||||
gpr.FlushLockX(ECX);
|
||||
gpr.Lock(a, b, s);
|
||||
gpr.BindToRegister(a, (a == b || a == s), true);
|
||||
MOV(32, R(ECX), gpr.R(b));
|
||||
TEST(32, R(ECX), Imm32(32));
|
||||
if (a != s)
|
||||
@ -1666,6 +1932,7 @@ void Jit64::srwx(UGeckoInstruction inst)
|
||||
SHR(32, gpr.R(a), R(ECX));
|
||||
gpr.UnlockAll();
|
||||
gpr.UnlockAllX();
|
||||
#endif
|
||||
}
|
||||
// Shift of 0 doesn't update flags, so compare manually just in case
|
||||
if (inst.Rc)
|
||||
@ -1686,12 +1953,38 @@ void Jit64::slwx(UGeckoInstruction inst)
|
||||
{
|
||||
u32 amount = (u32)gpr.R(b).offset;
|
||||
gpr.SetImmediate32(a, (amount & 0x20) ? 0 : (u32)gpr.R(s).offset << amount);
|
||||
if (inst.Rc)
|
||||
{
|
||||
ComputeRC(gpr.R(a));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _M_X64
|
||||
gpr.FlushLockX(ECX);
|
||||
gpr.Lock(a, b, s);
|
||||
gpr.BindToRegister(a, true, true);
|
||||
gpr.BindToRegister(a, (a == b || a == s), true);
|
||||
MOV(32, R(ECX), gpr.R(b));
|
||||
if (a != s)
|
||||
{
|
||||
MOV(32, gpr.R(a), gpr.R(s));
|
||||
}
|
||||
SHL(64, gpr.R(a), R(ECX));
|
||||
if (inst.Rc)
|
||||
{
|
||||
AND(32, gpr.R(a), gpr.R(a));
|
||||
GenerateRC();
|
||||
}
|
||||
else
|
||||
{
|
||||
MOV(32, gpr.R(a), gpr.R(a));
|
||||
}
|
||||
gpr.UnlockAll();
|
||||
gpr.UnlockAllX();
|
||||
#else
|
||||
gpr.FlushLockX(ECX);
|
||||
gpr.Lock(a, b, s);
|
||||
gpr.BindToRegister(a, (a == b || a == s), true);
|
||||
MOV(32, R(ECX), gpr.R(b));
|
||||
TEST(32, R(ECX), Imm32(32));
|
||||
if (a != s)
|
||||
@ -1704,11 +1997,12 @@ void Jit64::slwx(UGeckoInstruction inst)
|
||||
SHL(32, gpr.R(a), R(ECX));
|
||||
gpr.UnlockAll();
|
||||
gpr.UnlockAllX();
|
||||
}
|
||||
// Shift of 0 doesn't update flags, so compare manually just in case
|
||||
if (inst.Rc)
|
||||
{
|
||||
ComputeRC(gpr.R(a));
|
||||
// Shift of 0 doesn't update flags, so compare manually just in case
|
||||
if (inst.Rc)
|
||||
{
|
||||
ComputeRC(gpr.R(a));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -1720,19 +2014,37 @@ void Jit64::srawx(UGeckoInstruction inst)
|
||||
int a = inst.RA;
|
||||
int b = inst.RB;
|
||||
int s = inst.RS;
|
||||
#ifdef _M_X64
|
||||
gpr.Lock(a, s, b);
|
||||
gpr.FlushLockX(ECX);
|
||||
gpr.BindToRegister(a, true, true);
|
||||
gpr.BindToRegister(a, (a == s || a == b), true);
|
||||
JitClearCA();
|
||||
MOV(32, R(ECX), gpr.R(b));
|
||||
if (a != s)
|
||||
MOV(32, gpr.R(a), gpr.R(s));
|
||||
SHL(64, gpr.R(a), Imm8(32));
|
||||
SAR(64, gpr.R(a), R(ECX));
|
||||
MOV(32, R(EAX), gpr.R(a));
|
||||
SHR(64, gpr.R(a), Imm8(32));
|
||||
TEST(32, gpr.R(a), R(EAX));
|
||||
FixupBranch nocarry = J_CC(CC_Z);
|
||||
JitSetCA();
|
||||
SetJumpTarget(nocarry);
|
||||
gpr.UnlockAll();
|
||||
gpr.UnlockAllX();
|
||||
#else
|
||||
gpr.Lock(a, s, b);
|
||||
gpr.FlushLockX(ECX);
|
||||
gpr.BindToRegister(a, (a == s || a == b), true);
|
||||
JitClearCA();
|
||||
MOV(32, R(ECX), gpr.R(b));
|
||||
if (a != s)
|
||||
MOV(32, gpr.R(a), gpr.R(s));
|
||||
TEST(32, R(ECX), Imm32(32));
|
||||
FixupBranch topBitSet = J_CC(CC_NZ);
|
||||
LEA(32, EAX, MComplex(gpr.RX(a), gpr.RX(a), 1, 0));
|
||||
XOR(32, R(EAX), R(EAX));
|
||||
SHRD(32, R(EAX), gpr.R(a), R(ECX));
|
||||
SAR(32, gpr.R(a), R(ECX));
|
||||
NOT(32, R(ECX));
|
||||
SHL(32, R(EAX), R(ECX));
|
||||
TEST(32, R(EAX), gpr.R(a));
|
||||
FixupBranch nocarry1 = J_CC(CC_Z);
|
||||
JitSetCA();
|
||||
@ -1746,7 +2058,7 @@ void Jit64::srawx(UGeckoInstruction inst)
|
||||
SetJumpTarget(nocarry2);
|
||||
gpr.UnlockAll();
|
||||
gpr.UnlockAllX();
|
||||
|
||||
#endif
|
||||
if (inst.Rc) {
|
||||
ComputeRC(gpr.R(a));
|
||||
}
|
||||
|
Reference in New Issue
Block a user