mirror of https://github.com/PCSX2/pcsx2.git
wxgui: another sync with trunk to pick up more of those cdvd fixes.
git-svn-id: http://pcsx2.googlecode.com/svn/branches/wxgui@1711 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
commit
635596c412
|
@ -592,8 +592,22 @@ typedef void (CALLBACK* _SPU2async)(u32 cycles);
|
||||||
// NOTE: The read/write functions CANNOT use XMM/MMX regs
|
// NOTE: The read/write functions CANNOT use XMM/MMX regs
|
||||||
// If you want to use them, need to save and restore current ones
|
// If you want to use them, need to save and restore current ones
|
||||||
typedef s32 (CALLBACK* _CDVDopen)(const char* pTitleFilename);
|
typedef s32 (CALLBACK* _CDVDopen)(const char* pTitleFilename);
|
||||||
|
|
||||||
|
// Initiates an asynchronous track read operation.
|
||||||
|
// Returns -1 on error (invalid track)
|
||||||
|
// Returns 0 on success.
|
||||||
typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode);
|
typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode);
|
||||||
|
|
||||||
|
// *OBSOLETE* returns a pointer to the buffer, or NULL if data hasn't finished
|
||||||
|
// loading yet.
|
||||||
typedef u8* (CALLBACK* _CDVDgetBuffer)();
|
typedef u8* (CALLBACK* _CDVDgetBuffer)();
|
||||||
|
|
||||||
|
// Copies loaded data to the target buffer.
|
||||||
|
// Returns -2 if the asynchronous read is still pending.
|
||||||
|
// Returns -1 if the asyncronous read failed.
|
||||||
|
// Returns 0 on success.
|
||||||
|
typedef s32 (CALLBACK* _CDVDgetBuffer2)(u8* buffer);
|
||||||
|
|
||||||
typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq);
|
typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq);
|
||||||
typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer);
|
typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer);
|
||||||
typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer);
|
typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer);
|
||||||
|
@ -603,7 +617,6 @@ typedef s32 (CALLBACK* _CDVDgetTrayStatus)();
|
||||||
typedef s32 (CALLBACK* _CDVDctrlTrayOpen)();
|
typedef s32 (CALLBACK* _CDVDctrlTrayOpen)();
|
||||||
typedef s32 (CALLBACK* _CDVDctrlTrayClose)();
|
typedef s32 (CALLBACK* _CDVDctrlTrayClose)();
|
||||||
typedef s32 (CALLBACK* _CDVDreadSector)(u8* buffer, u32 lsn, int mode);
|
typedef s32 (CALLBACK* _CDVDreadSector)(u8* buffer, u32 lsn, int mode);
|
||||||
typedef s32 (CALLBACK* _CDVDgetBuffer2)(u8* buffer);
|
|
||||||
typedef s32 (CALLBACK* _CDVDgetDualInfo)(s32* dualType, u32* _layer1start);
|
typedef s32 (CALLBACK* _CDVDgetDualInfo)(s32* dualType, u32* _layer1start);
|
||||||
|
|
||||||
typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)());
|
typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)());
|
||||||
|
|
|
@ -59,7 +59,7 @@ extern SessionOverrideFlags g_Session;
|
||||||
//------------ CPU Options!!! ---------------
|
//------------ CPU Options!!! ---------------
|
||||||
#define CHECK_MICROVU0 (Config.Options&PCSX2_MICROVU0)
|
#define CHECK_MICROVU0 (Config.Options&PCSX2_MICROVU0)
|
||||||
#define CHECK_MICROVU1 (Config.Options&PCSX2_MICROVU1)
|
#define CHECK_MICROVU1 (Config.Options&PCSX2_MICROVU1)
|
||||||
//#define CHECK_MACROVU0 // ifndef = Use sVU for VU macro, ifdef = Use mVU for VU macro
|
#define CHECK_MACROVU0 // ifndef = Use sVU for VU macro, ifdef = Use mVU for VU macro
|
||||||
#define CHECK_EEREC (!g_Session.ForceDisableEErec && Config.Options&PCSX2_EEREC)
|
#define CHECK_EEREC (!g_Session.ForceDisableEErec && Config.Options&PCSX2_EEREC)
|
||||||
#define CHECK_VU0REC (!g_Session.ForceDisableVU0rec && Config.Options&PCSX2_VU0REC)
|
#define CHECK_VU0REC (!g_Session.ForceDisableVU0rec && Config.Options&PCSX2_VU0REC)
|
||||||
#define CHECK_VU1REC (!g_Session.ForceDisableVU1rec && (Config.Options&PCSX2_VU1REC))
|
#define CHECK_VU1REC (!g_Session.ForceDisableVU1rec && (Config.Options&PCSX2_VU1REC))
|
||||||
|
|
|
@ -1,10 +1,45 @@
|
||||||
Instruction for installations:
|
-------------------------------------
|
||||||
|
PCSX2 NSIS Installer Instructions
|
||||||
Install NSIS (tested with 2.45)
|
-------------------------------------
|
||||||
Install NSIS Script Advanced Uninstall Log NSIS Header (you can find it opn NSIS wiki)
|
|
||||||
Create a folder
|
* Install NSIS (tested with 2.45)
|
||||||
Put the nsis script in said folder
|
* Install NSIS Script: Advanced Uninstall Log (you can find it on NSIS wiki)
|
||||||
Put vcredist_x86.exe in said folder
|
|
||||||
Put the pcsx2 folder in said folder (warning, leave only the files you want in the installer. All files from the pcsx2 folder will be added to the installer )
|
* Download the latest Visual C++ Redistributable (currently 2008 SP1 as of this writing) and
|
||||||
Edit the NSIS script with a text editor, changing the installer name and putting the correct name for the menu item (2 times, both filename and link name)
|
save it to this nsis/ folder.
|
||||||
Compile the NSIS script
|
|
||||||
|
* Load the PCSX2 Suite solution and rebuild all in the following targets:
|
||||||
|
* Release SSE2
|
||||||
|
* Release SSSE3 (only needed if packaging plugins)
|
||||||
|
* Release SSE4 (only needed if packaging plugins)
|
||||||
|
* Devel (optional)
|
||||||
|
|
||||||
|
You may selectively unload plugins you do not wish to package prior to running the NSIS
|
||||||
|
script.
|
||||||
|
|
||||||
|
* Compile script, and Enjoy :)
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------
|
||||||
|
Compilation Targets and Plugin Inclusion
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
pcsx2-dev.exe is included into the installer as well *if* present (but is not required).
|
||||||
|
The Release mode (without -dev) is required, and the script errors if it's missing.
|
||||||
|
|
||||||
|
To include non-NULL plugins into the installer you must specify /DINC_PLUGINS on the command
|
||||||
|
line when compiling the script. The installer will include plugins only if they are present.
|
||||||
|
If you do not build plugins, or remove some (or all) plugins before running the nsis script,
|
||||||
|
only PCSX2 and whatever remaining plugins will be packaged.
|
||||||
|
|
||||||
|
GSdx SSE2, SSSE3, and SSE4 versions are all included into the installer *if* they are present.
|
||||||
|
You will need to follow the above instructions and compile all release targets to get all the
|
||||||
|
GSdx DLLs.
|
||||||
|
|
||||||
|
--------------------------------------------
|
||||||
|
TODO / Wish List!!
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
* pcsx2-dev should probably be an optional section, conditionally scripted only if the
|
||||||
|
file is present at compilation time, and packaged.
|
||||||
|
|
|
@ -1,147 +1,242 @@
|
||||||
; Pcsx2 NSIS installer script
|
; PCSX2 NSIS installer script
|
||||||
; loosely based on a collection of examples and on information from the wikipedia
|
; loosely based on a collection of examples and on information from the wikipedia
|
||||||
|
|
||||||
!define APP_NAME "Pcsx2 - A Playstation 2 Emulator"
|
; Application version, changed for each release to match the verision
|
||||||
!define INSTDIR_REG_ROOT "HKLM"
|
|
||||||
!define INSTDIR_REG_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}"
|
; ----------------------------------------
|
||||||
|
; Determine the revision numbers of the various components
|
||||||
;--------------------------------
|
|
||||||
;Include Modern UI 2 and advanced log uninstaller. all credits to the respective authors
|
!system 'SubWCRev.exe ..\pcsx2 templates\svnrev_pcsx2.nsh svnrev_pcsx2.nsh'
|
||||||
|
|
||||||
!include "MUI2.nsh"
|
!ifdef INC_PLUGINS
|
||||||
!include "AdvUninstLog.nsh"
|
!system 'SubWCRev.exe ..\plugins\gsdx templates\svnrev_gsdx.nsh svnrev_gsdx.nsh'
|
||||||
|
!system 'SubWCRev.exe ..\plugins\spu2-x templates\svnrev_spu2x.nsh svnrev_spu2x.nsh'
|
||||||
;--------------------------------
|
!system 'SubWCRev.exe ..\plugins\cdvdiso templates\svnrev_cdvdiso.nsh svnrev_cdvdiso.nsh'
|
||||||
|
!system 'SubWCRev.exe ..\plugins\lilypad templates\svnrev_lilypad.nsh svnrev_lilypad.nsh'
|
||||||
; The name of the installer
|
!system 'SubWCRev.exe ..\plugins\zerogs\dx templates\svnrev_zerogs.nsh svnrev_zerogs.nsh'
|
||||||
Name "Pcsx2"
|
!system 'SubWCRev.exe ..\plugins\zerospu2 templates\svnrev_zerospu2.nsh svnrev_zerospu2.nsh'
|
||||||
|
!endif
|
||||||
; The file to write. To change each release
|
|
||||||
OutFile "Pcsx2-beta-1474-setup.exe"
|
!include "svnrev_pcsx2.nsh"
|
||||||
|
|
||||||
; The default installation directory
|
!ifdef INC_PLUGINS
|
||||||
InstallDir "$PROGRAMFILES\Pcsx2"
|
!include "svnrev_gsdx.nsh"
|
||||||
|
!include "svnrev_spu2x.nsh"
|
||||||
; Registry key to check for directory (so if you install again, it will
|
!include "svnrev_cdvdiso.nsh"
|
||||||
; overwrite the old one automatically)
|
!include "svnrev_lilypad.nsh"
|
||||||
InstallDirRegKey HKLM "Software\Pcsx2" "Install_Dir"
|
!include "svnrev_zerogs.nsh"
|
||||||
|
!include "svnrev_zerospu2.nsh"
|
||||||
; Request application privileges for Windows Vista
|
!endif
|
||||||
RequestExecutionLevel admin
|
|
||||||
|
; ----------------------------------------
|
||||||
; Pages
|
|
||||||
|
!define APP_NAME "PCSX2 Beta r${SVNREV}"
|
||||||
!insertmacro UNATTENDED_UNINSTALL
|
|
||||||
!define MUI_COMPONENTSPAGE_NODESC ;no decription is really necessary at this stage...
|
!define INSTDIR_REG_ROOT "HKLM"
|
||||||
!insertmacro MUI_PAGE_COMPONENTS
|
!define INSTDIR_REG_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\PCSX2-beta-r${SVNREV}"
|
||||||
!insertmacro MUI_PAGE_DIRECTORY
|
|
||||||
!insertmacro MUI_PAGE_INSTFILES
|
|
||||||
|
; ----------------------------------------
|
||||||
!insertmacro MUI_UNPAGE_CONFIRM
|
; Include Modern UI 2 and advanced log uninstaller.
|
||||||
!insertmacro MUI_UNPAGE_COMPONENTS
|
|
||||||
!insertmacro MUI_UNPAGE_INSTFILES
|
!include "MUI2.nsh"
|
||||||
|
!include "AdvUninstLog.nsh"
|
||||||
|
|
||||||
;--------------------------------
|
; -------------------------------------
|
||||||
|
; Test if Visual Studio Redistributables 2008 SP1 installed
|
||||||
; Basic section (emulation proper)
|
; Returns -1 if there is no VC redistributables intstalled
|
||||||
Section "Pcsx2 (required)"
|
;
|
||||||
|
Function CheckVCRedist
|
||||||
SectionIn RO
|
|
||||||
|
Push $R0
|
||||||
; Set output path to the installation directory.
|
ClearErrors
|
||||||
SetOutPath $INSTDIR
|
ReadRegDword $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{9A25302D-30C0-39D9-BD6F-21E6EC160475}" "Version"
|
||||||
|
|
||||||
; Put file there. It's catched by the uninstaller script
|
; if VS 2005+ redist SP1 not installed, install it
|
||||||
!insertmacro UNINSTALL.LOG_OPEN_INSTALL
|
IfErrors 0 VSRedistInstalled
|
||||||
File /r "Pcsx2\"
|
StrCpy $R0 "-1"
|
||||||
!insertmacro UNINSTALL.LOG_CLOSE_INSTALL
|
|
||||||
|
VSRedistInstalled:
|
||||||
; Write the installation path into the registry
|
Exch $R0
|
||||||
WriteRegStr HKLM Software\Pcsx2 "Install_Dir" "$INSTDIR"
|
|
||||||
|
FunctionEnd
|
||||||
; Write the uninstall keys for Windows
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pcsx2" "DisplayName" "Pcsx2 - Playstation 2 Emulator"
|
; ----------------------------------------
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pcsx2" "UninstallString" '"$INSTDIR\uninstall.exe"'
|
; The name of the installer
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pcsx2" "NoModify" 1
|
Name "PCSX2 Beta r${SVNREV}"
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pcsx2" "NoRepair" 1
|
|
||||||
WriteUninstaller "uninstall.exe"
|
OutFile "pcsx2-beta-${SVNREV}-setup.exe"
|
||||||
|
|
||||||
SectionEnd
|
; The default installation directory
|
||||||
|
InstallDir "$PROGRAMFILES\pcsx2-r${SVNREV}"
|
||||||
; Optional sections (can be disabled by the user)
|
|
||||||
Section "Start Menu Shortcuts"
|
; Registry key to check for directory (so if you install again, it will
|
||||||
|
; overwrite the old one automatically)
|
||||||
; Need to change name too, for each version
|
InstallDirRegKey HKLM "Software\pcsx2" "Install_Dir"
|
||||||
CreateDirectory "$SMPROGRAMS\Pcsx2"
|
|
||||||
CreateShortCut "$SMPROGRAMS\Pcsx2\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
|
; Request application privileges for Windows Vista
|
||||||
CreateShortCut "$SMPROGRAMS\Pcsx2\Pcsx2.lnk" "$INSTDIR\pcsx2-beta-1474.exe" "" "$INSTDIR\pcsx2-beta-1474.exe" 0
|
RequestExecutionLevel admin
|
||||||
|
|
||||||
SectionEnd
|
; Pages
|
||||||
|
|
||||||
; Optional, but required if you don't already have it
|
!insertmacro UNATTENDED_UNINSTALL
|
||||||
Section "Microsoft Visual C++ 2008 SP1 Redist(Required)"
|
!define MUI_COMPONENTSPAGE_NODESC ;no decription is really necessary at this stage...
|
||||||
|
!insertmacro MUI_PAGE_COMPONENTS
|
||||||
SetOutPath $TEMP
|
!insertmacro MUI_PAGE_DIRECTORY
|
||||||
File "vcredist_x86.exe"
|
!insertmacro MUI_PAGE_INSTFILES
|
||||||
ExecWait "$TEMP\vcredist_x86.exe"
|
|
||||||
|
!insertmacro MUI_UNPAGE_CONFIRM
|
||||||
SectionEnd
|
!insertmacro MUI_UNPAGE_COMPONENTS
|
||||||
|
!insertmacro MUI_UNPAGE_INSTFILES
|
||||||
;--------------------------------
|
|
||||||
|
|
||||||
Function .onInit
|
; ----------------------------------------
|
||||||
|
; Basic section (emulation proper)
|
||||||
;prepare log always within .onInit function
|
Section "PCSX2 Beta r${SVNREV} (required)"
|
||||||
!insertmacro UNINSTALL.LOG_PREPARE_INSTALL
|
|
||||||
|
SectionIn RO
|
||||||
FunctionEnd
|
|
||||||
|
; Put file there. It's catched by the uninstaller script
|
||||||
|
SetOutPath $INSTDIR
|
||||||
Function .onInstSuccess
|
!insertmacro UNINSTALL.LOG_OPEN_INSTALL
|
||||||
|
|
||||||
;create/update log always within .onInstSuccess function
|
SetOutPath $INSTDIR
|
||||||
!insertmacro UNINSTALL.LOG_UPDATE_INSTALL
|
File /oname=pcsx2-r${SVNREV}.exe ..\bin\pcsx2.exe
|
||||||
|
File ..\bin\w32pthreads.dll
|
||||||
FunctionEnd
|
File ..\bin\gnu_gettext.dll
|
||||||
|
|
||||||
;--------------------------------
|
File /nonfatal /oname=pcsx2-dev-r${SVNREV}.exe ..\bin\pcsx2-dev.exe
|
||||||
|
|
||||||
|
SetOutPath $INSTDIR\Langs
|
||||||
|
File /r ..\bin\Langs\*.mo
|
||||||
; Uninstaller
|
|
||||||
|
SetOutPath $INSTDIR\Patches
|
||||||
Section "Un.Standard uninstallation (Leaves user created files untouched)"
|
File /r ..\bin\Patches\*.pnach
|
||||||
|
|
||||||
; Remove registry keys
|
; NULL plugins are required, and really there should be more but we don't have working
|
||||||
DeleteRegKey HKLM Software\Microsoft\Windows\CurrentVersion\Uninstall\Pcsx2
|
; SPU2 or GS null plugins right now.
|
||||||
DeleteRegKey HKLM Software\Pcsx2
|
|
||||||
|
File ..\bin\Plugins\USBnull.dll
|
||||||
; Remove shortcuts, if any
|
File ..\bin\Plugins\DEV9null.dll
|
||||||
Delete "$SMPROGRAMS\Pcsx2\*.*"
|
File ..\bin\Plugins\FWnull.dll
|
||||||
RMDir "$SMPROGRAMS\Pcsx2"
|
File ..\bin\Plugins\CDVDnull.dll
|
||||||
|
|
||||||
!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR"
|
!ifdef INC_PLUGINS
|
||||||
DeleteRegKey ${INSTDIR_REG_ROOT} "${INSTDIR_REG_KEY}"
|
SetOutPath $INSTDIR\Plugins
|
||||||
|
File /nonfatal /oname=gsdx-sse2-r${SVNREV_GSDX}.dll ..\bin\Plugins\gsdx-sse2.dll
|
||||||
SectionEnd
|
File /nonfatal /oname=gsdx-ssse3-r${SVNREV_GSDX}.dll ..\bin\Plugins\gsdx-ssse3.dll
|
||||||
|
File /nonfatal /oname=gsdx-sse4-r${SVNREV_GSDX}.dll ..\bin\Plugins\gsdx-sse4.dll
|
||||||
; This option lets you COMPLETELY uninstall by deleting the main folder. Caution! :)
|
File /nonfatal /oname=spu2-x-r${SVNREV_SPU2X}.dll ..\bin\Plugins\spu2-x.dll
|
||||||
Section /o "Un.Complete Uninstall. WARNING, this will delete every file in the program folder"
|
File /nonfatal /oname=cdvdiso-r${SVNREV_CDVDISO}.dll ..\bin\Plugins\cdvdiso.dll
|
||||||
|
File /nonfatal /oname=lilypad-r${SVNREV_LILYPAD}.dll ..\bin\Plugins\lilypad.dll
|
||||||
MessageBox MB_YESNO "You have chosen to remove ALL files in the installation folder. This will remove all your saves, screenshots, patches and bios as well. Do you want to proceed?" IDYES true IDNO false
|
|
||||||
true:
|
File /nonfatal /oname=zerogs-r${SVNREV_ZEROGS}.dll ..\bin\Plugins\zerogs.dll
|
||||||
Delete "$SMPROGRAMS\Pcsx2\*.*"
|
File /nonfatal /oname=zerospu2-r${SVNREV_ZEROSPU2}.dll ..\bin\Plugins\zerospu2.dll
|
||||||
RMDir "$SMPROGRAMS\Pcsx2"
|
!endif
|
||||||
RMDir /r "$INSTDIR"
|
|
||||||
DeleteRegKey ${INSTDIR_REG_ROOT} "${INSTDIR_REG_KEY}"
|
SetOutPath $INSTDIR
|
||||||
false:
|
!insertmacro UNINSTALL.LOG_CLOSE_INSTALL
|
||||||
|
|
||||||
SectionEnd
|
; Write the installation path into the registry
|
||||||
|
WriteRegStr HKLM Software\pcsx2 "Install_Dir" "$INSTDIR"
|
||||||
Function UN.onInit
|
|
||||||
|
; Write the uninstall keys for Windows
|
||||||
;begin uninstall, could be added on top of uninstall section instead
|
WriteRegStr HKLM "${INSTDIR_REG_KEY}" "DisplayName" "PCSX2 - Playstation 2 Emulator"
|
||||||
!insertmacro UNINSTALL.LOG_BEGIN_UNINSTALL
|
WriteRegStr HKLM "${INSTDIR_REG_KEY}" "UninstallString" '"$INSTDIR\uninstall-r${SVNREV}.exe"'
|
||||||
|
WriteRegDWORD HKLM "${INSTDIR_REG_KEY}" "NoModify" 1
|
||||||
FunctionEnd
|
WriteRegDWORD HKLM "${INSTDIR_REG_KEY}" "NoRepair" 1
|
||||||
|
WriteUninstaller "uninstall-r${SVNREV}.exe"
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
; ----------------------------------------
|
||||||
|
; MSVC Redistributable - required if the user des not already have it
|
||||||
|
; Note: if your NSIS generates an error here it means you need to download the latest
|
||||||
|
; visual studio redist package from microsoft. Any redist 2008/SP1 or newer will do.
|
||||||
|
Section "Microsoft Visual C++ 2008 SP1 Redist (required)"
|
||||||
|
|
||||||
|
SectionIn RO
|
||||||
|
SetOutPath $TEMP
|
||||||
|
File "vcredist_x86.exe"
|
||||||
|
Call CheckVCRedist
|
||||||
|
StrCmp $R0 "-1" installRedist
|
||||||
|
DetailPrint "Visual C++ 2008 SP1 Redistributable already installed, skipping..."
|
||||||
|
Goto skipRedist
|
||||||
|
|
||||||
|
installRedist:
|
||||||
|
ExecWait "$TEMP\vcredist_x86.exe"
|
||||||
|
|
||||||
|
SkipRedist:
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
; ----------------------------------------
|
||||||
|
; Optional sections (can be disabled by the user)
|
||||||
|
Section "Start Menu Shortcuts"
|
||||||
|
|
||||||
|
SetOutPath $INSTDIR
|
||||||
|
|
||||||
|
; Need to change name too, for each version
|
||||||
|
CreateDirectory "$SMPROGRAMS\pcsx2"
|
||||||
|
CreateShortCut "$SMPROGRAMS\pcsx2\Uninstall-r${SVNREV}.lnk" "$INSTDIR\uninstall-r${SVNREV}.exe" "" "$INSTDIR\uninstall-r${SVNREV}.exe" 0
|
||||||
|
CreateShortCut "$SMPROGRAMS\pcsx2\pcsx2-r${SVNREV}.lnk" "$INSTDIR\pcsx2-r${SVNREV}.exe" "" "$INSTDIR\pcsx2-r${SVNREV}.exe" 0
|
||||||
|
CreateShortCut "$SMPROGRAMS\pcsx2\pcsx2-dev-r${SVNREV}.lnk" "$INSTDIR\pcsx2-dev-r${SVNREV}.exe" "" "$INSTDIR\pcsx2-dev-r${SVNREV}.exe" 0 "" "" \
|
||||||
|
"PCSX2 Devel (has debugging and memory dumping)"
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
;--------------------------------
|
||||||
|
|
||||||
|
Function .onInit
|
||||||
|
|
||||||
|
;prepare log always within .onInit function
|
||||||
|
!insertmacro UNINSTALL.LOG_PREPARE_INSTALL
|
||||||
|
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
|
||||||
|
Function .onInstSuccess
|
||||||
|
|
||||||
|
;create/update log always within .onInstSuccess function
|
||||||
|
!insertmacro UNINSTALL.LOG_UPDATE_INSTALL
|
||||||
|
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
|
||||||
|
; --------------------------------------
|
||||||
|
; Uninstaller
|
||||||
|
|
||||||
|
Section "Un.Safe uninstall (Removes only files installed by this installer)"
|
||||||
|
|
||||||
|
; Remove registry keys
|
||||||
|
DeleteRegKey HKLM ${INSTDIR_REG_KEY}
|
||||||
|
DeleteRegKey HKLM Software\pcsx2
|
||||||
|
|
||||||
|
; Remove shortcuts, if any
|
||||||
|
Delete "$SMPROGRAMS\pcsx2\*.*"
|
||||||
|
RMDir "$SMPROGRAMS\pcsx2"
|
||||||
|
|
||||||
|
!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR"
|
||||||
|
DeleteRegKey ${INSTDIR_REG_ROOT} "${INSTDIR_REG_KEY}"
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
; This option lets you COMPLETELY uninstall by deleting the main folder. Caution! :)
|
||||||
|
Section /o "Un.Complete Uninstall. *Completely* removes all files and folders."
|
||||||
|
|
||||||
|
MessageBox MB_YESNO "WANRING! You have chosen to remove ALL files in the installation folder, including all saves, screenshots, plugins, patches, and bios files. Do you want to proceed?" IDYES true IDNO false
|
||||||
|
true:
|
||||||
|
Delete "$SMPROGRAMS\pcsx2\*.*"
|
||||||
|
RMDir "$SMPROGRAMS\pcsx2"
|
||||||
|
RMDir /r "$INSTDIR"
|
||||||
|
DeleteRegKey ${INSTDIR_REG_ROOT} "${INSTDIR_REG_KEY}"
|
||||||
|
false:
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Function UN.onInit
|
||||||
|
|
||||||
|
;begin uninstall, could be added on top of uninstall section instead
|
||||||
|
!insertmacro UNINSTALL.LOG_BEGIN_UNINSTALL
|
||||||
|
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
!define SVNREV_CDVDISO $WCREV$
|
|
@ -0,0 +1 @@
|
||||||
|
!define SVNREV_GSDX $WCREV$
|
|
@ -0,0 +1 @@
|
||||||
|
!define SVNREV_LILYPAD $WCREV$
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
!define SVNREV $WCREV$
|
||||||
|
!define SVN_MODS $WCMODS?1:0$
|
|
@ -0,0 +1 @@
|
||||||
|
!define SVNREV_SPU2X $WCREV$
|
|
@ -0,0 +1 @@
|
||||||
|
!define SVNREV_ZEROGS $WCREV$
|
|
@ -0,0 +1 @@
|
||||||
|
!define SVNREV_ZEROSPU2 $WCREV$
|
|
@ -722,35 +722,49 @@ __forceinline void cdvdReadInterrupt()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (cdvd.RErr == 0)
|
if( cdvd.RErr == 0 )
|
||||||
{
|
{
|
||||||
cdr.RErr = DoCDVDgetBuffer(cdr.Transfer);
|
while( (cdvd.RErr = DoCDVDgetBuffer(cdr.Transfer)), cdvd.RErr == -2 )
|
||||||
|
{
|
||||||
|
// not finished yet ... block on the read until it finishes.
|
||||||
|
Threading::Sleep( 0 );
|
||||||
|
Threading::SpinWait();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (cdr.RErr == -1)
|
|
||||||
|
if (cdvd.RErr == -1)
|
||||||
{
|
{
|
||||||
cdvd.RetryCntP++;
|
cdvd.RetryCntP++;
|
||||||
Console::Error("CDVD READ ERROR, sector=%d", params cdvd.Sector);
|
|
||||||
|
|
||||||
if (cdvd.RetryCntP <= cdvd.RetryCnt)
|
if (cdvd.RetryCntP <= cdvd.RetryCnt)
|
||||||
{
|
{
|
||||||
|
CDVD_LOG( "CDVD read err, retrying... (attempt %d of %d)", cdvd.RetryCntP, cdvd.RetryCnt );
|
||||||
cdvd.RErr = DoCDVDreadTrack(cdvd.Sector, cdvd.ReadMode);
|
cdvd.RErr = DoCDVDreadTrack(cdvd.Sector, cdvd.ReadMode);
|
||||||
CDVDREAD_INT(cdvd.ReadTime);
|
CDVDREAD_INT(cdvd.ReadTime);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else if(cdr.RErr == -2)
|
Console::Error("CDVD READ ERROR, sector = 0x%08x", params cdvd.Sector);
|
||||||
{
|
|
||||||
// not finished yet ... give it a bit more time
|
|
||||||
CDVDREAD_INT(cdvd.ReadTime);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cdvd.Reading = false;
|
cdvd.Reading = false;
|
||||||
|
|
||||||
|
// Any other value besides 0 should be considered invalid here (wtf is that wacky
|
||||||
|
// plugin trying to do?)
|
||||||
|
jASSUME( cdvd.RErr == 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cdvdReadSector() == -1)
|
if (cdvdReadSector() == -1)
|
||||||
{
|
{
|
||||||
|
// This means that the BCR/DMA hasn't finished yet, and rather than fire off the
|
||||||
|
// sector-finished notice too early (which might overwrite game data) we delay a
|
||||||
|
// bit and try to read the sector again later.
|
||||||
|
// An arbitrary delay of some number of cycles probably makes more sense here,
|
||||||
|
// but for now it's based on the cdvd.ReadTime value. -- air
|
||||||
|
|
||||||
assert((int)cdvd.ReadTime > 0 );
|
assert((int)cdvd.ReadTime > 0 );
|
||||||
CDVDREAD_INT(cdvd.ReadTime);
|
CDVDREAD_INT(cdvd.ReadTime/4);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -772,7 +786,7 @@ __forceinline void cdvdReadInterrupt()
|
||||||
|
|
||||||
cdvd.RetryCntP = 0;
|
cdvd.RetryCntP = 0;
|
||||||
cdvd.Reading = 1;
|
cdvd.Reading = 1;
|
||||||
cdr.RErr = DoCDVDreadTrack(cdvd.Sector, cdvd.ReadMode);
|
cdvd.RErr = DoCDVDreadTrack(cdvd.Sector, cdvd.ReadMode);
|
||||||
CDVDREAD_INT(cdvd.ReadTime);
|
CDVDREAD_INT(cdvd.ReadTime);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "IopCommon.h"
|
#include "IopCommon.h"
|
||||||
#include "CDVD/CDVDaccess.h"
|
#include "CDVD/CDVDaccess.h"
|
||||||
|
|
||||||
extern char isoFileName[];
|
//extern char isoFileName[];
|
||||||
|
|
||||||
#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */
|
#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */
|
||||||
#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */
|
#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */
|
||||||
|
|
|
@ -45,6 +45,7 @@ static int diskTypeCached = -1;
|
||||||
|
|
||||||
// used to bridge the gap between the old getBuffer api and the new getBuffer2 api.
|
// used to bridge the gap between the old getBuffer api and the new getBuffer2 api.
|
||||||
int lastReadSize;
|
int lastReadSize;
|
||||||
|
int lastLSN; // needed for block dumping
|
||||||
|
|
||||||
// Records last read block length for block dumping
|
// Records last read block length for block dumping
|
||||||
static int plsn = 0;
|
static int plsn = 0;
|
||||||
|
@ -57,11 +58,9 @@ static void CheckNullCDVD()
|
||||||
DevAssert( CDVD != NULL, "Invalid CDVD object state (null pointer exception)" );
|
DevAssert( CDVD != NULL, "Invalid CDVD object state (null pointer exception)" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
|
||||||
// Disk Type detection stuff (from cdvdGigaherz)
|
// Disk Type detection stuff (from cdvdGigaherz)
|
||||||
//
|
//
|
||||||
|
|
||||||
int CheckDiskTypeFS(int baseType)
|
int CheckDiskTypeFS(int baseType)
|
||||||
{
|
{
|
||||||
int f;
|
int f;
|
||||||
|
@ -119,7 +118,7 @@ static int FindDiskType(int mType)
|
||||||
}
|
}
|
||||||
else if (mType < 0)
|
else if (mType < 0)
|
||||||
{
|
{
|
||||||
static u8 bleh[2352];
|
static u8 bleh[CD_FRAMESIZE_RAW];
|
||||||
cdvdTD td;
|
cdvdTD td;
|
||||||
|
|
||||||
CDVD->getTD(0,&td);
|
CDVD->getTD(0,&td);
|
||||||
|
@ -314,26 +313,26 @@ s32 DoCDVDopen(const char* pTitleFilename)
|
||||||
cdvdTD td;
|
cdvdTD td;
|
||||||
CDVD->getTD(0, &td);
|
CDVD->getTD(0, &td);
|
||||||
|
|
||||||
int blockofs = 0, blocksize = 0, blocks = td.lsn;
|
blockDumpFile = isoCreate(temp.ToAscii().data(), ISOFLAGS_BLOCKDUMP_V3);
|
||||||
|
|
||||||
switch(cdtype)
|
if( blockDumpFile != NULL )
|
||||||
{
|
{
|
||||||
case CDVD_TYPE_PS2DVD:
|
int blockofs = 0, blocksize = CD_FRAMESIZE_RAW, blocks = td.lsn;
|
||||||
case CDVD_TYPE_DVDV:
|
|
||||||
case CDVD_TYPE_DETCTDVDS:
|
|
||||||
case CDVD_TYPE_DETCTDVDD:
|
|
||||||
blockofs = 24;
|
|
||||||
blocksize = 2048;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
blockofs = 0;
|
|
||||||
blocksize= 2352;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockDumpFile = isoCreate(temp.ToAscii().data(), ISOFLAGS_BLOCKDUMP);
|
// hack: Because of limitations of the current cdvd design, we can't query the blocksize
|
||||||
if (blockDumpFile) isoSetFormat(blockDumpFile, blockofs, blocksize, blocks);
|
// of the underlying media. So lets make a best guess:
|
||||||
|
|
||||||
|
switch(cdtype)
|
||||||
|
{
|
||||||
|
case CDVD_TYPE_PS2DVD:
|
||||||
|
case CDVD_TYPE_DVDV:
|
||||||
|
case CDVD_TYPE_DETCTDVDS:
|
||||||
|
case CDVD_TYPE_DETCTDVDD:
|
||||||
|
blocksize = 2048;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
isoSetFormat(blockDumpFile, blockofs, blocksize, blocks);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -388,7 +387,7 @@ s32 DoCDVDreadTrack(u32 lsn, int mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
//DevCon::Notice("CDVD readTrack(lsn=%d,mode=%d)",params lsn, lastReadSize);
|
//DevCon::Notice("CDVD readTrack(lsn=%d,mode=%d)",params lsn, lastReadSize);
|
||||||
|
lastLSN = lsn;
|
||||||
return CDVD->readTrack(lsn,mode);
|
return CDVD->readTrack(lsn,mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,7 +398,7 @@ s32 DoCDVDgetBuffer(u8* buffer)
|
||||||
|
|
||||||
if (ret == 0 && blockDumpFile != NULL)
|
if (ret == 0 && blockDumpFile != NULL)
|
||||||
{
|
{
|
||||||
isoWriteBlock(blockDumpFile, buffer, lastReadSize);
|
isoWriteBlock(blockDumpFile, buffer, lastLSN);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -524,5 +523,5 @@ CDVD_API CDVDapi_NoDisc =
|
||||||
NODISCgetBuffer2,
|
NODISCgetBuffer2,
|
||||||
NODISCgetDualInfo,
|
NODISCgetDualInfo,
|
||||||
|
|
||||||
NULL
|
NODISCgetUniqueFilename
|
||||||
};
|
};
|
||||||
|
|
|
@ -295,9 +295,10 @@ s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
isoReadBlock(iso, cdbuffer + iso->blockofs, lsn);
|
isoReadBlock(iso, cdbuffer, lsn);
|
||||||
|
|
||||||
pbuffer = cdbuffer;
|
pbuffer = cdbuffer;
|
||||||
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case CDVD_MODE_2352:
|
case CDVD_MODE_2352:
|
||||||
|
@ -317,6 +318,11 @@ s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// version 3 blockdumps have no pbuffer header, so lets reset back to the
|
||||||
|
// original pointer. :)
|
||||||
|
if( iso->flags & ISOFLAGS_BLOCKDUMP_V3 )
|
||||||
|
pbuffer = cdbuffer;
|
||||||
|
|
||||||
memcpy_fast(tempbuffer,pbuffer,psize);
|
memcpy_fast(tempbuffer,pbuffer,psize);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -329,9 +335,9 @@ s32 CALLBACK ISOreadTrack(u32 lsn, int mode)
|
||||||
if (_lsn < 0) lsn = iso->blocks + _lsn;
|
if (_lsn < 0) lsn = iso->blocks + _lsn;
|
||||||
if (lsn > iso->blocks) return -1;
|
if (lsn > iso->blocks) return -1;
|
||||||
|
|
||||||
isoReadBlock(iso, cdbuffer + iso->blockofs, lsn);
|
isoReadBlock(iso, cdbuffer, lsn);
|
||||||
|
|
||||||
pbuffer = cdbuffer;
|
pbuffer = cdbuffer;
|
||||||
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case CDVD_MODE_2352:
|
case CDVD_MODE_2352:
|
||||||
|
@ -351,6 +357,11 @@ s32 CALLBACK ISOreadTrack(u32 lsn, int mode)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// version 3 blockdumps have no pbuffer header, so lets reset back to the
|
||||||
|
// original pointer. :)
|
||||||
|
if( iso->flags & ISOFLAGS_BLOCKDUMP_V3 )
|
||||||
|
pbuffer = cdbuffer;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,5 +426,5 @@ CDVD_API CDVDapi_Iso =
|
||||||
ISOgetBuffer2,
|
ISOgetBuffer2,
|
||||||
ISOgetDualInfo,
|
ISOgetDualInfo,
|
||||||
|
|
||||||
NULL
|
ISOgetUniqueFilename
|
||||||
};
|
};
|
||||||
|
|
|
@ -497,24 +497,26 @@ void cdrReadInterrupt() {
|
||||||
cdr.StatP|= 0x22;
|
cdr.StatP|= 0x22;
|
||||||
cdr.Result[0] = cdr.StatP;
|
cdr.Result[0] = cdr.StatP;
|
||||||
|
|
||||||
Console::Status("Reading From CDR");
|
if( cdr.RErr == 0 )
|
||||||
cdr.RErr = DoCDVDgetBuffer(cdr.Transfer);
|
{
|
||||||
|
while( (cdr.RErr = DoCDVDgetBuffer(cdr.Transfer)), cdr.RErr == -2 )
|
||||||
|
{
|
||||||
|
// not finished yet ... block on the read until it finishes.
|
||||||
|
Threading::Sleep( 0 );
|
||||||
|
Threading::SpinWait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cdr.RErr == -1)
|
if (cdr.RErr == -1)
|
||||||
{
|
{
|
||||||
CDR_LOG(" err\n");
|
CDR_LOG(" err\n");
|
||||||
memzero_ptr<2340>(cdr.Transfer);
|
memzero_obj(cdr.Transfer);
|
||||||
cdr.Stat = DiskError;
|
cdr.Stat = DiskError;
|
||||||
cdr.Result[0]|= 0x01;
|
cdr.Result[0] |= 0x01;
|
||||||
ReadTrack();
|
ReadTrack();
|
||||||
CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime);
|
CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(cdr.RErr == -2)
|
|
||||||
{
|
|
||||||
// async mode is not finished yet ... give it a bit more time
|
|
||||||
CDREAD_INT(cdReadTime / 4);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cdr.Stat = DataReady;
|
cdr.Stat = DataReady;
|
||||||
|
|
||||||
|
|
|
@ -29,12 +29,12 @@
|
||||||
int detect(isoFile *iso)
|
int detect(isoFile *iso)
|
||||||
{
|
{
|
||||||
u8 buf[2448];
|
u8 buf[2448];
|
||||||
struct cdVolDesc *volDesc;
|
cdVolDesc *volDesc;
|
||||||
|
|
||||||
if (isoReadBlock(iso, buf + iso->blockofs, 16) == -1) return -1;
|
if (isoReadBlock(iso, buf, 16) == -1) return -1;
|
||||||
|
|
||||||
volDesc = (struct cdVolDesc *)(buf + 24);
|
|
||||||
|
|
||||||
|
volDesc = (cdVolDesc *) (( iso->flags & ISOFLAGS_BLOCKDUMP_V3 ) ? buf : (buf + 24));
|
||||||
|
|
||||||
if (strncmp((char*)volDesc->volID, "CD001", 5)) return 0;
|
if (strncmp((char*)volDesc->volID, "CD001", 5)) return 0;
|
||||||
|
|
||||||
if (volDesc->rootToc.tocSize == 2048)
|
if (volDesc->rootToc.tocSize == 2048)
|
||||||
|
@ -87,7 +87,16 @@ int isoDetect(isoFile *iso) // based on florin's CDVDbin detection code :)
|
||||||
|
|
||||||
if (strncmp(buf, "BDV2", 4) == 0)
|
if (strncmp(buf, "BDV2", 4) == 0)
|
||||||
{
|
{
|
||||||
iso->flags = ISOFLAGS_BLOCKDUMP;
|
iso->flags = ISOFLAGS_BLOCKDUMP_V2;
|
||||||
|
_readfile(iso->handle, &iso->blocksize, 4);
|
||||||
|
_readfile(iso->handle, &iso->blocks, 4);
|
||||||
|
_readfile(iso->handle, &iso->blockofs, 4);
|
||||||
|
_isoReadDtable(iso);
|
||||||
|
return (detect(iso) == 1) ? 0 : -1;
|
||||||
|
}
|
||||||
|
else if (strncmp(buf, "BDV3", 4) == 0)
|
||||||
|
{
|
||||||
|
iso->flags = ISOFLAGS_BLOCKDUMP_V3;
|
||||||
_readfile(iso->handle, &iso->blocksize, 4);
|
_readfile(iso->handle, &iso->blocksize, 4);
|
||||||
_readfile(iso->handle, &iso->blocks, 4);
|
_readfile(iso->handle, &iso->blocks, 4);
|
||||||
_readfile(iso->handle, &iso->blockofs, 4);
|
_readfile(iso->handle, &iso->blockofs, 4);
|
||||||
|
@ -111,7 +120,7 @@ int isoDetect(isoFile *iso) // based on florin's CDVDbin detection code :)
|
||||||
if (tryIsoType(iso, 2448, -8, 0)) return 0; // RAWQ 2448
|
if (tryIsoType(iso, 2448, -8, 0)) return 0; // RAWQ 2448
|
||||||
|
|
||||||
iso->offset = 0;
|
iso->offset = 0;
|
||||||
iso->blocksize = 2352;
|
iso->blocksize = CD_FRAMESIZE_RAW;
|
||||||
iso->blockofs = 0;
|
iso->blockofs = 0;
|
||||||
iso->type = ISOTYPE_AUDIO;
|
iso->type = ISOTYPE_AUDIO;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -232,13 +241,19 @@ int isoSetFormat(isoFile *iso, int blockofs, int blocksize, int blocks)
|
||||||
Console::WriteLn("blocksize = %d", params iso->blocksize);
|
Console::WriteLn("blocksize = %d", params iso->blocksize);
|
||||||
Console::WriteLn("blocks = %d", params iso->blocks);
|
Console::WriteLn("blocks = %d", params iso->blocks);
|
||||||
|
|
||||||
if (iso->flags & ISOFLAGS_BLOCKDUMP)
|
if (iso->flags & ISOFLAGS_BLOCKDUMP_V2)
|
||||||
{
|
{
|
||||||
if (_writefile(iso->handle, "BDV2", 4) < 4) return -1;
|
if (_writefile(iso->handle, "BDV2", 4) < 4) return -1;
|
||||||
if (_writefile(iso->handle, &blocksize, 4) < 4) return -1;
|
if (_writefile(iso->handle, &blocksize, 4) < 4) return -1;
|
||||||
if (_writefile(iso->handle, &blocks, 4) < 4) return -1;
|
if (_writefile(iso->handle, &blocks, 4) < 4) return -1;
|
||||||
if (_writefile(iso->handle, &blockofs, 4) < 4) return -1;
|
if (_writefile(iso->handle, &blockofs, 4) < 4) return -1;
|
||||||
}
|
}
|
||||||
|
else if (iso->flags & ISOFLAGS_BLOCKDUMP_V3)
|
||||||
|
{
|
||||||
|
if (_writefile(iso->handle, "BDV3", 4) < 4) return -1;
|
||||||
|
if (_writefile(iso->handle, &blocksize, 4) < 4) return -1;
|
||||||
|
if (_writefile(iso->handle, &blocks, 4) < 4) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -275,7 +290,7 @@ int _isoReadBlock(isoFile *iso, u8 *dst, int lsn)
|
||||||
memset(dst, 0, iso->blockofs);
|
memset(dst, 0, iso->blockofs);
|
||||||
_seekfile(iso->handle, ofs, SEEK_SET);
|
_seekfile(iso->handle, ofs, SEEK_SET);
|
||||||
|
|
||||||
ret = _readfile(iso->handle, dst, iso->blocksize);
|
ret = _readfile(iso->handle, dst + iso->blockofs, iso->blocksize);
|
||||||
|
|
||||||
if (ret < iso->blocksize)
|
if (ret < iso->blocksize)
|
||||||
{
|
{
|
||||||
|
@ -293,13 +308,13 @@ int _isoReadBlockD(isoFile *iso, u8 *dst, int lsn)
|
||||||
// Console::WriteLn("_isoReadBlockD %d, blocksize=%d, blockofs=%d\n", params lsn, iso->blocksize, iso->blockofs);
|
// Console::WriteLn("_isoReadBlockD %d, blocksize=%d, blockofs=%d\n", params lsn, iso->blocksize, iso->blockofs);
|
||||||
|
|
||||||
memset(dst, 0, iso->blockofs);
|
memset(dst, 0, iso->blockofs);
|
||||||
for (int i = 0; i < iso->dtablesize;i++)
|
for (int i = 0; i < iso->dtablesize; i++)
|
||||||
{
|
{
|
||||||
if (iso->dtable[i] != lsn) continue;
|
if (iso->dtable[i] != lsn) continue;
|
||||||
|
|
||||||
_seekfile(iso->handle, 16 + i * (iso->blocksize + 4) + 4, SEEK_SET);
|
_seekfile(iso->handle, 16 + i * (iso->blocksize + 4) + 4, SEEK_SET);
|
||||||
ret = _readfile(iso->handle, dst, iso->blocksize);
|
ret = _readfile(iso->handle, dst + iso->blockofs, iso->blocksize);
|
||||||
|
|
||||||
if (ret < iso->blocksize) return -1;
|
if (ret < iso->blocksize) return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -330,7 +345,7 @@ int _isoReadBlockM(isoFile *iso, u8 *dst, int lsn)
|
||||||
|
|
||||||
memset(dst, 0, iso->blockofs);
|
memset(dst, 0, iso->blockofs);
|
||||||
_seekfile(iso->multih[i].handle, ofs, SEEK_SET);
|
_seekfile(iso->multih[i].handle, ofs, SEEK_SET);
|
||||||
ret = _readfile(iso->multih[i].handle, dst, iso->blocksize);
|
ret = _readfile(iso->multih[i].handle, dst + iso->blockofs, iso->blocksize);
|
||||||
|
|
||||||
if (ret < iso->blocksize)
|
if (ret < iso->blocksize)
|
||||||
{
|
{
|
||||||
|
@ -351,7 +366,9 @@ int isoReadBlock(isoFile *iso, u8 *dst, int lsn)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iso->flags & ISOFLAGS_BLOCKDUMP)
|
if (iso->flags & ISOFLAGS_BLOCKDUMP_V2)
|
||||||
|
ret = _isoReadBlockD(iso, dst, lsn);
|
||||||
|
else if( iso->flags & ISOFLAGS_BLOCKDUMP_V3 )
|
||||||
ret = _isoReadBlockD(iso, dst, lsn);
|
ret = _isoReadBlockD(iso, dst, lsn);
|
||||||
else if (iso->flags & ISOFLAGS_MULTI)
|
else if (iso->flags & ISOFLAGS_MULTI)
|
||||||
ret = _isoReadBlockM(iso, dst, lsn);
|
ret = _isoReadBlockM(iso, dst, lsn);
|
||||||
|
@ -376,7 +393,7 @@ int _isoWriteBlock(isoFile *iso, u8 *src, int lsn)
|
||||||
u64 ofs = (u64)lsn * iso->blocksize + iso->offset;
|
u64 ofs = (u64)lsn * iso->blocksize + iso->offset;
|
||||||
|
|
||||||
_seekfile(iso->handle, ofs, SEEK_SET);
|
_seekfile(iso->handle, ofs, SEEK_SET);
|
||||||
ret = _writefile(iso->handle, src, iso->blocksize);
|
ret = _writefile(iso->handle, src + iso->blockofs, iso->blocksize);
|
||||||
if (ret < iso->blocksize) return -1;
|
if (ret < iso->blocksize) return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -390,7 +407,7 @@ int _isoWriteBlockD(isoFile *iso, u8 *src, int lsn)
|
||||||
|
|
||||||
ret = _writefile(iso->handle, &lsn, 4);
|
ret = _writefile(iso->handle, &lsn, 4);
|
||||||
if (ret < 4) return -1;
|
if (ret < 4) return -1;
|
||||||
ret = _writefile(iso->handle, src, iso->blocksize);
|
ret = _writefile(iso->handle, src + iso->blockofs, iso->blocksize);
|
||||||
|
|
||||||
// Console::WriteLn("_isoWriteBlock %d", params ret);
|
// Console::WriteLn("_isoWriteBlock %d", params ret);
|
||||||
|
|
||||||
|
@ -401,15 +418,10 @@ int _isoWriteBlockD(isoFile *iso, u8 *src, int lsn)
|
||||||
|
|
||||||
int isoWriteBlock(isoFile *iso, u8 *src, int lsn)
|
int isoWriteBlock(isoFile *iso, u8 *src, int lsn)
|
||||||
{
|
{
|
||||||
int ret;
|
if (iso->flags & ISOFLAGS_BLOCKDUMP_V3)
|
||||||
|
return _isoWriteBlockD(iso, src, lsn);
|
||||||
if (iso->flags & ISOFLAGS_BLOCKDUMP)
|
|
||||||
ret = _isoWriteBlockD(iso, src, lsn);
|
|
||||||
else
|
else
|
||||||
ret = _isoWriteBlock(iso, src, lsn);
|
return _isoWriteBlock(iso, src, lsn);
|
||||||
|
|
||||||
if (ret == -1) return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void isoClose(isoFile *iso)
|
void isoClose(isoFile *iso)
|
||||||
|
|
|
@ -33,30 +33,31 @@ enum isoType
|
||||||
|
|
||||||
enum isoFlags
|
enum isoFlags
|
||||||
{
|
{
|
||||||
ISOFLAGS_Z = 0x0001,
|
ISOFLAGS_Z = 0x0001,
|
||||||
ISOFLAGS_Z2 = 0x0002,
|
ISOFLAGS_Z2 = 0x0002,
|
||||||
ISOFLAGS_BLOCKDUMP = 0x0004,
|
ISOFLAGS_BLOCKDUMP_V2 = 0x0004,
|
||||||
ISOFLAGS_MULTI = 0x0008,
|
ISOFLAGS_MULTI = 0x0008,
|
||||||
ISOFLAGS_BZ2 = 0x0010
|
ISOFLAGS_BZ2 = 0x0010,
|
||||||
|
ISOFLAGS_BLOCKDUMP_V3 = 0x0020
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CD_FRAMESIZE_RAW 2352
|
static const int CD_FRAMESIZE_RAW = 2352;
|
||||||
#define DATA_SIZE (CD_FRAMESIZE_RAW-12)
|
static const int CD_DATA_SIZE = CD_FRAMESIZE_RAW - 12;
|
||||||
|
|
||||||
//#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */
|
//#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */
|
||||||
//#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */
|
//#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */
|
||||||
|
|
||||||
typedef struct
|
struct _multih
|
||||||
{
|
{
|
||||||
u32 slsn;
|
u32 slsn;
|
||||||
u32 elsn;
|
u32 elsn;
|
||||||
void *handle;
|
void *handle;
|
||||||
} _multih;
|
};
|
||||||
|
|
||||||
typedef struct
|
struct isoFile
|
||||||
{
|
{
|
||||||
char filename[256];
|
char filename[256];
|
||||||
u32 type;
|
isoType type;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
u32 offset;
|
u32 offset;
|
||||||
u32 blockofs;
|
u32 blockofs;
|
||||||
|
@ -70,15 +71,15 @@ typedef struct
|
||||||
_multih multih[8];
|
_multih multih[8];
|
||||||
int buflsn;
|
int buflsn;
|
||||||
u8 *buffer;
|
u8 *buffer;
|
||||||
} isoFile;
|
};
|
||||||
|
|
||||||
|
|
||||||
isoFile *isoOpen(const char *filename);
|
extern isoFile *isoOpen(const char *filename);
|
||||||
isoFile *isoCreate(const char *filename, int mode);
|
extern isoFile *isoCreate(const char *filename, int mode);
|
||||||
int isoSetFormat(isoFile *iso, int blockofs, int blocksize, int blocks);
|
extern int isoSetFormat(isoFile *iso, int blockofs, int blocksize, int blocks);
|
||||||
int isoDetect(isoFile *iso);
|
extern int isoDetect(isoFile *iso);
|
||||||
int isoReadBlock(isoFile *iso, u8 *dst, int lsn);
|
extern int isoReadBlock(isoFile *iso, u8 *dst, int lsn);
|
||||||
int isoWriteBlock(isoFile *iso, u8 *src, int lsn);
|
extern int isoWriteBlock(isoFile *iso, u8 *src, int lsn);
|
||||||
void isoClose(isoFile *iso);
|
extern void isoClose(isoFile *iso);
|
||||||
|
|
||||||
#endif /* __LIBISO_H__ */
|
#endif /* __LIBISO_H__ */
|
||||||
|
|
|
@ -38,7 +38,7 @@ void *_openfile(const char *filename, int flags)
|
||||||
handle = CreateFile(wxString::FromAscii(filename).c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
|
handle = CreateFile(wxString::FromAscii(filename).c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return handle == INVALID_HANDLE_VALUE ? NULL : handle;
|
return (handle == INVALID_HANDLE_VALUE) ? NULL : handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 _tellfile(void *handle)
|
u64 _tellfile(void *handle)
|
||||||
|
|
|
@ -133,7 +133,7 @@ void iDumpRegisters(u32 startpc, u32 temp)
|
||||||
|
|
||||||
for(i = 0; i < ArraySize(dmacs); ++i) {
|
for(i = 0; i < ArraySize(dmacs); ++i) {
|
||||||
DMACh* p = (DMACh*)(PS2MEM_HW+dmacs[i]);
|
DMACh* p = (DMACh*)(PS2MEM_HW+dmacs[i]);
|
||||||
__Log("dma%d c%x m%x q%x t%x s%x", i, p->chcr, p->madr, p->qwc, p->tadr, p->sadr);
|
__Log("dma%d c%x m%x q%x t%x s%x", i, p->chcr._u32, p->madr, p->qwc, p->tadr, p->sadr);
|
||||||
}
|
}
|
||||||
__Log("dmac %x %x %x %x", psHu32(DMAC_CTRL), psHu32(DMAC_STAT), psHu32(DMAC_RBSR), psHu32(DMAC_RBOR));
|
__Log("dmac %x %x %x %x", psHu32(DMAC_CTRL), psHu32(DMAC_STAT), psHu32(DMAC_RBSR), psHu32(DMAC_RBOR));
|
||||||
__Log("intc %x %x", psHu32(INTC_STAT), psHu32(INTC_MASK));
|
__Log("intc %x %x", psHu32(INTC_STAT), psHu32(INTC_MASK));
|
||||||
|
|
|
@ -57,9 +57,9 @@ __forceinline void gsInterrupt()
|
||||||
{
|
{
|
||||||
GIF_LOG("gsInterrupt: %8.8x", cpuRegs.cycle);
|
GIF_LOG("gsInterrupt: %8.8x", cpuRegs.cycle);
|
||||||
|
|
||||||
if (!(CHCR::STR(gif)))
|
if (!(gif->chcr.STR))
|
||||||
{
|
{
|
||||||
//Console::WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", params gif->chcr, gif->qwc, done);
|
//Console::WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", params gif->chcr._u32, gif->qwc, done);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ __forceinline void gsInterrupt()
|
||||||
|
|
||||||
gspath3done = 0;
|
gspath3done = 0;
|
||||||
gscycles = 0;
|
gscycles = 0;
|
||||||
CHCR::clearSTR(gif);
|
gif->chcr.STR = 0;
|
||||||
vif1Regs->stat &= ~VIF1_STAT_VGW;
|
vif1Regs->stat &= ~VIF1_STAT_VGW;
|
||||||
|
|
||||||
psHu32(GIF_STAT) &= ~(GIF_STAT_APATH3 | GIF_STAT_OPH | GIF_STAT_P3Q | GIF_STAT_FQC);
|
psHu32(GIF_STAT) &= ~(GIF_STAT_APATH3 | GIF_STAT_OPH | GIF_STAT_P3Q | GIF_STAT_FQC);
|
||||||
|
@ -150,7 +150,7 @@ static __forceinline void GIFchain()
|
||||||
|
|
||||||
static __forceinline bool checkTieBit(u32* &ptag)
|
static __forceinline bool checkTieBit(u32* &ptag)
|
||||||
{
|
{
|
||||||
if ((CHCR::TIE(gif)) && (Tag::IRQ(ptag))) //Check TIE bit of CHCR and IRQ bit of tag
|
if (gif->chcr.TIE && (Tag::IRQ(ptag))) //Check TIE bit of CHCR and IRQ bit of tag
|
||||||
{
|
{
|
||||||
GIF_LOG("dmaIrq Set");
|
GIF_LOG("dmaIrq Set");
|
||||||
gspath3done = 1;
|
gspath3done = 1;
|
||||||
|
@ -228,7 +228,7 @@ void GIFdma()
|
||||||
{
|
{
|
||||||
if (gif->qwc == 0)
|
if (gif->qwc == 0)
|
||||||
{
|
{
|
||||||
if ((CHCR::MOD(gif) == CHAIN_MODE) && CHCR::STR(gif))
|
if ((gif->chcr.MOD == CHAIN_MODE) && gif->chcr.STR)
|
||||||
{
|
{
|
||||||
if (!ReadTag(ptag, id)) return;
|
if (!ReadTag(ptag, id)) return;
|
||||||
GIF_LOG("PTH3 MASK gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx", ptag[1], ptag[0], gif->qwc, id, gif->madr);
|
GIF_LOG("PTH3 MASK gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx", ptag[1], ptag[0], gif->qwc, id, gif->madr);
|
||||||
|
@ -251,10 +251,10 @@ void GIFdma()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer Dn_QWC from Dn_MADR to GIF
|
// Transfer Dn_QWC from Dn_MADR to GIF
|
||||||
if ((CHCR::MOD(gif) == NORMAL_MODE) || (gif->qwc > 0)) // Normal Mode
|
if ((gif->chcr.MOD == NORMAL_MODE) || (gif->qwc > 0)) // Normal Mode
|
||||||
{
|
{
|
||||||
|
|
||||||
if (((psHu32(DMAC_CTRL) & 0xC0) == 0x80) && (CHCR::MOD(gif) == NORMAL_MODE))
|
if (((psHu32(DMAC_CTRL) & 0xC0) == 0x80) && (gif->chcr.MOD == NORMAL_MODE))
|
||||||
{
|
{
|
||||||
Console::WriteLn("DMA Stall Control on GIF normal");
|
Console::WriteLn("DMA Stall Control on GIF normal");
|
||||||
}
|
}
|
||||||
|
@ -265,7 +265,7 @@ void GIFdma()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((CHCR::MOD(gif) == CHAIN_MODE) && (gspath3done == 0)) // Chain Mode
|
if ((gif->chcr.MOD == CHAIN_MODE) && (gspath3done == 0)) // Chain Mode
|
||||||
{
|
{
|
||||||
if (!ReadTag(ptag, id)) return;
|
if (!ReadTag(ptag, id)) return;
|
||||||
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx", ptag[1], ptag[0], gif->qwc, id, gif->madr);
|
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx", ptag[1], ptag[0], gif->qwc, id, gif->madr);
|
||||||
|
@ -316,7 +316,7 @@ void dmaGIF()
|
||||||
{
|
{
|
||||||
//We used to add wait time for the buffer to fill here, fixing some timing problems in path 3 masking
|
//We used to add wait time for the buffer to fill here, fixing some timing problems in path 3 masking
|
||||||
//It takes the time of 24 QW for the BUS to become ready - The Punisher And Streetball
|
//It takes the time of 24 QW for the BUS to become ready - The Punisher And Streetball
|
||||||
GIF_LOG("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gif->chcr, gif->madr, gif->qwc, gif->tadr, gif->asr0, gif->asr1);
|
GIF_LOG("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gif->chcr._u32, gif->madr, gif->qwc, gif->tadr, gif->asr0, gif->asr1);
|
||||||
|
|
||||||
Path3progress = STOPPED_MODE;
|
Path3progress = STOPPED_MODE;
|
||||||
gspath3done = 0; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :)
|
gspath3done = 0; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :)
|
||||||
|
@ -331,7 +331,7 @@ void dmaGIF()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((gif->qwc == 0) && ((CHCR::MOD(gif) != NORMAL_MODE)))
|
if ((gif->qwc == 0) && (gif->chcr.MOD != NORMAL_MODE))
|
||||||
{
|
{
|
||||||
u32 *ptag;
|
u32 *ptag;
|
||||||
|
|
||||||
|
@ -437,7 +437,7 @@ void mfifoGIFtransfer(int qwc)
|
||||||
gifstate &= ~GIF_STATE_EMPTY;
|
gifstate &= ~GIF_STATE_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
GIF_LOG("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr, gif->madr, gif->tadr);
|
GIF_LOG("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr);
|
||||||
|
|
||||||
if (gif->qwc == 0)
|
if (gif->qwc == 0)
|
||||||
{
|
{
|
||||||
|
@ -495,7 +495,7 @@ void mfifoGIFtransfer(int qwc)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((CHCR::TIE(gif)) && (Tag::IRQ(ptag)))
|
if ((gif->chcr.TIE) && (Tag::IRQ(ptag)))
|
||||||
{
|
{
|
||||||
SPR_LOG("dmaIrq Set");
|
SPR_LOG("dmaIrq Set");
|
||||||
gifstate = GIF_STATE_DONE;
|
gifstate = GIF_STATE_DONE;
|
||||||
|
@ -515,7 +515,7 @@ void mfifoGIFtransfer(int qwc)
|
||||||
if ((gif->qwc == 0) && (gifstate == GIF_STATE_DONE)) gifstate = GIF_STATE_STALL;
|
if ((gif->qwc == 0) && (gifstate == GIF_STATE_DONE)) gifstate = GIF_STATE_STALL;
|
||||||
CPU_INT(11,mfifocycles);
|
CPU_INT(11,mfifocycles);
|
||||||
|
|
||||||
SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x", gif->chcr, gif->madr, gif->tadr);
|
SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gifMFIFOInterrupt()
|
void gifMFIFOInterrupt()
|
||||||
|
@ -523,13 +523,13 @@ void gifMFIFOInterrupt()
|
||||||
mfifocycles = 0;
|
mfifocycles = 0;
|
||||||
if (Path3progress == STOPPED_MODE) psHu32(GIF_STAT)&= ~(GIF_STAT_APATH3 | GIF_STAT_OPH); // OPH=0 | APATH=0
|
if (Path3progress == STOPPED_MODE) psHu32(GIF_STAT)&= ~(GIF_STAT_APATH3 | GIF_STAT_OPH); // OPH=0 | APATH=0
|
||||||
|
|
||||||
if ((CHCR::STR(spr0)) && (spr0->qwc == 0))
|
if ((spr0->chcr.STR) && (spr0->qwc == 0))
|
||||||
{
|
{
|
||||||
CHCR::clearSTR(spr0);
|
spr0->chcr.STR = 0;
|
||||||
hwDmacIrq(DMAC_FROM_SPR);
|
hwDmacIrq(DMAC_FROM_SPR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(CHCR::STR(gif)))
|
if (!(gif->chcr.STR))
|
||||||
{
|
{
|
||||||
Console::WriteLn("WTF GIFMFIFO");
|
Console::WriteLn("WTF GIFMFIFO");
|
||||||
cpuRegs.interrupt &= ~(1 << 11);
|
cpuRegs.interrupt &= ~(1 << 11);
|
||||||
|
@ -573,7 +573,7 @@ void gifMFIFOInterrupt()
|
||||||
psHu32(GIF_STAT) &= ~(GIF_STAT_APATH3 | GIF_STAT_OPH | GIF_STAT_P3Q | GIF_STAT_FQC); // OPH, APATH, P3Q, FQC = 0
|
psHu32(GIF_STAT) &= ~(GIF_STAT_APATH3 | GIF_STAT_OPH | GIF_STAT_P3Q | GIF_STAT_FQC); // OPH, APATH, P3Q, FQC = 0
|
||||||
|
|
||||||
vif1Regs->stat &= ~VIF1_STAT_VGW;
|
vif1Regs->stat &= ~VIF1_STAT_VGW;
|
||||||
CHCR::clearSTR(gif);
|
gif->chcr.STR = 0;
|
||||||
gifstate = GIF_STATE_READY;
|
gifstate = GIF_STATE_READY;
|
||||||
hwDmacIrq(DMAC_GIF);
|
hwDmacIrq(DMAC_GIF);
|
||||||
clearFIFOstuff(false);
|
clearFIFOstuff(false);
|
||||||
|
|
32
pcsx2/Gif.h
32
pcsx2/Gif.h
|
@ -46,9 +46,9 @@ union tGIF_CTRL
|
||||||
u32 PSE : 1;
|
u32 PSE : 1;
|
||||||
u32 reserved2 : 28;
|
u32 reserved2 : 28;
|
||||||
};
|
};
|
||||||
u32 value;
|
u32 _u32;
|
||||||
|
|
||||||
tGIF_CTRL( u32 val ) : value( val )
|
tGIF_CTRL( u32 val ) : _u32( val )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -62,9 +62,9 @@ union tGIF_MODE
|
||||||
u32 IMT : 1;
|
u32 IMT : 1;
|
||||||
u32 reserved2 : 29;
|
u32 reserved2 : 29;
|
||||||
};
|
};
|
||||||
u32 value;
|
u32 _u32;
|
||||||
|
|
||||||
tGIF_MODE( u32 val ) : value( val )
|
tGIF_MODE( u32 val ) : _u32( val )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -89,9 +89,9 @@ union tGIF_STAT
|
||||||
u32 FQC : 5;
|
u32 FQC : 5;
|
||||||
u32 reserved3 : 3;
|
u32 reserved3 : 3;
|
||||||
};
|
};
|
||||||
u32 value;
|
u32 _u32;
|
||||||
|
|
||||||
tGIF_STAT( u32 val ) : value( val )
|
tGIF_STAT( u32 val ) : _u32( val )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -104,9 +104,9 @@ union tGIF_TAG0
|
||||||
u32 EOP : 1;
|
u32 EOP : 1;
|
||||||
u32 TAG : 16;
|
u32 TAG : 16;
|
||||||
};
|
};
|
||||||
u32 value;
|
u32 _u32;
|
||||||
|
|
||||||
tGIF_TAG0( u32 val ) : value( val )
|
tGIF_TAG0( u32 val ) : _u32( val )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -121,9 +121,9 @@ union tGIF_TAG1
|
||||||
u32 FLG : 2;
|
u32 FLG : 2;
|
||||||
u32 NREG : 4;
|
u32 NREG : 4;
|
||||||
};
|
};
|
||||||
u32 value;
|
u32 _u32;
|
||||||
|
|
||||||
tGIF_TAG1( u32 val ) : value( val )
|
tGIF_TAG1( u32 val ) : _u32( val )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -139,9 +139,9 @@ union tGIF_CNT
|
||||||
u32 reserved2 : 10;
|
u32 reserved2 : 10;
|
||||||
|
|
||||||
};
|
};
|
||||||
u32 value;
|
u32 _u32;
|
||||||
|
|
||||||
tGIF_CNT( u32 val ) : value( val )
|
tGIF_CNT( u32 val ) : _u32( val )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -153,9 +153,9 @@ union tGIF_P3CNT
|
||||||
u32 P3CNT : 15;
|
u32 P3CNT : 15;
|
||||||
u32 reserved1 : 17;
|
u32 reserved1 : 17;
|
||||||
};
|
};
|
||||||
u32 value;
|
u32 _u32;
|
||||||
|
|
||||||
tGIF_P3CNT( u32 val ) : value( val )
|
tGIF_P3CNT( u32 val ) : _u32( val )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -168,9 +168,9 @@ union tGIF_P3TAG
|
||||||
u32 EOP : 1;
|
u32 EOP : 1;
|
||||||
u32 reserved1 : 16;
|
u32 reserved1 : 16;
|
||||||
};
|
};
|
||||||
u32 value;
|
u32 _u32;
|
||||||
|
|
||||||
tGIF_P3TAG( u32 val ) : value( val )
|
tGIF_P3TAG( u32 val ) : _u32( val )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
12
pcsx2/Hw.cpp
12
pcsx2/Hw.cpp
|
@ -177,15 +177,15 @@ bool hwDmacSrcChainWithStack(DMACh *dma, int id) {
|
||||||
|
|
||||||
dma->madr = dma->tadr + 16; //Set MADR to data following the tag
|
dma->madr = dma->tadr + 16; //Set MADR to data following the tag
|
||||||
|
|
||||||
switch(CHCR::ASP(dma))
|
switch(dma->chcr.ASP)
|
||||||
{
|
{
|
||||||
case 0: { //Check if ASR0 is empty
|
case 0: { //Check if ASR0 is empty
|
||||||
dma->asr0 = dma->madr + (dma->qwc << 4); //If yes store Succeeding tag
|
dma->asr0 = dma->madr + (dma->qwc << 4); //If yes store Succeeding tag
|
||||||
dma->chcr = (dma->chcr & 0xffffffcf) | 0x10; //1 Address in call stack
|
dma->chcr._u32 = (dma->chcr._u32 & 0xffffffcf) | 0x10; //1 Address in call stack
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
dma->chcr = (dma->chcr & 0xffffffcf) | 0x20; //2 Addresses in call stack
|
dma->chcr._u32 = (dma->chcr._u32 & 0xffffffcf) | 0x20; //2 Addresses in call stack
|
||||||
dma->asr1 = dma->madr + (dma->qwc << 4); //If no store Succeeding tag in ASR1
|
dma->asr1 = dma->madr + (dma->qwc << 4); //If no store Succeeding tag in ASR1
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -200,17 +200,17 @@ bool hwDmacSrcChainWithStack(DMACh *dma, int id) {
|
||||||
}
|
}
|
||||||
case TAG_RET: // Ret - Transfer QWC following the tag, load next tag
|
case TAG_RET: // Ret - Transfer QWC following the tag, load next tag
|
||||||
dma->madr = dma->tadr + 16; //Set MADR to data following the tag
|
dma->madr = dma->tadr + 16; //Set MADR to data following the tag
|
||||||
switch(CHCR::ASP(dma))
|
switch(dma->chcr.ASP)
|
||||||
{
|
{
|
||||||
case 2: { //If ASR1 is NOT equal to 0 (Contains address)
|
case 2: { //If ASR1 is NOT equal to 0 (Contains address)
|
||||||
dma->chcr = (dma->chcr & 0xffffffcf) | 0x10; //1 Address left in call stack
|
dma->chcr._u32 = (dma->chcr._u32 & 0xffffffcf) | 0x10; //1 Address left in call stack
|
||||||
dma->tadr = dma->asr1; //Read ASR1 as next tag
|
dma->tadr = dma->asr1; //Read ASR1 as next tag
|
||||||
dma->asr1 = 0; //Clear ASR1
|
dma->asr1 = 0; //Clear ASR1
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//If ASR1 is empty (No address held)
|
//If ASR1 is empty (No address held)
|
||||||
case 1:{ //Check if ASR0 is NOT equal to 0 (Contains address)
|
case 1:{ //Check if ASR0 is NOT equal to 0 (Contains address)
|
||||||
dma->chcr = (dma->chcr & 0xffffffcf); //No addresses left in call stack
|
dma->chcr._u32 = (dma->chcr._u32 & 0xffffffcf); //No addresses left in call stack
|
||||||
dma->tadr = dma->asr0; //Read ASR0 as next tag
|
dma->tadr = dma->asr0; //Read ASR0 as next tag
|
||||||
dma->asr0 = 0; //Clear ASR0
|
dma->asr0 = 0; //Clear ASR0
|
||||||
break;
|
break;
|
||||||
|
|
150
pcsx2/Hw.h
150
pcsx2/Hw.h
|
@ -47,8 +47,23 @@ void __fastcall WriteFIFO_page_7(u32 mem, const mem128_t *value);
|
||||||
// --- DMA ---
|
// --- DMA ---
|
||||||
//
|
//
|
||||||
|
|
||||||
|
union tDMA_CHCR {
|
||||||
|
struct {
|
||||||
|
u32 DIR : 1;
|
||||||
|
u32 reserved1 : 1;
|
||||||
|
u32 MOD : 2;
|
||||||
|
u32 ASP : 2;
|
||||||
|
u32 TTE : 1;
|
||||||
|
u32 TIE : 1;
|
||||||
|
u32 STR : 1;
|
||||||
|
u32 reserved2 : 7;
|
||||||
|
u32 TAG : 16;
|
||||||
|
};
|
||||||
|
u32 _u32;
|
||||||
|
};
|
||||||
|
|
||||||
struct DMACh {
|
struct DMACh {
|
||||||
u32 chcr;
|
tDMA_CHCR chcr;
|
||||||
u32 null0[3];
|
u32 null0[3];
|
||||||
u32 madr;
|
u32 madr;
|
||||||
u32 null1[3];
|
u32 null1[3];
|
||||||
|
@ -418,6 +433,137 @@ enum DMAInter
|
||||||
MEISintr = 0x40004000
|
MEISintr = 0x40004000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
union tDMAC_CTRL {
|
||||||
|
struct {
|
||||||
|
u32 DMAE : 1;
|
||||||
|
u32 RELE : 1;
|
||||||
|
u32 MFD : 2;
|
||||||
|
u32 STS : 2;
|
||||||
|
u32 STD : 2;
|
||||||
|
u32 RCYC : 3;
|
||||||
|
u32 reserved1 : 21;
|
||||||
|
};
|
||||||
|
u32 _u32;
|
||||||
|
};
|
||||||
|
|
||||||
|
union tDMAC_STAT {
|
||||||
|
struct {
|
||||||
|
u32 CIS0 : 1;
|
||||||
|
u32 CIS1 : 1;
|
||||||
|
u32 CIS2 : 1;
|
||||||
|
u32 CIS3 : 1;
|
||||||
|
u32 CIS4 : 1;
|
||||||
|
u32 CIS5 : 1;
|
||||||
|
u32 CIS6 : 1;
|
||||||
|
u32 CIS7 : 1;
|
||||||
|
u32 CIS8 : 1;
|
||||||
|
u32 CIS9 : 1;
|
||||||
|
u32 reserved1 : 3;
|
||||||
|
u32 SIS : 1;
|
||||||
|
u32 MEIS : 1;
|
||||||
|
u32 BEIS : 1;
|
||||||
|
u32 CIM0 : 1;
|
||||||
|
u32 CIM1 : 1;
|
||||||
|
u32 CIM2 : 1;
|
||||||
|
u32 CIM3 : 1;
|
||||||
|
u32 CIM4 : 1;
|
||||||
|
u32 CIM5 : 1;
|
||||||
|
u32 CIM6 : 1;
|
||||||
|
u32 CIM7 : 1;
|
||||||
|
u32 CIM8 : 1;
|
||||||
|
u32 CIM9 : 1;
|
||||||
|
u32 reserved2 : 3;
|
||||||
|
u32 SIM : 1;
|
||||||
|
u32 MEIM : 1;
|
||||||
|
u32 reserved3 : 1;
|
||||||
|
};
|
||||||
|
u32 _u32;
|
||||||
|
};
|
||||||
|
|
||||||
|
union tDMAC_PCR {
|
||||||
|
struct {
|
||||||
|
u32 CPC0 : 1;
|
||||||
|
u32 CPC1 : 1;
|
||||||
|
u32 CPC2 : 1;
|
||||||
|
u32 CPC3 : 1;
|
||||||
|
u32 CPC4 : 1;
|
||||||
|
u32 CPC5 : 1;
|
||||||
|
u32 CPC6 : 1;
|
||||||
|
u32 CPC7 : 1;
|
||||||
|
u32 CPC8 : 1;
|
||||||
|
u32 CPC9 : 1;
|
||||||
|
u32 reserved1 : 6;
|
||||||
|
u32 CDE0 : 1;
|
||||||
|
u32 CDE1 : 1;
|
||||||
|
u32 CDE2 : 1;
|
||||||
|
u32 CDE3 : 1;
|
||||||
|
u32 CDE4 : 1;
|
||||||
|
u32 CDE5 : 1;
|
||||||
|
u32 CDE6 : 1;
|
||||||
|
u32 CDE7 : 1;
|
||||||
|
u32 CDE8 : 1;
|
||||||
|
u32 CDE9 : 1;
|
||||||
|
u32 reserved2 : 5;
|
||||||
|
u32 PCE : 1;
|
||||||
|
};
|
||||||
|
u32 _u32;
|
||||||
|
};
|
||||||
|
|
||||||
|
union tDMAC_SQWC {
|
||||||
|
struct {
|
||||||
|
u32 SQWC : 8;
|
||||||
|
u32 reserved1 : 8;
|
||||||
|
u32 TQWC : 8;
|
||||||
|
u32 reserved2 : 8;
|
||||||
|
};
|
||||||
|
u32 _u32;
|
||||||
|
};
|
||||||
|
|
||||||
|
union tDMAC_RBSR {
|
||||||
|
struct {
|
||||||
|
u32 RMSK : 31;
|
||||||
|
u32 reserved1 : 1;
|
||||||
|
};
|
||||||
|
u32 _u32;
|
||||||
|
};
|
||||||
|
|
||||||
|
union tDMAC_RBOR {
|
||||||
|
struct {
|
||||||
|
u32 ADDR : 31;
|
||||||
|
u32 reserved1 : 1;
|
||||||
|
};
|
||||||
|
u32 _u32;
|
||||||
|
};
|
||||||
|
|
||||||
|
union tDMAC_STADR {
|
||||||
|
struct {
|
||||||
|
u32 ADDR : 31;
|
||||||
|
u32 reserved1 : 1;
|
||||||
|
};
|
||||||
|
u32 _u32;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DMACregisters
|
||||||
|
{
|
||||||
|
// Note: not yet tested.
|
||||||
|
tDMAC_CTRL ctrl;
|
||||||
|
u32 padding[3];
|
||||||
|
tDMAC_STAT stat;
|
||||||
|
u32 padding1[3];
|
||||||
|
tDMAC_PCR pcr;
|
||||||
|
u32 padding2[3];
|
||||||
|
|
||||||
|
tDMAC_SQWC sqwc;
|
||||||
|
u32 padding3[3];
|
||||||
|
tDMAC_RBSR rbsr;
|
||||||
|
u32 padding4[3];
|
||||||
|
tDMAC_RBOR rbor;
|
||||||
|
u32 padding5[3];
|
||||||
|
tDMAC_STADR stadr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define dmacRegs ((DMACregisters*)(PS2MEM_HW+0xE000))
|
||||||
|
|
||||||
#ifdef PCSX2_VIRTUAL_MEM
|
#ifdef PCSX2_VIRTUAL_MEM
|
||||||
|
|
||||||
#define dmaGetAddrBase(addr) (((addr) & 0x80000000) ? (void*)&PS2MEM_SCRATCH[(addr) & 0x3ff0] : (void*)(PS2MEM_BASE+TRANSFORM_ADDR(addr)))
|
#define dmaGetAddrBase(addr) (((addr) & 0x80000000) ? (void*)&PS2MEM_SCRATCH[(addr) & 0x3ff0] : (void*)(PS2MEM_BASE+TRANSFORM_ADDR(addr)))
|
||||||
|
@ -485,7 +631,7 @@ static __forceinline u32 *_dmaGetAddr(DMACh *dma, u32 addr, u32 num)
|
||||||
|
|
||||||
// DMA End
|
// DMA End
|
||||||
psHu32(DMAC_STAT) |= 1<<num;
|
psHu32(DMAC_STAT) |= 1<<num;
|
||||||
dma->chcr &= ~0x100;
|
dma->chcr.STR = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
|
|
|
@ -811,7 +811,7 @@ void IPUCMD_WRITE(u32 val)
|
||||||
|
|
||||||
case SCE_IPU_FDEC:
|
case SCE_IPU_FDEC:
|
||||||
IPU_LOG("IPU FDEC command. Skip 0x%X bits, FIFO 0x%X qwords, BP 0x%X, FP %d, CHCR 0x%x, %x",
|
IPU_LOG("IPU FDEC command. Skip 0x%X bits, FIFO 0x%X qwords, BP 0x%X, FP %d, CHCR 0x%x, %x",
|
||||||
val & 0x3f, g_BP.IFC, (int)g_BP.BP, g_BP.FP, ipu1dma->chcr, cpuRegs.pc);
|
val & 0x3f, g_BP.IFC, (int)g_BP.BP, g_BP.FP, ipu1dma->chcr._u32, cpuRegs.pc);
|
||||||
g_BP.BP += val & 0x3F;
|
g_BP.BP += val & 0x3F;
|
||||||
if (ipuFDEC(val)) return;
|
if (ipuFDEC(val)) return;
|
||||||
ipuRegs->cmd.BUSY = 0x80000000;
|
ipuRegs->cmd.BUSY = 0x80000000;
|
||||||
|
@ -840,7 +840,7 @@ void IPUCMD_WRITE(u32 val)
|
||||||
|
|
||||||
if (ipuCSC(ipuRegs->cmd.DATA))
|
if (ipuCSC(ipuRegs->cmd.DATA))
|
||||||
{
|
{
|
||||||
if (ipu0dma->qwc > 0 && (CHCR::STR(ipu0dma))) IPU_INT0_FROM();
|
if (ipu0dma->qwc > 0 && ipu0dma->chcr.STR) IPU_INT0_FROM();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -855,7 +855,7 @@ void IPUCMD_WRITE(u32 val)
|
||||||
if (ipuIDEC(val))
|
if (ipuIDEC(val))
|
||||||
{
|
{
|
||||||
// idec done, ipu0 done too
|
// idec done, ipu0 done too
|
||||||
if (ipu0dma->qwc > 0 && (CHCR::STR(ipu0dma))) IPU_INT0_FROM();
|
if (ipu0dma->qwc > 0 && ipu0dma->chcr.STR) IPU_INT0_FROM();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ipuRegs->topbusy = 0x80000000;
|
ipuRegs->topbusy = 0x80000000;
|
||||||
|
@ -867,7 +867,7 @@ void IPUCMD_WRITE(u32 val)
|
||||||
case SCE_IPU_BDEC:
|
case SCE_IPU_BDEC:
|
||||||
if (ipuBDEC(val))
|
if (ipuBDEC(val))
|
||||||
{
|
{
|
||||||
if (ipu0dma->qwc > 0 && (CHCR::STR(ipu0dma))) IPU_INT0_FROM();
|
if (ipu0dma->qwc > 0 && ipu0dma->chcr.STR) IPU_INT0_FROM();
|
||||||
if (ipuRegs->ctrl.SCD || ipuRegs->ctrl.ECD) hwIntcIrq(INTC_IPU);
|
if (ipuRegs->ctrl.SCD || ipuRegs->ctrl.ECD) hwIntcIrq(INTC_IPU);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -931,7 +931,7 @@ void IPUWorker()
|
||||||
hwIntcIrq(INTC_IPU);
|
hwIntcIrq(INTC_IPU);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((ipu0dma->qwc > 0) && (CHCR::STR(ipu0dma))) IPU_INT0_FROM();
|
if (ipu0dma->qwc > 0 && ipu0dma->chcr.STR) IPU_INT0_FROM();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCE_IPU_PACK:
|
case SCE_IPU_PACK:
|
||||||
|
@ -957,7 +957,7 @@ void IPUWorker()
|
||||||
ipuCurCmd = 0xffffffff;
|
ipuCurCmd = 0xffffffff;
|
||||||
|
|
||||||
// CHECK!: IPU0dma remains when IDEC is done, so we need to clear it
|
// CHECK!: IPU0dma remains when IDEC is done, so we need to clear it
|
||||||
if ((ipu0dma->qwc > 0) && (CHCR::STR(ipu0dma))) IPU_INT0_FROM();
|
if (ipu0dma->qwc > 0 && ipu0dma->chcr.STR) IPU_INT0_FROM();
|
||||||
s_routine = NULL;
|
s_routine = NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -974,7 +974,7 @@ void IPUWorker()
|
||||||
ipuRegs->cmd.BUSY = 0;
|
ipuRegs->cmd.BUSY = 0;
|
||||||
ipuCurCmd = 0xffffffff;
|
ipuCurCmd = 0xffffffff;
|
||||||
|
|
||||||
if ((ipu0dma->qwc > 0) && (CHCR::STR(ipu0dma))) IPU_INT0_FROM();
|
if (ipu0dma->qwc > 0 && ipu0dma->chcr.STR) IPU_INT0_FROM();
|
||||||
s_routine = NULL;
|
s_routine = NULL;
|
||||||
if (ipuRegs->ctrl.SCD || ipuRegs->ctrl.ECD) hwIntcIrq(INTC_IPU);
|
if (ipuRegs->ctrl.SCD || ipuRegs->ctrl.ECD) hwIntcIrq(INTC_IPU);
|
||||||
return;
|
return;
|
||||||
|
@ -1450,9 +1450,9 @@ static __forceinline bool ipuDmacSrcChain(DMACh *tag, u32 *ptag)
|
||||||
|
|
||||||
static __forceinline void flushGIF()
|
static __forceinline void flushGIF()
|
||||||
{
|
{
|
||||||
while(CHCR::STR(gif) && (vif1Regs->mskpath3 == 0))
|
while(gif->chcr.STR && (vif1Regs->mskpath3 == 0))
|
||||||
{
|
{
|
||||||
GIF_LOG("Flushing gif chcr %x tadr %x madr %x qwc %x", gif->chcr, gif->tadr, gif->madr, gif->qwc);
|
GIF_LOG("Flushing gif chcr %x tadr %x madr %x qwc %x", gif->chcr._u32, gif->tadr, gif->madr, gif->qwc);
|
||||||
gsInterrupt();
|
gsInterrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1463,9 +1463,9 @@ int IPU1dma()
|
||||||
bool done = false;
|
bool done = false;
|
||||||
int ipu1cycles = 0, totalqwc = 0;
|
int ipu1cycles = 0, totalqwc = 0;
|
||||||
|
|
||||||
assert(!(CHCR::TTE(ipu1dma)));
|
assert(!ipu1dma->chcr.TTE);
|
||||||
|
|
||||||
if (!(CHCR::STR(ipu1dma)) || (cpuRegs.interrupt & (1 << DMAC_TO_IPU))) return 0;
|
if (!(ipu1dma->chcr.STR) || (cpuRegs.interrupt & (1 << DMAC_TO_IPU))) return 0;
|
||||||
|
|
||||||
assert(!(g_nDMATransfer & IPU_DMA_TIE1));
|
assert(!(g_nDMATransfer & IPU_DMA_TIE1));
|
||||||
|
|
||||||
|
@ -1478,7 +1478,7 @@ int IPU1dma()
|
||||||
if (IPU1chain(totalqwc)) return totalqwc;
|
if (IPU1chain(totalqwc)) return totalqwc;
|
||||||
|
|
||||||
//Check TIE bit of CHCR and IRQ bit of tag
|
//Check TIE bit of CHCR and IRQ bit of tag
|
||||||
if (CHCR::TIE(ipu1dma) && (g_nDMATransfer & IPU_DMA_DOTIE1))
|
if (ipu1dma->chcr.TIE && (g_nDMATransfer & IPU_DMA_DOTIE1))
|
||||||
{
|
{
|
||||||
Console::WriteLn("IPU1 TIE");
|
Console::WriteLn("IPU1 TIE");
|
||||||
|
|
||||||
|
@ -1488,7 +1488,7 @@ int IPU1dma()
|
||||||
return totalqwc;
|
return totalqwc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CHCR::MOD(ipu1dma) == NORMAL_MODE) // If mode is normal mode.
|
if (ipu1dma->chcr.MOD == NORMAL_MODE) // If mode is normal mode.
|
||||||
{
|
{
|
||||||
IPU_INT_TO(totalqwc * BIAS);
|
IPU_INT_TO(totalqwc * BIAS);
|
||||||
return totalqwc;
|
return totalqwc;
|
||||||
|
@ -1496,9 +1496,9 @@ int IPU1dma()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Chain mode.
|
// Chain mode.
|
||||||
u32 tag = ipu1dma->chcr; // upper bits describe current tag
|
u32 tag = ipu1dma->chcr._u32; // upper bits describe current tag
|
||||||
|
|
||||||
if (CHCR::TIE(ipu1dma) && Tag::IRQ(tag))
|
if (ipu1dma->chcr.TIE && Tag::IRQ(tag))
|
||||||
{
|
{
|
||||||
ptag = (u32*)dmaGetAddr(ipu1dma->tadr);
|
ptag = (u32*)dmaGetAddr(ipu1dma->tadr);
|
||||||
|
|
||||||
|
@ -1523,7 +1523,7 @@ int IPU1dma()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normal Mode & qwc is finished
|
// Normal Mode & qwc is finished
|
||||||
if ((CHCR::MOD(ipu1dma) == NORMAL_MODE) && (ipu1dma->qwc == 0))
|
if ((ipu1dma->chcr.MOD == NORMAL_MODE) && (ipu1dma->qwc == 0))
|
||||||
{
|
{
|
||||||
//Console::WriteLn("ipu1 normal empty qwc?");
|
//Console::WriteLn("ipu1 normal empty qwc?");
|
||||||
return totalqwc;
|
return totalqwc;
|
||||||
|
@ -1555,7 +1555,7 @@ int IPU1dma()
|
||||||
ptag[1], ptag[0], ipu1dma->qwc, ipu1dma->madr, 8 - g_BP.IFC);
|
ptag[1], ptag[0], ipu1dma->qwc, ipu1dma->madr, 8 - g_BP.IFC);
|
||||||
|
|
||||||
|
|
||||||
if (CHCR::TIE(ipu1dma) && Tag::IRQ(ptag))
|
if (ipu1dma->chcr.TIE && Tag::IRQ(ptag))
|
||||||
g_nDMATransfer |= IPU_DMA_DOTIE1;
|
g_nDMATransfer |= IPU_DMA_DOTIE1;
|
||||||
else
|
else
|
||||||
g_nDMATransfer &= ~IPU_DMA_DOTIE1;
|
g_nDMATransfer &= ~IPU_DMA_DOTIE1;
|
||||||
|
@ -1672,15 +1672,15 @@ int IPU0dma()
|
||||||
int readsize;
|
int readsize;
|
||||||
void* pMem;
|
void* pMem;
|
||||||
|
|
||||||
if ((!(CHCR::STR(ipu0dma)) || (cpuRegs.interrupt & (1 << DMAC_FROM_IPU))) || (ipu0dma->qwc == 0))
|
if ((!(ipu0dma->chcr.STR) || (cpuRegs.interrupt & (1 << DMAC_FROM_IPU))) || (ipu0dma->qwc == 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
assert(!(CHCR::TTE(ipu0dma)));
|
assert(!(ipu0dma->chcr.TTE));
|
||||||
|
|
||||||
IPU_LOG("dmaIPU0 chcr = %lx, madr = %lx, qwc = %lx",
|
IPU_LOG("dmaIPU0 chcr = %lx, madr = %lx, qwc = %lx",
|
||||||
ipu0dma->chcr, ipu0dma->madr, ipu0dma->qwc);
|
ipu0dma->chcr._u32, ipu0dma->madr, ipu0dma->qwc);
|
||||||
|
|
||||||
assert((ipu0dma->chcr & 0xC) == 0);
|
assert((ipu0dma->chcr._u32 & 0xC) == 0);
|
||||||
pMem = (u32*)dmaGetAddr(ipu0dma->madr);
|
pMem = (u32*)dmaGetAddr(ipu0dma->madr);
|
||||||
readsize = min(ipu0dma->qwc, (u16)ipuRegs->ctrl.OFC);
|
readsize = min(ipu0dma->qwc, (u16)ipuRegs->ctrl.OFC);
|
||||||
FIFOfrom_read(pMem, readsize);
|
FIFOfrom_read(pMem, readsize);
|
||||||
|
@ -1734,14 +1734,14 @@ void ipu0Interrupt()
|
||||||
{
|
{
|
||||||
// gif
|
// gif
|
||||||
g_nDMATransfer &= ~IPU_DMA_GIFSTALL;
|
g_nDMATransfer &= ~IPU_DMA_GIFSTALL;
|
||||||
if (CHCR::STR(gif)) GIFdma();
|
if (gif->chcr.STR) GIFdma();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_nDMATransfer & IPU_DMA_VIFSTALL)
|
if (g_nDMATransfer & IPU_DMA_VIFSTALL)
|
||||||
{
|
{
|
||||||
// vif
|
// vif
|
||||||
g_nDMATransfer &= ~IPU_DMA_VIFSTALL;
|
g_nDMATransfer &= ~IPU_DMA_VIFSTALL;
|
||||||
if (CHCR::STR(vif1ch)) dmaVIF1();
|
if (vif1ch->chcr.STR) dmaVIF1();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_nDMATransfer & IPU_DMA_TIE0)
|
if (g_nDMATransfer & IPU_DMA_TIE0)
|
||||||
|
@ -1749,7 +1749,7 @@ void ipu0Interrupt()
|
||||||
g_nDMATransfer &= ~IPU_DMA_TIE0;
|
g_nDMATransfer &= ~IPU_DMA_TIE0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHCR::clearSTR(ipu0dma);
|
ipu0dma->chcr.STR = 0;
|
||||||
|
|
||||||
hwDmacIrq(DMAC_FROM_IPU);
|
hwDmacIrq(DMAC_FROM_IPU);
|
||||||
}
|
}
|
||||||
|
@ -1767,7 +1767,7 @@ IPU_FORCEINLINE void ipu1Interrupt()
|
||||||
if (g_nDMATransfer & IPU_DMA_TIE1)
|
if (g_nDMATransfer & IPU_DMA_TIE1)
|
||||||
g_nDMATransfer &= ~IPU_DMA_TIE1;
|
g_nDMATransfer &= ~IPU_DMA_TIE1;
|
||||||
else
|
else
|
||||||
CHCR::clearSTR(ipu1dma);
|
ipu1dma->chcr.STR = 0;
|
||||||
|
|
||||||
hwDmacIrq(DMAC_TO_IPU);
|
hwDmacIrq(DMAC_TO_IPU);
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,40 +60,6 @@ union tIPU_CMD {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ipu_ctrl_m_flags
|
|
||||||
{
|
|
||||||
IPU_CTRL_IFC_M = (0x0f<< 0),
|
|
||||||
IPU_CTRL_OFC_M = (0x0f<< 4),
|
|
||||||
IPU_CTRL_CBP_M = (0x3f<< 8),
|
|
||||||
IPU_CTRL_ECD_M = (0x01<<14),
|
|
||||||
IPU_CTRL_SCD_M = (0x01<<15),
|
|
||||||
IPU_CTRL_IDP_M = (0x03<<16),
|
|
||||||
IPU_CTRL_AS_M = (0x01<<20),
|
|
||||||
IPU_CTRL_IVF_M = (0x01<<21),
|
|
||||||
IPU_CTRL_QST_M = (0x01<<22),
|
|
||||||
IPU_CTRL_MP1_M = (0x01<<23),
|
|
||||||
IPU_CTRL_PCT_M = (0x07<<24),
|
|
||||||
IPU_CTRL_RST_M = (0x01<<30),
|
|
||||||
IPU_CTRL_BUSY_M = (0x01<<31)
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ipu_ctrl_o_flags
|
|
||||||
{
|
|
||||||
IPU_CTRL_IFC_O = ( 0),
|
|
||||||
IPU_CTRL_OFC_O = ( 4),
|
|
||||||
IPU_CTRL_CBP_O = ( 8),
|
|
||||||
IPU_CTRL_ECD_O = (14),
|
|
||||||
IPU_CTRL_SCD_O = (15),
|
|
||||||
IPU_CTRL_IDP_O = (16),
|
|
||||||
IPU_CTRL_AS_O = (20),
|
|
||||||
IPU_CTRL_IVF_O = (21),
|
|
||||||
IPU_CTRL_QST_O = (22),
|
|
||||||
IPU_CTRL_MP1_O = (23),
|
|
||||||
IPU_CTRL_PCT_O = (24),
|
|
||||||
IPU_CTRL_RST_O = (30),
|
|
||||||
IPU_CTRL_BUSY_O = (31)
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Bitfield Structure
|
// Bitfield Structure
|
||||||
//
|
//
|
||||||
|
@ -118,20 +84,6 @@ union tIPU_CTRL {
|
||||||
u32 _u32;
|
u32 _u32;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ipu_bp_m_flags
|
|
||||||
{
|
|
||||||
IPU_BP_BP_M = (0x7f<< 0),
|
|
||||||
IPU_BP_IFC_M = (0x0f<< 8),
|
|
||||||
IPU_BP_FP_M = (0x03<<16)
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ipu_bp_o_flags
|
|
||||||
{
|
|
||||||
IPU_BP_BP_O = ( 0),
|
|
||||||
IPU_BP_IFC_O = ( 8),
|
|
||||||
IPU_BP_FP_O = (16)
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Bitfield Structure
|
// Bitfield Structure
|
||||||
//
|
//
|
||||||
|
|
|
@ -321,21 +321,15 @@ static const LegacyApi_OptMethod s_MethMessOpt_PAD[] =
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void CALLBACK CDVD_newDiskCB(void (*callback)()) {}
|
void CALLBACK CDVD_newDiskCB(void (*callback)()) {}
|
||||||
|
|
||||||
extern int lastReadSize;
|
extern int lastReadSize, lastLSN;
|
||||||
static s32 CALLBACK CDVD_getBuffer2(u8* buffer)
|
static s32 CALLBACK CDVD_getBuffer2(u8* buffer)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
// TEMP: until I fix all the plugins to use this function style
|
// TEMP: until I fix all the plugins to use this function style
|
||||||
u8* pb = CDVD->getBuffer();
|
u8* pb = CDVD->getBuffer();
|
||||||
if(pb != NULL)
|
if(pb == NULL) return -2;
|
||||||
{
|
|
||||||
memcpy(buffer,pb,lastReadSize);
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
else ret = -2;
|
|
||||||
|
|
||||||
return ret;
|
memcpy_fast( buffer, pb, lastReadSize );
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static s32 CALLBACK CDVD_readSector(u8* buffer, u32 lsn, int mode)
|
static s32 CALLBACK CDVD_readSector(u8* buffer, u32 lsn, int mode)
|
||||||
|
@ -359,6 +353,8 @@ static s32 CALLBACK CDVD_readSector(u8* buffer, u32 lsn, int mode)
|
||||||
lastReadSize = 2048;
|
lastReadSize = 2048;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastLSN = lsn;
|
||||||
return CDVD->getBuffer2(buffer);
|
return CDVD->getBuffer2(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,7 @@ static __forceinline void _dmaSPR0()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer Dn_QWC from SPR to Dn_MADR
|
// Transfer Dn_QWC from SPR to Dn_MADR
|
||||||
switch(CHCR::MOD(spr0))
|
switch(spr0->chcr.MOD)
|
||||||
{
|
{
|
||||||
case NORMAL_MODE:
|
case NORMAL_MODE:
|
||||||
{
|
{
|
||||||
|
@ -192,7 +192,7 @@ static __forceinline void _dmaSPR0()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SPR0chain();
|
SPR0chain();
|
||||||
if (CHCR::TIE(spr0) && Tag::IRQ(ptag)) //Check TIE bit of CHCR and IRQ bit of tag
|
if (spr0->chcr.TIE && Tag::IRQ(ptag)) //Check TIE bit of CHCR and IRQ bit of tag
|
||||||
{
|
{
|
||||||
//Console::WriteLn("SPR0 TIE");
|
//Console::WriteLn("SPR0 TIE");
|
||||||
done = TRUE;
|
done = TRUE;
|
||||||
|
@ -229,23 +229,23 @@ void SPRFROMinterrupt()
|
||||||
{
|
{
|
||||||
if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("GIF MFIFO Write outside MFIFO area");
|
if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("GIF MFIFO Write outside MFIFO area");
|
||||||
spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR));
|
spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR));
|
||||||
//Console::WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", params gif->chcr, gif->madr, gif->tadr);
|
//Console::WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", params gif->chcr._u32, gif->madr, gif->tadr);
|
||||||
mfifoGIFtransfer(mfifotransferred);
|
mfifoGIFtransfer(mfifotransferred);
|
||||||
mfifotransferred = 0;
|
mfifotransferred = 0;
|
||||||
if (CHCR::STR(gif)) return;
|
if (gif->chcr.STR) return;
|
||||||
}
|
}
|
||||||
else if ((psHu32(DMAC_CTRL) & 0xC) == 0x8) // VIF1 MFIFO
|
else if ((psHu32(DMAC_CTRL) & 0xC) == 0x8) // VIF1 MFIFO
|
||||||
{
|
{
|
||||||
if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("VIF MFIFO Write outside MFIFO area");
|
if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("VIF MFIFO Write outside MFIFO area");
|
||||||
spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR));
|
spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR));
|
||||||
//Console::WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", params vif1ch->chcr, vif1ch->madr, vif1ch->tadr);
|
//Console::WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", params vif1ch->chcr._u32, vif1ch->madr, vif1ch->tadr);
|
||||||
mfifoVIF1transfer(mfifotransferred);
|
mfifoVIF1transfer(mfifotransferred);
|
||||||
mfifotransferred = 0;
|
mfifotransferred = 0;
|
||||||
if (CHCR::STR(vif1ch)) return;
|
if (vif1ch->chcr.STR) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (spr0finished == 0) return;
|
if (spr0finished == 0) return;
|
||||||
CHCR::clearSTR(spr0);
|
spr0->chcr.STR = 0;
|
||||||
hwDmacIrq(DMAC_FROM_SPR);
|
hwDmacIrq(DMAC_FROM_SPR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,9 +253,9 @@ void SPRFROMinterrupt()
|
||||||
void dmaSPR0() // fromSPR
|
void dmaSPR0() // fromSPR
|
||||||
{
|
{
|
||||||
SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx",
|
SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx",
|
||||||
spr0->chcr, spr0->madr, spr0->qwc, spr0->sadr);
|
spr0->chcr._u32, spr0->madr, spr0->qwc, spr0->sadr);
|
||||||
|
|
||||||
if ((CHCR::MOD(spr0) == CHAIN_MODE) && spr0->qwc == 0)
|
if ((spr0->chcr.MOD == CHAIN_MODE) && spr0->qwc == 0)
|
||||||
{
|
{
|
||||||
u32 *ptag;
|
u32 *ptag;
|
||||||
ptag = (u32*) & PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; //Set memory pointer to SADR
|
ptag = (u32*) & PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; //Set memory pointer to SADR
|
||||||
|
@ -324,7 +324,7 @@ void _SPR1interleave()
|
||||||
|
|
||||||
void _dmaSPR1() // toSPR work function
|
void _dmaSPR1() // toSPR work function
|
||||||
{
|
{
|
||||||
switch(CHCR::MOD(spr1))
|
switch(spr1->chcr.MOD)
|
||||||
{
|
{
|
||||||
case NORMAL_MODE:
|
case NORMAL_MODE:
|
||||||
{
|
{
|
||||||
|
@ -338,7 +338,7 @@ void _dmaSPR1() // toSPR work function
|
||||||
{
|
{
|
||||||
u32 *ptag;
|
u32 *ptag;
|
||||||
int id;
|
int id;
|
||||||
bool done = FALSE;
|
bool done = false;
|
||||||
|
|
||||||
if (spr1->qwc > 0)
|
if (spr1->qwc > 0)
|
||||||
{
|
{
|
||||||
|
@ -353,7 +353,7 @@ void _dmaSPR1() // toSPR work function
|
||||||
|
|
||||||
if (!(Tag::Transfer("SPR1 Tag", spr1, ptag)))
|
if (!(Tag::Transfer("SPR1 Tag", spr1, ptag)))
|
||||||
{
|
{
|
||||||
done = TRUE;
|
done = true;
|
||||||
spr1finished = (done) ? 1: 0;
|
spr1finished = (done) ? 1: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,7 +361,7 @@ void _dmaSPR1() // toSPR work function
|
||||||
spr1->madr = ptag[1]; //MADR = ADDR field
|
spr1->madr = ptag[1]; //MADR = ADDR field
|
||||||
|
|
||||||
// Transfer dma tag if tte is set
|
// Transfer dma tag if tte is set
|
||||||
if (CHCR::TTE(spr1))
|
if (spr1->chcr.TTE)
|
||||||
{
|
{
|
||||||
SPR_LOG("SPR TTE: %x_%x\n", ptag[3], ptag[2]);
|
SPR_LOG("SPR TTE: %x_%x\n", ptag[3], ptag[2]);
|
||||||
SPR1transfer(ptag, 4); //Transfer Tag
|
SPR1transfer(ptag, 4); //Transfer Tag
|
||||||
|
@ -373,12 +373,12 @@ void _dmaSPR1() // toSPR work function
|
||||||
done = (hwDmacSrcChain(spr1, id) == 1);
|
done = (hwDmacSrcChain(spr1, id) == 1);
|
||||||
SPR1chain(); //Transfers the data set by the switch
|
SPR1chain(); //Transfers the data set by the switch
|
||||||
|
|
||||||
if (CHCR::TIE(spr1) && Tag::IRQ(ptag)) //Check TIE bit of CHCR and IRQ bit of tag
|
if (spr1->chcr.TIE && Tag::IRQ(ptag)) //Check TIE bit of CHCR and IRQ bit of tag
|
||||||
{
|
{
|
||||||
SPR_LOG("dmaIrq Set");
|
SPR_LOG("dmaIrq Set");
|
||||||
|
|
||||||
//Console::WriteLn("SPR1 TIE");
|
//Console::WriteLn("SPR1 TIE");
|
||||||
done = TRUE;
|
done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
spr1finished = done;
|
spr1finished = done;
|
||||||
|
@ -403,10 +403,10 @@ void dmaSPR1() // toSPR
|
||||||
|
|
||||||
SPR_LOG("dmaSPR1 chcr = 0x%x, madr = 0x%x, qwc = 0x%x\n"
|
SPR_LOG("dmaSPR1 chcr = 0x%x, madr = 0x%x, qwc = 0x%x\n"
|
||||||
" tadr = 0x%x, sadr = 0x%x",
|
" tadr = 0x%x, sadr = 0x%x",
|
||||||
spr1->chcr, spr1->madr, spr1->qwc,
|
spr1->chcr._u32, spr1->madr, spr1->qwc,
|
||||||
spr1->tadr, spr1->sadr);
|
spr1->tadr, spr1->sadr);
|
||||||
|
|
||||||
if ((CHCR::MOD(spr1) == CHAIN_MODE) && (spr1->qwc == 0))
|
if ((spr1->chcr.MOD == CHAIN_MODE) && (spr1->qwc == 0))
|
||||||
{
|
{
|
||||||
u32 *ptag;
|
u32 *ptag;
|
||||||
ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR
|
ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR
|
||||||
|
@ -423,7 +423,7 @@ void SPRTOinterrupt()
|
||||||
{
|
{
|
||||||
_dmaSPR1();
|
_dmaSPR1();
|
||||||
if (spr1finished == 0) return;
|
if (spr1finished == 0) return;
|
||||||
CHCR::clearSTR(spr1);
|
spr1->chcr.STR = 0;
|
||||||
hwDmacIrq(DMAC_TO_SPR);
|
hwDmacIrq(DMAC_TO_SPR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -222,7 +222,7 @@ __forceinline void SIF0Dma()
|
||||||
if (sif0dma->qwc == 0)
|
if (sif0dma->qwc == 0)
|
||||||
{
|
{
|
||||||
// Stop if TIE & the IRQ are set, or at the end. (I'll try to convert this to use the tags code later.)
|
// Stop if TIE & the IRQ are set, or at the end. (I'll try to convert this to use the tags code later.)
|
||||||
if (((sif0dma->chcr & 0x80000080) == 0x80000080) || (sif0.end))
|
if (((sif0dma->chcr._u32 & 0x80000080) == 0x80000080) || (sif0.end))
|
||||||
{
|
{
|
||||||
if (sif0.end)
|
if (sif0.end)
|
||||||
SIF_LOG(" EE SIF end");
|
SIF_LOG(" EE SIF end");
|
||||||
|
@ -241,7 +241,7 @@ __forceinline void SIF0Dma()
|
||||||
|
|
||||||
sif0dma->qwc = (u16)tag[0];
|
sif0dma->qwc = (u16)tag[0];
|
||||||
sif0dma->madr = tag[1];
|
sif0dma->madr = tag[1];
|
||||||
sif0dma->chcr = (sif0dma->chcr & 0xffff) | (tag[0] & 0xffff0000);
|
sif0dma->chcr._u32 = (sif0dma->chcr._u32 & 0xffff) | (tag[0] & 0xffff0000);
|
||||||
|
|
||||||
SIF_LOG(" EE SIF dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)", sif0dma->madr, sif0dma->qwc, (tag[0] >> 28)&3, (tag[0] >> 31)&1, tag[1], tag[0]);
|
SIF_LOG(" EE SIF dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)", sif0dma->madr, sif0dma->qwc, (tag[0] >> 28)&3, (tag[0] >> 31)&1, tag[1], tag[0]);
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ __forceinline void SIF1Dma()
|
||||||
|
|
||||||
if (sif1dma->qwc == 0) // If there's no more to transfer
|
if (sif1dma->qwc == 0) // If there's no more to transfer
|
||||||
{
|
{
|
||||||
if ((CHCR::MOD(sif1dma) == NORMAL_MODE) || sif1.end) // If NORMAL mode or end of CHAIN then stop DMA
|
if ((sif1dma->chcr.MOD == NORMAL_MODE) || sif1.end) // If NORMAL mode or end of CHAIN then stop DMA
|
||||||
{
|
{
|
||||||
// Stop & signal interrupts on EE
|
// Stop & signal interrupts on EE
|
||||||
SIF_LOG("EE SIF1 End %x", sif1.end);
|
SIF_LOG("EE SIF1 End %x", sif1.end);
|
||||||
|
@ -294,10 +294,10 @@ __forceinline void SIF1Dma()
|
||||||
//_dmaGetAddr(sif1dma, *ptag, sif1dma->tadr, 6);
|
//_dmaGetAddr(sif1dma, *ptag, sif1dma->tadr, 6);
|
||||||
|
|
||||||
|
|
||||||
sif1dma->chcr = (sif1dma->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); // Copy the tag
|
sif1dma->chcr._u32 = (sif1dma->chcr._u32 & 0xFFFF) | ((*ptag) & 0xFFFF0000); // Copy the tag
|
||||||
sif1dma->qwc = (u16)ptag[0];
|
sif1dma->qwc = (u16)ptag[0];
|
||||||
|
|
||||||
if (CHCR::TTE(sif1dma))
|
if (sif1dma->chcr.TTE)
|
||||||
{
|
{
|
||||||
Console::WriteLn("SIF1 TTE");
|
Console::WriteLn("SIF1 TTE");
|
||||||
SIF1write(ptag + 2, 2);
|
SIF1write(ptag + 2, 2);
|
||||||
|
@ -343,7 +343,7 @@ __forceinline void SIF1Dma()
|
||||||
default:
|
default:
|
||||||
Console::WriteLn("Bad addr1 source chain");
|
Console::WriteLn("Bad addr1 source chain");
|
||||||
}
|
}
|
||||||
if ((CHCR::TIE(sif1dma)) && (Tag::IRQ(ptag)))
|
if ((sif1dma->chcr.TIE) && (Tag::IRQ(ptag)))
|
||||||
{
|
{
|
||||||
Console::WriteLn("SIF1 TIE");
|
Console::WriteLn("SIF1 TIE");
|
||||||
sif1.end = 1;
|
sif1.end = 1;
|
||||||
|
@ -435,19 +435,19 @@ __forceinline void sif1Interrupt()
|
||||||
__forceinline void EEsif0Interrupt()
|
__forceinline void EEsif0Interrupt()
|
||||||
{
|
{
|
||||||
hwDmacIrq(DMAC_SIF0);
|
hwDmacIrq(DMAC_SIF0);
|
||||||
CHCR::clearSTR(sif0dma);
|
sif0dma->chcr.STR = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline void EEsif1Interrupt()
|
__forceinline void EEsif1Interrupt()
|
||||||
{
|
{
|
||||||
hwDmacIrq(DMAC_SIF1);
|
hwDmacIrq(DMAC_SIF1);
|
||||||
CHCR::clearSTR(sif1dma);
|
sif1dma->chcr.STR = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline void dmaSIF0()
|
__forceinline void dmaSIF0()
|
||||||
{
|
{
|
||||||
SIF_LOG("EE: dmaSIF0 chcr = %lx, madr = %lx, qwc = %lx, tadr = %lx",
|
SIF_LOG("EE: dmaSIF0 chcr = %lx, madr = %lx, qwc = %lx, tadr = %lx",
|
||||||
sif0dma->chcr, sif0dma->madr, sif0dma->qwc, sif0dma->tadr);
|
sif0dma->chcr._u32, sif0dma->madr, sif0dma->qwc, sif0dma->tadr);
|
||||||
|
|
||||||
if (sif0.fifoReadPos != sif0.fifoWritePos)
|
if (sif0.fifoReadPos != sif0.fifoWritePos)
|
||||||
{
|
{
|
||||||
|
@ -470,7 +470,7 @@ __forceinline void dmaSIF0()
|
||||||
__forceinline void dmaSIF1()
|
__forceinline void dmaSIF1()
|
||||||
{
|
{
|
||||||
SIF_LOG("EE: dmaSIF1 chcr = %lx, madr = %lx, qwc = %lx, tadr = %lx",
|
SIF_LOG("EE: dmaSIF1 chcr = %lx, madr = %lx, qwc = %lx, tadr = %lx",
|
||||||
sif1dma->chcr, sif1dma->madr, sif1dma->qwc, sif1dma->tadr);
|
sif1dma->chcr._u32, sif1dma->madr, sif1dma->qwc, sif1dma->tadr);
|
||||||
|
|
||||||
if (sif1.fifoReadPos != sif1.fifoWritePos)
|
if (sif1.fifoReadPos != sif1.fifoWritePos)
|
||||||
{
|
{
|
||||||
|
@ -494,9 +494,9 @@ __forceinline void dmaSIF1()
|
||||||
__forceinline void dmaSIF2()
|
__forceinline void dmaSIF2()
|
||||||
{
|
{
|
||||||
SIF_LOG("dmaSIF2 chcr = %lx, madr = %lx, qwc = %lx",
|
SIF_LOG("dmaSIF2 chcr = %lx, madr = %lx, qwc = %lx",
|
||||||
sif2dma->chcr, sif2dma->madr, sif2dma->qwc);
|
sif2dma->chcr._u32, sif2dma->madr, sif2dma->qwc);
|
||||||
|
|
||||||
CHCR::clearSTR(sif2dma);
|
sif2dma->chcr.STR = 0;
|
||||||
hwDmacIrq(DMAC_SIF2);
|
hwDmacIrq(DMAC_SIF2);
|
||||||
Console::WriteLn("*PCSX2*: dmaSIF2");
|
Console::WriteLn("*PCSX2*: dmaSIF2");
|
||||||
}
|
}
|
||||||
|
|
114
pcsx2/Tags.h
114
pcsx2/Tags.h
|
@ -107,7 +107,7 @@ namespace Tag
|
||||||
static __forceinline void UpperTransfer(DMACh *tag, u32* ptag)
|
static __forceinline void UpperTransfer(DMACh *tag, u32* ptag)
|
||||||
{
|
{
|
||||||
// Transfer upper part of tag to CHCR bits 31-15
|
// Transfer upper part of tag to CHCR bits 31-15
|
||||||
tag->chcr = (tag->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000);
|
tag->chcr._u32 = (tag->chcr._u32 & 0xFFFF) | ((*ptag) & 0xFFFF0000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __forceinline void LowerTransfer(DMACh *tag, u32* ptag)
|
static __forceinline void LowerTransfer(DMACh *tag, u32* ptag)
|
||||||
|
@ -193,100 +193,28 @@ namespace Tag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace CHCR
|
// Print information about a chcr tag.
|
||||||
|
static __forceinline void PrintCHCR(const char* s, DMACh *tag)
|
||||||
{
|
{
|
||||||
// Query the flags in the channel control register.
|
u8 num_addr = tag->chcr.ASP;
|
||||||
static __forceinline bool STR(DMACh *tag) { return !!(tag->chcr & CHCR_STR); }
|
u32 mode = tag->chcr.MOD;
|
||||||
static __forceinline bool TIE(DMACh *tag) { return !!(tag->chcr & CHCR_TIE); }
|
|
||||||
static __forceinline bool TTE(DMACh *tag) { return !!(tag->chcr & CHCR_TTE); }
|
|
||||||
static __forceinline u8 DIR(DMACh *tag) { return (tag->chcr & CHCR_DIR); }
|
|
||||||
|
|
||||||
static __forceinline TransferMode MOD(DMACh *tag)
|
Console::Write("%s chcr %s mem: ", params s, (tag->chcr.DIR) ? "from" : "to");
|
||||||
{
|
|
||||||
return (TransferMode)((tag->chcr & CHCR_MOD) >> 2);
|
if (mode == NORMAL_MODE)
|
||||||
}
|
Console::Write(" normal mode; ");
|
||||||
|
else if (mode == CHAIN_MODE)
|
||||||
static __forceinline u8 ASP(DMACh *tag)
|
Console::Write(" chain mode; ");
|
||||||
{
|
else if (mode == INTERLEAVE_MODE)
|
||||||
|
Console::Write(" interleave mode; ");
|
||||||
return (TransferMode)((tag->chcr & CHCR_ASP) >> 4);
|
else
|
||||||
}
|
Console::Write(" ?? mode; ");
|
||||||
|
|
||||||
// Clear the individual flags.
|
if (num_addr != 0) Console::Write("ASP = %d;", params num_addr);
|
||||||
static __forceinline void clearSTR(DMACh *tag) { tag->chcr &= ~CHCR_STR; }
|
if (tag->chcr.TTE) Console::Write("TTE;");
|
||||||
static __forceinline void clearTIE(DMACh *tag) { tag->chcr &= ~CHCR_TIE; }
|
if (tag->chcr.TIE) Console::Write("TIE;");
|
||||||
static __forceinline void clearTTE(DMACh *tag) { tag->chcr &= ~CHCR_TTE; }
|
if (tag->chcr.STR) Console::Write(" (DMA started)."); else Console::Write(" (DMA stopped).");
|
||||||
static __forceinline void clearDIR(DMACh *tag) { tag->chcr &= ~CHCR_DIR; }
|
Console::WriteLn("");
|
||||||
|
|
||||||
// Set them.
|
|
||||||
static __forceinline void setSTR(DMACh *tag) { tag->chcr |= CHCR_STR; }
|
|
||||||
static __forceinline void setTIE(DMACh *tag) { tag->chcr |= CHCR_TIE; }
|
|
||||||
static __forceinline void setTTE(DMACh *tag) { tag->chcr |= CHCR_TTE; }
|
|
||||||
static __forceinline void setDIR(DMACh *tag) { tag->chcr |= CHCR_DIR; }
|
|
||||||
|
|
||||||
static __forceinline void setMOD(DMACh *tag, TransferMode mode)
|
|
||||||
{
|
|
||||||
if (mode & (1 << 0))
|
|
||||||
tag->chcr |= CHCR_MOD1;
|
|
||||||
else
|
|
||||||
tag->chcr &= CHCR_MOD1;
|
|
||||||
|
|
||||||
if (mode & (1 << 1))
|
|
||||||
tag->chcr |= CHCR_MOD2;
|
|
||||||
else
|
|
||||||
tag->chcr &= CHCR_MOD2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __forceinline void setASP(DMACh *tag, u8 num)
|
|
||||||
{
|
|
||||||
if (num & (1 << 0))
|
|
||||||
tag->chcr |= CHCR_ASP1;
|
|
||||||
else
|
|
||||||
tag->chcr &= CHCR_ASP2;
|
|
||||||
|
|
||||||
if (num & (1 << 1))
|
|
||||||
tag->chcr |= CHCR_ASP1;
|
|
||||||
else
|
|
||||||
tag->chcr &= CHCR_ASP2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print information about a chcr tag.
|
|
||||||
static __forceinline void Print(const char* s, DMACh *tag)
|
|
||||||
{
|
|
||||||
u8 num_addr = ASP(tag);
|
|
||||||
TransferMode mode = MOD(tag);
|
|
||||||
|
|
||||||
Console::Write("%s chcr %s mem: ", params s, CHCR::DIR(tag) ? "from" : "to");
|
|
||||||
|
|
||||||
if (mode == NORMAL_MODE)
|
|
||||||
Console::Write(" normal mode; ");
|
|
||||||
else if (mode == CHAIN_MODE)
|
|
||||||
Console::Write(" chain mode; ");
|
|
||||||
else if (mode == INTERLEAVE_MODE)
|
|
||||||
Console::Write(" interleave mode; ");
|
|
||||||
else
|
|
||||||
Console::Write(" ?? mode; ");
|
|
||||||
|
|
||||||
if (num_addr != 0) Console::Write("ASP = %d;", params num_addr);
|
|
||||||
if (TTE(tag)) Console::Write("TTE;");
|
|
||||||
if (TIE(tag)) Console::Write("TIE;");
|
|
||||||
if (STR(tag)) Console::Write(" (DMA started)."); else Console::Write(" (DMA stopped).");
|
|
||||||
Console::WriteLn("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace QWC
|
|
||||||
{
|
|
||||||
static __forceinline bool Empty(DMACh *tag)
|
|
||||||
{
|
|
||||||
return (tag->qwc == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static __forceinline void Clear(DMACh *tag)
|
|
||||||
{
|
|
||||||
tag->qwc = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace D_CTRL
|
namespace D_CTRL
|
||||||
|
|
|
@ -66,35 +66,31 @@ void COP2_Unknown()
|
||||||
}
|
}
|
||||||
|
|
||||||
//****************************************************************************
|
//****************************************************************************
|
||||||
void _vu0WaitMicro() {
|
|
||||||
int startcycle;
|
__forceinline void _vu0run(bool breakOnMbit) {
|
||||||
|
|
||||||
if ((VU0.VI[REG_VPU_STAT].UL & 0x1) == 0) {
|
if (!(VU0.VI[REG_VPU_STAT].UL & 1)) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
startcycle = VU0.cycle;
|
int startcycle = VU0.cycle;
|
||||||
|
VU0.flags &= ~VUFLAG_MFLAGSET;
|
||||||
|
|
||||||
VU0.flags|= VUFLAG_BREAKONMFLAG;
|
do {
|
||||||
VU0.flags&= ~VUFLAG_MFLAGSET;
|
// knockout kings 2002 loops here with sVU
|
||||||
|
if (breakOnMbit && (VU0.cycle-startcycle > 0x1000)) {
|
||||||
if (!CHECK_MICROVU0) {
|
Console::Notice("VU0 perma-stall, breaking execution...");
|
||||||
do {
|
break; // mVU will never get here (it handles mBit internally)
|
||||||
CpuVU0.ExecuteBlock();
|
}
|
||||||
// knockout kings 2002 loops here
|
CpuVU0.ExecuteBlock();
|
||||||
if( VU0.cycle-startcycle > 0x1000 ) {
|
} while ((VU0.VI[REG_VPU_STAT].UL & 1) // E-bit Termination
|
||||||
Console::Notice("VU0 perma-stall, breaking execution..."); // (email zero if gfx are bad)
|
&& (!breakOnMbit || !(VU0.flags & VUFLAG_MFLAGSET))); // M-bit Break
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while ((VU0.VI[REG_VPU_STAT].UL & 0x1) && (VU0.flags & VUFLAG_MFLAGSET) == 0);
|
|
||||||
}
|
|
||||||
else CpuVU0.ExecuteBlock(); // Note: Need to test Knockout Kings 2002 with mVU!
|
|
||||||
|
|
||||||
//NEW
|
//NEW
|
||||||
cpuRegs.cycle += (VU0.cycle-startcycle)*2;
|
cpuRegs.cycle += (VU0.cycle-startcycle)*2;
|
||||||
VU0.flags&= ~VUFLAG_BREAKONMFLAG;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _vu0WaitMicro() { _vu0run(1); } // Runs VU0 Micro Until E-bit or M-Bit End
|
||||||
|
void _vu0FinishMicro() { _vu0run(0); } // Runs VU0 Micro Until E-Bit End
|
||||||
|
|
||||||
namespace R5900 {
|
namespace R5900 {
|
||||||
namespace Interpreter{
|
namespace Interpreter{
|
||||||
namespace OpcodeImpl
|
namespace OpcodeImpl
|
||||||
|
|
|
@ -434,7 +434,7 @@ void mfifoVIF1transfer(int qwc)
|
||||||
if (qwc > 0)
|
if (qwc > 0)
|
||||||
{
|
{
|
||||||
vifqwc += qwc;
|
vifqwc += qwc;
|
||||||
SPR_LOG("Added %x qw to mfifo, total now %x - Vif CHCR %x Stalled %x done %x", qwc, vifqwc, vif1ch->chcr, vif1.vifstalled, vif1.done);
|
SPR_LOG("Added %x qw to mfifo, total now %x - Vif CHCR %x Stalled %x done %x", qwc, vifqwc, vif1ch->chcr._u32, vif1.vifstalled, vif1.done);
|
||||||
if (vif1.inprogress & 0x10)
|
if (vif1.inprogress & 0x10)
|
||||||
{
|
{
|
||||||
if (vif1ch->madr >= psHu32(DMAC_RBOR) && vif1ch->madr <= (psHu32(DMAC_RBOR) + psHu32(DMAC_RBSR)))
|
if (vif1ch->madr >= psHu32(DMAC_RBOR) && vif1ch->madr <= (psHu32(DMAC_RBOR) + psHu32(DMAC_RBSR)))
|
||||||
|
@ -453,7 +453,7 @@ void mfifoVIF1transfer(int qwc)
|
||||||
{
|
{
|
||||||
ptag = (u32*)dmaGetAddr(vif1ch->tadr);
|
ptag = (u32*)dmaGetAddr(vif1ch->tadr);
|
||||||
|
|
||||||
if (CHCR::TTE(vif1ch))
|
if (vif1ch->chcr.TTE)
|
||||||
{
|
{
|
||||||
if (vif1.stallontag)
|
if (vif1.stallontag)
|
||||||
ret = VIF1transfer(ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset, 1); //Transfer Tag on Stall
|
ret = VIF1transfer(ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset, 1); //Transfer Tag on Stall
|
||||||
|
@ -513,7 +513,7 @@ void mfifoVIF1transfer(int qwc)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((CHCR::TIE(vif1ch)) && (Tag::IRQ(ptag)))
|
if ((vif1ch->chcr.TIE) && (Tag::IRQ(ptag)))
|
||||||
{
|
{
|
||||||
VIF_LOG("dmaIrq Set");
|
VIF_LOG("dmaIrq Set");
|
||||||
vif1.done = true;
|
vif1.done = true;
|
||||||
|
@ -522,7 +522,7 @@ void mfifoVIF1transfer(int qwc)
|
||||||
|
|
||||||
vif1.inprogress |= 1;
|
vif1.inprogress |= 1;
|
||||||
|
|
||||||
SPR_LOG("mfifoVIF1transfer end %x madr %x, tadr %x vifqwc %x", vif1ch->chcr, vif1ch->madr, vif1ch->tadr, vifqwc);
|
SPR_LOG("mfifoVIF1transfer end %x madr %x, tadr %x vifqwc %x", vif1ch->chcr._u32, vif1ch->madr, vif1ch->tadr, vifqwc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vifMFIFOInterrupt()
|
void vifMFIFOInterrupt()
|
||||||
|
@ -533,7 +533,7 @@ void vifMFIFOInterrupt()
|
||||||
|
|
||||||
if ((vif1Regs->stat & VIF1_STAT_VGW))
|
if ((vif1Regs->stat & VIF1_STAT_VGW))
|
||||||
{
|
{
|
||||||
if (CHCR::STR(gif))
|
if (gif->chcr.STR)
|
||||||
{
|
{
|
||||||
CPU_INT(10, 16);
|
CPU_INT(10, 16);
|
||||||
return;
|
return;
|
||||||
|
@ -545,9 +545,9 @@ void vifMFIFOInterrupt()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((CHCR::STR(spr0)) && (spr0->qwc == 0))
|
if ((spr0->chcr.STR) && (spr0->qwc == 0))
|
||||||
{
|
{
|
||||||
CHCR::clearSTR(spr0);
|
spr0->chcr.STR = 0;
|
||||||
hwDmacIrq(DMAC_FROM_SPR);
|
hwDmacIrq(DMAC_FROM_SPR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,7 +559,7 @@ void vifMFIFOInterrupt()
|
||||||
if (vif1Regs->stat & (VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
|
if (vif1Regs->stat & (VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
|
||||||
{
|
{
|
||||||
vif1Regs->stat &= ~VIF1_STAT_FQC; // FQC=0
|
vif1Regs->stat &= ~VIF1_STAT_FQC; // FQC=0
|
||||||
CHCR::clearSTR(vif1ch);
|
vif1ch->chcr.STR = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -606,7 +606,7 @@ void vifMFIFOInterrupt()
|
||||||
|
|
||||||
vif1.done = 1;
|
vif1.done = 1;
|
||||||
g_vifCycles = 0;
|
g_vifCycles = 0;
|
||||||
CHCR::clearSTR(vif1ch);
|
vif1ch->chcr.STR = 0;
|
||||||
hwDmacIrq(DMAC_VIF1);
|
hwDmacIrq(DMAC_VIF1);
|
||||||
VIF_LOG("vif mfifo dma end");
|
VIF_LOG("vif mfifo dma end");
|
||||||
|
|
||||||
|
|
54
pcsx2/Vif.h
54
pcsx2/Vif.h
|
@ -29,32 +29,52 @@ struct vifCycle {
|
||||||
//
|
//
|
||||||
union tVIF_STAT {
|
union tVIF_STAT {
|
||||||
struct {
|
struct {
|
||||||
u32 VPS : 2;
|
u32 VPS : 2; // Vif(0/1) status.
|
||||||
u32 VEW : 1;
|
u32 VEW : 1; // E-bit wait (1 - wait, 0 - don't wait)
|
||||||
u32 VGW : 1;
|
u32 VGW : 1; // Status waiting for the end of gif transfer (Vif1 only)
|
||||||
u32 reserved : 2;
|
u32 reserved : 2;
|
||||||
u32 MRK : 1;
|
u32 MRK : 1; // Mark Detect
|
||||||
u32 DBF : 1;
|
u32 DBF : 1; // Double Buffer Flag
|
||||||
u32 VSS : 1;
|
u32 VSS : 1; // Stopped by STOP
|
||||||
u32 VFS : 1;
|
u32 VFS : 1; // Stopped by ForceBreak
|
||||||
u32 VIS : 1;
|
u32 VIS : 1; // Vif Interrupt Stall
|
||||||
u32 INT : 1;
|
u32 INT : 1; // Intereupt by the i bit.
|
||||||
u32 ER0 : 1;
|
u32 ER0 : 1; // DmaTag Mismatch error.
|
||||||
u32 ER1 : 1;
|
u32 ER1 : 1; // VifCode error
|
||||||
u32 reserved2 : 9;
|
u32 reserved2 : 9;
|
||||||
u32 FDR : 1;
|
u32 FDR : 1; // VIF/FIFO transfer direction. (0 - memory -> Vif, 1 - Vif -> memory)
|
||||||
u32 FQC : 5;
|
u32 FQC : 5; // Amount of data. Up to 8 qwords on Vif0, 16 on Vif1.
|
||||||
|
};
|
||||||
|
u32 _u32;
|
||||||
|
};
|
||||||
|
|
||||||
|
union tVIF_FBRST {
|
||||||
|
struct {
|
||||||
|
u32 RST : 1; // Resets Vif(0/1) when written.
|
||||||
|
u32 FBK : 1; // Causes a Forcebreak to Vif((0/1) when 1 is written. (Stall)
|
||||||
|
u32 STP : 1; // Stops after the end of the Vifcode in progress when written. (Stall)
|
||||||
|
u32 STC : 1; // Cancels the Vif(0/1) stall and clears Vif Stats VSS, VFS, VIS, INT, ER0 & ER1.
|
||||||
|
u32 reserved : 28;
|
||||||
|
};
|
||||||
|
u32 _u32;
|
||||||
|
};
|
||||||
|
|
||||||
|
union tVIF_ERR {
|
||||||
|
struct {
|
||||||
|
u32 MII : 1; // Masks Stat INT.
|
||||||
|
u32 ME0 : 1; // Masks Stat Err0.
|
||||||
|
u32 ME1 : 1; // Masks Stat Err1.
|
||||||
|
u32 reserved : 29;
|
||||||
};
|
};
|
||||||
u32 _u32;
|
u32 _u32;
|
||||||
};
|
};
|
||||||
|
|
||||||
// r0-r3 and c0-c3 would be more managable as arrays.
|
|
||||||
struct VIFregisters {
|
struct VIFregisters {
|
||||||
u32 stat;
|
u32 stat;
|
||||||
u32 pad0[3];
|
u32 pad0[3];
|
||||||
u32 fbrst;
|
u32 fbrst;
|
||||||
u32 pad1[3];
|
u32 pad1[3];
|
||||||
u32 err;
|
tVIF_ERR err;
|
||||||
u32 pad2[3];
|
u32 pad2[3];
|
||||||
u32 mark;
|
u32 mark;
|
||||||
u32 pad3[3];
|
u32 pad3[3];
|
||||||
|
@ -102,7 +122,7 @@ struct VIFregisters {
|
||||||
u32 addr;
|
u32 addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum vif_errors
|
/*enum vif_errors
|
||||||
{
|
{
|
||||||
VIF_ERR_MII = 0x1,
|
VIF_ERR_MII = 0x1,
|
||||||
VIF_ERR_ME0 = 0x2,
|
VIF_ERR_ME0 = 0x2,
|
||||||
|
@ -120,7 +140,7 @@ namespace VIF_ERR
|
||||||
|
|
||||||
// If true, VifCode errors are masked.
|
// If true, VifCode errors are masked.
|
||||||
static __forceinline bool ME1(VIFregisters *tag) { return !!(tag->err & VIF_ERR_ME1); }
|
static __forceinline bool ME1(VIFregisters *tag) { return !!(tag->err & VIF_ERR_ME1); }
|
||||||
}
|
}*/
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
|
|
@ -1222,7 +1222,7 @@ static void Vif0CMDMPGTransfer() // MPG
|
||||||
static void Vif0CMDNull() // invalid opcode
|
static void Vif0CMDNull() // invalid opcode
|
||||||
{
|
{
|
||||||
// if ME1, then force the vif to interrupt
|
// if ME1, then force the vif to interrupt
|
||||||
if (!(VIF_ERR::ME1(vif0Regs))) //Ignore vifcode and tag mismatch error
|
if (!(vif0Regs->err.ME1)) //Ignore vifcode and tag mismatch error
|
||||||
{
|
{
|
||||||
Console::WriteLn("UNKNOWN VifCmd: %x", params vif0.cmd);
|
Console::WriteLn("UNKNOWN VifCmd: %x", params vif0.cmd);
|
||||||
vif0Regs->stat |= VIF0_STAT_ER1;
|
vif0Regs->stat |= VIF0_STAT_ER1;
|
||||||
|
@ -1274,7 +1274,7 @@ int VIF0transfer(u32 *data, int size, int istag)
|
||||||
|
|
||||||
if ((vif0.cmd & 0x7f) > 0x4A)
|
if ((vif0.cmd & 0x7f) > 0x4A)
|
||||||
{
|
{
|
||||||
if (!(VIF_ERR::ME1(vif0Regs))) //Ignore vifcode and tag mismatch error
|
if (!(vif0Regs->err.ME1)) //Ignore vifcode and tag mismatch error
|
||||||
{
|
{
|
||||||
Console::WriteLn("UNKNOWN VifCmd: %x", params vif0.cmd);
|
Console::WriteLn("UNKNOWN VifCmd: %x", params vif0.cmd);
|
||||||
vif0Regs->stat |= VIF0_STAT_ER1;
|
vif0Regs->stat |= VIF0_STAT_ER1;
|
||||||
|
@ -1294,7 +1294,7 @@ int VIF0transfer(u32 *data, int size, int istag)
|
||||||
{
|
{
|
||||||
vif0.cmd &= 0x7f;
|
vif0.cmd &= 0x7f;
|
||||||
|
|
||||||
if (!(VIF_ERR::MII(vif0Regs))) //i bit on vifcode and not masked by VIF0_ERR
|
if (!(vif0Regs->err.MII)) //i bit on vifcode and not masked by VIF0_ERR
|
||||||
{
|
{
|
||||||
VIF_LOG("Interrupt on VIFcmd: %x (INTC_MASK = %x)", vif0.cmd, psHu32(INTC_MASK));
|
VIF_LOG("Interrupt on VIFcmd: %x (INTC_MASK = %x)", vif0.cmd, psHu32(INTC_MASK));
|
||||||
|
|
||||||
|
@ -1385,7 +1385,7 @@ int _chainVIF0()
|
||||||
vif0ptag[1], vif0ptag[0], vif0ch->qwc, id, vif0ch->madr, vif0ch->tadr);
|
vif0ptag[1], vif0ptag[0], vif0ch->qwc, id, vif0ch->madr, vif0ch->tadr);
|
||||||
|
|
||||||
// Transfer dma tag if tte is set
|
// Transfer dma tag if tte is set
|
||||||
if (CHCR::TTE(vif0ch))
|
if (vif0ch->chcr.TTE)
|
||||||
{
|
{
|
||||||
if (vif0.vifstalled)
|
if (vif0.vifstalled)
|
||||||
ret = VIF0transfer(vif0ptag + (2 + vif0.irqoffset), 2 - vif0.irqoffset, 1); //Transfer Tag on stall
|
ret = VIF0transfer(vif0ptag + (2 + vif0.irqoffset), 2 - vif0.irqoffset, 1); //Transfer Tag on stall
|
||||||
|
@ -1403,7 +1403,7 @@ int _chainVIF0()
|
||||||
|
|
||||||
ret = _VIF0chain(); //Transfers the data set by the switch
|
ret = _VIF0chain(); //Transfers the data set by the switch
|
||||||
|
|
||||||
if (CHCR::TIE(vif0ch) && Tag::IRQ(vif0ptag)) //Check TIE bit of CHCR and IRQ bit of tag
|
if (vif0ch->chcr.TIE && Tag::IRQ(vif0ptag)) //Check TIE bit of CHCR and IRQ bit of tag
|
||||||
{
|
{
|
||||||
VIF_LOG("dmaIrq Set\n");
|
VIF_LOG("dmaIrq Set\n");
|
||||||
|
|
||||||
|
@ -1426,7 +1426,7 @@ void vif0Interrupt()
|
||||||
if (vif0Regs->stat & (VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS))
|
if (vif0Regs->stat & (VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS))
|
||||||
{
|
{
|
||||||
vif0Regs->stat &= ~VIF0_STAT_FQC; // FQC=0
|
vif0Regs->stat &= ~VIF0_STAT_FQC; // FQC=0
|
||||||
CHCR::clearSTR(vif0ch);
|
vif0ch->chcr.STR = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1442,9 +1442,9 @@ void vif0Interrupt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CHCR::STR(vif0ch)) Console::WriteLn("Vif0 running when CHCR = %x", params vif0ch->chcr);
|
if (!vif0ch->chcr.STR) Console::WriteLn("Vif0 running when CHCR = %x", params vif0ch->chcr._u32);
|
||||||
|
|
||||||
if ((CHCR::MOD(vif0ch) == CHAIN_MODE) && (!vif0.done) && (!vif0.vifstalled))
|
if ((vif0ch->chcr.MOD == CHAIN_MODE) && (!vif0.done) && (!vif0.vifstalled))
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!(psHu32(DMAC_CTRL) & 0x1))
|
if (!(psHu32(DMAC_CTRL) & 0x1))
|
||||||
|
@ -1465,7 +1465,7 @@ void vif0Interrupt()
|
||||||
if (vif0ch->qwc > 0) Console::WriteLn("VIF0 Ending with QWC left");
|
if (vif0ch->qwc > 0) Console::WriteLn("VIF0 Ending with QWC left");
|
||||||
if (vif0.cmd != 0) Console::WriteLn("vif0.cmd still set %x", params vif0.cmd);
|
if (vif0.cmd != 0) Console::WriteLn("vif0.cmd still set %x", params vif0.cmd);
|
||||||
|
|
||||||
CHCR::clearSTR(vif0ch);
|
vif0ch->chcr.STR = 0;
|
||||||
hwDmacIrq(DMAC_VIF0);
|
hwDmacIrq(DMAC_VIF0);
|
||||||
vif0Regs->stat &= ~VIF0_STAT_FQC; // FQC=0
|
vif0Regs->stat &= ~VIF0_STAT_FQC; // FQC=0
|
||||||
}
|
}
|
||||||
|
@ -1510,14 +1510,14 @@ void dmaVIF0()
|
||||||
{
|
{
|
||||||
VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n"
|
VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n"
|
||||||
" tadr = %lx, asr0 = %lx, asr1 = %lx\n",
|
" tadr = %lx, asr0 = %lx, asr1 = %lx\n",
|
||||||
vif0ch->chcr, vif0ch->madr, vif0ch->qwc,
|
vif0ch->chcr._u32, vif0ch->madr, vif0ch->qwc,
|
||||||
vif0ch->tadr, vif0ch->asr0, vif0ch->asr1);
|
vif0ch->tadr, vif0ch->asr0, vif0ch->asr1);
|
||||||
|
|
||||||
g_vifCycles = 0;
|
g_vifCycles = 0;
|
||||||
|
|
||||||
vif0Regs->stat |= 0x8000000; // FQC=8
|
vif0Regs->stat |= 0x8000000; // FQC=8
|
||||||
|
|
||||||
if (!(vif0ch->chcr & 0x4) || vif0ch->qwc > 0) // Normal Mode
|
if (!(vif0ch->chcr.MOD & 0x1) || vif0ch->qwc > 0) // Normal Mode
|
||||||
{
|
{
|
||||||
if (_VIF0chain() == -2)
|
if (_VIF0chain() == -2)
|
||||||
{
|
{
|
||||||
|
@ -1561,7 +1561,7 @@ void vif0Write32(u32 mem, u32 value)
|
||||||
psHu64(VIF0_FIFO) = 0;
|
psHu64(VIF0_FIFO) = 0;
|
||||||
psHu64(VIF0_FIFO + 8) = 0; // VIF0_FIFO + 8
|
psHu64(VIF0_FIFO + 8) = 0; // VIF0_FIFO + 8
|
||||||
vif0.done = true;
|
vif0.done = true;
|
||||||
vif0Regs->err = 0;
|
vif0Regs->err._u32 = 0;
|
||||||
vif0Regs->stat &= ~(VIF0_STAT_FQC | VIF0_STAT_INT | VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS | VIF0_STAT_VPS); // FQC=0
|
vif0Regs->stat &= ~(VIF0_STAT_FQC | VIF0_STAT_INT | VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS | VIF0_STAT_VPS); // FQC=0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1608,7 +1608,7 @@ void vif0Write32(u32 mem, u32 value)
|
||||||
else
|
else
|
||||||
_VIF0chain();
|
_VIF0chain();
|
||||||
|
|
||||||
CHCR::setSTR(vif0ch);
|
vif0ch->chcr.STR = 1;
|
||||||
CPU_INT(0, g_vifCycles); // Gets the timing right - Flatout
|
CPU_INT(0, g_vifCycles); // Gets the timing right - Flatout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1620,7 +1620,7 @@ void vif0Write32(u32 mem, u32 value)
|
||||||
VIF_LOG("VIF0_ERR write32 0x%8.8x", value);
|
VIF_LOG("VIF0_ERR write32 0x%8.8x", value);
|
||||||
|
|
||||||
/* Set VIF0_ERR with 'value' */
|
/* Set VIF0_ERR with 'value' */
|
||||||
vif0Regs->err = value;
|
vif0Regs->err._u32 = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIF0_R0:
|
case VIF0_R0:
|
||||||
|
@ -1862,7 +1862,7 @@ static int __fastcall Vif1TransDirectHL(u32 *data)
|
||||||
|
|
||||||
if ((vif1.cmd & 0x7f) == 0x51)
|
if ((vif1.cmd & 0x7f) == 0x51)
|
||||||
{
|
{
|
||||||
if (CHCR::STR(gif) && (!vif1Regs->mskpath3 && (Path3progress == IMAGE_MODE))) //PATH3 is in image mode, so wait for end of transfer
|
if (gif->chcr.STR && (!vif1Regs->mskpath3 && (Path3progress == IMAGE_MODE))) //PATH3 is in image mode, so wait for end of transfer
|
||||||
{
|
{
|
||||||
vif1Regs->stat |= VIF1_STAT_VGW;
|
vif1Regs->stat |= VIF1_STAT_VGW;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2055,7 +2055,7 @@ void Vif1MskPath3() // MSKPATH3
|
||||||
}
|
}
|
||||||
static void Vif1CMDMskPath3() // MSKPATH3
|
static void Vif1CMDMskPath3() // MSKPATH3
|
||||||
{
|
{
|
||||||
if (CHCR::STR(vif1ch))
|
if (vif1ch->chcr.STR)
|
||||||
{
|
{
|
||||||
schedulepath3msk = 0x10 | ((vif1Regs->code >> 15) & 0x1);
|
schedulepath3msk = 0x10 | ((vif1Regs->code >> 15) & 0x1);
|
||||||
vif1.vifstalled = true;
|
vif1.vifstalled = true;
|
||||||
|
@ -2083,7 +2083,7 @@ static void Vif1CMDFlush() // FLUSH/E/A
|
||||||
if ((vif1.cmd & 0x7f) == 0x13)
|
if ((vif1.cmd & 0x7f) == 0x13)
|
||||||
{
|
{
|
||||||
// Gif is already transferring so wait for it.
|
// Gif is already transferring so wait for it.
|
||||||
if (((Path3progress != STOPPED_MODE) || !vif1Regs->mskpath3) && CHCR::STR(gif))
|
if (((Path3progress != STOPPED_MODE) || !vif1Regs->mskpath3) && gif->chcr.STR)
|
||||||
{
|
{
|
||||||
vif1Regs->stat |= VIF1_STAT_VGW;
|
vif1Regs->stat |= VIF1_STAT_VGW;
|
||||||
CPU_INT(2, 4);
|
CPU_INT(2, 4);
|
||||||
|
@ -2144,7 +2144,7 @@ static void Vif1CMDNull() // invalid opcode
|
||||||
{
|
{
|
||||||
// if ME1, then force the vif to interrupt
|
// if ME1, then force the vif to interrupt
|
||||||
|
|
||||||
if (!(VIF_ERR::ME1(vif1Regs))) //Ignore vifcode and tag mismatch error
|
if (!(vif1Regs->err.ME1)) //Ignore vifcode and tag mismatch error
|
||||||
{
|
{
|
||||||
Console::WriteLn("UNKNOWN VifCmd: %x\n", params vif1.cmd);
|
Console::WriteLn("UNKNOWN VifCmd: %x\n", params vif1.cmd);
|
||||||
vif1Regs->stat |= VIF1_STAT_ER1;
|
vif1Regs->stat |= VIF1_STAT_ER1;
|
||||||
|
@ -2242,7 +2242,7 @@ int VIF1transfer(u32 *data, int size, int istag)
|
||||||
|
|
||||||
if ((vif1.cmd & 0x7f) > 0x51)
|
if ((vif1.cmd & 0x7f) > 0x51)
|
||||||
{
|
{
|
||||||
if (!(VIF_ERR::ME1(vif1Regs))) //Ignore vifcode and tag mismatch error
|
if (!(vif0Regs->err.ME1)) //Ignore vifcode and tag mismatch error
|
||||||
{
|
{
|
||||||
Console::WriteLn("UNKNOWN VifCmd: %x", params vif1.cmd);
|
Console::WriteLn("UNKNOWN VifCmd: %x", params vif1.cmd);
|
||||||
vif1Regs->stat |= VIF1_STAT_ER1;
|
vif1Regs->stat |= VIF1_STAT_ER1;
|
||||||
|
@ -2260,7 +2260,7 @@ int VIF1transfer(u32 *data, int size, int istag)
|
||||||
{
|
{
|
||||||
vif1.cmd &= 0x7f;
|
vif1.cmd &= 0x7f;
|
||||||
|
|
||||||
if (!(VIF_ERR::MII(vif1Regs))) //i bit on vifcode and not masked by VIF1_ERR
|
if (!(vif1Regs->err.MII)) //i bit on vifcode and not masked by VIF1_ERR
|
||||||
{
|
{
|
||||||
VIF_LOG("Interrupt on VIFcmd: %x (INTC_MASK = %x)", vif1.cmd, psHu32(INTC_MASK));
|
VIF_LOG("Interrupt on VIFcmd: %x (INTC_MASK = %x)", vif1.cmd, psHu32(INTC_MASK));
|
||||||
|
|
||||||
|
@ -2461,7 +2461,7 @@ __forceinline void vif1SetupTransfer()
|
||||||
|
|
||||||
vif1.inprogress = 1;
|
vif1.inprogress = 1;
|
||||||
|
|
||||||
if (CHCR::TTE(vif1ch))
|
if (vif1ch->chcr.TTE)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (vif1.vifstalled)
|
if (vif1.vifstalled)
|
||||||
|
@ -2480,7 +2480,7 @@ __forceinline void vif1SetupTransfer()
|
||||||
vif1.done |= hwDmacSrcChainWithStack(vif1ch, id);
|
vif1.done |= hwDmacSrcChainWithStack(vif1ch, id);
|
||||||
|
|
||||||
//Check TIE bit of CHCR and IRQ bit of tag
|
//Check TIE bit of CHCR and IRQ bit of tag
|
||||||
if ((CHCR::TIE(vif1ch)) && (Tag::IRQ(vif1ptag)))
|
if (vif1ch->chcr.TIE && (Tag::IRQ(vif1ptag)))
|
||||||
{
|
{
|
||||||
VIF_LOG("dmaIrq Set");
|
VIF_LOG("dmaIrq Set");
|
||||||
|
|
||||||
|
@ -2501,7 +2501,7 @@ __forceinline void vif1Interrupt()
|
||||||
|
|
||||||
if((vif1Regs->stat & VIF1_STAT_VGW))
|
if((vif1Regs->stat & VIF1_STAT_VGW))
|
||||||
{
|
{
|
||||||
if (CHCR::STR(gif))
|
if (gif->chcr.STR)
|
||||||
{
|
{
|
||||||
CPU_INT(1, gif->qwc * BIAS);
|
CPU_INT(1, gif->qwc * BIAS);
|
||||||
return;
|
return;
|
||||||
|
@ -2510,7 +2510,7 @@ __forceinline void vif1Interrupt()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(CHCR::STR(vif1ch))) Console::WriteLn("Vif1 running when CHCR == %x", params vif1ch->chcr);
|
if (!(vif1ch->chcr.STR)) Console::WriteLn("Vif1 running when CHCR == %x", params vif1ch->chcr._u32);
|
||||||
|
|
||||||
if (vif1.irq && vif1.tag.size == 0)
|
if (vif1.irq && vif1.tag.size == 0)
|
||||||
{
|
{
|
||||||
|
@ -2522,7 +2522,7 @@ __forceinline void vif1Interrupt()
|
||||||
vif1Regs->stat &= ~VIF1_STAT_FQC; // FQC=0
|
vif1Regs->stat &= ~VIF1_STAT_FQC; // FQC=0
|
||||||
|
|
||||||
// One game doesnt like vif stalling at end, cant remember what. Spiderman isnt keen on it tho
|
// One game doesnt like vif stalling at end, cant remember what. Spiderman isnt keen on it tho
|
||||||
CHCR::clearSTR(vif1ch);
|
vif1ch->chcr.STR = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ((vif1ch->qwc > 0) || (vif1.irqoffset > 0))
|
else if ((vif1ch->qwc > 0) || (vif1.irqoffset > 0))
|
||||||
|
@ -2567,7 +2567,7 @@ __forceinline void vif1Interrupt()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vif1Regs->stat &= ~VIF1_STAT_VPS; //Vif goes idle as the stall happened between commands;
|
vif1Regs->stat &= ~VIF1_STAT_VPS; //Vif goes idle as the stall happened between commands;
|
||||||
CHCR::clearSTR(vif1ch);
|
vif1ch->chcr.STR = 0;
|
||||||
g_vifCycles = 0;
|
g_vifCycles = 0;
|
||||||
hwDmacIrq(DMAC_VIF1);
|
hwDmacIrq(DMAC_VIF1);
|
||||||
|
|
||||||
|
@ -2575,7 +2575,7 @@ __forceinline void vif1Interrupt()
|
||||||
//Games effected by setting, Fatal Frame, KH2, Shox, Crash N Burn, GT3/4 possibly
|
//Games effected by setting, Fatal Frame, KH2, Shox, Crash N Burn, GT3/4 possibly
|
||||||
//Im guessing due to the full gs fifo before the reverse? (Refraction)
|
//Im guessing due to the full gs fifo before the reverse? (Refraction)
|
||||||
//Note also this is only the condition for reverse fifo mode, normal direction clears it as normal
|
//Note also this is only the condition for reverse fifo mode, normal direction clears it as normal
|
||||||
if (!vif1Regs->mskpath3 || (CHCR::DIR(vif1ch))) vif1Regs->stat &= ~0x1F000000; // FQC=0
|
if (!vif1Regs->mskpath3 || vif1ch->chcr.DIR) vif1Regs->stat &= ~0x1F000000; // FQC=0
|
||||||
}
|
}
|
||||||
|
|
||||||
void dmaVIF1()
|
void dmaVIF1()
|
||||||
|
@ -2592,7 +2592,7 @@ void dmaVIF1()
|
||||||
{
|
{
|
||||||
//Console::WriteLn("VIFMFIFO\n");
|
//Console::WriteLn("VIFMFIFO\n");
|
||||||
// Test changed because the Final Fantasy 12 opening somehow has the tag in *Undefined* mode, which is not in the documentation that I saw.
|
// Test changed because the Final Fantasy 12 opening somehow has the tag in *Undefined* mode, which is not in the documentation that I saw.
|
||||||
if (CHCR::MOD(vif1ch) == NORMAL_MODE) Console::WriteLn("MFIFO mode is normal (which isn't normal here)! %x", params vif1ch->chcr);
|
if (vif1ch->chcr.MOD == NORMAL_MODE) Console::WriteLn("MFIFO mode is normal (which isn't normal here)! %x", params vif1ch->chcr);
|
||||||
vifMFIFOInterrupt();
|
vifMFIFOInterrupt();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2604,13 +2604,13 @@ void dmaVIF1()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((CHCR::MOD(vif1ch) == NORMAL_MODE) || vif1ch->qwc > 0) // Normal Mode
|
if ((vif1ch->chcr.MOD == NORMAL_MODE) || vif1ch->qwc > 0) // Normal Mode
|
||||||
{
|
{
|
||||||
|
|
||||||
if ((psHu32(DMAC_CTRL) & 0xC0) == 0x40)
|
if ((psHu32(DMAC_CTRL) & 0xC0) == 0x40)
|
||||||
Console::WriteLn("DMA Stall Control on VIF1 normal");
|
Console::WriteLn("DMA Stall Control on VIF1 normal");
|
||||||
|
|
||||||
if ((CHCR::DIR(vif1ch))) // to Memory
|
if (vif1ch->chcr.DIR) // to Memory
|
||||||
vif1.dmamode = VIF_NORMAL_TO_MEM_MODE;
|
vif1.dmamode = VIF_NORMAL_TO_MEM_MODE;
|
||||||
else
|
else
|
||||||
vif1.dmamode = VIF_NORMAL_FROM_MEM_MODE;
|
vif1.dmamode = VIF_NORMAL_FROM_MEM_MODE;
|
||||||
|
@ -2659,10 +2659,10 @@ void vif1Write32(u32 mem, u32 value)
|
||||||
{
|
{
|
||||||
vif1Regs->mskpath3 = 0;
|
vif1Regs->mskpath3 = 0;
|
||||||
psHu32(GIF_STAT) &= ~GIF_STAT_IMT;
|
psHu32(GIF_STAT) &= ~GIF_STAT_IMT;
|
||||||
if (CHCR::STR(gif)) CPU_INT(2, 4);
|
if (gif->chcr.STR) CPU_INT(2, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
vif1Regs->err = 0;
|
vif1Regs->err._u32 = 0;
|
||||||
vif1.inprogress = 0;
|
vif1.inprogress = 0;
|
||||||
vif1Regs->stat &= ~(VIF1_STAT_FQC | VIF1_STAT_FDR | VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS | VIF1_STAT_VPS); // FQC=0
|
vif1Regs->stat &= ~(VIF1_STAT_FQC | VIF1_STAT_FDR | VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS | VIF1_STAT_VPS); // FQC=0
|
||||||
}
|
}
|
||||||
|
@ -2718,7 +2718,7 @@ void vif1Write32(u32 mem, u32 value)
|
||||||
// Gets the timing right - Flatout
|
// Gets the timing right - Flatout
|
||||||
CPU_INT(1, vif1ch->qwc * BIAS);
|
CPU_INT(1, vif1ch->qwc * BIAS);
|
||||||
}
|
}
|
||||||
CHCR::setSTR(vif1ch);
|
vif1ch->chcr.STR = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2728,7 +2728,7 @@ void vif1Write32(u32 mem, u32 value)
|
||||||
VIF_LOG("VIF1_ERR write32 0x%8.8x", value);
|
VIF_LOG("VIF1_ERR write32 0x%8.8x", value);
|
||||||
|
|
||||||
/* Set VIF1_ERR with 'value' */
|
/* Set VIF1_ERR with 'value' */
|
||||||
vif1Regs->err = value;
|
vif1Regs->err._u32 = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIF1_STAT: // STAT
|
case VIF1_STAT: // STAT
|
||||||
|
|
|
@ -1,140 +1,165 @@
|
||||||
/* Pcsx2 - Pc Ps2 Emulator
|
/* Pcsx2 - Pc Ps2 Emulator
|
||||||
* Copyright (C) 2009 Pcsx2 Team
|
* Copyright (C) 2009 Pcsx2 Team
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// Micro VU - Pass 2 Functions
|
// Micro VU - Pass 2 Functions
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// Flag Allocators
|
// Flag Allocators
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
#define getFlagReg(regX, fInst) { \
|
#define getFlagReg(regX, fInst) { \
|
||||||
switch (fInst) { \
|
switch (fInst) { \
|
||||||
case 0: regX = gprF0; break; \
|
case 0: regX = gprF0; break; \
|
||||||
case 1: regX = gprF1; break; \
|
case 1: regX = gprF1; break; \
|
||||||
case 2: regX = gprF2; break; \
|
case 2: regX = gprF2; break; \
|
||||||
case 3: regX = gprF3; break; \
|
case 3: regX = gprF3; break; \
|
||||||
default: \
|
default: \
|
||||||
Console::Error("microVU Error: fInst = %d", params fInst); \
|
Console::Error("microVU Error: fInst = %d", params fInst); \
|
||||||
regX = gprF0; \
|
regX = gprF0; \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define setBitSFLAG(bitTest, bitSet) { \
|
#define setBitSFLAG(bitTest, bitSet) { \
|
||||||
TEST32ItoR(regT, bitTest); \
|
TEST32ItoR(regT, bitTest); \
|
||||||
pjmp = JZ8(0); \
|
pjmp = JZ8(0); \
|
||||||
OR32ItoR(reg, bitSet); \
|
OR32ItoR(reg, bitSet); \
|
||||||
x86SetJ8(pjmp); \
|
x86SetJ8(pjmp); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define setBitFSEQ(bitX) { \
|
#define setBitFSEQ(bitX) { \
|
||||||
TEST32ItoR(gprT1, bitX); \
|
TEST32ItoR(gprT1, bitX); \
|
||||||
pjmp = JZ8(0); \
|
pjmp = JZ8(0); \
|
||||||
OR32ItoR(gprT1, bitX); \
|
OR32ItoR(gprT1, bitX); \
|
||||||
x86SetJ8(pjmp); \
|
x86SetJ8(pjmp); \
|
||||||
}
|
}
|
||||||
|
|
||||||
microVUt(void) mVUallocSFLAGa(int reg, int fInstance) {
|
microVUt(void) mVUallocSFLAGa(int reg, int fInstance) {
|
||||||
getFlagReg(fInstance, fInstance);
|
getFlagReg(fInstance, fInstance);
|
||||||
MOV32RtoR(reg, fInstance);
|
MOV32RtoR(reg, fInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
microVUt(void) mVUallocSFLAGb(int reg, int fInstance) {
|
microVUt(void) mVUallocSFLAGb(int reg, int fInstance) {
|
||||||
getFlagReg(fInstance, fInstance);
|
getFlagReg(fInstance, fInstance);
|
||||||
MOV32RtoR(fInstance, reg);
|
MOV32RtoR(fInstance, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize Status Flag
|
// Normalize Status Flag
|
||||||
microVUt(void) mVUallocSFLAGc(int reg, int regT, int fInstance) {
|
microVUt(void) mVUallocSFLAGc(int reg, int regT, int fInstance) {
|
||||||
u8 *pjmp;
|
u8 *pjmp;
|
||||||
XOR32RtoR(reg, reg);
|
XOR32RtoR(reg, reg);
|
||||||
mVUallocSFLAGa(regT, fInstance);
|
mVUallocSFLAGa(regT, fInstance);
|
||||||
setBitSFLAG(0x0f00, 0x0001); // Z Bit
|
setBitSFLAG(0x0f00, 0x0001); // Z Bit
|
||||||
setBitSFLAG(0xf000, 0x0002); // S Bit
|
setBitSFLAG(0xf000, 0x0002); // S Bit
|
||||||
setBitSFLAG(0x000f, 0x0040); // ZS Bit
|
setBitSFLAG(0x000f, 0x0040); // ZS Bit
|
||||||
setBitSFLAG(0x00f0, 0x0080); // SS Bit
|
setBitSFLAG(0x00f0, 0x0080); // SS Bit
|
||||||
AND32ItoR(regT, 0xffff0000); // DS/DI/OS/US/D/I/O/U Bits
|
AND32ItoR(regT, 0xffff0000); // DS/DI/OS/US/D/I/O/U Bits
|
||||||
SHR32ItoR(regT, 14);
|
SHR32ItoR(regT, 14);
|
||||||
OR32RtoR(reg, regT);
|
OR32RtoR(reg, regT);
|
||||||
}
|
}
|
||||||
|
|
||||||
microVUt(void) mVUallocMFLAGa(mV, int reg, int fInstance) {
|
// Denormalizes Status Flag
|
||||||
MOVZX32M16toR(reg, (uptr)&mVU->macFlag[fInstance]);
|
microVUt(void) mVUallocSFLAGd(uptr memAddr, bool setAllflags) {
|
||||||
}
|
MOV32MtoR(gprF0, memAddr);
|
||||||
|
MOV32RtoR(gprF1, gprF0);
|
||||||
microVUt(void) mVUallocMFLAGb(mV, int reg, int fInstance) {
|
SHR32ItoR(gprF1, 3);
|
||||||
//AND32ItoR(reg, 0xffff);
|
AND32ItoR(gprF1, 0x18);
|
||||||
MOV32RtoM((uptr)&mVU->macFlag[fInstance], reg);
|
|
||||||
}
|
MOV32RtoR(gprF2, gprF0);
|
||||||
|
SHL32ItoR(gprF2, 11);
|
||||||
microVUt(void) mVUallocCFLAGa(mV, int reg, int fInstance) {
|
AND32ItoR(gprF2, 0x1800);
|
||||||
MOV32MtoR(reg, (uptr)&mVU->clipFlag[fInstance]);
|
OR32RtoR (gprF1, gprF2);
|
||||||
}
|
|
||||||
|
SHL32ItoR(gprF0, 14);
|
||||||
microVUt(void) mVUallocCFLAGb(mV, int reg, int fInstance) {
|
AND32ItoR(gprF0, 0x3cf0000);
|
||||||
MOV32RtoM((uptr)&mVU->clipFlag[fInstance], reg);
|
OR32RtoR (gprF1, gprF0);
|
||||||
}
|
|
||||||
|
if (setAllflags) {
|
||||||
//------------------------------------------------------------------
|
MOV32RtoR(gprF0, gprF1);
|
||||||
// VI Reg Allocators
|
MOV32RtoR(gprF2, gprF1);
|
||||||
//------------------------------------------------------------------
|
MOV32RtoR(gprF3, gprF1);
|
||||||
|
}
|
||||||
microVUt(void) mVUallocVIa(mV, int GPRreg, int _reg_) {
|
}
|
||||||
if (!_reg_) { XOR32RtoR(GPRreg, GPRreg); }
|
|
||||||
else { MOVZX32Rm16toR(GPRreg, gprR, (_reg_ - 9) * 16); }
|
microVUt(void) mVUallocMFLAGa(mV, int reg, int fInstance) {
|
||||||
}
|
MOVZX32M16toR(reg, (uptr)&mVU->macFlag[fInstance]);
|
||||||
|
}
|
||||||
microVUt(void) mVUallocVIb(mV, int GPRreg, int _reg_) {
|
|
||||||
if (mVUlow.backupVI) { // Backs up reg to memory (used when VI is modified b4 a branch)
|
microVUt(void) mVUallocMFLAGb(mV, int reg, int fInstance) {
|
||||||
MOVZX32M16toR(gprR, (uptr)&mVU->regs->VI[_reg_].UL);
|
//AND32ItoR(reg, 0xffff);
|
||||||
MOV32RtoM((uptr)&mVU->VIbackup, gprR);
|
if (fInstance < 4) MOV32RtoM((uptr)&mVU->macFlag[fInstance], reg); // microVU
|
||||||
MOV32ItoR(gprR, Roffset);
|
else MOV32RtoM((uptr)&mVU->regs->VI[REG_MAC_FLAG].UL, reg); // macroVU
|
||||||
}
|
}
|
||||||
if (_reg_ == 0) { return; }
|
|
||||||
else if (_reg_ < 16) { MOV16RtoRm(gprR, GPRreg, (_reg_ - 9) * 16); }
|
microVUt(void) mVUallocCFLAGa(mV, int reg, int fInstance) {
|
||||||
}
|
if (fInstance < 4) MOV32MtoR(reg, (uptr)&mVU->clipFlag[fInstance]); // microVU
|
||||||
|
else MOV32MtoR(reg, (uptr)&mVU->regs->VI[REG_CLIP_FLAG].UL); // macroVU
|
||||||
//------------------------------------------------------------------
|
}
|
||||||
// I/P/Q Reg Allocators
|
|
||||||
//------------------------------------------------------------------
|
microVUt(void) mVUallocCFLAGb(mV, int reg, int fInstance) {
|
||||||
|
if (fInstance < 4) MOV32RtoM((uptr)&mVU->clipFlag[fInstance], reg); // microVU
|
||||||
microVUt(void) getPreg(mV, int reg) {
|
else MOV32RtoM((uptr)&mVU->regs->VI[REG_CLIP_FLAG].UL, reg); // macroVU
|
||||||
mVUunpack_xyzw(reg, xmmPQ, (2 + mVUinfo.readP));
|
}
|
||||||
/*if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT1, 15);*/
|
|
||||||
}
|
//------------------------------------------------------------------
|
||||||
|
// VI Reg Allocators
|
||||||
microVUt(void) getQreg(int reg, int qInstance) {
|
//------------------------------------------------------------------
|
||||||
mVUunpack_xyzw(reg, xmmPQ, qInstance);
|
|
||||||
/*if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2<vuIndex>(reg, xmmT1, 15);*/
|
microVUt(void) mVUallocVIa(mV, int GPRreg, int _reg_) {
|
||||||
}
|
if (!_reg_) { XOR32RtoR(GPRreg, GPRreg); }
|
||||||
|
else { MOVZX32M16toR(GPRreg, (uptr)&mVU->regs->VI[_reg_].UL); }
|
||||||
microVUt(void) writeQreg(int reg, int qInstance) {
|
}
|
||||||
if (qInstance) {
|
|
||||||
if (!x86caps.hasStreamingSIMD4Extensions) {
|
microVUt(void) mVUallocVIb(mV, int GPRreg, int _reg_) {
|
||||||
SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, 0xe1);
|
if (mVUlow.backupVI) { // Backs up reg to memory (used when VI is modified b4 a branch)
|
||||||
SSE_MOVSS_XMM_to_XMM(xmmPQ, reg);
|
MOVZX32M16toR(gprT3, (uptr)&mVU->regs->VI[_reg_].UL);
|
||||||
SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, 0xe1);
|
MOV32RtoM((uptr)&mVU->VIbackup, gprT3);
|
||||||
}
|
}
|
||||||
else SSE4_INSERTPS_XMM_to_XMM(xmmPQ, reg, _MM_MK_INSERTPS_NDX(0, 1, 0));
|
if (_reg_ == 0) { return; }
|
||||||
}
|
else if (_reg_ < 16) { MOV16RtoM((uptr)&mVU->regs->VI[_reg_].UL, GPRreg); }
|
||||||
else SSE_MOVSS_XMM_to_XMM(xmmPQ, reg);
|
}
|
||||||
}
|
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
// I/P/Q Reg Allocators
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
|
microVUt(void) getPreg(mV, int reg) {
|
||||||
|
mVUunpack_xyzw(reg, xmmPQ, (2 + mVUinfo.readP));
|
||||||
|
/*if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT1, 15);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
microVUt(void) getQreg(int reg, int qInstance) {
|
||||||
|
mVUunpack_xyzw(reg, xmmPQ, qInstance);
|
||||||
|
/*if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2<vuIndex>(reg, xmmT1, 15);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
microVUt(void) writeQreg(int reg, int qInstance) {
|
||||||
|
if (qInstance) {
|
||||||
|
if (!x86caps.hasStreamingSIMD4Extensions) {
|
||||||
|
SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, 0xe1);
|
||||||
|
SSE_MOVSS_XMM_to_XMM(xmmPQ, reg);
|
||||||
|
SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, 0xe1);
|
||||||
|
}
|
||||||
|
else SSE4_INSERTPS_XMM_to_XMM(xmmPQ, reg, _MM_MK_INSERTPS_NDX(0, 1, 0));
|
||||||
|
}
|
||||||
|
else SSE_MOVSS_XMM_to_XMM(xmmPQ, reg);
|
||||||
|
}
|
||||||
|
|
|
@ -1,194 +1,199 @@
|
||||||
/* Pcsx2 - Pc Ps2 Emulator
|
/* Pcsx2 - Pc Ps2 Emulator
|
||||||
* Copyright (C) 2009 Pcsx2 Team
|
* Copyright (C) 2009 Pcsx2 Team
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
microVUt(void) mVUincCycles(mV, int x);
|
microVUt(void) mVUincCycles(mV, int x);
|
||||||
microVUr(void*) mVUcompile(microVU* mVU, u32 startPC, uptr pState);
|
microVUr(void*) mVUcompile(microVU* mVU, u32 startPC, uptr pState);
|
||||||
|
|
||||||
#define blockCreate(addr) { if (!mVUblocks[addr]) mVUblocks[addr] = new microBlockManager(); }
|
#define blockCreate(addr) { if (!mVUblocks[addr]) mVUblocks[addr] = new microBlockManager(); }
|
||||||
#define sI ((mVUpBlock->pState.needExactMatch & 1) ? 3 : ((mVUpBlock->pState.flags >> 0) & 3))
|
#define sI ((mVUpBlock->pState.needExactMatch & 1) ? 3 : ((mVUpBlock->pState.flags >> 0) & 3))
|
||||||
#define cI ((mVUpBlock->pState.needExactMatch & 4) ? 3 : ((mVUpBlock->pState.flags >> 2) & 3))
|
#define cI ((mVUpBlock->pState.needExactMatch & 4) ? 3 : ((mVUpBlock->pState.flags >> 2) & 3))
|
||||||
|
|
||||||
microVUt(void) mVUendProgram(mV, microFlagCycles* mFC, int isEbit) {
|
microVUt(void) mVUendProgram(mV, microFlagCycles* mFC, int isEbit) {
|
||||||
|
|
||||||
int fStatus = (isEbit) ? findFlagInst(mFC->xStatus, 0x7fffffff) : sI;
|
int fStatus = (isEbit) ? findFlagInst(mFC->xStatus, 0x7fffffff) : sI;
|
||||||
int fMac = (isEbit) ? findFlagInst(mFC->xMac, 0x7fffffff) : 0;
|
int fMac = (isEbit) ? findFlagInst(mFC->xMac, 0x7fffffff) : 0;
|
||||||
int fClip = (isEbit) ? findFlagInst(mFC->xClip, 0x7fffffff) : cI;
|
int fClip = (isEbit) ? findFlagInst(mFC->xClip, 0x7fffffff) : cI;
|
||||||
int qInst = 0;
|
int qInst = 0;
|
||||||
int pInst = 0;
|
int pInst = 0;
|
||||||
mVU->regAlloc->flushAll();
|
mVU->regAlloc->flushAll();
|
||||||
|
|
||||||
if (isEbit) {
|
if (isEbit) {
|
||||||
mVUprint("mVUcompile ebit");
|
mVUprint("mVUcompile ebit");
|
||||||
memset(&mVUinfo, 0, sizeof(mVUinfo));
|
memset(&mVUinfo, 0, sizeof(mVUinfo));
|
||||||
memset(&mVUregsTemp, 0, sizeof(mVUregsTemp));
|
memset(&mVUregsTemp, 0, sizeof(mVUregsTemp));
|
||||||
mVUincCycles(mVU, 100); // Ensures Valid P/Q instances (And sets all cycle data to 0)
|
mVUincCycles(mVU, 100); // Ensures Valid P/Q instances (And sets all cycle data to 0)
|
||||||
mVUcycles -= 100;
|
mVUcycles -= 100;
|
||||||
qInst = mVU->q;
|
qInst = mVU->q;
|
||||||
pInst = mVU->p;
|
pInst = mVU->p;
|
||||||
if (mVUinfo.doDivFlag) {
|
if (mVUinfo.doDivFlag) {
|
||||||
sFLAG.doFlag = 1;
|
sFLAG.doFlag = 1;
|
||||||
sFLAG.write = fStatus;
|
sFLAG.write = fStatus;
|
||||||
mVUdivSet(mVU);
|
mVUdivSet(mVU);
|
||||||
}
|
}
|
||||||
if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); }
|
if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save P/Q Regs
|
// Save P/Q Regs
|
||||||
if (qInst) { SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, 0xe5); }
|
if (qInst) { SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, 0xe5); }
|
||||||
SSE_MOVSS_XMM_to_M32((uptr)&mVU->regs->VI[REG_Q].UL, xmmPQ);
|
SSE_MOVSS_XMM_to_M32((uptr)&mVU->regs->VI[REG_Q].UL, xmmPQ);
|
||||||
if (isVU1) {
|
if (isVU1) {
|
||||||
SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, pInst ? 3 : 2);
|
SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, pInst ? 3 : 2);
|
||||||
SSE_MOVSS_XMM_to_M32((uptr)&mVU->regs->VI[REG_P].UL, xmmPQ);
|
SSE_MOVSS_XMM_to_M32((uptr)&mVU->regs->VI[REG_P].UL, xmmPQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save Flag Instances
|
// Save Flag Instances
|
||||||
mVUallocSFLAGc(gprT1, gprT2, fStatus);
|
#ifdef CHECK_MACROVU0
|
||||||
MOV32RtoM((uptr)&mVU->regs->VI[REG_STATUS_FLAG].UL, gprT1);
|
getFlagReg(fStatus, fStatus);
|
||||||
mVUallocMFLAGa(mVU, gprT1, fMac);
|
MOV32RtoM((uptr)&mVU->regs->VI[REG_STATUS_FLAG].UL, fStatus);
|
||||||
mVUallocCFLAGa(mVU, gprT2, fClip);
|
#else
|
||||||
MOV32RtoM((uptr)&mVU->regs->VI[REG_MAC_FLAG].UL, gprT1);
|
mVUallocSFLAGc(gprT1, gprT2, fStatus);
|
||||||
MOV32RtoM((uptr)&mVU->regs->VI[REG_CLIP_FLAG].UL, gprT2);
|
MOV32RtoM((uptr)&mVU->regs->VI[REG_STATUS_FLAG].UL, gprT1);
|
||||||
|
#endif
|
||||||
if (isEbit || isVU1) { // Clear 'is busy' Flags
|
mVUallocMFLAGa(mVU, gprT1, fMac);
|
||||||
AND32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag
|
mVUallocCFLAGa(mVU, gprT2, fClip);
|
||||||
AND32ItoM((uptr)&mVU->regs->vifRegs->stat, ~VIF1_STAT_VEW); // Clear VU 'is busy' signal for vif
|
MOV32RtoM((uptr)&mVU->regs->VI[REG_MAC_FLAG].UL, gprT1);
|
||||||
}
|
MOV32RtoM((uptr)&mVU->regs->VI[REG_CLIP_FLAG].UL, gprT2);
|
||||||
|
|
||||||
if (isEbit != 2) { // Save PC, and Jump to Exit Point
|
if (isEbit || isVU1) { // Clear 'is busy' Flags
|
||||||
MOV32ItoM((uptr)&mVU->regs->VI[REG_TPC].UL, xPC);
|
AND32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag
|
||||||
JMP32((uptr)mVU->exitFunct - ((uptr)x86Ptr + 5));
|
AND32ItoM((uptr)&mVU->regs->vifRegs->stat, ~VIF1_STAT_VEW); // Clear VU 'is busy' signal for vif
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (isEbit != 2) { // Save PC, and Jump to Exit Point
|
||||||
// Recompiles Code for Proper Flags and Q/P regs on Block Linkings
|
MOV32ItoM((uptr)&mVU->regs->VI[REG_TPC].UL, xPC);
|
||||||
microVUt(void) mVUsetupBranch(mV, microFlagCycles& mFC) {
|
JMP32((uptr)mVU->exitFunct - ((uptr)x86Ptr + 5));
|
||||||
|
}
|
||||||
mVU->regAlloc->flushAll(); // Flush Allocated Regs
|
}
|
||||||
mVUsetupFlags(mVU, mFC); // Shuffle Flag Instances
|
|
||||||
|
// Recompiles Code for Proper Flags and Q/P regs on Block Linkings
|
||||||
// Shuffle P/Q regs since every block starts at instance #0
|
microVUt(void) mVUsetupBranch(mV, microFlagCycles& mFC) {
|
||||||
if (mVU->p || mVU->q) { SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, shufflePQ); }
|
|
||||||
}
|
mVU->regAlloc->flushAll(); // Flush Allocated Regs
|
||||||
|
mVUsetupFlags(mVU, mFC); // Shuffle Flag Instances
|
||||||
void normBranchCompile(microVU* mVU, u32 branchPC) {
|
|
||||||
using namespace x86Emitter;
|
// Shuffle P/Q regs since every block starts at instance #0
|
||||||
microBlock* pBlock;
|
if (mVU->p || mVU->q) { SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, shufflePQ); }
|
||||||
blockCreate(branchPC/8);
|
}
|
||||||
pBlock = mVUblocks[branchPC/8]->search((microRegInfo*)&mVUregs);
|
|
||||||
if (pBlock) { xJMP(pBlock->x86ptrStart); }
|
void normBranchCompile(microVU* mVU, u32 branchPC) {
|
||||||
else { mVUcompile(mVU, branchPC, (uptr)&mVUregs); }
|
using namespace x86Emitter;
|
||||||
}
|
microBlock* pBlock;
|
||||||
|
blockCreate(branchPC/8);
|
||||||
void normJumpCompile(mV, microFlagCycles& mFC, bool isEvilJump) {
|
pBlock = mVUblocks[branchPC/8]->search((microRegInfo*)&mVUregs);
|
||||||
using namespace x86Emitter;
|
if (pBlock) { xJMP(pBlock->x86ptrStart); }
|
||||||
memcpy_fast(&mVUpBlock->pStateEnd, &mVUregs, sizeof(microRegInfo));
|
else { mVUcompile(mVU, branchPC, (uptr)&mVUregs); }
|
||||||
mVUsetupBranch(mVU, mFC);
|
}
|
||||||
mVUbackupRegs(mVU);
|
|
||||||
|
void normJumpCompile(mV, microFlagCycles& mFC, bool isEvilJump) {
|
||||||
if (isEvilJump) MOV32MtoR(gprT2, (uptr)&mVU->evilBranch);
|
using namespace x86Emitter;
|
||||||
else MOV32MtoR(gprT2, (uptr)&mVU->branch);
|
memcpy_fast(&mVUpBlock->pStateEnd, &mVUregs, sizeof(microRegInfo));
|
||||||
MOV32ItoR(gprR, (u32)&mVUpBlock->pStateEnd);
|
mVUsetupBranch(mVU, mFC);
|
||||||
|
mVUbackupRegs(mVU);
|
||||||
if (!mVU->index) xCALL(mVUcompileJIT<0>); //(u32 startPC, uptr pState)
|
|
||||||
else xCALL(mVUcompileJIT<1>);
|
if (isEvilJump) MOV32MtoR(gprT2, (uptr)&mVU->evilBranch);
|
||||||
|
else MOV32MtoR(gprT2, (uptr)&mVU->branch);
|
||||||
mVUrestoreRegs(mVU);
|
MOV32ItoR(gprT3, (u32)&mVUpBlock->pStateEnd);
|
||||||
JMPR(gprT1); // Jump to rec-code address
|
|
||||||
}
|
if (!mVU->index) xCALL(mVUcompileJIT<0>); //(u32 startPC, uptr pState)
|
||||||
|
else xCALL(mVUcompileJIT<1>);
|
||||||
void normBranch(mV, microFlagCycles& mFC) {
|
|
||||||
|
mVUrestoreRegs(mVU);
|
||||||
// E-bit Branch
|
JMPR(gprT1); // Jump to rec-code address
|
||||||
if (mVUup.eBit) { iPC = branchAddr/4; mVUendProgram(mVU, &mFC, 1); return; }
|
}
|
||||||
|
|
||||||
// Normal Branch
|
void normBranch(mV, microFlagCycles& mFC) {
|
||||||
mVUsetupBranch(mVU, mFC);
|
|
||||||
normBranchCompile(mVU, branchAddr);
|
// E-bit Branch
|
||||||
}
|
if (mVUup.eBit) { iPC = branchAddr/4; mVUendProgram(mVU, &mFC, 1); return; }
|
||||||
|
|
||||||
void condBranch(mV, microFlagCycles& mFC, int JMPcc) {
|
// Normal Branch
|
||||||
using namespace x86Emitter;
|
mVUsetupBranch(mVU, mFC);
|
||||||
mVUsetupBranch(mVU, mFC);
|
normBranchCompile(mVU, branchAddr);
|
||||||
xCMP(ptr16[&mVU->branch], 0);
|
}
|
||||||
incPC(3);
|
|
||||||
if (mVUup.eBit) { // Conditional Branch With E-Bit Set
|
void condBranch(mV, microFlagCycles& mFC, int JMPcc) {
|
||||||
mVUendProgram(mVU, &mFC, 2);
|
using namespace x86Emitter;
|
||||||
xForwardJump8 eJMP((JccComparisonType)JMPcc);
|
mVUsetupBranch(mVU, mFC);
|
||||||
incPC(1); // Set PC to First instruction of Non-Taken Side
|
xCMP(ptr16[&mVU->branch], 0);
|
||||||
xMOV(ptr32[&mVU->regs->VI[REG_TPC].UL], xPC);
|
incPC(3);
|
||||||
xJMP(mVU->exitFunct);
|
if (mVUup.eBit) { // Conditional Branch With E-Bit Set
|
||||||
eJMP.SetTarget();
|
mVUendProgram(mVU, &mFC, 2);
|
||||||
incPC(-4); // Go Back to Branch Opcode to get branchAddr
|
xForwardJump8 eJMP((JccComparisonType)JMPcc);
|
||||||
iPC = branchAddr/4;
|
incPC(1); // Set PC to First instruction of Non-Taken Side
|
||||||
xMOV(ptr32[&mVU->regs->VI[REG_TPC].UL], xPC);
|
xMOV(ptr32[&mVU->regs->VI[REG_TPC].UL], xPC);
|
||||||
xJMP(mVU->exitFunct);
|
xJMP(mVU->exitFunct);
|
||||||
return;
|
eJMP.SetTarget();
|
||||||
}
|
incPC(-4); // Go Back to Branch Opcode to get branchAddr
|
||||||
else { // Normal Conditional Branch
|
iPC = branchAddr/4;
|
||||||
microBlock* bBlock;
|
xMOV(ptr32[&mVU->regs->VI[REG_TPC].UL], xPC);
|
||||||
incPC2(1); // Check if Branch Non-Taken Side has already been recompiled
|
xJMP(mVU->exitFunct);
|
||||||
blockCreate(iPC/2);
|
return;
|
||||||
bBlock = mVUblocks[iPC/2]->search((microRegInfo*)&mVUregs);
|
}
|
||||||
incPC2(-1);
|
else { // Normal Conditional Branch
|
||||||
if (bBlock) { // Branch non-taken has already been compiled
|
microBlock* bBlock;
|
||||||
xJcc(xInvertCond((JccComparisonType)JMPcc), bBlock->x86ptrStart);
|
incPC2(1); // Check if Branch Non-Taken Side has already been recompiled
|
||||||
incPC(-3); // Go back to branch opcode (to get branch imm addr)
|
blockCreate(iPC/2);
|
||||||
normBranchCompile(mVU, branchAddr);
|
bBlock = mVUblocks[iPC/2]->search((microRegInfo*)&mVUregs);
|
||||||
}
|
incPC2(-1);
|
||||||
else {
|
if (bBlock) { // Branch non-taken has already been compiled
|
||||||
s32* ajmp = xJcc32((JccComparisonType)JMPcc);
|
xJcc(xInvertCond((JccComparisonType)JMPcc), bBlock->x86ptrStart);
|
||||||
u32 bPC = iPC; // mVUcompile can modify iPC, mVUpBlock, and mVUregs so back them up
|
incPC(-3); // Go back to branch opcode (to get branch imm addr)
|
||||||
microBlock* pBlock = mVUpBlock;
|
normBranchCompile(mVU, branchAddr);
|
||||||
memcpy_fast(&pBlock->pStateEnd, &mVUregs, sizeof(microRegInfo));
|
}
|
||||||
|
else {
|
||||||
incPC2(1); // Get PC for branch not-taken
|
s32* ajmp = xJcc32((JccComparisonType)JMPcc);
|
||||||
mVUcompile(mVU, xPC, (uptr)&mVUregs);
|
u32 bPC = iPC; // mVUcompile can modify iPC, mVUpBlock, and mVUregs so back them up
|
||||||
|
microBlock* pBlock = mVUpBlock;
|
||||||
iPC = bPC;
|
memcpy_fast(&pBlock->pStateEnd, &mVUregs, sizeof(microRegInfo));
|
||||||
incPC(-3); // Go back to branch opcode (to get branch imm addr)
|
|
||||||
uptr jumpAddr = (uptr)mVUblockFetch(mVU, branchAddr, (uptr)&pBlock->pStateEnd);
|
incPC2(1); // Get PC for branch not-taken
|
||||||
*ajmp = (jumpAddr - ((uptr)ajmp + 4));
|
mVUcompile(mVU, xPC, (uptr)&mVUregs);
|
||||||
}
|
|
||||||
}
|
iPC = bPC;
|
||||||
}
|
incPC(-3); // Go back to branch opcode (to get branch imm addr)
|
||||||
|
uptr jumpAddr = (uptr)mVUblockFetch(mVU, branchAddr, (uptr)&pBlock->pStateEnd);
|
||||||
void normJump(mV, microFlagCycles& mFC) {
|
*ajmp = (jumpAddr - ((uptr)ajmp + 4));
|
||||||
using namespace x86Emitter;
|
}
|
||||||
|
}
|
||||||
if (mVUlow.constJump.isValid) { // Jump Address is Constant
|
}
|
||||||
if (mVUup.eBit) { // E-bit Jump
|
|
||||||
iPC = (mVUlow.constJump.regValue*2)&(mVU->progSize-1);
|
void normJump(mV, microFlagCycles& mFC) {
|
||||||
mVUendProgram(mVU, &mFC, 1);
|
using namespace x86Emitter;
|
||||||
return;
|
|
||||||
}
|
if (mVUlow.constJump.isValid) { // Jump Address is Constant
|
||||||
int jumpAddr = (mVUlow.constJump.regValue*8)&(mVU->microMemSize-8);
|
if (mVUup.eBit) { // E-bit Jump
|
||||||
mVUsetupBranch(mVU, mFC);
|
iPC = (mVUlow.constJump.regValue*2)&(mVU->progSize-1);
|
||||||
normBranchCompile(mVU, jumpAddr);
|
mVUendProgram(mVU, &mFC, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
int jumpAddr = (mVUlow.constJump.regValue*8)&(mVU->microMemSize-8);
|
||||||
if (mVUup.eBit) { // E-bit Jump
|
mVUsetupBranch(mVU, mFC);
|
||||||
mVUendProgram(mVU, &mFC, 2);
|
normBranchCompile(mVU, jumpAddr);
|
||||||
MOV32MtoR(gprT1, (uptr)&mVU->branch);
|
return;
|
||||||
MOV32RtoM((uptr)&mVU->regs->VI[REG_TPC].UL, gprT1);
|
}
|
||||||
xJMP(mVU->exitFunct);
|
|
||||||
}
|
if (mVUup.eBit) { // E-bit Jump
|
||||||
else normJumpCompile(mVU, mFC, 0);
|
mVUendProgram(mVU, &mFC, 2);
|
||||||
}
|
MOV32MtoR(gprT1, (uptr)&mVU->branch);
|
||||||
|
MOV32RtoM((uptr)&mVU->regs->VI[REG_TPC].UL, gprT1);
|
||||||
|
xJMP(mVU->exitFunct);
|
||||||
|
}
|
||||||
|
else normJumpCompile(mVU, mFC, 0);
|
||||||
|
}
|
||||||
|
|
|
@ -1,434 +1,433 @@
|
||||||
/* Pcsx2 - Pc Ps2 Emulator
|
/* Pcsx2 - Pc Ps2 Emulator
|
||||||
* Copyright (C) 2009 Pcsx2 Team
|
* Copyright (C) 2009 Pcsx2 Team
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// Helper Macros
|
// Helper Macros
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
#define calcCycles(reg, x) { reg = ((reg > x) ? (reg - x) : 0); }
|
#define calcCycles(reg, x) { reg = ((reg > x) ? (reg - x) : 0); }
|
||||||
#define optimizeReg(rState) { rState = (rState==1) ? 0 : rState; }
|
#define optimizeReg(rState) { rState = (rState==1) ? 0 : rState; }
|
||||||
#define tCycles(dest, src) { dest = aMax(dest, src); }
|
#define tCycles(dest, src) { dest = aMax(dest, src); }
|
||||||
#define incP() { mVU->p = (mVU->p+1) & 1; }
|
#define incP() { mVU->p = (mVU->p+1) & 1; }
|
||||||
#define incQ() { mVU->q = (mVU->q+1) & 1; }
|
#define incQ() { mVU->q = (mVU->q+1) & 1; }
|
||||||
#define doUpperOp() { mVUopU(mVU, 1); mVUdivSet(mVU); }
|
#define doUpperOp() { mVUopU(mVU, 1); mVUdivSet(mVU); }
|
||||||
#define doLowerOp() { incPC(-1); mVUopL(mVU, 1); incPC(1); }
|
#define doLowerOp() { incPC(-1); mVUopL(mVU, 1); incPC(1); }
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// Helper Functions
|
// Helper Functions
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
// Used by mVUsetupRange
|
// Used by mVUsetupRange
|
||||||
microVUt(void) mVUcheckIsSame(mV) {
|
microVUt(void) mVUcheckIsSame(mV) {
|
||||||
|
|
||||||
if (mVU->prog.isSame == -1) {
|
if (mVU->prog.isSame == -1) {
|
||||||
mVU->prog.isSame = !memcmp_mmx((u8*)mVUcurProg.data, mVU->regs->Micro, mVU->microMemSize);
|
mVU->prog.isSame = !memcmp_mmx((u8*)mVUcurProg.data, mVU->regs->Micro, mVU->microMemSize);
|
||||||
}
|
}
|
||||||
if (mVU->prog.isSame == 0) {
|
if (mVU->prog.isSame == 0) {
|
||||||
if (!isVU1) mVUcacheProg<0>(mVU->prog.cur);
|
if (!isVU1) mVUcacheProg<0>(mVU->prog.cur);
|
||||||
else mVUcacheProg<1>(mVU->prog.cur);
|
else mVUcacheProg<1>(mVU->prog.cur);
|
||||||
mVU->prog.isSame = 1;
|
mVU->prog.isSame = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets up microProgram PC ranges based on whats been recompiled
|
// Sets up microProgram PC ranges based on whats been recompiled
|
||||||
microVUt(void) mVUsetupRange(mV, s32 pc, bool isStartPC) {
|
microVUt(void) mVUsetupRange(mV, s32 pc, bool isStartPC) {
|
||||||
|
|
||||||
if (isStartPC || !(mVUrange[1] == -1)) {
|
if (isStartPC || !(mVUrange[1] == -1)) {
|
||||||
for (int i = 0; i <= mVUcurProg.ranges.total; i++) {
|
for (int i = 0; i <= mVUcurProg.ranges.total; i++) {
|
||||||
if ((pc >= mVUcurProg.ranges.range[i][0])
|
if ((pc >= mVUcurProg.ranges.range[i][0])
|
||||||
&& (pc <= mVUcurProg.ranges.range[i][1])) { return; }
|
&& (pc <= mVUcurProg.ranges.range[i][1])) { return; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mVUcheckIsSame(mVU);
|
mVUcheckIsSame(mVU);
|
||||||
|
|
||||||
if (isStartPC) {
|
if (isStartPC) {
|
||||||
if (mVUcurProg.ranges.total < mVUcurProg.ranges.max) {
|
if (mVUcurProg.ranges.total < mVUcurProg.ranges.max) {
|
||||||
mVUcurProg.ranges.total++;
|
mVUcurProg.ranges.total++;
|
||||||
mVUrange[0] = pc;
|
mVUrange[0] = pc;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mVUcurProg.ranges.total = 0;
|
mVUcurProg.ranges.total = 0;
|
||||||
mVUrange[0] = 0;
|
mVUrange[0] = 0;
|
||||||
mVUrange[1] = mVU->microMemSize - 8;
|
mVUrange[1] = mVU->microMemSize - 8;
|
||||||
DevCon::Status("microVU%d: Prog Range List Full", params mVU->index);
|
DevCon::Status("microVU%d: Prog Range List Full", params mVU->index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (mVUrange[0] <= pc) {
|
if (mVUrange[0] <= pc) {
|
||||||
mVUrange[1] = pc;
|
mVUrange[1] = pc;
|
||||||
bool mergedRange = 0;
|
bool mergedRange = 0;
|
||||||
for (int i = 0; i <= (mVUcurProg.ranges.total-1); i++) {
|
for (int i = 0; i <= (mVUcurProg.ranges.total-1); i++) {
|
||||||
int rStart = (mVUrange[0] < 8) ? 0 : (mVUrange[0] - 8);
|
int rStart = (mVUrange[0] < 8) ? 0 : (mVUrange[0] - 8);
|
||||||
int rEnd = pc;
|
int rEnd = pc;
|
||||||
if((mVUcurProg.ranges.range[i][1] >= rStart)
|
if((mVUcurProg.ranges.range[i][1] >= rStart)
|
||||||
&& (mVUcurProg.ranges.range[i][1] <= rEnd)){
|
&& (mVUcurProg.ranges.range[i][1] <= rEnd)){
|
||||||
mVUcurProg.ranges.range[i][1] = pc;
|
mVUcurProg.ranges.range[i][1] = pc;
|
||||||
mergedRange = 1;
|
mergedRange = 1;
|
||||||
//DevCon::Status("microVU%d: Prog Range Merging", params mVU->index);
|
//DevCon::Status("microVU%d: Prog Range Merging", params mVU->index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mergedRange) {
|
if (mergedRange) {
|
||||||
mVUrange[0] = -1;
|
mVUrange[0] = -1;
|
||||||
mVUrange[1] = -1;
|
mVUrange[1] = -1;
|
||||||
mVUcurProg.ranges.total--;
|
mVUcurProg.ranges.total--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DevCon::Status("microVU%d: Prog Range Wrap [%04x] [%d]", params mVU->index, mVUrange[0], mVUrange[1]);
|
DevCon::Status("microVU%d: Prog Range Wrap [%04x] [%d]", params mVU->index, mVUrange[0], mVUrange[1]);
|
||||||
mVUrange[1] = mVU->microMemSize - 8;
|
mVUrange[1] = mVU->microMemSize - 8;
|
||||||
if (mVUcurProg.ranges.total < mVUcurProg.ranges.max) {
|
if (mVUcurProg.ranges.total < mVUcurProg.ranges.max) {
|
||||||
mVUcurProg.ranges.total++;
|
mVUcurProg.ranges.total++;
|
||||||
mVUrange[0] = 0;
|
mVUrange[0] = 0;
|
||||||
mVUrange[1] = pc;
|
mVUrange[1] = pc;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mVUcurProg.ranges.total = 0;
|
mVUcurProg.ranges.total = 0;
|
||||||
mVUrange[0] = 0;
|
mVUrange[0] = 0;
|
||||||
mVUrange[1] = mVU->microMemSize - 8;
|
mVUrange[1] = mVU->microMemSize - 8;
|
||||||
DevCon::Status("microVU%d: Prog Range List Full", params mVU->index);
|
DevCon::Status("microVU%d: Prog Range List Full", params mVU->index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
microVUt(void) startLoop(mV) {
|
microVUt(void) startLoop(mV) {
|
||||||
if (curI & _Mbit_) { Console::Status("microVU%d: M-bit set!", params getIndex); }
|
if (curI & _Mbit_) { Console::Status("microVU%d: M-bit set!", params getIndex); }
|
||||||
if (curI & _Dbit_) { DevCon::Status ("microVU%d: D-bit set!", params getIndex); }
|
if (curI & _Dbit_) { DevCon::Status ("microVU%d: D-bit set!", params getIndex); }
|
||||||
if (curI & _Tbit_) { DevCon::Status ("microVU%d: T-bit set!", params getIndex); }
|
if (curI & _Tbit_) { DevCon::Status ("microVU%d: T-bit set!", params getIndex); }
|
||||||
memset(&mVUinfo, 0, sizeof(mVUinfo));
|
memset(&mVUinfo, 0, sizeof(mVUinfo));
|
||||||
memset(&mVUregsTemp, 0, sizeof(mVUregsTemp));
|
memset(&mVUregsTemp, 0, sizeof(mVUregsTemp));
|
||||||
}
|
}
|
||||||
|
|
||||||
microVUt(void) doIbit(mV) {
|
microVUt(void) doIbit(mV) {
|
||||||
if (mVUup.iBit) {
|
if (mVUup.iBit) {
|
||||||
incPC(-1);
|
incPC(-1);
|
||||||
u32 tempI;
|
u32 tempI;
|
||||||
mVU->regAlloc->clearRegVF(33);
|
mVU->regAlloc->clearRegVF(33);
|
||||||
|
|
||||||
if (CHECK_VU_OVERFLOW && ((curI & 0x7fffffff) >= 0x7f800000)) {
|
if (CHECK_VU_OVERFLOW && ((curI & 0x7fffffff) >= 0x7f800000)) {
|
||||||
Console::Status("microVU%d: Clamping I Reg", params mVU->index);
|
Console::Status("microVU%d: Clamping I Reg", params mVU->index);
|
||||||
tempI = (0x80000000 & curI) | 0x7f7fffff; // Clamp I Reg
|
tempI = (0x80000000 & curI) | 0x7f7fffff; // Clamp I Reg
|
||||||
}
|
}
|
||||||
else tempI = curI;
|
else tempI = curI;
|
||||||
|
|
||||||
MOV32ItoM((uptr)&mVU->regs->VI[REG_I].UL, tempI);
|
MOV32ItoM((uptr)&mVU->regs->VI[REG_I].UL, tempI);
|
||||||
incPC(1);
|
incPC(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
microVUt(void) doSwapOp(mV) {
|
microVUt(void) doSwapOp(mV) {
|
||||||
if (mVUinfo.backupVF && !mVUlow.noWriteVF) {
|
if (mVUinfo.backupVF && !mVUlow.noWriteVF) {
|
||||||
DevCon::Status("microVU%d: Backing Up VF Reg [%04x]", params getIndex, xPC);
|
DevCon::Status("microVU%d: Backing Up VF Reg [%04x]", params getIndex, xPC);
|
||||||
int t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg);
|
int t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg);
|
||||||
int t2 = mVU->regAlloc->allocReg();
|
int t2 = mVU->regAlloc->allocReg();
|
||||||
SSE_MOVAPS_XMM_to_XMM(t2, t1);
|
SSE_MOVAPS_XMM_to_XMM(t2, t1);
|
||||||
mVU->regAlloc->clearNeeded(t1);
|
mVU->regAlloc->clearNeeded(t1);
|
||||||
mVUopL(mVU, 1);
|
mVUopL(mVU, 1);
|
||||||
t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg, mVUlow.VF_write.reg, 0xf, 0);
|
t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg, mVUlow.VF_write.reg, 0xf, 0);
|
||||||
SSE_XORPS_XMM_to_XMM(t2, t1);
|
SSE_XORPS_XMM_to_XMM(t2, t1);
|
||||||
SSE_XORPS_XMM_to_XMM(t1, t2);
|
SSE_XORPS_XMM_to_XMM(t1, t2);
|
||||||
SSE_XORPS_XMM_to_XMM(t2, t1);
|
SSE_XORPS_XMM_to_XMM(t2, t1);
|
||||||
mVU->regAlloc->clearNeeded(t1);
|
mVU->regAlloc->clearNeeded(t1);
|
||||||
incPC(1);
|
incPC(1);
|
||||||
doUpperOp();
|
doUpperOp();
|
||||||
t1 = mVU->regAlloc->allocReg(-1, mVUlow.VF_write.reg, 0xf);
|
t1 = mVU->regAlloc->allocReg(-1, mVUlow.VF_write.reg, 0xf);
|
||||||
SSE_MOVAPS_XMM_to_XMM(t1, t2);
|
SSE_MOVAPS_XMM_to_XMM(t1, t2);
|
||||||
mVU->regAlloc->clearNeeded(t1);
|
mVU->regAlloc->clearNeeded(t1);
|
||||||
mVU->regAlloc->clearNeeded(t2);
|
mVU->regAlloc->clearNeeded(t2);
|
||||||
}
|
}
|
||||||
else { mVUopL(mVU, 1); incPC(1); doUpperOp(); }
|
else { mVUopL(mVU, 1); incPC(1); doUpperOp(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
microVUt(void) branchWarning(mV) {
|
microVUt(void) branchWarning(mV) {
|
||||||
incPC(-2);
|
incPC(-2);
|
||||||
if (mVUup.eBit && mVUbranch) {
|
if (mVUup.eBit && mVUbranch) {
|
||||||
incPC(2);
|
incPC(2);
|
||||||
Console::Error("microVU%d Warning: Branch in E-bit delay slot! [%04x]", params mVU->index, xPC);
|
Console::Error("microVU%d Warning: Branch in E-bit delay slot! [%04x]", params mVU->index, xPC);
|
||||||
mVUlow.isNOP = 1;
|
mVUlow.isNOP = 1;
|
||||||
}
|
}
|
||||||
else incPC(2);
|
else incPC(2);
|
||||||
if (mVUinfo.isBdelay) { // Check if VI Reg Written to on Branch Delay Slot Instruction
|
if (mVUinfo.isBdelay) { // Check if VI Reg Written to on Branch Delay Slot Instruction
|
||||||
if (mVUlow.VI_write.reg && mVUlow.VI_write.used && !mVUlow.readFlags) {
|
if (mVUlow.VI_write.reg && mVUlow.VI_write.used && !mVUlow.readFlags) {
|
||||||
mVUlow.backupVI = 1;
|
mVUlow.backupVI = 1;
|
||||||
mVUregs.viBackUp = mVUlow.VI_write.reg;
|
mVUregs.viBackUp = mVUlow.VI_write.reg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
microVUt(void) eBitPass1(mV, int& branch) {
|
microVUt(void) eBitPass1(mV, int& branch) {
|
||||||
if (mVUregs.blockType != 1) {
|
if (mVUregs.blockType != 1) {
|
||||||
branch = 1;
|
branch = 1;
|
||||||
mVUup.eBit = 1;
|
mVUup.eBit = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
microVUt(void) eBitWarning(mV) {
|
microVUt(void) eBitWarning(mV) {
|
||||||
if (mVUpBlock->pState.blockType == 1) Console::Error("microVU%d Warning: Branch, E-bit, Branch! [%04x]", params mVU->index, xPC);
|
if (mVUpBlock->pState.blockType == 1) Console::Error("microVU%d Warning: Branch, E-bit, Branch! [%04x]", params mVU->index, xPC);
|
||||||
if (mVUpBlock->pState.blockType == 2) Console::Error("microVU%d Warning: Branch, Branch, Branch! [%04x]", params mVU->index, xPC);
|
if (mVUpBlock->pState.blockType == 2) Console::Error("microVU%d Warning: Branch, Branch, Branch! [%04x]", params mVU->index, xPC);
|
||||||
incPC(2);
|
incPC(2);
|
||||||
if (curI & _Ebit_) {
|
if (curI & _Ebit_) {
|
||||||
DevCon::Status("microVU%d: E-bit in Branch delay slot! [%04x]", params mVU->index, xPC);
|
DevCon::Status("microVU%d: E-bit in Branch delay slot! [%04x]", params mVU->index, xPC);
|
||||||
mVUregs.blockType = 1;
|
mVUregs.blockType = 1;
|
||||||
}
|
}
|
||||||
incPC(-2);
|
incPC(-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optimizes the End Pipeline State Removing Unnecessary Info
|
// Optimizes the End Pipeline State Removing Unnecessary Info
|
||||||
microVUt(void) mVUoptimizePipeState(mV) {
|
microVUt(void) mVUoptimizePipeState(mV) {
|
||||||
for (int i = 0; i < 32; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
optimizeReg(mVUregs.VF[i].x);
|
optimizeReg(mVUregs.VF[i].x);
|
||||||
optimizeReg(mVUregs.VF[i].y);
|
optimizeReg(mVUregs.VF[i].y);
|
||||||
optimizeReg(mVUregs.VF[i].z);
|
optimizeReg(mVUregs.VF[i].z);
|
||||||
optimizeReg(mVUregs.VF[i].w);
|
optimizeReg(mVUregs.VF[i].w);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
optimizeReg(mVUregs.VI[i]);
|
optimizeReg(mVUregs.VI[i]);
|
||||||
}
|
}
|
||||||
if (mVUregs.q) { optimizeReg(mVUregs.q); if (!mVUregs.q) { incQ(); } }
|
if (mVUregs.q) { optimizeReg(mVUregs.q); if (!mVUregs.q) { incQ(); } }
|
||||||
if (mVUregs.p) { optimizeReg(mVUregs.p); if (!mVUregs.p) { incP(); } }
|
if (mVUregs.p) { optimizeReg(mVUregs.p); if (!mVUregs.p) { incP(); } }
|
||||||
mVUregs.r = 0; // There are no stalls on the R-reg, so its Safe to discard info
|
mVUregs.r = 0; // There are no stalls on the R-reg, so its Safe to discard info
|
||||||
}
|
}
|
||||||
|
|
||||||
microVUt(void) mVUincCycles(mV, int x) {
|
microVUt(void) mVUincCycles(mV, int x) {
|
||||||
mVUcycles += x;
|
mVUcycles += x;
|
||||||
for (int z = 31; z > 0; z--) {
|
for (int z = 31; z > 0; z--) {
|
||||||
calcCycles(mVUregs.VF[z].x, x);
|
calcCycles(mVUregs.VF[z].x, x);
|
||||||
calcCycles(mVUregs.VF[z].y, x);
|
calcCycles(mVUregs.VF[z].y, x);
|
||||||
calcCycles(mVUregs.VF[z].z, x);
|
calcCycles(mVUregs.VF[z].z, x);
|
||||||
calcCycles(mVUregs.VF[z].w, x);
|
calcCycles(mVUregs.VF[z].w, x);
|
||||||
}
|
}
|
||||||
for (int z = 16; z > 0; z--) {
|
for (int z = 16; z > 0; z--) {
|
||||||
calcCycles(mVUregs.VI[z], x);
|
calcCycles(mVUregs.VI[z], x);
|
||||||
}
|
}
|
||||||
if (mVUregs.q) {
|
if (mVUregs.q) {
|
||||||
if (mVUregs.q > 4) { calcCycles(mVUregs.q, x); if (mVUregs.q <= 4) { mVUinfo.doDivFlag = 1; } }
|
if (mVUregs.q > 4) { calcCycles(mVUregs.q, x); if (mVUregs.q <= 4) { mVUinfo.doDivFlag = 1; } }
|
||||||
else { calcCycles(mVUregs.q, x); }
|
else { calcCycles(mVUregs.q, x); }
|
||||||
if (!mVUregs.q) { incQ(); }
|
if (!mVUregs.q) { incQ(); }
|
||||||
}
|
}
|
||||||
if (mVUregs.p) {
|
if (mVUregs.p) {
|
||||||
calcCycles(mVUregs.p, x);
|
calcCycles(mVUregs.p, x);
|
||||||
if (!mVUregs.p || mVUregsTemp.p) { incP(); }
|
if (!mVUregs.p || mVUregsTemp.p) { incP(); }
|
||||||
}
|
}
|
||||||
if (mVUregs.xgkick) {
|
if (mVUregs.xgkick) {
|
||||||
calcCycles(mVUregs.xgkick, x);
|
calcCycles(mVUregs.xgkick, x);
|
||||||
if (!mVUregs.xgkick) { mVUinfo.doXGKICK = 1; }
|
if (!mVUregs.xgkick) { mVUinfo.doXGKICK = 1; }
|
||||||
}
|
}
|
||||||
calcCycles(mVUregs.r, x);
|
calcCycles(mVUregs.r, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define cmpVFregs(VFreg1, VFreg2, xVar) { \
|
#define cmpVFregs(VFreg1, VFreg2, xVar) { \
|
||||||
if (VFreg1.reg == VFreg2.reg) { \
|
if (VFreg1.reg == VFreg2.reg) { \
|
||||||
if ((VFreg1.x && VFreg2.x) \
|
if ((VFreg1.x && VFreg2.x) \
|
||||||
|| (VFreg1.y && VFreg2.y) \
|
|| (VFreg1.y && VFreg2.y) \
|
||||||
|| (VFreg1.z && VFreg2.z) \
|
|| (VFreg1.z && VFreg2.z) \
|
||||||
|| (VFreg1.w && VFreg2.w)) \
|
|| (VFreg1.w && VFreg2.w)) \
|
||||||
{ xVar = 1; } \
|
{ xVar = 1; } \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
microVUt(void) mVUsetCycles(mV) {
|
microVUt(void) mVUsetCycles(mV) {
|
||||||
mVUincCycles(mVU, mVUstall);
|
mVUincCycles(mVU, mVUstall);
|
||||||
// If upper Op && lower Op write to same VF reg:
|
// If upper Op && lower Op write to same VF reg:
|
||||||
if ((mVUregsTemp.VFreg[0] == mVUregsTemp.VFreg[1]) && mVUregsTemp.VFreg[0]) {
|
if ((mVUregsTemp.VFreg[0] == mVUregsTemp.VFreg[1]) && mVUregsTemp.VFreg[0]) {
|
||||||
if (mVUregsTemp.r || mVUregsTemp.VI) mVUlow.noWriteVF = 1;
|
if (mVUregsTemp.r || mVUregsTemp.VI) mVUlow.noWriteVF = 1;
|
||||||
else mVUlow.isNOP = 1; // If lower Op doesn't modify anything else, then make it a NOP
|
else mVUlow.isNOP = 1; // If lower Op doesn't modify anything else, then make it a NOP
|
||||||
}
|
}
|
||||||
// If lower op reads a VF reg that upper Op writes to:
|
// If lower op reads a VF reg that upper Op writes to:
|
||||||
if ((mVUlow.VF_read[0].reg || mVUlow.VF_read[1].reg) && mVUup.VF_write.reg) {
|
if ((mVUlow.VF_read[0].reg || mVUlow.VF_read[1].reg) && mVUup.VF_write.reg) {
|
||||||
cmpVFregs(mVUup.VF_write, mVUlow.VF_read[0], mVUinfo.swapOps);
|
cmpVFregs(mVUup.VF_write, mVUlow.VF_read[0], mVUinfo.swapOps);
|
||||||
cmpVFregs(mVUup.VF_write, mVUlow.VF_read[1], mVUinfo.swapOps);
|
cmpVFregs(mVUup.VF_write, mVUlow.VF_read[1], mVUinfo.swapOps);
|
||||||
}
|
}
|
||||||
// If above case is true, and upper op reads a VF reg that lower Op Writes to:
|
// If above case is true, and upper op reads a VF reg that lower Op Writes to:
|
||||||
if (mVUinfo.swapOps && ((mVUup.VF_read[0].reg || mVUup.VF_read[1].reg) && mVUlow.VF_write.reg)) {
|
if (mVUinfo.swapOps && ((mVUup.VF_read[0].reg || mVUup.VF_read[1].reg) && mVUlow.VF_write.reg)) {
|
||||||
cmpVFregs(mVUlow.VF_write, mVUup.VF_read[0], mVUinfo.backupVF);
|
cmpVFregs(mVUlow.VF_write, mVUup.VF_read[0], mVUinfo.backupVF);
|
||||||
cmpVFregs(mVUlow.VF_write, mVUup.VF_read[1], mVUinfo.backupVF);
|
cmpVFregs(mVUlow.VF_write, mVUup.VF_read[1], mVUinfo.backupVF);
|
||||||
}
|
}
|
||||||
|
|
||||||
tCycles(mVUregs.VF[mVUregsTemp.VFreg[0]].x, mVUregsTemp.VF[0].x);
|
tCycles(mVUregs.VF[mVUregsTemp.VFreg[0]].x, mVUregsTemp.VF[0].x);
|
||||||
tCycles(mVUregs.VF[mVUregsTemp.VFreg[0]].y, mVUregsTemp.VF[0].y);
|
tCycles(mVUregs.VF[mVUregsTemp.VFreg[0]].y, mVUregsTemp.VF[0].y);
|
||||||
tCycles(mVUregs.VF[mVUregsTemp.VFreg[0]].z, mVUregsTemp.VF[0].z);
|
tCycles(mVUregs.VF[mVUregsTemp.VFreg[0]].z, mVUregsTemp.VF[0].z);
|
||||||
tCycles(mVUregs.VF[mVUregsTemp.VFreg[0]].w, mVUregsTemp.VF[0].w);
|
tCycles(mVUregs.VF[mVUregsTemp.VFreg[0]].w, mVUregsTemp.VF[0].w);
|
||||||
|
|
||||||
tCycles(mVUregs.VF[mVUregsTemp.VFreg[1]].x, mVUregsTemp.VF[1].x);
|
tCycles(mVUregs.VF[mVUregsTemp.VFreg[1]].x, mVUregsTemp.VF[1].x);
|
||||||
tCycles(mVUregs.VF[mVUregsTemp.VFreg[1]].y, mVUregsTemp.VF[1].y);
|
tCycles(mVUregs.VF[mVUregsTemp.VFreg[1]].y, mVUregsTemp.VF[1].y);
|
||||||
tCycles(mVUregs.VF[mVUregsTemp.VFreg[1]].z, mVUregsTemp.VF[1].z);
|
tCycles(mVUregs.VF[mVUregsTemp.VFreg[1]].z, mVUregsTemp.VF[1].z);
|
||||||
tCycles(mVUregs.VF[mVUregsTemp.VFreg[1]].w, mVUregsTemp.VF[1].w);
|
tCycles(mVUregs.VF[mVUregsTemp.VFreg[1]].w, mVUregsTemp.VF[1].w);
|
||||||
|
|
||||||
tCycles(mVUregs.VI[mVUregsTemp.VIreg], mVUregsTemp.VI);
|
tCycles(mVUregs.VI[mVUregsTemp.VIreg], mVUregsTemp.VI);
|
||||||
tCycles(mVUregs.q, mVUregsTemp.q);
|
tCycles(mVUregs.q, mVUregsTemp.q);
|
||||||
tCycles(mVUregs.p, mVUregsTemp.p);
|
tCycles(mVUregs.p, mVUregsTemp.p);
|
||||||
tCycles(mVUregs.r, mVUregsTemp.r);
|
tCycles(mVUregs.r, mVUregsTemp.r);
|
||||||
tCycles(mVUregs.xgkick, mVUregsTemp.xgkick);
|
tCycles(mVUregs.xgkick, mVUregsTemp.xgkick);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __fastcall mVUwarning0(mV) { Console::Error("microVU0 Warning: Exiting from Possible Infinite Loop [%04x] [%x]", params xPC, mVU->prog.cur); }
|
void __fastcall mVUwarning0(mV) { Console::Error("microVU0 Warning: Exiting from Possible Infinite Loop [%04x] [%x]", params xPC, mVU->prog.cur); }
|
||||||
void __fastcall mVUwarning1(mV) { Console::Error("microVU1 Warning: Exiting from Possible Infinite Loop [%04x] [%x]", params xPC, mVU->prog.cur); }
|
void __fastcall mVUwarning1(mV) { Console::Error("microVU1 Warning: Exiting from Possible Infinite Loop [%04x] [%x]", params xPC, mVU->prog.cur); }
|
||||||
void __fastcall mVUprintPC1(u32 PC) { Console::Write("Block PC [%04x] ", params PC); }
|
void __fastcall mVUprintPC1(u32 PC) { Console::Write("Block PC [%04x] ", params PC); }
|
||||||
void __fastcall mVUprintPC2(u32 PC) { Console::Write("[%04x]\n", params PC); }
|
void __fastcall mVUprintPC2(u32 PC) { Console::Write("[%04x]\n", params PC); }
|
||||||
|
|
||||||
microVUt(void) mVUtestCycles(mV) {
|
microVUt(void) mVUtestCycles(mV) {
|
||||||
u32* vu0jmp;
|
u32* vu0jmp;
|
||||||
iPC = mVUstartPC;
|
iPC = mVUstartPC;
|
||||||
mVUdebugNOW(0);
|
mVUdebugNOW(0);
|
||||||
SUB32ItoM((uptr)&mVU->cycles, mVUcycles);
|
SUB32ItoM((uptr)&mVU->cycles, mVUcycles);
|
||||||
if (IsDevBuild || !isVU1) {
|
if (IsDevBuild || !isVU1) {
|
||||||
u32* jmp32 = JG32(0);
|
u32* jmp32 = JG32(0);
|
||||||
if (!isVU1) { TEST32ItoM((uptr)&mVU->regs->flags, VUFLAG_MFLAGSET); vu0jmp = JZ32(0); }
|
if (!isVU1) { TEST32ItoM((uptr)&mVU->regs->flags, VUFLAG_MFLAGSET); vu0jmp = JZ32(0); }
|
||||||
MOV32ItoR(gprT2, (uptr)mVU);
|
MOV32ItoR(gprT2, (uptr)mVU);
|
||||||
if (isVU1) CALLFunc((uptr)mVUwarning1);
|
if (isVU1) CALLFunc((uptr)mVUwarning1);
|
||||||
//else CALLFunc((uptr)mVUwarning0); // VU0 is allowed early exit for COP2 Interlock Simulation
|
//else CALLFunc((uptr)mVUwarning0); // VU0 is allowed early exit for COP2 Interlock Simulation
|
||||||
MOV32ItoR(gprR, Roffset); // Restore gprR
|
mVUendProgram(mVU, NULL, 0);
|
||||||
mVUendProgram(mVU, NULL, 0);
|
if (!isVU1) x86SetJ32(vu0jmp);
|
||||||
if (!isVU1) x86SetJ32(vu0jmp);
|
x86SetJ32(jmp32);
|
||||||
x86SetJ32(jmp32);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// Initialize VI Constants (vi15 propagates through blocks)
|
||||||
// Initialize VI Constants (vi15 propagates through blocks)
|
microVUt(void) mVUinitConstValues(microVU* mVU) {
|
||||||
microVUt(void) mVUinitConstValues(microVU* mVU) {
|
for (int i = 0; i < 16; i++) {
|
||||||
for (int i = 0; i < 16; i++) {
|
mVUconstReg[i].isValid = 0;
|
||||||
mVUconstReg[i].isValid = 0;
|
mVUconstReg[i].regValue = 0;
|
||||||
mVUconstReg[i].regValue = 0;
|
}
|
||||||
}
|
mVUconstReg[15].isValid = mVUregs.vi15 >> 31;
|
||||||
mVUconstReg[15].isValid = mVUregs.vi15 >> 31;
|
mVUconstReg[15].regValue = mVUconstReg[15].isValid ? (mVUregs.vi15&0xffff) : 0;
|
||||||
mVUconstReg[15].regValue = mVUconstReg[15].isValid ? (mVUregs.vi15&0xffff) : 0;
|
}
|
||||||
}
|
|
||||||
|
// Initialize Variables
|
||||||
// Initialize Variables
|
microVUt(void) mVUinitFirstPass(microVU* mVU, uptr pState, u8* thisPtr) {
|
||||||
microVUt(void) mVUinitFirstPass(microVU* mVU, uptr pState, u8* thisPtr) {
|
mVUstartPC = iPC; // Block Start PC
|
||||||
mVUstartPC = iPC; // Block Start PC
|
mVUbranch = 0; // Branch Type
|
||||||
mVUbranch = 0; // Branch Type
|
mVUcount = 0; // Number of instructions ran
|
||||||
mVUcount = 0; // Number of instructions ran
|
mVUcycles = 0; // Skips "M" phase, and starts counting cycles at "T" stage
|
||||||
mVUcycles = 0; // Skips "M" phase, and starts counting cycles at "T" stage
|
mVU->p = 0; // All blocks start at p index #0
|
||||||
mVU->p = 0; // All blocks start at p index #0
|
mVU->q = 0; // All blocks start at q index #0
|
||||||
mVU->q = 0; // All blocks start at q index #0
|
memcpy_fast(&mVUregs, (microRegInfo*)pState, sizeof(microRegInfo)); // Loads up Pipeline State Info
|
||||||
memcpy_fast(&mVUregs, (microRegInfo*)pState, sizeof(microRegInfo)); // Loads up Pipeline State Info
|
mVUblock.x86ptrStart = thisPtr;
|
||||||
mVUblock.x86ptrStart = thisPtr;
|
mVUpBlock = mVUblocks[mVUstartPC/2]->add(&mVUblock); // Add this block to block manager
|
||||||
mVUpBlock = mVUblocks[mVUstartPC/2]->add(&mVUblock); // Add this block to block manager
|
mVUregs.blockType = 0;
|
||||||
mVUregs.blockType = 0;
|
mVUregs.viBackUp = 0;
|
||||||
mVUregs.viBackUp = 0;
|
mVUregs.flags = 0;
|
||||||
mVUregs.flags = 0;
|
mVUregs.needExactMatch = 0;
|
||||||
mVUregs.needExactMatch = 0;
|
mVUsFlagHack = CHECK_VU_FLAGHACK;
|
||||||
mVUsFlagHack = CHECK_VU_FLAGHACK;
|
mVUinitConstValues(mVU);
|
||||||
mVUinitConstValues(mVU);
|
}
|
||||||
}
|
|
||||||
|
//------------------------------------------------------------------
|
||||||
//------------------------------------------------------------------
|
// Recompiler
|
||||||
// Recompiler
|
//------------------------------------------------------------------
|
||||||
//------------------------------------------------------------------
|
|
||||||
|
microVUr(void*) mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
|
||||||
microVUr(void*) mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
|
|
||||||
|
using namespace x86Emitter;
|
||||||
using namespace x86Emitter;
|
microFlagCycles mFC;
|
||||||
microFlagCycles mFC;
|
u8* thisPtr = x86Ptr;
|
||||||
u8* thisPtr = x86Ptr;
|
const u32 endCount = (((microRegInfo*)pState)->blockType) ? 1 : (mVU->microMemSize / 8);
|
||||||
const u32 endCount = (((microRegInfo*)pState)->blockType) ? 1 : (mVU->microMemSize / 8);
|
|
||||||
|
// First Pass
|
||||||
// First Pass
|
iPC = startPC / 4;
|
||||||
iPC = startPC / 4;
|
mVUsetupRange(mVU, startPC, 1); // Setup Program Bounds/Range
|
||||||
mVUsetupRange(mVU, startPC, 1); // Setup Program Bounds/Range
|
mVU->regAlloc->reset(); // Reset regAlloc
|
||||||
mVU->regAlloc->reset(); // Reset regAlloc
|
mVUinitFirstPass(mVU, pState, thisPtr);
|
||||||
mVUinitFirstPass(mVU, pState, thisPtr);
|
|
||||||
|
for (int branch = 0; mVUcount < endCount; mVUcount++) {
|
||||||
for (int branch = 0; mVUcount < endCount; mVUcount++) {
|
incPC(1);
|
||||||
incPC(1);
|
startLoop(mVU);
|
||||||
startLoop(mVU);
|
mVUincCycles(mVU, 1);
|
||||||
mVUincCycles(mVU, 1);
|
mVUopU(mVU, 0);
|
||||||
mVUopU(mVU, 0);
|
if (curI & _Ebit_) { eBitPass1(mVU, branch); }
|
||||||
if (curI & _Ebit_) { eBitPass1(mVU, branch); }
|
if (curI & _DTbit_) { branch = 4; }
|
||||||
if (curI & _DTbit_) { branch = 4; }
|
if (curI & _Mbit_) { mVUup.mBit = 1; }
|
||||||
if (curI & _Mbit_) { mVUup.mBit = 1; }
|
if (curI & _Ibit_) { mVUlow.isNOP = 1; mVUup.iBit = 1; }
|
||||||
if (curI & _Ibit_) { mVUlow.isNOP = 1; mVUup.iBit = 1; }
|
else { incPC(-1); mVUopL(mVU, 0); incPC(1); }
|
||||||
else { incPC(-1); mVUopL(mVU, 0); incPC(1); }
|
mVUsetCycles(mVU);
|
||||||
mVUsetCycles(mVU);
|
mVUinfo.readQ = mVU->q;
|
||||||
mVUinfo.readQ = mVU->q;
|
mVUinfo.writeQ = !mVU->q;
|
||||||
mVUinfo.writeQ = !mVU->q;
|
mVUinfo.readP = mVU->p;
|
||||||
mVUinfo.readP = mVU->p;
|
mVUinfo.writeP = !mVU->p;
|
||||||
mVUinfo.writeP = !mVU->p;
|
if (branch >= 2) { mVUinfo.isEOB = 1; if (branch == 3) { mVUinfo.isBdelay = 1; } mVUcount++; branchWarning(mVU); break; }
|
||||||
if (branch >= 2) { mVUinfo.isEOB = 1; if (branch == 3) { mVUinfo.isBdelay = 1; } mVUcount++; branchWarning(mVU); break; }
|
else if (branch == 1) { branch = 2; }
|
||||||
else if (branch == 1) { branch = 2; }
|
if (mVUbranch) { mVUsetFlagInfo(mVU); eBitWarning(mVU); branch = 3; mVUbranch = 0; }
|
||||||
if (mVUbranch) { mVUsetFlagInfo(mVU); eBitWarning(mVU); branch = 3; mVUbranch = 0; }
|
incPC(1);
|
||||||
incPC(1);
|
}
|
||||||
}
|
|
||||||
|
// Fix up vi15 const info for propagation through blocks
|
||||||
// Fix up vi15 const info for propagation through blocks
|
mVUregs.vi15 = (mVUconstReg[15].isValid && !CHECK_VU_CONSTHACK) ? ((1<<31) | (mVUconstReg[15].regValue&0xffff)) : 0;
|
||||||
mVUregs.vi15 = (mVUconstReg[15].isValid && !CHECK_VU_CONSTHACK) ? ((1<<31) | (mVUconstReg[15].regValue&0xffff)) : 0;
|
|
||||||
|
mVUsetFlags(mVU, mFC); // Sets Up Flag instances
|
||||||
mVUsetFlags(mVU, mFC); // Sets Up Flag instances
|
mVUoptimizePipeState(mVU); // Optimize the End Pipeline State for nicer Block Linking
|
||||||
mVUoptimizePipeState(mVU); // Optimize the End Pipeline State for nicer Block Linking
|
mVUtestCycles(mVU); // Update VU Cycles and Exit Early if Necessary
|
||||||
mVUtestCycles(mVU); // Update VU Cycles and Exit Early if Necessary
|
|
||||||
|
// Second Pass
|
||||||
// Second Pass
|
iPC = mVUstartPC;
|
||||||
iPC = mVUstartPC;
|
setCode();
|
||||||
setCode();
|
mVUbranch = 0;
|
||||||
mVUbranch = 0;
|
u32 x = 0;
|
||||||
u32 x = 0;
|
for (; x < endCount; x++) {
|
||||||
for (; x < endCount; x++) {
|
if (mVUinfo.isEOB) { x = 0xffff; }
|
||||||
if (mVUinfo.isEOB) { x = 0xffff; }
|
if (mVUup.mBit) { OR32ItoM((uptr)&mVU->regs->flags, VUFLAG_MFLAGSET); }
|
||||||
if (mVUup.mBit) { OR32ItoM((uptr)&mVU->regs->flags, VUFLAG_MFLAGSET); }
|
if (mVUlow.isNOP) { incPC(1); doUpperOp(); doIbit(mVU); }
|
||||||
if (mVUlow.isNOP) { incPC(1); doUpperOp(); doIbit(mVU); }
|
else if (!mVUinfo.swapOps) { incPC(1); doUpperOp(); doLowerOp(); }
|
||||||
else if (!mVUinfo.swapOps) { incPC(1); doUpperOp(); doLowerOp(); }
|
else { doSwapOp(mVU); }
|
||||||
else { doSwapOp(mVU); }
|
if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); }
|
||||||
if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); }
|
if (!doRegAlloc) { mVU->regAlloc->flushAll(); }
|
||||||
if (!doRegAlloc) { mVU->regAlloc->flushAll(); }
|
if (isEvilBlock) { mVUsetupRange(mVU, xPC, 0); normJumpCompile(mVU, mFC, 1); return thisPtr; }
|
||||||
if (isEvilBlock) { mVUsetupRange(mVU, xPC, 0); normJumpCompile(mVU, mFC, 1); return thisPtr; }
|
else if (!mVUinfo.isBdelay) { incPC(1); }
|
||||||
else if (!mVUinfo.isBdelay) { incPC(1); }
|
else {
|
||||||
else {
|
mVUsetupRange(mVU, xPC, 0);
|
||||||
mVUsetupRange(mVU, xPC, 0);
|
mVUdebugNOW(1);
|
||||||
mVUdebugNOW(1);
|
incPC(-3); // Go back to branch opcode
|
||||||
incPC(-3); // Go back to branch opcode
|
switch (mVUlow.branch) {
|
||||||
switch (mVUlow.branch) {
|
case 1: case 2: normBranch(mVU, mFC); return thisPtr; // B/BAL
|
||||||
case 1: case 2: normBranch(mVU, mFC); return thisPtr; // B/BAL
|
case 9: case 10: normJump (mVU, mFC); return thisPtr; // JR/JALR
|
||||||
case 9: case 10: normJump (mVU, mFC); return thisPtr; // JR/JALR
|
case 3: condBranch(mVU, mFC, Jcc_Equal); return thisPtr; // IBEQ
|
||||||
case 3: condBranch(mVU, mFC, Jcc_Equal); return thisPtr; // IBEQ
|
case 4: condBranch(mVU, mFC, Jcc_GreaterOrEqual); return thisPtr; // IBGEZ
|
||||||
case 4: condBranch(mVU, mFC, Jcc_GreaterOrEqual); return thisPtr; // IBGEZ
|
case 5: condBranch(mVU, mFC, Jcc_Greater); return thisPtr; // IBGTZ
|
||||||
case 5: condBranch(mVU, mFC, Jcc_Greater); return thisPtr; // IBGTZ
|
case 6: condBranch(mVU, mFC, Jcc_LessOrEqual); return thisPtr; // IBLEQ
|
||||||
case 6: condBranch(mVU, mFC, Jcc_LessOrEqual); return thisPtr; // IBLEQ
|
case 7: condBranch(mVU, mFC, Jcc_Less); return thisPtr; // IBLTZ
|
||||||
case 7: condBranch(mVU, mFC, Jcc_Less); return thisPtr; // IBLTZ
|
case 8: condBranch(mVU, mFC, Jcc_NotEqual); return thisPtr; // IBNEQ
|
||||||
case 8: condBranch(mVU, mFC, Jcc_NotEqual); return thisPtr; // IBNEQ
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if ((x == endCount) && (x!=1)) { Console::Error("microVU%d: Possible infinite compiling loop!", params mVU->index); }
|
||||||
if ((x == endCount) && (x!=1)) { Console::Error("microVU%d: Possible infinite compiling loop!", params mVU->index); }
|
|
||||||
|
// E-bit End
|
||||||
// E-bit End
|
mVUsetupRange(mVU, xPC-8, 0);
|
||||||
mVUsetupRange(mVU, xPC-8, 0);
|
mVUendProgram(mVU, &mFC, 1);
|
||||||
mVUendProgram(mVU, &mFC, 1);
|
return thisPtr;
|
||||||
return thisPtr;
|
}
|
||||||
}
|
|
||||||
|
// Search for Existing Compiled Block (if found, return x86ptr; else, compile and return x86ptr)
|
||||||
// Search for Existing Compiled Block (if found, return x86ptr; else, compile and return x86ptr)
|
microVUt(void*) mVUblockFetch(microVU* mVU, u32 startPC, uptr pState) {
|
||||||
microVUt(void*) mVUblockFetch(microVU* mVU, u32 startPC, uptr pState) {
|
|
||||||
|
using namespace x86Emitter;
|
||||||
using namespace x86Emitter;
|
if (startPC > mVU->microMemSize-8) { DevCon::Error("microVU%d: invalid startPC [%04x]", params mVU->index, startPC); }
|
||||||
if (startPC > mVU->microMemSize-8) { DevCon::Error("microVU%d: invalid startPC [%04x]", params mVU->index, startPC); }
|
startPC &= mVU->microMemSize-8;
|
||||||
startPC &= mVU->microMemSize-8;
|
|
||||||
|
blockCreate(startPC/8);
|
||||||
blockCreate(startPC/8);
|
microBlock* pBlock = mVUblocks[startPC/8]->search((microRegInfo*)pState);
|
||||||
microBlock* pBlock = mVUblocks[startPC/8]->search((microRegInfo*)pState);
|
if (pBlock) { return pBlock->x86ptrStart; }
|
||||||
if (pBlock) { return pBlock->x86ptrStart; }
|
else { return mVUcompile(mVU, startPC, pState); }
|
||||||
else { return mVUcompile(mVU, startPC, pState); }
|
}
|
||||||
}
|
|
||||||
|
// mVUcompileJIT() - Called By JR/JALR during execution
|
||||||
// mVUcompileJIT() - Called By JR/JALR during execution
|
microVUx(void*) __fastcall mVUcompileJIT(u32 startPC, uptr pState) {
|
||||||
microVUx(void*) __fastcall mVUcompileJIT(u32 startPC, uptr pState) {
|
return mVUblockFetch(mVUx, startPC, pState);
|
||||||
return mVUblockFetch(mVUx, startPC, pState);
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -1,151 +1,140 @@
|
||||||
/* Pcsx2 - Pc Ps2 Emulator
|
/* Pcsx2 - Pc Ps2 Emulator
|
||||||
* Copyright (C) 2009 Pcsx2 Team
|
* Copyright (C) 2009 Pcsx2 Team
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// Dispatcher Functions
|
// Dispatcher Functions
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
// Generates the code for entering recompiled blocks
|
// Generates the code for entering recompiled blocks
|
||||||
void mVUdispatcherA(mV) {
|
void mVUdispatcherA(mV) {
|
||||||
mVU->startFunct = x86Ptr;
|
mVU->startFunct = x86Ptr;
|
||||||
|
|
||||||
// __fastcall = The first two DWORD or smaller arguments are passed in ECX and EDX registers; all other arguments are passed right to left.
|
// __fastcall = The first two DWORD or smaller arguments are passed in ECX and EDX registers; all other arguments are passed right to left.
|
||||||
if (!isVU1) { CALLFunc((uptr)mVUexecuteVU0); }
|
if (!isVU1) { CALLFunc((uptr)mVUexecuteVU0); }
|
||||||
else { CALLFunc((uptr)mVUexecuteVU1); }
|
else { CALLFunc((uptr)mVUexecuteVU1); }
|
||||||
|
|
||||||
// Backup cpu state
|
// Backup cpu state
|
||||||
PUSH32R(EBX);
|
PUSH32R(EBX);
|
||||||
PUSH32R(EBP);
|
PUSH32R(EBP);
|
||||||
PUSH32R(ESI);
|
PUSH32R(ESI);
|
||||||
PUSH32R(EDI);
|
PUSH32R(EDI);
|
||||||
|
|
||||||
// Load VU's MXCSR state
|
// Load VU's MXCSR state
|
||||||
SSE_LDMXCSR((uptr)&g_sseVUMXCSR);
|
SSE_LDMXCSR((uptr)&g_sseVUMXCSR);
|
||||||
|
|
||||||
// Load Regs
|
// Load Regs
|
||||||
MOV32ItoR(gprR, Roffset); // Load VI Reg Offset
|
#ifdef CHECK_MACROVU0
|
||||||
MOV32MtoR(gprF0, (uptr)&mVU->regs->VI[REG_STATUS_FLAG].UL);
|
MOV32MtoR(gprF0, (uptr)&mVU->regs->VI[REG_STATUS_FLAG].UL);
|
||||||
|
MOV32RtoR(gprF1, gprF0);
|
||||||
MOV32RtoR(gprF1, gprF0);
|
MOV32RtoR(gprF2, gprF0);
|
||||||
SHR32ItoR(gprF1, 3);
|
MOV32RtoR(gprF3, gprF0);
|
||||||
AND32ItoR(gprF1, 0x18);
|
#else
|
||||||
|
mVUallocSFLAGd((uptr)&mVU->regs->VI[REG_STATUS_FLAG].UL, 1);
|
||||||
MOV32RtoR(gprF2, gprF0);
|
#endif
|
||||||
SHL32ItoR(gprF2, 11);
|
|
||||||
AND32ItoR(gprF2, 0x1800);
|
SSE_MOVAPS_M128_to_XMM(xmmT1, (uptr)&mVU->regs->VI[REG_MAC_FLAG].UL);
|
||||||
OR32RtoR (gprF1, gprF2);
|
SSE_SHUFPS_XMM_to_XMM (xmmT1, xmmT1, 0);
|
||||||
|
SSE_MOVAPS_XMM_to_M128((uptr)mVU->macFlag, xmmT1);
|
||||||
SHL32ItoR(gprF0, 14);
|
|
||||||
AND32ItoR(gprF0, 0x3cf0000);
|
SSE_MOVAPS_M128_to_XMM(xmmT1, (uptr)&mVU->regs->VI[REG_CLIP_FLAG].UL);
|
||||||
OR32RtoR (gprF1, gprF0);
|
SSE_SHUFPS_XMM_to_XMM (xmmT1, xmmT1, 0);
|
||||||
|
SSE_MOVAPS_XMM_to_M128((uptr)mVU->clipFlag, xmmT1);
|
||||||
MOV32RtoR(gprF0, gprF1);
|
|
||||||
MOV32RtoR(gprF2, gprF1);
|
SSE_MOVAPS_M128_to_XMM(xmmT1, (uptr)&mVU->regs->VI[REG_P].UL);
|
||||||
MOV32RtoR(gprF3, gprF1);
|
SSE_MOVAPS_M128_to_XMM(xmmPQ, (uptr)&mVU->regs->VI[REG_Q].UL);
|
||||||
|
SSE_SHUFPS_XMM_to_XMM(xmmPQ, xmmT1, 0); // wzyx = PPQQ
|
||||||
SSE_MOVAPS_M128_to_XMM(xmmT1, (uptr)&mVU->regs->VI[REG_MAC_FLAG].UL);
|
|
||||||
SSE_SHUFPS_XMM_to_XMM (xmmT1, xmmT1, 0);
|
// Jump to Recompiled Code Block
|
||||||
SSE_MOVAPS_XMM_to_M128((uptr)mVU->macFlag, xmmT1);
|
JMPR(EAX);
|
||||||
|
}
|
||||||
SSE_MOVAPS_M128_to_XMM(xmmT1, (uptr)&mVU->regs->VI[REG_CLIP_FLAG].UL);
|
|
||||||
SSE_SHUFPS_XMM_to_XMM (xmmT1, xmmT1, 0);
|
// Generates the code to exit from recompiled blocks
|
||||||
SSE_MOVAPS_XMM_to_M128((uptr)mVU->clipFlag, xmmT1);
|
void mVUdispatcherB(mV) {
|
||||||
|
mVU->exitFunct = x86Ptr;
|
||||||
SSE_MOVAPS_M128_to_XMM(xmmT1, (uptr)&mVU->regs->VI[REG_P].UL);
|
|
||||||
SSE_MOVAPS_M128_to_XMM(xmmPQ, (uptr)&mVU->regs->VI[REG_Q].UL);
|
// Load EE's MXCSR state
|
||||||
SSE_SHUFPS_XMM_to_XMM(xmmPQ, xmmT1, 0); // wzyx = PPQQ
|
SSE_LDMXCSR((uptr)&g_sseMXCSR);
|
||||||
|
|
||||||
// Jump to Recompiled Code Block
|
// __fastcall = The first two DWORD or smaller arguments are passed in ECX and EDX registers; all other arguments are passed right to left.
|
||||||
JMPR(EAX);
|
if (!isVU1) { CALLFunc((uptr)mVUcleanUpVU0); }
|
||||||
}
|
else { CALLFunc((uptr)mVUcleanUpVU1); }
|
||||||
|
|
||||||
// Generates the code to exit from recompiled blocks
|
// Restore cpu state
|
||||||
void mVUdispatcherB(mV) {
|
POP32R(EDI);
|
||||||
mVU->exitFunct = x86Ptr;
|
POP32R(ESI);
|
||||||
|
POP32R(EBP);
|
||||||
// Load EE's MXCSR state
|
POP32R(EBX);
|
||||||
SSE_LDMXCSR((uptr)&g_sseMXCSR);
|
|
||||||
|
RET();
|
||||||
// __fastcall = The first two DWORD or smaller arguments are passed in ECX and EDX registers; all other arguments are passed right to left.
|
|
||||||
if (!isVU1) { CALLFunc((uptr)mVUcleanUpVU0); }
|
mVUcacheCheck(x86Ptr, mVU->cache, 0x1000);
|
||||||
else { CALLFunc((uptr)mVUcleanUpVU1); }
|
}
|
||||||
|
|
||||||
// Restore cpu state
|
//------------------------------------------------------------------
|
||||||
POP32R(EDI);
|
// Execution Functions
|
||||||
POP32R(ESI);
|
//------------------------------------------------------------------
|
||||||
POP32R(EBP);
|
|
||||||
POP32R(EBX);
|
// Executes for number of cycles
|
||||||
|
microVUx(void*) __fastcall mVUexecute(u32 startPC, u32 cycles) {
|
||||||
RET();
|
|
||||||
|
microVU* mVU = mVUx;
|
||||||
mVUcacheCheck(x86Ptr, mVU->cache, 0x1000);
|
//mVUprint("microVU%x: startPC = 0x%x, cycles = 0x%x", params vuIndex, startPC, cycles);
|
||||||
}
|
|
||||||
|
mVUsearchProg<vuIndex>(); // Find and set correct program
|
||||||
//------------------------------------------------------------------
|
mVU->cycles = cycles;
|
||||||
// Execution Functions
|
mVU->totalCycles = cycles;
|
||||||
//------------------------------------------------------------------
|
|
||||||
|
x86SetPtr(mVU->prog.x86ptr); // Set x86ptr to where last program left off
|
||||||
// Executes for number of cycles
|
return mVUblockFetch(mVU, startPC, (uptr)&mVU->prog.lpState);
|
||||||
microVUx(void*) __fastcall mVUexecute(u32 startPC, u32 cycles) {
|
}
|
||||||
|
|
||||||
microVU* mVU = mVUx;
|
//------------------------------------------------------------------
|
||||||
//mVUprint("microVU%x: startPC = 0x%x, cycles = 0x%x", params vuIndex, startPC, cycles);
|
// Cleanup Functions
|
||||||
|
//------------------------------------------------------------------
|
||||||
mVUsearchProg<vuIndex>(); // Find and set correct program
|
|
||||||
mVU->cycles = cycles;
|
microVUx(void) mVUcleanUp() {
|
||||||
mVU->totalCycles = cycles;
|
microVU* mVU = mVUx;
|
||||||
|
//mVUprint("microVU: Program exited successfully!");
|
||||||
x86SetPtr(mVU->prog.x86ptr); // Set x86ptr to where last program left off
|
//mVUprint("microVU: VF0 = {%x,%x,%x,%x}", params mVU->regs->VF[0].UL[0], mVU->regs->VF[0].UL[1], mVU->regs->VF[0].UL[2], mVU->regs->VF[0].UL[3]);
|
||||||
return mVUblockFetch(mVU, startPC, (uptr)&mVU->prog.lpState);
|
//mVUprint("microVU: VI0 = %x", params mVU->regs->VI[0].UL);
|
||||||
}
|
mVU->prog.x86ptr = x86Ptr;
|
||||||
|
mVUcacheCheck(x86Ptr, mVU->prog.x86start, (uptr)(mVU->prog.x86end - mVU->prog.x86start));
|
||||||
//------------------------------------------------------------------
|
mVU->cycles = mVU->totalCycles - mVU->cycles;
|
||||||
// Cleanup Functions
|
mVU->regs->cycle += mVU->cycles;
|
||||||
//------------------------------------------------------------------
|
cpuRegs.cycle += ((mVU->cycles < 3000) ? mVU->cycles : 3000) * EmuConfig.Speedhacks.VUCycleSteal;
|
||||||
|
//static int ax = 0; ax++;
|
||||||
microVUx(void) mVUcleanUp() {
|
//if (!(ax % 100000)) {
|
||||||
microVU* mVU = mVUx;
|
// for (u32 i = 0; i < (mVU->progSize / 2); i++) {
|
||||||
//mVUprint("microVU: Program exited successfully!");
|
// if (mVUcurProg.block[i]) {
|
||||||
//mVUprint("microVU: VF0 = {%x,%x,%x,%x}", params mVU->regs->VF[0].UL[0], mVU->regs->VF[0].UL[1], mVU->regs->VF[0].UL[2], mVU->regs->VF[0].UL[3]);
|
// mVUcurProg.block[i]->printInfo();
|
||||||
//mVUprint("microVU: VI0 = %x", params mVU->regs->VI[0].UL);
|
// }
|
||||||
mVU->prog.x86ptr = x86Ptr;
|
// }
|
||||||
mVUcacheCheck(x86Ptr, mVU->prog.x86start, (uptr)(mVU->prog.x86end - mVU->prog.x86start));
|
//}
|
||||||
mVU->cycles = mVU->totalCycles - mVU->cycles;
|
}
|
||||||
mVU->regs->cycle += mVU->cycles;
|
|
||||||
cpuRegs.cycle += ((mVU->cycles < 3000) ? mVU->cycles : 3000) * EmuConfig.Speedhacks.VUCycleSteal;
|
//------------------------------------------------------------------
|
||||||
//static int ax = 0; ax++;
|
// Caller Functions
|
||||||
//if (!(ax % 100000)) {
|
//------------------------------------------------------------------
|
||||||
// for (u32 i = 0; i < (mVU->progSize / 2); i++) {
|
|
||||||
// if (mVUcurProg.block[i]) {
|
void* __fastcall mVUexecuteVU0(u32 startPC, u32 cycles) { return mVUexecute<0>(startPC, cycles); }
|
||||||
// mVUcurProg.block[i]->printInfo();
|
void* __fastcall mVUexecuteVU1(u32 startPC, u32 cycles) { return mVUexecute<1>(startPC, cycles); }
|
||||||
// }
|
void __fastcall mVUcleanUpVU0() { mVUcleanUp<0>(); }
|
||||||
// }
|
void __fastcall mVUcleanUpVU1() { mVUcleanUp<1>(); }
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
// Caller Functions
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
|
|
||||||
void* __fastcall mVUexecuteVU0(u32 startPC, u32 cycles) { return mVUexecute<0>(startPC, cycles); }
|
|
||||||
void* __fastcall mVUexecuteVU1(u32 startPC, u32 cycles) { return mVUexecute<1>(startPC, cycles); }
|
|
||||||
void __fastcall mVUcleanUpVU0() { mVUcleanUp<0>(); }
|
|
||||||
void __fastcall mVUcleanUpVU1() { mVUcleanUp<1>(); }
|
|
||||||
|
|
||||||
|
|
|
@ -1,284 +1,283 @@
|
||||||
/* Pcsx2 - Pc Ps2 Emulator
|
/* Pcsx2 - Pc Ps2 Emulator
|
||||||
* Copyright (C) 2009 Pcsx2 Team
|
* Copyright (C) 2009 Pcsx2 Team
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Sets FDIV Flags at the proper time
|
// Sets FDIV Flags at the proper time
|
||||||
microVUt(void) mVUdivSet(mV) {
|
microVUt(void) mVUdivSet(mV) {
|
||||||
int flagReg1, flagReg2;
|
int flagReg1, flagReg2;
|
||||||
if (mVUinfo.doDivFlag) {
|
if (mVUinfo.doDivFlag) {
|
||||||
getFlagReg(flagReg1, sFLAG.write);
|
getFlagReg(flagReg1, sFLAG.write);
|
||||||
if (!sFLAG.doFlag) { getFlagReg(flagReg2, sFLAG.lastWrite); MOV32RtoR(flagReg1, flagReg2); }
|
if (!sFLAG.doFlag) { getFlagReg(flagReg2, sFLAG.lastWrite); MOV32RtoR(flagReg1, flagReg2); }
|
||||||
AND32ItoR(flagReg1, 0xfff3ffff);
|
AND32ItoR(flagReg1, 0xfff3ffff);
|
||||||
OR32MtoR (flagReg1, (uptr)&mVU->divFlag);
|
OR32MtoR (flagReg1, (uptr)&mVU->divFlag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optimizes out unneeded status flag updates
|
// Optimizes out unneeded status flag updates
|
||||||
microVUt(void) mVUstatusFlagOp(mV) {
|
microVUt(void) mVUstatusFlagOp(mV) {
|
||||||
int curPC = iPC;
|
int curPC = iPC;
|
||||||
int i = mVUcount;
|
int i = mVUcount;
|
||||||
bool runLoop = 1;
|
bool runLoop = 1;
|
||||||
if (sFLAG.doFlag) { sFLAG.doNonSticky = 1; }
|
if (sFLAG.doFlag) { sFLAG.doNonSticky = 1; }
|
||||||
else {
|
else {
|
||||||
for (; i > 0; i--) {
|
for (; i > 0; i--) {
|
||||||
incPC2(-2);
|
incPC2(-2);
|
||||||
if (sFLAG.doNonSticky) { runLoop = 0; break; }
|
if (sFLAG.doNonSticky) { runLoop = 0; break; }
|
||||||
else if (sFLAG.doFlag) { sFLAG.doNonSticky = 1; break; }
|
else if (sFLAG.doFlag) { sFLAG.doNonSticky = 1; break; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (runLoop) {
|
if (runLoop) {
|
||||||
for (; i > 0; i--) {
|
for (; i > 0; i--) {
|
||||||
incPC2(-2);
|
incPC2(-2);
|
||||||
if (sFLAG.doNonSticky) break;
|
if (sFLAG.doNonSticky) break;
|
||||||
sFLAG.doFlag = 0;
|
sFLAG.doFlag = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iPC = curPC;
|
iPC = curPC;
|
||||||
DevCon::Status("microVU%d: FSSET Optimization", params getIndex);
|
DevCon::Status("microVU%d: FSSET Optimization", params getIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
int findFlagInst(int* fFlag, int cycles) {
|
int findFlagInst(int* fFlag, int cycles) {
|
||||||
int j = 0, jValue = -1;
|
int j = 0, jValue = -1;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
if ((fFlag[i] <= cycles) && (fFlag[i] > jValue)) { j = i; jValue = fFlag[i]; }
|
if ((fFlag[i] <= cycles) && (fFlag[i] > jValue)) { j = i; jValue = fFlag[i]; }
|
||||||
}
|
}
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup Last 4 instances of Status/Mac/Clip flags (needed for accurate block linking)
|
// Setup Last 4 instances of Status/Mac/Clip flags (needed for accurate block linking)
|
||||||
int sortFlag(int* fFlag, int* bFlag, int cycles) {
|
int sortFlag(int* fFlag, int* bFlag, int cycles) {
|
||||||
int lFlag = -5;
|
int lFlag = -5;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
bFlag[i] = findFlagInst(fFlag, cycles);
|
bFlag[i] = findFlagInst(fFlag, cycles);
|
||||||
if (lFlag != bFlag[i]) { x++; }
|
if (lFlag != bFlag[i]) { x++; }
|
||||||
lFlag = bFlag[i];
|
lFlag = bFlag[i];
|
||||||
cycles++;
|
cycles++;
|
||||||
}
|
}
|
||||||
return x; // Returns the number of Valid Flag Instances
|
return x; // Returns the number of Valid Flag Instances
|
||||||
}
|
}
|
||||||
|
|
||||||
#define sFlagCond (sFLAG.doFlag || mVUlow.isFSSET || mVUinfo.doDivFlag)
|
#define sFlagCond (sFLAG.doFlag || mVUlow.isFSSET || mVUinfo.doDivFlag)
|
||||||
#define sHackCond (mVUsFlagHack && !sFLAG.doNonSticky)
|
#define sHackCond (mVUsFlagHack && !sFLAG.doNonSticky)
|
||||||
|
|
||||||
// Note: Flag handling is 'very' complex, it requires full knowledge of how microVU recs work, so don't touch!
|
// Note: Flag handling is 'very' complex, it requires full knowledge of how microVU recs work, so don't touch!
|
||||||
microVUt(void) mVUsetFlags(mV, microFlagCycles& mFC) {
|
microVUt(void) mVUsetFlags(mV, microFlagCycles& mFC) {
|
||||||
|
|
||||||
int endPC = iPC;
|
int endPC = iPC;
|
||||||
u32 aCount = 1; // Amount of instructions needed to get valid mac flag instances for block linking
|
u32 aCount = 1; // Amount of instructions needed to get valid mac flag instances for block linking
|
||||||
|
|
||||||
// Ensure last ~4+ instructions update mac/status flags (if next block's first 4 instructions will read them)
|
// Ensure last ~4+ instructions update mac/status flags (if next block's first 4 instructions will read them)
|
||||||
for (int i = mVUcount; i > 0; i--, aCount++) {
|
for (int i = mVUcount; i > 0; i--, aCount++) {
|
||||||
if (sFLAG.doFlag) {
|
if (sFLAG.doFlag) {
|
||||||
if (__Mac) { mFLAG.doFlag = 1; }
|
if (__Mac) { mFLAG.doFlag = 1; }
|
||||||
if (__Status) { sFLAG.doNonSticky = 1; }
|
if (__Status) { sFLAG.doNonSticky = 1; }
|
||||||
if (aCount >= 4) { break; }
|
if (aCount >= 4) { break; }
|
||||||
}
|
}
|
||||||
incPC2(-2);
|
incPC2(-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status/Mac Flags Setup Code
|
// Status/Mac Flags Setup Code
|
||||||
int xS = 0, xM = 0, xC = 0;
|
int xS = 0, xM = 0, xC = 0;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
mFC.xStatus[i] = i;
|
mFC.xStatus[i] = i;
|
||||||
mFC.xMac [i] = i;
|
mFC.xMac [i] = i;
|
||||||
mFC.xClip [i] = i;
|
mFC.xClip [i] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(mVUpBlock->pState.needExactMatch & 1)) {
|
if (!(mVUpBlock->pState.needExactMatch & 1)) {
|
||||||
xS = (mVUpBlock->pState.flags >> 0) & 3;
|
xS = (mVUpBlock->pState.flags >> 0) & 3;
|
||||||
mFC.xStatus[0] = -1; mFC.xStatus[1] = -1;
|
mFC.xStatus[0] = -1; mFC.xStatus[1] = -1;
|
||||||
mFC.xStatus[2] = -1; mFC.xStatus[3] = -1;
|
mFC.xStatus[2] = -1; mFC.xStatus[3] = -1;
|
||||||
mFC.xStatus[(xS-1)&3] = 0;
|
mFC.xStatus[(xS-1)&3] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(mVUpBlock->pState.needExactMatch & 4)) {
|
if (!(mVUpBlock->pState.needExactMatch & 4)) {
|
||||||
xC = (mVUpBlock->pState.flags >> 2) & 3;
|
xC = (mVUpBlock->pState.flags >> 2) & 3;
|
||||||
mFC.xClip[0] = -1; mFC.xClip[1] = -1;
|
mFC.xClip[0] = -1; mFC.xClip[1] = -1;
|
||||||
mFC.xClip[2] = -1; mFC.xClip[3] = -1;
|
mFC.xClip[2] = -1; mFC.xClip[3] = -1;
|
||||||
mFC.xClip[(xC-1)&3] = 0;
|
mFC.xClip[(xC-1)&3] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(mVUpBlock->pState.needExactMatch & 2)) {
|
if (!(mVUpBlock->pState.needExactMatch & 2)) {
|
||||||
mFC.xMac[0] = -1; mFC.xMac[1] = -1;
|
mFC.xMac[0] = -1; mFC.xMac[1] = -1;
|
||||||
mFC.xMac[2] = -1; mFC.xMac[3] = -1;
|
mFC.xMac[2] = -1; mFC.xMac[3] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mFC.cycles = 0;
|
mFC.cycles = 0;
|
||||||
u32 xCount = mVUcount; // Backup count
|
u32 xCount = mVUcount; // Backup count
|
||||||
iPC = mVUstartPC;
|
iPC = mVUstartPC;
|
||||||
for (mVUcount = 0; mVUcount < xCount; mVUcount++) {
|
for (mVUcount = 0; mVUcount < xCount; mVUcount++) {
|
||||||
if (mVUlow.isFSSET) {
|
if (mVUlow.isFSSET) {
|
||||||
if (__Status) { // Don't Optimize out on the last ~4+ instructions
|
if (__Status) { // Don't Optimize out on the last ~4+ instructions
|
||||||
if ((xCount - mVUcount) > aCount) { mVUstatusFlagOp(mVU); }
|
if ((xCount - mVUcount) > aCount) { mVUstatusFlagOp(mVU); }
|
||||||
}
|
}
|
||||||
else mVUstatusFlagOp(mVU);
|
else mVUstatusFlagOp(mVU);
|
||||||
}
|
}
|
||||||
mFC.cycles += mVUstall;
|
mFC.cycles += mVUstall;
|
||||||
|
|
||||||
sFLAG.read = findFlagInst(mFC.xStatus, mFC.cycles);
|
sFLAG.read = findFlagInst(mFC.xStatus, mFC.cycles);
|
||||||
mFLAG.read = findFlagInst(mFC.xMac, mFC.cycles);
|
mFLAG.read = findFlagInst(mFC.xMac, mFC.cycles);
|
||||||
cFLAG.read = findFlagInst(mFC.xClip, mFC.cycles);
|
cFLAG.read = findFlagInst(mFC.xClip, mFC.cycles);
|
||||||
|
|
||||||
sFLAG.write = xS;
|
sFLAG.write = xS;
|
||||||
mFLAG.write = xM;
|
mFLAG.write = xM;
|
||||||
cFLAG.write = xC;
|
cFLAG.write = xC;
|
||||||
|
|
||||||
sFLAG.lastWrite = (xS-1) & 3;
|
sFLAG.lastWrite = (xS-1) & 3;
|
||||||
mFLAG.lastWrite = (xM-1) & 3;
|
mFLAG.lastWrite = (xM-1) & 3;
|
||||||
cFLAG.lastWrite = (xC-1) & 3;
|
cFLAG.lastWrite = (xC-1) & 3;
|
||||||
|
|
||||||
if (sHackCond) { sFLAG.doFlag = 0; }
|
if (sHackCond) { sFLAG.doFlag = 0; }
|
||||||
if (sFlagCond) { mFC.xStatus[xS] = mFC.cycles + 4; xS = (xS+1) & 3; }
|
if (sFlagCond) { mFC.xStatus[xS] = mFC.cycles + 4; xS = (xS+1) & 3; }
|
||||||
if (mFLAG.doFlag) { mFC.xMac [xM] = mFC.cycles + 4; xM = (xM+1) & 3; }
|
if (mFLAG.doFlag) { mFC.xMac [xM] = mFC.cycles + 4; xM = (xM+1) & 3; }
|
||||||
if (cFLAG.doFlag) { mFC.xClip [xC] = mFC.cycles + 4; xC = (xC+1) & 3; }
|
if (cFLAG.doFlag) { mFC.xClip [xC] = mFC.cycles + 4; xC = (xC+1) & 3; }
|
||||||
|
|
||||||
mFC.cycles++;
|
mFC.cycles++;
|
||||||
incPC2(2);
|
incPC2(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
mVUregs.flags = ((__Clip) ? 0 : (xC << 2)) | ((__Status) ? 0 : xS);
|
mVUregs.flags = ((__Clip) ? 0 : (xC << 2)) | ((__Status) ? 0 : xS);
|
||||||
iPC = endPC;
|
iPC = endPC;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define getFlagReg1(x) ((x == 3) ? gprF3 : ((x == 2) ? gprF2 : ((x == 1) ? gprF1 : gprF0)))
|
#define getFlagReg1(x) ((x == 3) ? gprF3 : ((x == 2) ? gprF2 : ((x == 1) ? gprF1 : gprF0)))
|
||||||
#define getFlagReg2(x) ((bStatus[0] == x) ? getFlagReg1(x) : gprT1)
|
#define getFlagReg2(x) ((bStatus[0] == x) ? getFlagReg1(x) : gprT1)
|
||||||
#define getFlagReg3(x) ((gFlag == x) ? gprT1 : getFlagReg1(x))
|
#define getFlagReg3(x) ((gFlag == x) ? gprT1 : getFlagReg1(x))
|
||||||
#define getFlagReg4(x) ((gFlag == x) ? gprT1 : gprT2)
|
#define getFlagReg4(x) ((gFlag == x) ? gprT1 : gprT2)
|
||||||
#define shuffleMac ((bMac [3]<<6)|(bMac [2]<<4)|(bMac [1]<<2)|bMac [0])
|
#define shuffleMac ((bMac [3]<<6)|(bMac [2]<<4)|(bMac [1]<<2)|bMac [0])
|
||||||
#define shuffleClip ((bClip[3]<<6)|(bClip[2]<<4)|(bClip[1]<<2)|bClip[0])
|
#define shuffleClip ((bClip[3]<<6)|(bClip[2]<<4)|(bClip[1]<<2)|bClip[0])
|
||||||
|
|
||||||
// Recompiles Code for Proper Flags on Block Linkings
|
// Recompiles Code for Proper Flags on Block Linkings
|
||||||
microVUt(void) mVUsetupFlags(mV, microFlagCycles& mFC) {
|
microVUt(void) mVUsetupFlags(mV, microFlagCycles& mFC) {
|
||||||
|
|
||||||
if (__Status) {
|
if (__Status) {
|
||||||
int bStatus[4];
|
int bStatus[4];
|
||||||
int sortRegs = sortFlag(mFC.xStatus, bStatus, mFC.cycles);
|
int sortRegs = sortFlag(mFC.xStatus, bStatus, mFC.cycles);
|
||||||
// DevCon::Status("sortRegs = %d", params sortRegs);
|
// DevCon::Status("sortRegs = %d", params sortRegs);
|
||||||
// Note: Emitter will optimize out mov(reg1, reg1) cases...
|
// Note: Emitter will optimize out mov(reg1, reg1) cases...
|
||||||
if (sortRegs == 1) {
|
if (sortRegs == 1) {
|
||||||
MOV32RtoR(gprF0, getFlagReg1(bStatus[0]));
|
MOV32RtoR(gprF0, getFlagReg1(bStatus[0]));
|
||||||
MOV32RtoR(gprF1, getFlagReg1(bStatus[1]));
|
MOV32RtoR(gprF1, getFlagReg1(bStatus[1]));
|
||||||
MOV32RtoR(gprF2, getFlagReg1(bStatus[2]));
|
MOV32RtoR(gprF2, getFlagReg1(bStatus[2]));
|
||||||
MOV32RtoR(gprF3, getFlagReg1(bStatus[3]));
|
MOV32RtoR(gprF3, getFlagReg1(bStatus[3]));
|
||||||
}
|
}
|
||||||
else if (sortRegs == 2) {
|
else if (sortRegs == 2) {
|
||||||
MOV32RtoR(gprT1, getFlagReg1(bStatus[3]));
|
MOV32RtoR(gprT1, getFlagReg1(bStatus[3]));
|
||||||
MOV32RtoR(gprF0, getFlagReg1(bStatus[0]));
|
MOV32RtoR(gprF0, getFlagReg1(bStatus[0]));
|
||||||
MOV32RtoR(gprF1, getFlagReg2(bStatus[1]));
|
MOV32RtoR(gprF1, getFlagReg2(bStatus[1]));
|
||||||
MOV32RtoR(gprF2, getFlagReg2(bStatus[2]));
|
MOV32RtoR(gprF2, getFlagReg2(bStatus[2]));
|
||||||
MOV32RtoR(gprF3, gprT1);
|
MOV32RtoR(gprF3, gprT1);
|
||||||
}
|
}
|
||||||
else if (sortRegs == 3) {
|
else if (sortRegs == 3) {
|
||||||
int gFlag = (bStatus[0] == bStatus[1]) ? bStatus[2] : bStatus[1];
|
int gFlag = (bStatus[0] == bStatus[1]) ? bStatus[2] : bStatus[1];
|
||||||
MOV32RtoR(gprT1, getFlagReg1(gFlag));
|
MOV32RtoR(gprT1, getFlagReg1(gFlag));
|
||||||
MOV32RtoR(gprT2, getFlagReg1(bStatus[3]));
|
MOV32RtoR(gprT2, getFlagReg1(bStatus[3]));
|
||||||
MOV32RtoR(gprF0, getFlagReg1(bStatus[0]));
|
MOV32RtoR(gprF0, getFlagReg1(bStatus[0]));
|
||||||
MOV32RtoR(gprF1, getFlagReg3(bStatus[1]));
|
MOV32RtoR(gprF1, getFlagReg3(bStatus[1]));
|
||||||
MOV32RtoR(gprF2, getFlagReg4(bStatus[2]));
|
MOV32RtoR(gprF2, getFlagReg4(bStatus[2]));
|
||||||
MOV32RtoR(gprF3, gprT2);
|
MOV32RtoR(gprF3, gprT2);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
MOV32RtoR(gprT1, getFlagReg1(bStatus[0]));
|
MOV32RtoR(gprT1, getFlagReg1(bStatus[0]));
|
||||||
MOV32RtoR(gprT2, getFlagReg1(bStatus[1]));
|
MOV32RtoR(gprT2, getFlagReg1(bStatus[1]));
|
||||||
MOV32RtoR(gprR, getFlagReg1(bStatus[2]));
|
MOV32RtoR(gprT3, getFlagReg1(bStatus[2]));
|
||||||
MOV32RtoR(gprF3, getFlagReg1(bStatus[3]));
|
MOV32RtoR(gprF3, getFlagReg1(bStatus[3]));
|
||||||
MOV32RtoR(gprF0, gprT1);
|
MOV32RtoR(gprF0, gprT1);
|
||||||
MOV32RtoR(gprF1, gprT2);
|
MOV32RtoR(gprF1, gprT2);
|
||||||
MOV32RtoR(gprF2, gprR);
|
MOV32RtoR(gprF2, gprT3);
|
||||||
MOV32ItoR(gprR, Roffset); // Restore gprR
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (__Mac) {
|
||||||
if (__Mac) {
|
int bMac[4];
|
||||||
int bMac[4];
|
sortFlag(mFC.xMac, bMac, mFC.cycles);
|
||||||
sortFlag(mFC.xMac, bMac, mFC.cycles);
|
SSE_MOVAPS_M128_to_XMM(xmmT1, (uptr)mVU->macFlag);
|
||||||
SSE_MOVAPS_M128_to_XMM(xmmT1, (uptr)mVU->macFlag);
|
SSE_SHUFPS_XMM_to_XMM (xmmT1, xmmT1, shuffleMac);
|
||||||
SSE_SHUFPS_XMM_to_XMM (xmmT1, xmmT1, shuffleMac);
|
SSE_MOVAPS_XMM_to_M128((uptr)mVU->macFlag, xmmT1);
|
||||||
SSE_MOVAPS_XMM_to_M128((uptr)mVU->macFlag, xmmT1);
|
}
|
||||||
}
|
|
||||||
|
if (__Clip) {
|
||||||
if (__Clip) {
|
int bClip[4];
|
||||||
int bClip[4];
|
sortFlag(mFC.xClip, bClip, mFC.cycles);
|
||||||
sortFlag(mFC.xClip, bClip, mFC.cycles);
|
SSE_MOVAPS_M128_to_XMM(xmmT2, (uptr)mVU->clipFlag);
|
||||||
SSE_MOVAPS_M128_to_XMM(xmmT2, (uptr)mVU->clipFlag);
|
SSE_SHUFPS_XMM_to_XMM (xmmT2, xmmT2, shuffleClip);
|
||||||
SSE_SHUFPS_XMM_to_XMM (xmmT2, xmmT2, shuffleClip);
|
SSE_MOVAPS_XMM_to_M128((uptr)mVU->clipFlag, xmmT2);
|
||||||
SSE_MOVAPS_XMM_to_M128((uptr)mVU->clipFlag, xmmT2);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
#define shortBranch() \
|
||||||
#define shortBranch() \
|
if ((branch == 3) || (branch == 4)) { \
|
||||||
if ((branch == 3) || (branch == 4)) { \
|
mVUflagPass(mVU, aBranchAddr, (xCount - (mVUcount+1))); \
|
||||||
mVUflagPass(mVU, aBranchAddr, (xCount - (mVUcount+1))); \
|
if (branch == 3) { mVUcount = 4; break; } \
|
||||||
if (branch == 3) { mVUcount = 4; break; } \
|
} \
|
||||||
} \
|
else break
|
||||||
else break
|
|
||||||
|
// Scan through instructions and check if flags are read (FSxxx, FMxxx, FCxxx opcodes)
|
||||||
// Scan through instructions and check if flags are read (FSxxx, FMxxx, FCxxx opcodes)
|
void mVUflagPass(mV, u32 startPC, u32 xCount) {
|
||||||
void mVUflagPass(mV, u32 startPC, u32 xCount) {
|
|
||||||
|
int oldPC = iPC;
|
||||||
int oldPC = iPC;
|
int oldCount = mVUcount;
|
||||||
int oldCount = mVUcount;
|
int oldBranch = mVUbranch;
|
||||||
int oldBranch = mVUbranch;
|
int aBranchAddr;
|
||||||
int aBranchAddr;
|
iPC = startPC / 4;
|
||||||
iPC = startPC / 4;
|
mVUcount = 0;
|
||||||
mVUcount = 0;
|
mVUbranch = 0;
|
||||||
mVUbranch = 0;
|
for (int branch = 0; mVUcount < xCount; mVUcount=(mVUregs.needExactMatch&8)?(mVUcount+1):mVUcount) {
|
||||||
for (int branch = 0; mVUcount < xCount; mVUcount=(mVUregs.needExactMatch&8)?(mVUcount+1):mVUcount) {
|
incPC(1);
|
||||||
incPC(1);
|
mVUopU(mVU, 3);
|
||||||
mVUopU(mVU, 3);
|
if ( curI & _Ebit_ ) { branch = 1; }
|
||||||
if ( curI & _Ebit_ ) { branch = 1; }
|
if ( curI & _DTbit_ ) { branch = 6; }
|
||||||
if ( curI & _DTbit_ ) { branch = 6; }
|
if (!(curI & _Ibit_) ) { incPC(-1); mVUopL(mVU, 3); incPC(1); }
|
||||||
if (!(curI & _Ibit_) ) { incPC(-1); mVUopL(mVU, 3); incPC(1); }
|
if (branch >= 2) { shortBranch(); }
|
||||||
if (branch >= 2) { shortBranch(); }
|
else if (branch == 1) { branch = 2; }
|
||||||
else if (branch == 1) { branch = 2; }
|
if (mVUbranch) { branch = ((mVUbranch>8)?(5):((mVUbranch<3)?3:4)); aBranchAddr = branchAddr; mVUbranch = 0; }
|
||||||
if (mVUbranch) { branch = ((mVUbranch>8)?(5):((mVUbranch<3)?3:4)); aBranchAddr = branchAddr; mVUbranch = 0; }
|
incPC(1);
|
||||||
incPC(1);
|
}
|
||||||
}
|
if (mVUcount < 4) { mVUregs.needExactMatch |= 0x7; }
|
||||||
if (mVUcount < 4) { mVUregs.needExactMatch |= 0x7; }
|
iPC = oldPC;
|
||||||
iPC = oldPC;
|
mVUcount = oldCount;
|
||||||
mVUcount = oldCount;
|
mVUbranch = oldBranch;
|
||||||
mVUbranch = oldBranch;
|
setCode();
|
||||||
setCode();
|
}
|
||||||
}
|
|
||||||
|
#define branchType1 if (mVUbranch <= 2) // B/BAL
|
||||||
#define branchType1 if (mVUbranch <= 2) // B/BAL
|
#define branchType2 else if (mVUbranch >= 9) // JR/JALR
|
||||||
#define branchType2 else if (mVUbranch >= 9) // JR/JALR
|
#define branchType3 else // Conditional Branch
|
||||||
#define branchType3 else // Conditional Branch
|
|
||||||
|
// Checks if the first 4 instructions of a block will read flags
|
||||||
// Checks if the first 4 instructions of a block will read flags
|
microVUt(void) mVUsetFlagInfo(mV) {
|
||||||
microVUt(void) mVUsetFlagInfo(mV) {
|
branchType1 { incPC(-1); mVUflagPass(mVU, branchAddr, 4); incPC(1); }
|
||||||
branchType1 { incPC(-1); mVUflagPass(mVU, branchAddr, 4); incPC(1); }
|
branchType2 {
|
||||||
branchType2 {
|
if (!mVUlow.constJump.isValid || CHECK_VU_CONSTHACK) { mVUregs.needExactMatch |= 0x7; }
|
||||||
if (!mVUlow.constJump.isValid || CHECK_VU_CONSTHACK) { mVUregs.needExactMatch |= 0x7; }
|
else { mVUflagPass(mVU, (mVUlow.constJump.regValue*8)&(mVU->microMemSize-8), 4); }
|
||||||
else { mVUflagPass(mVU, (mVUlow.constJump.regValue*8)&(mVU->microMemSize-8), 4); }
|
}
|
||||||
}
|
branchType3 {
|
||||||
branchType3 {
|
incPC(-1);
|
||||||
incPC(-1);
|
mVUflagPass(mVU, branchAddr, 4);
|
||||||
mVUflagPass(mVU, branchAddr, 4);
|
int backupFlagInfo = mVUregs.needExactMatch;
|
||||||
int backupFlagInfo = mVUregs.needExactMatch;
|
mVUregs.needExactMatch = 0;
|
||||||
mVUregs.needExactMatch = 0;
|
incPC(4); // Branch Not Taken
|
||||||
incPC(4); // Branch Not Taken
|
mVUflagPass(mVU, xPC, 4);
|
||||||
mVUflagPass(mVU, xPC, 4);
|
incPC(-3);
|
||||||
incPC(-3);
|
mVUregs.needExactMatch |= backupFlagInfo;
|
||||||
mVUregs.needExactMatch |= backupFlagInfo;
|
}
|
||||||
}
|
mVUregs.needExactMatch &= 0x7;
|
||||||
mVUregs.needExactMatch &= 0x7;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,292 +1,290 @@
|
||||||
/* Pcsx2 - Pc Ps2 Emulator
|
/* Pcsx2 - Pc Ps2 Emulator
|
||||||
* Copyright (C) 2009 Pcsx2 Team
|
* Copyright (C) 2009 Pcsx2 Team
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// Global Variables
|
// Global Variables
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
#define declareAllVariables \
|
#define declareAllVariables \
|
||||||
initVariable( _somePrefix_, u32, mVU_absclip, 0x7fffffff ); \
|
initVariable( _somePrefix_, u32, mVU_absclip, 0x7fffffff ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_signbit, 0x80000000 ); \
|
initVariable( _somePrefix_, u32, mVU_signbit, 0x80000000 ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_minvals, 0xff7fffff ); \
|
initVariable( _somePrefix_, u32, mVU_minvals, 0xff7fffff ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_maxvals, 0x7f7fffff ); \
|
initVariable( _somePrefix_, u32, mVU_maxvals, 0x7f7fffff ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_one, 0x3f800000 ); \
|
initVariable( _somePrefix_, u32, mVU_one, 0x3f800000 ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_T1, 0x3f7ffff5 ); \
|
initVariable( _somePrefix_, u32, mVU_T1, 0x3f7ffff5 ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_T2, 0xbeaaa61c ); \
|
initVariable( _somePrefix_, u32, mVU_T2, 0xbeaaa61c ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_T3, 0x3e4c40a6 ); \
|
initVariable( _somePrefix_, u32, mVU_T3, 0x3e4c40a6 ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_T4, 0xbe0e6c63 ); \
|
initVariable( _somePrefix_, u32, mVU_T4, 0xbe0e6c63 ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_T5, 0x3dc577df ); \
|
initVariable( _somePrefix_, u32, mVU_T5, 0x3dc577df ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_T6, 0xbd6501c4 ); \
|
initVariable( _somePrefix_, u32, mVU_T6, 0xbd6501c4 ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_T7, 0x3cb31652 ); \
|
initVariable( _somePrefix_, u32, mVU_T7, 0x3cb31652 ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_T8, 0xbb84d7e7 ); \
|
initVariable( _somePrefix_, u32, mVU_T8, 0xbb84d7e7 ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_Pi4, 0x3f490fdb ); \
|
initVariable( _somePrefix_, u32, mVU_Pi4, 0x3f490fdb ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_S2, 0xbe2aaaa4 ); \
|
initVariable( _somePrefix_, u32, mVU_S2, 0xbe2aaaa4 ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_S3, 0x3c08873e ); \
|
initVariable( _somePrefix_, u32, mVU_S3, 0x3c08873e ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_S4, 0xb94fb21f ); \
|
initVariable( _somePrefix_, u32, mVU_S4, 0xb94fb21f ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_S5, 0x362e9c14 ); \
|
initVariable( _somePrefix_, u32, mVU_S5, 0x362e9c14 ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_E1, 0x3e7fffa8 ); \
|
initVariable( _somePrefix_, u32, mVU_E1, 0x3e7fffa8 ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_E2, 0x3d0007f4 ); \
|
initVariable( _somePrefix_, u32, mVU_E2, 0x3d0007f4 ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_E3, 0x3b29d3ff ); \
|
initVariable( _somePrefix_, u32, mVU_E3, 0x3b29d3ff ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_E4, 0x3933e553 ); \
|
initVariable( _somePrefix_, u32, mVU_E4, 0x3933e553 ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_E5, 0x36b63510 ); \
|
initVariable( _somePrefix_, u32, mVU_E5, 0x36b63510 ); \
|
||||||
initVariable( _somePrefix_, u32, mVU_E6, 0x353961ac ); \
|
initVariable( _somePrefix_, u32, mVU_E6, 0x353961ac ); \
|
||||||
initVariable( _somePrefix_, float, mVU_FTOI_4, 16.0 ); \
|
initVariable( _somePrefix_, float, mVU_FTOI_4, 16.0 ); \
|
||||||
initVariable( _somePrefix_, float, mVU_FTOI_12, 4096.0 ); \
|
initVariable( _somePrefix_, float, mVU_FTOI_12, 4096.0 ); \
|
||||||
initVariable( _somePrefix_, float, mVU_FTOI_15, 32768.0 ); \
|
initVariable( _somePrefix_, float, mVU_FTOI_15, 32768.0 ); \
|
||||||
initVariable( _somePrefix_, float, mVU_ITOF_4, 0.0625f ); \
|
initVariable( _somePrefix_, float, mVU_ITOF_4, 0.0625f ); \
|
||||||
initVariable( _somePrefix_, float, mVU_ITOF_12, 0.000244140625 ); \
|
initVariable( _somePrefix_, float, mVU_ITOF_12, 0.000244140625 ); \
|
||||||
initVariable( _somePrefix_, float, mVU_ITOF_15, 0.000030517578125 );
|
initVariable( _somePrefix_, float, mVU_ITOF_15, 0.000030517578125 );
|
||||||
|
|
||||||
#define _somePrefix_ PCSX2_ALIGNED16_EXTERN
|
#define _somePrefix_ PCSX2_ALIGNED16_EXTERN
|
||||||
#define initVariable(aprefix, atype, aname, avalue) aprefix (const atype aname [4]);
|
#define initVariable(aprefix, atype, aname, avalue) aprefix (const atype aname [4]);
|
||||||
declareAllVariables
|
declareAllVariables
|
||||||
#undef _somePrefix_
|
#undef _somePrefix_
|
||||||
#undef initVariable
|
#undef initVariable
|
||||||
|
|
||||||
#define _somePrefix_ PCSX2_ALIGNED16
|
#define _somePrefix_ PCSX2_ALIGNED16
|
||||||
#define initVariable(aprefix, atype, aname, avalue) aprefix (const atype aname [4]) = {avalue, avalue, avalue, avalue};
|
#define initVariable(aprefix, atype, aname, avalue) aprefix (const atype aname [4]) = {avalue, avalue, avalue, avalue};
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// Helper Macros
|
// Helper Macros
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
#define _Ft_ ((mVU->code >> 16) & 0x1F) // The ft part of the instruction register
|
#define _Ft_ ((mVU->code >> 16) & 0x1F) // The ft part of the instruction register
|
||||||
#define _Fs_ ((mVU->code >> 11) & 0x1F) // The fs part of the instruction register
|
#define _Fs_ ((mVU->code >> 11) & 0x1F) // The fs part of the instruction register
|
||||||
#define _Fd_ ((mVU->code >> 6) & 0x1F) // The fd part of the instruction register
|
#define _Fd_ ((mVU->code >> 6) & 0x1F) // The fd part of the instruction register
|
||||||
|
|
||||||
#define _It_ ((mVU->code >> 16) & 0xF) // The it part of the instruction register
|
#define _It_ ((mVU->code >> 16) & 0xF) // The it part of the instruction register
|
||||||
#define _Is_ ((mVU->code >> 11) & 0xF) // The is part of the instruction register
|
#define _Is_ ((mVU->code >> 11) & 0xF) // The is part of the instruction register
|
||||||
#define _Id_ ((mVU->code >> 6) & 0xF) // The id part of the instruction register
|
#define _Id_ ((mVU->code >> 6) & 0xF) // The id part of the instruction register
|
||||||
|
|
||||||
#define _X ((mVU->code>>24) & 0x1)
|
#define _X ((mVU->code>>24) & 0x1)
|
||||||
#define _Y ((mVU->code>>23) & 0x1)
|
#define _Y ((mVU->code>>23) & 0x1)
|
||||||
#define _Z ((mVU->code>>22) & 0x1)
|
#define _Z ((mVU->code>>22) & 0x1)
|
||||||
#define _W ((mVU->code>>21) & 0x1)
|
#define _W ((mVU->code>>21) & 0x1)
|
||||||
|
|
||||||
#define _X_Y_Z_W (((mVU->code >> 21 ) & 0xF))
|
#define _X_Y_Z_W (((mVU->code >> 21 ) & 0xF))
|
||||||
#define _XYZW_SS (_X+_Y+_Z+_W==1)
|
#define _XYZW_SS (_X+_Y+_Z+_W==1)
|
||||||
#define _XYZW_SS2 (_XYZW_SS && (_X_Y_Z_W != 8))
|
#define _XYZW_SS2 (_XYZW_SS && (_X_Y_Z_W != 8))
|
||||||
#define _XYZW_PS (_X_Y_Z_W == 0xf)
|
#define _XYZW_PS (_X_Y_Z_W == 0xf)
|
||||||
#define _XYZWss(x) ((x==8) || (x==4) || (x==2) || (x==1))
|
#define _XYZWss(x) ((x==8) || (x==4) || (x==2) || (x==1))
|
||||||
|
|
||||||
#define _bc_ (mVU->code & 0x3)
|
#define _bc_ (mVU->code & 0x3)
|
||||||
#define _bc_x ((mVU->code & 0x3) == 0)
|
#define _bc_x ((mVU->code & 0x3) == 0)
|
||||||
#define _bc_y ((mVU->code & 0x3) == 1)
|
#define _bc_y ((mVU->code & 0x3) == 1)
|
||||||
#define _bc_z ((mVU->code & 0x3) == 2)
|
#define _bc_z ((mVU->code & 0x3) == 2)
|
||||||
#define _bc_w ((mVU->code & 0x3) == 3)
|
#define _bc_w ((mVU->code & 0x3) == 3)
|
||||||
|
|
||||||
#define _Fsf_ ((mVU->code >> 21) & 0x03)
|
#define _Fsf_ ((mVU->code >> 21) & 0x03)
|
||||||
#define _Ftf_ ((mVU->code >> 23) & 0x03)
|
#define _Ftf_ ((mVU->code >> 23) & 0x03)
|
||||||
|
|
||||||
#define _Imm5_ (s16)(((mVU->code & 0x400) ? 0xfff0 : 0) | ((mVU->code >> 6) & 0xf))
|
#define _Imm5_ (s16)(((mVU->code & 0x400) ? 0xfff0 : 0) | ((mVU->code >> 6) & 0xf))
|
||||||
#define _Imm11_ (s32)((mVU->code & 0x400) ? (0xfffffc00 | (mVU->code & 0x3ff)) : (mVU->code & 0x3ff))
|
#define _Imm11_ (s32)((mVU->code & 0x400) ? (0xfffffc00 | (mVU->code & 0x3ff)) : (mVU->code & 0x3ff))
|
||||||
#define _Imm12_ (((mVU->code >> 21) & 0x1) << 11) | (mVU->code & 0x7ff)
|
#define _Imm12_ (((mVU->code >> 21) & 0x1) << 11) | (mVU->code & 0x7ff)
|
||||||
#define _Imm15_ (((mVU->code >> 10) & 0x7800) | (mVU->code & 0x7ff))
|
#define _Imm15_ (((mVU->code >> 10) & 0x7800) | (mVU->code & 0x7ff))
|
||||||
#define _Imm24_ (u32)(mVU->code & 0xffffff)
|
#define _Imm24_ (u32)(mVU->code & 0xffffff)
|
||||||
|
|
||||||
#define _Ibit_ (1<<31)
|
#define _Ibit_ (1<<31)
|
||||||
#define _Ebit_ (1<<30)
|
#define _Ebit_ (1<<30)
|
||||||
#define _Mbit_ (1<<29)
|
#define _Mbit_ (1<<29)
|
||||||
#define _Dbit_ (1<<28)
|
#define _Dbit_ (1<<28)
|
||||||
#define _Tbit_ (1<<27)
|
#define _Tbit_ (1<<27)
|
||||||
#define _DTbit_ 0 //( _Dbit_ | _Tbit_ ) // ToDo: Implement this stuff...
|
#define _DTbit_ 0 //( _Dbit_ | _Tbit_ ) // ToDo: Implement this stuff...
|
||||||
|
|
||||||
#define divI 0x1040000
|
#define divI 0x1040000
|
||||||
#define divD 0x2080000
|
#define divD 0x2080000
|
||||||
|
|
||||||
#define isVU1 (mVU->index != 0)
|
#define isVU1 (mVU->index != 0)
|
||||||
#define getIndex (isVU1 ? 1 : 0)
|
#define getIndex (isVU1 ? 1 : 0)
|
||||||
#define getVUmem(x) (((isVU1) ? (x & 0x3ff) : ((x >= 0x400) ? (x & 0x43f) : (x & 0xff))) * 16)
|
#define getVUmem(x) (((isVU1) ? (x & 0x3ff) : ((x >= 0x400) ? (x & 0x43f) : (x & 0xff))) * 16)
|
||||||
#define offsetSS ((_X) ? (0) : ((_Y) ? (4) : ((_Z) ? 8: 12)))
|
#define offsetSS ((_X) ? (0) : ((_Y) ? (4) : ((_Z) ? 8: 12)))
|
||||||
#define offsetReg ((_X) ? (0) : ((_Y) ? (1) : ((_Z) ? 2: 3)))
|
#define offsetReg ((_X) ? (0) : ((_Y) ? (1) : ((_Z) ? 2: 3)))
|
||||||
|
|
||||||
#define xmmT1 0 // Used for regAlloc
|
#define xmmT1 0 // Used for regAlloc
|
||||||
#define xmmT2 1 // Used for regAlloc
|
#define xmmT2 1 // Used for regAlloc
|
||||||
#define xmmT3 2 // Used for regAlloc
|
#define xmmT3 2 // Used for regAlloc
|
||||||
#define xmmT4 3 // Used for regAlloc
|
#define xmmT4 3 // Used for regAlloc
|
||||||
#define xmmT5 4 // Used for regAlloc
|
#define xmmT5 4 // Used for regAlloc
|
||||||
#define xmmT6 5 // Used for regAlloc
|
#define xmmT6 5 // Used for regAlloc
|
||||||
#define xmmT7 6 // Used for regAlloc
|
#define xmmT7 6 // Used for regAlloc
|
||||||
#define xmmPQ 7 // Holds the Value and Backup Values of P and Q regs
|
#define xmmPQ 7 // Holds the Value and Backup Values of P and Q regs
|
||||||
|
|
||||||
#define gprT1 0 // Temp Reg
|
#define gprT1 0 // Temp Reg
|
||||||
#define gprT2 1 // Temp Reg
|
#define gprT2 1 // Temp Reg
|
||||||
#define gprR 2 // VI Reg Offset
|
#define gprT3 2 // Temp Reg
|
||||||
#define gprF0 3 // Status Flag 0
|
#define gprF0 3 // Status Flag 0
|
||||||
#define gprESP 4 // Don't use?
|
#define gprESP 4 // Don't use?
|
||||||
#define gprF1 5 // Status Flag 1
|
#define gprF1 5 // Status Flag 1
|
||||||
#define gprF2 6 // Status Flag 2
|
#define gprF2 6 // Status Flag 2
|
||||||
#define gprF3 7 // Status Flag 3
|
#define gprF3 7 // Status Flag 3
|
||||||
|
|
||||||
// Function Params
|
// Function Params
|
||||||
#define mP microVU* mVU, int recPass
|
#define mP microVU* mVU, int recPass
|
||||||
#define mV microVU* mVU
|
#define mV microVU* mVU
|
||||||
#define mF int recPass
|
#define mF int recPass
|
||||||
#define mX mVU, recPass
|
#define mX mVU, recPass
|
||||||
|
|
||||||
// Recursive Inline
|
// Recursive Inline
|
||||||
#ifndef __LINUX__
|
#ifndef __LINUX__
|
||||||
#define __recInline __releaseinline
|
#define __recInline __releaseinline
|
||||||
#else
|
#else
|
||||||
#define __recInline inline
|
#define __recInline inline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Function/Template Stuff
|
// Function/Template Stuff
|
||||||
#define mVUx (vuIndex ? µVU1 : µVU0)
|
#define mVUx (vuIndex ? µVU1 : µVU0)
|
||||||
#define mVUop(opName) void opName (mP)
|
#define mVUop(opName) void opName (mP)
|
||||||
#define microVUr(aType) __recInline aType
|
#define microVUr(aType) __recInline aType
|
||||||
#define microVUt(aType) __forceinline aType
|
#define microVUt(aType) __forceinline aType
|
||||||
#define microVUx(aType) template<int vuIndex> aType
|
#define microVUx(aType) template<int vuIndex> aType
|
||||||
#define microVUf(aType) template<int vuIndex> __forceinline aType
|
#define microVUf(aType) template<int vuIndex> __forceinline aType
|
||||||
|
|
||||||
// Define Passes
|
// Define Passes
|
||||||
#define pass1 if (recPass == 0)
|
#define pass1 if (recPass == 0)
|
||||||
#define pass2 if (recPass == 1)
|
#define pass2 if (recPass == 1)
|
||||||
#define pass3 if (recPass == 2)
|
#define pass3 if (recPass == 2)
|
||||||
#define pass4 if (recPass == 3)
|
#define pass4 if (recPass == 3)
|
||||||
|
|
||||||
// Upper Opcode Cases
|
// Upper Opcode Cases
|
||||||
#define opCase1 if (opCase == 1) // Normal Opcodes
|
#define opCase1 if (opCase == 1) // Normal Opcodes
|
||||||
#define opCase2 if (opCase == 2) // BC Opcodes
|
#define opCase2 if (opCase == 2) // BC Opcodes
|
||||||
#define opCase3 if (opCase == 3) // I Opcodes
|
#define opCase3 if (opCase == 3) // I Opcodes
|
||||||
#define opCase4 if (opCase == 4) // Q Opcodes
|
#define opCase4 if (opCase == 4) // Q Opcodes
|
||||||
|
|
||||||
// Define mVUquickSearch
|
// Define mVUquickSearch
|
||||||
#ifndef __LINUX__
|
#ifndef __LINUX__
|
||||||
PCSX2_ALIGNED16_EXTERN( u8 mVUsearchXMM[0x1000] );
|
PCSX2_ALIGNED16_EXTERN( u8 mVUsearchXMM[0x1000] );
|
||||||
typedef u32 (__fastcall *mVUCall)(void*, void*);
|
typedef u32 (__fastcall *mVUCall)(void*, void*);
|
||||||
#define mVUquickSearch(dest, src, size) ((((mVUCall)((void*)mVUsearchXMM))(dest, src)) == 0xf)
|
#define mVUquickSearch(dest, src, size) ((((mVUCall)((void*)mVUsearchXMM))(dest, src)) == 0xf)
|
||||||
#define mVUemitSearch() { mVUcustomSearch(); }
|
#define mVUemitSearch() { mVUcustomSearch(); }
|
||||||
#else
|
#else
|
||||||
// Note: GCC builds crash with custom search function, because
|
// Note: GCC builds crash with custom search function, because
|
||||||
// they're not guaranteeing 16-byte alignment on the structs :(
|
// they're not guaranteeing 16-byte alignment on the structs :(
|
||||||
// #define mVUquickSearch(dest, src, size) (!memcmp(dest, src, size))
|
// #define mVUquickSearch(dest, src, size) (!memcmp(dest, src, size))
|
||||||
#define mVUquickSearch(dest, src, size) (!memcmp_mmx(dest, src, size))
|
#define mVUquickSearch(dest, src, size) (!memcmp_mmx(dest, src, size))
|
||||||
#define mVUemitSearch()
|
#define mVUemitSearch()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Misc Macros...
|
// Misc Macros...
|
||||||
#define mVUprogI mVU->prog.prog[progIndex]
|
#define mVUprogI mVU->prog.prog[progIndex]
|
||||||
#define mVUcurProg mVU->prog.prog[mVU->prog.cur]
|
#define mVUcurProg mVU->prog.prog[mVU->prog.cur]
|
||||||
#define mVUblocks mVU->prog.prog[mVU->prog.cur].block
|
#define mVUblocks mVU->prog.prog[mVU->prog.cur].block
|
||||||
#define mVUir mVU->prog.IRinfo
|
#define mVUir mVU->prog.IRinfo
|
||||||
#define mVUbranch mVU->prog.IRinfo.branch
|
#define mVUbranch mVU->prog.IRinfo.branch
|
||||||
#define mVUcycles mVU->prog.IRinfo.cycles
|
#define mVUcycles mVU->prog.IRinfo.cycles
|
||||||
#define mVUcount mVU->prog.IRinfo.count
|
#define mVUcount mVU->prog.IRinfo.count
|
||||||
#define mVUpBlock mVU->prog.IRinfo.pBlock
|
#define mVUpBlock mVU->prog.IRinfo.pBlock
|
||||||
#define mVUblock mVU->prog.IRinfo.block
|
#define mVUblock mVU->prog.IRinfo.block
|
||||||
#define mVUregs mVU->prog.IRinfo.block.pState
|
#define mVUregs mVU->prog.IRinfo.block.pState
|
||||||
#define mVUregsTemp mVU->prog.IRinfo.regsTemp
|
#define mVUregsTemp mVU->prog.IRinfo.regsTemp
|
||||||
#define iPC mVU->prog.IRinfo.curPC
|
#define iPC mVU->prog.IRinfo.curPC
|
||||||
#define mVUsFlagHack mVU->prog.IRinfo.sFlagHack
|
#define mVUsFlagHack mVU->prog.IRinfo.sFlagHack
|
||||||
#define mVUconstReg mVU->prog.IRinfo.constReg
|
#define mVUconstReg mVU->prog.IRinfo.constReg
|
||||||
#define mVUstartPC mVU->prog.IRinfo.startPC
|
#define mVUstartPC mVU->prog.IRinfo.startPC
|
||||||
#define mVUinfo mVU->prog.IRinfo.info[iPC / 2]
|
#define mVUinfo mVU->prog.IRinfo.info[iPC / 2]
|
||||||
#define mVUstall mVUinfo.stall
|
#define mVUstall mVUinfo.stall
|
||||||
#define mVUup mVUinfo.uOp
|
#define mVUup mVUinfo.uOp
|
||||||
#define mVUlow mVUinfo.lOp
|
#define mVUlow mVUinfo.lOp
|
||||||
#define sFLAG mVUinfo.sFlag
|
#define sFLAG mVUinfo.sFlag
|
||||||
#define mFLAG mVUinfo.mFlag
|
#define mFLAG mVUinfo.mFlag
|
||||||
#define cFLAG mVUinfo.cFlag
|
#define cFLAG mVUinfo.cFlag
|
||||||
#define mVUrange mVUcurProg.ranges.range[mVUcurProg.ranges.total]
|
#define mVUrange mVUcurProg.ranges.range[mVUcurProg.ranges.total]
|
||||||
#define isEvilBlock (mVUpBlock->pState.blockType == 2)
|
#define isEvilBlock (mVUpBlock->pState.blockType == 2)
|
||||||
#define isBadOrEvil (mVUlow.badBranch || mVUlow.evilBranch)
|
#define isBadOrEvil (mVUlow.badBranch || mVUlow.evilBranch)
|
||||||
#define xPC ((iPC / 2) * 8)
|
#define xPC ((iPC / 2) * 8)
|
||||||
#define curI ((u32*)mVU->regs->Micro)[iPC] //mVUcurProg.data[iPC]
|
#define curI ((u32*)mVU->regs->Micro)[iPC] //mVUcurProg.data[iPC]
|
||||||
#define setCode() { mVU->code = curI; }
|
#define setCode() { mVU->code = curI; }
|
||||||
#define incPC(x) { iPC = ((iPC + x) & (mVU->progSize-1)); setCode(); }
|
#define incPC(x) { iPC = ((iPC + x) & (mVU->progSize-1)); setCode(); }
|
||||||
#define incPC2(x) { iPC = ((iPC + x) & (mVU->progSize-1)); }
|
#define incPC2(x) { iPC = ((iPC + x) & (mVU->progSize-1)); }
|
||||||
#define bSaveAddr (((xPC + 16) & (mVU->microMemSize-8)) / 8)
|
#define bSaveAddr (((xPC + 16) & (mVU->microMemSize-8)) / 8)
|
||||||
#define branchAddr ((xPC + 8 + (_Imm11_ * 8)) & (mVU->microMemSize-8))
|
#define branchAddr ((xPC + 8 + (_Imm11_ * 8)) & (mVU->microMemSize-8))
|
||||||
#define branchAddrN ((xPC + 16 + (_Imm11_ * 8)) & (mVU->microMemSize-8))
|
#define branchAddrN ((xPC + 16 + (_Imm11_ * 8)) & (mVU->microMemSize-8))
|
||||||
#define shufflePQ (((mVU->p) ? 0xb0 : 0xe0) | ((mVU->q) ? 0x01 : 0x04))
|
#define shufflePQ (((mVU->p) ? 0xb0 : 0xe0) | ((mVU->q) ? 0x01 : 0x04))
|
||||||
#define cmpOffset(x) ((u8*)&(((u8*)x)[mVUprogI.ranges.range[i][0]]))
|
#define cmpOffset(x) ((u8*)&(((u8*)x)[mVUprogI.ranges.range[i][0]]))
|
||||||
#define Rmem (uptr)&mVU->regs->VI[REG_R].UL
|
#define Rmem (uptr)&mVU->regs->VI[REG_R].UL
|
||||||
#define Roffset (uptr)&mVU->regs->VI[9].UL
|
#define aWrap(x, m) ((x > m) ? 0 : x)
|
||||||
#define aWrap(x, m) ((x > m) ? 0 : x)
|
#define shuffleSS(x) ((x==1)?(0x27):((x==2)?(0xc6):((x==4)?(0xe1):(0xe4))))
|
||||||
#define shuffleSS(x) ((x==1)?(0x27):((x==2)?(0xc6):((x==4)?(0xe1):(0xe4))))
|
|
||||||
|
// Flag Info
|
||||||
// Flag Info
|
#define __Status (mVUregs.needExactMatch & 1)
|
||||||
#define __Status (mVUregs.needExactMatch & 1)
|
#define __Mac (mVUregs.needExactMatch & 2)
|
||||||
#define __Mac (mVUregs.needExactMatch & 2)
|
#define __Clip (mVUregs.needExactMatch & 4)
|
||||||
#define __Clip (mVUregs.needExactMatch & 4)
|
|
||||||
|
// Pass 3 Helper Macros
|
||||||
// Pass 3 Helper Macros
|
#define _Fsf_String ((_Fsf_ == 3) ? "w" : ((_Fsf_ == 2) ? "z" : ((_Fsf_ == 1) ? "y" : "x")))
|
||||||
#define _Fsf_String ((_Fsf_ == 3) ? "w" : ((_Fsf_ == 2) ? "z" : ((_Fsf_ == 1) ? "y" : "x")))
|
#define _Ftf_String ((_Ftf_ == 3) ? "w" : ((_Ftf_ == 2) ? "z" : ((_Ftf_ == 1) ? "y" : "x")))
|
||||||
#define _Ftf_String ((_Ftf_ == 3) ? "w" : ((_Ftf_ == 2) ? "z" : ((_Ftf_ == 1) ? "y" : "x")))
|
#define xyzwStr(x,s) (_X_Y_Z_W == x) ? s :
|
||||||
#define xyzwStr(x,s) (_X_Y_Z_W == x) ? s :
|
#define _XYZW_String (xyzwStr(1, "w") (xyzwStr(2, "z") (xyzwStr(3, "zw") (xyzwStr(4, "y") (xyzwStr(5, "yw") (xyzwStr(6, "yz") (xyzwStr(7, "yzw") (xyzwStr(8, "x") (xyzwStr(9, "xw") (xyzwStr(10, "xz") (xyzwStr(11, "xzw") (xyzwStr(12, "xy") (xyzwStr(13, "xyw") (xyzwStr(14, "xyz") "xyzw"))))))))))))))
|
||||||
#define _XYZW_String (xyzwStr(1, "w") (xyzwStr(2, "z") (xyzwStr(3, "zw") (xyzwStr(4, "y") (xyzwStr(5, "yw") (xyzwStr(6, "yz") (xyzwStr(7, "yzw") (xyzwStr(8, "x") (xyzwStr(9, "xw") (xyzwStr(10, "xz") (xyzwStr(11, "xzw") (xyzwStr(12, "xy") (xyzwStr(13, "xyw") (xyzwStr(14, "xyz") "xyzw"))))))))))))))
|
#define _BC_String (_bc_x ? "x" : (_bc_y ? "y" : (_bc_z ? "z" : "w")))
|
||||||
#define _BC_String (_bc_x ? "x" : (_bc_y ? "y" : (_bc_z ? "z" : "w")))
|
#define mVUlogFtFs() { mVUlog(".%s vf%02d, vf%02d", _XYZW_String, _Ft_, _Fs_); }
|
||||||
#define mVUlogFtFs() { mVUlog(".%s vf%02d, vf%02d", _XYZW_String, _Ft_, _Fs_); }
|
#define mVUlogFd() { mVUlog(".%s vf%02d, vf%02d", _XYZW_String, _Fd_, _Fs_); }
|
||||||
#define mVUlogFd() { mVUlog(".%s vf%02d, vf%02d", _XYZW_String, _Fd_, _Fs_); }
|
#define mVUlogACC() { mVUlog(".%s ACC, vf%02d", _XYZW_String, _Fs_); }
|
||||||
#define mVUlogACC() { mVUlog(".%s ACC, vf%02d", _XYZW_String, _Fs_); }
|
#define mVUlogFt() { mVUlog(", vf%02d", _Ft_); }
|
||||||
#define mVUlogFt() { mVUlog(", vf%02d", _Ft_); }
|
#define mVUlogBC() { mVUlog(", vf%02d%s", _Ft_, _BC_String); }
|
||||||
#define mVUlogBC() { mVUlog(", vf%02d%s", _Ft_, _BC_String); }
|
#define mVUlogI() { mVUlog(", I"); }
|
||||||
#define mVUlogI() { mVUlog(", I"); }
|
#define mVUlogQ() { mVUlog(", Q"); }
|
||||||
#define mVUlogQ() { mVUlog(", Q"); }
|
#define mVUlogCLIP() { mVUlog("w.xyz vf%02d, vf%02dw", _Fs_, _Ft_); }
|
||||||
#define mVUlogCLIP() { mVUlog("w.xyz vf%02d, vf%02dw", _Fs_, _Ft_); }
|
|
||||||
|
// Debug Stuff...
|
||||||
// Debug Stuff...
|
#ifdef mVUdebug
|
||||||
#ifdef mVUdebug
|
#define mVUprint Console::Status
|
||||||
#define mVUprint Console::Status
|
#else
|
||||||
#else
|
#define mVUprint 0&&
|
||||||
#define mVUprint 0&&
|
#endif
|
||||||
#endif
|
|
||||||
|
// Program Logging...
|
||||||
// Program Logging...
|
#ifdef mVUlogProg
|
||||||
#ifdef mVUlogProg
|
#define mVUlog ((isVU1) ? __mVULog<1> : __mVULog<0>)
|
||||||
#define mVUlog ((isVU1) ? __mVULog<1> : __mVULog<0>)
|
#define mVUdumpProg __mVUdumpProgram<vuIndex>
|
||||||
#define mVUdumpProg __mVUdumpProgram<vuIndex>
|
#else
|
||||||
#else
|
#define mVUlog 0&&
|
||||||
#define mVUlog 0&&
|
#define mVUdumpProg 0&&
|
||||||
#define mVUdumpProg 0&&
|
#endif
|
||||||
#endif
|
|
||||||
|
// Reg Alloc
|
||||||
// Reg Alloc
|
#define doRegAlloc 1 // Set to 0 to flush every 64bit Instruction (Turns off regAlloc)
|
||||||
#define doRegAlloc 1 // Set to 0 to flush every 64bit Instruction (Turns off regAlloc)
|
|
||||||
|
// Speed Hacks
|
||||||
// Speed Hacks
|
#define CHECK_VU_CONSTHACK 1 // Disables Constant Propagation for Jumps
|
||||||
#define CHECK_VU_CONSTHACK 1 // Disables Constant Propagation for Jumps
|
#define CHECK_VU_FLAGHACK (EmuConfig.Speedhacks.vuFlagHack) // (Can cause Infinite loops, SPS, etc...)
|
||||||
#define CHECK_VU_FLAGHACK (EmuConfig.Speedhacks.vuFlagHack) // (Can cause Infinite loops, SPS, etc...)
|
#define CHECK_VU_MINMAXHACK (EmuConfig.Speedhacks.vuMinMax) // (Can cause SPS, Black Screens, etc...)
|
||||||
#define CHECK_VU_MINMAXHACK (EmuConfig.Speedhacks.vuMinMax) // (Can cause SPS, Black Screens, etc...)
|
|
||||||
|
// Unknown Data
|
||||||
// Unknown Data
|
#define mVU_XGKICK_CYCLES ((CHECK_XGKICKHACK) ? 3 : 1)
|
||||||
#define mVU_XGKICK_CYCLES ((CHECK_XGKICKHACK) ? 3 : 1)
|
// Its unknown at recompile time how long the xgkick transfer will take
|
||||||
// Its unknown at recompile time how long the xgkick transfer will take
|
// so give it a value that makes games happy :) (SO3 is fine at 1 cycle delay)
|
||||||
// so give it a value that makes games happy :) (SO3 is fine at 1 cycle delay)
|
|
||||||
|
|
||||||
|
// Cache Limit Check
|
||||||
// Cache Limit Check
|
#define mVUcacheCheck(ptr, start, limit) { \
|
||||||
#define mVUcacheCheck(ptr, start, limit) { \
|
uptr diff = ptr - start; \
|
||||||
uptr diff = ptr - start; \
|
if (diff >= limit) { \
|
||||||
if (diff >= limit) { \
|
Console::Status("microVU%d: Program cache limit reached. Size = 0x%x", params mVU->index, diff); \
|
||||||
Console::Status("microVU%d: Program cache limit reached. Size = 0x%x", params mVU->index, diff); \
|
mVUreset(mVU); \
|
||||||
mVUreset(mVU); \
|
} \
|
||||||
} \
|
}
|
||||||
}
|
|
||||||
|
#define mVUdebugNOW(isEndPC) { \
|
||||||
#define mVUdebugNOW(isEndPC) { \
|
if (mVUdebugNow) { \
|
||||||
if (mVUdebugNow) { \
|
MOV32ItoR(gprT2, xPC); \
|
||||||
MOV32ItoR(gprT2, xPC); \
|
if (isEndPC) { CALLFunc((uptr)mVUprintPC2); } \
|
||||||
if (isEndPC) { CALLFunc((uptr)mVUprintPC2); } \
|
else { CALLFunc((uptr)mVUprintPC1); } \
|
||||||
else { CALLFunc((uptr)mVUprintPC1); } \
|
} \
|
||||||
MOV32ItoR(gprR, Roffset); \
|
}
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
7862
setup/setup.vdproj
7862
setup/setup.vdproj
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue